| // |
| // ======================================================================== |
| // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.io; |
| |
| import java.io.BufferedWriter; |
| import java.io.IOException; |
| import java.io.InterruptedIOException; |
| import java.io.OutputStream; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.io.Writer; |
| |
| import org.eclipse.jetty.util.log.Log; |
| import org.eclipse.jetty.util.log.Logger; |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * A wrapper for the {@link java.io.PrintWriter} that re-throws the instances of |
| * {@link java.io.IOException} thrown by the underlying implementation of |
| * {@link java.io.Writer} as {@link RuntimeIOException} instances. |
| */ |
| public class UncheckedPrintWriter extends PrintWriter |
| { |
| private static final Logger LOG = Log.getLogger(UncheckedPrintWriter.class); |
| |
| private boolean _autoFlush = false; |
| private IOException _ioException; |
| private boolean _isClosed = false; |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Line separator string. This is the value of the line.separator property |
| * at the moment that the stream was created. |
| */ |
| private String _lineSeparator; |
| |
| public UncheckedPrintWriter(Writer out) |
| { |
| this(out,false); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Create a new PrintWriter. |
| * |
| * @param out |
| * A character-output stream |
| * @param autoFlush |
| * A boolean; if true, the println() methods will flush the |
| * output buffer |
| */ |
| public UncheckedPrintWriter(Writer out, boolean autoFlush) |
| { |
| super(out,autoFlush); |
| this._autoFlush = autoFlush; |
| this._lineSeparator = System.getProperty("line.separator"); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Create a new PrintWriter, without automatic line flushing, from an |
| * existing OutputStream. This convenience constructor creates the necessary |
| * intermediate OutputStreamWriter, which will convert characters into bytes |
| * using the default character encoding. |
| * |
| * @param out |
| * An output stream |
| * |
| * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream) |
| */ |
| public UncheckedPrintWriter(OutputStream out) |
| { |
| this(out,false); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Create a new PrintWriter from an existing OutputStream. This convenience |
| * constructor creates the necessary intermediate OutputStreamWriter, which |
| * will convert characters into bytes using the default character encoding. |
| * |
| * @param out |
| * An output stream |
| * @param autoFlush |
| * A boolean; if true, the println() methods will flush the |
| * output buffer |
| * |
| * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream) |
| */ |
| public UncheckedPrintWriter(OutputStream out, boolean autoFlush) |
| { |
| this(new BufferedWriter(new OutputStreamWriter(out)),autoFlush); |
| } |
| |
| |
| /* ------------------------------------------------------------ */ |
| public boolean checkError() |
| { |
| return _ioException!=null || super.checkError(); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| private void setError(Throwable th) |
| { |
| |
| super.setError(); |
| |
| if (th instanceof IOException) |
| _ioException=(IOException)th; |
| else |
| { |
| _ioException=new IOException(String.valueOf(th)); |
| _ioException.initCause(th); |
| } |
| |
| LOG.debug(th); |
| } |
| |
| |
| @Override |
| protected void setError() |
| { |
| setError(new IOException()); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** Check to make sure that the stream has not been closed */ |
| private void isOpen() throws IOException |
| { |
| if (_ioException!=null) |
| throw new RuntimeIOException(_ioException); |
| |
| if (_isClosed) |
| throw new IOException("Stream closed"); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Flush the stream. |
| */ |
| @Override |
| public void flush() |
| { |
| try |
| { |
| synchronized (lock) |
| { |
| isOpen(); |
| out.flush(); |
| } |
| } |
| catch (IOException ex) |
| { |
| setError(ex); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Close the stream. |
| */ |
| @Override |
| public void close() |
| { |
| try |
| { |
| synchronized (lock) |
| { |
| out.close(); |
| _isClosed = true; |
| } |
| } |
| catch (IOException ex) |
| { |
| setError(ex); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Write a single character. |
| * |
| * @param c |
| * int specifying a character to be written. |
| */ |
| @Override |
| public void write(int c) |
| { |
| try |
| { |
| synchronized (lock) |
| { |
| isOpen(); |
| out.write(c); |
| } |
| } |
| catch (InterruptedIOException x) |
| { |
| Thread.currentThread().interrupt(); |
| } |
| catch (IOException ex) |
| { |
| setError(ex); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Write a portion of an array of characters. |
| * |
| * @param buf |
| * Array of characters |
| * @param off |
| * Offset from which to start writing characters |
| * @param len |
| * Number of characters to write |
| */ |
| @Override |
| public void write(char buf[], int off, int len) |
| { |
| try |
| { |
| synchronized (lock) |
| { |
| isOpen(); |
| out.write(buf,off,len); |
| } |
| } |
| catch (InterruptedIOException x) |
| { |
| Thread.currentThread().interrupt(); |
| } |
| catch (IOException ex) |
| { |
| setError(ex); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Write an array of characters. This method cannot be inherited from the |
| * Writer class because it must suppress I/O exceptions. |
| * |
| * @param buf |
| * Array of characters to be written |
| */ |
| @Override |
| public void write(char buf[]) |
| { |
| this.write(buf,0,buf.length); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Write a portion of a string. |
| * |
| * @param s |
| * A String |
| * @param off |
| * Offset from which to start writing characters |
| * @param len |
| * Number of characters to write |
| */ |
| @Override |
| public void write(String s, int off, int len) |
| { |
| try |
| { |
| synchronized (lock) |
| { |
| isOpen(); |
| out.write(s,off,len); |
| } |
| } |
| catch (InterruptedIOException x) |
| { |
| Thread.currentThread().interrupt(); |
| } |
| catch (IOException ex) |
| { |
| setError(ex); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Write a string. This method cannot be inherited from the Writer class |
| * because it must suppress I/O exceptions. |
| * |
| * @param s |
| * String to be written |
| */ |
| @Override |
| public void write(String s) |
| { |
| this.write(s,0,s.length()); |
| } |
| |
| private void newLine() |
| { |
| try |
| { |
| synchronized (lock) |
| { |
| isOpen(); |
| out.write(_lineSeparator); |
| if (_autoFlush) |
| out.flush(); |
| } |
| } |
| catch (InterruptedIOException x) |
| { |
| Thread.currentThread().interrupt(); |
| } |
| catch (IOException ex) |
| { |
| setError(ex); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print a boolean value. The string produced by <code>{@link |
| * java.lang.String#valueOf(boolean)}</code> is translated into bytes |
| * according to the platform's default character encoding, and these bytes |
| * are written in exactly the manner of the <code>{@link |
| * #write(int)}</code> method. |
| * |
| * @param b |
| * The <code>boolean</code> to be printed |
| */ |
| @Override |
| public void print(boolean b) |
| { |
| this.write(b?"true":"false"); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print a character. The character is translated into one or more bytes |
| * according to the platform's default character encoding, and these bytes |
| * are written in exactly the manner of the <code>{@link |
| * #write(int)}</code> method. |
| * |
| * @param c |
| * The <code>char</code> to be printed |
| */ |
| @Override |
| public void print(char c) |
| { |
| this.write(c); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print an integer. The string produced by <code>{@link |
| * java.lang.String#valueOf(int)}</code> is translated into bytes according |
| * to the platform's default character encoding, and these bytes are written |
| * in exactly the manner of the <code>{@link #write(int)}</code> method. |
| * |
| * @param i |
| * The <code>int</code> to be printed |
| * @see java.lang.Integer#toString(int) |
| */ |
| @Override |
| public void print(int i) |
| { |
| this.write(String.valueOf(i)); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print a long integer. The string produced by <code>{@link |
| * java.lang.String#valueOf(long)}</code> is translated into bytes according |
| * to the platform's default character encoding, and these bytes are written |
| * in exactly the manner of the <code>{@link #write(int)}</code> method. |
| * |
| * @param l |
| * The <code>long</code> to be printed |
| * @see java.lang.Long#toString(long) |
| */ |
| @Override |
| public void print(long l) |
| { |
| this.write(String.valueOf(l)); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print a floating-point number. The string produced by <code>{@link |
| * java.lang.String#valueOf(float)}</code> is translated into bytes |
| * according to the platform's default character encoding, and these bytes |
| * are written in exactly the manner of the <code>{@link #write(int)}</code> |
| * method. |
| * |
| * @param f |
| * The <code>float</code> to be printed |
| * @see java.lang.Float#toString(float) |
| */ |
| @Override |
| public void print(float f) |
| { |
| this.write(String.valueOf(f)); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print a double-precision floating-point number. The string produced by |
| * <code>{@link java.lang.String#valueOf(double)}</code> is translated into |
| * bytes according to the platform's default character encoding, and these |
| * bytes are written in exactly the manner of the <code>{@link |
| * #write(int)}</code> method. |
| * |
| * @param d |
| * The <code>double</code> to be printed |
| * @see java.lang.Double#toString(double) |
| */ |
| @Override |
| public void print(double d) |
| { |
| this.write(String.valueOf(d)); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print an array of characters. The characters are converted into bytes |
| * according to the platform's default character encoding, and these bytes |
| * are written in exactly the manner of the <code>{@link #write(int)}</code> |
| * method. |
| * |
| * @param s |
| * The array of chars to be printed |
| * |
| * @throws NullPointerException |
| * If <code>s</code> is <code>null</code> |
| */ |
| @Override |
| public void print(char s[]) |
| { |
| this.write(s); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print a string. If the argument is <code>null</code> then the string |
| * <code>"null"</code> is printed. Otherwise, the string's characters are |
| * converted into bytes according to the platform's default character |
| * encoding, and these bytes are written in exactly the manner of the |
| * <code>{@link #write(int)}</code> method. |
| * |
| * @param s |
| * The <code>String</code> to be printed |
| */ |
| @Override |
| public void print(String s) |
| { |
| if (s == null) |
| { |
| s = "null"; |
| } |
| this.write(s); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print an object. The string produced by the <code>{@link |
| * java.lang.String#valueOf(Object)}</code> method is translated into bytes |
| * according to the platform's default character encoding, and these bytes |
| * are written in exactly the manner of the <code>{@link #write(int)}</code> |
| * method. |
| * |
| * @param obj |
| * The <code>Object</code> to be printed |
| * @see java.lang.Object#toString() |
| */ |
| @Override |
| public void print(Object obj) |
| { |
| this.write(String.valueOf(obj)); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Terminate the current line by writing the line separator string. The line |
| * separator string is defined by the system property |
| * <code>line.separator</code>, and is not necessarily a single newline |
| * character (<code>'\n'</code>). |
| */ |
| @Override |
| public void println() |
| { |
| this.newLine(); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print a boolean value and then terminate the line. This method behaves as |
| * though it invokes <code>{@link #print(boolean)}</code> and then |
| * <code>{@link #println()}</code>. |
| * |
| * @param x |
| * the <code>boolean</code> value to be printed |
| */ |
| @Override |
| public void println(boolean x) |
| { |
| synchronized (lock) |
| { |
| this.print(x); |
| this.println(); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print a character and then terminate the line. This method behaves as |
| * though it invokes <code>{@link #print(char)}</code> and then <code>{@link |
| * #println()}</code>. |
| * |
| * @param x |
| * the <code>char</code> value to be printed |
| */ |
| @Override |
| public void println(char x) |
| { |
| synchronized (lock) |
| { |
| this.print(x); |
| this.println(); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print an integer and then terminate the line. This method behaves as |
| * though it invokes <code>{@link #print(int)}</code> and then <code>{@link |
| * #println()}</code>. |
| * |
| * @param x |
| * the <code>int</code> value to be printed |
| */ |
| @Override |
| public void println(int x) |
| { |
| synchronized (lock) |
| { |
| this.print(x); |
| this.println(); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print a long integer and then terminate the line. This method behaves as |
| * though it invokes <code>{@link #print(long)}</code> and then |
| * <code>{@link #println()}</code>. |
| * |
| * @param x |
| * the <code>long</code> value to be printed |
| */ |
| @Override |
| public void println(long x) |
| { |
| synchronized (lock) |
| { |
| this.print(x); |
| this.println(); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print a floating-point number and then terminate the line. This method |
| * behaves as though it invokes <code>{@link #print(float)}</code> and then |
| * <code>{@link #println()}</code>. |
| * |
| * @param x |
| * the <code>float</code> value to be printed |
| */ |
| @Override |
| public void println(float x) |
| { |
| synchronized (lock) |
| { |
| this.print(x); |
| this.println(); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print a double-precision floating-point number and then terminate the |
| * line. This method behaves as though it invokes <code>{@link |
| * #print(double)}</code> and then <code>{@link #println()}</code>. |
| * |
| * @param x |
| * the <code>double</code> value to be printed |
| */ |
| /* ------------------------------------------------------------ */ |
| @Override |
| public void println(double x) |
| { |
| synchronized (lock) |
| { |
| this.print(x); |
| this.println(); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print an array of characters and then terminate the line. This method |
| * behaves as though it invokes <code>{@link #print(char[])}</code> and then |
| * <code>{@link #println()}</code>. |
| * |
| * @param x |
| * the array of <code>char</code> values to be printed |
| */ |
| @Override |
| public void println(char x[]) |
| { |
| synchronized (lock) |
| { |
| this.print(x); |
| this.println(); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print a String and then terminate the line. This method behaves as though |
| * it invokes <code>{@link #print(String)}</code> and then |
| * <code>{@link #println()}</code>. |
| * |
| * @param x |
| * the <code>String</code> value to be printed |
| */ |
| @Override |
| public void println(String x) |
| { |
| synchronized (lock) |
| { |
| this.print(x); |
| this.println(); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Print an Object and then terminate the line. This method behaves as |
| * though it invokes <code>{@link #print(Object)}</code> and then |
| * <code>{@link #println()}</code>. |
| * |
| * @param x |
| * the <code>Object</code> value to be printed |
| */ |
| @Override |
| public void println(Object x) |
| { |
| synchronized (lock) |
| { |
| this.print(x); |
| this.println(); |
| } |
| } |
| } |