KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > go > trove > net > PooledSocketFactory


1 /* ====================================================================
2  * Trove - Copyright (c) 1997-2000 Walt Disney Internet Group
3  * ====================================================================
4  * The Tea Software License, Version 1.1
5  *
6  * Copyright (c) 2000 Walt Disney Internet Group. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Walt Disney Internet Group (http://opensource.go.com/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact opensource@dig.com.
31  *
32  * 5. Products derived from this software may not be called "Tea",
33  * "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet",
34  * "Kettle", "Trove" or "BeanDoc" appear in their name, without prior
35  * written permission of the Walt Disney Internet Group.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE WALT DISNEY INTERNET GROUP OR ITS
41  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * For more information about Tea, please see http://opensource.go.com/.
51  */

52
53 package com.go.trove.net;
54
55 import java.io.*;
56 import java.net.*;
57 import java.util.*;
58
59 /******************************************************************************
60  * Socket factory implementation that pools connections to one wrapped socket
61  * factory. Sessions are ignored on all requests. Consider wrapping with a
62  * {@link LazySocketFactory} for automatic checking against pooled connections
63  * that may have been closed.
64  *
65  * @author Brian S O'Neill
66  * @version
67  * <!--$$Revision:--> 3 <!-- $-->, <!--$$JustDate:--> 00/12/05 <!-- $-->
68  */

69 public class PooledSocketFactory implements SocketFactory {
70     private final SocketFactory mFactory;
71     private final long mTimeout;
72     
73     // Stack of Sockets.
74
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 JavaDoc e, int count) {
89                 // Only act on the first exception.
90
if (count == 1) {
91                     // Assume all the pooled connections are bad, so ditch 'em.
92
clear();
93                 }
94             }
95         };
96     }
97
98     public InetAddressAndPort getInetAddressAndPort() {
99         return mFactory.getInetAddressAndPort();
100     }
101     
102     public InetAddressAndPort getInetAddressAndPort(Object JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc session, long timeout)
159         throws ConnectException, SocketException
160     {
161         return getSocket(timeout);
162     }
163
164     public void recycleSocket(CheckedSocket socket)
165         throws SocketException, IllegalArgumentException JavaDoc
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 JavaDoc
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     /**
203      * This class does two things. First, it supports virtual socket closure.
204      * After a socket is put back into the pool, it can't be used again, but
205      * the internal socket is still open.
206      *
207      * This class also tracks exceptions checks if this socket can be recycled.
208      */

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