View Javadoc

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