hc-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ol...@apache.org
Subject svn commit: r1784139 [1/2] - in /httpcomponents/httpclient/trunk: ./ httpclient5/ httpclient5/src/main/java/org/apache/hc/client5/http/impl/ httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/ httpclient5/src/main/java/org/apache/hc/client5/...
Date Thu, 23 Feb 2017 14:32:44 GMT
Author: olegk
Date: Thu Feb 23 14:32:43 2017
New Revision: 1784139

URL: http://svn.apache.org/viewvc?rev=1784139&view=rev
Log:
New non-blocking connection management APIs

Added:
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ComplexFuture.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/AsyncClientConnectionOperator.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/ManagedAsyncClientConnection.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncClientConnectionManager.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncConnectionEndpoint.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/H2TlsSupport.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/SSLUpgradeStrategy.java   (with props)
Modified:
    httpcomponents/httpclient/trunk/httpclient5/pom.xml
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ConnPoolSupport.java
    httpcomponents/httpclient/trunk/pom.xml

Modified: httpcomponents/httpclient/trunk/httpclient5/pom.xml
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/pom.xml?rev=1784139&r1=1784138&r2=1784139&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/pom.xml (original)
+++ httpcomponents/httpclient/trunk/httpclient5/pom.xml Thu Feb 23 14:32:43 2017
@@ -43,6 +43,11 @@
       <scope>compile</scope>
     </dependency>
     <dependency>
+      <groupId>org.apache.httpcomponents.core5</groupId>
+      <artifactId>httpcore5-h2</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-api</artifactId>
       <version>${log4j.version}</version>

