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 }