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 2017/02/23 14:32:44 UTC
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/...
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