1 // ========================================================================
2 // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
3 // ------------------------------------------------------------------------
4 // All rights reserved. This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v1.0
6 // and Apache License v2.0 which accompanies this distribution.
7 // The Eclipse Public License is available at
8 // http://www.eclipse.org/legal/epl-v10.html
9 // The Apache License v2.0 is available at
10 // http://www.opensource.org/licenses/apache2.0.php
11 // You may elect to redistribute this code under either of these licenses.
12 // ========================================================================
13
14 package org.eclipse.jetty.io;
15
16 import java.io.BufferedWriter;
17 import java.io.IOException;
18 import java.io.InterruptedIOException;
19 import java.io.OutputStream;
20 import java.io.OutputStreamWriter;
21 import java.io.PrintWriter;
22 import java.io.Writer;
23
24 import org.eclipse.jetty.util.log.Log;
25 import org.eclipse.jetty.util.log.Logger;
26
27 /* ------------------------------------------------------------ */
28 /**
29 * A wrapper for the {@link java.io.PrintWriter} that re-throws the instances of
30 * {@link java.io.IOException} thrown by the underlying implementation of
31 * {@link java.io.Writer} as {@link RuntimeIOException} instances.
32 */
33 public class UncheckedPrintWriter extends PrintWriter
34 {
35 private static final Logger LOG = Log.getLogger(UncheckedPrintWriter.class);
36
37 private boolean _autoFlush = false;
38 private IOException _ioException;
39 private boolean _isClosed = false;
40
41 /* ------------------------------------------------------------ */
42 /**
43 * Line separator string. This is the value of the line.separator property
44 * at the moment that the stream was created.
45 */
46 private String _lineSeparator;
47
48 public UncheckedPrintWriter(Writer out)
49 {
50 this(out,false);
51 }
52
53 /* ------------------------------------------------------------ */
54 /**
55 * Create a new PrintWriter.
56 *
57 * @param out
58 * A character-output stream
59 * @param autoFlush
60 * A boolean; if true, the println() methods will flush the
61 * output buffer
62 */
63 public UncheckedPrintWriter(Writer out, boolean autoFlush)
64 {
65 super(out,autoFlush);
66 this._autoFlush = autoFlush;
67 this._lineSeparator = System.getProperty("line.separator");
68 }
69
70 /* ------------------------------------------------------------ */
71 /**
72 * Create a new PrintWriter, without automatic line flushing, from an
73 * existing OutputStream. This convenience constructor creates the necessary
74 * intermediate OutputStreamWriter, which will convert characters into bytes
75 * using the default character encoding.
76 *
77 * @param out
78 * An output stream
79 *
80 * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
81 */
82 public UncheckedPrintWriter(OutputStream out)
83 {
84 this(out,false);
85 }
86
87 /* ------------------------------------------------------------ */
88 /**
89 * Create a new PrintWriter from an existing OutputStream. This convenience
90 * constructor creates the necessary intermediate OutputStreamWriter, which
91 * will convert characters into bytes using the default character encoding.
92 *
93 * @param out
94 * An output stream
95 * @param autoFlush
96 * A boolean; if true, the println() methods will flush the
97 * output buffer
98 *
99 * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
100 */
101 public UncheckedPrintWriter(OutputStream out, boolean autoFlush)
102 {
103 this(new BufferedWriter(new OutputStreamWriter(out)),autoFlush);
104 }
105
106
107 /* ------------------------------------------------------------ */
108 public boolean checkError()
109 {
110 return _ioException!=null || super.checkError();
111 }
112
113 /* ------------------------------------------------------------ */
114 private void setError(Throwable th)
115 {
116
117 super.setError();
118
119 if (th instanceof IOException)
120 _ioException=(IOException)th;
121 else
122 {
123 _ioException=new IOException(String.valueOf(th));
124 _ioException.initCause(th);
125 }
126
127 LOG.debug(th);
128 }
129
130
131 @Override
132 protected void setError()
133 {
134 setError(new IOException());
135 }
136
137 /* ------------------------------------------------------------ */
138 /** Check to make sure that the stream has not been closed */
139 private void isOpen() throws IOException
140 {
141 if (_ioException!=null)
142 throw new RuntimeIOException(_ioException);
143
144 if (_isClosed)
145 throw new IOException("Stream closed");
146 }
147
148 /* ------------------------------------------------------------ */
149 /**
150 * Flush the stream.
151 */
152 @Override
153 public void flush()
154 {
155 try
156 {
157 synchronized (lock)
158 {
159 isOpen();
160 out.flush();
161 }
162 }
163 catch (IOException ex)
164 {
165 setError(ex);
166 }
167 }
168
169 /* ------------------------------------------------------------ */
170 /**
171 * Close the stream.
172 */
173 @Override
174 public void close()
175 {
176 try
177 {
178 synchronized (lock)
179 {
180 out.close();
181 _isClosed = true;
182 }
183 }
184 catch (IOException ex)
185 {
186 setError(ex);
187 }
188 }
189
190 /* ------------------------------------------------------------ */
191 /**
192 * Write a single character.
193 *
194 * @param c
195 * int specifying a character to be written.
196 */
197 @Override
198 public void write(int c)
199 {
200 try
201 {
202 synchronized (lock)
203 {
204 isOpen();
205 out.write(c);
206 }
207 }
208 catch (InterruptedIOException x)
209 {
210 Thread.currentThread().interrupt();
211 }
212 catch (IOException ex)
213 {
214 setError(ex);
215 }
216 }
217
218 /* ------------------------------------------------------------ */
219 /**
220 * Write a portion of an array of characters.
221 *
222 * @param buf
223 * Array of characters
224 * @param off
225 * Offset from which to start writing characters
226 * @param len
227 * Number of characters to write
228 */
229 @Override
230 public void write(char buf[], int off, int len)
231 {
232 try
233 {
234 synchronized (lock)
235 {
236 isOpen();
237 out.write(buf,off,len);
238 }
239 }
240 catch (InterruptedIOException x)
241 {
242 Thread.currentThread().interrupt();
243 }
244 catch (IOException ex)
245 {
246 setError(ex);
247 }
248 }
249
250 /* ------------------------------------------------------------ */
251 /**
252 * Write an array of characters. This method cannot be inherited from the
253 * Writer class because it must suppress I/O exceptions.
254 *
255 * @param buf
256 * Array of characters to be written
257 */
258 @Override
259 public void write(char buf[])
260 {
261 this.write(buf,0,buf.length);
262 }
263
264 /* ------------------------------------------------------------ */
265 /**
266 * Write a portion of a string.
267 *
268 * @param s
269 * A String
270 * @param off
271 * Offset from which to start writing characters
272 * @param len
273 * Number of characters to write
274 */
275 @Override
276 public void write(String s, int off, int len)
277 {
278 try
279 {
280 synchronized (lock)
281 {
282 isOpen();
283 out.write(s,off,len);
284 }
285 }
286 catch (InterruptedIOException x)
287 {
288 Thread.currentThread().interrupt();
289 }
290 catch (IOException ex)
291 {
292 setError(ex);
293 }
294 }
295
296 /* ------------------------------------------------------------ */
297 /**
298 * Write a string. This method cannot be inherited from the Writer class
299 * because it must suppress I/O exceptions.
300 *
301 * @param s
302 * String to be written
303 */
304 @Override
305 public void write(String s)
306 {
307 this.write(s,0,s.length());
308 }
309
310 private void newLine()
311 {
312 try
313 {
314 synchronized (lock)
315 {
316 isOpen();
317 out.write(_lineSeparator);
318 if (_autoFlush)
319 out.flush();
320 }
321 }
322 catch (InterruptedIOException x)
323 {
324 Thread.currentThread().interrupt();
325 }
326 catch (IOException ex)
327 {
328 setError(ex);
329 }
330 }
331
332 /* ------------------------------------------------------------ */
333 /**
334 * Print a boolean value. The string produced by <code>{@link
335 * java.lang.String#valueOf(boolean)}</code> is translated into bytes
336 * according to the platform's default character encoding, and these bytes
337 * are written in exactly the manner of the <code>{@link
338 * #write(int)}</code> method.
339 *
340 * @param b
341 * The <code>boolean</code> to be printed
342 */
343 @Override
344 public void print(boolean b)
345 {
346 this.write(b?"true":"false");
347 }
348
349 /* ------------------------------------------------------------ */
350 /**
351 * Print a character. The character is translated into one or more bytes
352 * according to the platform's default character encoding, and these bytes
353 * are written in exactly the manner of the <code>{@link
354 * #write(int)}</code> method.
355 *
356 * @param c
357 * The <code>char</code> to be printed
358 */
359 @Override
360 public void print(char c)
361 {
362 this.write(c);
363 }
364
365 /* ------------------------------------------------------------ */
366 /**
367 * Print an integer. The string produced by <code>{@link
368 * java.lang.String#valueOf(int)}</code> is translated into bytes according
369 * to the platform's default character encoding, and these bytes are written
370 * in exactly the manner of the <code>{@link #write(int)}</code> method.
371 *
372 * @param i
373 * The <code>int</code> to be printed
374 * @see java.lang.Integer#toString(int)
375 */
376 @Override
377 public void print(int i)
378 {
379 this.write(String.valueOf(i));
380 }
381
382 /* ------------------------------------------------------------ */
383 /**
384 * Print a long integer. The string produced by <code>{@link
385 * java.lang.String#valueOf(long)}</code> is translated into bytes according
386 * to the platform's default character encoding, and these bytes are written
387 * in exactly the manner of the <code>{@link #write(int)}</code> method.
388 *
389 * @param l
390 * The <code>long</code> to be printed
391 * @see java.lang.Long#toString(long)
392 */
393 @Override
394 public void print(long l)
395 {
396 this.write(String.valueOf(l));
397 }
398
399 /* ------------------------------------------------------------ */
400 /**
401 * Print a floating-point number. The string produced by <code>{@link
402 * java.lang.String#valueOf(float)}</code> is translated into bytes
403 * according to the platform's default character encoding, and these bytes
404 * are written in exactly the manner of the <code>{@link #write(int)}</code>
405 * method.
406 *
407 * @param f
408 * The <code>float</code> to be printed
409 * @see java.lang.Float#toString(float)
410 */
411 @Override
412 public void print(float f)
413 {
414 this.write(String.valueOf(f));
415 }
416
417 /* ------------------------------------------------------------ */
418 /**
419 * Print a double-precision floating-point number. The string produced by
420 * <code>{@link java.lang.String#valueOf(double)}</code> is translated into
421 * bytes according to the platform's default character encoding, and these
422 * bytes are written in exactly the manner of the <code>{@link
423 * #write(int)}</code> method.
424 *
425 * @param d
426 * The <code>double</code> to be printed
427 * @see java.lang.Double#toString(double)
428 */
429 @Override
430 public void print(double d)
431 {
432 this.write(String.valueOf(d));
433 }
434
435 /* ------------------------------------------------------------ */
436 /**
437 * Print an array of characters. The characters are converted into bytes
438 * according to the platform's default character encoding, and these bytes
439 * are written in exactly the manner of the <code>{@link #write(int)}</code>
440 * method.
441 *
442 * @param s
443 * The array of chars to be printed
444 *
445 * @throws NullPointerException
446 * If <code>s</code> is <code>null</code>
447 */
448 @Override
449 public void print(char s[])
450 {
451 this.write(s);
452 }
453
454 /* ------------------------------------------------------------ */
455 /**
456 * Print a string. If the argument is <code>null</code> then the string
457 * <code>"null"</code> is printed. Otherwise, the string's characters are
458 * converted into bytes according to the platform's default character
459 * encoding, and these bytes are written in exactly the manner of the
460 * <code>{@link #write(int)}</code> method.
461 *
462 * @param s
463 * The <code>String</code> to be printed
464 */
465 @Override
466 public void print(String s)
467 {
468 if (s == null)
469 {
470 s = "null";
471 }
472 this.write(s);
473 }
474
475 /* ------------------------------------------------------------ */
476 /**
477 * Print an object. The string produced by the <code>{@link
478 * java.lang.String#valueOf(Object)}</code> method is translated into bytes
479 * according to the platform's default character encoding, and these bytes
480 * are written in exactly the manner of the <code>{@link #write(int)}</code>
481 * method.
482 *
483 * @param obj
484 * The <code>Object</code> to be printed
485 * @see java.lang.Object#toString()
486 */
487 @Override
488 public void print(Object obj)
489 {
490 this.write(String.valueOf(obj));
491 }
492
493 /* ------------------------------------------------------------ */
494 /**
495 * Terminate the current line by writing the line separator string. The line
496 * separator string is defined by the system property
497 * <code>line.separator</code>, and is not necessarily a single newline
498 * character (<code>'\n'</code>).
499 */
500 @Override
501 public void println()
502 {
503 this.newLine();
504 }
505
506 /* ------------------------------------------------------------ */
507 /**
508 * Print a boolean value and then terminate the line. This method behaves as
509 * though it invokes <code>{@link #print(boolean)}</code> and then
510 * <code>{@link #println()}</code>.
511 *
512 * @param x
513 * the <code>boolean</code> value to be printed
514 */
515 @Override
516 public void println(boolean x)
517 {
518 synchronized (lock)
519 {
520 this.print(x);
521 this.println();
522 }
523 }
524
525 /* ------------------------------------------------------------ */
526 /**
527 * Print a character and then terminate the line. This method behaves as
528 * though it invokes <code>{@link #print(char)}</code> and then <code>{@link
529 * #println()}</code>.
530 *
531 * @param x
532 * the <code>char</code> value to be printed
533 */
534 @Override
535 public void println(char x)
536 {
537 synchronized (lock)
538 {
539 this.print(x);
540 this.println();
541 }
542 }
543
544 /* ------------------------------------------------------------ */
545 /**
546 * Print an integer and then terminate the line. This method behaves as
547 * though it invokes <code>{@link #print(int)}</code> and then <code>{@link
548 * #println()}</code>.
549 *
550 * @param x
551 * the <code>int</code> value to be printed
552 */
553 @Override
554 public void println(int x)
555 {
556 synchronized (lock)
557 {
558 this.print(x);
559 this.println();
560 }
561 }
562
563 /* ------------------------------------------------------------ */
564 /**
565 * Print a long integer and then terminate the line. This method behaves as
566 * though it invokes <code>{@link #print(long)}</code> and then
567 * <code>{@link #println()}</code>.
568 *
569 * @param x
570 * the <code>long</code> value to be printed
571 */
572 @Override
573 public void println(long x)
574 {
575 synchronized (lock)
576 {
577 this.print(x);
578 this.println();
579 }
580 }
581
582 /* ------------------------------------------------------------ */
583 /**
584 * Print a floating-point number and then terminate the line. This method
585 * behaves as though it invokes <code>{@link #print(float)}</code> and then
586 * <code>{@link #println()}</code>.
587 *
588 * @param x
589 * the <code>float</code> value to be printed
590 */
591 @Override
592 public void println(float x)
593 {
594 synchronized (lock)
595 {
596 this.print(x);
597 this.println();
598 }
599 }
600
601 /* ------------------------------------------------------------ */
602 /**
603 * Print a double-precision floating-point number and then terminate the
604 * line. This method behaves as though it invokes <code>{@link
605 * #print(double)}</code> and then <code>{@link #println()}</code>.
606 *
607 * @param x
608 * the <code>double</code> value to be printed
609 */
610 /* ------------------------------------------------------------ */
611 @Override
612 public void println(double x)
613 {
614 synchronized (lock)
615 {
616 this.print(x);
617 this.println();
618 }
619 }
620
621 /* ------------------------------------------------------------ */
622 /**
623 * Print an array of characters and then terminate the line. This method
624 * behaves as though it invokes <code>{@link #print(char[])}</code> and then
625 * <code>{@link #println()}</code>.
626 *
627 * @param x
628 * the array of <code>char</code> values to be printed
629 */
630 @Override
631 public void println(char x[])
632 {
633 synchronized (lock)
634 {
635 this.print(x);
636 this.println();
637 }
638 }
639
640 /* ------------------------------------------------------------ */
641 /**
642 * Print a String and then terminate the line. This method behaves as though
643 * it invokes <code>{@link #print(String)}</code> and then
644 * <code>{@link #println()}</code>.
645 *
646 * @param x
647 * the <code>String</code> value to be printed
648 */
649 @Override
650 public void println(String x)
651 {
652 synchronized (lock)
653 {
654 this.print(x);
655 this.println();
656 }
657 }
658
659 /* ------------------------------------------------------------ */
660 /**
661 * Print an Object and then terminate the line. This method behaves as
662 * though it invokes <code>{@link #print(Object)}</code> and then
663 * <code>{@link #println()}</code>.
664 *
665 * @param x
666 * the <code>Object</code> value to be printed
667 */
668 @Override
669 public void println(Object x)
670 {
671 synchronized (lock)
672 {
673 this.print(x);
674 this.println();
675 }
676 }
677 }