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:33:48 UTC

svn commit: r1784140 [1/4] - in /httpcomponents/httpclient/trunk: httpclient5-testing/docker/apache-httpd/ httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/ httpclient5-testing/src/test/resources/ httpclient5/src/examples/org/ap...

Author: olegk
Date: Thu Feb 23 14:33:47 2017
New Revision: 1784140

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

Added:
    httpcomponents/httpclient/trunk/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpAsyncClientCompatibilityTest.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientConnectionEviction.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp2Multiplexing.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttpExchange.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttpExchangeStreaming.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/AsyncClientEndpoint.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/HttpAsyncClient.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractAsyncResponseConsumer.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractBinResponseConsumer.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractCharResponseConsumer.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AsyncRequestBuilder.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/DefaultAsyncRequestProducer.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpRequest.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleHttpResponse.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleRequestProducer.java
      - copied, changed from r1784139, httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/NoopUserTokenHandler.java
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/SimpleResponseConsumer.java
      - copied, changed from r1784139, httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/NoopUserTokenHandler.java
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultUserTokenHandler.java   (contents, props changed)
      - copied, changed from r1784139, httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/protocol/DefaultUserTokenHandler.java
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/IdleConnectionEvictor.java   (contents, props changed)
      - copied, changed from r1784139, httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/IdleConnectionEvictor.java
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/NoopUserTokenHandler.java
      - copied, changed from r1784139, httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/NoopUserTokenHandler.java
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AbstractHttpAsyncClientBase.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/CloseableHttpAsyncClient.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/DefaultAsyncHttp1ClientEventHandlerFactory.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/DefaultAsyncHttp2ClientEventHandlerFactory.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/DefaultAsyncHttpClientProtocolNegotiator.java   (contents, props changed)
      - copied, changed from r1784139, httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/NoopUserTokenHandler.java
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClients.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalHttpAsyncClient.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/logging/LogAppendable.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/logging/LoggingIOEventHandler.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/logging/LoggingIOSession.java   (with props)
    httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestIdleConnectionEvictor.java   (contents, props changed)
      - copied, changed from r1784139, httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestIdleConnectionEvictor.java
Removed:
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/protocol/DefaultUserTokenHandler.java
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/IdleConnectionEvictor.java
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/NoopUserTokenHandler.java
    httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestIdleConnectionEvictor.java
Modified:
    httpcomponents/httpclient/trunk/httpclient5-testing/docker/apache-httpd/httpd-ssl.conf
    httpcomponents/httpclient/trunk/httpclient5-testing/src/test/resources/log4j2-debug.xml.template
    httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/impl/sync/HttpClientBuilder.java
    httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/integration/TestIdleConnectionEviction.java

Modified: httpcomponents/httpclient/trunk/httpclient5-testing/docker/apache-httpd/httpd-ssl.conf
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-testing/docker/apache-httpd/httpd-ssl.conf?rev=1784140&r1=1784139&r2=1784140&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-testing/docker/apache-httpd/httpd-ssl.conf (original)
+++ httpcomponents/httpclient/trunk/httpclient5-testing/docker/apache-httpd/httpd-ssl.conf Thu Feb 23 14:33:47 2017
@@ -140,11 +140,20 @@ SSLSessionCacheTimeout  300
 
 #   General setup for the virtual host
 
-Protocols http/1.1
+Protocols h2 http/1.1
+
+<IfModule http2_module>
+
+    LogLevel http2:info
+    H2Push on
+    H2Direct on
+
+</IfModule>
+
 ServerAdmin dev@hc.apache.org
 ServerName localhost:8443
-ErrorLog "/usr/local/apache2/logs/error_log"
-TransferLog "/usr/local/apache2/logs/access_log"
+ErrorLog /proc/self/fd/2
+TransferLog /proc/self/fd/2
 
 DocumentRoot "/var/httpd/www"
 <Directory "/var/httpd/www">

