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