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 2013/04/02 22:10:04 UTC

svn commit: r1463727 [2/2] - in /httpcomponents/httpasyncclient/trunk/httpasyncclient/src: examples/org/apache/http/examples/nio/client/ main/java/org/apache/http/impl/nio/client/ main/java/org/apache/http/impl/nio/conn/ main/java/org/apache/http/nio/c...

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

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

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

Added: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/InternalState.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/InternalState.java?rev=1463727&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/InternalState.java (added)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/InternalState.java Tue Apr  2 20:10:03 2013
@@ -0,0 +1,214 @@
+/*
+ * ====================================================================
+ * 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.nio.ByteBuffer;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpRequestWrapper;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.routing.RouteTracker;
+import org.apache.http.nio.protocol.HttpAsyncRequestProducer;
+import org.apache.http.nio.protocol.HttpAsyncResponseConsumer;
+
+class InternalState {
+
+    private static final AtomicLong COUNTER = new AtomicLong(1);
+
+    private final long id;
+    private final HttpAsyncRequestProducer requestProducer;
+    private final HttpAsyncResponseConsumer<?> responseConsumer;
+    private final HttpClientContext localContext;
+
+    private boolean routeEstablished;
+    private RouteTracker routeTracker;
+    private boolean reusable;
+    private long validDuration;
+
+    private HttpRoute route;
+    private HttpRequestWrapper mainRequest;
+    private HttpResponse finalResponse;
+    private HttpRequestWrapper currentRequest;
+    private HttpResponse currentResponse;
+    private ByteBuffer tmpbuf;
+    private boolean requestContentProduced;
+    private int execCount;
+
+    private int redirectCount;
+    private HttpUriRequest redirect;
+
+    public InternalState(
+            final HttpAsyncRequestProducer requestProducer,
+            final HttpAsyncResponseConsumer<?> responseConsumer,
+            final HttpClientContext localContext) {
+        super();
+        this.id = COUNTER.getAndIncrement();
+        this.requestProducer = requestProducer;
+        this.responseConsumer = responseConsumer;
+        this.localContext = localContext;
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public HttpAsyncRequestProducer getRequestProducer() {
+        return requestProducer;
+    }
+
+    public HttpAsyncResponseConsumer<?> getResponseConsumer() {
+        return responseConsumer;
+    }
+
+    public HttpClientContext getLocalContext() {
+        return localContext;
+    }
+
+    public boolean isRouteEstablished() {
+        return routeEstablished;
+    }
+
+    public void setRouteEstablished(final boolean b) {
+        this.routeEstablished = b;
+    }
+
+    public RouteTracker getRouteTracker() {
+        return routeTracker;
+    }
+
+    public void setRouteTracker(final RouteTracker routeTracker) {
+        this.routeTracker = routeTracker;
+    }
+
+    public boolean isReusable() {
+        return reusable;
+    }
+
+    public void setReusable() {
+        this.reusable = true;
+    }
+
+    public void setNonReusable() {
+        this.reusable = false;
+    }
+
+    public long getValidDuration() {
+        return validDuration;
+    }
+
+    public void setValidDuration(final long validDuration) {
+        this.validDuration = validDuration;
+    }
+
+    public HttpRoute getRoute() {
+        return route;
+    }
+
+    public void setRoute(final HttpRoute route) {
+        this.route = route;
+    }
+
+    public HttpRequestWrapper getMainRequest() {
+        return mainRequest;
+    }
+
+    public void setMainRequest(final HttpRequestWrapper mainRequest) {
+        this.mainRequest = mainRequest;
+    }
+
+    public HttpResponse getFinalResponse() {
+        return finalResponse;
+    }
+
+    public void setFinalResponse(final HttpResponse finalResponse) {
+        this.finalResponse = finalResponse;
+    }
+
+    public HttpRequestWrapper getCurrentRequest() {
+        return currentRequest;
+    }
+
+    public void setCurrentRequest(final HttpRequestWrapper currentRequest) {
+        this.currentRequest = currentRequest;
+    }
+
+    public HttpResponse getCurrentResponse() {
+        return currentResponse;
+    }
+
+    public void setCurrentResponse(final HttpResponse currentResponse) {
+        this.currentResponse = currentResponse;
+    }
+
+    public ByteBuffer getTmpbuf() {
+        if (tmpbuf == null) {
+            tmpbuf = ByteBuffer.allocate(4 * 1024);
+        }
+        return tmpbuf;
+    }
+
+    public boolean isRequestContentProduced() {
+        return requestContentProduced;
+    }
+
+    public void setRequestContentProduced() {
+        this.requestContentProduced = true;
+    }
+
+    public int getExecCount() {
+        return execCount;
+    }
+
+    public void incrementExecCount() {
+        this.execCount++;
+    }
+
+    public int getRedirectCount() {
+        return redirectCount;
+    }
+
+    public void incrementRedirectCount() {
+        this.redirectCount++;
+    }
+
+    public HttpUriRequest getRedirect() {
+        return redirect;
+    }
+
+    public void setRedirect(final HttpUriRequest redirect) {
+        this.redirect = redirect;
+    }
+
+    @Override
+    public String toString() {
+        return Long.toString(id);
+    }
+
+}

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

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

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

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/LoggingAsyncRequestExecutor.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/LoggingAsyncRequestExecutor.java?rev=1463727&r1=1463726&r2=1463727&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/LoggingAsyncRequestExecutor.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/LoggingAsyncRequestExecutor.java Tue Apr  2 20:10:03 2013
@@ -36,7 +36,6 @@ import org.apache.http.nio.ContentDecode
 import org.apache.http.nio.ContentEncoder;
 import org.apache.http.nio.NHttpClientConnection;
 import org.apache.http.nio.protocol.HttpAsyncRequestExecutor;
-import org.apache.http.protocol.HttpContext;
 
 class LoggingAsyncRequestExecutor extends HttpAsyncRequestExecutor {
 
@@ -70,14 +69,6 @@ class LoggingAsyncRequestExecutor extend
     }
 
     @Override
-    public void exception(final NHttpClientConnection conn, final Exception ex) {
-        if (this.log.isErrorEnabled()) {
-            this.log.error(conn + " HTTP protocol exception: " + ex.getMessage(), ex);
-        }
-        super.exception(conn, ex);
-    }
-
-    @Override
     public void requestReady(
             final NHttpClientConnection conn) throws IOException, HttpException {
         if (this.log.isDebugEnabled()) {
@@ -131,13 +122,10 @@ class LoggingAsyncRequestExecutor extend
 
     @Override
     public void endOfInput(final NHttpClientConnection conn) throws IOException {
-        super.endOfInput(conn);
-        HttpContext context = conn.getContext();
-        DefaultAsyncRequestDirector<?> handler = (DefaultAsyncRequestDirector<?>) context.getAttribute(
-            HTTP_HANDLER);
-        if (handler != null && !handler.isDone()) {
-            handler.endOfStream();
+        if (this.log.isDebugEnabled()) {
+            this.log.debug(conn + " End of input");
         }
+        super.endOfInput(conn);
     }
 
 }

Added: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/MainClientExec.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/MainClientExec.java?rev=1463727&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/MainClientExec.java (added)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/MainClientExec.java Tue Apr  2 20:10:03 2013
@@ -0,0 +1,575 @@
+/*
+ * ====================================================================
+ * 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 java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.ByteBuffer;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.ConnectionReuseStrategy;
+import org.apache.http.HttpException;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.HttpVersion;
+import org.apache.http.ProtocolException;
+import org.apache.http.auth.AUTH;
+import org.apache.http.auth.AuthProtocolState;
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.AuthState;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.AuthenticationStrategy;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.NonRepeatableRequestException;
+import org.apache.http.client.RedirectException;
+import org.apache.http.client.RedirectStrategy;
+import org.apache.http.client.UserTokenHandler;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.Configurable;
+import org.apache.http.client.methods.HttpRequestWrapper;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.protocol.ClientContext;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.client.utils.URIUtils;
+import org.apache.http.conn.ConnectionKeepAliveStrategy;
+import org.apache.http.conn.routing.BasicRouteDirector;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.routing.HttpRouteDirector;
+import org.apache.http.conn.routing.HttpRoutePlanner;
+import org.apache.http.conn.routing.RouteTracker;
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.impl.execchain.HttpAuthenticator;
+import org.apache.http.message.BasicHttpRequest;
+import org.apache.http.nio.ContentDecoder;
+import org.apache.http.nio.ContentEncoder;
+import org.apache.http.nio.IOControl;
+import org.apache.http.nio.NHttpClientConnection;
+import org.apache.http.nio.conn.NHttpClientConnectionManager;
+import org.apache.http.nio.protocol.HttpAsyncRequestProducer;
+import org.apache.http.nio.protocol.HttpAsyncResponseConsumer;
+import org.apache.http.protocol.ExecutionContext;
+
+class MainClientExec implements InternalClientExec {
+
+    private final Log log = LogFactory.getLog(getClass());
+
+    private final NHttpClientConnectionManager connmgr;
+    private final HttpRoutePlanner routePlanner;
+    private final ConnectionKeepAliveStrategy keepaliveStrategy;
+    private final AuthenticationStrategy targetAuthStrategy;
+    private final AuthenticationStrategy proxyAuthStrategy;
+    private final UserTokenHandler userTokenHandler;
+    private final RedirectStrategy redirectStrategy;
+    private final HttpRouteDirector routeDirector;
+    private final HttpAuthenticator authenticator;
+
+    public MainClientExec(
+            final NHttpClientConnectionManager connmgr,
+            final HttpRoutePlanner routePlanner,
+            final ConnectionReuseStrategy reuseStrategy,
+            final ConnectionKeepAliveStrategy keepaliveStrategy,
+            final RedirectStrategy redirectStrategy,
+            final AuthenticationStrategy targetAuthStrategy,
+            final AuthenticationStrategy proxyAuthStrategy,
+            final UserTokenHandler userTokenHandler) {
+        super();
+        this.connmgr = connmgr;
+        this.routePlanner = routePlanner;
+        this.keepaliveStrategy = keepaliveStrategy;
+        this.redirectStrategy = redirectStrategy;
+        this.targetAuthStrategy = targetAuthStrategy;
+        this.proxyAuthStrategy = proxyAuthStrategy;
+        this.userTokenHandler = userTokenHandler;
+        this.routeDirector = new BasicRouteDirector();
+        this.authenticator = new HttpAuthenticator(log);
+    }
+
+    public void prepare(
+            final InternalState state,
+            final HttpHost target,
+            final HttpRequest original) throws HttpException, IOException {
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("[exchange: " + state.getId() + "] start execution");
+        }
+
+        final HttpClientContext localContext = state.getLocalContext();
+        final HttpRequestWrapper request = HttpRequestWrapper.wrap(original);
+        final HttpRoute route = this.routePlanner.determineRoute(target, request, localContext);
+        state.setRoute(route);
+        state.setMainRequest(request);
+        state.setCurrentRequest(request);
+
+        if (original instanceof Configurable) {
+            final RequestConfig config = ((Configurable) original).getConfig();
+            if (config != null) {
+                localContext.setRequestConfig(config);
+            }
+        }
+        prepareRequest(state);
+    }
+
+    public HttpRequest generateRequest(
+            final InternalState state,
+            final InternalConnManager connManager) throws IOException, HttpException {
+        final HttpClientContext localContext = state.getLocalContext();
+        final HttpAsyncRequestProducer requestProducer = state.getRequestProducer();
+        final HttpRoute route = state.getRoute();
+        final RouteTracker routeTracker = state.getRouteTracker();
+        final NHttpClientConnection managedConn = connManager.getConnection();
+        if (!state.isRouteEstablished()) {
+            int step;
+            loop:
+            do {
+                final HttpRoute fact = routeTracker.toRoute();
+                step = this.routeDirector.nextStep(route, fact);
+                switch (step) {
+                case HttpRouteDirector.CONNECT_TARGET:
+                    this.connmgr.initialize(managedConn, route, localContext);
+                    routeTracker.connectTarget(route.isSecure());
+                    break;
+                case HttpRouteDirector.CONNECT_PROXY:
+                    this.connmgr.initialize(managedConn, route, localContext);
+                    final HttpHost proxy  = route.getProxyHost();
+                    routeTracker.connectProxy(proxy, false);
+                    break;
+                case HttpRouteDirector.TUNNEL_TARGET:
+                    if (this.log.isDebugEnabled()) {
+                        this.log.debug("[exchange: " + state.getId() + "] Tunnel required");
+                    }
+                    final HttpRequest connect = createConnectRequest(route);
+                    state.setCurrentRequest(HttpRequestWrapper.wrap(connect));
+                    break loop;
+                case HttpRouteDirector.TUNNEL_PROXY:
+                    throw new HttpException("Proxy chains are not supported");
+                case HttpRouteDirector.LAYER_PROTOCOL:
+                    this.connmgr.upgrade(managedConn, route, localContext);
+                    routeTracker.layerProtocol(route.isSecure());
+                    break;
+                case HttpRouteDirector.UNREACHABLE:
+                    throw new HttpException("Unable to establish route: " +
+                            "planned = " + route + "; current = " + fact);
+                case HttpRouteDirector.COMPLETE:
+                    this.connmgr.routeComplete(managedConn, route, localContext);
+                    state.setRouteEstablished(true);
+                    state.setRouteTracker(null);
+                    break;
+                default:
+                    throw new IllegalStateException("Unknown step indicator "
+                            + step + " from RouteDirector.");
+                }
+            } while (step > HttpRouteDirector.COMPLETE);
+        }
+
+        HttpRequestWrapper currentRequest = state.getCurrentRequest();
+        if (currentRequest == null) {
+            currentRequest = state.getMainRequest();
+            state.setCurrentRequest(currentRequest);
+        }
+
+        if (state.isRouteEstablished()) {
+            state.incrementExecCount();
+            if (state.getExecCount() > 1
+                    && !requestProducer.isRepeatable()
+                    && state.isRequestContentProduced()) {
+                throw new NonRepeatableRequestException("Cannot retry request " +
+                    "with a non-repeatable request entity.");
+            }
+            if (this.log.isDebugEnabled()) {
+                this.log.debug("[exchange: " + state.getId() + "] Attempt " + state.getExecCount() +
+                    " to execute request");
+            }
+
+            if (!currentRequest.containsHeader(AUTH.WWW_AUTH_RESP)) {
+                final AuthState targetAuthState = localContext.getTargetAuthState();
+                if (this.log.isDebugEnabled()) {
+                    this.log.debug("Target auth state: " + targetAuthState.getState());
+                }
+                this.authenticator.generateAuthResponse(currentRequest, targetAuthState, localContext);
+            }
+            if (!currentRequest.containsHeader(AUTH.PROXY_AUTH_RESP) && !route.isTunnelled()) {
+                final AuthState proxyAuthState = localContext.getProxyAuthState();
+                if (this.log.isDebugEnabled()) {
+                    this.log.debug("Proxy auth state: " + proxyAuthState.getState());
+                }
+                this.authenticator.generateAuthResponse(currentRequest, proxyAuthState, localContext);
+            }
+        } else {
+            if (!currentRequest.containsHeader(AUTH.PROXY_AUTH_RESP)) {
+                final AuthState proxyAuthState = localContext.getProxyAuthState();
+                if (this.log.isDebugEnabled()) {
+                    this.log.debug("Proxy auth state: " + proxyAuthState.getState());
+                }
+                this.authenticator.generateAuthResponse(currentRequest, proxyAuthState, localContext);
+            }
+        }
+        return currentRequest;
+    }
+
+    public void produceContent(
+            final InternalState state,
+            final ContentEncoder encoder,
+            final IOControl ioctrl) throws IOException {
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("[exchange: " + state.getId() + "] produce content");
+        }
+        final HttpAsyncRequestProducer requestProducer = state.getRequestProducer();
+        state.setRequestContentProduced();
+        requestProducer.produceContent(encoder, ioctrl);
+        if (encoder.isCompleted()) {
+            requestProducer.resetRequest();
+        }
+    }
+
+    public void requestCompleted(final InternalState state) {
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("[exchange: " + state.getId() + "] Request completed");
+        }
+        final HttpClientContext localContext = state.getLocalContext();
+        final HttpAsyncRequestProducer requestProducer = state.getRequestProducer();
+        requestProducer.requestCompleted(localContext);
+    }
+
+    public void responseReceived(
+            final InternalState state,
+            final HttpResponse response) throws IOException, HttpException {
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("[exchange: " + state.getId() + "] Response received " + response.getStatusLine());
+        }
+        state.setCurrentResponse(response);
+
+        if (!state.isRouteEstablished()) {
+            final int status = response.getStatusLine().getStatusCode();
+            if (status < 200) {
+                throw new HttpException("Unexpected response to CONNECT request: " +
+                        response.getStatusLine());
+            }
+            if (status == HttpStatus.SC_OK) {
+                final RouteTracker routeTracker = state.getRouteTracker();
+                routeTracker.tunnelTarget(false);
+                state.setCurrentRequest(null);
+            } else {
+                if (!handleConnectResponse(state)) {
+                    state.setFinalResponse(response);
+                }
+            }
+        } else {
+            if (!handleResponse(state)) {
+                state.setFinalResponse(response);
+            }
+        }
+        if (state.getFinalResponse() != null) {
+            final HttpAsyncResponseConsumer<?> responseConsumer = state.getResponseConsumer();
+            responseConsumer.responseReceived(response);
+        }
+    }
+
+    public void consumeContent(
+            final InternalState state,
+            final ContentDecoder decoder,
+            final IOControl ioctrl) throws IOException {
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("[exchange: " + state.getId() + "] Consume content");
+        }
+        if (state.getFinalResponse() != null) {
+            final HttpAsyncResponseConsumer<?> responseConsumer = state.getResponseConsumer();
+            responseConsumer.consumeContent(decoder, ioctrl);
+        } else {
+            final ByteBuffer tmpbuf = state.getTmpbuf();
+            tmpbuf.clear();
+            decoder.read(tmpbuf);
+        }
+    }
+
+    public void responseCompleted(
+            final InternalState state,
+            final InternalConnManager connManager) throws HttpException {
+        final HttpClientContext localContext = state.getLocalContext();
+        final HttpResponse currentResponse = state.getCurrentResponse();
+
+        if (connManager.getConnection().isOpen()) {
+            final long validDuration = this.keepaliveStrategy.getKeepAliveDuration(
+                    currentResponse, localContext);
+            if (this.log.isDebugEnabled()) {
+                String s;
+                if (validDuration > 0) {
+                    s = "for " + validDuration + " " + TimeUnit.MILLISECONDS;
+                } else {
+                    s = "indefinitely";
+                }
+                this.log.debug("[exchange: " + state.getId() + "] Connection can be kept alive " + s);
+            }
+            state.setValidDuration(validDuration);
+            state.setReusable();
+        } else {
+            if (this.log.isDebugEnabled()) {
+                this.log.debug("[exchange: " + state.getId() + "] Connection cannot be kept alive");
+            }
+            state.setNonReusable();
+            final AuthState proxyAuthState = localContext.getProxyAuthState();
+            if (proxyAuthState.getState() == AuthProtocolState.SUCCESS
+                    && proxyAuthState.getAuthScheme() != null
+                    && proxyAuthState.getAuthScheme().isConnectionBased()) {
+                if (this.log.isDebugEnabled()) {
+                    this.log.debug("[exchange: " + state.getId() + "] Resetting proxy auth state");
+                }
+                proxyAuthState.reset();
+            }
+            final AuthState targetAuthState = localContext.getTargetAuthState();
+            if (targetAuthState.getState() == AuthProtocolState.SUCCESS
+                    && targetAuthState.getAuthScheme() != null
+                    && targetAuthState.getAuthScheme().isConnectionBased()) {
+                if (this.log.isDebugEnabled()) {
+                    this.log.debug("[exchange: " + state.getId() + "] Resetting target auth state");
+                }
+                targetAuthState.reset();
+            }
+        }
+
+        Object userToken = localContext.getUserToken();
+        if (userToken == null) {
+            userToken = this.userTokenHandler.getUserToken(localContext);
+            localContext.setAttribute(ClientContext.USER_TOKEN, userToken);
+        }
+
+        if (state.getFinalResponse() != null) {
+            final HttpAsyncResponseConsumer<?> responseConsumer = state.getResponseConsumer();
+            responseConsumer.responseCompleted(localContext);
+            if (this.log.isDebugEnabled()) {
+                this.log.debug("[exchange: " + state.getId() + "] Response processed");
+            }
+            connManager.releaseConnection();
+        } else {
+            if (state.getRedirect() != null) {
+                final HttpUriRequest redirect = state.getRedirect();
+                final URI uri = redirect.getURI();
+                if (this.log.isDebugEnabled()) {
+                    this.log.debug("[exchange: " + state.getId() + "] Redirecting to '" + uri + "'");
+                }
+                state.setRedirect(null);
+
+                final HttpHost newTarget = URIUtils.extractHost(uri);
+                if (newTarget == null) {
+                    throw new ProtocolException("Redirect URI does not specify a valid host name: " + uri);
+                }
+
+                // Reset auth states if redirecting to another host
+                final HttpRoute route = state.getRoute();
+                if (!route.getTargetHost().equals(newTarget)) {
+                    final AuthState targetAuthState = localContext.getTargetAuthState();
+                    if (this.log.isDebugEnabled()) {
+                        this.log.debug("[exchange: " + state.getId() + "] Resetting target auth state");
+                    }
+                    targetAuthState.reset();
+                    final AuthState proxyAuthState = localContext.getProxyAuthState();
+                    final AuthScheme authScheme = proxyAuthState.getAuthScheme();
+                    if (authScheme != null && authScheme.isConnectionBased()) {
+                        if (this.log.isDebugEnabled()) {
+                            this.log.debug("[exchange: " + state.getId() + "] Resetting proxy auth state");
+                        }
+                        proxyAuthState.reset();
+                    }
+                }
+
+                final HttpRequestWrapper newRequest = HttpRequestWrapper.wrap(redirect);
+                final HttpRoute newRoute = this.routePlanner.determineRoute(
+                    newTarget, newRequest, localContext);
+                state.setRoute(newRoute);
+                state.setMainRequest(newRequest);
+                state.setCurrentRequest(newRequest);
+                if (!route.equals(newRoute)) {
+                    connManager.releaseConnection();
+                }
+                prepareRequest(state);
+            }
+        }
+        state.setCurrentResponse(null);
+    }
+
+    private void rewriteRequestURI(final InternalState state) throws ProtocolException {
+        final HttpRequestWrapper request = state.getCurrentRequest();
+        final HttpRoute route = state.getRoute();
+        try {
+            URI uri = request.getURI();
+            if (uri != null) {
+                if (route.getProxyHost() != null && !route.isTunnelled()) {
+                    // Make sure the request URI is absolute
+                    if (!uri.isAbsolute()) {
+                        final HttpHost target = route.getTargetHost();
+                        uri = URIUtils.rewriteURI(uri, target, true);
+                    } else {
+                        uri = URIUtils.rewriteURI(uri);
+                    }
+                } else {
+                    // Make sure the request URI is relative
+                    if (uri.isAbsolute()) {
+                        uri = URIUtils.rewriteURI(uri, null, true);
+                    } else {
+                        uri = URIUtils.rewriteURI(uri);
+                    }
+                }
+                request.setURI(uri);
+            }
+        } catch (final URISyntaxException ex) {
+            throw new ProtocolException("Invalid URI: " +
+                    request.getRequestLine().getUri(), ex);
+        }
+    }
+
+    private void prepareRequest(final InternalState state) throws HttpException {
+        final HttpClientContext localContext = state.getLocalContext();
+        final HttpRequestWrapper currentRequest = state.getCurrentRequest();
+        final HttpRoute route = state.getRoute();
+        // Get user info from the URI
+        final URI requestURI = currentRequest.getURI();
+        if (requestURI != null) {
+            final String userinfo = requestURI.getUserInfo();
+            if (userinfo != null) {
+                final AuthState targetAuthState = localContext.getTargetAuthState();
+                targetAuthState.update(new BasicScheme(), new UsernamePasswordCredentials(userinfo));
+            }
+        }
+
+        HttpHost target = null;
+        final HttpRequest original = currentRequest.getOriginal();
+        URI uri = null;
+        if (original instanceof HttpUriRequest) {
+            uri = ((HttpUriRequest) original).getURI();
+        } else {
+            final String uriString = original.getRequestLine().getUri();
+            try {
+                uri = URI.create(uriString);
+            } catch (final IllegalArgumentException ex) {
+                if (this.log.isDebugEnabled()) {
+                    this.log.debug("Unable to parse '" + uriString + "' request URI: " + ex.getMessage());
+                }
+            }
+        }
+        if (uri != null && uri.isAbsolute() && uri.getHost() != null) {
+            target = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
+        }
+        if (target == null) {
+            target = route.getTargetHost();
+        }
+
+        // Re-write request URI if needed
+        rewriteRequestURI(state);
+
+        localContext.setAttribute(ExecutionContext.HTTP_TARGET_HOST, target);
+        localContext.setAttribute(ClientContext.ROUTE, route);
+    }
+
+    private HttpRequest createConnectRequest(final HttpRoute route) {
+        // see RFC 2817, section 5.2 and
+        // INTERNET-DRAFT: Tunneling TCP based protocols through
+        // Web proxy servers
+        final HttpHost target = route.getTargetHost();
+        final String host = target.getHostName();
+        final int port = target.getPort();
+        final StringBuilder buffer = new StringBuilder(host.length() + 6);
+        buffer.append(host);
+        buffer.append(':');
+        buffer.append(Integer.toString(port));
+        return new BasicHttpRequest("CONNECT", buffer.toString(), HttpVersion.HTTP_1_1);
+    }
+
+    private boolean handleConnectResponse(final InternalState state) throws HttpException {
+        final HttpClientContext localContext = state.getLocalContext();
+        final RequestConfig config = localContext.getRequestConfig();
+        if (config.isAuthenticationEnabled()) {
+            final CredentialsProvider credsProvider = localContext.getCredentialsProvider();
+            if (credsProvider != null) {
+                final HttpRoute route = state.getRoute();
+                final HttpHost proxy = route.getProxyHost();
+                final HttpResponse currentResponse = state.getCurrentResponse();
+                final AuthState proxyAuthState = localContext.getProxyAuthState();
+                if (this.authenticator.isAuthenticationRequested(proxy, currentResponse,
+                        this.proxyAuthStrategy, proxyAuthState, localContext)) {
+                    return this.authenticator.handleAuthChallenge(proxy, currentResponse,
+                            this.proxyAuthStrategy, proxyAuthState, localContext);
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean handleResponse(final InternalState state) throws HttpException {
+        final HttpClientContext localContext = state.getLocalContext();
+        final RequestConfig config = localContext.getRequestConfig();
+        if (config.isAuthenticationEnabled()) {
+            final CredentialsProvider credsProvider = localContext.getCredentialsProvider();
+            if (credsProvider != null) {
+                final HttpRoute route = state.getRoute();
+                final HttpResponse currentResponse = state.getCurrentResponse();
+                HttpHost target = localContext.getTargetHost();
+                if (target == null) {
+                    target = route.getTargetHost();
+                }
+                if (target.getPort() < 0) {
+                    target = new HttpHost(
+                            target.getHostName(),
+                            route.getTargetHost().getPort(),
+                            target.getSchemeName());
+                }
+                final AuthState targetAuthState = localContext.getTargetAuthState();
+                if (this.authenticator.isAuthenticationRequested(target, currentResponse,
+                        this.targetAuthStrategy, targetAuthState, localContext)) {
+                    return this.authenticator.handleAuthChallenge(target, currentResponse,
+                            this.targetAuthStrategy, targetAuthState, localContext);
+                }
+                final HttpHost proxy = route.getProxyHost();
+                final AuthState proxyAuthState = localContext.getProxyAuthState();
+                if (this.authenticator.isAuthenticationRequested(proxy, currentResponse,
+                        this.proxyAuthStrategy, proxyAuthState, localContext)) {
+                    return this.authenticator.handleAuthChallenge(proxy, currentResponse,
+                            this.proxyAuthStrategy, proxyAuthState, localContext);
+                }
+            }
+        }
+        if (config.isRedirectsEnabled()) {
+            final HttpRequest currentRequest = state.getCurrentRequest();
+            final HttpResponse currentResponse = state.getCurrentResponse();
+            if (this.redirectStrategy.isRedirected(currentRequest, currentResponse, localContext)) {
+                final int maxRedirects = config.getMaxRedirects() >= 0 ? config.getMaxRedirects() : 100;
+                if (state.getRedirectCount() >= maxRedirects) {
+                    throw new RedirectException("Maximum redirects (" + maxRedirects + ") exceeded");
+                }
+                state.incrementRedirectCount();
+                final HttpUriRequest redirect = this.redirectStrategy.getRedirect(currentRequest, currentResponse,
+                    localContext);
+                state.setRedirect(redirect);
+                return true;
+            }
+        }
+        return false;
+    }
+
+}

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

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

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

Added: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/MinimalClientExec.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/MinimalClientExec.java?rev=1463727&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/MinimalClientExec.java (added)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/MinimalClientExec.java Tue Apr  2 20:10:03 2013
@@ -0,0 +1,218 @@
+/*
+ * ====================================================================
+ * 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 java.net.URI;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.ConnectionReuseStrategy;
+import org.apache.http.HttpException;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.AuthenticationStrategy;
+import org.apache.http.client.RedirectStrategy;
+import org.apache.http.client.UserTokenHandler;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.Configurable;
+import org.apache.http.client.methods.HttpRequestWrapper;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.protocol.ClientContext;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.conn.ConnectionKeepAliveStrategy;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.routing.HttpRoutePlanner;
+import org.apache.http.nio.ContentDecoder;
+import org.apache.http.nio.ContentEncoder;
+import org.apache.http.nio.IOControl;
+import org.apache.http.nio.NHttpClientConnection;
+import org.apache.http.nio.conn.NHttpClientConnectionManager;
+import org.apache.http.nio.protocol.HttpAsyncRequestProducer;
+import org.apache.http.nio.protocol.HttpAsyncResponseConsumer;
+import org.apache.http.protocol.ExecutionContext;
+
+class MinimalClientExec implements InternalClientExec {
+
+    private final Log log = LogFactory.getLog(getClass());
+
+    private final NHttpClientConnectionManager connmgr;
+    private final HttpRoutePlanner routePlanner;
+    private final ConnectionKeepAliveStrategy keepaliveStrategy;
+
+    public MinimalClientExec(
+            final NHttpClientConnectionManager connmgr,
+            final HttpRoutePlanner routePlanner,
+            final ConnectionReuseStrategy reuseStrategy,
+            final ConnectionKeepAliveStrategy keepaliveStrategy,
+            final RedirectStrategy redirectStrategy,
+            final AuthenticationStrategy targetAuthStrategy,
+            final AuthenticationStrategy proxyAuthStrategy,
+            final UserTokenHandler userTokenHandler) {
+        super();
+        this.connmgr = connmgr;
+        this.routePlanner = routePlanner;
+        this.keepaliveStrategy = keepaliveStrategy;
+    }
+
+    public void prepare(
+            final InternalState state,
+            final HttpHost target,
+            final HttpRequest original) throws HttpException, IOException {
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("[exchange: " + state.getId() + "] start execution");
+        }
+
+        final HttpClientContext localContext = state.getLocalContext();
+        final HttpRequestWrapper request = HttpRequestWrapper.wrap(original);
+        final HttpRoute route = this.routePlanner.determineRoute(target, request, localContext);
+
+        state.setRoute(route);
+        state.setMainRequest(request);
+        state.setCurrentRequest(request);
+
+        if (original instanceof Configurable) {
+            final RequestConfig config = ((Configurable) original).getConfig();
+            if (config != null) {
+                localContext.setRequestConfig(config);
+            }
+        }
+
+        HttpHost host = null;
+        if (original instanceof HttpUriRequest) {
+            final URI uri = ((HttpUriRequest) original).getURI();
+            if (uri.isAbsolute()) {
+                host = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
+            }
+        }
+        if (host == null) {
+            host = target;
+        }
+
+        localContext.setAttribute(ExecutionContext.HTTP_TARGET_HOST, host);
+        localContext.setAttribute(ClientContext.ROUTE, route);
+    }
+
+    public HttpRequest generateRequest(
+            final InternalState state,
+            final InternalConnManager connManager) throws IOException, HttpException {
+        if (state.isRouteEstablished()) {
+            final HttpClientContext localContext = state.getLocalContext();
+            final HttpRoute route = state.getRoute();
+            final NHttpClientConnection managedConn = connManager.getConnection();
+            this.connmgr.initialize(managedConn, route, localContext);
+            this.connmgr.routeComplete(managedConn, route, localContext);
+
+        }
+        if (state.getCurrentRequest() == null) {
+            state.setCurrentRequest(state.getMainRequest());
+        }
+        return state.getCurrentRequest();
+    }
+
+    public void produceContent(
+            final InternalState state,
+            final ContentEncoder encoder,
+            final IOControl ioctrl) throws IOException {
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("[exchange: " + state.getId() + "] produce content");
+        }
+        final HttpAsyncRequestProducer requestProducer = state.getRequestProducer();
+        requestProducer.produceContent(encoder, ioctrl);
+        if (encoder.isCompleted()) {
+            requestProducer.resetRequest();
+        }
+    }
+
+    public void requestCompleted(final InternalState state) {
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("[exchange: " + state.getId() + "] Request completed");
+        }
+        final HttpClientContext localContext = state.getLocalContext();
+        final HttpAsyncRequestProducer requestProducer = state.getRequestProducer();
+        requestProducer.requestCompleted(localContext);
+    }
+
+    public void responseReceived(
+            final InternalState state,
+            final HttpResponse response) throws IOException, HttpException {
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("[exchange: " + state.getId() + "] Response received " + response.getStatusLine());
+        }
+        state.setCurrentResponse(response);
+        final HttpAsyncResponseConsumer<?> responseConsumer = state.getResponseConsumer();
+        responseConsumer.responseReceived(response);
+    }
+
+    public void consumeContent(
+            final InternalState state,
+            final ContentDecoder decoder,
+            final IOControl ioctrl) throws IOException {
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("[exchange: " + state.getId() + "] Consume content");
+        }
+        final HttpAsyncResponseConsumer<?> responseConsumer = state.getResponseConsumer();
+        responseConsumer.consumeContent(decoder, ioctrl);
+    }
+
+    public void responseCompleted(
+            final InternalState state,
+            final InternalConnManager connManager) throws HttpException {
+        final HttpClientContext localContext = state.getLocalContext();
+        final HttpResponse currentResponse = state.getCurrentResponse();
+
+        if (connManager.getConnection().isOpen()) {
+            final long validDuration = this.keepaliveStrategy.getKeepAliveDuration(
+                    currentResponse, localContext);
+            if (this.log.isDebugEnabled()) {
+                String s;
+                if (validDuration > 0) {
+                    s = "for " + validDuration + " " + TimeUnit.MILLISECONDS;
+                } else {
+                    s = "indefinitely";
+                }
+                this.log.debug("[exchange: " + state.getId() + "] Connection can be kept alive " + s);
+            }
+            state.setValidDuration(validDuration);
+            state.setReusable();
+        } else {
+            if (this.log.isDebugEnabled()) {
+                this.log.debug("[exchange: " + state.getId() + "] Connection cannot be kept alive");
+            }
+            state.setNonReusable();
+        }
+        final HttpAsyncResponseConsumer<?> responseConsumer = state.getResponseConsumer();
+        responseConsumer.responseCompleted(localContext);
+        if (this.log.isDebugEnabled()) {
+            this.log.debug("[exchange: " + state.getId() + "] Response processed");
+        }
+        state.setFinalResponse(currentResponse);
+    }
+
+}

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

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

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

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/conn/PoolingNHttpClientConnectionManager.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/conn/PoolingNHttpClientConnectionManager.java?rev=1463727&r1=1463726&r2=1463727&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/conn/PoolingNHttpClientConnectionManager.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/impl/nio/conn/PoolingNHttpClientConnectionManager.java Tue Apr  2 20:10:03 2013
@@ -51,11 +51,11 @@ import org.apache.http.conn.routing.Http
 import org.apache.http.impl.conn.DefaultSchemePortResolver;
 import org.apache.http.impl.conn.SystemDefaultDnsResolver;
 import org.apache.http.nio.NHttpClientConnection;
-import org.apache.http.nio.conn.NHttpClientConnectionManager;
 import org.apache.http.nio.conn.ManagedNHttpClientConnection;
+import org.apache.http.nio.conn.NHttpClientConnectionManager;
 import org.apache.http.nio.conn.NHttpConnectionFactory;
-import org.apache.http.nio.conn.scheme.LayeringStrategy;
 import org.apache.http.nio.conn.ssl.SSLLayeringStrategy;
+import org.apache.http.nio.conn.ssl.SchemeLayeringStrategy;
 import org.apache.http.nio.pool.NIOConnFactory;
 import org.apache.http.nio.reactor.ConnectingIOReactor;
 import org.apache.http.nio.reactor.IOEventDispatch;
@@ -76,12 +76,12 @@ public class PoolingNHttpClientConnectio
     private final ConnectingIOReactor ioreactor;
     private final ConfigData configData;
     private final CPool pool;
-    private final Registry<LayeringStrategy> layeringStrategyRegistry;
+    private final Registry<SchemeLayeringStrategy> layeringStrategyRegistry;
     private final SchemePortResolver schemePortResolver;
     private final DnsResolver dnsResolver;
 
-    private static Registry<LayeringStrategy> getDefaultRegistry() {
-        return RegistryBuilder.<LayeringStrategy>create()
+    private static Registry<SchemeLayeringStrategy> getDefaultRegistry() {
+        return RegistryBuilder.<SchemeLayeringStrategy>create()
                 .register("https", SSLLayeringStrategy.getDefaultStrategy())
                 .build();
     }
@@ -92,7 +92,7 @@ public class PoolingNHttpClientConnectio
 
     public PoolingNHttpClientConnectionManager(
             final ConnectingIOReactor ioreactor,
-            final Registry<LayeringStrategy> layeringStrategyRegistry) {
+            final Registry<SchemeLayeringStrategy> layeringStrategyRegistry) {
         this(ioreactor, null, layeringStrategyRegistry, null);
     }
 
@@ -112,14 +112,14 @@ public class PoolingNHttpClientConnectio
     public PoolingNHttpClientConnectionManager(
             final ConnectingIOReactor ioreactor,
             final NHttpConnectionFactory<ManagedNHttpClientConnection> connFactory,
-            final Registry<LayeringStrategy> layeringStrategyRegistry) {
+            final Registry<SchemeLayeringStrategy> layeringStrategyRegistry) {
         this(ioreactor, connFactory, layeringStrategyRegistry, null);
     }
 
     public PoolingNHttpClientConnectionManager(
             final ConnectingIOReactor ioreactor,
             final NHttpConnectionFactory<ManagedNHttpClientConnection> connFactory,
-            final Registry<LayeringStrategy> layeringStrategyRegistry,
+            final Registry<SchemeLayeringStrategy> layeringStrategyRegistry,
             final DnsResolver dnsResolver) {
         this(ioreactor, connFactory, layeringStrategyRegistry, null, dnsResolver,
             -1, TimeUnit.MILLISECONDS);
@@ -128,7 +128,7 @@ public class PoolingNHttpClientConnectio
     public PoolingNHttpClientConnectionManager(
             final ConnectingIOReactor ioreactor,
             final NHttpConnectionFactory<ManagedNHttpClientConnection> connFactory,
-            final Registry<LayeringStrategy> layeringStrategyRegistry,
+            final Registry<SchemeLayeringStrategy> layeringStrategyRegistry,
             final SchemePortResolver schemePortResolver,
             final DnsResolver dnsResolver,
             final long timeToLive, final TimeUnit tunit) {
@@ -150,7 +150,7 @@ public class PoolingNHttpClientConnectio
     PoolingNHttpClientConnectionManager(
             final ConnectingIOReactor ioreactor,
             final CPool pool,
-            final Registry<LayeringStrategy> layeringStrategyRegistry,
+            final Registry<SchemeLayeringStrategy> layeringStrategyRegistry,
             final SchemePortResolver schemePortResolver,
             final DnsResolver dnsResolver,
             final long timeToLive, final TimeUnit tunit) {
@@ -343,13 +343,13 @@ public class PoolingNHttpClientConnectio
         } else {
             host = route.getTargetHost();
         }
-        final LayeringStrategy layeringStrategy = layeringStrategyRegistry.lookup(
+        final SchemeLayeringStrategy layeringStrategy = layeringStrategyRegistry.lookup(
                 host.getSchemeName());
         if (layeringStrategy != null) {
             synchronized (managedConn) {
                 final CPoolEntry entry = CPoolProxy.getPoolEntry(managedConn);
                 final ManagedNHttpClientConnection conn = entry.getConnection();
-                final IOSession currentSession = layeringStrategy.layer(conn.getIOSession());
+                final IOSession currentSession = layeringStrategy.layer(host, conn.getIOSession());
                 conn.bind(currentSession);
             }
         }
@@ -362,13 +362,13 @@ public class PoolingNHttpClientConnectio
         Args.notNull(managedConn, "Managed connection");
         Args.notNull(route, "HTTP route");
         final HttpHost host  = route.getTargetHost();
-        final LayeringStrategy layeringStrategy = layeringStrategyRegistry.lookup(
+        final SchemeLayeringStrategy layeringStrategy = layeringStrategyRegistry.lookup(
             host.getSchemeName());
         synchronized (managedConn) {
             final CPoolEntry entry = CPoolProxy.getPoolEntry(managedConn);
             final ManagedNHttpClientConnection conn = entry.getConnection();
             Asserts.check(layeringStrategy != null, "Layering is not supported for this scheme");
-            final IOSession currentSession = layeringStrategy.layer(conn.getIOSession());
+            final IOSession currentSession = layeringStrategy.layer(host, conn.getIOSession());
             conn.bind(currentSession);
         }
     }

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/HttpAsyncClient.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/HttpAsyncClient.java?rev=1463727&r1=1463726&r2=1463727&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/HttpAsyncClient.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/HttpAsyncClient.java Tue Apr  2 20:10:03 2013
@@ -40,16 +40,22 @@ import org.apache.http.nio.reactor.IORea
 import org.apache.http.params.HttpParams;
 import org.apache.http.protocol.HttpContext;
 
+@SuppressWarnings("deprecation")
 public interface HttpAsyncClient {
 
+    @Deprecated
     void start();
 
+    @Deprecated
     void shutdown() throws InterruptedException;
 
+    @Deprecated
     IOReactorStatus getStatus();
 
+    @Deprecated
     ClientAsyncConnectionManager getConnectionManager();
 
+    @Deprecated
     HttpParams getParams();
 
     <T> Future<T> execute(

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/util/HttpAsyncClientUtils.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/util/HttpAsyncClientUtils.java?rev=1463727&r1=1463726&r2=1463727&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/util/HttpAsyncClientUtils.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/client/util/HttpAsyncClientUtils.java Tue Apr  2 20:10:03 2013
@@ -26,6 +26,9 @@
  */
 package org.apache.http.nio.client.util;
 
