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