View Javadoc

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 RuntimeIOException(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 }