/* PrintStream.java -- OutputStream for printing output
   Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005, 2006
   Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.io;

import java.util.Locale;
import java.util.Formatter;

import gnu.classpath.SystemProperties;

/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
 * "The Java Language Specification", ISBN 0-201-63451-1
 * Status:  Believed complete and correct to 1.3
 */

/**
 * This class prints Java primitive values and object to a stream as
 * text.  None of the methods in this class throw an exception.  However,
 * errors can be detected by calling the <code>checkError()</code> method.
 * Additionally, this stream can be designated as "autoflush" when
 * created so that any writes are automatically flushed to the underlying
 * output sink when the current line is terminated.
 * <p>
 * This class converts char's into byte's using the system default encoding.
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @author Tom Tromey (tromey@cygnus.com)
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 */
public class PrintStream extends FilterOutputStream implements Appendable
{
  /* Notice the implementation is quite similar to OutputStreamWriter.
   * This leads to some minor duplication, because neither inherits
   * from the other, and we want to maximize performance. */

  // Line separator string.
  private static final char[] line_separator
    = SystemProperties.getProperty("line.separator", "\n").toCharArray();

  /**
   *  Encoding name
   */
  private final String encoding;

  /**
   * This boolean indicates whether or not an error has ever occurred
   * on this stream.
   */
  private boolean error_occurred = false;

  /**
   * This is <code>true</code> if auto-flush is enabled,
   * <code>false</code> otherwise
   */
  private final boolean auto_flush;

  /**
   * This method initializes a new <code>PrintStream</code> object to write
   * to the specified output File. Doesn't autoflush.
   *
   * @param file The <code>File</code> to write to.
   * @throws FileNotFoundException if an error occurs while opening the file.
   *
   * @since 1.5
   */
  public PrintStream (File file)
    throws FileNotFoundException
  {
    this (new FileOutputStream(file), false);
  }

  /**
   * This method initializes a new <code>PrintStream</code> object to write
   * to the specified output File. Doesn't autoflush.
   *
   * @param file The <code>File</code> to write to.
   * @param encoding The name of the character encoding to use for this
   * object.
   * @throws FileNotFoundException If an error occurs while opening the file.
   * @throws UnsupportedEncodingException If the charset specified by
   * <code>encoding</code> is invalid.
   *
   * @since 1.5
   */
  public PrintStream (File file, String encoding)
    throws FileNotFoundException,UnsupportedEncodingException
  {
    this (new FileOutputStream(file), false, encoding);
  }

  /**
   * This method initializes a new <code>PrintStream</code> object to write
   * to the specified output File. Doesn't autoflush.
   *
   * @param fileName The name of the <code>File</code> to write to.
   * @throws FileNotFoundException if an error occurs while opening the file,
   *
   * @since 1.5
   */
  public PrintStream (String fileName)
    throws FileNotFoundException
  {
    this (new FileOutputStream(new File(fileName)), false);
  }

  /**
   * This method initializes a new <code>PrintStream</code> object to write
   * to the specified output File. Doesn't autoflush.
   *
   * @param fileName The name of the <code>File</code> to write to.
   * @param encoding The name of the character encoding to use for this
   * object.
   * @throws FileNotFoundException if an error occurs while opening the file.
   * @throws UnsupportedEncodingException If the charset specified by
   * <code>encoding</code> is invalid.
   *
   * @since 1.5
   */
  public PrintStream (String fileName, String encoding)
      throws FileNotFoundException,UnsupportedEncodingException
  {
    this (new FileOutputStream(new File(fileName)), false, encoding);
  }

  /**
   * This method initializes a new <code>PrintStream</code> object to write
   * to the specified output sink. Doesn't autoflush.
   *
   * @param out The <code>OutputStream</code> to write to.
   */
  public PrintStream (OutputStream out)
  {
    this (out, false);
  }

