KickJava   Java API By Example, From Geeks To Geeks.

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


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  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.vfs;
30
31 import com.caucho.util.Alarm;
32 import com.caucho.util.CharBuffer;
33
34 import java.io.IOException JavaDoc;
35 import java.io.InputStream JavaDoc;
36 import java.io.OutputStream JavaDoc;
37 import java.io.Reader JavaDoc;
38 import java.io.UnsupportedEncodingException JavaDoc;
39 import java.io.Writer JavaDoc;
40 import java.util.Iterator JavaDoc;
41 import java.util.logging.Level JavaDoc;
42 import java.util.logging.Logger JavaDoc;
43
44 /**
45  * A fast bufferered input 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>Dynamic streams, like tcp and http
51  * will properly flush writes before reading input. And random access
52  * streams, like RandomAccessFile, can use the same API as normal streams.
53  *
54  * <p>Most applications will use the Path routines to create their own streams.
55  * Specialized applications, like servers, need the capability of recycling
56  * streams.
57  */

58 public final class ReadStream extends InputStream JavaDoc {
59   public static int ZERO_COPY_SIZE = 1024;
60   
61   private TempBuffer _tempRead;
62   private byte []_readBuffer;
63   private int _readOffset;
64   private int _readLength;
65
66   private WriteStream _sibling;
67
68   private StreamImpl _source;
69   private long _position;
70
71   private long _readTime;
72
73   private Reader JavaDoc _readEncoding;
74   private String JavaDoc _readEncodingName;
75   private int _specialEncoding;
76
77   private boolean _disableClose;
78   private boolean _isDisableCloseSource;
79   private boolean _reuseBuffer;
80   private Reader JavaDoc _reader;
81
82   /**
83    * Creates an uninitialized stream. Use <code>init</code> to initialize.
84    */

85   public ReadStream()
86   {
87   }
88
89   /**
90    * Creates a stream and initializes with a specified source.
91    *
92    * @param source Underlying source for the stream.
93    */

94   public ReadStream(StreamImpl source)
95   {
96     init(source, null);
97   }
98
99   /**
100    * Creates a stream and initializes with a specified source.
101    *
102    * @param source Underlying source for the stream.
103    * @param sibling Sibling write stream.
104    */

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

116   public void init(StreamImpl source, WriteStream sibling)
117   {
118     _disableClose = false;
119     _isDisableCloseSource = false;
120     _readTime = 0;
121
122     if (_source != null && _source != source) {
123       close();
124     }
125     
126     if (source == null)
127       throw new IllegalArgumentException JavaDoc();
128
129     _source = source;
130     _sibling = sibling;
131
132     if (source.canRead()) {
133       if (_tempRead == null) {
134         _tempRead = TempBuffer.allocate();
135         _readBuffer = _tempRead._buf;
136       }
137     }
138     _readOffset = 0;
139     _readLength = 0;
140
141     _readEncoding = null;
142     _readEncodingName = "ISO-8859-1";
143   }
144
145   public void setSibling(WriteStream sibling)
146   {
147     _sibling = sibling;
148   }
149
150   public WriteStream getSibling()
151   {
152     return _sibling;
153   }
154
155   /**
156    * Returns the underlying source for the stream.
157    *
158    * @return the source
159    */

160   public StreamImpl getSource()
161   {
162     return _source;
163   }
164
165   public void setReuseBuffer(boolean reuse)
166   {
167     _reuseBuffer = reuse;
168   }
169
170   /**
171    * Pushes a filter on the top of the stream stack.
172    *
173    * @param filter the filter to be added.
174    */

175   public void pushFilter(StreamFilter filter)
176   {
177     filter.init(_source);
178     _source = filter;
179   }
180
181   public byte []getBuffer()
182   {
183     return _readBuffer;
184   }
185
186   public int getOffset()
187   {
188     return _readOffset;
189   }
190
191   public int getLength()
192   {
193     return _readLength;
194   }
195
196   public void setOffset(int offset)
197   {
198     _readOffset = offset;
199   }
200
201   /**
202    * Returns the read position.
203    */

204   public long getPosition()
205   {
206     return _position - (_readLength - _readOffset);
207   }
208
209   /**
210    * Returns the last read-time.
211    */

212   public long getReadTime()
213   {
214     return _readTime;
215   }
216   
217   /**
218    * Returns the sets current read position.
219    */

220   public boolean setPosition(long pos)
221     throws IOException JavaDoc
222   {
223     // Allow seeks to be reflected in the char Reader.
224
if (_readEncoding != null)
225       _readEncoding = Encoding.getReadEncoding(this, _readEncodingName);
226
227     if (pos < _position) {
228       _position = pos;
229       _readLength = _readOffset = 0;
230
231       if (_source != null) {
232     _source.seekStart(pos);
233
234     return true;
235       }
236       else
237     return false;
238     }
239     else if (pos < _position + _readLength) {
240       _readOffset = (int) (pos - _position);
241
242       return true;
243     }
244     else {
245       long n = pos - _position - _readOffset;
246       
247       return skip(n) == n;
248     }
249   }
250
251   /**
252    * Returns true if the stream allows reading.
253    */

254   public boolean canRead()
255   {
256     return _source.canRead();
257   }
258
259   /**
260    * Clears the read buffer.
261    */

262   public void clearRead()
263   {
264     _readOffset = 0;
265     _readLength = 0;
266   }
267
268   /**
269    * Returns an estimate of the available bytes. If a read would not block,
270    * it will always return greater than 0.
271    */

272   public int getAvailable() throws IOException JavaDoc
273   {
274     if (_readOffset < _readLength) {
275       return _readLength - _readOffset;
276     }
277
278     if (_sibling != null)
279       _sibling.flush();
280     
281     return _source.getAvailable();
282   }
283
284   /**
285    * Returns true if data in the buffer is available.
286    */

287   public int getBufferAvailable() throws IOException JavaDoc
288   {
289     return _readLength - _readOffset;
290   }
291
292   /**
293    * Compatibility with InputStream.
294    */

295   public int available() throws IOException JavaDoc
296   {
297     return getAvailable();
298   }
299
300   /**
301    * Returns the next byte or -1 if at the end of file.
302    */

303   public final int read() throws IOException JavaDoc
304   {
305     if (_readLength <= _readOffset) {
306       if (! readBuffer())
307     return -1;
308     }
309
310     return _readBuffer[_readOffset++] & 0xff;
311   }
312
313   /**
314    * Unreads the last byte.
315    */

316   public final void unread()
317   {
318     if (_readOffset <= 0)
319       throw new RuntimeException JavaDoc();
320
321     _readOffset--;
322   }
323
324   /**
325    * Waits for data to be available.
326    */

327   public final boolean waitForRead() throws IOException JavaDoc
328   {
329     if (_readLength <= _readOffset) {
330       if (! readBuffer())
331     return false;
332     }
333
334     return true;
335   }
336
337   /**
338    * Skips the next <code>n</code> bytes.
339    *
340    * @param n bytes to skip.
341    *
342    * @return number of bytes skipped.
343    */

344   public long skip(long n)
345     throws IOException JavaDoc
346   {
347     long count = _readLength - _readOffset;
348     
349     if (n < count) {
350       _readOffset += n;
351       return n;
352     }
353
354     _readLength = 0;
355     _readOffset = 0;
356
357     if (_source.hasSkip()) {
358       long skipped = _source.skip(n - count);
359       
360       if (skipped < 0)
361         return count;
362       else
363         return skipped + count;
364     }
365     
366     while (_readLength < _readOffset + n - count) {
367       count += _readLength - _readOffset;
368       _readOffset = 0;
369       _readLength = 0;
370
371       if (! readBuffer())
372     return count;
373     }
374     
375     _readOffset += (int) (n - count);
376
377     return n;
378   }
379
380   /**
381    * Reads into a byte array. <code>read</code> may return less than
382    * the maximum bytes even if more bytes are available to read.
383    *
384    * @param buf byte array
385    * @param offset offset into the byte array to start reading
386    * @param length maximum byte allowed to read.
387    *
388    * @return number of bytes read or -1 on end of file.
389    */

390   public final int read(byte []buf, int offset, int length)
391     throws IOException JavaDoc
392   {
393     int readOffset = _readOffset;
394     int readLength = _readLength;
395
396     if (readLength <= readOffset) {
397       if (ZERO_COPY_SIZE <= length) {
398         if (_sibling != null)
399           _sibling.flush();
400
401         int len = _source.read(buf, offset, length);
402
403     if (len > 0) {
404       _position += len;
405       _readTime = Alarm.getCurrentTime();
406     }
407
408     return len;
409       }
410         
411       if (! readBuffer())
412     return -1;
413
414       readOffset = _readOffset;
415       readLength = _readLength;
416     }
417
418     int sublen = readLength - readOffset;
419     if (length < sublen)
420       sublen = length;
421
422     System.arraycopy(_readBuffer, readOffset, buf, offset, sublen);
423
424     _readOffset = readOffset + sublen;
425     
426     return sublen;
427   }
428
429   /**
430    * Reads into a byte array. <code>readAll</code> will always read
431    * <code>length</code> bytes, blocking if necessary, until the end of
432    * file is reached.
433    *
434    * @param buf byte array
435    * @param offset offset into the byte array to start reading
436    * @param length maximum byte allowed to read.
437    *
438    * @return number of bytes read or -1 on end of file.
439    */

440   public int readAll(byte []buf, int offset, int length) throws IOException JavaDoc
441   {
442     int readLength = 0;
443
444     while (length > 0) {
445       int sublen = read(buf, offset, length);
446
447       if (sublen < 0)
448     return readLength == 0 ? -1 : readLength;
449
450       offset += sublen;
451       readLength += sublen;
452       length -= sublen;
453     }
454
455     return readLength == 0 ? -1 : readLength;
456   }
457
458   /*
459    * Reader methods
460    */

461
462   /**
463    * Sets the current read encoding. The encoding can either be a
464    * Java encoding name or a mime encoding.
465    *
466    * @param encoding name of the read encoding
467    */

468   public void setEncoding(String JavaDoc encoding)
469     throws UnsupportedEncodingException JavaDoc
470   {
471     String JavaDoc mimeName = Encoding.getMimeName(encoding);
472     
473     if (mimeName != null && mimeName.equals(_readEncodingName))
474       return;
475     
476     _readEncoding = Encoding.getReadEncoding(this, encoding);
477     _readEncodingName = mimeName;
478   }
479
480   /**
481    * Returns the mime-encoding currently read.
482    */

483   public String JavaDoc getEncoding()
484   {
485     return _readEncodingName;
486   }
487
488   /**
489    * Reads a character from the stream, returning -1 on end of file.
490    */

491   public final int readChar() throws IOException JavaDoc
492   {
493     if (_readEncoding != null) {
494       int ch = _readEncoding.read();
495       return ch;
496     }
497
498     if (_readLength <= _readOffset) {
499       if (! readBuffer())
500     return -1;
501     }
502
503     return _readBuffer[_readOffset++] & 0xff;
504   }
505
506   /**
507    * Reads into a character buffer from the stream. Like the byte
508    * array version, read may return less characters even though more
509    * characters are available.
510    *
511    * @param buf character buffer to fill
512    * @param offset starting offset into the character buffer
513    * @param length maximum number of characters to read
514    * @return number of characters read or -1 on end of file.
515    */

516   public final int read(char []buf, int offset, int length) throws IOException JavaDoc
517   {
518     if (_readEncoding != null)
519       return _readEncoding.read(buf, offset, length);
520     
521     byte []readBuffer = _readBuffer;
522     if (readBuffer == null)
523       return -1;
524
525     int readOffset = _readOffset;
526     int readLength = _readLength;
527
528     int sublen = readLength - readOffset;
529
530     if (sublen <= 0) {
531       if (! readBuffer()) {
532     return -1;
533       }
534       readLength = _readLength;
535       readOffset = _readOffset;
536       sublen = readLength - readOffset;
537     }
538
539     if (length < sublen)
540       sublen = length;
541
542     for (int i = 0; i < sublen; i++)
543       buf[offset + i] = (char) (readBuffer[readOffset + i] & 0xff);
544
545     _readOffset = readOffset + sublen;
546
547     return sublen;
548   }
549
550   /**
551    * Reads into a character buffer from the stream. <code>length</code>
552    * characters will always be read until the end of file is reached.
553    *
554    * @param buf character buffer to fill
555    * @param offset starting offset into the character buffer
556    * @param length maximum number of characters to read
557    * @return number of characters read or -1 on end of file.
558    */

559   public int readAll(char []buf, int offset, int length) throws IOException JavaDoc
560   {
561     int readLength = 0;
562
563     while (length > 0) {
564       int sublen = read(buf, offset, length);
565
566       if (sublen <= 0)
567     return readLength > 0 ? readLength : -1;
568
569       offset += sublen;
570       readLength += sublen;
571       length -= sublen;
572     }
573
574     return readLength;
575   }
576
577   /**
578    * Reads characters from the stream, appending to the character buffer.
579    *
580    * @param buf character buffer to fill
581    * @param length maximum number of characters to read
582    * @return number of characters read or -1 on end of file.
583    */

584   public int read(CharBuffer buf, int length) throws IOException JavaDoc
585   {
586     int len = buf.getLength();
587
588     buf.setLength(len + length);
589     int readLength = read(buf.getBuffer(), len, length);
590     if (readLength < 0)
591       buf.setLength(len);
592     else if (readLength < length)
593       buf.setLength(len + readLength);
594
595     return length;
596   }
597
598   /**
599    * Reads characters from the stream, appending to the character buffer.
600    * <code>length</code> characters will always be read until the end of
601    * file.
602    *
603    * @param buf character buffer to fill
604    * @param length maximum number of characters to read
605    * @return number of characters read or -1 on end of file.
606    */

607   public int readAll(CharBuffer buf, int length) throws IOException JavaDoc
608   {
609     int len = buf.getLength();
610
611     buf.setLength(len + length);
612     int readLength = readAll(buf.getBuffer(), len, length);
613     if (readLength < 0)
614       buf.setLength(len);
615     else if (readLength < length)
616       buf.setLength(len + readLength);
617
618     return length;
619   }
620
621   /**
622    * Reads a line from the stream, returning a string.
623    */

624   public final String JavaDoc readln() throws IOException JavaDoc
625   {
626     return readLine();
627   }
628
629   /**
630    * Reads a line, returning a string.
631    */

632   public String JavaDoc readLine() throws IOException JavaDoc
633   {
634     CharBuffer cb = new CharBuffer();
635
636     if (readLine(cb, true))
637       return cb.toString();
638     else if (cb.length() == 0)
639       return null;
640     else
641       return cb.toString();
642   }
643
644   /**
645    * Reads a line, returning a string.
646    */

647   public String JavaDoc readLineNoChop() throws IOException JavaDoc
648   {
649     CharBuffer cb = new CharBuffer();
650
651     if (readLine(cb, false))
652       return cb.toString();
653     else if (cb.length() == 0)
654       return null;
655     else
656       return cb.toString();
657   }
658
659   /**
660    * Fills the buffer with the next line from the input stream.
661    *
662    * @return true on success, false on end of file.
663    */

664   public final boolean readln(CharBuffer cb) throws IOException JavaDoc
665   {
666     return readLine(cb, true);
667   }
668   
669   /**
670    * Reads a line into the character buffer. \r\n is converted to \n.
671    *
672    * @param buf character buffer to fill
673    * @return false on end of file
674    */

675   public final boolean readLine(CharBuffer cb)
676     throws IOException JavaDoc
677   {
678     return readLine(cb, true);
679   }
680   
681   /**
682    * Reads a line into the character buffer. \r\n is converted to \n.
683    *
684    * @param buf character buffer to fill
685    * @return false on end of file
686    */

687   public final boolean readLine(CharBuffer cb, boolean isChop)
688     throws IOException JavaDoc
689   {
690     if (_readEncoding != null)
691       return readlnEncoded(cb, isChop);
692
693     int capacity = cb.getCapacity();
694     int offset = cb.getLength();
695     char []buf = cb.getBuffer();
696
697     byte []readBuffer = _readBuffer;
698
699     while (true) {
700       int readOffset = _readOffset;
701       
702       int sublen = _readLength - readOffset;
703       if (capacity - offset < sublen)
704         sublen = capacity - offset;
705
706       for (; sublen > 0; sublen--) {
707         int ch = readBuffer[readOffset++] & 0xff;
708
709     if (ch != '\n') {
710       buf[offset++] = (char) ch;
711     }
712         else if (isChop) {
713           if (offset > 0 && buf[offset - 1] == '\r')
714             cb.setLength(offset - 1);
715           else
716             cb.setLength(offset);
717           
718           _readOffset = readOffset;
719
720           return true;
721         }
722     else {
723       buf[offset++] = (char) '\n';
724
725       cb.setLength(offset);
726
727       _readOffset = readOffset;
728
729       return true;
730     }
731       }
732
733       _readOffset = readOffset;
734
735       if (_readLength <= readOffset) {
736     if (! readBuffer()) {
737       cb.setLength(offset);
738       return offset > 0;
739     }
740       }
741
742       if (capacity <= offset) {
743     cb.setLength(offset + 1);
744     capacity = cb.getCapacity();
745     buf = cb.getBuffer();
746       }
747     }
748   }
749   
750   /**
751    * Reads a line into the character buffer. \r\n is converted to \n.
752    *
753    * @param buf character buffer to fill.
754    * @param length number of characters to fill.
755    *
756    * @return -1 on end of file or the number of characters read.
757    */

758   public final int readLine(char []buf, int length)
759     throws IOException JavaDoc
760   {
761     return readLine(buf, length, true);
762   }
763   
764   /**
765    * Reads a line into the character buffer. \r\n is converted to \n.
766    *
767    * @param buf character buffer to fill.
768    * @param length number of characters to fill.
769    *
770    * @return -1 on end of file or the number of characters read.
771    */

772   public final int readLine(char []buf, int length, boolean isChop)
773     throws IOException JavaDoc
774   {
775     byte []readBuffer = _readBuffer;
776
777     int offset = 0;
778     
779     while (true) {
780       int readOffset = _readOffset;
781
782       int sublen = _readLength - readOffset;
783       if (sublen < length)
784         sublen = length;
785
786       for (; sublen > 0; sublen--) {
787         int ch = readBuffer[readOffset++] & 0xff;
788
789     if (ch != '\n') {
790     }
791         else if (isChop) {
792           _readOffset = readOffset;
793           
794           if (offset > 0 && buf[offset - 1] == '\r')
795             return offset - 1;
796           else
797             return offset;
798         }
799         else {
800       buf[offset++] = (char) ch;
801       
802           _readOffset = readOffset;
803       
804       return offset + 1;
805         }
806
807         buf[offset++] = (char) ch;
808       }
809       _readOffset = readOffset;
810
811       if (readOffset <= _readLength) {
812     if (! readBuffer()) {
813       return offset;
814     }
815       }
816
817       if (length <= offset)
818         return length + 1;
819     }
820   }
821   
822   private boolean readlnEncoded(CharBuffer cb, boolean isChop)
823     throws IOException JavaDoc
824   {
825     while (true) {
826       int ch = readChar();
827
828       if (ch < 0)
829     return cb.length() > 0;
830
831       if (ch != '\n') {
832       }
833       else if (isChop) {
834     if (cb.length() > 0 && cb.getLastChar() == '\r')
835       cb.setLength(cb.getLength() - 1);
836
837     return true;
838       }
839       else {
840     cb.append('\n');
841
842     return true;
843       }
844
845       cb.append((char) ch);
846     }
847   }
848
849   /**
850    * Copies this stream to the output stream.
851    *
852    * @param os destination stream.
853    */

854   public void writeToStream(OutputStream JavaDoc os) throws IOException JavaDoc
855   {
856     if (_readLength <= _readOffset) {
857       readBuffer();
858     }
859
860     while (_readOffset < _readLength) {
861       os.write(_readBuffer, _readOffset, _readLength - _readOffset);
862
863       readBuffer();
864     }
865   }
866
867   /**
868    * Writes <code>len<code> bytes to the output stream from this stream.
869    *
870    * @param os destination stream.
871    * @param len bytes to write.
872    */

873   public void writeToStream(OutputStream JavaDoc os, int len) throws IOException JavaDoc
874   {
875     while (len > 0) {
876       if (_readLength <= _readOffset) {
877     if (! readBuffer())
878       return;
879       }
880
881       int sublen = _readLength - _readOffset;
882       if (len < sublen)
883     sublen = len;
884
885       os.write(_readBuffer, _readOffset, sublen);
886       _readOffset += sublen;
887       len -= sublen;
888     }
889   }
890
891   /**
892    * Copies this stream to the output stream.
893    *
894    * @param out destination writer
895    */

896   public void writeToWriter(Writer JavaDoc out) throws IOException JavaDoc
897   {
898     int ch;
899     while ((ch = readChar()) >= 0)
900       out.write((char) ch);
901   }
902
903   /**
904    * Fills the buffer from the underlying stream.
905    */

906   public int fillBuffer()
907     throws IOException JavaDoc
908   {
909     if (! readBuffer())
910       return -1;
911     else
912       return _readLength;
913   }
914
915   /**
916    * Fills the buffer with a non-blocking read.
917    */

918   public boolean readNonBlock()
919     throws IOException JavaDoc
920   {
921     if (_readOffset < _readLength)
922       return true;
923     
924     if (_readBuffer == null) {
925       _readOffset = 0;
926       _readLength = 0;
927       return false;
928     }
929
930     if (_sibling != null)
931       _sibling.flush();
932
933     _readOffset = 0;
934     _readLength = _source.readNonBlock(_readBuffer, 0, _readBuffer.length);
935     
936     // Setting to 0 is needed to avoid int to long conversion errors with AIX
937
if (_readLength > 0) {
938       _position += _readLength;
939       _readTime = Alarm.getCurrentTime();
940       
941       return true;
942     }
943     else {
944       _readLength = 0;
945       return false;
946     }
947   }
948
949   /**
950    * Fills the buffer with a non-blocking read.
951    */

952   public boolean fillWithTimeout(long timeout)
953     throws IOException JavaDoc
954   {
955     if (_readOffset < _readLength)
956       return true;
957     
958     if (_readBuffer == null) {
959       _readOffset = 0;
960       _readLength = 0;
961       return false;
962     }
963
964     if (_sibling != null)
965       _sibling.flush();
966
967     _readOffset = 0;
968     _readLength = _source.readTimeout(_readBuffer, 0, _readBuffer.length,
969                       timeout);
970     
971     // Setting to 0 is needed to avoid int to long conversion errors with AIX
972
if (_readLength > 0) {
973       _position += _readLength;
974       _readTime = Alarm.getCurrentTime();
975       return true;
976     }
977     else {
978       _readLength = 0;
979       return false;
980     }
981   }
982
983   /**
984    * Fills the read buffer, flushing the write buffer.
985    *
986    * @return false on end of file and true if there's more data.
987    */

988   private boolean readBuffer()
989     throws IOException JavaDoc
990   {
991     if (_readBuffer == null) {
992       _readOffset = 0;
993       _readLength = 0;
994       return false;
995     }
996
997     if (_sibling != null)
998       _sibling.flush();
999
1000    _readOffset = 0;
1001    _readLength = _source.read(_readBuffer, 0, _readBuffer.length);
1002    
1003    // Setting to 0 is needed to avoid int to long conversion errors with AIX
1004
if (_readLength > 0) {
1005      _position += _readLength;
1006      _readTime = Alarm.getCurrentTime();
1007      return true;
1008    }
1009    else {
1010      _readLength = 0;
1011      return false;
1012    }
1013  }
1014
1015  private boolean readBuffer(int off)
1016    throws IOException JavaDoc
1017  {
1018    if (_readBuffer == null)
1019      return false;
1020
1021    if (_sibling != null)
1022      _sibling.flush();
1023
1024    _readOffset = 0;
1025    _readLength = _source.read(_readBuffer, off, _readBuffer.length - off);
1026
1027    // Setting to 0 is needed to avoid int to long conversion errors with AIX
1028
if (_readLength > 0) {
1029      _position += _readLength;
1030      _readTime = Alarm.getCurrentTime();
1031      return true;
1032    }
1033    else {
1034      _readLength = 0;
1035      return false;
1036    }
1037  }
1038
1039  /**
1040   * Disables close. Sometimes an application will pass a stream
1041   * to a client that may close the stream at an inappropriate time.
1042   * Setting disable close gives the calling routine control over closing
1043   * the stream.
1044   */

1045  public void setDisableClose(boolean disableClose)
1046  {
1047    _disableClose = disableClose;
1048  }
1049
1050  /**
1051   * Disables closing of the underlying source.
1052   */

1053  public void setDisableCloseSource(boolean disableClose)
1054  {
1055    _isDisableCloseSource = disableClose;
1056  }
1057
1058  /**
1059   * Close the stream.
1060   */

1061  public final void close()
1062  {
1063    try {
1064      if (_disableClose)
1065    return;
1066
1067      if (! _reuseBuffer) {
1068    if (_tempRead != null) {
1069      TempBuffer.free(_tempRead);
1070    }
1071    _tempRead = null;
1072    _readBuffer = null;
1073      }
1074
1075      if (_readEncoding != null) {
1076    Reader JavaDoc reader = _readEncoding;
1077    _readEncoding = null;
1078    reader.close();
1079      }
1080    
1081      if (_source != null && ! _isDisableCloseSource) {
1082    StreamImpl s = _source;
1083    _source = null;
1084    s.close();
1085      }
1086    } catch (IOException JavaDoc e) {
1087      log().log(Level.FINE, e.toString(), e);
1088    }
1089  }
1090
1091  /**
1092   * Returns a named attribute. For example, an HTTP stream
1093   * may use this to return header values.
1094   */

1095  public Object JavaDoc getAttribute(String JavaDoc name)
1096    throws IOException JavaDoc
1097  {
1098    if (_sibling != null)
1099      _sibling.flush();
1100    
1101    return _source.getAttribute(name);
1102  }
1103
1104  /**
1105   * Lists all named attributes.
1106   */

1107  public Iterator JavaDoc getAttributeNames()
1108    throws IOException JavaDoc
1109  {
1110    if (_sibling != null)
1111      _sibling.flush();
1112    
1113    return _source.getAttributeNames();
1114  }
1115
1116  /**
1117   * Sets a named attribute. For example, an HTTP stream
1118   * may use this to set header values.
1119   */

1120  public void setAttribute(String JavaDoc name, Object JavaDoc value)
1121    throws IOException JavaDoc
1122  {
1123    _source.setAttribute(name, value);
1124  }
1125
1126  /**
1127   * Removes a named attribute.
1128   */

1129  public void removeAttribute(String JavaDoc name)
1130    throws IOException JavaDoc
1131  {
1132    _source.removeAttribute(name);
1133  }
1134
1135  /**
1136   * Returns the Path which opened this stream.
1137   */

1138  public Path getPath()
1139  {
1140    return _source == null ? null : _source.getPath();
1141  }
1142
1143  /**
1144   * Returns the user path which opened this stream.
1145   *
1146   * <p>Parsing routines typically use this for error reporting.
1147   */

1148  public String JavaDoc getUserPath()
1149  {
1150    if (_source == null || _source.getPath() == null)
1151      return "stream";
1152    else
1153      return _source.getPath().getUserPath();
1154  }
1155
1156  /**
1157   * Returns the user path which opened this stream.
1158   *
1159   * <p>Parsing routines typically use this for error reporting.
1160   */

1161  public String JavaDoc getURL()
1162  {
1163    if (_source == null || _source.getPath() == null)
1164      return "stream:";
1165    else
1166      return _source.getPath().getURL();
1167  }
1168
1169  /**
1170   * Sets a path name associated with the stream.
1171   */

1172  public void setPath(Path path)
1173  {
1174    _source.setPath(path);
1175  }
1176
1177  /**
1178   * Returns a Reader reading to this stream.
1179   */

1180  public Reader JavaDoc getReader()
1181  {
1182    if (_reader == null)
1183      _reader = new StreamReader();
1184
1185    return _reader;
1186  }
1187
1188  private static Logger JavaDoc log()
1189  {
1190    return Logger.getLogger(ReadStream.class.getName());
1191  }
1192
1193  /**
1194   * Returns a printable representation of the read stream.
1195   */

1196  public String JavaDoc toString()
1197  {
1198    return "ReadStream[" + _source + "]";
1199  }
1200
1201  public class StreamReader extends Reader JavaDoc {
1202    public final int read()
1203      throws IOException JavaDoc
1204    {
1205      return ReadStream.this.readChar();
1206    }
1207
1208    public final int read(char []cbuf, int off, int len)
1209      throws IOException JavaDoc
1210    {
1211      return ReadStream.this.read(cbuf, off, len);
1212    }
1213
1214    public boolean ready()
1215      throws IOException JavaDoc
1216    {
1217      return ReadStream.this.available() > 0;
1218    }
1219  
1220    public final void close()
1221      throws IOException JavaDoc
1222    {
1223    }
1224
1225    public ReadStream getStream()
1226    {
1227      return ReadStream.this;
1228    }
1229  }
1230}
1231
Popular Tags