Mercurial > hg > blitz_condensed
comparison src/com/go/trove/net/PooledSocketFactory.java @ 0:3dc0c5604566
Initial checkin of blitz 2.0 fcs - no installer yet.
author | Dan Creswell <dan.creswell@gmail.com> |
---|---|
date | Sat, 21 Mar 2009 11:00:06 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3dc0c5604566 |
---|---|
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: 1.1 $-->, <!--$$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 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 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 /** | |
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 } |