Index: C:/Documents and Settings/Ortwin/My Documents/code/HttpClient-3.1/src/java/org/apache/commons/httpclient/HttpContentTooLargeException.java
===================================================================
--- C:/Documents and Settings/Ortwin/My Documents/code/HttpClient-3.1/src/java/org/apache/commons/httpclient/HttpContentTooLargeException.java (revision 0)
+++ C:/Documents and Settings/Ortwin/My Documents/code/HttpClient-3.1/src/java/org/apache/commons/httpclient/HttpContentTooLargeException.java (revision 0)
@@ -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;
+ }
+}
Index: C:/Documents and Settings/Ortwin/My Documents/code/HttpClient-3.1/src/java/org/apache/commons/httpclient/HttpMethodBase.java
===================================================================
--- C:/Documents and Settings/Ortwin/My Documents/code/HttpClient-3.1/src/java/org/apache/commons/httpclient/HttpMethodBase.java (revision 478198)
+++ C:/Documents and Settings/Ortwin/My Documents/code/HttpClient-3.1/src/java/org/apache/commons/httpclient/HttpMethodBase.java (working copy)
@@ -33,7 +33,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;
@@ -697,7 +699,7 @@
* Returns the response body of the HTTP method, if any, as an {@link InputStream}.
* If response body is not available, returns null
*
- * @return The response body
+ * @return The response body or null.
*
* @throws IOException If an I/O (transport) problem occurs while obtaining the
* response body.
@@ -725,7 +727,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 null.
*
* @throws IOException If an I/O (transport) problem occurs while obtaining the
* response body.
@@ -741,6 +743,59 @@
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 null
+ * The string conversion on the data is done using the character encoding specified
+ * in Content-Type header.
+ * + * 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.
+ *
+ * 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 null.
+ *
+ * @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);
+ }
+
+ ByteArrayOutputStream rawdata = new ByteArrayOutputStream();
+ 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());
+ }
/**
* Returns an array of the response footers that the HTTP method currently has
Index: C:/Documents and Settings/Ortwin/My Documents/code/HttpClient-3.1/src/test/org/apache/commons/httpclient/TestHttpMethodFundamentals.java
===================================================================
--- C:/Documents and Settings/Ortwin/My Documents/code/HttpClient-3.1/src/test/org/apache/commons/httpclient/TestHttpMethodFundamentals.java (revision 478198)
+++ C:/Documents and Settings/Ortwin/My Documents/code/HttpClient-3.1/src/test/org/apache/commons/httpclient/TestHttpMethodFundamentals.java (working copy)
@@ -248,6 +248,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();
}
@@ -268,6 +273,34 @@
}
}
+ 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();
+ }
+ }
+
public void testUrlGetMethodWithPathQuery() {
GetMethod method = new GetMethod("http://www.fubar.com/path1/path2?query=string");
try {