Mercurial > hg > blitz_condensed
comparison src/com/go/trove/net/CheckedSocket.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 * A socket that tracks if any I/O exceptions have occured and ensures that | |
61 * plain I/O exceptions are thrown as SocketExceptions. InterruptedIOExceptions | |
62 * do not affect the exception count, and they are not converted to | |
63 * SocketExceptions. | |
64 * <p> | |
65 * All socket exceptions thrown will actually be instances of | |
66 * {@link CheckedSocketException}, which subclasses SocketException. The error | |
67 * messages will contain additional information, and the original exception | |
68 * and socket can be obtained from it. | |
69 * | |
70 * @author Brian S O'Neill | |
71 * @version | |
72 * <!--$$Revision: 1.1 $-->, <!--$$JustDate:--> 01/03/16 <!-- $--> | |
73 */ | |
74 public class CheckedSocket extends FilteredSocket { | |
75 /** | |
76 * Returns a new CheckedSocket instance only if the given socket isn't | |
77 * already one. | |
78 */ | |
79 public static CheckedSocket check(Socket socket) throws SocketException { | |
80 if (socket instanceof CheckedSocket) { | |
81 return (CheckedSocket)socket; | |
82 } | |
83 else { | |
84 return new CheckedSocket(socket); | |
85 } | |
86 } | |
87 | |
88 private int mExceptionCount; | |
89 private InputStream mIn; | |
90 private OutputStream mOut; | |
91 | |
92 private Set mExceptionListeners; | |
93 | |
94 protected CheckedSocket(Socket socket) throws SocketException { | |
95 super(socket); | |
96 } | |
97 | |
98 /** | |
99 * Returns the total number of exceptions encountered while using this | |
100 * socket, excluding InterruptedIOExceptions. If this count is not zero, | |
101 * then the socket is potentially in an unrecoverable state. | |
102 */ | |
103 public int getExceptionCount() { | |
104 return mExceptionCount; | |
105 } | |
106 | |
107 /** | |
108 * Internally, the collection of listeners is saved in a set so that | |
109 * listener instances may be added multiple times without harm. | |
110 */ | |
111 public synchronized void addExceptionListener(ExceptionListener listener) { | |
112 if (mExceptionListeners == null) { | |
113 mExceptionListeners = new HashSet(); | |
114 } | |
115 mExceptionListeners.add(listener); | |
116 } | |
117 | |
118 public synchronized void removeExceptionListener(ExceptionListener listener) { | |
119 if (mExceptionListeners != null) { | |
120 mExceptionListeners.remove(listener); | |
121 } | |
122 } | |
123 | |
124 public synchronized InputStream getInputStream() throws IOException { | |
125 if (mIn != null) { | |
126 return mIn; | |
127 } | |
128 | |
129 try { | |
130 return mIn = new Input(super.getInputStream()); | |
131 } | |
132 catch (Exception e) { | |
133 throw handleIOException(e); | |
134 } | |
135 } | |
136 | |
137 public synchronized OutputStream getOutputStream() throws IOException { | |
138 if (mOut != null) { | |
139 return mOut; | |
140 } | |
141 | |
142 try { | |
143 return mOut = new Output(super.getOutputStream()); | |
144 } | |
145 catch (Exception e) { | |
146 throw handleIOException(e); | |
147 } | |
148 } | |
149 | |
150 public void setTcpNoDelay(boolean on) throws SocketException { | |
151 try { | |
152 super.setTcpNoDelay(on); | |
153 } | |
154 catch (Exception e) { | |
155 throw handleSocketException(e); | |
156 } | |
157 } | |
158 | |
159 public boolean getTcpNoDelay() throws SocketException { | |
160 try { | |
161 return super.getTcpNoDelay(); | |
162 } | |
163 catch (Exception e) { | |
164 throw handleSocketException(e); | |
165 } | |
166 } | |
167 | |
168 public void setSoLinger(boolean on, int linger) throws SocketException { | |
169 try { | |
170 super.setSoLinger(on, linger); | |
171 } | |
172 catch (Exception e) { | |
173 throw handleSocketException(e); | |
174 } | |
175 } | |
176 | |
177 public int getSoLinger() throws SocketException { | |
178 try { | |
179 return super.getSoLinger(); | |
180 } | |
181 catch (Exception e) { | |
182 throw handleSocketException(e); | |
183 } | |
184 } | |
185 | |
186 public void setSoTimeout(int timeout) throws SocketException { | |
187 try { | |
188 super.setSoTimeout(timeout); | |
189 } | |
190 catch (Exception e) { | |
191 throw handleSocketException(e); | |
192 } | |
193 } | |
194 | |
195 public int getSoTimeout() throws SocketException { | |
196 try { | |
197 return super.getSoTimeout(); | |
198 } | |
199 catch (Exception e) { | |
200 throw handleSocketException(e); | |
201 } | |
202 } | |
203 | |
204 public void setSendBufferSize(int size) throws SocketException { | |
205 try { | |
206 super.setSendBufferSize(size); | |
207 } | |
208 catch (Exception e) { | |
209 throw handleSocketException(e); | |
210 } | |
211 } | |
212 | |
213 public int getSendBufferSize() throws SocketException { | |
214 try { | |
215 return super.getSendBufferSize(); | |
216 } | |
217 catch (Exception e) { | |
218 throw handleSocketException(e); | |
219 } | |
220 } | |
221 | |
222 public void setReceiveBufferSize(int size) throws SocketException { | |
223 try { | |
224 super.setReceiveBufferSize(size); | |
225 } | |
226 catch (Exception e) { | |
227 throw handleSocketException(e); | |
228 } | |
229 } | |
230 | |
231 public int getReceiveBufferSize() throws SocketException { | |
232 try { | |
233 return super.getReceiveBufferSize(); | |
234 } | |
235 catch (Exception e) { | |
236 throw handleSocketException(e); | |
237 } | |
238 } | |
239 | |
240 public void close() throws IOException { | |
241 try { | |
242 super.close(); | |
243 } | |
244 catch (Exception e) { | |
245 throw handleIOException(e); | |
246 } | |
247 } | |
248 | |
249 public void setKeepAlive(boolean on) throws SocketException { | |
250 try { | |
251 super.setKeepAlive(on); | |
252 } | |
253 catch (Exception e) { | |
254 throw handleSocketException(e); | |
255 } | |
256 } | |
257 | |
258 public boolean getKeepAlive() throws SocketException { | |
259 try { | |
260 return super.getKeepAlive(); | |
261 } | |
262 catch (Exception e) { | |
263 throw handleSocketException(e); | |
264 } | |
265 } | |
266 | |
267 public void shutdownInput() throws IOException { | |
268 try { | |
269 super.shutdownInput(); | |
270 } | |
271 catch (Exception e) { | |
272 throw handleIOException(e); | |
273 } | |
274 } | |
275 | |
276 public void shutdownOutput() throws IOException { | |
277 try { | |
278 super.shutdownOutput(); | |
279 } | |
280 catch (Exception e) { | |
281 throw handleIOException(e); | |
282 } | |
283 } | |
284 | |
285 /** | |
286 * @param e should be instance of IOException or RuntimeException. | |
287 */ | |
288 IOException handleIOException(Exception e) { | |
289 if (e instanceof InterruptedIOException) { | |
290 return CheckedInterruptedIOException.create | |
291 ((InterruptedIOException)e, mSocket); | |
292 } | |
293 | |
294 int count; | |
295 synchronized (this) { | |
296 count = ++mExceptionCount; | |
297 } | |
298 exceptionOccurred(e, count); | |
299 | |
300 if (e instanceof CheckedSocketException) { | |
301 return (CheckedSocketException)e; | |
302 } | |
303 else if (e instanceof NullPointerException) { | |
304 // Workaround for a bug in the Socket class that sometimes | |
305 // causes a NullPointerException on a closed socket. | |
306 return CheckedSocketException.create(e, mSocket, "Socket closed"); | |
307 } | |
308 else { | |
309 return CheckedSocketException.create(e, mSocket); | |
310 } | |
311 } | |
312 | |
313 /** | |
314 * @param e Should be instance of SocketException or RuntimeException. | |
315 */ | |
316 SocketException handleSocketException(Exception e) { | |
317 int count; | |
318 synchronized (this) { | |
319 count = ++mExceptionCount; | |
320 } | |
321 exceptionOccurred(e, count); | |
322 | |
323 if (e instanceof CheckedSocketException) { | |
324 return (CheckedSocketException)e; | |
325 } | |
326 else if (e instanceof NullPointerException) { | |
327 // Workaround for a bug in the Socket class that sometimes | |
328 // causes a NullPointerException on a closed socket. | |
329 return CheckedSocketException.create(e, mSocket, "Socket closed"); | |
330 } | |
331 else { | |
332 return CheckedSocketException.create(e, mSocket); | |
333 } | |
334 } | |
335 | |
336 private synchronized void exceptionOccurred(Exception e, int count) { | |
337 if (mExceptionListeners != null) { | |
338 Iterator it = mExceptionListeners.iterator(); | |
339 while (it.hasNext()) { | |
340 ((ExceptionListener)it.next()) | |
341 .exceptionOccurred(this, e, count); | |
342 } | |
343 } | |
344 } | |
345 | |
346 public static interface ExceptionListener { | |
347 /** | |
348 * @param count new exception count, which will be one the first time | |
349 * this method is called. | |
350 */ | |
351 public void exceptionOccurred(CheckedSocket s, Exception e, int count); | |
352 } | |
353 | |
354 private class Input extends InputStream { | |
355 private final InputStream mStream; | |
356 | |
357 public Input(InputStream in) { | |
358 mStream = in; | |
359 } | |
360 | |
361 public int read() throws IOException { | |
362 try { | |
363 return mStream.read(); | |
364 } | |
365 catch (IOException e) { | |
366 throw handleIOException(e); | |
367 } | |
368 } | |
369 | |
370 public int read(byte[] b) throws IOException { | |
371 try { | |
372 return mStream.read(b); | |
373 } | |
374 catch (IOException e) { | |
375 throw handleIOException(e); | |
376 } | |
377 } | |
378 | |
379 public int read(byte[] b, int off, int len) throws IOException { | |
380 try { | |
381 return mStream.read(b, off, len); | |
382 } | |
383 catch (IOException e) { | |
384 throw handleIOException(e); | |
385 } | |
386 } | |
387 | |
388 public long skip(long n) throws IOException { | |
389 try { | |
390 return mStream.skip(n); | |
391 } | |
392 catch (IOException e) { | |
393 throw handleIOException(e); | |
394 } | |
395 } | |
396 | |
397 public int available() throws IOException { | |
398 try { | |
399 return mStream.available(); | |
400 } | |
401 catch (IOException e) { | |
402 throw handleIOException(e); | |
403 } | |
404 } | |
405 | |
406 public void close() throws IOException { | |
407 try { | |
408 mStream.close(); | |
409 } | |
410 catch (IOException e) { | |
411 throw handleIOException(e); | |
412 } | |
413 } | |
414 | |
415 public void mark(int readlimit) { | |
416 mStream.mark(readlimit); | |
417 } | |
418 | |
419 public void reset() throws IOException { | |
420 try { | |
421 mStream.reset(); | |
422 } | |
423 catch (IOException e) { | |
424 throw handleIOException(e); | |
425 } | |
426 } | |
427 | |
428 public boolean markSupported() { | |
429 return mStream.markSupported(); | |
430 } | |
431 } | |
432 | |
433 private class Output extends OutputStream { | |
434 private final OutputStream mStream; | |
435 | |
436 public Output(OutputStream out) { | |
437 mStream = out; | |
438 } | |
439 | |
440 public void write(int b) throws IOException { | |
441 try { | |
442 mStream.write(b); | |
443 } | |
444 catch (IOException e) { | |
445 throw handleIOException(e); | |
446 } | |
447 } | |
448 | |
449 public void write(byte[] b) throws IOException { | |
450 try { | |
451 mStream.write(b); | |
452 } | |
453 catch (IOException e) { | |
454 throw handleIOException(e); | |
455 } | |
456 } | |
457 | |
458 public void write(byte[] b, int off, int len) throws IOException { | |
459 try { | |
460 mStream.write(b, off, len); | |
461 } | |
462 catch (IOException e) { | |
463 throw handleIOException(e); | |
464 } | |
465 } | |
466 | |
467 public void flush() throws IOException { | |
468 try { | |
469 mStream.flush(); | |
470 } | |
471 catch (IOException e) { | |
472 throw handleIOException(e); | |
473 } | |
474 } | |
475 | |
476 public void close() throws IOException { | |
477 try { | |
478 mStream.close(); | |
479 } | |
480 catch (IOException e) { | |
481 throw handleIOException(e); | |
482 } | |
483 } | |
484 } | |
485 } |