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