You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by og...@apache.org on 2006/12/01 12:26:35 UTC

svn commit: r481225 - in /jakarta/commons/proper/httpclient/trunk: ./ src/java/org/apache/commons/httpclient/ src/test/org/apache/commons/httpclient/

Author: oglueck
Date: Fri Dec  1 03:26:28 2006
New Revision: 481225

URL: http://svn.apache.org/viewvc?view=rev&rev=481225
Log:
Added a convenience method that is memory-safe.

PR: HTTPCLIENT-610
Contributed by: Ortwin Glück
Reviewed by: Oleg Kalnichevski

Added:
    jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpContentTooLargeException.java
Modified:
    jakarta/commons/proper/httpclient/trunk/release_notes.txt
    jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpMethodBase.java
    jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestHttpMethodFundamentals.java

Modified: jakarta/commons/proper/httpclient/trunk/release_notes.txt
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/httpclient/trunk/release_notes.txt?view=diff&rev=481225&r1=481224&r2=481225
==============================================================================
--- jakarta/commons/proper/httpclient/trunk/release_notes.txt (original)
+++ jakarta/commons/proper/httpclient/trunk/release_notes.txt Fri Dec  1 03:26:28 2006
@@ -1,3 +1,8 @@
+Changes since Release 3.1 Beta 1:
+
+* [HTTPCLIENT-610] - Added for convenience HttpMethodBase.getResponseBodyAsString(int)
+           Contributed by Ortwin Glueck <oglueck at apache.org>
+           
 Release 3.1 Beta 1
 -------------------
 Changes since Release 3.1 Alpha 1:

Added: jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpContentTooLargeException.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpContentTooLargeException.java?view=auto&rev=481225
==============================================================================
--- jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpContentTooLargeException.java (added)
+++ jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpContentTooLargeException.java Fri Dec  1 03:26:28 2006
@@ -0,0 +1,22 @@
+package org.apache.commons.httpclient;
+
+/**
+ * Signals that the response content was larger than anticipated. 
+ * 
+ * @author Ortwin Glück
+ */
+public class HttpContentTooLargeException extends HttpException {
+    private int maxlen;
+
+    public HttpContentTooLargeException(String message, int maxlen) {
+        super(message);
+        this.maxlen = maxlen;
+    }
+    
+    /**
+     * @return the maximum anticipated content length in bytes.
+     */
+    public int getMaxLength() {
+        return maxlen;
+    }
+}

Modified: jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpMethodBase.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpMethodBase.java?view=diff&rev=481225&r1=481224&r2=481225
==============================================================================
--- jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpMethodBase.java (original)
+++ jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpMethodBase.java Fri Dec  1 03:26:28 2006
@@ -34,7 +34,9 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.InterruptedIOException;
+import java.io.Reader;
 import java.util.Collection;
 
 import org.apache.commons.httpclient.auth.AuthState;
@@ -698,7 +700,7 @@
      * Returns the response body of the HTTP method, if any, as an {@link InputStream}. 
      * If response body is not available, returns <tt>null</tt>
      * 
-     * @return The response body
+     * @return The response body or <code>null</code>.
      * 
      * @throws IOException If an I/O (transport) problem occurs while obtaining the 
      * response body.
@@ -726,7 +728,7 @@
      * recommended, to use getResponseAsStream if the content length of the response
      * is unknown or resonably large.
      * 
-     * @return The response body.
+     * @return The response body or <code>null</code>.
      * 
      * @throws IOException If an I/O (transport) problem occurs while obtaining the 
      * response body.
@@ -741,6 +743,61 @@
         } else {
             return null;
         }
+    }
+    
+    /**
+     * Returns the response body of the HTTP method, if any, as a {@link String}. 
+     * If response body is not available or cannot be read, returns <tt>null</tt>
+     * The string conversion on the data is done using the character encoding specified
+     * in <tt>Content-Type</tt> header.<p>
+     * 
+     * Note: This will cause the entire response body to be buffered in memory. This method is
+     * safe if the content length of the response is unknown, because the amount of memory used
+     * is limited.<p>
+     * 
+     * If the response is large this method involves lots of array copying and many object 
+     * allocations, which makes it unsuitable for high-performance / low-footprint applications.
+     * Those applications should use {@link #getResponseBodyAsStream()}.
+     * 
+     * @param maxlen the maximum content length to accept (number of bytes). Note that,
+     * depending on the encoding, this is not equal to the number of characters.
+     * @return The response body or <code>null</code>.
+     * 
+     * @throws IOException If an I/O (transport) problem occurs while obtaining the 
+     * response body.
+     */
+    public String getResponseBodyAsString(int maxlen) throws IOException {
+        if (maxlen < 0) throw new IllegalArgumentException("maxlen must be positive");
+        
+        // we might already know that the content is larger
+        long contentLength = getResponseContentLength();
+        if ((contentLength != -1) && (contentLength > maxlen)) {
+            throw new HttpContentTooLargeException("Content-Length is "+ contentLength, maxlen);
+        }
+        
+        LOG.debug("Buffering response body");
+        ByteArrayOutputStream rawdata = new ByteArrayOutputStream(
+                contentLength > 0 ? (int) contentLength : DEFAULT_INITIAL_BUFFER_SIZE);
+        InputStream in = getResponseBodyAsStream();
+        if (in == null) return null;
+        byte[] buffer = new byte[2048];
+        int pos = 0;
+        int len;
+        do {
+            len = in.read(buffer, 0, Math.min(buffer.length, maxlen-pos));
+            if (len == -1) break;
+            rawdata.write(buffer, 0, len);
+            pos += len;
+        } while (pos < maxlen);
+        
+        // check if there is even more data
+        if (pos == maxlen) {
+            if (in.read() != -1)
+                throw new HttpContentTooLargeException("Content-Length not known but larger than "
+                        + maxlen, maxlen);
+        }
+        
+        return EncodingUtil.getString(rawdata.toByteArray(), 0, pos, getResponseCharSet());
     }
 
     /**

Modified: jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestHttpMethodFundamentals.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestHttpMethodFundamentals.java?view=diff&rev=481225&r1=481224&r2=481225
==============================================================================
--- jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestHttpMethodFundamentals.java (original)
+++ jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestHttpMethodFundamentals.java Fri Dec  1 03:26:28 2006
@@ -249,6 +249,11 @@
             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
             String response = httpget.getResponseBodyAsString();
             assertNull(response);
+
+            this.client.executeMethod(httpget);
+            assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
+            response = httpget.getResponseBodyAsString(1);
+            assertNull(response);
         } finally {
             httpget.releaseConnection();
         }
@@ -264,6 +269,34 @@
             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
             byte[] response = httpget.getResponseBody();
             assertNull(response);
+        } finally {
+            httpget.releaseConnection();
+        }
+    }
+    
+    public void testLongBodyAsString() throws Exception {
+        this.server.setHttpService(new SimpleChunkedService());
+        
+        GetMethod httpget = new GetMethod("/test/");
+        try {
+            this.client.executeMethod(httpget);
+            assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
+            try {
+                httpget.getResponseBodyAsString(5); // too small
+            } catch(HttpContentTooLargeException e) {
+                /* expected */
+                assertEquals(5, e.getMaxLength());
+            }
+            
+            this.client.executeMethod(httpget);
+            assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
+            String response = httpget.getResponseBodyAsString(13); // exact size
+            assertEquals("1234567890123", response);
+
+            this.client.executeMethod(httpget);
+            assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
+            response = httpget.getResponseBodyAsString(128); // plenty
+            assertEquals("1234567890123", response);
         } finally {
             httpget.releaseConnection();
         }



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org