Added: httpcomponents/httpclient/trunk/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpAsyncClientCompatibilityTest.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpAsyncClientCompatibilityTest.java?rev=1784140&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpAsyncClientCompatibilityTest.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpAsyncClientCompatibilityTest.java Thu Feb 23 14:33:47 2017
@@ -0,0 +1,198 @@
+/*
+ * ====================================================================
+ * 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.testing.external;
+
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.hc.client5.http.async.AsyncClientEndpoint;
+import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
+import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
+import org.apache.hc.client5.http.async.methods.SimpleRequestProducer;
+import org.apache.hc.client5.http.async.methods.SimpleResponseConsumer;
+import org.apache.hc.client5.http.auth.AuthScope;
+import org.apache.hc.client5.http.auth.Credentials;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
+import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
+import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
+import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
+import org.apache.hc.client5.http.impl.sync.BasicCredentialsProvider;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.client5.http.ssl.SSLUpgradeStrategy;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.HttpVersion;
+import org.apache.hc.core5.http2.config.H2Config;
+import org.apache.hc.core5.ssl.SSLContexts;
+import org.apache.hc.core5.util.TextUtils;
+
+public class HttpAsyncClientCompatibilityTest {
+
+    public static void main(final String... args) throws Exception {
+        final HttpAsyncClientCompatibilityTest[] tests = new HttpAsyncClientCompatibilityTest[] {
+                new HttpAsyncClientCompatibilityTest(
+                        HttpVersion.HTTP_1_1, new HttpHost("localhost", 8080, "http"), null, null),
+                new HttpAsyncClientCompatibilityTest(
+                        HttpVersion.HTTP_2_0, new HttpHost("localhost", 8080, "http"), null, null),
+                new HttpAsyncClientCompatibilityTest(
+                        HttpVersion.HTTP_1_1, new HttpHost("localhost", 8443, "https"), null, null),
+                new HttpAsyncClientCompatibilityTest(
+                        HttpVersion.HTTP_2_0, new HttpHost("localhost", 8443, "https"), null, null)
+        };
+        for (final HttpAsyncClientCompatibilityTest test: tests) {
+            try {
+                test.execute();
+            } finally {
+                test.shutdown();
+            }
+        }
+    }
+
+    private final HttpVersion protocolVersion;
+    private final HttpHost target;
+    private final HttpHost proxy;
+    private final BasicCredentialsProvider credentialsProvider;
+    private final PoolingAsyncClientConnectionManager connManager;
+    private final CloseableHttpAsyncClient client;
+
+    HttpAsyncClientCompatibilityTest(
+            final HttpVersion protocolVersion,
+            final HttpHost target,
+            final HttpHost proxy,
+            final Credentials proxyCreds) throws Exception {
+        this.protocolVersion = protocolVersion;
+        this.target = target;
+        this.proxy = proxy;
+        this.credentialsProvider = new BasicCredentialsProvider();
+        final RequestConfig requestConfig = RequestConfig.custom()
+                .setProxy(proxy)
+                .build();
+        if (proxy != null && proxyCreds != null) {
+            this.credentialsProvider.setCredentials(new AuthScope(proxy), proxyCreds);
+        }
+        final SSLContext sslContext = SSLContexts.custom()
+                .loadTrustMaterial(getClass().getResource("/test-ca.keystore"), "nopassword".toCharArray()).build();
+        this.connManager = PoolingAsyncClientConnectionManagerBuilder.create()
+                .setTlsStrategy(new SSLUpgradeStrategy(sslContext))
+                .build();
+        this.client = HttpAsyncClients.custom()
+                .setProtocolVersion(this.protocolVersion)
+                .setH2Config(H2Config.custom()
+                        .setSettingAckNeeded(false)
+                        .build())
+                .setConnectionManager(this.connManager)
+                .setDefaultRequestConfig(requestConfig)
+                .build();
+    }
+
+    void shutdown() throws Exception {
+        client.close();
+    }
+
+    enum TestResult {OK, NOK};
+
+    private void logResult(final TestResult result, final HttpRequest request, final String message) {
+        final StringBuilder buf = new StringBuilder();
+        buf.append(result);
+        if (buf.length() == 2) {
+            buf.append(" ");
+        }
+        buf.append(": ").append(protocolVersion).append(" ").append(target);
+        if (proxy != null) {
+            buf.append(" via ").append(proxy);
+        }
+        buf.append(": ");
+        buf.append(request.getMethod()).append(" ").append(request.getRequestUri());
+        if (message != null && !TextUtils.isBlank(message)) {
+            buf.append(" -> ").append(message);
+        }
+        System.out.println(buf.toString());
+    }
+
+    void execute() throws Exception {
+
+        client.start();
+        // Initial ping
+        {
+            final HttpClientContext context = HttpClientContext.create();
+            context.setCredentialsProvider(credentialsProvider);
+
+            final SimpleHttpRequest options = new SimpleHttpRequest("OPTIONS", target, "*", null, null);
+            final Future<SimpleHttpResponse> future = client.execute(new SimpleRequestProducer(options), new SimpleResponseConsumer(), null);
+            try {
+                final SimpleHttpResponse response = future.get(5, TimeUnit.SECONDS);
+                final int code = response.getCode();
+                if (code == HttpStatus.SC_OK) {
+                    logResult(TestResult.OK, options, Objects.toString(response.getFirstHeader("server")));
+                } else {
+                    logResult(TestResult.NOK, options, "(status " + code + ")");
+                }
+            } catch (ExecutionException ex) {
+                final Throwable cause = ex.getCause();
+                logResult(TestResult.NOK, options, "(" + cause.getMessage() + ")");
+            } catch (TimeoutException ex) {
+                logResult(TestResult.NOK, options, "(time out)");
+            }
+        }
+        // Basic GET requests
+        {
+            final HttpClientContext context = HttpClientContext.create();
+            context.setCredentialsProvider(credentialsProvider);
+
+            final Future<AsyncClientEndpoint> leaseFuture = client.lease(target, null);
+            final AsyncClientEndpoint clientEndpoint = leaseFuture.get(20, TimeUnit.SECONDS);
+
+            final String[] requestUris = new String[] {"/", "/news.html", "/status.html"};
+            for (String requestUri: requestUris) {
+                final SimpleHttpRequest httpGet = new SimpleHttpRequest("GET", target, requestUri, null, null);
+                final Future<SimpleHttpResponse> future = clientEndpoint.execute(new SimpleRequestProducer(httpGet), new SimpleResponseConsumer(), null);
+                try {
+                    final SimpleHttpResponse response = future.get(5, TimeUnit.SECONDS);
+                    final int code = response.getCode();
+                    if (code == HttpStatus.SC_OK) {
+                        logResult(TestResult.OK, httpGet, "200");
+                    } else {
+                        logResult(TestResult.NOK, httpGet, "(status " + code + ")");
+                    }
+                } catch (ExecutionException ex) {
+                    final Throwable cause = ex.getCause();
+                    logResult(TestResult.NOK, httpGet, "(" + cause.getMessage() + ")");
+                } catch (TimeoutException ex) {
+                    logResult(TestResult.NOK, httpGet, "(time out)");
+                }
+            }
+        }
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpAsyncClientCompatibilityTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpAsyncClientCompatibilityTest.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpclient/trunk/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpAsyncClientCompatibilityTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpclient/trunk/httpclient5-testing/src/test/resources/log4j2-debug.xml.template
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-testing/src/test/resources/log4j2-debug.xml.template?rev=1784140&r1=1784139&r2=1784140&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-testing/src/test/resources/log4j2-debug.xml.template (original)
+++ httpcomponents/httpclient/trunk/httpclient5-testing/src/test/resources/log4j2-debug.xml.template Thu Feb 23 14:33:47 2017
@@ -25,7 +25,10 @@
         <Root level="warn">
             <AppenderRef ref="STDOUT"/>
         </Root>
-        <Logger name="org.apache.hc.client5.http.headers" level="debug"/>
+        <Logger name="org.apache.hc.core5.reactor" level="warn"/>
+        <Logger name="org.apache.hc.client5.http" level="warn"/>
         <Logger name="org.apache.hc.client5.http.wire" level="error"/>
+        <Logger name="org.apache.hc.client5.http2" level="warn"/>
+        <Logger name="org.apache.hc.client5.http2.frame.payload" level="error"/>
     </Loggers>
 </Configuration>
\ No newline at end of file

Added: httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientConnectionEviction.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientConnectionEviction.java?rev=1784140&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientConnectionEviction.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientConnectionEviction.java Thu Feb 23 14:33:47 2017
@@ -0,0 +1,124 @@
+/*
+ * ====================================================================
+ * 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.examples;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
+import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
+import org.apache.hc.client5.http.async.methods.SimpleRequestProducer;
+import org.apache.hc.client5.http.async.methods.SimpleResponseConsumer;
+import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
+import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.reactor.IOReactorConfig;
+
+/**
+ * Example demonstrating how to evict expired and idle connections
+ * from the connection pool.
+ */
+public class AsyncClientConnectionEviction {
+
+    public static void main(String[] args) throws Exception {
+
+        IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
+                .setConnectTimeout(5000)
+                .setSoTimeout(5000)
+                .build();
+
+        CloseableHttpAsyncClient client = HttpAsyncClients.custom()
+                .setIOReactorConfig(ioReactorConfig)
+                .evictExpiredConnections()
+                .evictIdleConnections(10, TimeUnit.SECONDS)
+                .build();
+
+        client.start();
+
+        HttpHost target = new HttpHost("httpbin.org");
+
+        final SimpleHttpRequest request = new SimpleHttpRequest("GET", target, "/", null, null);
+        final Future<SimpleHttpResponse> future1 = client.execute(
+                new SimpleRequestProducer(request),
+                new SimpleResponseConsumer(),
+                new FutureCallback<SimpleHttpResponse>() {
+
+                    @Override
+                    public void completed(final SimpleHttpResponse response) {
+                        System.out.println(request.getRequestUri() + "->" + response.getCode());
+                        System.out.println(response.getBody());
+                    }
+
+                    @Override
+                    public void failed(final Exception ex) {
+                        System.out.println(request.getRequestUri() + "->" + ex);
+                    }
+
+                    @Override
+                    public void cancelled() {
+                        System.out.println(request.getRequestUri() + " cancelled");
+                    }
+
+                });
+
+        future1.get();
+
+        Thread.sleep(TimeUnit.SECONDS.toMillis(30));
+
+        // Previous connection should get evicted from the pool by now
+
+        final Future<SimpleHttpResponse> future2 = client.execute(
+                new SimpleRequestProducer(request),
+                new SimpleResponseConsumer(),
+                new FutureCallback<SimpleHttpResponse>() {
+
+                    @Override
+                    public void completed(final SimpleHttpResponse response) {
+                        System.out.println(request.getRequestUri() + "->" + response.getCode());
+                        System.out.println(response.getBody());
+                    }
+
+                    @Override
+                    public void failed(final Exception ex) {
+                        System.out.println(request.getRequestUri() + "->" + ex);
+                    }
+
+                    @Override
+                    public void cancelled() {
+                        System.out.println(request.getRequestUri() + " cancelled");
+                    }
+
+                });
+
+        future2.get();
+
+        System.out.println("Shutting down");
+        client.shutdown(5, TimeUnit.SECONDS);
+    }
+
+}

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

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

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

