hc-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ol...@apache.org
Subject svn commit: r1038668 - in /httpcomponents/httpasyncclient/trunk: ./ src/examples/org/apache/http/examples/nio/client/ src/main/java/org/apache/http/impl/nio/client/ src/test/java/org/ src/test/java/org/apache/ src/test/java/org/apache/http/ src/test/ja...
Date Wed, 24 Nov 2010 16:15:30 GMT
Author: olegk
Date: Wed Nov 24 16:15:29 2010
New Revision: 1038668

URL: http://svn.apache.org/viewvc?rev=1038668&view=rev
Log:
Improved HTTP async protocol handler; added test cases

Added:
    httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/ConnState.java
  (with props)
    httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/MessageState.java
  (with props)
    httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/NHttpClientProtocolHandler.java
  (with props)
    httpcomponents/httpasyncclient/trunk/src/test/java/org/
    httpcomponents/httpasyncclient/trunk/src/test/java/org/apache/
    httpcomponents/httpasyncclient/trunk/src/test/java/org/apache/http/
    httpcomponents/httpasyncclient/trunk/src/test/java/org/apache/http/impl/
    httpcomponents/httpasyncclient/trunk/src/test/java/org/apache/http/impl/nio/
    httpcomponents/httpasyncclient/trunk/src/test/java/org/apache/http/impl/nio/client/
    httpcomponents/httpasyncclient/trunk/src/test/java/org/apache/http/impl/nio/client/TestHttpAsync.java
  (with props)
Removed:
    httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/InternalEventLogger.java
Modified:
    httpcomponents/httpasyncclient/trunk/pom.xml
    httpcomponents/httpasyncclient/trunk/src/examples/org/apache/http/examples/nio/client/AsyncClientRequest.java
    httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/BasicAsyncHttpClient.java

Modified: httpcomponents/httpasyncclient/trunk/pom.xml
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/pom.xml?rev=1038668&r1=1038667&r2=1038668&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/pom.xml (original)
+++ httpcomponents/httpasyncclient/trunk/pom.xml Wed Nov 24 16:15:29 2010
@@ -41,14 +41,6 @@
   <url>http://hc.apache.org/httpcomponents-client</url>
   <packaging>jar</packaging>
 
-  <licenses>
-    <license>
-      <name>Apache License</name>
-      <url>LICENSE.txt</url>
-      <distribution>repo</distribution>
-    </license>
-  </licenses>
-
   <dependencies>
     <dependency>
       <groupId>org.apache.httpcomponents</groupId>
@@ -76,6 +68,13 @@
       <version>${junit.version}</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+      <version>${httpclient.version}</version>
+      <classifier>tests</classifier>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <properties>
@@ -85,8 +84,8 @@
     <maven.compile.target>1.5</maven.compile.target>
     <maven.compile.optimize>true</maven.compile.optimize>
     <maven.compile.deprecation>true</maven.compile.deprecation>
-    <httpcore.version>4.1-beta1</httpcore.version>
-    <httpclient.version>4.0</httpclient.version>
+    <httpcore.version>4.1</httpcore.version>
+    <httpclient.version>4.1-beta1</httpclient.version>
     <commons-logging.version>1.1.1</commons-logging.version>
     <junit.version>4.8.1</junit.version>
   </properties>
@@ -95,13 +94,6 @@
     <resources>
       <resource>
         <directory>src/main/resources</directory>
-        <filtering>false</filtering>
-        <includes>
-            <include>META-INF/*</include>
-        </includes>
-      </resource>
-      <resource>
-        <directory>src/main/resources</directory>
         <filtering>true</filtering>
         <includes>
             <include>**/*.properties</include>

