Index: trunk/http-core/src/java/org/apache/http/protocol/HttpRequestExecutor.java
===================================================================
--- trunk/http-core/src/java/org/apache/http/protocol/HttpRequestExecutor.java (revision 380929)
+++ trunk/http-core/src/java/org/apache/http/protocol/HttpRequestExecutor.java (working copy)
@@ -45,8 +45,13 @@
/**
* Sends HTTP requests and receives the responses.
- * Takes care of request preprocessing and response postprocessing
- * by the respective interceptors.
+ * Applications typically call the {@link #execute execute} method,
+ * which takes care of all the necessary steps.
+ *
+ * The doXxx methods implement the individual steps in
+ * executing a request, like preprocessing of the request and
+ * postprocessing of the response by the respective interceptors.
+ * Those methods are typically not used directly by an application.
*
* @author Oleg Kalnichevski
*
@@ -159,6 +164,9 @@
/**
* Synchronously send a request and obtain the response.
+ * This method uses the {@link #getParams parameters} and
+ * {@link #getContext context} stored in this request executor.
+ * It is therefore not thread safe.
*
* @param request the request to send. It will be preprocessed.
* @param conn the connection over which to send.
@@ -182,12 +190,12 @@
}
//@@@ behavior if proxying - set real target or proxy, or both?
- this.defaultContext.setAttribute(HttpExecutionContext.HTTP_TARGET_HOST,
+ this.defaultContext.setAttribute(HttpExecutionContext.HTTP_TARGET_HOST,
conn.getTargetHost());
this.defaultContext.setAttribute(HttpExecutionContext.HTTP_CONNECTION,
conn);
- prepareRequest(request, this.defaultContext);
+ doPrepareRequest(request, this.defaultContext);
this.defaultContext.setAttribute(HttpExecutionContext.HTTP_REQUEST,
request);
@@ -197,10 +205,12 @@
// returns false or a non-recoverable exception is thrown
for (int execCount = 0; ; execCount++) {
try {
- establishConnection(conn, conn.getTargetHost(), request.getParams());
- response = sendRequest(request, conn, this.defaultContext);
+ doEstablishConnection(conn, conn.getTargetHost(),
+ request.getParams());
+ response = doSendRequest(request, conn, this.defaultContext);
if (response == null) {
- response = receiveResponse(request, conn, this.defaultContext);
+ response = doReceiveResponse(request, conn,
+ this.defaultContext);
}
// exit retry loop
break;
@@ -221,7 +231,7 @@
}
}
- finishResponse(response, this.defaultContext);
+ doFinishResponse(response, this.defaultContext);
return response;
@@ -229,6 +239,12 @@
/**
* Prepare a request for sending.
+ * This method is typically not called by an application directly.
+ * Use {@link #execute execute} instead.
+ *
+ * This method may be called by several threads simultaneously,
+ * but the {@link #getParams parameters} and request interceptors
+ * MUST NOT be modified concurrently.
*
* @param request the request to prepare
* @param context the context for sending the request
@@ -236,7 +252,7 @@
* @throws HttpException in case of a protocol or processing problem
* @throws IOException in case of an I/O problem
*/
- protected void prepareRequest(
+ public void doPrepareRequest(
final HttpRequest request,
final HttpContext context)
throws HttpException, IOException {
@@ -253,6 +269,10 @@
/**
* Establish a connection with the target host.
+ * This method is typically not called by an application directly.
+ * Use {@link #execute execute} instead.
+ *
+ * This method may be called by several threads simultaneously.
*
* @param conn the HTTP connection
* @param target the target host for the request, or
@@ -262,7 +282,7 @@
* @throws HttpException in case of a problem
* @throws IOException in case of an IO problem
*/
- protected void establishConnection(
+ public void doEstablishConnection(
final HttpClientConnection conn,
final HttpHost target,
final HttpParams params)
@@ -302,22 +322,30 @@
/**
* Send a request over a connection.
- * This method also handles the expect-continue handshake, if requested.
+ * This method is typically not called by an application directly.
+ * Use {@link #execute execute} instead.
+ *
+ * This method handles the expect-continue handshake if necessary.
+ * If it does not have to handle an expect-continue handshake, it will
+ * not use the connection for reading or anything else that depends on
+ * data coming in over the connection.
+ *
+ * This method is thread safe.
*
* @param request the request to send, already
- * {@link #prepareRequest prepared}
+ * {@link #doPrepareRequest prepared}
* @param conn the connection over which to send the request, already
- * {@link #establishConnection established}
+ * {@link #doEstablishConnection established}
* @param context the context for sending the request
*
* @return a terminal response received as part of an expect-continue
- * handshake or null if the expect-continue handshake
- * is not used.
+ * handshake, or
+ * null if the expect-continue handshake is not used
*
* @throws HttpException in case of a protocol or processing problem
* @throws IOException in case of an I/O problem
*/
- protected HttpResponse sendRequest(
+ public HttpResponse doSendRequest(
final HttpRequest request,
final HttpClientConnection conn,
final HttpContext context)
@@ -337,14 +365,16 @@
conn.sendRequestHeader(request);
if (request instanceof HttpEntityEnclosingRequest) {
- HttpEntityEnclosingRequest entityEnclRequest = (HttpEntityEnclosingRequest) request;
+ HttpEntityEnclosingRequest entityEnclRequest =
+ (HttpEntityEnclosingRequest) request;
// Check for expect-continue handshake. We have to flush the
// headers and wait for an 100-continue response to handle it.
// If we get a different response, we must not send the entity.
boolean sendentity = true;
final HttpVersion ver = request.getRequestLine().getHttpVersion();
- if (entityEnclRequest.expectContinue() && ver.greaterEquals(HttpVersion.HTTP_1_1)) {
+ if (entityEnclRequest.expectContinue() &&
+ ver.greaterEquals(HttpVersion.HTTP_1_1)) {
conn.flush();
// As suggested by RFC 2616 section 8.2.3, we don't wait for a
@@ -377,17 +407,23 @@
/**
* Wait for and receive a response.
+ * This method is typically not called by an application directly.
+ * Use {@link #execute execute} instead.
+ *
+ * This method will automatically ignore intermediate responses
+ * with status code 1xx.
+ * It is thread safe.
*
* @param request the request for which to obtain the response
* @param conn the connection over which the request was sent
* @param context the context for receiving the response
*
- * @return the response, not yet post-processed
+ * @return the final response, not yet post-processed
*
* @throws HttpException in case of a protocol or processing problem
* @throws IOException in case of an I/O problem
*/
- protected HttpResponse receiveResponse(
+ public HttpResponse doReceiveResponse(
final HttpRequest request,
final HttpClientConnection conn,
final HttpContext context)
@@ -401,7 +437,7 @@
if (context == null) {
throw new IllegalArgumentException("HTTP context may not be null");
}
- // see HttpRequestExecutor.doExecute, final part
+
HttpResponse response = null;
int statuscode = 0;
@@ -417,14 +453,20 @@
return response;
- } // obtainResponse
+ }
/**
* Finish a response.
- * This includes post-processing of the response object.
+ * This method is typically not called by an application directly.
+ * Use {@link #execute execute} instead.
+ *
+ * This method performs post-processing of the response object.
* It does not read the response entity, if any.
* It does not allow for immediate re-use of the
* connection over which the response is coming in.
+ *
+ * This method may be called by several threads simultaneously,
+ * but the response interceptors MUST NOT be modified concurrently.
*
* @param response the response object to finish
* @param context the context for post-processing the response
@@ -432,7 +474,7 @@
* @throws HttpException in case of a protocol or processing problem
* @throws IOException in case of an I/O problem
*/
- protected void finishResponse(
+ public void doFinishResponse(
final HttpResponse response,
final HttpContext context)
throws HttpException, IOException {
Index: trunk/http-async/src/java/org/apache/http/async/impl/SimpleHttpDispatcher.java
===================================================================
--- trunk/http-async/src/java/org/apache/http/async/impl/SimpleHttpDispatcher.java (revision 380929)
+++ trunk/http-async/src/java/org/apache/http/async/impl/SimpleHttpDispatcher.java (working copy)
@@ -43,9 +43,9 @@
import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.HttpException;
import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpRequestExecutor;
import org.apache.http.async.HttpHandle;
import org.apache.http.async.HttpDispatcher;
-import org.apache.http.async.AsyncHttpProcessor;
import org.apache.http.async.AbstractHttpHandle;
import org.apache.http.async.AbstractHttpDispatcher;
@@ -73,16 +73,17 @@
public class SimpleHttpDispatcher extends AbstractHttpDispatcher
implements HttpDispatcher {
// @@@ move some of this stuff to an abstract base class?
- // @@@ the AsyncHttpProcessor and getDefaultContext method, for example
+ // @@@ the HttpRequestExecutor and getDefaultContext method, for example
/** The one and only connection. */
private final HttpClientConnection client_connection;
/**
- * The HTTP processor.
+ * The underlying request executor.
* For pre- and postprocessing of requests and responses, respectively.
+ * Also holds the default context and HTTP parameters.
*/
- protected final AsyncHttpProcessor async_processor;
+ protected final HttpRequestExecutor request_executor;
/** The connection re-use strategy. */
private ConnectionReuseStrategy reuse_strategy;
@@ -120,23 +121,25 @@
* Create a new simple HTTP dispatcher.
*
* @param conn the connection to use
- * @param proc the HTTP processor to use,
- * including the default context
+ * @param reqexec the request executor to use,
+ * including the default context and params
* @param reuse the strategy for re-using connections, or
* null to disable connection re-use
*/
public SimpleHttpDispatcher(HttpClientConnection conn,
- AsyncHttpProcessor proc,
+ HttpRequestExecutor reqexec,
ConnectionReuseStrategy reuse) {
super(null);
if (conn == null)
- throw new IllegalArgumentException("connection must not be null");
- if (proc == null)
- throw new IllegalArgumentException("processor must not be null");
+ throw new IllegalArgumentException
+ ("connection must not be null");
+ if (reqexec == null)
+ throw new IllegalArgumentException
+ ("request executor must not be null");
client_connection = conn;
- async_processor = proc;
+ request_executor = reqexec;
reuse_strategy = reuse;
request_handle_queue = new LinkedList();
@@ -172,7 +175,7 @@
//@@@ - for now: no proxy (how to indicate proxy in the first place?)
HttpContext ctxt = prepareRequest
- (async_processor, request, target, context);
+ (request_executor, request, target, context);
SimpleHttpHandle hdl = new SimpleHttpHandle(this, request, ctxt);
// linked handles need to be tracked for abortAll()
@@ -206,7 +209,7 @@
throw new IllegalArgumentException("response must not be null");
handle.checkDispatcher(this);
- finishResponse(async_processor, response, handle.getContext());
+ finishResponse(request_executor, response, handle.getContext());
} // postprocessResponse
@@ -215,7 +218,7 @@
// non-javadoc, see interface HttpDispatcher
public final HttpContext getDefaultContext() {
- return async_processor.getContext();
+ return request_executor.getContext();
}
@@ -380,14 +383,14 @@
}
//@@@ TODO: retry handling!
- transmitRequest(async_processor,
+ transmitRequest(request_executor,
handle.getRequest(),
handle.getContext(),
client_connection);
//@@@ TODO: timeout handling!
HttpResponse response =
- obtainResponse(async_processor,
+ obtainResponse(request_executor,
handle.getRequest(),
handle.getContext(),
client_connection);
Index: trunk/http-async/src/java/org/apache/http/async/AbstractHttpDispatcher.java
===================================================================
--- trunk/http-async/src/java/org/apache/http/async/AbstractHttpDispatcher.java (revision 380929)
+++ trunk/http-async/src/java/org/apache/http/async/AbstractHttpDispatcher.java (working copy)
@@ -34,16 +34,19 @@
import java.util.LinkedList;
import org.apache.http.HttpClientConnection;
+import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
+import org.apache.http.ProtocolException;
import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpExecutionContext;
+import org.apache.http.protocol.HttpRequestExecutor;
+
/**
* Abstract base for implementations of {@link HttpDispatcher HttpDispatcher}.
- * Provides access to protected methods in
- * {@link AsyncHttpProcessor AsyncHttpProcessor}.
*
* @version $Revision$ $Date$
*
@@ -118,9 +121,8 @@
/**
* Prepare a request for sending.
- * Maps to {@link AsyncHttpProcessor#prepareRequest proc.prepareRequest}.
*
- * @param proc the processor to use for preparing
+ * @param hrx the request executor to use for preparing
* @param request the request to prepare
* @param target the target host for the request
* @param context the parent context for sending the request,
@@ -131,22 +133,32 @@
* @throws HttpException if the request can not be prepared
* @throws IOException in case of an IO problem
*/
- protected static HttpContext prepareRequest(AsyncHttpProcessor proc,
- HttpRequest request,
- HttpHost target,
- HttpContext context)
+ protected static HttpContext prepareRequest(HttpRequestExecutor hrx,
+ HttpRequest request,
+ HttpHost target,
+ HttpContext context)
throws HttpException, IOException {
- return proc.prepareRequest(request, target, context);
+ HttpExecutionContext hxc = new HttpExecutionContext(context);
+ hxc.setAttribute(HttpExecutionContext.HTTP_TARGET_HOST,
+ target);
+
+ // argument checking is done here...
+ hrx.doPrepareRequest(request, hxc);
+
+ hxc.setAttribute(HttpExecutionContext.HTTP_REQUEST,
+ request);
+
+ return hxc;
+
} // prepareRequest
/**
- * Send a request.
- * Maps to {@link AsyncHttpProcessor#transmitRequest proc.transmitRequest}.
+ * Establishe a connection and send a request.
*
- * @param proc the processor to use for transmission
+ * @param hrx the request executor to use for preparing
* @param request the request to send, already prepared
* @param context the request specific context returned by
* {@link #prepareRequest prepareRequest}
@@ -156,22 +168,45 @@
* @throws HttpException in case of a problem
* @throws IOException in case of an IO problem
*/
- protected static void transmitRequest(AsyncHttpProcessor proc,
+ protected static void transmitRequest(HttpRequestExecutor hrx,
HttpRequest request,
HttpContext context,
HttpClientConnection connection)
throws HttpException, IOException {
- proc.transmitRequest(request, context, connection);
+ if (request == null)
+ throw new IllegalArgumentException("request must not be null");
+ if (context == null)
+ throw new IllegalArgumentException("context must not be null");
+ if (connection == null)
+ throw new IllegalArgumentException("connection must not be null");
+ HttpHost target = (HttpHost)
+ context.getAttribute(HttpExecutionContext.HTTP_TARGET_HOST);
+ if (target == null) {
+ throw new IllegalStateException
+ ("target host missing in request context");
+ }
+ if (request instanceof HttpEntityEnclosingRequest
+ && ((HttpEntityEnclosingRequest)request).expectContinue()) {
+ throw new ProtocolException
+ ("expect-continue handshake not supported");
+ }
+
+ hrx.doEstablishConnection(connection, target, request.getParams());
+
+ context.setAttribute(HttpExecutionContext.HTTP_CONNECTION,
+ connection);
+
+ hrx.doSendRequest(request, connection, context);
+
} // transmitRequest
/**
* Wait for and receive a response.
- * Maps to {@link AsyncHttpProcessor#obtainResponse proc.obtainResponse}.
*
- * @param proc the processor to use for transmission
+ * @param hrx the request executor to use for preparing
* @param request the request for which to obtain the response
* @param connection the connection over which the request was sent
*
@@ -181,21 +216,21 @@
* @throws IOException in case of an IO problem
*/
protected static
- HttpResponse obtainResponse(AsyncHttpProcessor proc,
- HttpRequest request,
- HttpContext context,
- HttpClientConnection connection)
+ HttpResponse obtainResponse(HttpRequestExecutor hrx,
+ HttpRequest request,
+ HttpContext context,
+ HttpClientConnection connection)
throws HttpException, IOException {
- return proc.obtainResponse(request, context, connection);
+ return hrx.doReceiveResponse(request, connection, context);
} // obtainResponse
/**
* Finish a response.
- * Maps to {@link AsyncHttpProcessor#finishResponse proc.finishResponse}.
*
+ * @param hrx the request executor to use for preparing
* @param response the response object to finish
* @param context the context obtained from
* {@link #prepareRequest prepareRequest}
@@ -204,12 +239,12 @@
* @throws HttpException in case of a problem
* @throws IOException in case of an IO problem
*/
- protected static void finishResponse(AsyncHttpProcessor proc,
- HttpResponse response,
- HttpContext context)
+ protected static void finishResponse(HttpRequestExecutor hrx,
+ HttpResponse response,
+ HttpContext context)
throws HttpException, IOException {
- proc.finishResponse(response, context);
+ hrx.doFinishResponse(response, context);
} // finishResponse
Index: trunk/http-async/src/examples/org/apache/http/examples/ElementalAsyncGet.java
===================================================================
--- trunk/http-async/src/examples/org/apache/http/examples/ElementalAsyncGet.java (revision 380929)
+++ trunk/http-async/src/examples/org/apache/http/examples/ElementalAsyncGet.java (working copy)
@@ -46,8 +46,8 @@
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.async.HttpDispatcher;
import org.apache.http.async.HttpHandle;
-import org.apache.http.async.AsyncHttpProcessor;
import org.apache.http.async.impl.SimpleHttpDispatcher;
+import org.apache.http.protocol.HttpRequestExecutor;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestTargetHost;
@@ -158,19 +158,19 @@
HttpClientConnection conn = new DefaultHttpClientConnection();
- AsyncHttpProcessor proc = new AsyncHttpProcessor();
- proc.setParams(params);
+ HttpRequestExecutor hrx = new HttpRequestExecutor();
+ hrx.setParams(params);
// Required request interceptors
- proc.addInterceptor(new RequestContent());
- proc.addInterceptor(new RequestTargetHost());
+ hrx.addInterceptor(new RequestContent());
+ hrx.addInterceptor(new RequestTargetHost());
// Recommended request interceptors
- proc.addInterceptor(new RequestConnControl());
- proc.addInterceptor(new RequestUserAgent());
- // not supported: proc.addInterceptor(new RequestExpectContinue());
+ hrx.addInterceptor(new RequestConnControl());
+ hrx.addInterceptor(new RequestUserAgent());
+ // not supported: hrx.addInterceptor(new RequestExpectContinue());
ConnectionReuseStrategy crs = new DefaultConnectionReuseStrategy();
- HttpDispatcher hdp = new SimpleHttpDispatcher(conn, proc, crs);
+ HttpDispatcher hdp = new SimpleHttpDispatcher(conn, hrx, crs);
return hdp;