+import java.io.IOException;
+
+import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
 import org.apache.http.nio.client.HttpAsyncClient;
 
 /**
@@ -56,6 +59,16 @@ public class HttpAsyncClientUtils {
      * @param httpAsyncClient
      *            the HttpAsyncClient to close, may be null or already closed.
      */
+    public static void closeQuietly(final CloseableHttpAsyncClient httpAsyncClient) {
+        if (httpAsyncClient != null) {
+            try {
+                httpAsyncClient.close();
+            } catch (final IOException e) {
+            }
+        }
+    }
+
+    @Deprecated
     public static void closeQuietly(final HttpAsyncClient httpAsyncClient) {
         if (httpAsyncClient != null) {
             try {

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/scheme/LayeringStrategy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/scheme/LayeringStrategy.java?rev=1463727&r1=1463726&r2=1463727&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/scheme/LayeringStrategy.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/scheme/LayeringStrategy.java Tue Apr  2 20:10:03 2013
@@ -28,9 +28,9 @@ package org.apache.http.nio.conn.scheme;
 
 import org.apache.http.nio.reactor.IOSession;
 
+@Deprecated
 public interface LayeringStrategy {
 
-    @Deprecated
     boolean isSecure();
 
     IOSession layer(IOSession iosession);

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/ssl/SSLLayeringStrategy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/ssl/SSLLayeringStrategy.java?rev=1463727&r1=1463726&r2=1463727&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/ssl/SSLLayeringStrategy.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/ssl/SSLLayeringStrategy.java Tue Apr  2 20:10:03 2013
@@ -34,6 +34,8 @@ import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
@@ -45,6 +47,7 @@ import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
 
+import org.apache.http.HttpHost;
 import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
 import org.apache.http.conn.ssl.SSLSocketFactory;
 import org.apache.http.conn.ssl.TrustStrategy;
@@ -55,7 +58,8 @@ import org.apache.http.nio.reactor.ssl.S
 import org.apache.http.nio.reactor.ssl.SSLMode;
 import org.apache.http.nio.reactor.ssl.SSLSetupHandler;
 
-public class SSLLayeringStrategy implements LayeringStrategy {
+@SuppressWarnings("deprecation")
+public class SSLLayeringStrategy implements LayeringStrategy, SchemeLayeringStrategy {
 
     public static final String TLS   = "TLS";
     public static final String SSL   = "SSL";
@@ -179,34 +183,74 @@ public class SSLLayeringStrategy impleme
         return true;
     }
 
+    @Deprecated
     public SSLIOSession layer(final IOSession iosession) {
-        final SSLIOSession ssliosession = new SSLIOSession(iosession, SSLMode.CLIENT, this.sslContext,
-                new InternalSSLSetupHandler());
+        final SSLIOSession ssliosession = new SSLIOSession(
+            iosession,
+            SSLMode.CLIENT,
+            this.sslContext,
+            new SSLSetupHandler() {
+
+                public void initalize(
+                        final SSLEngine sslengine) throws SSLException {
+                    initializeEngine(sslengine);
+                }
+
+                public void verify(
+                        final IOSession iosession,
+                        final SSLSession sslsession) throws SSLException {
+                    verifySession(iosession, sslsession);
+                }
+
+        });
         iosession.setAttribute(SSLIOSession.SESSION_KEY, ssliosession);
         return ssliosession;
     }
 
-    protected void initializeEngine(final SSLEngine engine) {
-    }
+    public SSLIOSession layer(final HttpHost host, final IOSession iosession) {
+        final SSLIOSession ssliosession = new SSLIOSession(
+            iosession,
+            SSLMode.CLIENT,
+            this.sslContext,
+            new SSLSetupHandler() {
+
+                public void initalize(
+                        final SSLEngine sslengine) throws SSLException {
+                    initializeEngine(sslengine);
+                }
 
-    protected void verifySession(final IOSession iosession,
-                          final SSLSession sslsession) throws SSLException {
-        final InetSocketAddress address = (InetSocketAddress) iosession.getRemoteAddress();
-        hostnameVerifier.verify(address.getHostName(), sslsession);
+                public void verify(
+                        final IOSession iosession,
+                        final SSLSession sslsession) throws SSLException {
+                    verifySession(host, iosession, sslsession);
+                }
+
+        });
+        iosession.setAttribute(SSLIOSession.SESSION_KEY, ssliosession);
+        return ssliosession;
     }
 
-    class InternalSSLSetupHandler implements SSLSetupHandler {
+    protected void initializeEngine(final SSLEngine engine) {
+    }
 
-        public void initalize(
-                final SSLEngine sslengine) throws SSLException {
-            initializeEngine(sslengine);
-        }
+    @Deprecated
+    protected void verifySession(
+            final IOSession iosession,
+            final SSLSession sslsession) throws SSLException {
+        final InetSocketAddress address = (InetSocketAddress) iosession.getRemoteAddress();
 
-        public void verify(
-                final IOSession iosession,
-                final SSLSession sslsession) throws SSLException {
-            verifySession(iosession, sslsession);
-        }
+        final Certificate[] certs = sslsession.getPeerCertificates();
+        final X509Certificate x509 = (X509Certificate) certs[0];
+        hostnameVerifier.verify(address.getHostName(), x509);
+    }
 
+    protected void verifySession(
+            final HttpHost host,
+            final IOSession iosession,
+            final SSLSession sslsession) throws SSLException {
+        final Certificate[] certs = sslsession.getPeerCertificates();
+        final X509Certificate x509 = (X509Certificate) certs[0];
+        hostnameVerifier.verify(host.getHostName(), x509);
     }
+
 }

Copied: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/ssl/SchemeLayeringStrategy.java (from r1463726, httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/scheme/LayeringStrategy.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/ssl/SchemeLayeringStrategy.java?p2=httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/ssl/SchemeLayeringStrategy.java&p1=httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/scheme/LayeringStrategy.java&r1=1463726&r2=1463727&rev=1463727&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/scheme/LayeringStrategy.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/main/java/org/apache/http/nio/conn/ssl/SchemeLayeringStrategy.java Tue Apr  2 20:10:03 2013
@@ -24,15 +24,13 @@
  * <http://www.apache.org/>.
  *
  */
-package org.apache.http.nio.conn.scheme;
+package org.apache.http.nio.conn.ssl;
 
+import org.apache.http.HttpHost;
 import org.apache.http.nio.reactor.IOSession;
 
-public interface LayeringStrategy {
+public interface SchemeLayeringStrategy {
 
-    @Deprecated
-    boolean isSecure();
-
-    IOSession layer(IOSession iosession);
+    IOSession layer(HttpHost host, IOSession iosession);
 
 }

Modified: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/impl/nio/conn/TestPoolingHttpClientAsyncConnectionManager.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/impl/nio/conn/TestPoolingHttpClientAsyncConnectionManager.java?rev=1463727&r1=1463726&r2=1463727&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/impl/nio/conn/TestPoolingHttpClientAsyncConnectionManager.java (original)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/impl/nio/conn/TestPoolingHttpClientAsyncConnectionManager.java Tue Apr  2 20:10:03 2013
@@ -54,7 +54,7 @@ import org.apache.http.impl.nio.conn.Poo
 import org.apache.http.nio.NHttpClientConnection;
 import org.apache.http.nio.conn.ManagedNHttpClientConnection;
 import org.apache.http.nio.conn.NHttpConnectionFactory;
-import org.apache.http.nio.conn.scheme.LayeringStrategy;
+import org.apache.http.nio.conn.ssl.SchemeLayeringStrategy;
 import org.apache.http.nio.reactor.ConnectingIOReactor;
 import org.apache.http.nio.reactor.IOEventDispatch;
 import org.apache.http.nio.reactor.IOSession;
@@ -77,7 +77,7 @@ public class TestPoolingHttpClientAsyncC
     @Mock
     private CPool pool;
     @Mock
-    private LayeringStrategy layeringStrategy;
+    private SchemeLayeringStrategy layeringStrategy;
     @Mock
     private SchemePortResolver schemePortResolver;
     @Mock
@@ -97,13 +97,13 @@ public class TestPoolingHttpClientAsyncC
     @Mock
     private IOSession iosession;
 
-    private Registry<LayeringStrategy> layeringStrategyRegistry;
+    private Registry<SchemeLayeringStrategy> layeringStrategyRegistry;
     private PoolingNHttpClientConnectionManager connman;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        layeringStrategyRegistry = RegistryBuilder.<LayeringStrategy>create()
+        layeringStrategyRegistry = RegistryBuilder.<SchemeLayeringStrategy>create()
             .register("https", layeringStrategy).build();
         connman = new PoolingNHttpClientConnectionManager(
             ioreactor, pool, layeringStrategyRegistry,
@@ -283,7 +283,7 @@ public class TestPoolingHttpClientAsyncC
             sessionRequestCallbackCaptor.capture());
 
         Mockito.when(sessionRequest.getSession()).thenReturn(iosession);
-        Mockito.when(layeringStrategy.layer(iosession)).thenReturn(iosession);
+        Mockito.when(layeringStrategy.layer(target, iosession)).thenReturn(iosession);
 
         final SessionRequestCallback callback = sessionRequestCallbackCaptor.getValue();
         callback.completed(sessionRequest);
@@ -443,11 +443,11 @@ public class TestPoolingHttpClientAsyncC
         final NHttpClientConnection managedConn = CPoolProxy.newProxy(poolentry);
 
         Mockito.when(conn.getIOSession()).thenReturn(iosession);
-        Mockito.when(layeringStrategy.layer(iosession)).thenReturn(iosession);
+        Mockito.when(layeringStrategy.layer(target, iosession)).thenReturn(iosession);
 
         connman.initialize(managedConn, route, context);
 
-        Mockito.verify(layeringStrategy, Mockito.never()).layer(iosession);
+        Mockito.verify(layeringStrategy, Mockito.never()).layer(target, iosession);
         Mockito.verify(conn, Mockito.never()).bind(iosession);
 
         Assert.assertFalse(connman.isRouteComplete(managedConn));
@@ -465,11 +465,11 @@ public class TestPoolingHttpClientAsyncC
         final NHttpClientConnection managedConn = CPoolProxy.newProxy(poolentry);
 
         Mockito.when(conn.getIOSession()).thenReturn(iosession);
-        Mockito.when(layeringStrategy.layer(iosession)).thenReturn(iosession);
+        Mockito.when(layeringStrategy.layer(target, iosession)).thenReturn(iosession);
 
         connman.initialize(managedConn, route, context);
 
-        Mockito.verify(layeringStrategy).layer(iosession);
+        Mockito.verify(layeringStrategy).layer(target, iosession);
         Mockito.verify(conn).bind(iosession);
     }
 
@@ -485,11 +485,11 @@ public class TestPoolingHttpClientAsyncC
         final NHttpClientConnection managedConn = CPoolProxy.newProxy(poolentry);
 
         Mockito.when(conn.getIOSession()).thenReturn(iosession);
-        Mockito.when(layeringStrategy.layer(iosession)).thenReturn(iosession);
+        Mockito.when(layeringStrategy.layer(target, iosession)).thenReturn(iosession);
 
         connman.upgrade(managedConn, route, context);
 
-        Mockito.verify(layeringStrategy).layer(iosession);
+        Mockito.verify(layeringStrategy).layer(target, iosession);
         Mockito.verify(conn).bind(iosession);
     }
 
@@ -505,7 +505,7 @@ public class TestPoolingHttpClientAsyncC
         final NHttpClientConnection managedConn = CPoolProxy.newProxy(poolentry);
 
         Mockito.when(conn.getIOSession()).thenReturn(iosession);
-        Mockito.when(layeringStrategy.layer(iosession)).thenReturn(iosession);
+        Mockito.when(layeringStrategy.layer(target, iosession)).thenReturn(iosession);
 
         connman.upgrade(managedConn, route, context);
     }
@@ -522,7 +522,7 @@ public class TestPoolingHttpClientAsyncC
         final NHttpClientConnection managedConn = CPoolProxy.newProxy(poolentry);
 
         Mockito.when(conn.getIOSession()).thenReturn(iosession);
-        Mockito.when(layeringStrategy.layer(iosession)).thenReturn(iosession);
+        Mockito.when(layeringStrategy.layer(target, iosession)).thenReturn(iosession);
 
         connman.initialize(managedConn, route, context);
         connman.routeComplete(managedConn, route, context);
@@ -573,7 +573,8 @@ public class TestPoolingHttpClientAsyncC
         final HttpRoute route = new HttpRoute(new HttpHost("somehost"));
         internalConnFactory.create(route, iosession);
 
-        Mockito.verify(layeringStrategy, Mockito.never()).layer(Mockito.<IOSession>any());
+        Mockito.verify(layeringStrategy, Mockito.never()).layer(
+            Mockito.eq(new HttpHost("somehost")), Mockito.<IOSession>any());
         Mockito.verify(connFactory).create(Mockito.same(iosession), Mockito.<ConnectionConfig>any());
     }