--- /dev/null
+// ContentLengthInputStream.java\r
+// $Id: ContentLengthInputStream.java,v 1.1 2010/06/15 12:19:55 smhuang Exp $\r
+// (c) COPYRIGHT MIT and INRIA, 1996.\r
+// Please first read the full copyright statement in file COPYRIGHT.html\r
+\r
+package org.w3c.www.http;\r
+\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+\r
+/**\r
+ * The content length input stream is used internally to return entity bodies.\r
+ */\r
+\r
+public class ContentLengthInputStream extends InputStream {\r
+ /**\r
+ * The original input stream.\r
+ */\r
+ protected InputStream in = null;\r
+ /**\r
+ * The stream observer, if any.\r
+ */\r
+ protected HttpStreamObserver observer = null;\r
+\r
+ /**\r
+ * The number of bytes readable from the above stream.\r
+ */\r
+ protected int length = 0 ;\r
+ /**\r
+ * The place of a single pending mark.\r
+ */\r
+ protected int marklength = 0;\r
+\r
+ public void mark(int readlimit) {\r
+ in.mark(readlimit);\r
+ marklength = length;\r
+ }\r
+\r
+ public void reset() \r
+ throws IOException\r
+ {\r
+ in.reset();\r
+ length = marklength;\r
+ }\r
+\r
+ public synchronized void close() \r
+ throws IOException \r
+ {\r
+ if ( observer != null ) {\r
+ observer.notifyClose(this);\r
+ observer = null;\r
+ } \r
+ }\r
+\r
+ public int read()\r
+ throws IOException \r
+ {\r
+ if ( length > 0 ) {\r
+ length--;\r
+ // notify if the is nothing more to read\r
+ // FIXME is it the right place for this?\r
+ if ( length <= 0 ) {\r
+ if ( observer != null )\r
+ observer.notifyEOF(this);\r
+ observer = null;\r
+ }\r
+ int r = in.read();\r
+ if (r == -1) {\r
+ // mark end of stream in error\r
+ length = -1;\r
+ if ( observer != null ) {\r
+ observer.notifyFailure(this);\r
+ }\r
+ observer = null;\r
+ throw new IOException("Size not matching: "+length+" left");\r
+ }\r
+ return r;\r
+ }\r
+ if ( observer != null ) {\r
+ observer.notifyEOF(this);\r
+ observer = null;\r
+ }\r
+ return -1 ;\r
+ }\r
+\r
+ public int read (byte b[], int off, int len)\r
+ throws IOException \r
+ {\r
+ if ( length <= 0 ) {\r
+ if ( observer != null )\r
+ observer.notifyEOF(this);\r
+ observer = null;\r
+ return -1 ;\r
+ }\r
+ if ( len > length ) \r
+ len = length ;\r
+ len = in.read (b, off, len) ;\r
+ if ( len == -1 ) { // error code, dont let length grow\r
+ length = -1; // a bad thing happened anyway.\r
+ if ( observer != null )\r
+ observer.notifyFailure(this);\r
+ observer = null;\r
+ throw new IOException("Size not matching");\r
+ }\r
+ length -= len ;\r
+ if ( length <= 0 ) { // nothing to read, notify the observer (if any)\r
+ if ( observer != null )\r
+ observer.notifyEOF(this);\r
+ observer = null;\r
+ }\r
+ return len ;\r
+ }\r
+\r
+ public long skip (long n) \r
+ throws IOException \r
+ {\r
+ int howmany = (int) n ;\r
+ if (howmany > length)\r
+ howmany = length ;\r
+ howmany = (int) in.skip (howmany) ;\r
+ length -= howmany ;\r
+ return (long) howmany ;\r
+ }\r
+\r
+ public int available ()\r
+ throws IOException\r
+ {\r
+ int _av = in.available();\r
+ if (_av > length) {\r
+ return length;\r
+ }\r
+ return _av;\r
+ //return length ;\r
+ }\r
+\r
+ /**\r
+ * Make sure the stream is ultimately closed !\r
+ */\r
+\r
+ public void finalize() {\r
+ try {\r
+ close();\r
+ } catch (IOException ex) {\r
+ }\r
+ }\r
+\r
+ /**\r
+ * do we support mark() ?\r
+ * it depends on the underlying InputStream\r
+ * @return a boolean, true if mark is supported\r
+ */\r
+ public boolean markSupported() {\r
+ if( in == null )\r
+ return false;\r
+ else\r
+ return in.markSupported();\r
+ }\r
+\r
+ /**\r
+ * Builds a new content-length input stream.\r
+ * This stream acts as a normal stream except that it will return \r
+ * an end of file, after <em>count</em> bytes have been delivered.\r
+ */\r
+\r
+ public ContentLengthInputStream (InputStream in, int length) {\r
+ this(null, in, length);\r
+ }\r
+\r
+ public ContentLengthInputStream(HttpStreamObserver observer\r
+ , InputStream in\r
+ , int length) {\r
+ this.observer = observer;\r
+ this.in = in;\r
+ this.length = length;\r
+ }\r
+ \r
+}\r