Added: httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java?rev=1784140&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java Thu Feb 23 14:33:47 2017
@@ -0,0 +1,108 @@
+/*
+ * ====================================================================
+ * 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.examples;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hc.client5.http.async.AsyncClientEndpoint;
+import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
+import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
+import org.apache.hc.client5.http.async.methods.SimpleRequestProducer;
+import org.apache.hc.client5.http.async.methods.SimpleResponseConsumer;
+import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
+import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpVersion;
+import org.apache.hc.core5.reactor.IOReactorConfig;
+
+/**
+ * This example demonstrates pipelined execution of multiple HTTP/1.1 message exchanges.
+ */
+public class AsyncClientHttp1Pipelining {
+
+    public static void main(String[] args) throws Exception {
+
+        IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
+                .setConnectTimeout(5000)
+                .setSoTimeout(5000)
+                .build();
+
+        CloseableHttpAsyncClient client = HttpAsyncClients.custom()
+                .setProtocolVersion(HttpVersion.HTTP_1_1)
+                .setIOReactorConfig(ioReactorConfig)
+                .build();
+
+        client.start();
+
+        HttpHost target = new HttpHost("httpbin.org");
+        Future<AsyncClientEndpoint> leaseFuture = client.lease(target, null);
+        AsyncClientEndpoint endpoint = leaseFuture.get(30, TimeUnit.SECONDS);
+        try {
+            String[] requestUris = new String[] {"/", "/ip", "/user-agent", "/headers"};
+
+            final CountDownLatch latch = new CountDownLatch(requestUris.length);
+            for (final String requestUri: requestUris) {
+                SimpleHttpRequest request = new SimpleHttpRequest("GET", target, requestUri, null, null);
+                endpoint.execute(
+                        new SimpleRequestProducer(request),
+                        new SimpleResponseConsumer(),
+                        new FutureCallback<SimpleHttpResponse>() {
+
+                            @Override
+                            public void completed(final SimpleHttpResponse response) {
+                                latch.countDown();
+                                System.out.println(requestUri + "->" + response.getCode());
+                                System.out.println(response.getBody());
+                            }
+
+                            @Override
+                            public void failed(final Exception ex) {
+                                latch.countDown();
+                                System.out.println(requestUri + "->" + ex);
+                            }
+
+                            @Override
+                            public void cancelled() {
+                                latch.countDown();
+                                System.out.println(requestUri + " cancelled");
+                            }
+
+                        });
+            }
+            latch.await();
+        } finally {
+            endpoint.releaseAndReuse();
+        }
+
+        System.out.println("Shutting down");
+        client.shutdown(5, TimeUnit.SECONDS);
+    }
+
+}

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

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

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

