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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] #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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]