Modified: httpcomponents/httpasyncclient/trunk/src/examples/org/apache/http/examples/nio/client/AsyncClientRequest.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/src/examples/org/apache/http/examples/nio/client/AsyncClientRequest.java?rev=1038668&r1=1038667&r2=1038668&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/src/examples/org/apache/http/examples/nio/client/AsyncClientRequest.java
(original)
+++ httpcomponents/httpasyncclient/trunk/src/examples/org/apache/http/examples/nio/client/AsyncClientRequest.java
Wed Nov 24 16:15:29 2010
@@ -61,7 +61,7 @@ public class AsyncClientRequest {
         
         asynchttpclient.start();
         
-        HttpHost target = new HttpHost("www.google.ch", 80);
+        HttpHost target = new HttpHost("www.apache.org", 80);
         BasicHttpRequest request = new BasicHttpRequest("GET", "/"); 
 
         HttpExchange[] httpx = new HttpExchange[10]; 

Modified: httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/BasicAsyncHttpClient.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/BasicAsyncHttpClient.java?rev=1038668&r1=1038667&r2=1038668&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/BasicAsyncHttpClient.java
(original)
+++ httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/BasicAsyncHttpClient.java
Wed Nov 24 16:15:29 2010
@@ -41,7 +41,6 @@ import org.apache.http.impl.nio.reactor.
 import org.apache.http.nio.client.AsyncHttpClient;
 import org.apache.http.nio.client.HttpExchange;
 import org.apache.http.nio.conn.IOSessionManager;
-import org.apache.http.nio.protocol.AsyncNHttpClientHandler;
 import org.apache.http.nio.reactor.ConnectingIOReactor;
 import org.apache.http.nio.reactor.IOEventDispatch;
 import org.apache.http.nio.reactor.IOReactorException;
@@ -121,17 +120,16 @@ public class BasicAsyncHttpClient implem
         return new DefaultConnectionReuseStrategy();
     }
     
-    public HttpParams getParams() {
-        return this.params;
+    public IOSessionManager<HttpRoute> getSessionManager() {
+        return this.sessmrg;
     }
 
     private void doExecute() {
-        AsyncNHttpClientHandler handler = new AsyncNHttpClientHandler(
+        NHttpClientProtocolHandler handler = new NHttpClientProtocolHandler(
                 createHttpProcessor(),
                 new InternalRequestExecutionHandler(),
                 createConnectionReuseStrategy(),
                 this.params);
-        handler.setEventListener(new InternalEventLogger(this.log));
         IOEventDispatch ioEventDispatch = new InternalClientEventDispatch(handler, this.params);
         try {
             this.ioReactor.execute(ioEventDispatch);

Added: httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/ConnState.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/ConnState.java?rev=1038668&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/ConnState.java
(added)
+++ httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/ConnState.java
Wed Nov 24 16:15:29 2010
@@ -0,0 +1,162 @@
+/*
+ * ====================================================================
+ * 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.impl.nio.client;
+
+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;
+
+class ConnState {
+
+    private MessageState requestState;
+    private MessageState responseState;
+    private HttpRequest request;
+    private HttpResponse response;
+    private ConsumingNHttpEntity consumingEntity;
+    private ProducingNHttpEntity producingEntity;
+    private boolean valid;
+    private int timeout;
+
+    public ConnState() {
+        super();
+        this.valid = true;
+        this.requestState = MessageState.READY;
+        this.responseState = MessageState.READY;
+    }
+
+    public MessageState getRequestState() {
+        return this.requestState;
+    }
+
+    public void setRequestState(final MessageState state) {
+        this.requestState = state;
+    }
+
+    public MessageState getResponseState() {
+        return this.responseState;
+    }
+
+    public void setResponseState(final MessageState state) {
+        this.responseState = state;
+    }
+
+    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 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 getTimeout() {
+        return this.timeout;
+    }
+
+    public void setTimeout(int timeout) {
+        this.timeout = timeout;
+    }
+
+    public void resetInput() throws IOException {
+        this.response = null;
+        if (this.consumingEntity != null) {
+            this.consumingEntity.finish();
+            this.consumingEntity = null;
+        }
+        this.responseState = MessageState.READY;
+    }
+
+    public void resetOutput() throws IOException {
+        this.request = null;
+        if (this.producingEntity != null) {
+            this.producingEntity.finish();
+            this.producingEntity = null;
+        }
+        this.requestState = MessageState.READY;
+    }
+
+    public void reset() throws IOException {
+        resetInput();
+        resetOutput();
+    }
+
+    public boolean isValid() {
+        return this.valid;
+    }
+
+    public void invalidate() {
+        this.valid = false;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder buf = new StringBuilder();
+        buf.append("[request state=");
+        buf.append(this.requestState);
+        if (this.request != null) {
+            buf.append(",request=");
+            buf.append(this.request.getRequestLine());
+        }
+        buf.append(",response state=");
+        buf.append(this.responseState);
+        if (this.response != null) {
+            buf.append(",response=");
+            buf.append(this.response.getStatusLine());
+        }
+        buf.append(",valid=");
+        buf.append(this.valid);
+        buf.append("]");
+        return buf.toString();
+    }
+
+}
\ No newline at end of file

Propchange: httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/ConnState.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/ConnState.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/ConnState.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/MessageState.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/MessageState.java?rev=1038668&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/MessageState.java
(added)
+++ httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/MessageState.java
Wed Nov 24 16:15:29 2010
@@ -0,0 +1,33 @@
+/*
+ * ====================================================================
+ * 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.impl.nio.client;
+
+enum MessageState {
+
+    READY, HEAD, ACK, BODY_STREAM, COMPLETED
+
+}
\ No newline at end of file

Propchange: httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/MessageState.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/MessageState.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/MessageState.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/NHttpClientProtocolHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/NHttpClientProtocolHandler.java?rev=1038668&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/NHttpClientProtocolHandler.java
(added)
+++ httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/NHttpClientProtocolHandler.java
Wed Nov 24 16:15:29 2010
@@ -0,0 +1,453 @@
+/*
+ * ====================================================================
+ * 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.impl.nio.client;
+
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.ConnectionReuseStrategy;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpException;
+import org.apache.http.HttpInetConnection;
+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.NHttpClientHandler;
+import org.apache.http.nio.NHttpConnection;
+import org.apache.http.nio.entity.ConsumingNHttpEntity;
+import org.apache.http.nio.entity.ConsumingNHttpEntityTemplate;
+import org.apache.http.nio.entity.NHttpEntityWrapper;
+import org.apache.http.nio.entity.ProducingNHttpEntity;
+import org.apache.http.nio.entity.SkipContentListener;
+import org.apache.http.nio.protocol.NHttpRequestExecutionHandler;
+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;
+
+/**
+ * Fully asynchronous HTTP client side protocol handler that implements the
+ * essential requirements of the HTTP protocol for the server side message
+ * processing as described by RFC 2616. It is capable of executing HTTP requests
+ * with nearly constant memory footprint. Only HTTP message heads are stored in
+ * memory, while content of message bodies is streamed directly from the entity
+ * to the underlying channel (and vice versa) using {@link ConsumingNHttpEntity}
+ * and {@link ProducingNHttpEntity} interfaces.
+ */
+class NHttpClientProtocolHandler implements NHttpClientHandler {
+
+    private final Log log;
+
+    private static final String CONN_STATE = "http.nio.conn-state";
+
+    private final HttpProcessor httpProcessor;
+    private final NHttpRequestExecutionHandler execHandler;
+    private final ConnectionReuseStrategy connStrategy;
+    private final ByteBufferAllocator allocator;
+    private final HttpParams params;
+
+    public NHttpClientProtocolHandler(
+            final HttpProcessor httpProcessor,
+            final NHttpRequestExecutionHandler execHandler,
+            final ConnectionReuseStrategy connStrategy,
+            final ByteBufferAllocator allocator,
+            final HttpParams params) {
+        if (httpProcessor == null) {
+            throw new IllegalArgumentException("HTTP processor may not be null.");
+        }
+        if (execHandler == null) {
+            throw new IllegalArgumentException("HTTP request execution handler may not be
null.");
+        }
+        if (connStrategy == null) {
+            throw new IllegalArgumentException("Connection reuse strategy may not be null");
+        }
+        if (allocator == null) {
+            throw new IllegalArgumentException("ByteBuffer allocator may not be null");
+        }
+        if (params == null) {
+            throw new IllegalArgumentException("HTTP parameters may not be null");
+        }
+        this.httpProcessor = httpProcessor;
+        this.execHandler = execHandler;
+        this.connStrategy = connStrategy;
+        this.allocator = allocator;
+        this.params = params;
+        this.log = LogFactory.getLog(getClass());
+    }
+
+    public NHttpClientProtocolHandler(
+            final HttpProcessor httpProcessor,
+            final NHttpRequestExecutionHandler execHandler,
+            final ConnectionReuseStrategy connStrategy,
+            final HttpParams params) {
+        this(httpProcessor, execHandler, connStrategy, new HeapByteBufferAllocator(), params);
+    }
+
+    private void closeConnection(final NHttpClientConnection conn) {
+        try {
+            conn.close();
+        } catch (IOException ex) {
+            try {
+                conn.shutdown();
+            } catch (IOException ignore) {
+                this.log.debug("I/O error terminating connection: " + ex.getMessage(), ex);
+            }
+        }
+    }
+
+    protected void shutdownConnection(final NHttpClientConnection conn) {
+        try {
+            conn.shutdown();
+        } catch (IOException ex) {
+            this.log.debug("I/O error terminating connection: " + ex.getMessage(), ex);
+        }
+    }
+
+    public void connected(final NHttpClientConnection conn, final Object attachment) {
+        ConnState connState = new ConnState();
+        HttpContext context = conn.getContext();
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("Connected " + formatState(conn, connState));
+        }
+        context.setAttribute(CONN_STATE, connState);
+        context.setAttribute(ExecutionContext.HTTP_CONNECTION, conn);
+        this.execHandler.initalizeContext(context, attachment);
+        requestReady(conn);
+    }
+
+    public void closed(final NHttpClientConnection conn) {
+        HttpContext context = conn.getContext();
+        ConnState connState = (ConnState) context.getAttribute(CONN_STATE);
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("Disconnected " + formatState(conn, connState));
+        }
+        try {
+            connState.reset();
+            this.execHandler.finalizeContext(context);
+        } catch (IOException ex) {
+            this.log.debug("I/O error resetting connection state: " + ex.getMessage(), ex);
+        }
+    }
+
+    public void exception(final NHttpClientConnection conn, final HttpException ex) {
+        this.log.error("HTTP protocol exception: " + ex.getMessage(), ex);
+        closeConnection(conn);
+    }
+
+    public void exception(final NHttpClientConnection conn, final IOException ex) {
+        this.log.error("I/O error: " + ex.getMessage(), ex);
+        shutdownConnection(conn);
+    }
+
+    public void requestReady(final NHttpClientConnection conn) {
+        HttpContext context = conn.getContext();
+        ConnState connState = (ConnState) context.getAttribute(CONN_STATE);
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("Request ready " + formatState(conn, connState));
+        }
+        if (connState.getRequestState() != MessageState.READY) {
+            return;
+        }
+        try {
+            HttpRequest request = this.execHandler.submitRequest(context);
+            if (request == null) {
+                if (this.log.isDebugEnabled()) {
+                    this.log.debug("No request submitted " + formatState(conn, connState));
+                }
+                return;
+            }
+
+            request.setParams(new DefaultedHttpParams(request.getParams(), this.params));
+
+            context.setAttribute(ExecutionContext.HTTP_REQUEST, request);
+            this.httpProcessor.process(request, context);
+
+            HttpEntityEnclosingRequest entityReq = null;
+            HttpEntity entity = null;
+
+            if (request instanceof HttpEntityEnclosingRequest) {
+                entityReq = (HttpEntityEnclosingRequest) request;
+                entity = entityReq.getEntity();
+            }
+
+            if (entity instanceof ProducingNHttpEntity) {
+                connState.setProducingEntity((ProducingNHttpEntity) entity);
+            } else if (entity != null) {
+                connState.setProducingEntity(new NHttpEntityWrapper(entity));
+            }
+
+            connState.setRequest(request);
+            conn.submitRequest(request);
+
+            if (entityReq != null && entityReq.expectContinue()) {
+                int timeout = conn.getSocketTimeout();
+                connState.setTimeout(timeout);
+                timeout = this.params.getIntParameter(
+                        CoreProtocolPNames.WAIT_FOR_CONTINUE, 3000);
+                conn.setSocketTimeout(timeout);
+                connState.setRequestState(MessageState.ACK);
+            } else if (connState.getProducingEntity() != null) {
+                connState.setRequestState(MessageState.BODY_STREAM);
+            } else {
+                connState.setRequestState(MessageState.COMPLETED);
+            }
+
+        } catch (IOException ex) {
+            shutdownConnection(conn);
+            this.log.error("I/O error: " + ex.getMessage(), ex);
+        } catch (HttpException ex) {
+            closeConnection(conn);
+            this.log.error("HTTP protocol exception: " + ex.getMessage(), ex);
+        }
+    }
+
+    public void inputReady(final NHttpClientConnection conn, final ContentDecoder decoder)
{
+        HttpContext context = conn.getContext();
+        ConnState connState = (ConnState) context.getAttribute(CONN_STATE);
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("Input ready " + formatState(conn, connState));
+        }
+        ConsumingNHttpEntity consumingEntity = connState.getConsumingEntity();
+        try {
+            consumingEntity.consumeContent(decoder, conn);
+            if (decoder.isCompleted()) {
+                processResponse(conn, connState);
+            }
+        } catch (IOException ex) {
+            shutdownConnection(conn);
+            this.log.error("I/O error: " + ex.getMessage(), ex);
+        }
+    }
+
+    public void outputReady(final NHttpClientConnection conn, final ContentEncoder encoder)
{
+        HttpContext context = conn.getContext();
+        ConnState connState = (ConnState) context.getAttribute(CONN_STATE);
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("Output ready " + formatState(conn, connState));
+        }
+        try {
+            if (connState.getRequestState() == MessageState.ACK) {
+                conn.suspendOutput();
+                return;
+            }
+            ProducingNHttpEntity entity = connState.getProducingEntity();
+            entity.produceContent(encoder, conn);
+            if (encoder.isCompleted()) {
+                connState.setRequestState(MessageState.COMPLETED);
+            }
+        } catch (IOException ex) {
+            shutdownConnection(conn);
+            this.log.error("I/O error: " + ex.getMessage(), ex);
+        }
+    }
+
+    public void responseReceived(final NHttpClientConnection conn) {
+        HttpContext context = conn.getContext();
+        ConnState connState = (ConnState) context.getAttribute(CONN_STATE);
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("Response received " + formatState(conn, connState));
+        }
+
+        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.getRequestState() == MessageState.ACK) {
+                    continueRequest(conn, connState);
+                    connState.setRequestState(MessageState.BODY_STREAM);
+                }
+                return;
+            } else {
+                connState.setResponse(response);
+                if (connState.getRequestState() == MessageState.ACK) {
+                    cancelRequest(conn, connState);
+                    connState.setRequestState(MessageState.COMPLETED);
+                } else if (connState.getRequestState() == MessageState.BODY_STREAM) {
+                    // Early response
+                    cancelRequest(conn, connState);
+                    connState.invalidate();
+                    conn.suspendOutput();
+                }
+            }
+            context.setAttribute(ExecutionContext.HTTP_RESPONSE, response);
+            if (!canResponseHaveBody(request, response)) {
+                conn.resetInput();
+                response.setEntity(null);
+                this.httpProcessor.process(response, context);
+                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);
+                    this.httpProcessor.process(response, context);
+                }
+            }
+        } catch (IOException ex) {
+            shutdownConnection(conn);
+            this.log.error("I/O error: " + ex.getMessage(), ex);
+        } catch (HttpException ex) {
+            closeConnection(conn);
+            this.log.error("HTTP protocol exception: " + ex.getMessage(), ex);
+        }
+    }
+
+    public void timeout(final NHttpClientConnection conn) {
+        HttpContext context = conn.getContext();
+        ConnState connState = (ConnState) context.getAttribute(CONN_STATE);
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("Timeout " + formatState(conn, connState));
+        }
+        try {
+            if (connState.getRequestState() == MessageState.ACK) {
+                continueRequest(conn, connState);
+                connState.setRequestState(MessageState.BODY_STREAM);
+            } else {
+                if (conn.getStatus() == NHttpConnection.ACTIVE) {
+                    conn.close();
+                    if (conn.getStatus() == NHttpConnection.CLOSING) {
+                        // Give the connection some grace time to
+                        // close itself nicely
+                        conn.setSocketTimeout(250);
+                    }
+                } else {
+                    conn.shutdown();
+                }
+            }
+        } catch (IOException ex) {
+            shutdownConnection(conn);
+            this.log.error("I/O error: " + ex.getMessage(), ex);
+        }
+    }
+
+    private void continueRequest(
+            final NHttpClientConnection conn,
+            final ConnState connState) {
+        int timeout = connState.getTimeout();
+        conn.setSocketTimeout(timeout);
+        conn.requestOutput();
+    }
+
+    private void cancelRequest(
+            final NHttpClientConnection conn,
+            final ConnState connState) throws IOException {
+        int timeout = connState.getTimeout();
+        conn.setSocketTimeout(timeout);
+        conn.resetOutput();
+        connState.resetOutput();
+    }
+
+    private void processResponse(
+            final NHttpClientConnection conn,
+            final ConnState connState) throws IOException {
+        if (!connState.isValid()) {
+            conn.close();
+        }
+        HttpContext context = conn.getContext();
+        HttpResponse response = connState.getResponse();
+        this.execHandler.handleResponse(response, context);
+        if (!this.connStrategy.keepAlive(response, context)) {
+            conn.close();
+        }
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("Response processed " + formatState(conn, connState));
+        }
+        if (conn.isOpen()) {
+            // Ready for another request
+            connState.resetInput();
+            connState.resetOutput();
+            conn.requestOutput();
+        }
+    }
+
+    private boolean canResponseHaveBody(final HttpRequest request, final HttpResponse response)
{
+
+        if (request != null && "HEAD".equalsIgnoreCase(request.getRequestLine().getMethod()))
{
+            return false;
+        }
+
+        int status = response.getStatusLine().getStatusCode();
+        return status >= HttpStatus.SC_OK
+            && status != HttpStatus.SC_NO_CONTENT
+            && status != HttpStatus.SC_NOT_MODIFIED
+            && status != HttpStatus.SC_RESET_CONTENT;
+    }
+
+    private String formatState(final NHttpConnection conn, final ConnState connState) {
+        StringBuilder buf = new StringBuilder();
+        buf.append("[");
+        if (conn.isOpen() && (conn instanceof HttpInetConnection)) {
+            HttpInetConnection inetconn = (HttpInetConnection) conn;
+            buf.append(inetconn.getRemoteAddress());
+            buf.append(":");
+            buf.append(inetconn.getRemotePort());
+        }
+        buf.append("(");
+        buf.append(conn.isOpen() ? "open" : "closed");
+        buf.append("),request=");
+        buf.append(connState.getRequestState());
+        if (connState.getRequest() != null) {
+            buf.append("(");
+            buf.append(connState.getRequest().getRequestLine());
+            buf.append(")");
+        }
+        buf.append(",response=");
+        buf.append(connState.getResponseState());
+        if (connState.getResponse() != null) {
+            buf.append("(");
+            buf.append(connState.getResponse().getStatusLine());
+            buf.append(")");
+        }
+        buf.append(",valid=");
+        buf.append(connState.isValid());
+        buf.append("]");
+        return buf.toString();
+    }
+
+}