Added: httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp2Multiplexing.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp2Multiplexing.java?rev=1784140&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp2Multiplexing.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttp2Multiplexing.java Thu Feb 23 14:33:47 2017
@@ -0,0 +1,109 @@
+/*
+ * ====================================================================
+ * 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.examples;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hc.client5.http.async.AsyncClientEndpoint;
+import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
+import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
+import org.apache.hc.client5.http.async.methods.SimpleRequestProducer;
+import org.apache.hc.client5.http.async.methods.SimpleResponseConsumer;
+import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
+import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpVersion;
+import org.apache.hc.core5.reactor.IOReactorConfig;
+
+/**
+ * This example demonstrates concurrent (multiplexed) execution of multiple
+ * HTTP/2 message exchanges.
+ */
+public class AsyncClientHttp2Multiplexing {
+
+    public static void main(String[] args) throws Exception {
+
+        IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
+                .setConnectTimeout(5000)
+                .setSoTimeout(5000)
+                .build();
+
+        CloseableHttpAsyncClient client = HttpAsyncClients.custom()
+                .setProtocolVersion(HttpVersion.HTTP_1_1)
+                .setIOReactorConfig(ioReactorConfig)
+                .build();
+
+        client.start();
+
+        HttpHost target = new HttpHost("http2bin.org");
+        Future<AsyncClientEndpoint> leaseFuture = client.lease(target, null);
+        AsyncClientEndpoint endpoint = leaseFuture.get(30, TimeUnit.SECONDS);
+        try {
+            String[] requestUris = new String[] {"/", "/ip", "/user-agent", "/headers"};
+
+            final CountDownLatch latch = new CountDownLatch(requestUris.length);
+            for (final String requestUri: requestUris) {
+                SimpleHttpRequest request = new SimpleHttpRequest("GET", target, requestUri, null, null);
+                endpoint.execute(
+                        new SimpleRequestProducer(request),
+                        new SimpleResponseConsumer(),
+                        new FutureCallback<SimpleHttpResponse>() {
+
+                            @Override
+                            public void completed(final SimpleHttpResponse response) {
+                                latch.countDown();
+                                System.out.println(requestUri + "->" + response.getCode());
+                                System.out.println(response.getBody());
+                            }
+
+                            @Override
+                            public void failed(final Exception ex) {
+                                latch.countDown();
+                                System.out.println(requestUri + "->" + ex);
+                            }
+
+                            @Override
+                            public void cancelled() {
+                                latch.countDown();
+                                System.out.println(requestUri + " cancelled");
+                            }
+
+                        });
+            }
+            latch.await();
+        } finally {
+            endpoint.releaseAndReuse();
+        }
+
+        System.out.println("Shutting down");
+        client.shutdown(5, TimeUnit.SECONDS);
+    }
+
+}

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

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

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

