You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2005/04/05 20:37:48 UTC

svn commit: r160206 - in jakarta/httpclient/trunk/http-common/src: java/org/apache/http/impl/ java/org/apache/http/io/ test/org/apache/http/impl/

Author: olegk
Date: Tue Apr  5 11:37:44 2005
New Revision: 160206

URL: http://svn.apache.org/viewcvs?view=rev&rev=160206
Log:
Extra test coverage, javadocs

Added:
    jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestBasicRequest.java   (with props)
    jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultResponseConsumedWatcher.java   (with props)
Modified:
    jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/DefaultEntityGenerator.java
    jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ChunkedInputStream.java
    jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ChunkedOutputStream.java
    jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ContentLengthInputStream.java
    jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestAllImpl.java
    jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultConnectionReuseStrategy.java
    jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultEntityGenerator.java

Modified: jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/DefaultEntityGenerator.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/DefaultEntityGenerator.java?view=diff&r1=160205&r2=160206
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/DefaultEntityGenerator.java (original)
+++ jakarta/httpclient/trunk/http-common/src/java/org/apache/http/impl/DefaultEntityGenerator.java Tue Apr  5 11:37:44 2005
@@ -49,7 +49,135 @@
 
 /**
  * <p>
+ * This entity generator comforms to the entity transfer rules outlined in the 
+ * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec4.4">Section 4.4</a>, 
+ * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6">Section 3.6</a>, 
+ * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.41">Section 14.41</a>
+ * and <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec14.13">Section 14.13</a>
+ * of <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.txt">RFC 2616</a>
  * </p>
+ * <h>4.4 Message Length</h>
+ * <p>
+ * The transfer-length of a message is the length of the message-body as it appears in the 
+ * message; that is, after any transfer-codings have been applied. When a message-body is 
+ * included with a message, the transfer-length of that body is determined by one of the 
+ * following (in order of precedence):
+ * </p>
+ * <p>
+ * 1.Any response message which "MUST NOT" include a message-body (such as the 1xx, 204, 
+ * and 304 responses and any response to a HEAD request) is always terminated by the first 
+ * empty line after the header fields, regardless of the entity-header fields present in the 
+ * message.
+ * </p>
+ * <p>
+ * 2.If a Transfer-Encoding header field (section 14.41) is present and has any value other 
+ * than "identity", then the transfer-length is defined by use of the "chunked" transfer-
+ * coding (section 3.6), unless the message is terminated by closing the connection.
+ * </p>
+ * <p>
+ * 3.If a Content-Length header field (section 14.13) is present, its decimal value in 
+ * OCTETs represents both the entity-length and the transfer-length. The Content-Length 
+ * header field MUST NOT be sent if these two lengths are different (i.e., if a 
+ * Transfer-Encoding
+ * </p>
+ * <pre>
+ *    header field is present). If a message is received with both a
+ *    Transfer-Encoding header field and a Content-Length header field,
+ *    the latter MUST be ignored.
+ * </pre>
+ * <p>
+ * 4.If the message uses the media type "multipart/byteranges", and the ransfer-length is not 
+ * otherwise specified, then this self- elimiting media type defines the transfer-length. 
+ * This media type UST NOT be used unless the sender knows that the recipient can arse it; the 
+ * presence in a request of a Range header with ultiple byte- range specifiers from a 1.1 
+ * client implies that the lient can parse multipart/byteranges responses.
+ * </p>
+ * <pre>
+ *     A range header might be forwarded by a 1.0 proxy that does not
+ *     understand multipart/byteranges; in this case the server MUST
+ *     delimit the message using methods defined in items 1,3 or 5 of
+ *     this section.
+ * </pre>
+ * <p>
+ * 5.By the server closing the connection. (Closing the connection cannot be used to indicate 
+ * the end of a request body, since that would leave no possibility for the server to send back 
+ * a response.)
+ * </p>
+ * <p>
+ * For compatibility with HTTP/1.0 applications, HTTP/1.1 requests containing a message-body 
+ * MUST include a valid Content-Length header field unless the server is known to be HTTP/1.1 
+ * compliant. If a request contains a message-body and a Content-Length is not given, the 
+ * server SHOULD respond with 400 (bad request) if it cannot determine the length of the 
+ * message, or with 411 (length required) if it wishes to insist on receiving a valid 
+ * Content-Length.
+ * </p>
+ * <p>All HTTP/1.1 applications that receive entities MUST accept the "chunked" transfer-coding 
+ * (section 3.6), thus allowing this mechanism to be used for messages when the message 
+ * length cannot be determined in advance. 
+ * </p>
+ * <h>3.6 Transfer Codings</h>
+ * <p>
+ * Transfer-coding values are used to indicate an encoding transformation that 
+ * has been, can be, or may need to be applied to an entity-body in order to ensure 
+ * "safe transport" through the network. This differs from a content coding in that 
+ * the transfer-coding is a property of the message, not of the original entity.
+ * </p>
+ * <pre>
+ * transfer-coding         = "chunked" | transfer-extension
+ * transfer-extension      = token *( ";" parameter )
+ * </pre>
+ * <p>
+ * Parameters are in the form of attribute/value pairs.
+ * </p>
+ * <pre>
+ * parameter               = attribute "=" value
+ * attribute               = token
+ * value                   = token | quoted-string
+ * </pre>
+ * <p>
+ * All transfer-coding values are case-insensitive. HTTP/1.1 uses transfer-coding values in 
+ * the TE header field (section 14.39) and in the Transfer-Encoding header field (section 14.41).
+ * </p>
+ * <p>
+ * Whenever a transfer-coding is applied to a message-body, the set of transfer-codings MUST 
+ * include "chunked", unless the message is terminated by closing the connection. When the 
+ * "chunked" transfer-coding is used, it MUST be the last transfer-coding applied to the 
+ * message-body. The "chunked" transfer-coding MUST NOT be applied more than once to a 
+ * message-body. These rules allow the recipient to determine the transfer-length of the 
+ * message (section 4.4).
+ * </p>
+ * <h>14.41 Transfer-Encoding</h>
+ * <p>
+ * The Transfer-Encoding general-header field indicates what (if any) type of transformation has 
+ * been applied to the message body in order to safely transfer it between the sender and the 
+ * recipient. This differs from the content-coding in that the transfer-coding is a property of 
+ * the message, not of the entity.
+ * </p>
+ * <pre>
+ *   Transfer-Encoding       = "Transfer-Encoding" ":" 1#transfer-coding
+ * </pre>
+ * <p>
+ * If multiple encodings have been applied to an entity, the transfer- codings MUST be listed in 
+ * the order in which they were applied. Additional information about the encoding parameters 
+ * MAY be provided by other entity-header fields not defined by this specification.
+ * </p> 
+ * <h>14.13 Content-Length</h>
+ * <p>
+ * The Content-Length entity-header field indicates the size of the entity-body, in decimal 
+ * number of OCTETs, sent to the recipient or, in the case of the HEAD method, the size of 
+ * the entity-body that would have been sent had the request been a GET.
+ * </p>
+ * <pre>
+ *   Content-Length    = "Content-Length" ":" 1*DIGIT
+ * </pre>
+ * <p>
+ * Applications SHOULD use this field to indicate the transfer-length of the message-body, 
+ * unless this is prohibited by the rules in section 4.4. 
+ * </p>
+ * <p>
+ * This entity generator currently supports only "chunked" and "identitiy" transfer-coding</a>
+ * </p>
+ * 
  * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
  *
  * @version $Revision$
@@ -105,7 +233,7 @@
             if (strict) {
                 // Currently only chunk and identity are supported
                 for (int i = 0; i < encodings.length; i++) {
-                    String encoding = encodings[i].getValue();
+                    String encoding = encodings[i].getName();
                     if (encoding != null && !encoding.equals("") 
                         && !encoding.equalsIgnoreCase(CHUNKED_ENCODING)
                         && !encoding.equalsIgnoreCase(IDENTITY_ENCODING)) {
@@ -113,8 +241,7 @@
                     }
                 }
             }
-            // The chunked encoding must be the last one applied
-            // RFC2616, 14.41
+            // The chunked encoding must be the last one applied RFC2616, 14.41
             int len = encodings.length;
             if (IDENTITY_ENCODING.equalsIgnoreCase(transferEncodingHeader.getValue())) {
                 entity.setChunked(false);

Modified: jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ChunkedInputStream.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ChunkedInputStream.java?view=diff&r1=160205&r2=160206
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ChunkedInputStream.java (original)
+++ jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ChunkedInputStream.java Tue Apr  5 11:37:44 2005
@@ -40,16 +40,76 @@
 import org.apache.http.util.HeadersParser;
 
 /**
- * <p>Transparently coalesces chunks of a HTTP stream that uses
- * Transfer-Encoding chunked.</p>
+ * <p>This class implements chunked transfer coding as described in the 
+ * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6">Section 3.6.1</a> 
+ * of <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.txt">RFC 2616</a>. 
+ * It transparently coalesces chunks of a HTTP stream that uses chunked transfer coding.</p>
+ * 
+ * <h>3.6.1 Chunked Transfer Coding</h>
+ * <p>
+ * The chunked encoding modifies the body of a message in order to transfer it as a series 
+ * of chunks, each with its own size indicator, followed by an OPTIONAL trailer containing 
+ * entity-header fields. This allows dynamically produced content to be transferred along 
+ * with the information necessary for the recipient to verify that it has received the full 
+ * message.
+ * </p>
+ * <pre>
+ *  Chunked-Body   = *chunk
+ *                   last-chunk
+ *                   trailer
+ *                   CRLF
  *
- * <p>Note that this class NEVER closes the underlying stream, even when close
+ *  chunk          = chunk-size [ chunk-extension ] CRLF
+ *                   chunk-data CRLF
+ *  chunk-size     = 1*HEX
+ *  last-chunk     = 1*("0") [ chunk-extension ] CRLF
+ *
+ *  chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
+ *  chunk-ext-name = token
+ *  chunk-ext-val  = token | quoted-string
+ *  chunk-data     = chunk-size(OCTET)
+ *  trailer        = *(entity-header CRLF)
+ * </pre>
+ * <p>
+ * The chunk-size field is a string of hex digits indicating the size of the chunk. The 
+ * chunked encoding is ended by any chunk whose size is zero, followed by the trailer, 
+ * which is terminated by an empty line.
+ * </p>
+ * <p>
+ * The trailer allows the sender to include additional HTTP header fields at the end 
+ * of the message. The Trailer header field can be used to indicate which header fields 
+ * are included in a trailer (see section 14.40).
+ * </p>
+ * <p>
+ * A server using chunked transfer-coding in a response MUST NOT use the trailer for any 
+ * header fields unless at least one of the following is true:
+ * </p>
+ * <p>
+ * a)the request included a TE header field that indicates "trailers" is acceptable in 
+ * the transfer-coding of the response, as described in section 14.39; or,
+ * </p>
+ * <p>
+ * b)the server is the origin server for the response, the trailer fields consist entirely 
+ * of optional metadata, and the recipient could use the message (in a manner acceptable 
+ * to the origin server) without receiving this metadata. In other words, the origin server 
+ * is willing to accept the possibility that the trailer fields might be silently discarded 
+ * along the path to the client.
+ * </p>
+ * <p>
+ * This requirement prevents an interoperability failure when the message is being received 
+ * by an HTTP/1.1 (or later) proxy and forwarded to an HTTP/1.0 recipient. It avoids a 
+ * situation where compliance with the protocol would have necessitated a possibly infinite 
+ * buffer on the proxy. 
+ * </p>
+ * <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 invocation of subsequent HTTP 1.1 calls, while
  * not requiring the client to remember to read the entire contents of the
- * response.</p>
+ * response.
+ * </p>
  *
- * @author Ortwin Glück
+ * @author Ortwin Glueck
  * @author Sean C. Sullivan
  * @author Martin Elwin
  * @author Eric Johnson

Modified: jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ChunkedOutputStream.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ChunkedOutputStream.java?view=diff&r1=160205&r2=160206
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ChunkedOutputStream.java (original)
+++ jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ChunkedOutputStream.java Tue Apr  5 11:37:44 2005
@@ -35,9 +35,69 @@
 import org.apache.http.util.EncodingUtil;
 
 /**
- * Implements HTTP chunking support. Writes are buffered to an internal buffer (2048 default size).
- * Chunks are guaranteed to be at least as large as the buffer size (except for the last chunk).
+ * <p>This class implements chunked transfer coding as described in the 
+ * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6">Section 3.6.1</a> 
+ * of <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.txt">RFC 2616</a>. 
+ * Writes are buffered to an internal buffer (2048 default size). Chunks are guaranteed 
+ * to be at least as large as the buffer size (except for the last chunk).</p>
+ * 
+ * <h>3.6.1 Chunked Transfer Coding</h>
+ * <p>
+ * The chunked encoding modifies the body of a message in order to transfer it as a series 
+ * of chunks, each with its own size indicator, followed by an OPTIONAL trailer containing 
+ * entity-header fields. This allows dynamically produced content to be transferred along 
+ * with the information necessary for the recipient to verify that it has received the full 
+ * message.
+ * </p>
+ * <pre>
+ *  Chunked-Body   = *chunk
+ *                   last-chunk
+ *                   trailer
+ *                   CRLF
  *
+ *  chunk          = chunk-size [ chunk-extension ] CRLF
+ *                   chunk-data CRLF
+ *  chunk-size     = 1*HEX
+ *  last-chunk     = 1*("0") [ chunk-extension ] CRLF
+ *
+ *  chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
+ *  chunk-ext-name = token
+ *  chunk-ext-val  = token | quoted-string
+ *  chunk-data     = chunk-size(OCTET)
+ *  trailer        = *(entity-header CRLF)
+ * </pre>
+ * <p>
+ * The chunk-size field is a string of hex digits indicating the size of the chunk. The 
+ * chunked encoding is ended by any chunk whose size is zero, followed by the trailer, 
+ * which is terminated by an empty line.
+ * </p>
+ * <p>
+ * The trailer allows the sender to include additional HTTP header fields at the end 
+ * of the message. The Trailer header field can be used to indicate which header fields 
+ * are included in a trailer (see section 14.40).
+ * </p>
+ * <p>
+ * A server using chunked transfer-coding in a response MUST NOT use the trailer for any 
+ * header fields unless at least one of the following is true:
+ * </p>
+ * <p>
+ * a)the request included a TE header field that indicates "trailers" is acceptable in 
+ * the transfer-coding of the response, as described in section 14.39; or,
+ * </p>
+ * <p>
+ * b)the server is the origin server for the response, the trailer fields consist entirely 
+ * of optional metadata, and the recipient could use the message (in a manner acceptable 
+ * to the origin server) without receiving this metadata. In other words, the origin server 
+ * is willing to accept the possibility that the trailer fields might be silently discarded 
+ * along the path to the client.
+ * </p>
+ * <p>
+ * This requirement prevents an interoperability failure when the message is being received 
+ * by an HTTP/1.1 (or later) proxy and forwarded to an HTTP/1.0 recipient. It avoids a 
+ * situation where compliance with the protocol would have necessitated a possibly infinite 
+ * buffer on the proxy. 
+ * </p>
+ * 
  * @author Mohammad Rezaei, Goldman, Sachs & Co.
  */
 public class ChunkedOutputStream extends OutputStream {

Modified: jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ContentLengthInputStream.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ContentLengthInputStream.java?view=diff&r1=160205&r2=160206
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ContentLengthInputStream.java (original)
+++ jakarta/httpclient/trunk/http-common/src/java/org/apache/http/io/ContentLengthInputStream.java Tue Apr  5 11:37:44 2005
@@ -33,8 +33,16 @@
 import java.io.InputStream;
 
 /**
- * Cuts the wrapped InputStream off after a specified number of bytes.
- *
+ * <p>
+ * This class cuts the wrapped InputStream off after a specified number of bytes.
+ * </p>
+ * <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 invocation of subsequent HTTP 1.1 calls, while
+ * not requiring the client to remember to read the entire contents of the
+ * response.
+ * </p>
  * <p>Implementation note: Choices abound. One approach would pass
  * through the {@link InputStream#mark} and {@link InputStream#reset} calls to
  * the underlying stream.  That's tricky, though, because you then have to

Modified: jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestAllImpl.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestAllImpl.java?view=diff&r1=160205&r2=160206
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestAllImpl.java (original)
+++ jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestAllImpl.java Tue Apr  5 11:37:44 2005
@@ -43,6 +43,8 @@
         suite.addTest(TestAutoCloseInputStream.suite());
         suite.addTest(TestDefaultConnectionReuseStrategy.suite());
         suite.addTest(TestDefaultEntityGenerator.suite());
+        suite.addTest(TestDefaultResponseConsumedWatcher.suite());
+        suite.addTest(TestBasicRequest.suite());
         return suite;
     }
 

Added: jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestBasicRequest.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestBasicRequest.java?view=auto&rev=160206
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestBasicRequest.java (added)
+++ jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestBasicRequest.java Tue Apr  5 11:37:44 2005
@@ -0,0 +1,104 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ * ====================================================================
+ *
+ *  Copyright 2002-2004 The Apache Software Foundation
+ *
+ *  Licensed 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;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.http.HttpMutableRequest;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpVersion;
+import org.apache.http.RequestLine;
+import org.apache.http.params.HttpProtocolParams;
+
+public class TestBasicRequest extends TestCase {
+
+    public TestBasicRequest(String testName) {
+        super(testName);
+    }
+
+    // ------------------------------------------------------- TestCase Methods
+
+    public static Test suite() {
+        return new TestSuite(TestBasicRequest.class);
+    }
+
+    // ------------------------------------------------------------------- Main
+    public static void main(String args[]) {
+        String[] testCaseName = { TestBasicRequest.class.getName() };
+        junit.textui.TestRunner.main(testCaseName);
+    }
+
+    public void testConstructor() throws Exception {
+        new BasicHttpRequest("GET", "/stuff");
+        new BasicHttpRequest(new RequestLine("GET", "/stuff", HttpVersion.HTTP_1_1));
+        try {
+            new BasicHttpRequest(null, "/stuff");
+            fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+        try {
+            new BasicHttpRequest("GET", null);
+            fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+    }
+
+    public void testRequestLine() throws Exception {
+        HttpRequest request = new BasicHttpRequest("GET", "/stuff");
+        request.getParams().setParameter(
+                HttpProtocolParams.PROTOCOL_VERSION, HttpVersion.HTTP_1_0);
+        assertEquals("GET", request.getRequestLine().getMethod());
+        assertEquals("/stuff", request.getRequestLine().getUri());
+        assertEquals(HttpVersion.HTTP_1_0, request.getRequestLine().getHttpVersion());
+    }
+
+    public void testRequestLine2() throws Exception {
+        HttpRequest request = new BasicHttpRequest(
+                new RequestLine("GET", "/stuff", HttpVersion.HTTP_1_0));
+        assertEquals("GET", request.getRequestLine().getMethod());
+        assertEquals("/stuff", request.getRequestLine().getUri());
+        assertEquals(HttpVersion.HTTP_1_0, request.getRequestLine().getHttpVersion());
+    }
+
+    public void testNullRequestLine() throws Exception {
+        HttpMutableRequest request = new BasicHttpRequest("GET", "/stuff");
+        try {
+            request.setRequestLine(null);
+            fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+    }
+
+}
+

Propchange: jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestBasicRequest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestBasicRequest.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestBasicRequest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultConnectionReuseStrategy.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultConnectionReuseStrategy.java?view=diff&r1=160205&r2=160206
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultConnectionReuseStrategy.java (original)
+++ jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultConnectionReuseStrategy.java Tue Apr  5 11:37:44 2005
@@ -72,7 +72,6 @@
         entity.setContentLength(-1);
         HttpMutableResponse response = new BasicHttpResponse();
         response.setStatusLine(new StatusLine(HttpVersion.HTTP_1_0, 200, "OK"));
-        response.setParams(new DefaultHttpParams(null));
         response.setEntity(entity);
 
         ConnectionReuseStrategy s = new DefaultConnectionReuseStrategy();
@@ -86,7 +85,6 @@
         HttpMutableResponse response = new BasicHttpResponse();
         // Use HTTP 1.1
         response.setStatusLine(new StatusLine(HttpVersion.HTTP_1_1, 200, "OK"));
-        response.setParams(new DefaultHttpParams(null));
         response.addHeader(new Header("Connection", "close"));
         response.setEntity(entity);
 
@@ -101,7 +99,6 @@
         HttpMutableResponse response = new BasicHttpResponse();
         // Use HTTP 1.0
         response.setStatusLine(new StatusLine(HttpVersion.HTTP_1_0, 200, "OK"));
-        response.setParams(new DefaultHttpParams(null));
         response.addHeader(new Header("Connection", "keep-alive"));
         response.setEntity(entity);
 
@@ -112,7 +109,6 @@
     public void testHTTP10Default() throws Exception {
         HttpMutableResponse response = new BasicHttpResponse();
         response.setStatusLine(new StatusLine(HttpVersion.HTTP_1_0, 200, "OK"));
-        response.setParams(new DefaultHttpParams(null));
 
         ConnectionReuseStrategy s = new DefaultConnectionReuseStrategy();
         assertFalse(s.keepAlive(response));
@@ -121,7 +117,6 @@
     public void testHTTP11Default() throws Exception {
         HttpMutableResponse response = new BasicHttpResponse();
         response.setStatusLine(new StatusLine(HttpVersion.HTTP_1_1, 200, "OK"));
-        response.setParams(new DefaultHttpParams(null));
 
         ConnectionReuseStrategy s = new DefaultConnectionReuseStrategy();
         assertTrue(s.keepAlive(response));
@@ -130,7 +125,6 @@
     public void testFutureHTTP() throws Exception {
         HttpMutableResponse response = new BasicHttpResponse();
         response.setStatusLine(new StatusLine(new HttpVersion(3, 45), 200, "OK"));
-        response.setParams(new DefaultHttpParams(null));
 
         ConnectionReuseStrategy s = new DefaultConnectionReuseStrategy();
         assertTrue(s.keepAlive(response));
@@ -140,7 +134,6 @@
         HttpMutableResponse response = new BasicHttpResponse();
         // Use HTTP 1.0
         response.setStatusLine(new StatusLine(HttpVersion.HTTP_1_0, 200, "OK"));
-        response.setParams(new DefaultHttpParams(null));
         response.addHeader(new Header("Connection", "keep--alive"));
 
         ConnectionReuseStrategy s = new DefaultConnectionReuseStrategy();
@@ -151,7 +144,6 @@
         HttpMutableResponse response = new BasicHttpResponse();
         // Use HTTP 1.0
         response.setStatusLine(new StatusLine(HttpVersion.HTTP_1_0, 200, "OK"));
-        response.setParams(new DefaultHttpParams(null));
         response.addHeader(new Header("Connection", null));
 
         ConnectionReuseStrategy s = new DefaultConnectionReuseStrategy();

Modified: jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultEntityGenerator.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultEntityGenerator.java?view=diff&r1=160205&r2=160206
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultEntityGenerator.java (original)
+++ jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultEntityGenerator.java Tue Apr  5 11:37:44 2005
@@ -41,7 +41,6 @@
 import org.apache.http.io.HttpDataReceiver;
 import org.apache.http.io.InputStreamHttpDataReceiver;
 import org.apache.http.mockup.HttpDataReceiverMockup;
-import org.apache.http.params.HttpParams;
 import org.apache.http.params.HttpProtocolParams;
 
 import junit.framework.Test;
@@ -66,7 +65,7 @@
         junit.textui.TestRunner.main(testCaseName);
     }
 
-    public void testIllegalResponseArg() throws Exception {
+    public void testIllegalGenerateArg() throws Exception {
         EntityGenerator entitygen = new DefaultEntityGenerator();
         try {
             entitygen.generate(null, null);
@@ -82,14 +81,107 @@
         }
     }
 
+    public void testEntityWithTransferEncoding() throws Exception {
+        HttpDataReceiver datareceiver = new HttpDataReceiverMockup("0\r\n", "US-ASCII");
+        HttpMutableMessage message = new BasicHttpMessage();
+        
+        // lenient mode 
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
+        message.addHeader(new Header("Content-Type", "unknown"));
+        message.addHeader(new Header("Transfer-Encoding", "identity, chunked"));
+        message.addHeader(new Header("Content-Length", "plain wrong"));
+        EntityGenerator entitygen = new DefaultEntityGenerator();
+        HttpEntity entity = entitygen.generate(datareceiver, message);
+        assertNotNull(entity);
+        assertEquals(-1, entity.getContentLength());
+        assertTrue(entity.isChunked());
+        assertTrue(entity.getInputStream() instanceof ChunkedInputStream);
+
+        // strict mode 
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, true);
+        entity = entitygen.generate(datareceiver, message);
+        assertNotNull(entity);
+        assertEquals(-1, entity.getContentLength());
+        assertTrue(entity.isChunked());
+        assertTrue(entity.getInputStream() instanceof ChunkedInputStream);
+    }
+
+    public void testEntityWithIdentityTransferEncoding() throws Exception {
+        InputStream instream = new ByteArrayInputStream(new byte[] {});
+        HttpDataReceiver datareceiver = new InputStreamHttpDataReceiver(instream);
+        HttpMutableMessage message = new BasicHttpMessage();
+        
+        // lenient mode 
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
+        message.addHeader(new Header("Content-Type", "unknown"));
+        message.addHeader(new Header("Transfer-Encoding", "identity"));
+        message.addHeader(new Header("Content-Length", "plain wrong"));
+        EntityGenerator entitygen = new DefaultEntityGenerator();
+        HttpEntity entity = entitygen.generate(datareceiver, message);
+        assertNotNull(entity);
+        assertEquals(-1, entity.getContentLength());
+        assertFalse(entity.isChunked());
+        assertTrue(entity.getInputStream() instanceof ByteArrayInputStream);
+    }
+
+    public void testEntityWithUnsupportedTransferEncoding() throws Exception {
+        HttpDataReceiver datareceiver = new HttpDataReceiverMockup("0\r\n", "US-ASCII");
+        HttpMutableMessage message = new BasicHttpMessage();
+        
+        // lenient mode 
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
+        message.addHeader(new Header("Content-Type", "unknown"));
+        message.addHeader(new Header("Transfer-Encoding", "whatever; param=value, chunked"));
+        message.addHeader(new Header("Content-Length", "plain wrong"));
+        EntityGenerator entitygen = new DefaultEntityGenerator();
+        HttpEntity entity = entitygen.generate(datareceiver, message);
+        assertNotNull(entity);
+        assertEquals(-1, entity.getContentLength());
+        assertTrue(entity.isChunked());
+        assertTrue(entity.getInputStream() instanceof ChunkedInputStream);
+
+        // strict mode 
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, true);
+        try {
+            entitygen.generate(datareceiver, message);
+            fail("ProtocolException should have been thrown");
+        } catch (ProtocolException ex) {
+            // expected
+        }
+    }
+
+    public void testChunkedTransferEncodingMustBeLast() throws Exception {
+        HttpDataReceiver datareceiver = new HttpDataReceiverMockup("0\r\n", "US-ASCII");
+        HttpMutableMessage message = new BasicHttpMessage();
+        
+        // lenient mode 
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
+        message.addHeader(new Header("Content-Type", "unknown"));
+        message.addHeader(new Header("Transfer-Encoding", "chunked, identity"));
+        message.addHeader(new Header("Content-Length", "plain wrong"));
+        EntityGenerator entitygen = new DefaultEntityGenerator();
+        HttpEntity entity = entitygen.generate(datareceiver, message);
+        assertNotNull(entity);
+        assertEquals(-1, entity.getContentLength());
+        assertFalse(entity.isChunked());
+        assertFalse(entity.getInputStream() instanceof ChunkedInputStream);
+
+        // strict mode 
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, true);
+        try {
+            entitygen.generate(datareceiver, message);
+            fail("ProtocolException should have been thrown");
+        } catch (ProtocolException ex) {
+            // expected
+        }
+    }
+
     public void testEntityWithContentLength() throws Exception {
         HttpDataReceiver datareceiver = new HttpDataReceiverMockup(new byte[] {});
         HttpMutableMessage message = new BasicHttpMessage();
-        HttpParams params = new DefaultHttpParams(null);
-        message.setParams(params);
         
         // lenient mode 
-        params.setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
         message.addHeader(new Header("Content-Type", "unknown"));
         message.addHeader(new Header("Content-Length", "0"));
         EntityGenerator entitygen = new DefaultEntityGenerator();
@@ -103,11 +195,9 @@
     public void testEntityWithMultipleContentLength() throws Exception {
         HttpDataReceiver datareceiver = new HttpDataReceiverMockup(new byte[] {'0'});
         HttpMutableMessage message = new BasicHttpMessage();
-        HttpParams params = new DefaultHttpParams(null);
-        message.setParams(params);
 
         // lenient mode 
-        params.setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
         message.addHeader(new Header("Content-Type", "unknown"));
         message.addHeader(new Header("Content-Length", "0"));
         message.addHeader(new Header("Content-Length", "0"));
@@ -121,7 +211,7 @@
         assertTrue(entity.getInputStream() instanceof ContentLengthInputStream);
         
         // strict mode 
-        params.setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, true);
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, true);
         try {
             entitygen.generate(datareceiver, message);
             fail("ProtocolException should have been thrown");
@@ -133,11 +223,9 @@
     public void testEntityWithMultipleContentLengthSomeWrong() throws Exception {
         HttpDataReceiver datareceiver = new HttpDataReceiverMockup(new byte[] {'0'});
         HttpMutableMessage message = new BasicHttpMessage();
-        HttpParams params = new DefaultHttpParams(null);
-        message.setParams(params);
 
         // lenient mode 
-        params.setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
         message.addHeader(new Header("Content-Type", "unknown"));
         message.addHeader(new Header("Content-Length", "1"));
         message.addHeader(new Header("Content-Length", "yyy"));
@@ -151,7 +239,7 @@
         assertTrue(entity.getInputStream() instanceof ContentLengthInputStream);
         
         // strict mode 
-        params.setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, true);
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, true);
         try {
             entitygen.generate(datareceiver, message);
             fail("ProtocolException should have been thrown");
@@ -163,11 +251,9 @@
     public void testEntityWithMultipleContentLengthAllWrong() throws Exception {
         HttpDataReceiver datareceiver = new HttpDataReceiverMockup(new byte[] {'0'});
         HttpMutableMessage message = new BasicHttpMessage();
-        HttpParams params = new DefaultHttpParams(null);
-        message.setParams(params);
 
         // lenient mode 
-        params.setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
         message.addHeader(new Header("Content-Type", "unknown"));
         message.addHeader(new Header("Content-Length", "yyy"));
         message.addHeader(new Header("Content-Length", "xxx"));
@@ -181,7 +267,7 @@
         assertTrue(entity.getInputStream() instanceof HttpDataInputStream);
         
         // strict mode 
-        params.setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, true);
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, true);
         try {
             entitygen.generate(datareceiver, message);
             fail("ProtocolException should have been thrown");
@@ -193,11 +279,9 @@
     public void testEntityWithInvalidContentLength() throws Exception {
         HttpDataReceiver datareceiver = new HttpDataReceiverMockup(new byte[] {'0'});
         HttpMutableMessage message = new BasicHttpMessage();
-        HttpParams params = new DefaultHttpParams(null);
-        message.setParams(params);
 
         // lenient mode 
-        params.setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
         message.addHeader(new Header("Content-Type", "unknown"));
         message.addHeader(new Header("Content-Length", "xxx"));
         EntityGenerator entitygen = new DefaultEntityGenerator();
@@ -210,7 +294,7 @@
         assertTrue(entity.getInputStream() instanceof HttpDataInputStream);
         
         // strict mode 
-        params.setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, true);
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, true);
         try {
             entitygen.generate(datareceiver, message);
             fail("ProtocolException should have been thrown");
@@ -222,11 +306,9 @@
     public void testEntityNeitherContentLengthNorTransferEncoding() throws Exception {
         HttpDataReceiver datareceiver = new HttpDataReceiverMockup(new byte[] {'0'});
         HttpMutableMessage message = new BasicHttpMessage();
-        HttpParams params = new DefaultHttpParams(null);
-        message.setParams(params);
 
         // lenient mode 
-        params.setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
+        message.getParams().setBooleanParameter(HttpProtocolParams.STRICT_TRANSFER_ENCODING, false);
         EntityGenerator entitygen = new DefaultEntityGenerator();
         HttpEntity entity = entitygen.generate(datareceiver, message);
         assertNotNull(entity);

Added: jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultResponseConsumedWatcher.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultResponseConsumedWatcher.java?view=auto&rev=160206
==============================================================================
--- jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultResponseConsumedWatcher.java (added)
+++ jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultResponseConsumedWatcher.java Tue Apr  5 11:37:44 2005
@@ -0,0 +1,127 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ * ====================================================================
+ *
+ *  Copyright 2002-2004 The Apache Software Foundation
+ *
+ *  Licensed 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;
+
+import java.io.ByteArrayInputStream;
+
+import org.apache.http.Header;
+import org.apache.http.HttpConnection;
+import org.apache.http.HttpMutableEntity;
+import org.apache.http.HttpMutableResponse;
+import org.apache.http.HttpVersion;
+import org.apache.http.StatusLine;
+import org.apache.http.mockup.HttpConnectionMockup;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class TestDefaultResponseConsumedWatcher extends TestCase {
+
+    public TestDefaultResponseConsumedWatcher(String testName) {
+        super(testName);
+    }
+
+    // ------------------------------------------------------- TestCase Methods
+
+    public static Test suite() {
+        return new TestSuite(TestDefaultResponseConsumedWatcher.class);
+    }
+
+    // ------------------------------------------------------------------- Main
+    public static void main(String args[]) {
+        String[] testCaseName = { TestDefaultResponseConsumedWatcher.class.getName() };
+        junit.textui.TestRunner.main(testCaseName);
+    }
+
+    public void testIllegalResponseArg() throws Exception {
+        try {
+            ResponseConsumedWatcher watcher = new DefaultResponseConsumedWatcher(null, null);
+            fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+        try {
+            ResponseConsumedWatcher watcher = new DefaultResponseConsumedWatcher(
+                    new HttpConnectionMockup(), null);
+            fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+    }
+
+    public void testConnectionAutoClose() throws Exception {
+        byte[] data = new byte[] {'1', '2', '3'};
+        HttpConnection conn = new HttpConnectionMockup();
+        HttpMutableEntity entity = new BasicHttpEntity();
+        entity.setChunked(false);
+        entity.setContentLength(data.length);
+        entity.setInputStream(new ByteArrayInputStream(data));
+        
+        HttpMutableResponse response = new BasicHttpResponse();
+        response.setStatusLine(new StatusLine(HttpVersion.HTTP_1_0, 200, "OK"));
+        response.setHeader(new Header("Connection", "Close"));
+        response.setParams(new DefaultHttpParams(null));
+        response.setEntity(entity);
+        
+        // Wrap the entity input stream 
+        ResponseConsumedWatcher watcher = new DefaultResponseConsumedWatcher(conn, response);
+        entity.setInputStream(new AutoCloseInputStream(entity.getInputStream(), watcher));
+        
+        assertTrue(conn.isOpen());
+        int b;
+        while ((b = entity.getInputStream().read()) != -1) {}
+        assertFalse(conn.isOpen());
+    }
+
+    public void testConnectionKeepAlive() throws Exception {
+        byte[] data = new byte[] {'1', '2', '3'};
+        HttpConnection conn = new HttpConnectionMockup();
+        HttpMutableEntity entity = new BasicHttpEntity();
+        entity.setChunked(false);
+        entity.setContentLength(data.length);
+        entity.setInputStream(new ByteArrayInputStream(data));
+        
+        HttpMutableResponse response = new BasicHttpResponse();
+        response.setStatusLine(new StatusLine(HttpVersion.HTTP_1_1, 200, "OK"));
+        response.setHeader(new Header("Connection", "Keep-alive"));
+        response.setParams(new DefaultHttpParams(null));
+        response.setEntity(entity);
+        
+        // Wrap the entity input stream 
+        ResponseConsumedWatcher watcher = new DefaultResponseConsumedWatcher(conn, response);
+        entity.setInputStream(new AutoCloseInputStream(entity.getInputStream(), watcher));
+        
+        assertTrue(conn.isOpen());
+        int b;
+        while ((b = entity.getInputStream().read()) != -1) {}
+        assertTrue(conn.isOpen());
+    }
+}
+

Propchange: jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultResponseConsumedWatcher.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultResponseConsumedWatcher.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpclient/trunk/http-common/src/test/org/apache/http/impl/TestDefaultResponseConsumedWatcher.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain