Index: java/org/apache/commons/httpclient/methods/ByteArrayRequestEntity.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/ByteArrayRequestEntity.java,v
retrieving revision 1.3
diff -u -r1.3 ByteArrayRequestEntity.java
--- java/org/apache/commons/httpclient/methods/ByteArrayRequestEntity.java 13 May 2004 02:26:08 -0000 1.3
+++ java/org/apache/commons/httpclient/methods/ByteArrayRequestEntity.java 26 Sep 2004 15:05:20 -0000
@@ -85,8 +85,8 @@
/* (non-Javadoc)
* @see org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream)
*/
- public void writeRequest(OutputStream out) throws IOException {
- out.write(content);
+ public int writeRequest(final OutputStream out, final Monitor monitor) throws IOException {
+ return EntityWriter.writeContent(this.content, out, monitor);
}
/**
Index: java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java,v
retrieving revision 1.39
diff -u -r1.39 EntityEnclosingMethod.java
--- java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java 3 Jul 2004 14:27:03 -0000 1.39
+++ java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java 26 Sep 2004 15:05:21 -0000
@@ -1,5 +1,5 @@
/*
- * $Header: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java,v 1.39 2004/07/03 14:27:03 olegk Exp $
+ * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java,v 1.39 2004/07/03 14:27:03 olegk Exp $
* $Revision: 1.39 $
* $Date: 2004/07/03 14:27:03 $
*
@@ -454,7 +454,7 @@
* @throws HttpException if a protocol exception occurs. Usually protocol exceptions
* cannot be recovered from.
*/
- protected boolean writeRequestBody(HttpState state, HttpConnection conn)
+ protected boolean writeRequestBody(final HttpState state, final HttpConnection conn)
throws IOException, HttpException {
LOG.trace(
"enter EntityEnclosingMethod.writeRequestBody(HttpState, HttpConnection)");
@@ -492,16 +492,37 @@
outstream = new ChunkedOutputStream(outstream);
}
- requestEntity.writeRequest(outstream);
+ RequestEntity.Monitor monitor = new RequestEntity.Monitor() {
+
+ public boolean isResponseAvailable() throws IOException {
+ return conn.isResponseAvailable();
+ }
+
+ };
+
+ // An HTTP/1.1 (or later) client sending a message-body SHOULD monitor
+ // the network connection for an error status while it is transmitting
+ // the request. If the client sees an error status, it SHOULD
+ // immediately cease transmitting the body. If the body is being sent
+ // using a "chunked" encoding (section 3.6), a zero length chunk and
+ // empty trailer MAY be used to prematurely mark the end of the message.
+ // If the body was preceded by a Content-Length header, the client MUST
+ // close the connection.
- // This is hardly the most elegant solution to closing chunked stream
+ int result = requestEntity.writeRequest(outstream, monitor);
+ // TODO: This is hardly the most elegant solution to closing chunked stream
+ // Consider a better solution
if (outstream instanceof ChunkedOutputStream) {
((ChunkedOutputStream) outstream).finish();
}
-
outstream.flush();
-
- LOG.debug("Request body sent");
+ if (result == RequestEntity.WRITE_COMPLETE) {
+ LOG.debug("Request body sent");
+ }
+ if (contentLength != CONTENT_LENGTH_CHUNKED && result == RequestEntity.WRITE_PARTIAL) {
+ LOG.debug("Request has not been fully sent");
+ setConnectionCloseForced(true);
+ }
return true;
}
Index: java/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java,v
retrieving revision 1.4
diff -u -r1.4 InputStreamRequestEntity.java
--- java/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java 17 May 2004 21:46:03 -0000 1.4
+++ java/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java 26 Sep 2004 15:05:22 -0000
@@ -1,5 +1,5 @@
/*
- * $Header: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java,v 1.4 2004/05/17 21:46:03 olegk Exp $
+ * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java,v 1.4 2004/05/17 21:46:03 olegk Exp $
* $Revision: 1.4 $
* $Date: 2004/05/17 21:46:03 $
*
@@ -164,18 +164,12 @@
/* (non-Javadoc)
* @see org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream)
*/
- public void writeRequest(OutputStream out) throws IOException {
+ public int writeRequest(final OutputStream out, final Monitor monitor) throws IOException {
- if (content != null) {
- byte[] tmp = new byte[4096];
- int total = 0;
- int i = 0;
- while ((i = content.read(tmp)) >= 0) {
- out.write(tmp, 0, i);
- total += i;
- }
- } else if (buffer != null) {
- out.write(buffer);
+ if (this.content != null) {
+ return EntityWriter.writeContent(this.content, out, monitor);
+ } else if (this.buffer != null) {
+ return EntityWriter.writeContent(this.buffer, out, monitor);
} else {
throw new IllegalStateException("Content must be set before entity is written");
}
Index: java/org/apache/commons/httpclient/methods/RequestEntity.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/RequestEntity.java,v
retrieving revision 1.4
diff -u -r1.4 RequestEntity.java
--- java/org/apache/commons/httpclient/methods/RequestEntity.java 17 May 2004 21:46:03 -0000 1.4
+++ java/org/apache/commons/httpclient/methods/RequestEntity.java 26 Sep 2004 15:05:22 -0000
@@ -1,5 +1,5 @@
/*
- * $Header: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/RequestEntity.java,v 1.4 2004/05/17 21:46:03 olegk Exp $
+ * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/RequestEntity.java,v 1.4 2004/05/17 21:46:03 olegk Exp $
* $Revision: 1.4 $
* $Date: 2004/05/17 21:46:03 $
*
@@ -37,6 +37,31 @@
*/
public interface RequestEntity {
+ public static int WRITE_COMPLETE = 0;
+
+ public static int WRITE_PARTIAL = -1;
+
+ /**
+ * As suggested in the HTTP/1.1 spec, the client sending a message-body SHOULD monitor
+ * the network connection for an error status while it is transmitting the request.
+ * If the client sees an error status, it SHOULD immediately cease transmitting the body.
+ *
+ * This interface defines a connection monitor for request entities.
+ */
+ public static interface Monitor {
+
+ /**
+ * Tests whether a response is already available.
+ *
+ * @return true is a response is already available,
+ * false otherwise.
+ *
+ * @throws IOException if an I/O error occurs
+ */
+ boolean isResponseAvailable() throws IOException;
+
+ }
+
/**
* Tests if {@link #writeRequest(OutputStream)} can be called more than once.
*
@@ -47,10 +72,16 @@
/**
* Writes the request entity to the given stream.
- * @param out
- * @throws IOException
+ * @param out output stream
+ * @param monitor connection monitor
+ *
+ * @return WRITE_COMPLETE is the request entity has been fully transmitted.
+ * WRITE_PARTIAL is the request entity has not been fully transmitted
+ * and the connection may need to be closed.
+ *
+ * @throws IOException if an I/O error occurs
*/
- void writeRequest(OutputStream out) throws IOException;
+ int writeRequest(OutputStream out, Monitor monitor) throws IOException;
/**
* Gets the request entity's length.
@@ -66,5 +97,5 @@
* @see org.apache.commons.httpclient.HttpMethod#setRequestHeader(String, String)
*/
String getContentType();
-
+
}
Index: java/org/apache/commons/httpclient/methods/StringRequestEntity.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/StringRequestEntity.java,v
retrieving revision 1.3
diff -u -r1.3 StringRequestEntity.java
--- java/org/apache/commons/httpclient/methods/StringRequestEntity.java 3 Jul 2004 14:27:03 -0000 1.3
+++ java/org/apache/commons/httpclient/methods/StringRequestEntity.java 26 Sep 2004 15:05:23 -0000
@@ -1,5 +1,5 @@
/*
- * $Header: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/StringRequestEntity.java,v 1.3 2004/07/03 14:27:03 olegk Exp $
+ * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/StringRequestEntity.java,v 1.3 2004/07/03 14:27:03 olegk Exp $
* $Revision: 1.3 $
* $Date: 2004/07/03 14:27:03 $
*
@@ -132,12 +132,8 @@
/* (non-Javadoc)
* @see org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream)
*/
- public void writeRequest(OutputStream out) throws IOException {
- if (out == null) {
- throw new IllegalArgumentException("Output stream may not be null");
- }
- out.write(this.content);
- out.flush();
+ public int writeRequest(final OutputStream out, Monitor monitor) throws IOException {
+ return EntityWriter.writeContent(this.content, out, monitor);
}
/**
Index: test/org/apache/commons/httpclient/TestMethodCharEncoding.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestMethodCharEncoding.java,v
retrieving revision 1.10
diff -u -r1.10 TestMethodCharEncoding.java
--- test/org/apache/commons/httpclient/TestMethodCharEncoding.java 3 Jul 2004 14:27:03 -0000 1.10
+++ test/org/apache/commons/httpclient/TestMethodCharEncoding.java 26 Sep 2004 15:05:24 -0000
@@ -170,8 +170,16 @@
assertNotNull("Request body", entity);
+ RequestEntity.Monitor monitor = new RequestEntity.Monitor() {
+
+ public boolean isResponseAvailable() throws IOException {
+ return false;
+ }
+
+ };
+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
- entity.writeRequest(bos);
+ entity.writeRequest(bos, monitor);
InputStream instream = new ByteArrayInputStream(bos.toByteArray());
for (int i = 0; i < sample.length; i++) {
@@ -258,8 +266,16 @@
httppost.setRequestHeader("Content-Type", PostMethod.FORM_URL_ENCODED_CONTENT_TYPE
+ "; charset=" + CHARSET_UTF8);
+ RequestEntity.Monitor monitor = new RequestEntity.Monitor() {
+
+ public boolean isResponseAvailable() throws IOException {
+ return false;
+ }
+
+ };
+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
- httppost.getRequestEntity().writeRequest(bos);
+ httppost.getRequestEntity().writeRequest(bos, monitor);
Map params = new HashMap();
StringTokenizer tokenizer = new StringTokenizer(
Index: test/org/apache/commons/httpclient/TestMethodsNoHost.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestMethodsNoHost.java,v
retrieving revision 1.23
diff -u -r1.23 TestMethodsNoHost.java
--- test/org/apache/commons/httpclient/TestMethodsNoHost.java 12 May 2004 20:43:54 -0000 1.23
+++ test/org/apache/commons/httpclient/TestMethodsNoHost.java 26 Sep 2004 15:05:25 -0000
@@ -1,5 +1,5 @@
/*
- * $Header: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestMethodsNoHost.java,v 1.23 2004/05/12 20:43:54 olegk Exp $
+ * $Header: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestMethodsNoHost.java,v 1.23 2004/05/12 20:43:54 olegk Exp $
* $Revision: 1.23 $
* $Date: 2004/05/12 20:43:54 $
* ====================================================================
@@ -31,6 +31,7 @@
package org.apache.commons.httpclient;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
@@ -77,8 +78,17 @@
// ----------------------------------------------------------------- Tests
private String getRequestAsString(RequestEntity entity) throws Exception {
+
+ RequestEntity.Monitor monitor = new RequestEntity.Monitor() {
+
+ public boolean isResponseAvailable() throws IOException {
+ return false;
+ }
+
+ };
+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
- entity.writeRequest(bos);
+ entity.writeRequest(bos, monitor);
return new String(bos.toByteArray(), "UTF-8");
}
Index: test/org/apache/commons/httpclient/TestWebappPostMethod.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestWebappPostMethod.java,v
retrieving revision 1.7
diff -u -r1.7 TestWebappPostMethod.java
--- test/org/apache/commons/httpclient/TestWebappPostMethod.java 12 May 2004 20:43:54 -0000 1.7
+++ test/org/apache/commons/httpclient/TestWebappPostMethod.java 26 Sep 2004 15:05:25 -0000
@@ -1,5 +1,5 @@
/*
- * $Header: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestWebappPostMethod.java,v 1.7 2004/05/12 20:43:54 olegk Exp $
+ * $Header: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestWebappPostMethod.java,v 1.7 2004/05/12 20:43:54 olegk Exp $
* $Revision: 1.7 $
* $Date: 2004/05/12 20:43:54 $
*
@@ -33,6 +33,7 @@
import junit.framework.*;
import org.apache.commons.httpclient.methods.*;
+
import java.io.*;
/**
@@ -177,8 +178,17 @@
}
private String getRequestAsString(RequestEntity entity) throws Exception {
+
+ RequestEntity.Monitor monitor = new RequestEntity.Monitor() {
+
+ public boolean isResponseAvailable() throws IOException {
+ return false;
+ }
+
+ };
+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
- entity.writeRequest(bos);
+ entity.writeRequest(bos, monitor);
return new String(bos.toByteArray(), "UTF-8");
}
Index: java/org/apache/commons/httpclient/methods/EntityWriter.java
===================================================================
RCS file: java/org/apache/commons/httpclient/methods/EntityWriter.java
diff -N java/org/apache/commons/httpclient/methods/EntityWriter.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ java/org/apache/commons/httpclient/methods/EntityWriter.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,99 @@
+/*
+ * $Header$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ *
+ * Copyright 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
+ * .
+ *
+ * [Additional notices, if required by prior licensing conditions]
+ *
+ */
+package org.apache.commons.httpclient.methods;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * @since 3.0
+ */
+public abstract class EntityWriter implements RequestEntity {
+
+ private EntityWriter() {
+ super();
+ }
+
+ public static int writeContent(final byte[] content,
+ final OutputStream out, Monitor monitor) throws IOException {
+ if (content == null) {
+ throw new IllegalArgumentException("Content may not be null");
+ }
+ if (out == null) {
+ throw new IllegalArgumentException("Output stream may not be null");
+ }
+ if (monitor == null) {
+ throw new IllegalArgumentException("Feedback interface may not be null");
+ }
+ int i = 0;
+ int remaining = content.length;
+ int chunk = 1024;
+ while (remaining > 0) {
+ if (monitor.isResponseAvailable()) {
+ return WRITE_PARTIAL;
+ }
+ if (remaining < 1024) {
+ chunk = remaining;
+ } else {
+ chunk = 1024;
+ }
+ out.write(content, i, chunk);
+ i += chunk;
+ remaining -= chunk;
+ }
+ out.flush();
+ return WRITE_COMPLETE;
+ }
+
+ public static int writeContent(final InputStream in,
+ final OutputStream out, Monitor monitor) throws IOException {
+ if (in == null) {
+ throw new IllegalArgumentException("Input stream may not be null");
+ }
+ if (out == null) {
+ throw new IllegalArgumentException("Output stream may not be null");
+ }
+ if (monitor == null) {
+ throw new IllegalArgumentException("Feedback interface may not be null");
+ }
+ byte[] tmp = new byte[1024];
+ int i = 0;
+ while ((i = in.read(tmp)) >= 0) {
+ if (monitor.isResponseAvailable()) {
+ return WRITE_PARTIAL;
+ }
+ out.write(tmp, 0, i);
+ }
+ out.flush();
+ return WRITE_COMPLETE;
+ }
+}