Added: httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttpExchange.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttpExchange.java?rev=1784140&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttpExchange.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttpExchange.java Thu Feb 23 14:33:47 2017
@@ -0,0 +1,94 @@
+/*
+ * ====================================================================
+ * 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.examples;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
+import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
+import org.apache.hc.client5.http.async.methods.SimpleRequestProducer;
+import org.apache.hc.client5.http.async.methods.SimpleResponseConsumer;
+import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
+import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.reactor.IOReactorConfig;
+
+/**
+ * Example of asynchronous HTTP/1.1 request execution.
+ */
+public class AsyncClientHttpExchange {
+
+    public static void main(String[] args) throws Exception {
+
+        IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
+                .setConnectTimeout(5000)
+                .setSoTimeout(5000)
+                .build();
+
+        CloseableHttpAsyncClient client = HttpAsyncClients.custom()
+                .setIOReactorConfig(ioReactorConfig)
+                .build();
+
+        client.start();
+
+        HttpHost target = new HttpHost("httpbin.org");
+        String[] requestUris = new String[] {"/", "/ip", "/user-agent", "/headers"};
+
+        for (final String requestUri: requestUris) {
+            SimpleHttpRequest request = new SimpleHttpRequest("GET", target, requestUri, null, null);
+            Future<SimpleHttpResponse> future = client.execute(
+                    new SimpleRequestProducer(request),
+                    new SimpleResponseConsumer(),
+                    new FutureCallback<SimpleHttpResponse>() {
+
+                        @Override
+                        public void completed(final SimpleHttpResponse response) {
+                            System.out.println(requestUri + "->" + response.getCode());
+                            System.out.println(response.getBody());
+                        }
+
+                        @Override
+                        public void failed(final Exception ex) {
+                            System.out.println(requestUri + "->" + ex);
+                        }
+
+                        @Override
+                        public void cancelled() {
+                            System.out.println(requestUri + " cancelled");
+                        }
+
+                    });
+            future.get();
+        }
+
+        System.out.println("Shutting down");
+        client.shutdown(5, TimeUnit.SECONDS);
+    }
+
+}

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

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

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

Added: httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttpExchangeStreaming.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttpExchangeStreaming.java?rev=1784140&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttpExchangeStreaming.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/examples/org/apache/hc/client5/http/examples/AsyncClientHttpExchangeStreaming.java Thu Feb 23 14:33:47 2017
@@ -0,0 +1,111 @@
+/*
+ * ====================================================================
+ * 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.examples;
+
+import java.io.IOException;
+import java.nio.CharBuffer;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hc.client5.http.async.methods.AbstractCharResponseConsumer;
+import org.apache.hc.client5.http.async.methods.AsyncRequestBuilder;
+import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
+import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.message.StatusLine;
+import org.apache.hc.core5.reactor.IOReactorConfig;
+
+/**
+ * Example of asynchronous HTTP/1.1 request execution with response streaming.
+ */
+public class AsyncClientHttpExchangeStreaming {
+
+    public static void main(String[] args) throws Exception {
+
+        IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
+                .setConnectTimeout(5000)
+                .setSoTimeout(5000)
+                .build();
+
+        CloseableHttpAsyncClient client = HttpAsyncClients.custom()
+                .setIOReactorConfig(ioReactorConfig)
+                .build();
+
+        client.start();
+
+        HttpHost target = new HttpHost("httpbin.org");
+        String[] requestUris = new String[] {"/", "/ip", "/user-agent", "/headers"};
+
+        for (final String requestUri: requestUris) {
+            Future<Void> future = client.execute(
+                    AsyncRequestBuilder.get(target, requestUri).build(),
+                    new AbstractCharResponseConsumer<Void>() {
+
+                        @Override
+                        protected void start(
+                                final HttpResponse response,
+                                final ContentType contentType) throws HttpException, IOException {
+                            System.out.println(requestUri + "->" + new StatusLine(response));
+                        }
+
+                        @Override
+                        protected int capacity() {
+                            return Integer.MAX_VALUE;
+                        }
+
+                        @Override
+                        protected void data(final CharBuffer data, final boolean endOfStream) throws IOException {
+                            while (data.hasRemaining()) {
+                                System.out.print(data.get());
+                            }
+                            if (endOfStream) {
+                                System.out.println();
+                            }
+                        }
+
+                        @Override
+                        protected Void getResult() {
+                            return null;
+                        }
+
+                        @Override
+                        public void failed(final Exception cause) {
+                            System.out.println(requestUri + "->" + cause);
+                        }
+
+                    }, null);
+            future.get();
+        }
+
+        System.out.println("Shutting down");
+        client.shutdown(5, TimeUnit.SECONDS);
+    }
+
+}

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

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

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