  /**
   * This method initializes a new <code>PrintStream</code> object to write
   * to the specified output sink.  This constructor also allows "auto-flush"
   * functionality to be specified where the stream will be flushed after
   * every <code>print</code> or <code>println</code> call, when the
   * <code>write</code> methods with array arguments are called, or when a
   * single new-line character is written.
   * <p>
   *
   * @param out The <code>OutputStream</code> to write to.
   * @param auto_flush <code>true</code> to flush the stream after every
   * line, <code>false</code> otherwise
   * @exception NullPointerException If out is null.
   */
  public PrintStream (OutputStream out, boolean auto_flush)
  {
    super (out);

    if (out == null)
      throw new NullPointerException("out is null");

    String encoding;
    try {
        encoding = SystemProperties.getProperty("file.encoding");
    } catch (SecurityException e){
        encoding = "ISO8859_1";
    } catch (IllegalArgumentException e){
        encoding = "ISO8859_1";
    } catch (NullPointerException e){
        encoding = "ISO8859_1";
    }
    this.encoding = encoding;
    this.auto_flush = auto_flush;
  }

  /**
   * This method initializes a new <code>PrintStream</code> object to write
   * to the specified output sink.  This constructor also allows "auto-flush"
   * functionality to be specified where the stream will be flushed after
   * every <code>print</code> or <code>println</code> call, when the
   * <code>write</code> methods with array arguments are called, or when a
   * single new-line character is written.
   * <p>
   *
   * @param out The <code>OutputStream</code> to write to.
   * @param auto_flush <code>true</code> to flush the stream after every
   * line, <code>false</code> otherwise
   * @param encoding The name of the character encoding to use for this
   * object.
   * @exception NullPointerException If out or encoding is null.
   */
  public PrintStream (OutputStream out, boolean auto_flush, String encoding)
    throws UnsupportedEncodingException
  {
    super (out);

    if (out == null)
      throw new NullPointerException("out is null");

    if (encoding == null)
      throw new NullPointerException("encoding is null");

    new String(new byte[]{0}, encoding);    // check if encoding is supported
    this.encoding = encoding;
    this.auto_flush = auto_flush;
  }

  /**
   * This method checks to see if an error has occurred on this stream.  Note
   * that once an error has occurred, this method will continue to report
   * <code>true</code> forever for this stream.  Before checking for an
   * error condition, this method flushes the stream.
   *
   * @return <code>true</code> if an error has occurred,
   * <code>false</code> otherwise
   */
  public boolean checkError ()
  {
    flush ();
    return error_occurred;
  }

  /**
   * This method can be called by subclasses to indicate that an error
   * has occurred and should be reported by <code>checkError</code>.
   */
  protected void setError ()
  {
    error_occurred = true;
  }

  /**
   * This method closes this stream and all underlying streams.
   */
  public void close ()
  {
    try
      {
        flush();
        out.close();
      }
    catch (InterruptedIOException iioe)
      {
        Thread.currentThread().interrupt();
      }
    catch (IOException e)
      {
        setError ();
      }
  }

  /**
   * This method flushes any buffered bytes to the underlying stream and
   * then flushes that stream as well.
   */
  public void flush ()
  {
    try
      {
        out.flush();
      }
    catch (InterruptedIOException iioe)
      {
        Thread.currentThread().interrupt();
      }
    catch (IOException e)
      {
        setError ();
      }
  }

  private synchronized void print (String str, boolean println)
  {
    try
      {
        writeChars(str, 0, str.length());
        if (println)
          writeChars(line_separator, 0, line_separator.length);
        if (auto_flush)
          flush();
      }
    catch (InterruptedIOException iioe)
      {
        Thread.currentThread().interrupt();
      }
    catch (IOException e)
      {
        setError ();
      }
  }

  private synchronized void print (char[] chars, int pos, int len,
                                   boolean println)
  {
    try
      {
        writeChars(chars, pos, len);
        if (println)
          writeChars(line_separator, 0, line_separator.length);
        if (auto_flush)
          flush();
      }
    catch (InterruptedIOException iioe)
      {
        Thread.currentThread().interrupt();
      }
    catch (IOException e)
      {
        setError ();
      }
  }

  private void writeChars(char[] buf, int offset, int count)
    throws IOException
  {
      byte[] bytes = (new String(buf, offset, count)).getBytes(encoding);
      out.write(bytes, 0, bytes.length);
  }

