Index: module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java
===================================================================
--- module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java (revision 630309)
+++ module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java (working copy)
@@ -50,7 +50,6 @@
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
-import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
@@ -202,7 +201,7 @@
}
private NHttpClientHandler createHttpClientHandler(
- final HttpRequestExecutionHandler requestExecutionHandler) {
+ final NHttpRequestExecutionHandler requestExecutionHandler) {
BasicHttpProcessor httpproc = new BasicHttpProcessor();
httpproc.addInterceptor(new RequestContent());
httpproc.addInterceptor(new RequestTargetHost());
@@ -210,7 +209,7 @@
httpproc.addInterceptor(new RequestUserAgent());
httpproc.addInterceptor(new RequestExpectContinue());
- BufferingHttpClientHandler clientHandler = new BufferingHttpClientHandler(
+ AsyncNHttpClientHandler clientHandler = new AsyncNHttpClientHandler(
httpproc,
requestExecutionHandler,
new DefaultConnectionReuseStrategy(),
@@ -262,7 +261,7 @@
};
- HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+ NHttpRequestExecutionHandler requestExecutionHandler = new NHttpRequestExecutionHandler() {
public void initalizeContext(final HttpContext context, final Object attachment) {
context.setAttribute("LIST", (ByteSequence) attachment);
@@ -282,6 +281,13 @@
}
return get;
}
+
+ @Override
+ public ConsumingNHttpEntity responseEntity(HttpRequest request,
+ HttpResponse response, HttpContext context)
+ throws IOException {
+ return new BufferingNHttpEntity(response.getEntity(), new HeapByteBufferAllocator());
+ }
public void handleResponse(final HttpResponse response, final HttpContext context) {
NHttpConnection conn = (NHttpConnection) context.getAttribute(
@@ -394,7 +400,7 @@
}
};
- HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+ NHttpRequestExecutionHandler requestExecutionHandler = new NHttpRequestExecutionHandler() {
public void initalizeContext(final HttpContext context, final Object attachment) {
context.setAttribute("LIST", (ByteSequence) attachment);
@@ -404,6 +410,13 @@
public void finalizeContext(final HttpContext context) {
}
+
+ @Override
+ public ConsumingNHttpEntity responseEntity(HttpRequest request,
+ HttpResponse response, HttpContext context)
+ throws IOException {
+ return new BufferingNHttpEntity(response.getEntity(), new HeapByteBufferAllocator());
+ }
public HttpRequest submitRequest(final HttpContext context) {
int i = ((Integer) context.getAttribute("REQ-COUNT")).intValue();
@@ -412,7 +425,7 @@
post = new BasicHttpEntityEnclosingRequest("POST", "/?" + i);
byte[] data = requestData.getBytes(i);
- ByteArrayEntity outgoing = new ByteArrayEntity(data);
+ NByteArrayEntity outgoing = new NByteArrayEntity(data);
post.setEntity(outgoing);
context.setAttribute("REQ-COUNT", new Integer(i + 1));
@@ -533,7 +546,7 @@
}
};
- HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+ NHttpRequestExecutionHandler requestExecutionHandler = new NHttpRequestExecutionHandler() {
public void initalizeContext(final HttpContext context, final Object attachment) {
context.setAttribute("LIST", (ByteSequence) attachment);
@@ -543,6 +556,13 @@
public void finalizeContext(final HttpContext context) {
}
+
+ @Override
+ public ConsumingNHttpEntity responseEntity(HttpRequest request,
+ HttpResponse response, HttpContext context)
+ throws IOException {
+ return new BufferingNHttpEntity(response.getEntity(), new HeapByteBufferAllocator());
+ }
public HttpRequest submitRequest(final HttpContext context) {
int i = ((Integer) context.getAttribute("REQ-COUNT")).intValue();
@@ -550,7 +570,7 @@
if (i < reqNo) {
post = new BasicHttpEntityEnclosingRequest("POST", "/?" + i);
byte[] data = requestData.getBytes(i);
- ByteArrayEntity outgoing = new ByteArrayEntity(data);
+ NByteArrayEntity outgoing = new NByteArrayEntity(data);
outgoing.setChunked(true);
post.setEntity(outgoing);
@@ -679,7 +699,7 @@
this.client.getParams().setParameter(
CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_0);
- HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+ NHttpRequestExecutionHandler requestExecutionHandler = new NHttpRequestExecutionHandler() {
public void initalizeContext(final HttpContext context, final Object attachment) {
context.setAttribute("LIST", (ByteSequence) attachment);
@@ -690,13 +710,20 @@
public void finalizeContext(final HttpContext context) {
}
+ @Override
+ public ConsumingNHttpEntity responseEntity(HttpRequest request,
+ HttpResponse response, HttpContext context)
+ throws IOException {
+ return new BufferingNHttpEntity(response.getEntity(), new HeapByteBufferAllocator());
+ }
+
public HttpRequest submitRequest(final HttpContext context) {
int i = ((Integer) context.getAttribute("REQ-COUNT")).intValue();
BasicHttpEntityEnclosingRequest post = null;
if (i < reqNo) {
post = new BasicHttpEntityEnclosingRequest("POST", "/?" + i);
byte[] data = requestData.getBytes(i);
- ByteArrayEntity outgoing = new ByteArrayEntity(data);
+ NByteArrayEntity outgoing = new NByteArrayEntity(data);
post.setEntity(outgoing);
context.setAttribute("REQ-COUNT", new Integer(i + 1));
@@ -820,7 +847,7 @@
// Activate 'expect: continue' handshake
this.client.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, true);
- HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+ NHttpRequestExecutionHandler requestExecutionHandler = new NHttpRequestExecutionHandler() {
public void initalizeContext(final HttpContext context, final Object attachment) {
context.setAttribute("LIST", (ByteSequence) attachment);
@@ -830,6 +857,13 @@
public void finalizeContext(final HttpContext context) {
}
+
+ @Override
+ public ConsumingNHttpEntity responseEntity(HttpRequest request,
+ HttpResponse response, HttpContext context)
+ throws IOException {
+ return new BufferingNHttpEntity(response.getEntity(), new HeapByteBufferAllocator());
+ }
public HttpRequest submitRequest(final HttpContext context) {
int i = ((Integer) context.getAttribute("REQ-COUNT")).intValue();
@@ -837,7 +871,7 @@
if (i < reqNo) {
post = new BasicHttpEntityEnclosingRequest("POST", "/?" + i);
byte[] data = requestData.getBytes(i);
- ByteArrayEntity outgoing = new ByteArrayEntity(data);
+ NByteArrayEntity outgoing = new NByteArrayEntity(data);
outgoing.setChunked(true);
post.setEntity(outgoing);
@@ -973,7 +1007,7 @@
// Activate 'expect: continue' handshake
this.client.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, true);
- HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+ NHttpRequestExecutionHandler requestExecutionHandler = new NHttpRequestExecutionHandler() {
public void initalizeContext(final HttpContext context, final Object attachment) {
context.setAttribute("LIST", (ResponseSequence) attachment);
@@ -983,6 +1017,13 @@
public void finalizeContext(final HttpContext context) {
}
+
+ @Override
+ public ConsumingNHttpEntity responseEntity(HttpRequest request,
+ HttpResponse response, HttpContext context)
+ throws IOException {
+ return new BufferingNHttpEntity(response.getEntity(), new HeapByteBufferAllocator());
+ }
public HttpRequest submitRequest(final HttpContext context) {
int i = ((Integer) context.getAttribute("REQ-COUNT")).intValue();
@@ -990,7 +1031,7 @@
if (i < reqNo) {
post = new BasicHttpEntityEnclosingRequest("POST", "/");
post.addHeader("Secret", Integer.toString(i));
- ByteArrayEntity outgoing = new ByteArrayEntity(
+ NByteArrayEntity outgoing = new NByteArrayEntity(
EncodingUtils.getAsciiBytes("No content"));
post.setEntity(outgoing);
@@ -1011,7 +1052,7 @@
HttpEntity entity = response.getEntity();
if (entity != null) {
try {
- entity.consumeContent();
+ EntityUtils.toByteArray(entity);
} catch (IOException ex) {
requestCount.abort();
return;
@@ -1112,7 +1153,7 @@
};
- HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+ NHttpRequestExecutionHandler requestExecutionHandler = new NHttpRequestExecutionHandler() {
public void initalizeContext(final HttpContext context, final Object attachment) {
context.setAttribute("LIST", (ResponseSequence) attachment);
@@ -1122,6 +1163,13 @@
public void finalizeContext(final HttpContext context) {
}
+
+ @Override
+ public ConsumingNHttpEntity responseEntity(HttpRequest request,
+ HttpResponse response, HttpContext context)
+ throws IOException {
+ return new BufferingNHttpEntity(response.getEntity(), new HeapByteBufferAllocator());
+ }
public HttpRequest submitRequest(final HttpContext context) {
int i = ((Integer) context.getAttribute("REQ-COUNT")).intValue();
Index: module-nio/src/main/java/org/apache/http/nio/protocol/AbstractNHttpClientHandler.java
===================================================================
--- module-nio/src/main/java/org/apache/http/nio/protocol/AbstractNHttpClientHandler.java (revision 0)
+++ module-nio/src/main/java/org/apache/http/nio/protocol/AbstractNHttpClientHandler.java (revision 0)
@@ -0,0 +1,75 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpClientHandlerBase.java $
+ * $Revision: 547966 $
+ * $Date: 2007-06-16 15:26:21 -0400 (Sat, 16 Jun 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ * .
+ *
+ */
+
+package org.apache.http.nio.protocol;
+
+import java.io.IOException;
+
+import org.apache.http.ConnectionReuseStrategy;
+import org.apache.http.HttpException;
+import org.apache.http.nio.NHttpClientConnection;
+import org.apache.http.nio.NHttpClientHandler;
+import org.apache.http.nio.util.ByteBufferAllocator;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpProcessor;
+
+public abstract class AbstractNHttpClientHandler extends NHttpHandlerBase
+ implements NHttpClientHandler {
+
+ public AbstractNHttpClientHandler(
+ final HttpProcessor httpProcessor,
+ final ConnectionReuseStrategy connStrategy,
+ final ByteBufferAllocator allocator,
+ final HttpParams params) {
+ super(httpProcessor, connStrategy, allocator, params);
+ }
+
+ public void closed(final NHttpClientConnection conn) {
+ if (this.eventListener != null) {
+ this.eventListener.connectionClosed(conn);
+ }
+ }
+
+ public void exception(final NHttpClientConnection conn, final HttpException ex) {
+ closeConnection(conn, ex);
+ if (this.eventListener != null) {
+ this.eventListener.fatalProtocolException(ex, conn);
+ }
+ }
+
+ public void exception(final NHttpClientConnection conn, final IOException ex) {
+ shutdownConnection(conn, ex);
+ if (this.eventListener != null) {
+ this.eventListener.fatalIOException(ex, conn);
+ }
+ }
+
+}
Property changes on: module-nio/src/main/java/org/apache/http/nio/protocol/AbstractNHttpClientHandler.java
___________________________________________________________________
Name: svn:executable
+ *
Index: module-nio/src/main/java/org/apache/http/nio/protocol/NHttpClientHandlerBase.java
===================================================================
--- module-nio/src/main/java/org/apache/http/nio/protocol/NHttpClientHandlerBase.java (revision 630309)
+++ module-nio/src/main/java/org/apache/http/nio/protocol/NHttpClientHandlerBase.java (working copy)
@@ -36,13 +36,11 @@
import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.HttpException;
import org.apache.http.nio.NHttpClientConnection;
-import org.apache.http.nio.NHttpClientHandler;
import org.apache.http.nio.util.ByteBufferAllocator;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpProcessor;
-public abstract class NHttpClientHandlerBase extends NHttpHandlerBase
- implements NHttpClientHandler {
+public abstract class NHttpClientHandlerBase extends AbstractNHttpClientHandler {
protected HttpRequestExecutionHandler execHandler;
Index: module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestExecutionHandler.java
===================================================================
--- module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestExecutionHandler.java (revision 0)
+++ module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestExecutionHandler.java (revision 0)
@@ -0,0 +1,132 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/HttpRequestExecutionHandler.java $
+ * $Revision: 613298 $
+ * $Date: 2008-01-18 17:09:22 -0500 (Fri, 18 Jan 2008) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ * .
+ *
+ */
+
+package org.apache.http.nio.protocol;
+
+import java.io.IOException;
+
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.nio.entity.ConsumingNHttpEntity;
+import org.apache.http.nio.entity.ProducingNHttpEntity;
+import org.apache.http.nio.reactor.ConnectingIOReactor;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * HTTP request execution handler can be used by client-side protocol handlers
+ * to trigger the submission of a new HTTP request and the processing of an HTTP
+ * response. When a new response entity is available for consumption,
+ * {@link #responseEntity(HttpRequest, HttpResponse, HttpContext)} is called.
+ * After the {@link ConsumingNHttpEntity} consumes the response body,
+ * {@link #handleResponse(HttpResponse, HttpContext)} is notified that the
+ * response is fully read.
+ *
+ * @author Oleg Kalnichevski
+ *
+ */
+public interface NHttpRequestExecutionHandler {
+
+ /**
+ * Triggered when a new connection has been established and the
+ * HTTP context needs to be initialized.
+ *
+ *
The attachment object is the same object which was passed
+ * to the connecting I/O reactor when the connection request was
+ * made. The attachment may optionally contain some state information
+ * required in order to correctly initalize the HTTP context.
+ *
+ * @see ConnectingIOReactor#connect
+ *
+ * @param context the actual HTTP context
+ * @param attachment the object passed to the connecting I/O reactor
+ * upon the request for a new connection.
+ */
+ void initalizeContext(HttpContext context, Object attachment);
+
+ /**
+ * Triggered when the underlying connection is ready to send a new
+ * HTTP request to the target host. This method may return
+ * null if the client is not yet ready to send a
+ * request. In this case the connection will remain open and
+ * can be activated at a later point.
+ *
+ * If the request has an entity, the entity must be an
+ * instance of {@link ProducingNHttpEntity}.
+ *
+ * @param context the actual HTTP context
+ * @return an HTTP request to be sent or null if no
+ * request needs to be sent
+ */
+ HttpRequest submitRequest(HttpContext context);
+
+ /**
+ * Triggered when a response is received with an entity. This method should
+ * return a {@link ConsumingNHttpEntity} that will be used to consume the
+ * entity. null is a valid response value, and will indicate
+ * that the entity should be silently ignored.
+ *
+ * After the entity is fully consumed,
+ * {@link NHttpRequestExecutionHandler#handleResponse(HttpResponse, HttpContext)}
+ * is called to notify a full response & entity are ready to be processed.
+ *
+ * @param request
+ * The request that generated this response.
+ * @param response
+ * The response containing the existing entity.
+ * @param context
+ * the actual HTTP context
+ * @return An entity that will asynchronously consume the response's content
+ * body.
+ */
+ ConsumingNHttpEntity responseEntity(HttpRequest request,
+ HttpResponse response, HttpContext context) throws IOException;
+
+ /**
+ * Triggered when an HTTP response is ready to be processed.
+ *
+ * @param response
+ * the HTTP response to be processed
+ * @param context
+ * the actual HTTP context
+ */
+ void handleResponse(HttpResponse response, HttpContext context)
+ throws IOException;
+
+ /**
+ * Triggered when the connection is terminated. This event can be used
+ * to release objects stored in the context or perform some other kind
+ * of cleanup.
+ *
+ * @param context the actual HTTP context
+ */
+ void finalizeContext(HttpContext context);
+
+}
Property changes on: module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestExecutionHandler.java
___________________________________________________________________
Name: svn:executable
+ *
Index: module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpClientHandler.java
===================================================================
--- module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpClientHandler.java (revision 0)
+++ module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpClientHandler.java (revision 0)
@@ -0,0 +1,449 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/BufferingHttpClientHandler.java $
+ * $Revision: 617652 $
+ * $Date: 2008-02-01 16:18:00 -0500 (Fri, 01 Feb 2008) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ * .
+ *
+ */
+
+package org.apache.http.nio.protocol;
+
+import java.io.IOException;
+
+import org.apache.http.ConnectionReuseStrategy;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.nio.ContentDecoder;
+import org.apache.http.nio.ContentEncoder;
+import org.apache.http.nio.NHttpClientConnection;
+import org.apache.http.nio.entity.ConsumingNHttpEntity;
+import org.apache.http.nio.entity.ConsumingNHttpEntityTemplate;
+import org.apache.http.nio.entity.ProducingNHttpEntity;
+import org.apache.http.nio.entity.SkipContentListener;
+import org.apache.http.nio.util.ByteBufferAllocator;
+import org.apache.http.nio.util.HeapByteBufferAllocator;
+import org.apache.http.params.CoreProtocolPNames;
+import org.apache.http.params.DefaultedHttpParams;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.ExecutionContext;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpProcessor;
+
+/**
+ * HTTP client handler implementation that asynchronously reads & writes out the
+ * content of messages.
+ *
+ * @see ConsumingNHttpEntity
+ * @see ProducingNHttpEntity
+ *
+ * @author Oleg Kalnichevski
+ * @author Sam Berlin
+ *
+ */
+public class AsyncNHttpClientHandler extends AbstractNHttpClientHandler {
+
+ protected NHttpRequestExecutionHandler execHandler;
+
+ public AsyncNHttpClientHandler(
+ final HttpProcessor httpProcessor,
+ final NHttpRequestExecutionHandler execHandler,
+ final ConnectionReuseStrategy connStrategy,
+ final ByteBufferAllocator allocator,
+ final HttpParams params) {
+ super(httpProcessor, connStrategy, allocator, params);
+ if (execHandler == null) {
+ throw new IllegalArgumentException("HTTP request execution handler may not be null.");
+ }
+ this.execHandler = execHandler;
+ }
+
+ public AsyncNHttpClientHandler(
+ final HttpProcessor httpProcessor,
+ final NHttpRequestExecutionHandler execHandler,
+ final ConnectionReuseStrategy connStrategy,
+ final HttpParams params) {
+ this(httpProcessor, execHandler, connStrategy,
+ new HeapByteBufferAllocator(), params);
+ }
+
+ public void connected(final NHttpClientConnection conn, final Object attachment) {
+ HttpContext context = conn.getContext();
+
+ initialize(conn, attachment);
+
+ ClientConnState connState = new ClientConnState();
+ context.setAttribute(CONN_STATE, connState);
+
+ if (this.eventListener != null) {
+ this.eventListener.connectionOpen(conn);
+ }
+
+ requestReady(conn);
+ }
+
+ @Override
+ public void closed(final NHttpClientConnection conn) {
+ HttpContext context = conn.getContext();
+
+ ClientConnState connState = (ClientConnState) context.getAttribute(CONN_STATE);
+ connState.reset();
+
+ this.execHandler.finalizeContext(context);
+
+ // TODO - replace with super.closed(conn); ?
+ if (this.eventListener != null) {
+ this.eventListener.connectionClosed(conn);
+ }
+ }
+
+ public void requestReady(final NHttpClientConnection conn) {
+ HttpContext context = conn.getContext();
+
+ ClientConnState connState = (ClientConnState) context.getAttribute(CONN_STATE);
+ if (connState.getOutputState() != ClientConnState.READY) {
+ return;
+ }
+
+ try {
+
+ HttpRequest request = this.execHandler.submitRequest(context);
+ if (request == null) {
+ return;
+ }
+
+ request.setParams(
+ new DefaultedHttpParams(request.getParams(), this.params));
+
+ context.setAttribute(ExecutionContext.HTTP_REQUEST, request);
+ this.httpProcessor.process(request, context);
+ connState.setRequest(request);
+ conn.submitRequest(request);
+ connState.setOutputState(ClientConnState.REQUEST_SENT);
+
+ if (request instanceof HttpEntityEnclosingRequest) {
+ HttpEntityEnclosingRequest entityReq = (HttpEntityEnclosingRequest)request;
+ ProducingNHttpEntity entity = (ProducingNHttpEntity)entityReq.getEntity();
+ connState.setProducingEntity(entity);
+
+ if (entityReq.expectContinue()) {
+ int timeout = conn.getSocketTimeout();
+ connState.setTimeout(timeout);
+ timeout = this.params.getIntParameter(
+ CoreProtocolPNames.WAIT_FOR_CONTINUE, 3000);
+ conn.setSocketTimeout(timeout);
+ connState.setOutputState(ClientConnState.EXPECT_CONTINUE);
+ }
+ }
+
+ } catch (IOException ex) {
+ shutdownConnection(conn, ex);
+ if (this.eventListener != null) {
+ this.eventListener.fatalIOException(ex, conn);
+ }
+ } catch (HttpException ex) {
+ closeConnection(conn, ex);
+ if (this.eventListener != null) {
+ this.eventListener.fatalProtocolException(ex, conn);
+ }
+ }
+ }
+
+ public void inputReady(final NHttpClientConnection conn, final ContentDecoder decoder) {
+ HttpContext context = conn.getContext();
+
+ ClientConnState connState = (ClientConnState) context.getAttribute(CONN_STATE);
+
+ ConsumingNHttpEntity consumingEntity = connState.getConsumingEntity();
+
+ try {
+ consumingEntity.consumeContent(decoder, conn);
+ if (decoder.isCompleted()) {
+ processResponse(conn, connState);
+ }
+
+ } catch (IOException ex) {
+ shutdownConnection(conn, ex);
+ if (this.eventListener != null) {
+ this.eventListener.fatalIOException(ex, conn);
+ }
+ } catch (HttpException ex) {
+ closeConnection(conn, ex);
+ if (this.eventListener != null) {
+ this.eventListener.fatalProtocolException(ex, conn);
+ }
+ }
+ }
+
+ public void outputReady(final NHttpClientConnection conn, final ContentEncoder encoder) {
+ HttpContext context = conn.getContext();
+ ClientConnState connState = (ClientConnState) context.getAttribute(CONN_STATE);
+
+ try {
+ if (connState.getOutputState() == ClientConnState.EXPECT_CONTINUE) {
+ conn.suspendOutput();
+ return;
+ }
+
+ ProducingNHttpEntity entity = connState.getProducingEntity();
+
+ entity.produceContent(encoder, conn);
+ } catch (IOException ex) {
+ shutdownConnection(conn, ex);
+ if (this.eventListener != null) {
+ this.eventListener.fatalIOException(ex, conn);
+ }
+ }
+ }
+
+ public void responseReceived(final NHttpClientConnection conn) {
+ HttpContext context = conn.getContext();
+ ClientConnState connState = (ClientConnState) context.getAttribute(CONN_STATE);
+
+ HttpResponse response = conn.getHttpResponse();
+ response.setParams(
+ new DefaultedHttpParams(response.getParams(), this.params));
+
+ HttpRequest request = connState.getRequest();
+ try {
+
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode < HttpStatus.SC_OK) {
+ // 1xx intermediate response
+ if (statusCode == HttpStatus.SC_CONTINUE
+ && connState.getOutputState() == ClientConnState.EXPECT_CONTINUE) {
+ continueRequest(conn, connState);
+ }
+ return;
+ } else {
+ connState.setResponse(response);
+
+ if (connState.getOutputState() == ClientConnState.EXPECT_CONTINUE) {
+ cancelRequest(conn, connState);
+ }
+ }
+ if (!canResponseHaveBody(request, response)) {
+ conn.resetInput();
+ response.setEntity(null);
+ processResponse(conn, connState);
+ } else {
+ HttpEntity entity = response.getEntity();
+ if(entity != null) {
+ ConsumingNHttpEntity consumingEntity = execHandler
+ .responseEntity(request, response, context);
+ if(consumingEntity == null) {
+ consumingEntity = new ConsumingNHttpEntityTemplate(
+ entity, new SkipContentListener(allocator));
+ }
+ response.setEntity(consumingEntity);
+ connState.setConsumingEntity(consumingEntity);
+ }
+ }
+
+
+ } catch (IOException ex) {
+ shutdownConnection(conn, ex);
+ if (this.eventListener != null) {
+ this.eventListener.fatalIOException(ex, conn);
+ }
+ } catch (HttpException ex) {
+ closeConnection(conn, ex);
+ if (this.eventListener != null) {
+ this.eventListener.fatalProtocolException(ex, conn);
+ }
+ }
+ }
+
+ public void timeout(final NHttpClientConnection conn) {
+ HttpContext context = conn.getContext();
+ ClientConnState connState = (ClientConnState) context.getAttribute(CONN_STATE);
+
+ try {
+
+ if (connState.getOutputState() == ClientConnState.EXPECT_CONTINUE) {
+ continueRequest(conn, connState);
+ return;
+ }
+
+ } catch (IOException ex) {
+ shutdownConnection(conn, ex);
+ if (this.eventListener != null) {
+ this.eventListener.fatalIOException(ex, conn);
+ }
+ }
+
+ handleTimeout(conn);
+ }
+
+ private void initialize(
+ final NHttpClientConnection conn,
+ final Object attachment) {
+ HttpContext context = conn.getContext();
+
+ context.setAttribute(ExecutionContext.HTTP_CONNECTION, conn);
+ this.execHandler.initalizeContext(context, attachment);
+ }
+
+ private void continueRequest(
+ final NHttpClientConnection conn,
+ final ClientConnState connState) throws IOException {
+
+ int timeout = connState.getTimeout();
+ conn.setSocketTimeout(timeout);
+
+ conn.requestOutput();
+ connState.setOutputState(ClientConnState.REQUEST_SENT);
+ }
+
+ private void cancelRequest(
+ final NHttpClientConnection conn,
+ final ClientConnState connState) throws IOException {
+
+ int timeout = connState.getTimeout();
+ conn.setSocketTimeout(timeout);
+
+ conn.resetOutput();
+ connState.resetOutput();
+ }
+
+ private void processResponse(
+ final NHttpClientConnection conn,
+ final ClientConnState connState) throws IOException, HttpException {
+
+ HttpContext context = conn.getContext();
+ HttpResponse response = connState.getResponse();
+
+ context.setAttribute(ExecutionContext.HTTP_RESPONSE, response);
+
+ this.httpProcessor.process(response, context);
+
+ this.execHandler.handleResponse(response, context);
+
+ if (!this.connStrategy.keepAlive(response, context)) {
+ conn.close();
+ } else {
+ // Ready for another request
+ connState.resetInput();
+ connState.resetOutput();
+ conn.requestOutput();
+ }
+ }
+
+ protected static class ClientConnState {
+
+ public static final int READY = 0;
+ public static final int REQUEST_SENT = 1;
+ public static final int EXPECT_CONTINUE = 2;
+ public static final int REQUEST_BODY_STREAM = 4;
+ public static final int REQUEST_BODY_DONE = 8;
+ public static final int RESPONSE_RECEIVED = 16;
+ public static final int RESPONSE_BODY_STREAM = 32;
+ public static final int RESPONSE_BODY_DONE = 64;
+
+ private int outputState;
+
+ private HttpRequest request;
+ private HttpResponse response;
+ private ConsumingNHttpEntity consumingEntity;
+ private ProducingNHttpEntity producingEntity;
+
+ private int timeout;
+
+ public void setConsumingEntity(ConsumingNHttpEntity consumingEntity) {
+ this.consumingEntity = consumingEntity;
+ }
+
+ public void setProducingEntity(ProducingNHttpEntity entity) {
+ this.producingEntity = entity;
+ }
+
+ public ProducingNHttpEntity getProducingEntity() {
+ return producingEntity;
+ }
+
+ public ConsumingNHttpEntity getConsumingEntity() {
+ return consumingEntity;
+ }
+
+ public int getOutputState() {
+ return this.outputState;
+ }
+
+ public void setOutputState(int outputState) {
+ this.outputState = outputState;
+ }
+
+ public HttpRequest getRequest() {
+ return this.request;
+ }
+
+ public void setRequest(final HttpRequest request) {
+ this.request = request;
+ }
+
+ public HttpResponse getResponse() {
+ return this.response;
+ }
+
+ public void setResponse(final HttpResponse response) {
+ this.response = response;
+ }
+
+ public int getTimeout() {
+ return this.timeout;
+ }
+
+ public void setTimeout(int timeout) {
+ this.timeout = timeout;
+ }
+
+ public void resetInput() {
+ this.response = null;
+ if(consumingEntity != null) {
+ consumingEntity.finish();
+ consumingEntity = null;
+ }
+ }
+
+ public void resetOutput() {
+ this.request = null;
+ if(producingEntity != null) {
+ producingEntity.finish();
+ producingEntity = null;
+ }
+ this.outputState = READY;
+ }
+
+ public void reset() {
+ resetInput();
+ resetOutput();
+ }
+ }
+
+}
Property changes on: module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpClientHandler.java
___________________________________________________________________
Name: svn:executable
+ *
Index: module-nio/src/examples/org/apache/http/examples/nio/NHttpClient.java
===================================================================
--- module-nio/src/examples/org/apache/http/examples/nio/NHttpClient.java (revision 630309)
+++ module-nio/src/examples/org/apache/http/examples/nio/NHttpClient.java (working copy)
@@ -40,23 +40,26 @@
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
-import org.apache.http.params.BasicHttpParams;
import org.apache.http.impl.nio.DefaultClientIOEventDispatch;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.nio.NHttpConnection;
-import org.apache.http.nio.protocol.BufferingHttpClientHandler;
+import org.apache.http.nio.entity.BufferingNHttpEntity;
+import org.apache.http.nio.entity.ConsumingNHttpEntity;
+import org.apache.http.nio.protocol.AsyncNHttpClientHandler;
import org.apache.http.nio.protocol.EventListener;
-import org.apache.http.nio.protocol.HttpRequestExecutionHandler;
+import org.apache.http.nio.protocol.NHttpRequestExecutionHandler;
import org.apache.http.nio.reactor.ConnectingIOReactor;
import org.apache.http.nio.reactor.IOEventDispatch;
import org.apache.http.nio.reactor.SessionRequest;
+import org.apache.http.nio.util.HeapByteBufferAllocator;
+import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
+import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
-import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.BasicHttpProcessor;
+import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
-import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestExpectContinue;
@@ -89,7 +92,7 @@
// I/O event and main threads
RequestCount requestCount = new RequestCount(3);
- BufferingHttpClientHandler handler = new BufferingHttpClientHandler(
+ AsyncNHttpClientHandler handler = new AsyncNHttpClientHandler(
httpproc,
new MyHttpRequestExecutionHandler(requestCount),
new DefaultConnectionReuseStrategy(),
@@ -147,7 +150,7 @@
System.out.println("Done");
}
- static class MyHttpRequestExecutionHandler implements HttpRequestExecutionHandler {
+ static class MyHttpRequestExecutionHandler implements NHttpRequestExecutionHandler {
private final static String REQUEST_SENT = "request-sent";
private final static String RESPONSE_RECEIVED = "response-received";
@@ -174,6 +177,13 @@
}
}
}
+
+ @Override
+ public ConsumingNHttpEntity responseEntity(HttpRequest request,
+ HttpResponse response, HttpContext context) throws IOException {
+ // Create an entity that will buffer the response in memory.
+ return new BufferingNHttpEntity(response.getEntity(), new HeapByteBufferAllocator());
+ }
public HttpRequest submitRequest(final HttpContext context) {
HttpHost targetHost = (HttpHost) context.getAttribute(
Index: module-nio/src/examples/org/apache/http/examples/nio/NHttpSSLClient.java
===================================================================
--- module-nio/src/examples/org/apache/http/examples/nio/NHttpSSLClient.java (revision 630309)
+++ module-nio/src/examples/org/apache/http/examples/nio/NHttpSSLClient.java (working copy)
@@ -46,16 +46,19 @@
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.nio.NHttpConnection;
-import org.apache.http.nio.protocol.BufferingHttpClientHandler;
+import org.apache.http.nio.entity.BufferingNHttpEntity;
+import org.apache.http.nio.entity.ConsumingNHttpEntity;
+import org.apache.http.nio.protocol.AsyncNHttpClientHandler;
import org.apache.http.nio.protocol.EventListener;
-import org.apache.http.nio.protocol.HttpRequestExecutionHandler;
+import org.apache.http.nio.protocol.NHttpRequestExecutionHandler;
import org.apache.http.nio.reactor.ConnectingIOReactor;
import org.apache.http.nio.reactor.IOEventDispatch;
import org.apache.http.nio.reactor.SessionRequest;
+import org.apache.http.nio.util.HeapByteBufferAllocator;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
+import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
-import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
@@ -95,7 +98,7 @@
// I/O event and main threads
RequestCount requestCount = new RequestCount(3);
- BufferingHttpClientHandler handler = new BufferingHttpClientHandler(
+ AsyncNHttpClientHandler handler = new AsyncNHttpClientHandler(
httpproc,
new MyHttpRequestExecutionHandler(requestCount),
new DefaultConnectionReuseStrategy(),
@@ -156,7 +159,7 @@
System.out.println("Done");
}
- static class MyHttpRequestExecutionHandler implements HttpRequestExecutionHandler {
+ static class MyHttpRequestExecutionHandler implements NHttpRequestExecutionHandler {
private final static String REQUEST_SENT = "request-sent";
private final static String RESPONSE_RECEIVED = "response-received";
@@ -183,6 +186,13 @@
}
}
}
+
+ @Override
+ public ConsumingNHttpEntity responseEntity(HttpRequest request,
+ HttpResponse response, HttpContext context) throws IOException {
+ // Create an entity that will buffer the response in memory.
+ return new BufferingNHttpEntity(response.getEntity(), new HeapByteBufferAllocator());
+ }
public HttpRequest submitRequest(final HttpContext context) {
HttpHost targetHost = (HttpHost) context.getAttribute(