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