001: // ContentLengthInputStream.java
002: // $Id: ContentLengthInputStream.java,v 1.14 2004/12/16 17:58:20 ylafon Exp $
003: // (c) COPYRIGHT MIT and INRIA, 1996.
004: // Please first read the full copyright statement in file COPYRIGHT.html
005:
006: package org.w3c.www.http;
007:
008: import java.io.IOException;
009: import java.io.InputStream;
010:
011: /**
012: * The content length input stream is used internally to return entity bodies.
013: */
014:
015: public class ContentLengthInputStream extends InputStream {
016: /**
017: * The original input stream.
018: */
019: protected InputStream in = null;
020: /**
021: * The stream observer, if any.
022: */
023: protected HttpStreamObserver observer = null;
024:
025: /**
026: * The number of bytes readable from the above stream.
027: */
028: protected int length = 0;
029: /**
030: * The place of a single pending mark.
031: */
032: protected int marklength = 0;
033:
034: public void mark(int readlimit) {
035: in.mark(readlimit);
036: marklength = length;
037: }
038:
039: public void reset() throws IOException {
040: in.reset();
041: length = marklength;
042: }
043:
044: public synchronized void close() throws IOException {
045: if (observer != null) {
046: observer.notifyClose(this );
047: observer = null;
048: }
049: }
050:
051: public int read() throws IOException {
052: if (length > 0) {
053: length--;
054: // notify if the is nothing more to read
055: // FIXME is it the right place for this?
056: if (length <= 0) {
057: if (observer != null)
058: observer.notifyEOF(this );
059: observer = null;
060: }
061: int r = in.read();
062: if (r == -1) {
063: // mark end of stream in error
064: length = -1;
065: if (observer != null) {
066: observer.notifyFailure(this );
067: }
068: observer = null;
069: throw new IOException("Size not matching: " + length
070: + " left");
071: }
072: return r;
073: }
074: if (observer != null) {
075: observer.notifyEOF(this );
076: observer = null;
077: }
078: return -1;
079: }
080:
081: public int read(byte b[], int off, int len) throws IOException {
082: if (length <= 0) {
083: if (observer != null)
084: observer.notifyEOF(this );
085: observer = null;
086: return -1;
087: }
088: if (len > length)
089: len = length;
090: len = in.read(b, off, len);
091: if (len == -1) { // error code, dont let length grow
092: length = -1; // a bad thing happened anyway.
093: if (observer != null)
094: observer.notifyFailure(this );
095: observer = null;
096: throw new IOException("Size not matching");
097: }
098: length -= len;
099: if (length <= 0) { // nothing to read, notify the observer (if any)
100: if (observer != null)
101: observer.notifyEOF(this );
102: observer = null;
103: }
104: return len;
105: }
106:
107: public long skip(long n) throws IOException {
108: int howmany = (int) n;
109: if (howmany > length)
110: howmany = length;
111: howmany = (int) in.skip(howmany);
112: length -= howmany;
113: return (long) howmany;
114: }
115:
116: public int available() throws IOException {
117: int _av = in.available();
118: if (_av > length) {
119: return length;
120: }
121: return _av;
122: //return length ;
123: }
124:
125: /**
126: * Make sure the stream is ultimately closed !
127: */
128:
129: public void finalize() {
130: try {
131: close();
132: } catch (IOException ex) {
133: }
134: }
135:
136: /**
137: * do we support mark() ?
138: * it depends on the underlying InputStream
139: * @return a boolean, true if mark is supported
140: */
141: public boolean markSupported() {
142: if (in == null)
143: return false;
144: else
145: return in.markSupported();
146: }
147:
148: /**
149: * Builds a new content-length input stream.
150: * This stream acts as a normal stream except that it will return
151: * an end of file, after <em>count</em> bytes have been delivered.
152: */
153:
154: public ContentLengthInputStream(InputStream in, int length) {
155: this (null, in, length);
156: }
157:
158: public ContentLengthInputStream(HttpStreamObserver observer,
159: InputStream in, int length) {
160: this.observer = observer;
161: this.in = in;
162: this.length = length;
163: }
164:
165: }
|