001    /* PrintStream.java -- OutputStream for printing output
002       Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010     
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package java.io;
040    
041    import java.util.Formatter;
042    import java.util.Locale;
043    
044    import gnu.gcj.convert.UnicodeToBytes;
045    
046    /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
047     * "The Java Language Specification", ISBN 0-201-63451-1
048     * Status:  Believed complete and correct to 1.3
049     */
050    
051    /**
052     * This class prints Java primitive values and object to a stream as
053     * text.  None of the methods in this class throw an exception.  However,
054     * errors can be detected by calling the <code>checkError()</code> method.
055     * Additionally, this stream can be designated as "autoflush" when 
056     * created so that any writes are automatically flushed to the underlying
057     * output sink when the current line is terminated.
058     * <p>
059     * This class converts char's into byte's using the system default encoding.
060     *
061     * @author Aaron M. Renn (arenn@urbanophile.com)
062     * @author Tom Tromey (tromey@cygnus.com)
063     */
064    public class PrintStream extends FilterOutputStream implements Appendable
065    {
066      /* Notice the implementation is quite similar to OutputStreamWriter.
067       * This leads to some minor duplication, because neither inherits
068       * from the other, and we want to maximize performance. */
069    
070      // Line separator string.
071      private static final char[] line_separator
072        = System.getProperty("line.separator").toCharArray();
073      
074      UnicodeToBytes converter;
075    
076      // Work buffer of characters for converter.
077      char[] work = new char[100];
078      // Work buffer of bytes where we temporarily keep converter output.
079      byte[] work_bytes = new byte[100];
080    
081      /**
082       * This boolean indicates whether or not an error has ever occurred
083       * on this stream.
084       */
085      private boolean error_occurred = false;
086    
087      /**
088       * This is <code>true</code> if auto-flush is enabled, 
089       * <code>false</code> otherwise
090       */
091      private boolean auto_flush;
092    
093      /**
094       * This method intializes a new <code>PrintStream</code> object to write
095       * to the specified output sink.
096       *
097       * @param out The <code>OutputStream</code> to write to.
098       */
099      public PrintStream (OutputStream out)
100      {
101        this (out, false);
102      }
103    
104      /**
105       * This method intializes a new <code>PrintStream</code> object to write
106       * to the specified output sink.  This constructor also allows "auto-flush"
107       * functionality to be specified where the stream will be flushed after
108       * every <code>print</code> or <code>println</code> call, when the 
109       * <code>write</code> methods with array arguments are called, or when a 
110       * single new-line character is written.
111       * <p>
112       *
113       * @param out The <code>OutputStream</code> to write to.
114       * @param auto_flush <code>true</code> to flush the stream after every 
115       * line, <code>false</code> otherwise
116       */
117      public PrintStream (OutputStream out, boolean auto_flush)
118      {
119        super (out);
120    
121        converter = UnicodeToBytes.getDefaultEncoder();
122        this.auto_flush = auto_flush;
123      }
124    
125      /**
126       * This method intializes a new <code>PrintStream</code> object to write
127       * to the specified output sink.  This constructor also allows "auto-flush"
128       * functionality to be specified where the stream will be flushed after
129       * every <code>print</code> or <code>println</code> call, when the 
130       * <code>write</code> methods with array arguments are called, or when a 
131       * single new-line character is written.
132       * <p>
133       *
134       * @param out The <code>OutputStream</code> to write to.
135       * @param auto_flush <code>true</code> to flush the stream after every 
136       * line, <code>false</code> otherwise
137       * @param encoding The name of the character encoding to use for this
138       * object.
139       */
140      public PrintStream (OutputStream out, boolean auto_flush, String encoding)
141        throws UnsupportedEncodingException
142      {
143        super (out);
144    
145        converter = UnicodeToBytes.getEncoder (encoding);
146        this.auto_flush = auto_flush;
147      }
148    
149      /**
150       * This method checks to see if an error has occurred on this stream.  Note
151       * that once an error has occurred, this method will continue to report
152       * <code>true</code> forever for this stream.  Before checking for an
153       * error condition, this method flushes the stream.
154       *
155       * @return <code>true</code> if an error has occurred, 
156       * <code>false</code> otherwise
157       */
158      public boolean checkError ()
159      {
160        flush ();
161        return error_occurred;
162      }
163    
164      /**
165       * This method can be called by subclasses to indicate that an error
166       * has occurred and should be reported by <code>checkError</code>.
167       */
168      protected void setError ()
169      {
170        error_occurred = true;
171      }
172    
173      /**
174       * This method closes this stream and all underlying streams.
175       */
176      public void close ()
177      {
178        try
179          {
180            converter.setFinished();
181            writeChars(new char[0], 0, 0);
182            flush();
183            out.close();
184          }
185        catch (InterruptedIOException iioe)
186          {
187            Thread.currentThread().interrupt();
188          }
189        catch (IOException e)
190          {
191            setError ();
192          }
193      }
194    
195      /**
196       * This method flushes any buffered bytes to the underlying stream and
197       * then flushes that stream as well.
198       */
199      public void flush ()
200      {
201        try
202          {
203            out.flush();
204          }
205        catch (InterruptedIOException iioe)
206          {
207            Thread.currentThread().interrupt();
208          }
209        catch (IOException e)
210          {
211            setError ();
212          }
213      }
214    
215      private synchronized void print (String str, boolean println)
216      {
217        try
218          {
219            writeChars(str, 0, str.length());
220            if (println)
221              writeChars(line_separator, 0, line_separator.length);
222            if (auto_flush)
223              flush();
224          }
225        catch (InterruptedIOException iioe)
226          {
227            Thread.currentThread().interrupt();
228          }
229        catch (IOException e)
230          {
231            setError ();
232          }
233      }
234    
235      private synchronized void print (char[] chars, int pos, int len,
236                                       boolean println)
237      {
238        try
239          {
240            writeChars(chars, pos, len);
241            if (println)
242              writeChars(line_separator, 0, line_separator.length);
243            if (auto_flush)
244              flush();
245          }
246        catch (InterruptedIOException iioe)
247          {
248            Thread.currentThread().interrupt();
249          }
250        catch (IOException e)
251          {
252            setError ();
253          }
254      }
255    
256      private void writeChars(char[] buf, int offset, int count)
257        throws IOException
258      {
259        do
260          {
261            converter.setOutput(work_bytes, 0);
262            int converted = converter.write(buf, offset, count);
263            offset += converted;
264            count -= converted;
265            out.write(work_bytes, 0, converter.count);
266          }
267        while (count > 0 || converter.havePendingBytes());
268      }
269    
270      private void writeChars(String str, int offset, int count)
271        throws IOException
272      {
273        do
274          {
275            converter.setOutput(work_bytes, 0);
276            int converted = converter.write(str, offset, count, work);
277            offset += converted;
278            count -= converted;
279            out.write(work_bytes, 0, converter.count);
280          }
281        while (count > 0 || converter.havePendingBytes());
282      }
283    
284      /**
285       * This methods prints a boolean value to the stream.  <code>true</code>
286       * values are printed as "true" and <code>false</code> values are printed
287       * as "false".
288       *
289       * @param bool The <code>boolean</code> value to print
290       */
291      public void print (boolean bool)
292      {
293        print(String.valueOf(bool), false);
294      }
295    
296      /**
297       * This method prints an integer to the stream.  The value printed is
298       * determined using the <code>String.valueOf()</code> method.
299       *
300       * @param inum The <code>int</code> value to be printed
301       */
302      public void print (int inum)
303      {
304        print(String.valueOf(inum), false);
305      }
306    
307      /**
308       * This method prints a long to the stream.  The value printed is
309       * determined using the <code>String.valueOf()</code> method.
310       *
311       * @param lnum The <code>long</code> value to be printed
312       */
313      public void print (long lnum)
314      {
315        print(String.valueOf(lnum), false);
316      }
317    
318      /**
319       * This method prints a float to the stream.  The value printed is
320       * determined using the <code>String.valueOf()</code> method.
321       *
322       * @param fnum The <code>float</code> value to be printed
323       */
324      public void print (float fnum)
325      {
326        print(String.valueOf(fnum), false);
327      }
328    
329      /**
330       * This method prints a double to the stream.  The value printed is
331       * determined using the <code>String.valueOf()</code> method.
332       *
333       * @param dnum The <code>double</code> value to be printed
334       */
335      public void print (double dnum)
336      {
337        print(String.valueOf(dnum), false);
338      }
339    
340      /**
341       * This method prints an <code>Object</code> to the stream.  The actual
342       * value printed is determined by calling the <code>String.valueOf()</code>
343       * method.
344       *
345       * @param obj The <code>Object</code> to print.
346       */
347      public void print (Object obj)
348      {
349        print(obj == null ? "null" : obj.toString(), false);
350      }
351    
352      /**
353       * This method prints a <code>String</code> to the stream.  The actual
354       * value printed depends on the system default encoding.
355       *
356       * @param str The <code>String</code> to print.
357       */
358      public void print (String str)
359      {
360        print(str == null ? "null" : str, false);
361      }
362    
363      /**
364       * This method prints a char to the stream.  The actual value printed is
365       * determined by the character encoding in use.
366       *
367       * @param ch The <code>char</code> value to be printed
368       */
369      public synchronized void print (char ch)
370      {
371        work[0] = ch;
372        print(work, 0, 1, false);
373      }
374    
375      /**
376       * This method prints an array of characters to the stream.  The actual
377       * value printed depends on the system default encoding.
378       *
379       * @param charArray The array of characters to print.
380       */
381      public void print (char[] charArray)
382      {
383        print(charArray, 0, charArray.length, false);
384      }
385    
386      /**
387       * This method prints a line separator sequence to the stream.  The value
388       * printed is determined by the system property <xmp>line.separator</xmp>
389       * and is not necessarily the Unix '\n' newline character.
390       */
391      public void println ()
392      {
393        print(line_separator, 0, line_separator.length, false);
394      }
395    
396      /**
397       * This methods prints a boolean value to the stream.  <code>true</code>
398       * values are printed as "true" and <code>false</code> values are printed
399       * as "false".
400       * <p>
401       * This method prints a line termination sequence after printing the value.
402       *
403       * @param bool The <code>boolean</code> value to print
404       */
405      public void println (boolean bool)
406      {
407        print(String.valueOf(bool), true);
408      }
409    
410      /**
411       * This method prints an integer to the stream.  The value printed is
412       * determined using the <code>String.valueOf()</code> method.
413       * <p>
414       * This method prints a line termination sequence after printing the value.
415       *
416       * @param inum The <code>int</code> value to be printed
417       */
418      public void println (int inum)
419      {
420        print(String.valueOf(inum), true);
421      }
422    
423      /**
424       * This method prints a long to the stream.  The value printed is
425       * determined using the <code>String.valueOf()</code> method.
426       * <p>
427       * This method prints a line termination sequence after printing the value.
428       *
429       * @param lnum The <code>long</code> value to be printed
430       */
431      public void println (long lnum)
432      {
433        print(String.valueOf(lnum), true);
434      }
435    
436      /**
437       * This method prints a float to the stream.  The value printed is
438       * determined using the <code>String.valueOf()</code> method.
439       * <p>
440       * This method prints a line termination sequence after printing the value.
441       *
442       * @param fnum The <code>float</code> value to be printed
443       */
444      public void println (float fnum)
445      {
446        print(String.valueOf(fnum), true);
447      }
448    
449      /**
450       * This method prints a double to the stream.  The value printed is
451       * determined using the <code>String.valueOf()</code> method.
452       * <p>
453       * This method prints a line termination sequence after printing the value.
454       *
455       * @param dnum The <code>double</code> value to be printed
456       */
457      public void println (double dnum)
458      {
459        print(String.valueOf(dnum), true);
460      }
461    
462      /**
463       * This method prints an <code>Object</code> to the stream.  The actual
464       * value printed is determined by calling the <code>String.valueOf()</code>
465       * method.
466       * <p>
467       * This method prints a line termination sequence after printing the value.
468       *
469       * @param obj The <code>Object</code> to print.
470       */
471      public void println (Object obj)
472      {
473        print(obj == null ? "null" : obj.toString(), true);
474      }
475    
476      /**
477       * This method prints a <code>String</code> to the stream.  The actual
478       * value printed depends on the system default encoding.
479       * <p>
480       * This method prints a line termination sequence after printing the value.
481       *
482       * @param str The <code>String</code> to print.
483       */
484      public void println (String str)
485      {
486        print (str == null ? "null" : str, true);
487      }
488    
489      /**
490       * This method prints a char to the stream.  The actual value printed is
491       * determined by the character encoding in use.
492       * <p>
493       * This method prints a line termination sequence after printing the value.
494       *
495       * @param ch The <code>char</code> value to be printed
496       */
497      public synchronized void println (char ch)
498      {
499        work[0] = ch;
500        print(work, 0, 1, true);
501      }
502    
503      /**
504       * This method prints an array of characters to the stream.  The actual
505       * value printed depends on the system default encoding.
506       * <p>
507       * This method prints a line termination sequence after printing the value.
508       *
509       * @param charArray The array of characters to print.
510       */
511      public void println (char[] charArray)
512      {
513        print(charArray, 0, charArray.length, true);
514      }
515    
516      /**
517       * This method writes a byte of data to the stream.  If auto-flush is
518       * enabled, printing a newline character will cause the stream to be
519       * flushed after the character is written.
520       * 
521       * @param oneByte The byte to be written
522       */
523      public void write (int oneByte)
524      {
525        try
526          {
527            out.write (oneByte & 0xff);
528            
529            if (auto_flush && (oneByte == '\n'))
530              flush ();
531          }
532        catch (InterruptedIOException iioe)
533          {
534            Thread.currentThread ().interrupt ();
535          }
536        catch (IOException e)
537          {
538            setError ();
539          }
540      }
541    
542      /**
543       * This method writes <code>len</code> bytes from the specified array
544       * starting at index <code>offset</code> into the array.
545       *
546       * @param buffer The array of bytes to write
547       * @param offset The index into the array to start writing from
548       * @param len The number of bytes to write
549       */
550      public void write (byte[] buffer, int offset, int len)
551      {
552        try
553          {
554            out.write (buffer, offset, len);
555            
556            if (auto_flush)
557              flush ();
558          }
559        catch (InterruptedIOException iioe)
560          {
561            Thread.currentThread ().interrupt ();
562          }
563        catch (IOException e)
564          {
565            setError ();
566          }
567      }
568    
569      /** @since 1.5 */
570      public PrintStream append(char c)
571      {
572        print(c);
573        return this;
574      }
575    
576      /** @since 1.5 */
577      public PrintStream append(CharSequence cs)
578      {
579        print(cs == null ? "null" : cs.toString());
580        return this;
581      }
582    
583      /** @since 1.5 */
584      public PrintStream append(CharSequence cs, int start, int end)
585      {
586        print(cs == null ? "null" : cs.subSequence(start, end).toString());
587        return this;
588      }
589    
590      /** @since 1.5 */
591      public PrintStream printf(String format, Object... args)
592      {
593        return format(format, args);
594      }
595    
596      /** @since 1.5 */
597      public PrintStream printf(Locale locale, String format, Object... args)
598      {
599        return format(locale, format, args);
600      }
601    
602      /** @since 1.5 */
603      public PrintStream format(String format, Object... args)
604      {
605        return format(Locale.getDefault(), format, args);
606      }
607    
608      /** @since 1.5 */
609      public PrintStream format(Locale locale, String format, Object... args)
610      {
611        Formatter f = new Formatter(this, locale);
612        f.format(format, args);
613        return this;
614      }
615    } // class PrintStream
616