KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > vfs > WriteStream


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.vfs;
31
32 import com.caucho.util.CharSegment;
33 import com.caucho.vfs.i18n.EncodingWriter;
34
35 import java.io.IOException JavaDoc;
36 import java.io.InputStream JavaDoc;
37 import java.io.PrintWriter JavaDoc;
38 import java.io.Reader JavaDoc;
39 import java.io.UnsupportedEncodingException JavaDoc;
40 import java.io.Writer JavaDoc;
41 import java.util.Iterator JavaDoc;
42 import java.util.Locale JavaDoc;
43
44 /**
45  * A fast bufferered output stream supporting both character
46  * and byte data. The underlying stream sources are provided by StreamImpl
47  * classes, so all streams have the same API regardless of the underlying
48  * implementation.
49  *
50  * <p>OutputStream and Writers are combined. The <code>write</code> routines
51  * write bytes and the <code>print</code> routines write characters.
52  *
53  * <p>Most applications will use the Path routines to create their own streams.
54  * Specialized applications, like servers, need the capability of recycling
55  * streams.
56  */

57 public class WriteStream extends OutputStreamWithBuffer {
58   private static byte []lfBytes = new byte[] {'\n'};
59   private static byte []crBytes = new byte[] {'\r'};
60   private static byte []crlfBytes = new byte[] {'\r', '\n'};
61
62   private static String JavaDoc _sysNewline;
63   private static byte []_sysNewlineBytes;
64
65   static {
66     _sysNewline = Path.getNewlineString();
67     _sysNewlineBytes = _sysNewline.getBytes();
68   }
69   
70   private TempBuffer _tempWrite;
71   private byte []_writeBuffer;
72   private int _writeLength;
73
74   private StreamImpl _source;
75
76   private char []chars;
77   private byte []_bytes;
78
79   private EncodingWriter _writeEncoding;
80   private String JavaDoc _writeEncodingName;
81
82   private boolean _implicitFlush = false;
83   private boolean flushOnNewline;
84   private boolean _disableClose;
85   private boolean _isDisableCloseSource;
86   private boolean _disableFlush;
87   private boolean reuseBuffer;
88
89   private StreamWriter _writer;
90   private StreamPrintWriter _printWriter;
91
92   private String JavaDoc newline = "\n";
93   private byte []newlineBytes = lfBytes;
94
95   /**
96    * Creates an uninitialized stream. Use <code>init</code> to initialize.
97    */

98   public WriteStream()
99   {
100   }
101
102   /**
103    * Creates a stream and initializes with a specified source.
104    *
105    * @param source Underlying source for the stream.
106    */

107   public WriteStream(StreamImpl source)
108   {
109     init(source);
110   }
111
112   /**
113    * Initializes the stream with a given source.
114    *
115    * @param source Underlying source for the stream.
116    */

117   public void init(StreamImpl source)
118   {
119     _disableClose = false;
120     _isDisableCloseSource = false;
121
122     if (this._source != null && this._source != source) {
123       try {
124     close();
125       } catch (IOException JavaDoc e) {
126       }
127     }
128
129     if (source == null)
130       throw new IllegalArgumentException JavaDoc();
131
132     if (_tempWrite == null) {
133       _tempWrite = TempBuffer.allocate();
134       _writeBuffer = _tempWrite._buf;
135     }
136
137     this._source = source;
138
139     _writeLength = 0;
140     flushOnNewline = source.getFlushOnNewline();
141     // Possibly, this should be dependent on the source. For example,
142
// a http: stream should behave the same on Mac as on unix.
143
// For now, CauchoSystem.getNewlineString() returns "\n".
144
newline = _sysNewline;
145     newlineBytes = _sysNewlineBytes;
146
147     _writeEncoding = null;
148     _writeEncodingName = "ISO-8859-1";
149   }
150
151   /**
152    * Returns the underlying source for the stream.
153    *
154    * @return the source
155    */

156   public StreamImpl getSource()
157   {
158     return _source;
159   }
160
161   /**
162    * Pushes a filter on the top of the stream stack.
163    *
164    * @param filter the filter to be added.
165    */

166   public void pushFilter(StreamFilter filter)
167   {
168     filter.init(_source);
169     _source = filter;
170   }
171
172   /**
173    * Returns true if the buffer allows writes.
174    *
175    * <p>LogStreams, used for debugging, use this feature to
176    * test if they should write with very little overhead.
177    *
178    * <code><pre>
179    * if (dbg.canWrite())
180    * dbg.log("some debug value " + expensiveDebugCalculation(foo));
181    * </pre></code>
182    */

183   public boolean canWrite()
184   {
185     return _source != null && _source.canWrite();
186   }
187
188   /**
189    * Clears the write buffer
190    */

191   public void clearWrite()
192   {
193     if (_source != null)
194       _source.clearWrite();
195   }
196
197   public void setReuseBuffer(boolean reuse)
198   {
199     this.reuseBuffer = reuse;
200   }
201
202   /**
203    * Returns the write buffer.
204    */

205   public byte []getBuffer()
206   {
207     return _writeBuffer;
208   }
209
210   /**
211    * Returns the write offset.
212    */

213   public int getBufferOffset()
214   {
215     return _writeLength;
216   }
217
218   /**
219    * Sets the write offset.
220    */

221   public void setBufferOffset(int offset)
222   {
223     _writeLength = offset;
224   }
225
226   /**
227    * Returns the write size.
228    */

229   public int getBufferSize()
230   {
231     return _writeBuffer.length;
232   }
233
234   /**
235    * Returns the bytes remaining in the buffer.
236    */

237   public int getRemaining()
238   {
239     if (_source == null)
240       return 0;
241     else
242       return _writeBuffer.length - _writeLength;
243   }
244
245   public void setImplicitFlush(boolean implicitFlush)
246   {
247     _implicitFlush = implicitFlush;
248   }
249
250   /**
251    * Writes a byte.
252    */

253   public void write(int ch) throws IOException JavaDoc
254   {
255     if (_source == null)
256       return;
257
258     int len = _writeLength;
259     if (_writeBuffer.length <= len) {
260       _writeLength = 0;
261       _source.write(_writeBuffer, 0, len, false);
262     }
263
264     _writeBuffer[_writeLength++] = (byte) ch;
265
266     if (_implicitFlush)
267       flush();
268   }
269
270   /**
271    * Writes a byte array
272    */

273   public void write(byte []buf, int offset, int length) throws IOException JavaDoc
274   {
275     byte []buffer = _writeBuffer;
276     
277     if (_source == null)
278       return;
279
280     int bufferLength = buffer.length;
281     int writeLength = _writeLength;
282
283     if (bufferLength <= length &&
284     _source.write(buffer, 0, writeLength,
285               buf, offset, length, false)) {
286       _writeLength = 0;
287       return;
288     }
289     
290     while (length > 0) {
291       int sublen = bufferLength - writeLength;
292
293       if (length < sublen)
294     sublen = length;
295       
296       System.arraycopy(buf, offset, buffer, writeLength, sublen);
297
298       writeLength += sublen;
299       offset += sublen;
300       length -= sublen;
301
302       if (bufferLength <= writeLength) {
303     int len = writeLength;
304     writeLength = 0;
305     _source.write(buffer, 0, len, false);
306       }
307     }
308
309     _writeLength = writeLength;
310
311     if (_implicitFlush)
312       flush();
313   }
314
315   /**
316    * Flushes and writes the buffer
317    */

318   public byte []nextBuffer(int offset) throws IOException JavaDoc
319   {
320     _writeLength = 0;
321     _source.write(_writeBuffer, 0, offset, false);
322
323     if (_implicitFlush)
324       flush();
325
326     return _writeBuffer;
327   }
328
329   /**
330    * Writes a byte array.
331    */

332   public void write(byte []buf) throws IOException JavaDoc
333   {
334     write(buf, 0, buf.length);
335   }
336
337   /**
338    * Flushes the buffer to the source.
339    */

340   public void flush() throws IOException JavaDoc
341   {
342     if (_disableFlush || _source == null)
343       return;
344
345     int len = _writeLength;
346     if (len > 0) {
347       _writeLength = 0;
348       _source.write(_writeBuffer, 0, len, false);
349     }
350
351     if (_source != null)
352       _source.flush();
353   }
354
355   /**
356    * Flushes the buffer to the disk
357    */

358   public void flushToDisk() throws IOException JavaDoc
359   {
360     StreamImpl source = _source;
361     
362     if (_disableFlush || source == null)
363       return;
364
365     int len = _writeLength;
366     if (len > 0) {
367       _writeLength = 0;
368       source.write(_writeBuffer, 0, len, false);
369     }
370
371     source.flushToDisk();
372   }
373
374   /**
375    * Flushes the buffer to the source.
376    */

377   public void flushBuffer() throws IOException JavaDoc
378   {
379     if (_disableFlush || _source == null)
380       return;
381
382     int len = _writeLength;
383     if (len > 0) {
384       _writeLength = 0;
385       _source.write(_writeBuffer, 0, len, false);
386       _source.flushBuffer();
387     }
388   }
389
390   /**
391    * Seeks based on the start
392    */

393   public void seekStart(long offset)
394     throws IOException JavaDoc
395   {
396     flushBuffer();
397
398     StreamImpl source = _source;
399     
400     if (source != null)
401       source.seekStart(offset);
402   }
403
404   /**
405    * Seeks based on the end
406    */

407   public void seekEnd(long offset)
408     throws IOException JavaDoc
409   {
410     flushBuffer();
411
412     StreamImpl source = _source;
413     
414     if (source != null)
415       source.seekEnd(offset);
416   }
417
418   /*
419    * Writer methods
420    */

421
422   /**
423    * Sets the character encoding for writing to this stream.
424    * Encoding can be a Java encoding or a mime-encoding.
425    */

426   public void setEncoding(String JavaDoc encoding)
427     throws UnsupportedEncodingException JavaDoc
428   {
429     if (_source instanceof ReaderWriterStream)
430       encoding = "UTF-8";
431     
432     String JavaDoc mimeName = Encoding.getMimeName(encoding);
433     
434     if (mimeName != null && mimeName.equals(_writeEncodingName))
435       return;
436
437     if (_source != null)
438       _source.setWriteEncoding(encoding);
439     
440     _writeEncoding = Encoding.getWriteEncoding(encoding);
441     _writeEncodingName = mimeName;
442   }
443
444   public void setLocale(Locale JavaDoc locale)
445     throws UnsupportedEncodingException JavaDoc
446   {
447     if (_writeEncoding == null && locale != null)
448       setEncoding(Encoding.getMimeName(locale));
449   }
450
451   /**
452    * Returns the mime-encoding used for writing.
453    */

454   public String JavaDoc getEncoding()
455   {
456     if (_source instanceof ReaderWriterStream)
457       return ((ReaderWriterStream) _source).getEncoding();
458     else
459       return _writeEncodingName;
460   }
461
462   public String JavaDoc getJavaEncoding()
463   {
464     return Encoding.getJavaName(getEncoding());
465   }
466
467   /**
468    * Some streams, like log streams, should be flushed on every println
469    * call. Embedded newlines, i.e. '\n' in strings, do not trigger a
470    * flush.
471    *
472    * @param flushOnNewline set to true if println flushes.
473    */

474   public void setFlushOnNewline(boolean flushOnNewline)
475   {
476     this.flushOnNewline = flushOnNewline;
477   }
478
479   /**
480    * Returns the current string used for println newlines
481    */

482   public String JavaDoc getNewlineString()
483   {
484     return newline;
485   }
486
487   /**
488    * Sets the string to use for println newlines
489    */

490   public void setNewlineString(String JavaDoc newline)
491   {
492     if (newline != null) {
493       if (this.newline == newline || newline.equals(this.newline)) {
494       }
495       else if (newline == "\n" || newline.equals("\n")) {
496         this.newlineBytes = lfBytes;
497       }
498       else if (newline == "\r\n" || newline.equals("\r\n")) {
499         this.newlineBytes = crlfBytes;
500       }
501       else if (newline == "\r" || newline.equals("\r")) {
502         this.newlineBytes = crBytes;
503       }
504       else {
505         this.newlineBytes = newline.getBytes();
506       }
507       this.newline = newline;
508     }
509   }
510
511   /**
512    * Prints the character buffer to the stream.
513    *
514    * @param buffer character buffer to write
515    * @param offset offset into the buffer to start writes
516    * @param length number of characters to write
517    */

518   public final void print(char []buffer, int offset, int length)
519     throws IOException JavaDoc
520   {
521     byte []writeBuffer = this._writeBuffer;
522
523     if (_source == null)
524       return;
525
526     if (_writeEncoding != null) {
527       _disableFlush = true;
528       _writeEncoding.write(this, buffer, offset, length);
529       _disableFlush = false;
530       return;
531     }
532
533     while (length > 0) {
534       int writeLength = _writeLength;
535       int sublen = writeBuffer.length - writeLength;
536
537       if (sublen <= 0) {
538     _source.write(writeBuffer, 0, writeLength, false);
539     writeLength = 0;
540     sublen = writeBuffer.length - writeLength;
541       }
542       if (length < sublen)
543     sublen = length;
544
545       for (int i = sublen - 1; i >= 0; i--)
546     writeBuffer[writeLength + i] = (byte) buffer[offset + i];
547
548       _writeLength = writeLength + sublen;
549       offset += sublen;
550       length -= sublen;
551     }
552
553     if (_implicitFlush)
554       flush();
555   }
556
557   /**
558    * Prints the character buffer to the stream.
559    *
560    * @param ch char
561    */

562   public final void print(char ch)
563     throws IOException JavaDoc
564   {
565     if (_writeEncoding != null) {
566       _disableFlush = true;
567       _writeEncoding.write(this, ch);
568       _disableFlush = false;
569       return;
570     }
571
572     write((byte) ch);
573   }
574
575   /**
576    * Prints the character buffer to the stream.
577    *
578    * @param buffer character buffer to write
579    */

580   public final void print(char []buffer)
581     throws IOException JavaDoc
582   {
583     print(buffer, 0, buffer.length);
584   }
585
586   /**
587    * Prints the character buffer to the stream.
588    *
589    * @param segment character buffer to write
590    */

591   public final void print(CharSegment segment)
592     throws IOException JavaDoc
593   {
594     print(segment.getBuffer(), segment.getOffset(), segment.getLength());
595   }
596
597   /**
598    * Prints a string.
599    */

600   public final void print(String JavaDoc string) throws IOException JavaDoc
601   {
602     if (string == null)
603       string = "null";
604     
605     int length = string.length();
606     int offset = 0;
607     while (length > 0) {
608       int sublen = length < 1024 ? length : 1024;
609
610       if (chars == null || chars.length < sublen)
611     chars = new char[sublen < 32 ? 32 : sublen];
612
613       string.getChars(offset, offset + sublen, chars, 0);
614
615       print(chars, 0, sublen);
616
617       length -= sublen;
618       offset += sublen;
619     }
620   }
621
622   /**
623    * Prints a substring.
624    *
625    * @param string the string to print
626    * @param offset starting offset into the string
627    * @param length length of the substring to print.
628    */

629   public final void print(String JavaDoc string, int offset, int length)
630     throws IOException JavaDoc
631   {
632     if (string == null)
633       string = "null";
634     
635     while (length > 0) {
636       int sublen = length < 1024 ? length : 1024;
637
638       if (chars == null || chars.length < sublen)
639     chars = new char[sublen < 32 ? 32 : sublen];
640
641       string.getChars(offset, offset + sublen, chars, 0);
642
643       print(chars, 0, sublen);
644
645       length -= sublen;
646       offset += sublen;
647     }
648   }
649
650   /**
651    * Prints a boolean.
652    */

653   public final void print(boolean b) throws IOException JavaDoc
654   {
655     print(b ? "true" : "false");
656   }
657
658   /**
659    * Prints an integer.
660    */

661   public final void print(int i) throws IOException JavaDoc
662   {
663     if (i == 0x80000000) {
664       print("-2147483648");
665       return;
666     }
667
668     if (i < 0) {
669       write('-');
670       i = -i;
671     } else if (i < 9) {
672       write('0' + i);
673       return;
674     }
675
676     int length = 0;
677     int exp = 10;
678
679     if (i >= 1000000000)
680       length = 9;
681     else {
682       for (; i >= exp; length++)
683         exp = 10 * exp;
684     }
685
686     byte []buffer = _writeBuffer;
687     int writeLength = this._writeLength;
688     
689     if (writeLength + length < buffer.length) {
690       writeLength += length;
691       this._writeLength = writeLength + 1;
692       
693       for (int j = 0; j <= length; j++) {
694         buffer[writeLength - j] = (byte) (i % 10 + '0');
695         i = i / 10;
696       }
697       return;
698     }
699     
700     if (_bytes == null)
701       _bytes = new byte[32];
702
703     int j = 31;
704     
705     while (i > 0) {
706       _bytes[--j] = (byte) ((i % 10) + '0');
707       i /= 10;
708     }
709
710     write(_bytes, j, 31 - j);
711   }
712
713   /**
714    * Prints a long.
715    */

716   public final void print(long i) throws IOException JavaDoc
717   {
718     if (i == 0x8000000000000000L) {
719       print("-9223372036854775808");
720       return;
721     }
722     
723     if (_bytes == null)
724       _bytes = new byte[32];
725
726     if (i < 0) {
727       write('-');
728       i = -i;
729     } else if (i == 0) {
730       write('0');
731       return;
732     }
733
734     int j = 31;
735     
736     while (i > 0) {
737       _bytes[--j] = (byte) ((i % 10) + '0');
738       i /= 10;
739     }
740
741     write(_bytes, j, 31 - j);
742   }
743
744   /**
745    * Prints a float.
746    */

747   public final void print(float f) throws IOException JavaDoc
748   {
749     print(String.valueOf(f));
750   }
751
752   /**
753    * Prints an double
754    */

755   public final void print(double d) throws IOException JavaDoc
756   {
757     print(String.valueOf(d));
758   }
759
760   /**
761    * Prints a double, converted by String.valueOf()
762    */

763   public final void print(Object JavaDoc o) throws IOException JavaDoc
764   {
765     if (o == null)
766       print("null");
767     else if (o instanceof VfsWriteObject)
768       ((VfsWriteObject) o).print(this);
769     else
770       print(o.toString());
771   }
772
773   /**
774    * Prints a newline
775    */

776   public final void println() throws IOException JavaDoc
777   {
778     write(newlineBytes, 0, newlineBytes.length);
779     if (flushOnNewline)
780       flush();
781   }
782
783   /**
784    * Prints a character buffer followed by a newline.
785    */

786   public final void println(char []buf, int offset, int length)
787     throws IOException JavaDoc
788   {
789     print(buf, offset, length);
790     write(newlineBytes, 0, newlineBytes.length);
791     if (flushOnNewline)
792       flush();
793   }
794
795   /**
796    * Prints a string buffer followed by a newline.
797    */

798   public final void println(String JavaDoc string) throws IOException JavaDoc
799   {
800     print(string);
801     write(newlineBytes, 0, newlineBytes.length);
802     if (flushOnNewline)
803       flush();
804   }
805
806   /**
807    * Prints a boolean followed by a newline.
808    */

809   public final void println(boolean b) throws IOException JavaDoc
810   {
811     println(b ? "true" : "false");
812   }
813
814   /**
815    * Prints a char followed by a newline.
816    */

817   public final void println(char ch) throws IOException JavaDoc
818   {
819     write(ch);
820     write(newlineBytes, 0, newlineBytes.length);
821     if (flushOnNewline)
822       flush();
823   }
824
825   /**
826    * Prints an integer followed by a newline.
827    */

828   public final void println(int i) throws IOException JavaDoc
829   {
830     print(i);
831     write(newlineBytes, 0, newlineBytes.length);
832     if (flushOnNewline)
833       flush();
834   }
835
836   /**
837    * Prints a long followed by a newline.
838    */

839   public final void println(long l) throws IOException JavaDoc
840   {
841     print(l);
842     write(newlineBytes, 0, newlineBytes.length);
843     if (flushOnNewline)
844       flush();
845   }
846
847   /**
848    * Prints a float followed by a newline.
849    */

850   public final void println(float f) throws IOException JavaDoc
851   {
852     println(String.valueOf(f));
853   }
854
855   /**
856    * Prints a double followed by a newline.
857    */

858   public final void println(double d) throws IOException JavaDoc
859   {
860     println(String.valueOf(d));
861   }
862
863   /**
864    * Prints an object, converted to a string, followed by a newline.
865    */

866   public final void println(Object JavaDoc o) throws IOException JavaDoc
867   {
868     if (o == null)
869       println("null");
870     else
871       println(o.toString());
872   }
873
874   /**
875    * Returns a printWriter writing to this stream.
876    */

877   public PrintWriter JavaDoc getPrintWriter()
878   {
879     /*
880     if (_writer == null)
881       _writer = new StreamWriter();
882     */

883
884     if (_printWriter == null)
885       _printWriter = new StreamPrintWriter(this);
886     /*
887     else
888       _printWriter.setWriter(_writer);
889     */

890
891     return _printWriter;
892   }
893
894   /**
895    * Logs a line to the stream. log is essentially println, but
896    * it doesn't throw an exception and it always flushes the output.
897    */

898   public final void log(String JavaDoc string)
899   {
900     try {
901       synchronized (this) {
902         println(string);
903         flush();
904       }
905     } catch (Exception JavaDoc e) {
906     }
907   }
908
909   public final void log(Throwable JavaDoc exn)
910   {
911     try {
912       PrintWriter JavaDoc out = getPrintWriter();
913       synchronized (this) {
914         if (exn != null) {
915           exn.printStackTrace(out);
916           flush();
917         }
918       }
919     } catch (Throwable JavaDoc e) {
920       e.printStackTrace();
921     }
922   }
923
924   /**
925    * Writes the contents of a JDK stream. Essentially this will copy
926    * <code>source</code> to the current stream.
927    *
928    * @param source InputStream to read.
929    */

930   public long writeStream(InputStream JavaDoc source) throws IOException JavaDoc
931   {
932     if (source == null)
933       return 0;
934
935     int len;
936     int length = _writeBuffer.length;
937     long outputLength = 0;
938
939     if (_writeLength >= length) {
940       int tmplen = _writeLength;
941       _writeLength = 0;
942       _source.write(_writeBuffer, 0, tmplen, false);
943       outputLength += tmplen;
944     }
945
946     while ((len = source.read(_writeBuffer,
947                   _writeLength,
948                   length - _writeLength)) >= 0) {
949       _writeLength += len;
950       outputLength += len;
951       
952       if (length <= _writeLength) {
953     int tmplen = _writeLength;
954     _writeLength = 0;
955     _source.write(_writeBuffer, 0, tmplen, false);
956       }
957     }
958
959     if (flushOnNewline || _implicitFlush)
960       flush();
961
962     return outputLength;
963   }
964
965   /**
966    * Writes the contents of a JDK reader. Essentially this will copy
967    * <code>source</code> to the current stream.
968    *
969    * @param source InputStream to read.
970    */

971   public void writeStream(Reader JavaDoc reader) throws IOException JavaDoc
972   {
973     if (reader == null)
974       return;
975
976     if (chars == null)
977       chars = new char[256];
978
979     int len;
980     while ((len = reader.read(chars, 0, chars.length)) > 0) {
981       print(chars, 0, len);
982     }
983   }
984
985   /**
986    * Writes the contents of a JDK stream. Essentially this will copy
987    * <code>source</code> to the current stream.
988    *
989    * @param source InputStream to read.
990    */

991   public void writeStream(InputStream JavaDoc source, int totalLength)
992     throws IOException JavaDoc
993   {
994     if (source == null)
995       return;
996
997     int len;
998     int length = _writeBuffer.length;
999
1000    if (_writeLength >= length) {
1001      int tmplen = _writeLength;
1002      _writeLength = 0;
1003      this._source.write(_writeBuffer, 0, tmplen, false);
1004    }
1005
1006    while (totalLength > 0) {
1007      int sublen = length - _writeLength;
1008      
1009      if (sublen > totalLength)
1010        sublen = totalLength;
1011      
1012      sublen = source.read(_writeBuffer, _writeLength, sublen);
1013      if (sublen < 0)
1014        break;
1015      
1016      _writeLength += sublen;
1017      totalLength -= sublen;
1018      if (_writeLength >= length) {
1019    int tmplen = _writeLength;
1020    _writeLength = 0;
1021    _source.write(_writeBuffer, 0, tmplen, false);
1022      }
1023    }
1024
1025    if (flushOnNewline || _implicitFlush)
1026      flush();
1027  }
1028
1029
1030  /**
1031   * Writes the contents of a JDK stream. Essentially this will copy
1032   * <code>source</code> to the current stream.
1033   *
1034   * @param source InputStream to read.
1035   */

1036  public void writeStream(StreamImpl source) throws IOException JavaDoc
1037  {
1038    if (source == null)
1039      return;
1040
1041    int len;
1042    int length = _writeBuffer.length;
1043
1044    if (_writeLength >= length) {
1045      int tmplen = _writeLength;
1046      _writeLength = 0;
1047      this._source.write(_writeBuffer, 0, tmplen, false);
1048    }
1049
1050    while ((len = source.read(_writeBuffer,
1051                  _writeLength,
1052                  length - _writeLength)) >= 0) {
1053      _writeLength += len;
1054      if (_writeLength >= length) {
1055    int tmplen = _writeLength;
1056    _writeLength = 0;
1057    this._source.write(_writeBuffer, 0, tmplen, false);
1058      }
1059    }
1060
1061    if (flushOnNewline || _implicitFlush)
1062      flush();
1063  }
1064
1065  /**
1066   * Copies a file to the stream.
1067   *
1068   * @param path Path of the file to copy.
1069   */

1070  public void writeFile(Path path) throws IOException JavaDoc
1071  {
1072    StreamImpl is = path.openReadImpl();
1073
1074    try {
1075      if (is != null)
1076    writeStream(is);
1077    } finally {
1078      if (is != null)
1079    is.close();
1080    }
1081  }
1082
1083  /**
1084   * Disables close. Sometimes an application will pass a stream
1085   * to a client that may close the stream at an inappropriate time.
1086   * Setting disable close gives the calling routine control over closing
1087   * the stream.
1088   */

1089  public void setDisableClose(boolean disableClose)
1090  {
1091    this._disableClose = disableClose;
1092  }
1093
1094  public boolean getDisableClose()
1095  {
1096    return _disableClose;
1097  }
1098
1099  /**
1100   * Disables close of the underlying source.
1101   */

1102  public void setDisableCloseSource(boolean disableClose)
1103  {
1104    _isDisableCloseSource = disableClose;
1105  }
1106
1107  /**
1108   * Returns true if the stream is closed.
1109   */

1110  public final boolean isClosed()
1111  {
1112    return _source != null;
1113  }
1114
1115  /**
1116   * Close the stream, first flushing the write buffer.
1117   */

1118  public final void close() throws IOException JavaDoc
1119  {
1120    StreamImpl s = _source;
1121    
1122    try {
1123      int len = _writeLength;
1124      if (len > 0) {
1125    _writeLength = 0;
1126        if (s != null)
1127          s.write(_writeBuffer, 0, len, true);
1128      }
1129    } finally {
1130      if (_disableClose) {
1131    return;
1132      }
1133
1134      _source = null;
1135
1136      if (_writeEncoding != null)
1137        _writeEncoding = null;
1138
1139      if (! reuseBuffer) {
1140        if (_tempWrite != null)
1141          TempBuffer.free(_tempWrite);
1142        _tempWrite = null;
1143        _writeBuffer = null;
1144      }
1145
1146      if (s != null && ! _isDisableCloseSource)
1147    s.closeWrite();
1148    }
1149  }
1150
1151  /**
1152   * Frees the buffer
1153   */

1154  public final void free()
1155  {
1156    _source = null;
1157    if (_tempWrite != null)
1158      TempBuffer.free(_tempWrite);
1159    _tempWrite = null;
1160    _writeBuffer = null;
1161  }
1162    
1163
1164  /**
1165   * Returns a named attribute. For example, an HTTP stream
1166   * may use this to return header values.
1167   */

1168  public Object JavaDoc getAttribute(String JavaDoc name)
1169    throws IOException JavaDoc
1170  {
1171    return _source.getAttribute(name);
1172  }
1173
1174  /**
1175   * Sets a named attribute. For example, an HTTP stream
1176   * may use this to set header values.
1177   */

1178  public void setAttribute(String JavaDoc name, Object JavaDoc value)
1179    throws IOException JavaDoc
1180  {
1181    _source.setAttribute(name, value);
1182  }
1183
1184  /**
1185   * Removes a named attribute.
1186   */

1187  public void removeAttribute(String JavaDoc name)
1188    throws IOException JavaDoc
1189  {
1190    _source.removeAttribute(name);
1191  }
1192
1193  /**
1194   * Lists all named attributes.
1195   */

1196  public Iterator JavaDoc getAttributeNames()
1197    throws IOException JavaDoc
1198  {
1199    return _source.getAttributeNames();
1200  }
1201
1202  /**
1203   * Returns the Path which opened this stream.
1204   */

1205  public Path getPath()
1206  {
1207    if (_source != null)
1208      return _source.getPath();
1209    else
1210      return null;
1211  }
1212
1213  /**
1214   * Returns the user path which opened this stream.
1215   *
1216   * <p>Parsing routines typically use this for error reporting.
1217   */

1218  public String JavaDoc getUserPath()
1219  {
1220    return _source.getPath().getUserPath();
1221  }
1222
1223  /**
1224   * Sets a path name associated with the stream.
1225   */

1226  public void setPath(Path path)
1227  {
1228    _source.setPath(path);
1229  }
1230  
1231  /**
1232   * For testing, sets the system newlines.
1233   */

1234  public static void setSystemNewline(String JavaDoc newline)
1235  {
1236    _sysNewline = newline;
1237    _sysNewlineBytes = _sysNewline.getBytes();
1238  }
1239
1240  private class StreamWriter extends Writer
1241    implements EnclosedWriteStream, FlushBuffer {
1242    public final void write(char ch)
1243      throws IOException JavaDoc
1244    {
1245      WriteStream.this.print(ch);
1246    }
1247
1248    public final void write(char []buffer, int offset, int length)
1249      throws IOException JavaDoc
1250    {
1251      WriteStream.this.print(buffer, offset, length);
1252    }
1253
1254    public final void write(char []buffer)
1255      throws IOException JavaDoc
1256    {
1257      WriteStream.this.print(buffer, 0, buffer.length);
1258    }
1259
1260    public final void write(String JavaDoc string)
1261      throws IOException JavaDoc
1262    {
1263      WriteStream.this.print(string);
1264    }
1265
1266    public final void write(String JavaDoc string, int off, int len)
1267      throws IOException JavaDoc
1268    {
1269      WriteStream.this.print(string, off, len);
1270    }
1271
1272    public final void flush()
1273      throws IOException JavaDoc
1274    {
1275      WriteStream.this.flush();
1276    }
1277
1278    public final void flushBuffer()
1279      throws IOException JavaDoc
1280    {
1281      WriteStream.this.flushBuffer();
1282    }
1283  
1284    public final void close()
1285      throws IOException JavaDoc
1286    {
1287      // XXX: if flush, then servlets are sloooow
1288
// WriteStream.this.flush();
1289
}
1290
1291    public WriteStream getWriteStream()
1292    {
1293      return WriteStream.this;
1294    }
1295  }
1296}
1297
Popular Tags