1 52 53 package com.go.trove.net; 54 55 import java.io.*; 56 import java.net.*; 57 import java.util.*; 58 59 69 public class PooledSocketFactory implements SocketFactory { 70 private final SocketFactory mFactory; 71 private final long mTimeout; 72 73 private final Stack mPool = new Stack(); 75 76 private CheckedSocket.ExceptionListener mListener; 77 78 public PooledSocketFactory(SocketFactory factory) { 79 this(factory, factory.getDefaultTimeout()); 80 } 81 82 public PooledSocketFactory(SocketFactory factory, long timeout) { 83 mFactory = factory; 84 mTimeout = timeout; 85 86 mListener = new CheckedSocket.ExceptionListener() { 87 public void exceptionOccurred(CheckedSocket s, 88 Exception e, int count) { 89 if (count == 1) { 91 clear(); 93 } 94 } 95 }; 96 } 97 98 public InetAddressAndPort getInetAddressAndPort() { 99 return mFactory.getInetAddressAndPort(); 100 } 101 102 public InetAddressAndPort getInetAddressAndPort(Object session) { 103 return mFactory.getInetAddressAndPort(); 104 } 105 106 public long getDefaultTimeout() { 107 return mTimeout; 108 } 109 110 public CheckedSocket createSocket() 111 throws ConnectException, SocketException 112 { 113 return createSocket(null, mTimeout); 114 } 115 116 public CheckedSocket createSocket(Object session) 117 throws ConnectException, SocketException 118 { 119 return createSocket(mTimeout); 120 } 121 122 public CheckedSocket createSocket(long timeout) 123 throws ConnectException, SocketException 124 { 125 return new PooledSocket(mFactory.createSocket(timeout)); 126 } 127 128 public CheckedSocket createSocket(Object session, long timeout) 129 throws ConnectException, SocketException 130 { 131 return createSocket(timeout); 132 } 133 134 public CheckedSocket getSocket() 135 throws ConnectException, SocketException 136 { 137 return getSocket(mTimeout); 138 } 139 140 public CheckedSocket getSocket(Object session) 141 throws ConnectException, SocketException 142 { 143 return getSocket(mTimeout); 144 } 145 146 public CheckedSocket getSocket(long timeout) 147 throws ConnectException, SocketException 148 { 149 synchronized (mPool) { 150 if (mPool.size() > 0) { 151 return new PooledSocket((Socket)mPool.pop()); 152 } 153 } 154 155 return new PooledSocket(mFactory.createSocket(timeout)); 156 } 157 158 public CheckedSocket getSocket(Object session, long timeout) 159 throws ConnectException, SocketException 160 { 161 return getSocket(timeout); 162 } 163 164 public void recycleSocket(CheckedSocket socket) 165 throws SocketException, IllegalArgumentException 166 { 167 if (socket != null) { 168 if (socket instanceof PooledSocket) { 169 PooledSocket psock = (PooledSocket)socket; 170 171 if (psock.getOwner() == this) { 172 psock.removeExceptionListener(mListener); 173 Socket s = psock.recycle(); 174 if (s != null) { 175 mPool.push(s); 176 } 177 return; 178 } 179 } 180 181 throw new IllegalArgumentException 182 ("Socket did not originate from this pool"); 183 } 184 } 185 186 public void clear() { 187 synchronized (mPool) { 188 while (mPool.size() > 0) { 189 try { 190 ((Socket)mPool.pop()).close(); 191 } 192 catch (IOException e) { 193 } 194 } 195 } 196 } 197 198 public int getAvailableCount() { 199 return mPool.size(); 200 } 201 202 209 private class PooledSocket extends CheckedSocket { 210 private InputStream mIn; 211 private OutputStream mOut; 212 private boolean mClosed; 213 214 public PooledSocket(Socket s) throws SocketException { 215 super(s); 216 addExceptionListener(mListener); 217 } 218 219 public synchronized InputStream getInputStream() throws IOException { 220 if (mIn != null) { 221 return mIn; 222 } 223 224 final InputStream mStream = super.getInputStream(); 225 226 mIn = new InputStream() { 227 public int read() throws IOException { 228 check(); 229 return mStream.read(); 230 } 231 232 public int read(byte[] b) throws IOException { 233 check(); 234 return mStream.read(b); 235 } 236 237 public int read(byte[] b, int off, int len) throws IOException{ 238 check(); 239 return mStream.read(b, off, len); 240 } 241 242 public long skip(long n) throws IOException { 243 check(); 244 return mStream.skip(n); 245 } 246 247 public int available() throws IOException { 248 check(); 249 return mStream.available(); 250 } 251 252 public void close() throws IOException { 253 if (doClose()) { 254 mStream.close(); 255 } 256 } 257 258 public void mark(int readlimit) { 259 mStream.mark(readlimit); 260 } 261 262 public void reset() throws IOException { 263 check(); 264 mStream.reset(); 265 } 266 267 public boolean markSupported() { 268 return mStream.markSupported(); 269 } 270 }; 271 272 return mIn; 273 } 274 275 public synchronized OutputStream getOutputStream() throws IOException { 276 if (mOut != null) { 277 return mOut; 278 } 279 280 final OutputStream mStream = super.getOutputStream(); 281 282 mOut = new OutputStream() { 283 public void write(int b) throws IOException { 284 check(); 285 mStream.write(b); 286 } 287 288 public void write(byte[] b) throws IOException { 289 check(); 290 mStream.write(b); 291 } 292 293 public void write(byte[] b, int off, int len) throws IOException { 294 check(); 295 mStream.write(b, off, len); 296 } 297 298 public void flush() throws IOException { 299 check(); 300 mStream.flush(); 301 } 302 303 public void close() throws IOException { 304 if (doClose()){ 305 mStream.close(); 306 } 307 } 308 }; 309 310 return mOut; 311 } 312 313 public void setTcpNoDelay(boolean on) throws SocketException { 314 check(); 315 super.setTcpNoDelay(on); 316 } 317 318 public boolean getTcpNoDelay() throws SocketException { 319 check(); 320 return super.getTcpNoDelay(); 321 } 322 323 public void setSoLinger(boolean on, int linger) throws SocketException { 324 check(); 325 super.setSoLinger(on, linger); 326 } 327 328 public int getSoLinger() throws SocketException { 329 check(); 330 return super.getSoLinger(); 331 } 332 333 public void setSoTimeout(int timeout) throws SocketException { 334 check(); 335 super.setSoTimeout(timeout); 336 } 337 338 public int getSoTimeout() throws SocketException { 339 check(); 340 return super.getSoTimeout(); 341 } 342 343 public void setSendBufferSize(int size) throws SocketException { 344 check(); 345 super.setSendBufferSize(size); 346 } 347 348 public int getSendBufferSize() throws SocketException { 349 check(); 350 return super.getSendBufferSize(); 351 } 352 353 public void setReceiveBufferSize(int size) throws SocketException { 354 check(); 355 super.setReceiveBufferSize(size); 356 } 357 358 public int getReceiveBufferSize() throws SocketException { 359 check(); 360 return super.getReceiveBufferSize(); 361 } 362 363 public void close() throws IOException { 364 if (doClose()) { 365 super.close(); 366 } 367 } 368 369 SocketFactory getOwner() { 370 return PooledSocketFactory.this; 371 } 372 373 Socket recycle() throws SocketException { 374 if (mClosed) { 375 return null; 376 } 377 else if (getExceptionCount() != 0) { 378 try { 379 close(); 380 } 381 catch (IOException e) { 382 throw new SocketException(e.getMessage()); 383 } 384 return null; 385 } 386 else { 387 mClosed = true; 388 return mSocket; 389 } 390 } 391 392 boolean doClose() { 393 return (mClosed) ? false : (mClosed = true); 394 } 395 396 void check() throws SocketException { 397 if (mClosed) { 398 throw new SocketException("Socket closed"); 399 } 400 } 401 } 402 } 403 | Popular Tags |