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