Added: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/AsyncClientEndpoint.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/AsyncClientEndpoint.java?rev=1784140&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/AsyncClientEndpoint.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/AsyncClientEndpoint.java Thu Feb 23 14:33:47 2017
@@ -0,0 +1,178 @@
+/*
+ * ====================================================================
+ * 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.async;
+
+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 endpoint leased from a connection manager.
+ * <p>
+ * Once the endpoint is no longer needed it MUST be released with {@link #releaseAndReuse()}
+ * or {@link #releaseAndDiscard()}.
+ *
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.SAFE)
+public abstract class AsyncClientEndpoint {
+
+    /**
+     * Initiates a message exchange using the given handler.
+     * <p>
+     * Once the endpoint is no longer needed it MUST be released with {@link #releaseAndReuse()}
+     * or {@link #releaseAndDiscard()}.
+     */
+    public abstract void execute(AsyncClientExchangeHandler exchangeHandler, HttpContext context);
+
+    /**
+     * Releases the underlying connection back to the connection pool as re-usable.
+     */
+    public abstract void releaseAndReuse();
+
+    /**
+     * Shuts down the underlying connection and removes it from the connection pool.
+     */
+    public abstract void releaseAndDiscard();
+
+    /**
+     * Initiates message exchange using the given request producer and response consumer.
+     * <p>
+     * Once the endpoint is no longer needed it MUST be released with {@link #releaseAndReuse()}
+     * or {@link #releaseAndDiscard()}.
+     */
+    public final <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;
+    }
+
+    /**
+     * Initiates a message exchange using the given request producer and response consumer.
+     * <p>
+     * Once the endpoint is no longer needed it MUST be released with {@link #releaseAndReuse()}
+     * or {@link #releaseAndDiscard()}.
+     */
+    public final <T> Future<T> execute(
+            final AsyncRequestProducer requestProducer,
+            final AsyncResponseConsumer<T> responseConsumer,
+            final FutureCallback<T> callback) {
+        return execute(requestProducer, responseConsumer, null, callback);
+    }
+
+    /**
+     * Initiates a message exchange using the given request producer and response consumer and
+     * automatically invokes {@link #releaseAndReuse()} upon its successful completion.
+     */
+    public final <T> Future<T> executeAndRelease(
+            final AsyncRequestProducer requestProducer,
+            final AsyncResponseConsumer<T> responseConsumer,
+            final HttpContext context,
+            final FutureCallback<T> callback) {
+        return execute(requestProducer, responseConsumer, context, new FutureCallback<T>() {
+
+            @Override
+            public void completed(final T result) {
+                try {
+                    if (callback != null) {
+                        callback.completed(result);
+                    }
+                } finally {
+                    releaseAndReuse();
+                }
+            }
+
+            @Override
+            public void failed(final Exception ex) {
+                try {
+                    if (callback != null) {
+                        callback.failed(ex);
+                    }
+                } finally {
+                    releaseAndDiscard();
+                }
+            }
+
+            @Override
+            public void cancelled() {
+                try {
+                    if (callback != null) {
+                        callback.cancelled();
+                    }
+                } finally {
+                    releaseAndDiscard();
+                }
+            }
+
+        });
+    }
+
+    /**
+     * Initiates a message exchange using the given request producer and response consumer and
+     * automatically invokes {@link #releaseAndReuse()} upon its successful completion.
+     */
+    public final <T> Future<T> executeAndRelease(
+            final AsyncRequestProducer requestProducer,
+            final AsyncResponseConsumer<T> responseConsumer,
+            final FutureCallback<T> callback) {
+        return executeAndRelease(requestProducer, responseConsumer, null, callback);
+    }
+
+}

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

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

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