Added: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ComplexFuture.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ComplexFuture.java?rev=1784139&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ComplexFuture.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ComplexFuture.java Thu Feb 23 14:32:43 2017
@@ -0,0 +1,81 @@
+/*
+ * ====================================================================
+ * 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.hc.client5.http.impl;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.hc.core5.concurrent.BasicFuture;
+import org.apache.hc.core5.concurrent.Cancellable;
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.util.Args;
+
+public final class ComplexFuture<T> extends BasicFuture<T> {
+
+    private final AtomicReference<Cancellable> dependencyRef;
+
+    public ComplexFuture(final FutureCallback<T> callback) {
+        super(callback);
+        this.dependencyRef = new AtomicReference<>(null);
+    }
+
+    public void setDependency(final Cancellable dependency) {
+        Args.notNull(dependency, "dependency");
+        if (isDone()) {
+            dependency.cancel();
+        } else {
+            dependencyRef.set(dependency);
+        }
+    }
+
+    public void setDependency(final Future<?> dependency) {
+        Args.notNull(dependency, "dependency");
+        setDependency(new Cancellable() {
+
+            @Override
+            public boolean cancel() {
+                return dependency.cancel(true);
+            }
+
+        });
+    }
+
+    public void clearDependency() {
+        dependencyRef.set(null);
+    }
+
+    @Override
+    public boolean cancel(final boolean mayInterruptIfRunning) {
+        final boolean cancelled = super.cancel(mayInterruptIfRunning);
+        final Cancellable dependency = dependencyRef.getAndSet(null);
+        if (dependency != null) {
+            dependency.cancel();
+        }
+        return cancelled;
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ComplexFuture.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ComplexFuture.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ComplexFuture.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ConnPoolSupport.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ConnPoolSupport.java?rev=1784139&r1=1784138&r2=1784139&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ConnPoolSupport.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ConnPoolSupport.java Thu Feb 23 14:32:43 2017
@@ -40,7 +40,7 @@ public final class ConnPoolSupport {
         if (object instanceof Identifiable) {
             return ((Identifiable) object).getId();
         } else {
-            return Integer.toHexString(System.identityHashCode(object));
+            return object.getClass().getSimpleName() + "-" + Integer.toHexString(System.identityHashCode(object));
         }
     }
 

Added: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/AsyncClientConnectionOperator.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/AsyncClientConnectionOperator.java?rev=1784139&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/AsyncClientConnectionOperator.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/AsyncClientConnectionOperator.java Thu Feb 23 14:32:43 2017
@@ -0,0 +1,172 @@
+/*
+ * ====================================================================
+ * 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.hc.client5.http.impl.nio;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.hc.client5.http.ConnectTimeoutException;
+import org.apache.hc.client5.http.DnsResolver;
+import org.apache.hc.client5.http.HttpHostConnectException;
+import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.SystemDefaultDnsResolver;
+import org.apache.hc.client5.http.UnsupportedSchemeException;
+import org.apache.hc.client5.http.impl.ComplexFuture;
+import org.apache.hc.client5.http.impl.DefaultSchemePortResolver;
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.config.Lookup;
+import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
+import org.apache.hc.core5.reactor.ConnectionInitiator;
+import org.apache.hc.core5.reactor.IOSession;
+import org.apache.hc.core5.reactor.SessionRequest;
+import org.apache.hc.core5.reactor.SessionRequestCallback;
+import org.apache.hc.core5.util.Args;
+
+final class AsyncClientConnectionOperator {
+
+    private final SchemePortResolver schemePortResolver;
+    private final DnsResolver dnsResolver;
+    private final Lookup<TlsStrategy> tlsStrategyLookup;
+
+    AsyncClientConnectionOperator(
+            final SchemePortResolver schemePortResolver,
+            final DnsResolver dnsResolver,
+            final Lookup<TlsStrategy> tlsStrategyLookup) {
+        this.schemePortResolver = schemePortResolver != null ? schemePortResolver : DefaultSchemePortResolver.INSTANCE;
+        this.dnsResolver = dnsResolver != null ? dnsResolver : SystemDefaultDnsResolver.INSTANCE;
+        this.tlsStrategyLookup = tlsStrategyLookup;
+    }
+
+    public Future<ManagedAsyncClientConnection> connect(
+            final ConnectionInitiator connectionInitiator,
+            final HttpHost host,
+            final SocketAddress localAddress,
+            final long timeout,
+            final TimeUnit timeUnit,
+            final FutureCallback<ManagedAsyncClientConnection> callback) {
+        Args.notNull(connectionInitiator, "Connection initiator");
+        Args.notNull(host, "Host");
+        final ComplexFuture<ManagedAsyncClientConnection> future = new ComplexFuture<>(callback);
+        final InetAddress[] remoteAddresses;
+        try {
+            remoteAddresses = dnsResolver.resolve(host.getHostName());
+        } catch (UnknownHostException ex) {
+            future.failed(ex);
+            return future;
+        }
+        final int port;
+        try {
+            port = schemePortResolver.resolve(host);
+        } catch (UnsupportedSchemeException ex) {
+            future.failed(ex);
+            return future;
+        }
+        final TlsStrategy tlsStrategy = tlsStrategyLookup != null ? tlsStrategyLookup.lookup(host.getSchemeName()) : null;
+        final Runnable runnable = new Runnable() {
+
+            private final AtomicInteger attempt = new AtomicInteger(0);
+
+            void executeNext() {
+                final int index = attempt.getAndIncrement();
+                final InetSocketAddress remoteAddress = new InetSocketAddress(remoteAddresses[index], port);
+                final SessionRequest sessionRequest = connectionInitiator.connect(
+                        host,
+                        // TODO: fix after upgrading to HttpCore 5.0a3
+                        // TODO: remoteAddress
+                        localAddress,
+                        null, new SessionRequestCallback() {
+
+                            @Override
+                            public void completed(final SessionRequest request) {
+                                final IOSession session = request.getSession();
+                                final ManagedAsyncClientConnection connection = new ManagedAsyncClientConnection(session);
+                                if (tlsStrategy != null) {
+                                    tlsStrategy.upgrade(
+                                            connection,
+                                            host.getHostName(),
+                                            session.getLocalAddress(),
+                                            session.getRemoteAddress());
+                                }
+                                future.completed(connection);
+                            }
+
+                            @Override
+                            public void failed(final SessionRequest request) {
+                                if (attempt.get() >= remoteAddresses.length) {
+                                    future.failed(new HttpHostConnectException(request.getException(), host, remoteAddresses));
+                                } else {
+                                    executeNext();
+                                }
+                            }
+
+                            @Override
+                            public void timeout(final SessionRequest request) {
+                                future.failed(new ConnectTimeoutException(new SocketException(), host, remoteAddresses));
+                            }
+
+                            @Override
+                            public void cancelled(final SessionRequest request) {
+                                future.cancel();
+                            }
+
+                        });
+                future.setDependency(sessionRequest);
+                final int connectTimeout = (int) (timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS).toMillis(timeout);
+                sessionRequest.setConnectTimeout(connectTimeout);
+            }
+
+            @Override
+            public void run() {
+                executeNext();
+            }
+
+        };
+        runnable.run();
+        return future;
+    }
+
+    public void upgrade(final ManagedAsyncClientConnection connection, final HttpHost host) {
+        final TlsStrategy tlsStrategy = tlsStrategyLookup != null ? tlsStrategyLookup.lookup(host.getHostName()) : null;
+        if (tlsStrategy != null) {
+            tlsStrategy.upgrade(
+                    connection,
+                    // TODO: fix after upgrading to HttpCore 5.0a3
+                    host.getHostName(),
+                    connection.getLocalAddress(),
+                    connection.getRemoteAddress());
+        }
+
+    }
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/AsyncClientConnectionOperator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/AsyncClientConnectionOperator.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/AsyncClientConnectionOperator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/ManagedAsyncClientConnection.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/ManagedAsyncClientConnection.java?rev=1784139&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/ManagedAsyncClientConnection.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/ManagedAsyncClientConnection.java Thu Feb 23 14:32:43 2017
@@ -0,0 +1,186 @@
+/*
+ * ====================================================================
+ * 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.hc.client5.http.impl.nio;
+
+import java.io.IOException;
+import java.net.SocketAddress;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+
+import org.apache.hc.client5.http.impl.ConnPoolSupport;
+import org.apache.hc.client5.http.ssl.H2TlsSupport;
+import org.apache.hc.client5.http.utils.Identifiable;
+import org.apache.hc.core5.http.HttpConnection;
+import org.apache.hc.core5.http.HttpConnectionMetrics;
+import org.apache.hc.core5.http.HttpVersion;
+import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.reactor.Command;
+import org.apache.hc.core5.reactor.IOEventHandler;
+import org.apache.hc.core5.reactor.IOSession;
+import org.apache.hc.core5.reactor.ssl.SSLBufferManagement;
+import org.apache.hc.core5.reactor.ssl.SSLSessionInitializer;
+import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier;
+import org.apache.hc.core5.reactor.ssl.TransportSecurityLayer;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+final class ManagedAsyncClientConnection implements Identifiable, HttpConnection, TransportSecurityLayer {
+
+    private final Logger log = LogManager.getLogger(getClass());
+
+    private final IOSession ioSession;
+    private final AtomicBoolean closed;
+
+    public ManagedAsyncClientConnection(final IOSession ioSession) {
+        this.ioSession = ioSession;
+        this.closed = new AtomicBoolean();
+    }
+
+    @Override
+    public String getId() {
+        return ConnPoolSupport.getId(ioSession);
+    }
+
+    @Override
+    public void shutdown() throws IOException {
+        if (this.closed.compareAndSet(false, true)) {
+            if (log.isDebugEnabled()) {
+                log.debug(getId() + ": Shutdown connection");
+            }
+            ioSession.shutdown();
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (this.closed.compareAndSet(false, true)) {
+            if (log.isDebugEnabled()) {
+                log.debug(getId() + ": Close connection");
+            }
+            ioSession.close();
+        }
+    }
+
+    @Override
+    public boolean isOpen() {
+        return !ioSession.isClosed();
+    }
+
+    @Override
+    public void setSocketTimeout(final int timeout) {
+        ioSession.setSocketTimeout(timeout);
+    }
+
+    @Override
+    public int getSocketTimeout() {
+        return ioSession.getSocketTimeout();
+    }
+
+    @Override
+    public SocketAddress getRemoteAddress() {
+        return ioSession.getRemoteAddress();
+    }
+
+    @Override
+    public SocketAddress getLocalAddress() {
+        return ioSession.getLocalAddress();
+    }
+
+    @Override
+    public HttpConnectionMetrics getMetrics() {
+        final IOEventHandler handler = ioSession.getHandler();
+        if (handler instanceof HttpConnection) {
+            return ((HttpConnection) handler).getMetrics();
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public ProtocolVersion getProtocolVersion() {
+        final IOEventHandler handler = ioSession.getHandler();
+        if (handler instanceof HttpConnection) {
+            return ((HttpConnection) handler).getProtocolVersion();
+        } else {
+            return HttpVersion.DEFAULT;
+        }
+    }
+
+    @Override
+    public void start(
+            final SSLContext sslContext,
+            final SSLBufferManagement sslBufferManagement,
+            final SSLSessionInitializer initializer,
+            final SSLSessionVerifier verifier) throws UnsupportedOperationException {
+        if (log.isDebugEnabled()) {
+            log.debug(getId() + ": start TLS");
+        }
+        if (ioSession instanceof TransportSecurityLayer) {
+            final IOEventHandler handler = ioSession.getHandler();
+            final ProtocolVersion protocolVersion;
+            if (handler instanceof HttpConnection) {
+                protocolVersion = ((HttpConnection) handler).getProtocolVersion();
+            } else {
+                protocolVersion = null;
+            }
+            ((TransportSecurityLayer) ioSession).start(
+                    sslContext,
+                    sslBufferManagement,
+                    HttpVersion.HTTP_2.greaterEquals(protocolVersion) ? H2TlsSupport.decorateInitializer(initializer) : initializer,
+                    verifier);
+        } else {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    @Override
+    public SSLSession getSSLSession() {
+        if (ioSession instanceof TransportSecurityLayer) {
+            return ((TransportSecurityLayer) ioSession).getSSLSession();
+        } else {
+            return null;
+        }
+    }
+
+    public void submitPriorityCommand(final Command command) {
+        if (log.isDebugEnabled()) {
+            log.debug(getId() + ": priority command " + command);
+        }
+        ioSession.addFirst(command);
+    }
+
+    public void submitCommand(final Command command) {
+        if (log.isDebugEnabled()) {
+            log.debug(getId() + ": command " + command);
+        }
+        ioSession.addLast(command);
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/ManagedAsyncClientConnection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/ManagedAsyncClientConnection.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/ManagedAsyncClientConnection.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java?rev=1784139&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java Thu Feb 23 14:32:43 2017
@@ -0,0 +1,445 @@
+/*
+ * ====================================================================
+ * 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.hc.client5.http.impl.nio;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.hc.client5.http.DnsResolver;
+import org.apache.hc.client5.http.HttpRoute;
+import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.impl.ComplexFuture;
+import org.apache.hc.client5.http.impl.ConnPoolSupport;
+import org.apache.hc.client5.http.impl.ConnectionShutdownException;
+import org.apache.hc.client5.http.nio.AsyncClientConnectionManager;
+import org.apache.hc.client5.http.nio.AsyncConnectionEndpoint;
+import org.apache.hc.client5.http.utils.Identifiable;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.function.Callback;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpVersion;
+import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.config.Lookup;
+import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler;
+import org.apache.hc.core5.http.nio.command.ExecutionCommand;
+import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.http2.nio.command.PingCommand;
+import org.apache.hc.core5.http2.nio.support.BasicPingHandler;
+import org.apache.hc.core5.pool.ConnPoolControl;
+import org.apache.hc.core5.pool.ConnPoolListener;
+import org.apache.hc.core5.pool.ConnPoolPolicy;
+import org.apache.hc.core5.pool.PoolEntry;
+import org.apache.hc.core5.pool.PoolStats;
+import org.apache.hc.core5.pool.StrictConnPool;
+import org.apache.hc.core5.reactor.ConnectionInitiator;
+import org.apache.hc.core5.util.Args;
+import org.apache.hc.core5.util.Asserts;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * {@code PoolingAsyncClientConnectionManager} maintains a pool of non-blocking
+ * {@link org.apache.hc.core5.http.HttpConnection}s and is able to service
+ * connection requests from multiple execution threads. Connections are pooled
+ * on a per route basis. A request for a route which already the manager has
+ * persistent connections for available in the pool will be services by leasing
+ * a connection from the pool rather than creating a new connection.
+ * <p>
+ * {@code PoolingAsyncClientConnectionManager} maintains a maximum limit
+ * of connection on a per route basis and in total. Connection limits
+ * can be adjusted using {@link ConnPoolControl} methods.
+ * <p>
+ * Total time to live (TTL) set at construction time defines maximum life span
+ * of persistent connections regardless of their expiration setting. No persistent
+ * connection will be re-used past its TTL value.
+ *
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL)
+public class PoolingAsyncClientConnectionManager implements AsyncClientConnectionManager, ConnPoolControl<HttpRoute> {
+
+    private final Logger log = LogManager.getLogger(getClass());
+
+    private final AsyncClientConnectionOperator connectionOperator;
+    private final StrictConnPool<HttpRoute, ManagedAsyncClientConnection> pool;
+    private final AtomicBoolean closed;
+
+    private volatile int validateAfterInactivity;
+
+    public PoolingAsyncClientConnectionManager(
+            final Lookup<TlsStrategy> tlsStrategyLookup,
+            final SchemePortResolver schemePortResolver,
+            final DnsResolver dnsResolver,
+            final long timeToLive,
+            final TimeUnit timeUnit,
+            final ConnPoolPolicy policy,
+            final ConnPoolListener<HttpRoute> connPoolListener) {
+        this.connectionOperator = new AsyncClientConnectionOperator(schemePortResolver, dnsResolver, tlsStrategyLookup);
+        this.pool = new StrictConnPool<>(20, 50, timeToLive, timeUnit,
+                policy != null ? policy : ConnPoolPolicy.LIFO, connPoolListener);
+        this.closed = new AtomicBoolean(false);
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    @Override
+    public void close() {
+        if (closed.compareAndSet(false, true)) {
+            log.debug("Connection manager is shutting down");
+            pool.shutdown();
+            log.debug("Connection manager shut down");
+        }
+    }
+
+    private InternalConnectionEndpoint cast(final AsyncConnectionEndpoint endpoint) {
+        if (endpoint instanceof InternalConnectionEndpoint) {
+            return (InternalConnectionEndpoint) endpoint;
+        } else {
+            throw new IllegalStateException("Unexpected endpoint class: " + endpoint.getClass());
+        }
+    }
+
+    @Override
+    public Future<AsyncConnectionEndpoint> lease(
+            final HttpRoute route,
+            final Object state,
+            final long timeout,
+            final TimeUnit timeUnit,
+            final FutureCallback<AsyncConnectionEndpoint> callback) {
+        if (log.isDebugEnabled()) {
+            log.debug("Connection request: " + ConnPoolSupport.formatStats(null, route, state, pool));
+        }
+        final ComplexFuture<AsyncConnectionEndpoint> resultFuture = new ComplexFuture<>(callback);
+        final Future<PoolEntry<HttpRoute, ManagedAsyncClientConnection>> leaseFuture = pool.lease(
+                route, state, timeout, timeUnit, new FutureCallback<PoolEntry<HttpRoute, ManagedAsyncClientConnection>>() {
+
+                    void leaseCompleted(final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry) {
+                        resultFuture.completed(new InternalConnectionEndpoint(poolEntry));
+                        if (log.isDebugEnabled()) {
+                            log.debug("Connection leased: " + ConnPoolSupport.formatStats(poolEntry.getConnection(), route, state, pool));
+                        }
+                    }
+
+                    @Override
+                    public void completed(final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry) {
+                        final ManagedAsyncClientConnection connection = poolEntry.getConnection();
+                        if (connection != null && validateAfterInactivity > 0 &&
+                                poolEntry.getUpdated() + validateAfterInactivity <= System.currentTimeMillis()) {
+                            final ProtocolVersion protocolVersion = connection.getProtocolVersion();
+                            if (HttpVersion.HTTP_2_0.greaterEquals(protocolVersion)) {
+                                connection.submitPriorityCommand(new PingCommand(new BasicPingHandler(new Callback<Boolean>() {
+
+                                    @Override
+                                    public void execute(final Boolean result) {
+                                        if (result == Boolean.FALSE) {
+                                            if (log.isDebugEnabled()) {
+                                                log.debug("Connection " + ConnPoolSupport.getId(connection) + " is stale");
+                                            }
+                                            poolEntry.discardConnection();
+                                        }
+                                        leaseCompleted(poolEntry);
+                                    }
+
+                                })));
+                            } else {
+                                leaseCompleted(poolEntry);
+                            }
+                        } else {
+                            leaseCompleted(poolEntry);
+                        }
+                    }
+
+                    @Override
+                    public void failed(final Exception ex) {
+                        resultFuture.failed(ex);
+                    }
+
+                    @Override
+                    public void cancelled() {
+                        resultFuture.cancel();
+                    }
+
+                });
+        resultFuture.setDependency(leaseFuture);
+        return resultFuture;
+    }
+
+    @Override
+    public void release(
+            final AsyncConnectionEndpoint endpoint,
+            final Object state,
+            final long keepAlive, final TimeUnit timeUnit) {
+        Args.notNull(endpoint, "Managed endpoint");
+        final PoolEntry<HttpRoute, ManagedAsyncClientConnection> entry = cast(endpoint).detach();
+        if (entry == null) {
+            return;
+        }
+        final ManagedAsyncClientConnection connection = entry.getConnection();
+        boolean reusable = connection != null && connection.isOpen();
+        try {
+            if (reusable) {
+                final TimeUnit effectiveUnit = timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS;
+                entry.updateConnection(keepAlive, effectiveUnit, state);
+                if (log.isDebugEnabled()) {
+                    final String s;
+                    if (keepAlive > 0) {
+                        s = "for " + (double) effectiveUnit.toMillis(keepAlive) / 1000 + " seconds";
+                    } else {
+                        s = "indefinitely";
+                    }
+                    log.debug("Connection " + ConnPoolSupport.getId(connection) + " can be kept alive " + s);
+                }
+            }
+        } catch (RuntimeException ex) {
+            reusable = false;
+            throw ex;
+        } finally {
+            pool.release(entry, reusable);
+            if (log.isDebugEnabled()) {
+                log.debug("Connection released: " + ConnPoolSupport.formatStats(
+                        connection, entry.getRoute(), entry.getState(), pool));
+            }
+        }
+    }
+
+    @Override
+    public Future<AsyncConnectionEndpoint> connect(
+            final AsyncConnectionEndpoint endpoint,
+            final ConnectionInitiator connectionInitiator,
+            final long timeout,
+            final TimeUnit timeUnit,
+            final HttpContext context,
+            final FutureCallback<AsyncConnectionEndpoint> callback) {
+        Args.notNull(endpoint, "Endpoint");
+        Args.notNull(connectionInitiator, "Connection initiator");
+        final InternalConnectionEndpoint internalEndpoint = cast(endpoint);
+        final ComplexFuture<AsyncConnectionEndpoint> resultFuture = new ComplexFuture<>(callback);
+        if (internalEndpoint.isConnected()) {
+            resultFuture.completed(endpoint);
+            return resultFuture;
+        }
+        final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry = internalEndpoint.getPoolEntry();
+        final HttpRoute route = poolEntry.getRoute();
+        final HttpHost host;
+        if (route.getProxyHost() != null) {
+            host = route.getProxyHost();
+        } else {
+            host = route.getTargetHost();
+        }
+        final InetSocketAddress localAddress = route.getLocalSocketAddress();
+        final Future<ManagedAsyncClientConnection> connectFuture = connectionOperator.connect(
+                connectionInitiator, host, localAddress, timeout, timeUnit, new FutureCallback<ManagedAsyncClientConnection>() {
+
+                    @Override
+                    public void completed(final ManagedAsyncClientConnection connection) {
+                        poolEntry.assignConnection(connection);
+                        resultFuture.completed(new InternalConnectionEndpoint(poolEntry));
+                    }
+
+                    @Override
+                    public void failed(final Exception ex) {
+                        resultFuture.failed(ex);
+                    }
+
+                    @Override
+                    public void cancelled() {
+                        resultFuture.cancel();
+                    }
+
+                });
+        resultFuture.setDependency(connectFuture);
+        return resultFuture;
+    }
+
+    @Override
+    public void upgrade(
+            final AsyncConnectionEndpoint endpoint,
+            final HttpContext context) {
+        Args.notNull(endpoint, "Managed endpoint");
+        final InternalConnectionEndpoint internalEndpoint = cast(endpoint);
+        final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry = internalEndpoint.getValidatedPoolEntry();
+        final HttpRoute route = poolEntry.getRoute();
+        connectionOperator.upgrade(poolEntry.getConnection(), route.getTargetHost());
+    }
+
+    @Override
+    public void setMaxTotal(final int max) {
+        pool.setMaxTotal(max);
+    }
+
+    @Override
+    public int getMaxTotal() {
+        return pool.getMaxTotal();
+    }
+
+    @Override
+    public void setDefaultMaxPerRoute(final int max) {
+        pool.setDefaultMaxPerRoute(max);
+    }
+
+    @Override
+    public int getDefaultMaxPerRoute() {
+        return pool.getDefaultMaxPerRoute();
+    }
+
+    @Override
+    public void setMaxPerRoute(final HttpRoute route, final int max) {
+        pool.setMaxPerRoute(route, max);
+    }
+
+    @Override
+    public int getMaxPerRoute(final HttpRoute route) {
+        return pool.getMaxPerRoute(route);
+    }
+
+    @Override
+    public void closeIdle(final long idletime, final TimeUnit tunit) {
+        pool.closeIdle(idletime, tunit);
+    }
+
+    @Override
+    public void closeExpired() {
+        pool.closeExpired();
+    }
+
+    @Override
+    public PoolStats getTotalStats() {
+        return pool.getTotalStats();
+    }
+
+    @Override
+    public PoolStats getStats(final HttpRoute route) {
+        return pool.getStats(route);
+    }
+
+    public int getValidateAfterInactivity() {
+        return validateAfterInactivity;
+    }
+
+    /**
+     * Defines period of inactivity in milliseconds after which persistent connections must
+     * be re-validated prior to being {@link #lease(HttpRoute, Object, long, TimeUnit,
+     * FutureCallback)} leased} to the consumer. Non-positive value passed
+     * to this method disables connection validation. This check helps detect connections
+     * that have become stale (half-closed) while kept inactive in the pool.
+     */
+    public void setValidateAfterInactivity(final int ms) {
+        validateAfterInactivity = ms;
+    }
+
+    class InternalConnectionEndpoint extends AsyncConnectionEndpoint implements Identifiable {
+
+        private final AtomicReference<PoolEntry<HttpRoute, ManagedAsyncClientConnection>> poolEntryRef;
+
+        InternalConnectionEndpoint(final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry) {
+            this.poolEntryRef = new AtomicReference<>(poolEntry);
+        }
+
+        @Override
+        public String getId() {
+            final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry = poolEntryRef.get();
+            final ManagedAsyncClientConnection connection = poolEntry != null ? poolEntry.getConnection() : null;
+            return ConnPoolSupport.getId(connection);
+        }
+
+        PoolEntry<HttpRoute, ManagedAsyncClientConnection> getPoolEntry() {
+            final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry = poolEntryRef.get();
+            if (poolEntry == null) {
+                throw new ConnectionShutdownException();
+            }
+            return poolEntry;
+        }
+
+        PoolEntry<HttpRoute, ManagedAsyncClientConnection> getValidatedPoolEntry() {
+            final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry = getPoolEntry();
+            final ManagedAsyncClientConnection connection = poolEntry.getConnection();
+            Asserts.check(connection != null && connection.isOpen(), "Endpoint is not connected");
+            return poolEntry;
+        }
+
+        PoolEntry<HttpRoute, ManagedAsyncClientConnection> detach() {
+            return poolEntryRef.getAndSet(null);
+        }
+
+        @Override
+        public void shutdown() throws IOException {
+            final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry = poolEntryRef.get();
+            if (poolEntry != null) {
+                final ManagedAsyncClientConnection connection = poolEntry.getConnection();
+                poolEntry.discardConnection();
+                if (connection != null) {
+                    connection.shutdown();
+                }
+            }
+        }
+
+        @Override
+        public void close() throws IOException {
+            final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry = poolEntryRef.get();
+            if (poolEntry != null) {
+                poolEntry.discardConnection();
+            }
+        }
+
+        @Override
+        public boolean isConnected() {
+            final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry = poolEntryRef.get();
+            if (poolEntry == null) {
+                throw new ConnectionShutdownException();
+            }
+            final ManagedAsyncClientConnection connection = poolEntry.getConnection();
+            return connection != null && connection.isOpen();
+        }
+
+        @Override
+        public void setSocketTimeout(final int timeout) {
+            getValidatedPoolEntry().getConnection().setSocketTimeout(timeout);
+        }
+
+        @Override
+        public void execute(final AsyncClientExchangeHandler exchangeHandler, final HttpContext context) {
+            getValidatedPoolEntry().getConnection().submitCommand(new ExecutionCommand(exchangeHandler, context));
+        }
+
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java?rev=1784139&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java Thu Feb 23 14:32:43 2017
@@ -0,0 +1,203 @@
+/*
+ * ====================================================================
+ * 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.hc.client5.http.impl.nio;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hc.client5.http.DnsResolver;
+import org.apache.hc.client5.http.HttpRoute;
+import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.ssl.SSLUpgradeStrategy;
+import org.apache.hc.core5.http.config.RegistryBuilder;
+import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
+import org.apache.hc.core5.pool.ConnPoolListener;
+import org.apache.hc.core5.pool.ConnPoolPolicy;
+
+/**
+ * Builder for {@link PoolingAsyncClientConnectionManager} instances.
+ * <p>
+ * When a particular component is not explicitly set this class will
+ * use its default implementation. System properties will be taken
+ * into account when configuring the default implementations when
+ * {@link #useSystemProperties()} method is called prior to calling
+ * {@link #build()}.
+ * </p>
+ * <ul>
+ *  <li>ssl.TrustManagerFactory.algorithm</li>
+ *  <li>javax.net.ssl.trustStoreType</li>
+ *  <li>javax.net.ssl.trustStore</li>
+ *  <li>javax.net.ssl.trustStoreProvider</li>
+ *  <li>javax.net.ssl.trustStorePassword</li>
+ *  <li>ssl.KeyManagerFactory.algorithm</li>
+ *  <li>javax.net.ssl.keyStoreType</li>
+ *  <li>javax.net.ssl.keyStore</li>
+ *  <li>javax.net.ssl.keyStoreProvider</li>
+ *  <li>javax.net.ssl.keyStorePassword</li>
+ *  <li>https.protocols</li>
+ *  <li>https.cipherSuites</li>
+ * </ul>
+ *
+ * @since 5.0
+ */
+public class PoolingAsyncClientConnectionManagerBuilder {
+
+    private TlsStrategy tlsStrategy;
+    private SchemePortResolver schemePortResolver;
+    private DnsResolver dnsResolver;
+    private ConnPoolPolicy connPoolPolicy;
+    private ConnPoolListener<HttpRoute> connPoolListener;
+
+    private boolean systemProperties;
+
+    private int maxConnTotal = 0;
+    private int maxConnPerRoute = 0;
+
+    private long connTimeToLive = -1;
+    private TimeUnit connTimeToLiveTimeUnit = TimeUnit.MILLISECONDS;
+    private int validateAfterInactivity = 2000;
+
+    public static PoolingAsyncClientConnectionManagerBuilder create() {
+        return new PoolingAsyncClientConnectionManagerBuilder();
+    }
+
+    PoolingAsyncClientConnectionManagerBuilder() {
+        super();
+    }
+
+    /**
+     * Assigns {@link TlsStrategy} instance for TLS connections.
+     */
+    public final PoolingAsyncClientConnectionManagerBuilder setTlsStrategy(
+            final TlsStrategy tlsStrategy) {
+        this.tlsStrategy = tlsStrategy;
+        return this;
+    }
+
+    /**
+     * Assigns {@link DnsResolver} instance.
+     */
+    public final PoolingAsyncClientConnectionManagerBuilder setDnsResolver(final DnsResolver dnsResolver) {
+        this.dnsResolver = dnsResolver;
+        return this;
+    }
+
+    /**
+     * Assigns {@link SchemePortResolver} instance.
+     */
+    public final PoolingAsyncClientConnectionManagerBuilder setSchemePortResolver(final SchemePortResolver schemePortResolver) {
+        this.schemePortResolver = schemePortResolver;
+        return this;
+    }
+
+    /**
+     * Assigns {@link ConnPoolPolicy} value.
+     */
+    public final PoolingAsyncClientConnectionManagerBuilder setConnPoolPolicy(final ConnPoolPolicy connPoolPolicy) {
+        this.connPoolPolicy = connPoolPolicy;
+        return this;
+    }
+
+    /**
+     * Assigns {@link ConnPoolListener} instance.
+     */
+    public final PoolingAsyncClientConnectionManagerBuilder setConnPoolListener(final ConnPoolListener<HttpRoute> connPoolListener) {
+        this.connPoolListener = connPoolListener;
+        return this;
+    }
+
+    /**
+     * Assigns maximum total connection value.
+     */
+    public final PoolingAsyncClientConnectionManagerBuilder setMaxConnTotal(final int maxConnTotal) {
+        this.maxConnTotal = maxConnTotal;
+        return this;
+    }
+
+    /**
+     * Assigns maximum connection per route value.
+     */
+    public final PoolingAsyncClientConnectionManagerBuilder setMaxConnPerRoute(final int maxConnPerRoute) {
+        this.maxConnPerRoute = maxConnPerRoute;
+        return this;
+    }
+
+    /**
+     * Sets maximum time to live for persistent connections
+     */
+    public final PoolingAsyncClientConnectionManagerBuilder setConnectionTimeToLive(final long connTimeToLive, final TimeUnit connTimeToLiveTimeUnit) {
+        this.connTimeToLive = connTimeToLive;
+        this.connTimeToLiveTimeUnit = connTimeToLiveTimeUnit;
+        return this;
+    }
+
+    /**
+     * Sets period after inactivity in milliseconds after which persistent
+     * connections must be checked to ensure they are still valid.
+     *
+     * @see org.apache.hc.core5.http.io.HttpClientConnection#isStale()
+     */
+    public final PoolingAsyncClientConnectionManagerBuilder setValidateAfterInactivity(final int validateAfterInactivity) {
+        this.validateAfterInactivity = validateAfterInactivity;
+        return this;
+    }
+
+    /**
+     * Use system properties when creating and configuring default
+     * implementations.
+     */
+    public final PoolingAsyncClientConnectionManagerBuilder useSystemProperties() {
+        this.systemProperties = true;
+        return this;
+    }
+
+    public PoolingAsyncClientConnectionManager build() {
+        @SuppressWarnings("resource")
+        final PoolingAsyncClientConnectionManager poolingmgr = new PoolingAsyncClientConnectionManager(
+                RegistryBuilder.<TlsStrategy>create()
+                        .register("https", tlsStrategy != null ? tlsStrategy :
+                                (systemProperties ?
+                                        SSLUpgradeStrategy.getSystemDefault() :
+                                        SSLUpgradeStrategy.getDefault()))
+                        .build(),
+                schemePortResolver,
+                dnsResolver,
+                connTimeToLive,
+                connTimeToLiveTimeUnit != null ? connTimeToLiveTimeUnit : TimeUnit.MILLISECONDS,
+                connPoolPolicy,
+                connPoolListener);
+        poolingmgr.setValidateAfterInactivity(this.validateAfterInactivity);
+        if (maxConnTotal > 0) {
+            poolingmgr.setMaxTotal(maxConnTotal);
+        }
+        if (maxConnPerRoute > 0) {
+            poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute);
+        }
+        return poolingmgr;
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncClientConnectionManager.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncClientConnectionManager.java?rev=1784139&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncClientConnectionManager.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncClientConnectionManager.java Thu Feb 23 14:32:43 2017
@@ -0,0 +1,127 @@
+/*
+ * ====================================================================
+ * 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.hc.client5.http.nio;
+
+import java.io.Closeable;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hc.client5.http.HttpRoute;
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.reactor.ConnectionInitiator;
+
+/**
+ * Represents a manager of persistent non-blocking client connections.
+ * <p>
+ * The purpose of an HTTP connection manager is to serve as a factory for new
+ * HTTP connections, manage persistent connections and synchronize access to
+ * persistent connections making sure that only one thread of execution can
+ * have access to a connection at a time.
+ * <p>
+ * Implementations of this interface must be thread-safe. Access to shared
+ * data must be synchronized as methods of this interface may be executed
+ * from multiple threads.
+ *
+ * @since 5.0
+ */
+public interface AsyncClientConnectionManager extends Closeable {
+
+    /**
+     * Returns a {@link Future} object which can be used to obtain
+     * an {@link AsyncConnectionEndpoint} or to cancel the request by calling
+     * {@link Future#cancel(boolean)}.
+     * <p>
+     * Please note that newly allocated endpoints can be leased
+     * {@link AsyncConnectionEndpoint#isConnected() disconnected}. The consumer
+     * of the endpoint is responsible for fully establishing the route to
+     * the endpoint target by calling {@link #connect(AsyncConnectionEndpoint,
+     * ConnectionInitiator, long, TimeUnit, HttpContext, FutureCallback)}
+     * in order to connect directly to the target or to the first proxy hop,
+     * and optionally calling {@link #upgrade(AsyncConnectionEndpoint, HttpContext)}
+     * method to upgrade the underlying transport to Transport Layer Security
+     * after having executed a {@code CONNECT} method to all intermediate
+     * proxy hops.
+     *
+     * @param route HTTP route of the requested connection.
+     * @param state expected state of the connection or {@code null}
+     *              if the connection is not expected to carry any state.
+     * @param timeout lease request timeout.
+     * @param timeUnit time unit.
+     * @param callback result callback.
+     */
+    Future<AsyncConnectionEndpoint> lease(
+            HttpRoute route,
+            Object state,
+            long timeout,
+            TimeUnit timeUnit,
+            FutureCallback<AsyncConnectionEndpoint> callback);
+
+    /**
+     * Releases the endpoint back to the manager making it potentially
+     * re-usable by other consumers. Optionally, the maximum period
+     * of how long the manager should keep the connection alive can be
+     * defined using {@code validDuration} and {@code timeUnit}
+     * parameters.
+     *
+     * @param endpoint      the managed endpoint.
+     * @param newState      the new connection state of {@code null} if state-less.
+     * @param validDuration the duration of time this connection is valid for reuse.
+     * @param timeUnit the time unit.
+     */
+    void release(AsyncConnectionEndpoint endpoint, Object newState, long validDuration, TimeUnit timeUnit);
+
+    /**
+     * Connects the endpoint to the initial hop (connection target in case
+     * of a direct route or to the first proxy hop in case of a route via a proxy
+     * or multiple proxies).
+     *
+     * @param endpoint      the managed endpoint.
+     * @param connectTimeout connect timeout.
+     * @param timeUnit time unit.
+     * @param context the actual HTTP context.
+     * @param callback result callback.
+     */
+    Future<AsyncConnectionEndpoint> connect(
+            AsyncConnectionEndpoint endpoint,
+            ConnectionInitiator connectionInitiator,
+            long connectTimeout,
+            TimeUnit timeUnit,
+            HttpContext context,
+            FutureCallback<AsyncConnectionEndpoint> callback);
+
+    /**
+     * Upgrades the endpoint's underlying transport to Transport Layer Security.
+     *
+     * @param endpoint      the managed endpoint.
+     * @param context the actual HTTP context.
+     */
+    void upgrade(
+            AsyncConnectionEndpoint endpoint,
+            HttpContext context);
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncClientConnectionManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncClientConnectionManager.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncClientConnectionManager.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncConnectionEndpoint.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncConnectionEndpoint.java?rev=1784139&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncConnectionEndpoint.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncConnectionEndpoint.java Thu Feb 23 14:32:43 2017
@@ -0,0 +1,97 @@
+/*
+ * ====================================================================
+ * 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.hc.client5.http.nio;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.concurrent.Future;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.concurrent.BasicFuture;
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler;
+import org.apache.hc.core5.http.nio.AsyncRequestProducer;
+import org.apache.hc.core5.http.nio.AsyncResponseConsumer;
+import org.apache.hc.core5.http.nio.support.BasicClientExchangeHandler;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.http.protocol.HttpCoreContext;
+
+/**
+ * Client connection endpoint that can be used to execute message exchanges.
+ *
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.SAFE)
+public abstract class AsyncConnectionEndpoint implements Closeable {
+
+    public abstract void execute(AsyncClientExchangeHandler exchangeHandler, HttpContext context);
+
+    public <T> Future<T> execute(
+            final AsyncRequestProducer requestProducer,
+            final AsyncResponseConsumer<T> responseConsumer,
+            final HttpContext context,
+            final FutureCallback<T> callback) {
+        final BasicFuture<T> future = new BasicFuture<>(callback);
+        execute(new BasicClientExchangeHandler<>(requestProducer, responseConsumer,
+                        new FutureCallback<T>() {
+
+                            @Override
+                            public void completed(final T result) {
+                                future.completed(result);
+                            }
+
+                            @Override
+                            public void failed(final Exception ex) {
+                                future.failed(ex);
+                            }
+
+                            @Override
+                            public void cancelled() {
+                                future.cancel();
+                            }
+
+                        }),
+                context != null ? context : HttpCoreContext.create());
+        return future;
+    }
+
+    public <T> Future<T> execute(
+            final AsyncRequestProducer requestProducer,
+            final AsyncResponseConsumer<T> responseConsumer,
+            final FutureCallback<T> callback) {
+        return execute(requestProducer, responseConsumer, null, callback);
+    }
+
+    public abstract boolean isConnected();
+
+    public abstract void setSocketTimeout(int timeout);
+
+    public abstract void shutdown() throws IOException;
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncConnectionEndpoint.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncConnectionEndpoint.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncConnectionEndpoint.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/H2TlsSupport.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/H2TlsSupport.java?rev=1784139&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/H2TlsSupport.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/H2TlsSupport.java Thu Feb 23 14:32:43 2017
@@ -0,0 +1,377 @@
+/*
+ * ====================================================================
+ * 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.hc.client5.http.ssl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLException;
+
+import org.apache.hc.core5.reactor.ssl.SSLSessionInitializer;
+
+// TODO: use class from HttpCore 5.0a3
+public final class H2TlsSupport {
+
+    private final static String[] PROTOCOL_BLACKLIST = {
+            "TLSv1",
+            "TLSv1.1"
+    };
+
+    private final static String[] CIPHER_BLACKLIST = {
+            "TLS_NULL_WITH_NULL_NULL",
+            "TLS_RSA_WITH_NULL_MD5",
+            "TLS_RSA_WITH_NULL_SHA",
+            "TLS_RSA_EXPORT_WITH_RC4_40_MD5",
+            "TLS_RSA_WITH_RC4_128_MD5",
+            "TLS_RSA_WITH_RC4_128_SHA",
+            "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5",
+            "TLS_RSA_WITH_IDEA_CBC_SHA",
+            "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA",
+            "TLS_RSA_WITH_DES_CBC_SHA",
+            "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA",
+            "TLS_DH_DSS_WITH_DES_CBC_SHA",
+            "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA",
+            "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA",
+            "TLS_DH_RSA_WITH_DES_CBC_SHA",
+            "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+            "TLS_DHE_DSS_WITH_DES_CBC_SHA",
+            "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
+            "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+            "TLS_DHE_RSA_WITH_DES_CBC_SHA",
+            "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5",
+            "TLS_DH_anon_WITH_RC4_128_MD5",
+            "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+            "TLS_DH_anon_WITH_DES_CBC_SHA",
+            "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA",
+            "TLS_KRB5_WITH_DES_CBC_SHA",
+            "TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
+            "TLS_KRB5_WITH_RC4_128_SHA",
+            "TLS_KRB5_WITH_IDEA_CBC_SHA",
+            "TLS_KRB5_WITH_DES_CBC_MD5",
+            "TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
+            "TLS_KRB5_WITH_RC4_128_MD5",
+            "TLS_KRB5_WITH_IDEA_CBC_MD5",
+            "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
+            "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA",
+            "TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
+            "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
+            "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5",
+            "TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
+            "TLS_PSK_WITH_NULL_SHA",
+            "TLS_DHE_PSK_WITH_NULL_SHA",
+            "TLS_RSA_PSK_WITH_NULL_SHA",
+            "TLS_RSA_WITH_AES_128_CBC_SHA",
+            "TLS_DH_DSS_WITH_AES_128_CBC_SHA",
+            "TLS_DH_RSA_WITH_AES_128_CBC_SHA",
+            "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+            "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+            "TLS_DH_anon_WITH_AES_128_CBC_SHA",
+            "TLS_RSA_WITH_AES_256_CBC_SHA",
+            "TLS_DH_DSS_WITH_AES_256_CBC_SHA",
+            "TLS_DH_RSA_WITH_AES_256_CBC_SHA",
+            "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
+            "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+            "TLS_DH_anon_WITH_AES_256_CBC_SHA",
+            "TLS_RSA_WITH_NULL_SHA256",
+            "TLS_RSA_WITH_AES_128_CBC_SHA256",
+            "TLS_RSA_WITH_AES_256_CBC_SHA256",
+            "TLS_DH_DSS_WITH_AES_128_CBC_SHA256",
+            "TLS_DH_RSA_WITH_AES_128_CBC_SHA256",
+            "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
+            "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",
+            "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA",
+            "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA",
+            "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA",
+            "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",
+            "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA",
+            "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
+            "TLS_DH_DSS_WITH_AES_256_CBC_SHA256",
+            "TLS_DH_RSA_WITH_AES_256_CBC_SHA256",
+            "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
+            "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+            "TLS_DH_anon_WITH_AES_128_CBC_SHA256",
+            "TLS_DH_anon_WITH_AES_256_CBC_SHA256",
+            "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",
+            "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA",
+            "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA",
+            "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA",
+            "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",
+            "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",
+            "TLS_PSK_WITH_RC4_128_SHA",
+            "TLS_PSK_WITH_3DES_EDE_CBC_SHA",
+            "TLS_PSK_WITH_AES_128_CBC_SHA",
+            "TLS_PSK_WITH_AES_256_CBC_SHA",
+            "TLS_DHE_PSK_WITH_RC4_128_SHA",
+            "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA",
+            "TLS_DHE_PSK_WITH_AES_128_CBC_SHA",
+            "TLS_DHE_PSK_WITH_AES_256_CBC_SHA",
+            "TLS_RSA_PSK_WITH_RC4_128_SHA",
+            "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA",
+            "TLS_RSA_PSK_WITH_AES_128_CBC_SHA",
+            "TLS_RSA_PSK_WITH_AES_256_CBC_SHA",
+            "TLS_RSA_WITH_SEED_CBC_SHA",
+            "TLS_DH_DSS_WITH_SEED_CBC_SHA",
+            "TLS_DH_RSA_WITH_SEED_CBC_SHA",
+            "TLS_DHE_DSS_WITH_SEED_CBC_SHA",
+            "TLS_DHE_RSA_WITH_SEED_CBC_SHA",
+            "TLS_DH_anon_WITH_SEED_CBC_SHA",
+            "TLS_RSA_WITH_AES_128_GCM_SHA256",
+            "TLS_RSA_WITH_AES_256_GCM_SHA384",
+            "TLS_DH_RSA_WITH_AES_128_GCM_SHA256",
+            "TLS_DH_RSA_WITH_AES_256_GCM_SHA384",
+            "TLS_DH_DSS_WITH_AES_128_GCM_SHA256",
+            "TLS_DH_DSS_WITH_AES_256_GCM_SHA384",
+            "TLS_DH_anon_WITH_AES_128_GCM_SHA256",
+            "TLS_DH_anon_WITH_AES_256_GCM_SHA384",
+            "TLS_PSK_WITH_AES_128_GCM_SHA256",
+            "TLS_PSK_WITH_AES_256_GCM_SHA384",
+            "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256",
+            "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384",
+            "TLS_PSK_WITH_AES_128_CBC_SHA256",
+            "TLS_PSK_WITH_AES_256_CBC_SHA384",
+            "TLS_PSK_WITH_NULL_SHA256",
+            "TLS_PSK_WITH_NULL_SHA384",
+            "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",
+            "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",
+            "TLS_DHE_PSK_WITH_NULL_SHA256",
+            "TLS_DHE_PSK_WITH_NULL_SHA384",
+            "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256",
+            "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384",
+            "TLS_RSA_PSK_WITH_NULL_SHA256",
+            "TLS_RSA_PSK_WITH_NULL_SHA384",
+            "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",
+            "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256",
+            "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256",
+            "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256",
+            "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",
+            "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256",
+            "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
+            "TLS_ECDH_ECDSA_WITH_NULL_SHA",
+            "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
+            "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
+            "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+            "TLS_ECDHE_ECDSA_WITH_NULL_SHA",
+            "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+            "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+            "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+            "TLS_ECDH_RSA_WITH_NULL_SHA",
+            "TLS_ECDH_RSA_WITH_RC4_128_SHA",
+            "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
+            "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+            "TLS_ECDHE_RSA_WITH_NULL_SHA",
+            "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+            "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+            "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+            "TLS_ECDH_anon_WITH_NULL_SHA",
+            "TLS_ECDH_anon_WITH_RC4_128_SHA",
+            "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
+            "TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
+            "TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
+            "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA",
+            "TLS_SRP_SHA_WITH_AES_128_CBC_SHA",
+            "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA",
+            "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA",
+            "TLS_SRP_SHA_WITH_AES_256_CBC_SHA",
+            "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA",
+            "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA",
+            "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+            "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
+            "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
+            "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
+            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+            "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
+            "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
+            "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
+            "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
+            "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
+            "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
+            "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
+            "TLS_ECDHE_PSK_WITH_RC4_128_SHA",
+            "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA",
+            "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",
+            "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",
+            "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",
+            "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384",
+            "TLS_ECDHE_PSK_WITH_NULL_SHA",
+            "TLS_ECDHE_PSK_WITH_NULL_SHA256",
+            "TLS_ECDHE_PSK_WITH_NULL_SHA384",
+            "TLS_RSA_WITH_ARIA_128_CBC_SHA256",
+            "TLS_RSA_WITH_ARIA_256_CBC_SHA384",
+            "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256",
+            "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384",
+            "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256",
+            "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384",
+            "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256",
+            "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384",
+            "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256",
+            "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384",
+            "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256",
+            "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384",
+            "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256",
+            "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384",
+            "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256",
+            "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384",
+            "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256",
+            "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384",
+            "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256",
+            "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384",
+            "TLS_RSA_WITH_ARIA_128_GCM_SHA256",
+            "TLS_RSA_WITH_ARIA_256_GCM_SHA384",
+            "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256",
+            "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384",
+            "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256",
+            "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384",
+            "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256",
+            "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384",
+            "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256",
+            "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384",
+            "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256",
+            "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384",
+            "TLS_PSK_WITH_ARIA_128_CBC_SHA256",
+            "TLS_PSK_WITH_ARIA_256_CBC_SHA384",
+            "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256",
+            "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384",
+            "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256",
+            "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384",
+            "TLS_PSK_WITH_ARIA_128_GCM_SHA256",
+            "TLS_PSK_WITH_ARIA_256_GCM_SHA384",
+            "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256",
+            "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384",
+            "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256",
+            "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384",
+            "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384",
+            "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384",
+            "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384",
+            "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384",
+            "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256",
+            "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384",
+            "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256",
+            "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384",
+            "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256",
+            "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384",
+            "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256",
+            "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384",
+            "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256",
+            "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384",
+            "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256",
+            "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384",
+            "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256",
+            "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384",
+            "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256",
+            "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384",
+            "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384",
+            "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384",
+            "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384",
+            "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256",
+            "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384",
+            "TLS_RSA_WITH_AES_128_CCM",
+            "TLS_RSA_WITH_AES_256_CCM",
+            "TLS_RSA_WITH_AES_128_CCM_8",
+            "TLS_RSA_WITH_AES_256_CCM_8",
+            "TLS_PSK_WITH_AES_128_CCM",
+            "TLS_PSK_WITH_AES_256_CCM",
+            "TLS_PSK_WITH_AES_128_CCM_8",
+            "TLS_PSK_WITH_AES_256_CCM_8" };
+
+    private final static Set<String> BLACKLISED_PROTOCOLS = new CopyOnWriteArraySet<>(Arrays.asList(PROTOCOL_BLACKLIST));
+    private final static Set<String> BLACKLISED_CIPHERS = new CopyOnWriteArraySet<>(Arrays.asList(CIPHER_BLACKLIST));
+
+    public static String[] excludeBlacklistedProtocols(final String[] protocols) {
+        if (protocols == null) {
+            return null;
+        }
+        List<String> enabledProtocols = null;
+        for (String protocol: protocols) {
+            if (!protocol.startsWith("SSL") && !BLACKLISED_PROTOCOLS.contains(protocol)) {
+                if (enabledProtocols == null) {
+                    enabledProtocols = new ArrayList<>();
+                }
+                enabledProtocols.add(protocol);
+            }
+        }
+        return enabledProtocols != null ? enabledProtocols.toArray(new String[enabledProtocols.size()]) : protocols;
+    }
+
+    public static String[] excludeBlacklistedCiphers(final String[] ciphers) {
+        if (ciphers == null) {
+            return null;
+        }
+        List<String> enabledCiphers = null;
+        for (String cipher: ciphers) {
+            if (!BLACKLISED_CIPHERS.contains(cipher)) {
+                if (enabledCiphers == null) {
+                    enabledCiphers = new ArrayList<>();
+                }
+                enabledCiphers.add(cipher);
+            }
+        }
+        return enabledCiphers != null ? enabledCiphers.toArray(new String[enabledCiphers.size()]) : ciphers;
+    }
+
+    public static SSLSessionInitializer decorateInitializer(final SSLSessionInitializer initializer) {
+        return new SSLSessionInitializer() {
+
+            @Override
+            public void initialize(final SSLEngine sslengine) throws SSLException {
+                sslengine.setEnabledProtocols(H2TlsSupport.excludeBlacklistedProtocols(sslengine.getEnabledProtocols()));
+                sslengine.setEnabledCipherSuites(H2TlsSupport.excludeBlacklistedCiphers(sslengine.getEnabledCipherSuites()));
+                if (initializer != null) {
+                    initializer.initialize(sslengine);
+                }
+            }
+
+        };
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/H2TlsSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/H2TlsSupport.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/H2TlsSupport.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message