Propchange: httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/NHttpClientProtocolHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/NHttpClientProtocolHandler.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpasyncclient/trunk/src/main/java/org/apache/http/impl/nio/client/NHttpClientProtocolHandler.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpasyncclient/trunk/src/test/java/org/apache/http/impl/nio/client/TestHttpAsync.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/src/test/java/org/apache/http/impl/nio/client/TestHttpAsync.java?rev=1038668&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/src/test/java/org/apache/http/impl/nio/client/TestHttpAsync.java
(added)
+++ httpcomponents/httpasyncclient/trunk/src/test/java/org/apache/http/impl/nio/client/TestHttpAsync.java
Wed Nov 24 16:15:29 2010
@@ -0,0 +1,144 @@
+package org.apache.http.impl.nio.client;
+
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.Random;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.nio.conn.BasicIOSessionManager;
+import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
+import org.apache.http.localserver.ServerTestBase;
+import org.apache.http.nio.client.AsyncHttpClient;
+import org.apache.http.nio.client.HttpExchange;
+import org.apache.http.nio.entity.NByteArrayEntity;
+import org.apache.http.nio.reactor.ConnectingIOReactor;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.util.EntityUtils;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestHttpAsync extends ServerTestBase {
+
+    private HttpHost target;
+    private BasicIOSessionManager sessionManager;
+    private AsyncHttpClient httpclient;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        this.localServer.registerDefaultHandlers();
+        int port = this.localServer.getServiceAddress().getPort();
+        this.target = new HttpHost("localhost", port);
+        ConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(2, new BasicHttpParams());
+        this.sessionManager = new BasicIOSessionManager(ioReactor);
+        this.httpclient = new BasicAsyncHttpClient(ioReactor, this.sessionManager, null);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        this.httpclient.shutdown();
+        super.tearDown();
+    }
+
+    @Test
+    public void testSingleGet() throws Exception {
+        this.httpclient.start();
+        HttpGet httpget = new HttpGet("/random/2048");
+        HttpExchange httpexg = this.httpclient.execute(this.target, httpget);
+        HttpResponse response = httpexg.awaitResponse();
+        Assert.assertNotNull(response);
+        Assert.assertEquals(200, response.getStatusLine().getStatusCode());
+    }
+
+    @Test
+    public void testSinglePost() throws Exception {
+        byte[] b1 = new byte[1024];
+        Random rnd = new Random(System.currentTimeMillis());
+        rnd.nextBytes(b1);
+
+        this.httpclient.start();
+
+        HttpPost httppost = new HttpPost("/echo/stuff");
+        httppost.setEntity(new NByteArrayEntity(b1));
+
+        HttpExchange httpexg = this.httpclient.execute(this.target, httppost);
+        HttpResponse response = httpexg.awaitResponse();
+        Assert.assertNotNull(response);
+        Assert.assertEquals(200, response.getStatusLine().getStatusCode());
+        HttpEntity entity = response.getEntity();
+        Assert.assertNotNull(entity);
+        byte[] b2 = EntityUtils.toByteArray(entity);
+        Assert.assertArrayEquals(b1, b2);
+    }
+
+    @Test
+    public void testMultiplePostsOverMultipleConnections() throws Exception {
+        byte[] b1 = new byte[1024];
+        Random rnd = new Random(System.currentTimeMillis());
+        rnd.nextBytes(b1);
+
+        int reqCount = 20;
+
+        this.sessionManager.setDefaultMaxPerHost(reqCount);
+        this.sessionManager.setTotalMax(100);
+        this.httpclient.start();
+
+        Queue<HttpExchange> queue = new LinkedList<HttpExchange>();
+
+        for (int i = 0; i < reqCount; i++) {
+            HttpPost httppost = new HttpPost("/echo/stuff");
+            httppost.setEntity(new NByteArrayEntity(b1));
+            queue.add(this.httpclient.execute(this.target, httppost));
+        }
+
+        while (!queue.isEmpty()) {
+            HttpExchange httpexg = queue.remove();
+            HttpResponse response = httpexg.awaitResponse();
+            Assert.assertNotNull(response);
+            Assert.assertEquals(200, response.getStatusLine().getStatusCode());
+            HttpEntity entity = response.getEntity();
+            Assert.assertNotNull(entity);
+            byte[] b2 = EntityUtils.toByteArray(entity);
+            Assert.assertArrayEquals(b1, b2);
+        }
+    }
+
+    @Test
+    public void testMultiplePostsOverSingleConnection() throws Exception {
+        byte[] b1 = new byte[1024];
+        Random rnd = new Random(System.currentTimeMillis());
+        rnd.nextBytes(b1);
+
+        int reqCount = 20;
+
+        this.sessionManager.setDefaultMaxPerHost(1);
+        this.sessionManager.setTotalMax(100);
+        this.httpclient.start();
+
+        Queue<HttpExchange> queue = new LinkedList<HttpExchange>();
+
+        for (int i = 0; i < reqCount; i++) {
+            HttpPost httppost = new HttpPost("/echo/stuff");
+            httppost.setEntity(new NByteArrayEntity(b1));
+            queue.add(this.httpclient.execute(this.target, httppost));
+        }
+
+        while (!queue.isEmpty()) {
+            HttpExchange httpexg = queue.remove();
+            HttpResponse response = httpexg.awaitResponse();
+            Assert.assertNotNull(response);
+            Assert.assertEquals(200, response.getStatusLine().getStatusCode());
+            HttpEntity entity = response.getEntity();
+            Assert.assertNotNull(entity);
+            byte[] b2 = EntityUtils.toByteArray(entity);
+            Assert.assertArrayEquals(b1, b2);
+        }
+    }
+
+}

Propchange: httpcomponents/httpasyncclient/trunk/src/test/java/org/apache/http/impl/nio/client/TestHttpAsync.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpasyncclient/trunk/src/test/java/org/apache/http/impl/nio/client/TestHttpAsync.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpasyncclient/trunk/src/test/java/org/apache/http/impl/nio/client/TestHttpAsync.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message