Added: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/HttpAsyncClient.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/HttpAsyncClient.java?rev=1784140&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/HttpAsyncClient.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/HttpAsyncClient.java Thu Feb 23 14:33:47 2017
@@ -0,0 +1,82 @@
+/*
+ * ====================================================================
+ * 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.async;
+
+import java.util.concurrent.Future;
+
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.nio.AsyncRequestProducer;
+import org.apache.hc.core5.http.nio.AsyncResponseConsumer;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+/**
+ * This interface represents only the most basic contract for HTTP request
+ * execution. It imposes no restrictions or particular details on the request
+ * execution process and leaves the specifics of state management,
+ * authentication and redirect handling up to individual implementations.
+ *
+ * @since 4.0
+ */
+public interface HttpAsyncClient {
+
+    /**
+     * Leases {@link AsyncClientEndpoint} for the given {@link HttpHost}.
+     * <p>
+     * The endpoint MUST be released back when no longer used by calling
+     * {@link AsyncClientEndpoint#releaseAndReuse()} or {@link AsyncClientEndpoint#releaseAndDiscard()}
+     */
+    Future<AsyncClientEndpoint> lease(
+            HttpHost host,
+            HttpContext context,
+            FutureCallback<AsyncClientEndpoint> callback);
+
+    /**
+     * Initiates asynchronous HTTP request execution using the given context.
+     * <p>
+     * The request producer passed to this method will be used to generate
+     * a request message and stream out its content without buffering it
+     * in memory. The response consumer passed to this method will be used
+     * to process a response message without buffering its content in memory.
+     * <p>
+     * Please note it may be unsafe to interact with the context instance
+     * while the request is still being executed.
+     *
+     * @param <T> the result type of request execution.
+     * @param requestProducer request producer callback.
+     * @param responseConsumer response consumer callaback.
+     * @param context HTTP context
+     * @param callback future callback.
+     * @return future representing pending completion of the operation.
+     */
+    <T> Future<T> execute(
+            AsyncRequestProducer requestProducer,
+            AsyncResponseConsumer<T> responseConsumer,
+            HttpContext context,
+            FutureCallback<T> callback);
+
+}

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

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

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

