You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2008/02/24 20:16:33 UTC
svn commit: r630660 - in
/httpcomponents/httpcore/branches/limewire_contrib/module-nio/src:
main/java/org/apache/http/nio/protocol/
test/java/org/apache/http/nio/protocol/
Author: olegk
Date: Sun Feb 24 11:16:27 2008
New Revision: 630660
URL: http://svn.apache.org/viewvc?rev=630660&view=rev
Log:
HTTPCORE-148:
* Improved asynchronous client side HTTP protocol handler
Contributed by Sam Berlin <sberlin at gmail.com>
Reviewed by Oleg Kalnichevski
Added:
httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AbstractNHttpClientHandler.java (with props)
httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpClientHandler.java (with props)
httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestExecutionHandler.java (with props)
Modified:
httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpClientHandlerBase.java
httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java
Added: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AbstractNHttpClientHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AbstractNHttpClientHandler.java?rev=630660&view=auto
==============================================================================
--- httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AbstractNHttpClientHandler.java (added)
+++ httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AbstractNHttpClientHandler.java Sun Feb 24 11:16:27 2008
@@ -0,0 +1,75 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+
+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);
+ }
+ }
+
+}
Propchange: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AbstractNHttpClientHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AbstractNHttpClientHandler.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AbstractNHttpClientHandler.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpClientHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpClientHandler.java?rev=630660&view=auto
==============================================================================
--- httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpClientHandler.java (added)
+++ httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpClientHandler.java Sun Feb 24 11:16:27 2008
@@ -0,0 +1,448 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+
+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 <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ * @author <a href="mailto:sberlin at gmail.com">Sam Berlin</a>
+ *
+ */
+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);
+
+ 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 = this.execHandler.responseEntity(
+ response, context);
+ if (consumingEntity == null) {
+ consumingEntity = new ConsumingNHttpEntityTemplate(
+ entity, new SkipContentListener(this.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(final ConsumingNHttpEntity consumingEntity) {
+ this.consumingEntity = consumingEntity;
+ }
+
+ public void setProducingEntity(final ProducingNHttpEntity producingEntity) {
+ this.producingEntity = producingEntity;
+ }
+
+ 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 (this.consumingEntity != null) {
+ this.consumingEntity.finish();
+ this.consumingEntity = null;
+ }
+ }
+
+ public void resetOutput() {
+ this.request = null;
+ if (this.producingEntity != null) {
+ this.producingEntity.finish();
+ this.producingEntity = null;
+ }
+ this.outputState = READY;
+ }
+
+ public void reset() {
+ resetInput();
+ resetOutput();
+ }
+ }
+
+}
Propchange: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpClientHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpClientHandler.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpClientHandler.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpClientHandlerBase.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpClientHandlerBase.java?rev=630660&r1=630659&r2=630660&view=diff
==============================================================================
--- httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpClientHandlerBase.java (original)
+++ httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpClientHandlerBase.java Sun Feb 24 11:16:27 2008
@@ -36,18 +36,16 @@
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;
-
+
public NHttpClientHandlerBase(
- final HttpProcessor httpProcessor,
+ final HttpProcessor httpProcessor,
final HttpRequestExecutionHandler execHandler,
final ConnectionReuseStrategy connStrategy,
final ByteBufferAllocator allocator,
@@ -58,7 +56,7 @@
}
this.execHandler = execHandler;
}
-
+
public void closed(final NHttpClientConnection conn) {
if (this.eventListener != null) {
this.eventListener.connectionClosed(conn);
@@ -78,5 +76,5 @@
this.eventListener.fatalIOException(ex, conn);
}
}
-
+
}
Added: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestExecutionHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestExecutionHandler.java?rev=630660&view=auto
==============================================================================
--- httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestExecutionHandler.java (added)
+++ httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestExecutionHandler.java Sun Feb 24 11:16:27 2008
@@ -0,0 +1,130 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+
+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 <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ */
+public interface NHttpRequestExecutionHandler {
+
+ /**
+ * Triggered when a new connection has been established and the
+ * HTTP context needs to be initialized.
+ *
+ * <p>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
+ * <code>null</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.
+ * <p>
+ * If the request has an entity, the entity <b>must</b> be an
+ * instance of {@link ProducingNHttpEntity}.
+ *
+ * @param context the actual HTTP context
+ * @return an HTTP request to be sent or <code>null</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. <code>null</code> is a valid response value, and will indicate
+ * that the entity should be silently ignored.
+ * <p>
+ * 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 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(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);
+
+}
Propchange: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestExecutionHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestExecutionHandler.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestExecutionHandler.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java?rev=630660&r1=630659&r2=630660&view=diff
==============================================================================
--- httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java (original)
+++ httpcomponents/httpcore/branches/limewire_contrib/module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java Sun Feb 24 11:16:27 2008
@@ -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(),
@@ -240,13 +239,15 @@
NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() {
public ConsumingNHttpEntity entityRequest(
- HttpEntityEnclosingRequest request, HttpContext context) {
+ final HttpEntityEnclosingRequest request,
+ final HttpContext context) {
return null;
}
public void handle(
- HttpRequest request, HttpResponse response, HttpContext context)
- throws HttpException, IOException {
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
String s = request.getRequestLine().getUri();
URI uri;
try {
@@ -262,7 +263,7 @@
};
- HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+ NHttpRequestExecutionHandler requestExecutionHandler = new NHttpRequestExecutionHandler() {
public void initalizeContext(final HttpContext context, final Object attachment) {
context.setAttribute("LIST", (ByteSequence) attachment);
@@ -283,6 +284,13 @@
return get;
}
+ public ConsumingNHttpEntity responseEntity(
+ final HttpResponse response,
+ final 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(
ExecutionContext.HTTP_CONNECTION);
@@ -373,16 +381,17 @@
NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() {
public ConsumingNHttpEntity entityRequest(
- HttpEntityEnclosingRequest request, HttpContext context)
- throws HttpException, IOException {
+ final HttpEntityEnclosingRequest request,
+ final HttpContext context) throws HttpException, IOException {
return new BufferingNHttpEntity(
request.getEntity(),
new HeapByteBufferAllocator());
}
public void handle(
- HttpRequest request, HttpResponse response, HttpContext context)
- throws HttpException, IOException {
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
byte[] b = EntityUtils.toByteArray(entity);
@@ -394,7 +403,7 @@
}
};
- HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+ NHttpRequestExecutionHandler requestExecutionHandler = new NHttpRequestExecutionHandler() {
public void initalizeContext(final HttpContext context, final Object attachment) {
context.setAttribute("LIST", (ByteSequence) attachment);
@@ -405,6 +414,13 @@
public void finalizeContext(final HttpContext context) {
}
+ public ConsumingNHttpEntity responseEntity(
+ final HttpResponse response,
+ final 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;
@@ -412,7 +428,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));
@@ -510,16 +526,17 @@
NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() {
public ConsumingNHttpEntity entityRequest(
- HttpEntityEnclosingRequest request, HttpContext context)
- throws HttpException, IOException {
+ final HttpEntityEnclosingRequest request,
+ final HttpContext context) throws HttpException, IOException {
return new BufferingNHttpEntity(
request.getEntity(),
new HeapByteBufferAllocator());
}
public void handle(
- HttpRequest request, HttpResponse response, HttpContext context)
- throws HttpException, IOException {
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
byte[] b = EntityUtils.toByteArray(entity);
@@ -533,7 +550,7 @@
}
};
- HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+ NHttpRequestExecutionHandler requestExecutionHandler = new NHttpRequestExecutionHandler() {
public void initalizeContext(final HttpContext context, final Object attachment) {
context.setAttribute("LIST", (ByteSequence) attachment);
@@ -544,13 +561,20 @@
public void finalizeContext(final HttpContext context) {
}
+ public ConsumingNHttpEntity responseEntity(
+ final HttpResponse response,
+ final 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);
outgoing.setChunked(true);
post.setEntity(outgoing);
@@ -652,16 +676,17 @@
NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() {
public ConsumingNHttpEntity entityRequest(
- HttpEntityEnclosingRequest request, HttpContext context)
- throws HttpException, IOException {
+ final HttpEntityEnclosingRequest request,
+ final HttpContext context) throws HttpException, IOException {
return new BufferingNHttpEntity(
request.getEntity(),
new HeapByteBufferAllocator());
}
public void handle(
- HttpRequest request, HttpResponse response, HttpContext context)
- throws HttpException, IOException {
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
byte[] b = EntityUtils.toByteArray(entity);
@@ -679,7 +704,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 +715,20 @@
public void finalizeContext(final HttpContext context) {
}
+ public ConsumingNHttpEntity responseEntity(
+ final HttpResponse response,
+ final 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));
@@ -794,16 +826,17 @@
NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() {
public ConsumingNHttpEntity entityRequest(
- HttpEntityEnclosingRequest request, HttpContext context)
- throws HttpException, IOException {
+ final HttpEntityEnclosingRequest request,
+ final HttpContext context) throws HttpException, IOException {
return new BufferingNHttpEntity(
request.getEntity(),
new HeapByteBufferAllocator());
}
public void handle(
- HttpRequest request, HttpResponse response, HttpContext context)
- throws HttpException, IOException {
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
byte[] b = EntityUtils.toByteArray(entity);
@@ -820,7 +853,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);
@@ -831,13 +864,20 @@
public void finalizeContext(final HttpContext context) {
}
+ public ConsumingNHttpEntity responseEntity(
+ final HttpResponse response,
+ final 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);
outgoing.setChunked(true);
post.setEntity(outgoing);
@@ -929,16 +969,17 @@
NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() {
public ConsumingNHttpEntity entityRequest(
- HttpEntityEnclosingRequest request, HttpContext context)
- throws HttpException, IOException {
+ final HttpEntityEnclosingRequest request,
+ final HttpContext context) throws HttpException, IOException {
return new BufferingNHttpEntity(
request.getEntity(),
new HeapByteBufferAllocator());
}
public void handle(
- HttpRequest request, HttpResponse response, HttpContext context)
- throws HttpException, IOException {
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
NStringEntity outgoing = new NStringEntity("No content");
response.setEntity(outgoing);
}
@@ -973,7 +1014,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);
@@ -984,13 +1025,20 @@
public void finalizeContext(final HttpContext context) {
}
+ public ConsumingNHttpEntity responseEntity(
+ final HttpResponse response,
+ final 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", "/");
post.addHeader("Secret", Integer.toString(i));
- ByteArrayEntity outgoing = new ByteArrayEntity(
+ NByteArrayEntity outgoing = new NByteArrayEntity(
EncodingUtils.getAsciiBytes("No content"));
post.setEntity(outgoing);
@@ -1011,7 +1059,7 @@
HttpEntity entity = response.getEntity();
if (entity != null) {
try {
- entity.consumeContent();
+ EntityUtils.toByteArray(entity);
} catch (IOException ex) {
requestCount.abort();
return;
@@ -1087,16 +1135,17 @@
NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() {
public ConsumingNHttpEntity entityRequest(
- HttpEntityEnclosingRequest request, HttpContext context)
- throws HttpException, IOException {
+ final HttpEntityEnclosingRequest request,
+ final HttpContext context) throws HttpException, IOException {
return new BufferingNHttpEntity(
request.getEntity(),
new HeapByteBufferAllocator());
}
public void handle(
- HttpRequest request, HttpResponse response, HttpContext context)
- throws HttpException, IOException {
+ final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
String s = request.getRequestLine().getUri();
URI uri;
try {
@@ -1112,7 +1161,7 @@
};
- HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+ NHttpRequestExecutionHandler requestExecutionHandler = new NHttpRequestExecutionHandler() {
public void initalizeContext(final HttpContext context, final Object attachment) {
context.setAttribute("LIST", (ResponseSequence) attachment);
@@ -1121,6 +1170,13 @@
}
public void finalizeContext(final HttpContext context) {
+ }
+
+ public ConsumingNHttpEntity responseEntity(
+ final HttpResponse response,
+ final HttpContext context) throws IOException {
+ return new BufferingNHttpEntity(response.getEntity(),
+ new HeapByteBufferAllocator());
}
public HttpRequest submitRequest(final HttpContext context) {