diff options
Diffstat (limited to 'src/org/apache/http/impl/io/ChunkedInputStream.java')
-rw-r--r-- | src/org/apache/http/impl/io/ChunkedInputStream.java | 294 |
1 files changed, 0 insertions, 294 deletions
diff --git a/src/org/apache/http/impl/io/ChunkedInputStream.java b/src/org/apache/http/impl/io/ChunkedInputStream.java deleted file mode 100644 index 60cae90..0000000 --- a/src/org/apache/http/impl/io/ChunkedInputStream.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/impl/io/ChunkedInputStream.java $ - * $Revision: 569843 $ - * $Date: 2007-08-26 10:05:40 -0700 (Sun, 26 Aug 2007) $ - * - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * <http://www.apache.org/>. - * - */ - -package org.apache.http.impl.io; - -import java.io.IOException; -import java.io.InputStream; - -import org.apache.http.Header; -import org.apache.http.HttpException; -import org.apache.http.MalformedChunkCodingException; -import org.apache.http.io.SessionInputBuffer; -import org.apache.http.protocol.HTTP; -import org.apache.http.util.CharArrayBuffer; -import org.apache.http.util.ExceptionUtils; - -/** - * Implements chunked transfer coding. - * See <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.txt">RFC 2616</a>, - * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6">section 3.6.1</a>. - * It transparently coalesces chunks of a HTTP stream that uses chunked - * transfer coding. After the stream is read to the end, it provides access - * to the trailers, if any. - * <p> - * Note that this class NEVER closes the underlying stream, even when close - * gets called. Instead, it will read until the "end" of its chunking on - * close, which allows for the seamless execution of subsequent HTTP 1.1 - * requests, while not requiring the client to remember to read the entire - * contents of the response. - * </p> - * - * @author Ortwin Glueck - * @author Sean C. Sullivan - * @author Martin Elwin - * @author Eric Johnson - * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a> - * @author Michael Becke - * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a> - * - * @since 4.0 - * - */ -public class ChunkedInputStream extends InputStream { - - /** The session input buffer */ - private SessionInputBuffer in; - - private final CharArrayBuffer buffer; - - /** The chunk size */ - private int chunkSize; - - /** The current position within the current chunk */ - private int pos; - - /** True if we'are at the beginning of stream */ - private boolean bof = true; - - /** True if we've reached the end of stream */ - private boolean eof = false; - - /** True if this stream is closed */ - private boolean closed = false; - - private Header[] footers = new Header[] {}; - - public ChunkedInputStream(final SessionInputBuffer in) { - super(); - if (in == null) { - throw new IllegalArgumentException("Session input buffer may not be null"); - } - this.in = in; - this.pos = 0; - this.buffer = new CharArrayBuffer(16); - } - - /** - * <p> Returns all the data in a chunked stream in coalesced form. A chunk - * is followed by a CRLF. The method returns -1 as soon as a chunksize of 0 - * is detected.</p> - * - * <p> Trailer headers are read automcatically at the end of the stream and - * can be obtained with the getResponseFooters() method.</p> - * - * @return -1 of the end of the stream has been reached or the next data - * byte - * @throws IOException If an IO problem occurs - */ - public int read() throws IOException { - if (this.closed) { - throw new IOException("Attempted read from closed stream."); - } - if (this.eof) { - return -1; - } - if (this.pos >= this.chunkSize) { - nextChunk(); - if (this.eof) { - return -1; - } - } - pos++; - return in.read(); - } - - /** - * Read some bytes from the stream. - * @param b The byte array that will hold the contents from the stream. - * @param off The offset into the byte array at which bytes will start to be - * placed. - * @param len the maximum number of bytes that can be returned. - * @return The number of bytes returned or -1 if the end of stream has been - * reached. - * @see java.io.InputStream#read(byte[], int, int) - * @throws IOException if an IO problem occurs. - */ - public int read (byte[] b, int off, int len) throws IOException { - - if (closed) { - throw new IOException("Attempted read from closed stream."); - } - - if (eof) { - return -1; - } - if (pos >= chunkSize) { - nextChunk(); - if (eof) { - return -1; - } - } - len = Math.min(len, chunkSize - pos); - int count = in.read(b, off, len); - pos += count; - return count; - } - - /** - * Read some bytes from the stream. - * @param b The byte array that will hold the contents from the stream. - * @return The number of bytes returned or -1 if the end of stream has been - * reached. - * @see java.io.InputStream#read(byte[]) - * @throws IOException if an IO problem occurs. - */ - public int read (byte[] b) throws IOException { - return read(b, 0, b.length); - } - - /** - * Read the next chunk. - * @throws IOException If an IO error occurs. - */ - private void nextChunk() throws IOException { - chunkSize = getChunkSize(); - if (chunkSize < 0) { - throw new MalformedChunkCodingException("Negative chunk size"); - } - bof = false; - pos = 0; - if (chunkSize == 0) { - eof = true; - parseTrailerHeaders(); - } - } - - /** - * Expects the stream to start with a chunksize in hex with optional - * comments after a semicolon. The line must end with a CRLF: "a3; some - * comment\r\n" Positions the stream at the start of the next line. - * - * @param in The new input stream. - * @param required <tt>true<tt/> if a valid chunk must be present, - * <tt>false<tt/> otherwise. - * - * @return the chunk size as integer - * - * @throws IOException when the chunk size could not be parsed - */ - private int getChunkSize() throws IOException { - // skip CRLF - if (!bof) { - int cr = in.read(); - int lf = in.read(); - if ((cr != HTTP.CR) || (lf != HTTP.LF)) { - throw new MalformedChunkCodingException( - "CRLF expected at end of chunk"); - } - } - //parse data - this.buffer.clear(); - int i = this.in.readLine(this.buffer); - if (i == -1) { - throw new MalformedChunkCodingException( - "Chunked stream ended unexpectedly"); - } - int separator = this.buffer.indexOf(';'); - if (separator < 0) { - separator = this.buffer.length(); - } - try { - return Integer.parseInt(this.buffer.substringTrimmed(0, separator), 16); - } catch (NumberFormatException e) { - throw new MalformedChunkCodingException("Bad chunk header"); - } - } - - /** - * Reads and stores the Trailer headers. - * @throws IOException If an IO problem occurs - */ - private void parseTrailerHeaders() throws IOException { - try { - this.footers = AbstractMessageParser.parseHeaders - (in, -1, -1, null); - } catch (HttpException e) { - IOException ioe = new MalformedChunkCodingException("Invalid footer: " - + e.getMessage()); - ExceptionUtils.initCause(ioe, e); - throw ioe; - } - } - - /** - * Upon close, this reads the remainder of the chunked message, - * leaving the underlying socket at a position to start reading the - * next response without scanning. - * @throws IOException If an IO problem occurs. - */ - public void close() throws IOException { - if (!closed) { - try { - if (!eof) { - exhaustInputStream(this); - } - } finally { - eof = true; - closed = true; - } - } - } - - public Header[] getFooters() { - return (Header[])this.footers.clone(); - } - - /** - * Exhaust an input stream, reading until EOF has been encountered. - * - * <p>Note that this function is intended as a non-public utility. - * This is a little weird, but it seemed silly to make a utility - * class for this one function, so instead it is just static and - * shared that way.</p> - * - * @param inStream The {@link InputStream} to exhaust. - * @throws IOException If an IO problem occurs - */ - static void exhaustInputStream(final InputStream inStream) throws IOException { - // read and discard the remainder of the message - byte buffer[] = new byte[1024]; - while (inStream.read(buffer) >= 0) { - ; - } - } - -} |