Added: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractAsyncResponseConsumer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractAsyncResponseConsumer.java?rev=1784140&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractAsyncResponseConsumer.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractAsyncResponseConsumer.java Thu Feb 23 14:33:47 2017
@@ -0,0 +1,118 @@
+/*
+ * ====================================================================
+ * 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.async.methods;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.List;
+
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.EntityDetails;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.nio.AsyncEntityConsumer;
+import org.apache.hc.core5.http.nio.AsyncResponseConsumer;
+import org.apache.hc.core5.http.nio.CapacityChannel;
+import org.apache.hc.core5.util.Args;
+
+public abstract class AbstractAsyncResponseConsumer<T, E> implements AsyncResponseConsumer<T> {
+
+    private final AsyncEntityConsumer<E> entityConsumer;
+
+    public AbstractAsyncResponseConsumer(final AsyncEntityConsumer<E> entityConsumer) {
+        Args.notNull(entityConsumer, "Entity consumer");
+        this.entityConsumer = entityConsumer;
+    }
+
+    protected abstract T buildResult(HttpResponse response, E entity, ContentType contentType);
+
+    @Override
+    public final void consumeResponse(
+            final HttpResponse response,
+            final EntityDetails entityDetails,
+            final FutureCallback<T> resultCallback) throws HttpException, IOException {
+        if (entityDetails != null) {
+            entityConsumer.streamStart(entityDetails, new FutureCallback<E>() {
+
+                @Override
+                public void completed(final E result) {
+                    final ContentType contentType;
+                    try {
+                        contentType = ContentType.parse(entityDetails.getContentType());
+                        resultCallback.completed(buildResult(response, result, contentType));
+                    } catch (UnsupportedCharsetException ex) {
+                        resultCallback.failed(ex);
+                    }
+                }
+
+                @Override
+                public void failed(final Exception ex) {
+                    resultCallback.failed(ex);
+                }
+
+                @Override
+                public void cancelled() {
+                    resultCallback.cancelled();
+                }
+
+            });
+        } else {
+            resultCallback.completed(buildResult(response, null, null));
+            entityConsumer.releaseResources();
+        }
+
+    }
+
+    @Override
+    public final void updateCapacity(final CapacityChannel capacityChannel) throws IOException {
+        entityConsumer.updateCapacity(capacityChannel);
+    }
+
+    @Override
+    public final int consume(final ByteBuffer src) throws IOException {
+        return entityConsumer.consume(src);
+    }
+
+    @Override
+    public final void streamEnd(final List<? extends Header> trailers) throws HttpException, IOException {
+        entityConsumer.streamEnd(trailers);
+    }
+
+    @Override
+    public final void failed(final Exception cause) {
+        releaseResources();
+    }
+
+    @Override
+    public final void releaseResources() {
+        entityConsumer.releaseResources();
+    }
+
+}
\ No newline at end of file

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

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

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

Added: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractBinResponseConsumer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractBinResponseConsumer.java?rev=1784140&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractBinResponseConsumer.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractBinResponseConsumer.java Thu Feb 23 14:33:47 2017
@@ -0,0 +1,103 @@
+/*
+ * ====================================================================
+ * 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.async.methods;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.List;
+
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.EntityDetails;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.nio.AsyncResponseConsumer;
+import org.apache.hc.core5.http.nio.CapacityChannel;
+
+public abstract class AbstractBinResponseConsumer<T> implements AsyncResponseConsumer<T> {
+
+    private static final ByteBuffer EMPTY = ByteBuffer.wrap(new byte[0]);
+
+    private volatile FutureCallback<T> resultCallback;
+
+    protected abstract void start(HttpResponse response, ContentType contentType) throws HttpException, IOException;
+
+    protected abstract int capacity();
+
+    protected abstract void data(ByteBuffer data, boolean endOfStream) throws IOException;
+
+    protected abstract T getResult();
+
+    @Override
+    public final void consumeResponse(
+            final HttpResponse response,
+            final EntityDetails entityDetails,
+            final FutureCallback<T> resultCallback) throws HttpException, IOException {
+        this.resultCallback = resultCallback;
+        if (entityDetails != null) {
+            try {
+                final ContentType contentType = ContentType.parse(entityDetails.getContentType());
+                start(response, contentType);
+            } catch (UnsupportedCharsetException ex) {
+                throw new UnsupportedEncodingException(ex.getMessage());
+            }
+        } else {
+            start(response, null);
+            resultCallback.completed(getResult());
+        }
+
+    }
+
+    @Override
+    public final void updateCapacity(final CapacityChannel capacityChannel) throws IOException {
+        capacityChannel.update(capacity());
+    }
+
+    @Override
+    public final int consume(final ByteBuffer src) throws IOException {
+        data(src, false);
+        return capacity();
+    }
+
+    @Override
+    public final void streamEnd(final List<? extends Header> trailers) throws HttpException, IOException {
+        data(EMPTY, true);
+        resultCallback.completed(getResult());
+    }
+
+    @Override
+    public void failed(final Exception cause) {
+    }
+
+    @Override
+    public void releaseResources() {
+    }
+
+}
\ No newline at end of file

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

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

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

Added: httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractCharResponseConsumer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractCharResponseConsumer.java?rev=1784140&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractCharResponseConsumer.java (added)
+++ httpcomponents/httpclient/trunk/httpclient5/src/main/java/org/apache/hc/client5/http/async/methods/AbstractCharResponseConsumer.java Thu Feb 23 14:33:47 2017
@@ -0,0 +1,142 @@
+/*
+ * ====================================================================
+ * 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.async.methods;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.List;
+
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.EntityDetails;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.nio.AsyncResponseConsumer;
+import org.apache.hc.core5.http.nio.CapacityChannel;
+import org.apache.hc.core5.util.Asserts;
+
+public abstract class AbstractCharResponseConsumer<T> implements AsyncResponseConsumer<T> {
+
+    private static final ByteBuffer EMPTY_BIN = ByteBuffer.wrap(new byte[0]);
+    private static final CharBuffer EMPTY_CHAR = CharBuffer.wrap(new char[0]);
+
+    private final CharBuffer charbuf = CharBuffer.allocate(8192);
+
+    private volatile CharsetDecoder charsetDecoder;
+    private volatile FutureCallback<T> resultCallback;
+
+    protected abstract void start(HttpResponse response, ContentType contentType) throws HttpException, IOException;
+
+    protected abstract int capacity();
+
+    protected abstract void data(CharBuffer data, boolean endOfStream) throws IOException;
+
+    protected abstract T getResult();
+
+    @Override
+    public final void consumeResponse(
+            final HttpResponse response,
+            final EntityDetails entityDetails,
+            final FutureCallback<T> resultCallback) throws HttpException, IOException {
+        this.resultCallback = resultCallback;
+        if (entityDetails != null) {
+            ContentType contentType;
+            try {
+                contentType = ContentType.parse(entityDetails.getContentType());
+            } catch (UnsupportedCharsetException ex) {
+                throw new UnsupportedEncodingException(ex.getMessage());
+            }
+            Charset charset = contentType != null ? contentType.getCharset() : null;
+            if (charset == null) {
+                charset = StandardCharsets.US_ASCII;
+            }
+            charsetDecoder = charset.newDecoder();
+            start(response, contentType);
+        } else {
+            start(response, null);
+            resultCallback.completed(getResult());
+        }
+    }
+
+    @Override
+    public final void updateCapacity(final CapacityChannel capacityChannel) throws IOException {
+        capacityChannel.update(capacity());
+    }
+
+    private void checkResult(final CoderResult result) throws IOException {
+        if (result.isError()) {
+            result.throwException();
+        }
+    }
+
+    private void doDecode() throws IOException {
+        charbuf.flip();
+        final int chunk = charbuf.remaining();
+        if (chunk > 0) {
+            data(charbuf, false);
+        }
+        charbuf.clear();
+    }
+
+    @Override
+    public final int consume(final ByteBuffer src) throws IOException {
+        Asserts.notNull(charsetDecoder, "Charset decoder");
+        while (src.hasRemaining()) {
+            checkResult(charsetDecoder.decode(src, charbuf, false));
+            doDecode();
+        }
+        return capacity();
+    }
+
+    @Override
+    public final void streamEnd(final List<? extends Header> trailers) throws HttpException, IOException {
+        Asserts.notNull(charsetDecoder, "Charset decoder");
+        checkResult(charsetDecoder.decode(EMPTY_BIN, charbuf, true));
+        doDecode();
+        checkResult(charsetDecoder.flush(charbuf));
+        doDecode();
+        data(EMPTY_CHAR, true);
+        resultCallback.completed(getResult());
+    }
+
+    @Override
+    public void failed(final Exception cause) {
+    }
+
+    @Override
+    public void releaseResources() {
+    }
+
+}
\ No newline at end of file

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

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

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