  private void writeChars(String str, int offset, int count)
    throws IOException
  {
      byte[] bytes = str.substring(offset, offset+count).getBytes(encoding);
      out.write(bytes, 0, bytes.length);
  }

  /**
   * This methods prints a boolean value to the stream.  <code>true</code>
   * values are printed as "true" and <code>false</code> values are printed
   * as "false".
   *
   * @param bool The <code>boolean</code> value to print
   */
  public void print (boolean bool)
  {
    print(String.valueOf(bool), false);
  }

  /**
   * This method prints an integer to the stream.  The value printed is
   * determined using the <code>String.valueOf()</code> method.
   *
   * @param inum The <code>int</code> value to be printed
   */
  public void print (int inum)
  {
    print(String.valueOf(inum), false);
  }

  /**
   * This method prints a long to the stream.  The value printed is
   * determined using the <code>String.valueOf()</code> method.
   *
   * @param lnum The <code>long</code> value to be printed
   */
  public void print (long lnum)
  {
    print(String.valueOf(lnum), false);
  }

  /**
   * This method prints a float to the stream.  The value printed is
   * determined using the <code>String.valueOf()</code> method.
   *
   * @param fnum The <code>float</code> value to be printed
   */
  public void print (float fnum)
  {
    print(String.valueOf(fnum), false);
  }

  /**
   * This method prints a double to the stream.  The value printed is
   * determined using the <code>String.valueOf()</code> method.
   *
   * @param dnum The <code>double</code> value to be printed
   */
  public void print (double dnum)
  {
    print(String.valueOf(dnum), false);
  }

  /**
   * This method prints an <code>Object</code> to the stream.  The actual
   * value printed is determined by calling the <code>String.valueOf()</code>
   * method.
   *
   * @param obj The <code>Object</code> to print.
   */
  public void print (Object obj)
  {
    print(obj == null ? "null" : obj.toString(), false);
  }

  /**
   * This method prints a <code>String</code> to the stream.  The actual
   * value printed depends on the system default encoding.
   *
   * @param str The <code>String</code> to print.
   */
  public void print (String str)
  {
    print(str == null ? "null" : str, false);
  }

  /**
   * This method prints a char to the stream.  The actual value printed is
   * determined by the character encoding in use.
   *
   * @param ch The <code>char</code> value to be printed
   */
  public synchronized void print (char ch)
  {
    print(new char[]{ch}, 0, 1, false);
  }

  /**
   * This method prints an array of characters to the stream.  The actual
   * value printed depends on the system default encoding.
   *
   * @param charArray The array of characters to print.
   */
  public void print (char[] charArray)
  {
    print(charArray, 0, charArray.length, false);
  }

  /**
   * This method prints a line separator sequence to the stream.  The value
   * printed is determined by the system property <xmp>line.separator</xmp>
   * and is not necessarily the Unix '\n' newline character.
   */
  public void println ()
  {
    print(line_separator, 0, line_separator.length, false);
  }

  /**
   * This methods prints a boolean value to the stream.  <code>true</code>
   * values are printed as "true" and <code>false</code> values are printed
   * as "false".
   * <p>
   * This method prints a line termination sequence after printing the value.
   *
   * @param bool The <code>boolean</code> value to print
   */
  public void println (boolean bool)
  {
    print(String.valueOf(bool), true);
  }

  /**
   * This method prints an integer to the stream.  The value printed is
   * determined using the <code>String.valueOf()</code> method.
   * <p>
   * This method prints a line termination sequence after printing the value.
   *
   * @param inum The <code>int</code> value to be printed
   */
  public void println (int inum)
  {
    print(String.valueOf(inum), true);
  }

  /**
   * This method prints a long to the stream.  The value printed is
   * determined using the <code>String.valueOf()</code> method.
   * <p>
   * This method prints a line termination sequence after printing the value.
   *
   * @param lnum The <code>long</code> value to be printed
   */
  public void println (long lnum)
  {
    print(String.valueOf(lnum), true);
  }

  /**
   * This method prints a float to the stream.  The value printed is
   * determined using the <code>String.valueOf()</code> method.
   * <p>
   * This method prints a line termination sequence after printing the value.
   *
   * @param fnum The <code>float</code> value to be printed
   */
  public void println (float fnum)
  {
    print(String.valueOf(fnum), true);
  }

  /**
   * This method prints a double to the stream.  The value printed is
   * determined using the <code>String.valueOf()</code> method.
   * <p>
   * This method prints a line termination sequence after printing the value.
   *
   * @param dnum The <code>double</code> value to be printed
   */
  public void println (double dnum)
  {
    print(String.valueOf(dnum), true);
  }

  /**
   * This method prints an <code>Object</code> to the stream.  The actual
   * value printed is determined by calling the <code>String.valueOf()</code>
   * method.
   * <p>
   * This method prints a line termination sequence after printing the value.
   *
   * @param obj The <code>Object</code> to print.
   */
  public void println (Object obj)
  {
    print(obj == null ? "null" : obj.toString(), true);
  }

  /**
   * This method prints a <code>String</code> to the stream.  The actual
   * value printed depends on the system default encoding.
   * <p>
   * This method prints a line termination sequence after printing the value.
   *
   * @param str The <code>String</code> to print.
   */
  public void println (String str)
  {
    print (str == null ? "null" : str, true);
  }

  /**
   * This method prints a char to the stream.  The actual value printed is
   * determined by the character encoding in use.
   * <p>
   * This method prints a line termination sequence after printing the value.
   *
   * @param ch The <code>char</code> value to be printed
   */
  public synchronized void println (char ch)
  {
    print(new char[]{ch}, 0, 1, true);
  }

  /**
   * This method prints an array of characters to the stream.  The actual
   * value printed depends on the system default encoding.
   * <p>
   * This method prints a line termination sequence after printing the value.
   *
   * @param charArray The array of characters to print.
   */
  public void println (char[] charArray)
  {
    print(charArray, 0, charArray.length, true);
  }

  /**
   * This method writes a byte of data to the stream.  If auto-flush is
   * enabled, printing a newline character will cause the stream to be
   * flushed after the character is written.
   *
   * @param oneByte The byte to be written
   */
  public void write (int oneByte)
  {
    try
      {
        out.write (oneByte & 0xff);

        if (auto_flush && (oneByte == '\n'))
          flush ();
      }
    catch (InterruptedIOException iioe)
      {
        Thread.currentThread ().interrupt ();
      }
    catch (IOException e)
      {
        setError ();
      }
  }

  /**
   * This method writes <code>len</code> bytes from the specified array
   * starting at index <code>offset</code> into the array.
   *
   * @param buffer The array of bytes to write
   * @param offset The index into the array to start writing from
   * @param len The number of bytes to write
   */
  public void write (byte[] buffer, int offset, int len)
  {
    try
      {
        out.write (buffer, offset, len);

        if (auto_flush)
          flush ();
      }
    catch (InterruptedIOException iioe)
      {
        Thread.currentThread ().interrupt ();
      }
    catch (IOException e)
      {
        setError ();
      }
  }

  /** @since 1.5 */
  public PrintStream append(char c)
  {
    print(c);
    return this;
  }

  /** @since 1.5 */
  public PrintStream append(CharSequence cs)
  {
    print(cs == null ? "null" : cs.toString());
    return this;
  }

  /** @since 1.5 */
  public PrintStream append(CharSequence cs, int start, int end)
  {
    print(cs == null ? "null" : cs.subSequence(start, end).toString());
    return this;
  }

  /** @since 1.5 */
  public PrintStream printf(String format, Object... args)
  {
    return format(format, args);
  }

  /** @since 1.5 */
  public PrintStream printf(Locale locale, String format, Object... args)
  {
    return format(locale, format, args);
  }

  /** @since 1.5 */
  public PrintStream format(String format, Object... args)
  {
    return format(Locale.getDefault(), format, args);
  }

  /** @since 1.5 */
  public PrintStream format(Locale locale, String format, Object... args)
  {
    Formatter f = new Formatter(this, locale);
    f.format(format, args);
    return this;
  }
} // class PrintStream
