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 2016/12/03 09:47:15 UTC

svn commit: r1772441 [2/4] - in /httpcomponents/httpcore/trunk: httpcore5-ab/src/main/java/org/apache/hc/core5/http/benchmark/ httpcore5-ab/src/test/java/org/apache/hc/core5/http/benchmark/ httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/...

Modified: httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/ClassicReverseProxyExample.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/ClassicReverseProxyExample.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/ClassicReverseProxyExample.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/ClassicReverseProxyExample.java Sat Dec  3 09:47:13 2016
@@ -28,7 +28,6 @@
 package org.apache.hc.core5.http.examples;
 
 import java.io.IOException;
-import java.io.InterruptedIOException;
 import java.net.SocketTimeoutException;
 import java.util.Arrays;
 import java.util.Collections;
@@ -36,8 +35,6 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Locale;
 import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.hc.core5.http.ClassicHttpRequest;
@@ -45,21 +42,27 @@ import org.apache.hc.core5.http.ClassicH
 import org.apache.hc.core5.http.ConnectionClosedException;
 import org.apache.hc.core5.http.ExceptionListener;
 import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpConnection;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpHeaders;
 import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.config.SocketConfig;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
 import org.apache.hc.core5.http.impl.io.bootstrap.HttpRequester;
 import org.apache.hc.core5.http.impl.io.bootstrap.HttpServer;
 import org.apache.hc.core5.http.impl.io.bootstrap.RequesterBootstrap;
 import org.apache.hc.core5.http.impl.io.bootstrap.ServerBootstrap;
-import org.apache.hc.core5.http.impl.io.pool.BasicConnPool;
-import org.apache.hc.core5.http.impl.io.pool.BasicPoolEntry;
-import org.apache.hc.core5.http.io.HttpClientConnection;
 import org.apache.hc.core5.http.io.HttpRequestHandler;
-import org.apache.hc.core5.http.io.entity.HttpEntityWrapper;
 import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
+import org.apache.hc.core5.http.message.RequestLine;
+import org.apache.hc.core5.http.message.StatusLine;
 import org.apache.hc.core5.http.protocol.HttpContext;
 import org.apache.hc.core5.http.protocol.HttpCoreContext;
+import org.apache.hc.core5.pool.ConnPoolListener;
+import org.apache.hc.core5.pool.ConnPoolStats;
+import org.apache.hc.core5.pool.PoolStats;
 
 /**
  * Example of embedded HTTP/1.1 reverse proxy using classic I/O.
@@ -80,14 +83,74 @@ public class ClassicReverseProxyExample
         System.out.println("Reverse proxy to " + targetHost);
 
         final HttpRequester requester = RequesterBootstrap.bootstrap()
-                .create();
+                .setStreamListener(new Http1StreamListener() {
+
+                    @Override
+                    public void onRequestHead(final HttpConnection connection, final HttpRequest request) {
+                        System.out.println(connection + " >> " + new RequestLine(request));
+
+                    }
+
+                    @Override
+                    public void onResponseHead(final HttpConnection connection, final HttpResponse response) {
+                        System.out.println(connection + " << " + new StatusLine(response));
+                    }
+
+                    @Override
+                    public void onExchangeComplete(final HttpConnection connection, final boolean keepAlive) {
+                        if (keepAlive) {
+                            System.out.println(connection + " >> can be kept alive");
+                        } else {
+                            System.out.println(connection + " >> cannot be kept alive");
+                        }
+                    }
+
+                })
+                .setConnPoolListener(new ConnPoolListener<HttpHost>() {
 
-        final BasicConnPool connPool = new BasicConnPool();
-        connPool.setDefaultMaxPerRoute(20);
-        connPool.setMaxTotal(100);
+                    @Override
+                    public void onLease(final HttpHost route, final ConnPoolStats<HttpHost> connPoolStats) {
+                    }
+
+                    @Override
+                    public void onRelease(final HttpHost route, final ConnPoolStats<HttpHost> connPoolStats) {
+                        StringBuilder buf = new StringBuilder();
+                        buf.append(route).append(" ");
+                        PoolStats totals = connPoolStats.getTotalStats();
+                        buf.append(" total kept alive: ").append(totals.getAvailable()).append("; ");
+                        buf.append("total allocated: ").append(totals.getLeased() + totals.getAvailable());
+                        buf.append(" of ").append(totals.getMax());
+                        System.out.println(buf.toString());
+                    }
+
+                })
+                .create();
 
         final HttpServer server = ServerBootstrap.bootstrap()
                 .setListenerPort(port)
+                .setStreamListener(new Http1StreamListener() {
+
+                    @Override
+                    public void onRequestHead(final HttpConnection connection, final HttpRequest request) {
+                        System.out.println(connection + " >> " + new RequestLine(request));
+
+                    }
+
+                    @Override
+                    public void onResponseHead(final HttpConnection connection, final HttpResponse response) {
+                        System.out.println(connection + " << " + new StatusLine(response));
+                    }
+
+                    @Override
+                    public void onExchangeComplete(final HttpConnection connection, final boolean keepAlive) {
+                        if (keepAlive) {
+                            System.out.println(connection + " >> can be kept alive");
+                        } else {
+                            System.out.println(connection + " >> cannot be kept alive");
+                        }
+                    }
+
+                })
                 .setExceptionListener(new ExceptionListener() {
 
                     @Override
@@ -102,7 +165,7 @@ public class ClassicReverseProxyExample
                     }
 
                 })
-                .registerHandler("*", new ProxyHandler(targetHost, connPool, requester))
+                .registerHandler("*", new ProxyHandler(targetHost, requester))
                 .create();
 
         server.start();
@@ -110,6 +173,7 @@ public class ClassicReverseProxyExample
             @Override
             public void run() {
                 server.shutdown(5, TimeUnit.SECONDS);
+                requester.shutdown();
             }
         });
 
@@ -131,16 +195,13 @@ public class ClassicReverseProxyExample
     static class ProxyHandler implements HttpRequestHandler  {
 
         private final HttpHost targetHost;
-        private final BasicConnPool connPool;
         private final HttpRequester requester;
 
         public ProxyHandler(
                 final HttpHost targetHost,
-                final BasicConnPool connPool,
                 final HttpRequester requester) {
             super();
             this.targetHost = targetHost;
-            this.connPool = connPool;
             this.requester = requester;
         }
 
@@ -150,22 +211,6 @@ public class ClassicReverseProxyExample
                 final ClassicHttpResponse outgoingResponse,
                 final HttpContext serverContext) throws HttpException, IOException {
 
-            final Future<BasicPoolEntry> future = connPool.lease(targetHost, null);
-            final BasicPoolEntry poolEntry;
-            try {
-                poolEntry = future.get();
-            } catch (InterruptedException ex) {
-                throw new InterruptedIOException();
-            } catch (ExecutionException ex) {
-                Throwable cause = ex.getCause();
-                if (cause instanceof RuntimeException) {
-                    throw (RuntimeException) cause;
-                } else if (cause instanceof IOException) {
-                    throw (IOException) cause;
-                } else {
-                    throw new IOException("Failure obtaining connection to " + targetHost);
-                }
-            }
             final HttpCoreContext clientContext = HttpCoreContext.create();
             final ClassicHttpRequest outgoingRequest = new BasicClassicHttpRequest(incomingRequest.getMethod(), incomingRequest.getPath());
             for (Iterator<Header> it = incomingRequest.headerIterator(); it.hasNext(); ) {
@@ -174,8 +219,8 @@ public class ClassicReverseProxyExample
                     outgoingRequest.addHeader(header);
                 }
             }
-            final HttpClientConnection connection = poolEntry.getConnection();
-            final ClassicHttpResponse incomingResponse = requester.execute(connection, outgoingRequest, clientContext);
+            final ClassicHttpResponse incomingResponse = requester.execute(
+                    targetHost, outgoingRequest, SocketConfig.DEFAULT, clientContext);
             outgoingResponse.setCode(incomingResponse.getCode());
             for (Iterator<Header> it = incomingResponse.headerIterator(); it.hasNext(); ) {
                 Header header = it.next();
@@ -183,20 +228,7 @@ public class ClassicReverseProxyExample
                     outgoingResponse.addHeader(header);
                 }
             }
-            outgoingResponse.setEntity(new HttpEntityWrapper(incomingResponse.getEntity()) {
-
-                @Override
-                public void close() throws IOException {
-                    boolean keepAlive = false;
-                    try {
-                        super.close();
-                        keepAlive = requester.keepAlive(connection, outgoingRequest, incomingResponse, clientContext);
-                    } finally {
-                        connPool.release(poolEntry, keepAlive);
-                    }
-                }
-
-            });
+            outgoingResponse.setEntity(incomingResponse.getEntity());
         }
     }
 

Added: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureWrapper.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureWrapper.java?rev=1772441&view=auto
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureWrapper.java (added)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureWrapper.java Sat Dec  3 09:47:13 2016
@@ -0,0 +1,91 @@
+/*
+ * ====================================================================
+ * 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.core5.concurrent;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.hc.core5.util.Args;
+
+/**
+ * Future wrapper that can cancel an external operation by calling
+ * {@link Cancellable#cancel()} if cancelled itself.
+ *
+ * @param <T> the future result type of an asynchronous operation.
+ * @since 5.0
+ */
+public final class FutureWrapper<T> implements Future<T> {
+
+    private final Future<T> future;
+    private final Cancellable cancellable;
+
+    public FutureWrapper(final Future<T> future, final Cancellable cancellable) {
+        super();
+        this.future = Args.notNull(future, "Future");
+        this.cancellable = cancellable;
+    }
+
+    @Override
+    public boolean cancel(final boolean mayInterruptIfRunning) {
+        boolean cancelled;
+        try {
+            if (cancellable != null) {
+                cancellable.cancel();
+            }
+        } finally {
+            cancelled = future.cancel(mayInterruptIfRunning);
+        }
+        return cancelled;
+    }
+    @Override
+    public boolean isCancelled() {
+        return future.isCancelled();
+    }
+
+    @Override
+    public boolean isDone() {
+        return future.isDone();
+    }
+
+    @Override
+    public T get() throws InterruptedException, ExecutionException {
+        return future.get();
+    }
+
+    @Override
+    public T get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+        return future.get(timeout, unit);
+    }
+
+    @Override
+    public String toString() {
+        return future.toString();
+    }
+
+}

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureWrapper.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/concurrent/FutureWrapper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Copied: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/function/Callback.java (from r1772397, httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/pool/io/package-info.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/function/Callback.java?p2=httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/function/Callback.java&p1=httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/pool/io/package-info.java&r1=1772397&r2=1772441&rev=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/pool/io/package-info.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/function/Callback.java Sat Dec  3 09:47:13 2016
@@ -25,8 +25,15 @@
  *
  */
 
+package org.apache.hc.core5.function;
+
 /**
- * Client side connection pools APIs for synchronous, blocking
- * communication.
+ * Abstract callback.
+ *
+ * @since 5.0
  */
-package org.apache.hc.core5.pool.io;
+public interface Callback<T> {
+
+    void execute(T object);
+
+}

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/function/Callback.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/function/Callback.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/function/Callback.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Copied: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/function/Supplier.java (from r1772397, httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/Supplier.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/function/Supplier.java?p2=httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/function/Supplier.java&p1=httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/Supplier.java&r1=1772397&r2=1772441&rev=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/Supplier.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/function/Supplier.java Sat Dec  3 09:47:13 2016
@@ -25,7 +25,7 @@
  *
  */
 
-package org.apache.hc.core5.http;
+package org.apache.hc.core5.function;
 
 /**
  * Abstract object supplier.

Copied: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/ConnectionRequestTimeoutException.java (from r1772397, httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/Supplier.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/ConnectionRequestTimeoutException.java?p2=httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/ConnectionRequestTimeoutException.java&p1=httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/Supplier.java&r1=1772397&r2=1772441&rev=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/Supplier.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/ConnectionRequestTimeoutException.java Sat Dec  3 09:47:13 2016
@@ -27,13 +27,29 @@
 
 package org.apache.hc.core5.http;
 
+import java.io.InterruptedIOException;
+
 /**
- * Abstract object supplier.
+ * Signals timeout requesting connection.
  *
  * @since 5.0
  */
-public interface Supplier<T> {
+public class ConnectionRequestTimeoutException extends InterruptedIOException {
+
+    /**
+     * Creates a {@link ConnectionRequestTimeoutException} without details.
+     */
+    public ConnectionRequestTimeoutException() {
+        super();
+    }
 
-    T get();
+    /**
+     * Creates a {@link ConnectionRequestTimeoutException} with a detail message.
+     *
+     * @param message the exception detail message, or {@code null}
+     */
+    public ConnectionRequestTimeoutException(final String message) {
+        super(message);
+    }
 
 }

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/ConnectionRequestTimeoutException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/ConnectionRequestTimeoutException.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/ConnectionRequestTimeoutException.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/ExceptionListener.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/ExceptionListener.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/ExceptionListener.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/ExceptionListener.java Sat Dec  3 09:47:13 2016
@@ -26,9 +26,13 @@
  */
 package org.apache.hc.core5.http;
 
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+
 /**
  * @since 4.4
  */
+@Contract(threading = ThreadingBehavior.STATELESS)
 public interface ExceptionListener {
 
     ExceptionListener NO_OP = new ExceptionListener() {

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/HttpEntity.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/HttpEntity.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/HttpEntity.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/HttpEntity.java Sat Dec  3 09:47:13 2016
@@ -33,6 +33,8 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.List;
 
+import org.apache.hc.core5.function.Supplier;
+
 /**
  * An entity that can be sent or received with an HTTP message.
  * <p>

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/config/SocketConfig.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/config/SocketConfig.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/config/SocketConfig.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/config/SocketConfig.java Sat Dec  3 09:47:13 2016
@@ -41,6 +41,7 @@ public class SocketConfig {
 
     public static final SocketConfig DEFAULT = new Builder().build();
 
+    private final int connectTimeout;
     private final int soTimeout;
     private final boolean soReuseAddress;
     private final int soLinger;
@@ -51,6 +52,7 @@ public class SocketConfig {
     private final int backlogSize;
 
     SocketConfig(
+            final int connectTimeout,
             final int soTimeout,
             final boolean soReuseAddress,
             final int soLinger,
@@ -60,6 +62,7 @@ public class SocketConfig {
             final int rcvBufSize,
             final int backlogSize) {
         super();
+        this.connectTimeout = connectTimeout;
         this.soTimeout = soTimeout;
         this.soReuseAddress = soReuseAddress;
         this.soLinger = soLinger;
@@ -71,12 +74,26 @@ public class SocketConfig {
     }
 
     /**
-     * Determines the default socket timeout value for non-blocking I/O operations.
+     * Determines the default connect timeout value for blocking I/O operations.
      * <p>
      * Default: {@code 0} (no timeout)
      * </p>
      *
-     * @return the default socket timeout value for non-blocking I/O operations.
+     * @return the default connect timeout value for blocking I/O operations.
+     *
+     * @since 5.0
+     */
+    public int getConnectTimeout() {
+        return connectTimeout;
+    }
+
+    /**
+     * Determines the default socket timeout value for blocking I/O operations.
+     * <p>
+     * Default: {@code 0} (no timeout)
+     * </p>
+     *
+     * @return the default socket timeout value for blocking I/O operations.
      * @see java.net.SocketOptions#SO_TIMEOUT
      */
     public int getSoTimeout() {
@@ -185,7 +202,8 @@ public class SocketConfig {
     @Override
     public String toString() {
         final StringBuilder builder = new StringBuilder();
-        builder.append("[soTimeout=").append(this.soTimeout)
+        builder.append("[connectTimeout=").append(this.connectTimeout)
+                .append(", soTimeout=").append(this.soTimeout)
                 .append(", soReuseAddress=").append(this.soReuseAddress)
                 .append(", soLinger=").append(this.soLinger)
                 .append(", soKeepAlive=").append(this.soKeepAlive)
@@ -204,6 +222,7 @@ public class SocketConfig {
     public static SocketConfig.Builder copy(final SocketConfig config) {
         Args.notNull(config, "Socket config");
         return new Builder()
+            .setConnectTimeout(config.getConnectTimeout())
             .setSoTimeout(config.getSoTimeout())
             .setSoReuseAddress(config.isSoReuseAddress())
             .setSoLinger(config.getSoLinger())
@@ -216,6 +235,7 @@ public class SocketConfig {
 
     public static class Builder {
 
+        private int connectTimeout;
         private int soTimeout;
         private boolean soReuseAddress;
         private int soLinger;
@@ -230,6 +250,14 @@ public class SocketConfig {
             this.tcpNoDelay = true;
         }
 
+        /**
+         * @since 5.0
+         */
+        public Builder setConnectTimeout(final int connectTimeout) {
+            this.connectTimeout = connectTimeout;
+            return this;
+        }
+
         public Builder setSoTimeout(final int soTimeout) {
             this.soTimeout = soTimeout;
             return this;
@@ -280,8 +308,8 @@ public class SocketConfig {
         }
 
         public SocketConfig build() {
-            return new SocketConfig(soTimeout, soReuseAddress, soLinger, soKeepAlive, tcpNoDelay,
-                    sndBufSize, rcvBufSize, backlogSize);
+            return new SocketConfig(connectTimeout, soTimeout, soReuseAddress, soLinger,
+                    soKeepAlive, tcpNoDelay, sndBufSize, rcvBufSize, backlogSize);
         }
 
     }

Copied: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/ConnectionListener.java (from r1772397, httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ConnectionListener.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/ConnectionListener.java?p2=httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/ConnectionListener.java&p1=httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ConnectionListener.java&r1=1772397&r2=1772441&rev=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ConnectionListener.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/ConnectionListener.java Sat Dec  3 09:47:13 2016
@@ -24,8 +24,10 @@
  * <http://www.apache.org/>.
  *
  */
-package org.apache.hc.core5.http.impl.nio;
+package org.apache.hc.core5.http.impl;
 
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.HttpConnection;
 
 /**
@@ -33,6 +35,7 @@ import org.apache.hc.core5.http.HttpConn
  *
  * @since 5.0
  */
+@Contract(threading = ThreadingBehavior.STATELESS)
 public interface ConnectionListener {
 
     void onConnect(HttpConnection connection);

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/ConnectionListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/ConnectionListener.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/ConnectionListener.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Copied: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/Http1StreamListener.java (from r1772397, httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/Http1StreamListener.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/Http1StreamListener.java?p2=httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/Http1StreamListener.java&p1=httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/Http1StreamListener.java&r1=1772397&r2=1772441&rev=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/Http1StreamListener.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/Http1StreamListener.java Sat Dec  3 09:47:13 2016
@@ -24,8 +24,10 @@
  * <http://www.apache.org/>.
  *
  */
-package org.apache.hc.core5.http.impl.nio;
+package org.apache.hc.core5.http.impl;
 
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.HttpConnection;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
@@ -35,6 +37,7 @@ import org.apache.hc.core5.http.HttpResp
  *
  * @since 5.0
  */
+@Contract(threading = ThreadingBehavior.STATELESS)
 public interface Http1StreamListener {
 
     void onRequestHead(HttpConnection connection, HttpRequest request);

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/Http1StreamListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/Http1StreamListener.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/Http1StreamListener.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/PoolEntryHolder.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/PoolEntryHolder.java?rev=1772441&view=auto
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/PoolEntryHolder.java (added)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/PoolEntryHolder.java Sat Dec  3 09:47:13 2016
@@ -0,0 +1,85 @@
+/*
+ * ====================================================================
+ * 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.core5.http.impl;
+
+import java.io.Closeable;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.hc.core5.function.Callback;
+import org.apache.hc.core5.pool.ConnPool;
+import org.apache.hc.core5.pool.PoolEntry;
+
+/**
+ * @since 5.0
+ */
+public final class PoolEntryHolder<T, C extends Closeable> {
+
+    private final ConnPool<T, C> connPool;
+    private final Callback<C> shutdownCallback;
+    private final AtomicBoolean reusable;
+    private final AtomicReference<PoolEntry<T, C>> poolEntryRef;
+
+    public PoolEntryHolder(
+            final ConnPool<T, C> connPool,
+            final PoolEntry<T, C> poolEntry,
+            final Callback<C> shutdownCallback) {
+        this.connPool = connPool;
+        this.poolEntryRef = new AtomicReference<>(poolEntry);
+        this.shutdownCallback = shutdownCallback;
+        this.reusable = new AtomicBoolean(false);
+    }
+
+    public C getConnection() {
+        final PoolEntry<T, C> poolEntry = poolEntryRef.get();
+        return poolEntry != null ? poolEntry.getConnection() : null;
+    }
+
+    public void markReusable() {
+        reusable.set(true);
+    }
+
+    public void releaseConnection() {
+        final PoolEntry<T, C> poolEntry = poolEntryRef.getAndSet(null);
+        if (poolEntry != null) {
+            connPool.release(poolEntry, reusable.get());
+        }
+    }
+
+    public void abortConnection() {
+        final PoolEntry<T, C> poolEntry = poolEntryRef.getAndSet(null);
+        if (poolEntry != null) {
+            poolEntry.discardConnection(shutdownCallback);
+            connPool.release(poolEntry, false);
+        }
+    }
+
+    public boolean isReleased() {
+        return poolEntryRef.get() == null;
+    }
+
+}

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/PoolEntryHolder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/PoolEntryHolder.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/PoolEntryHolder.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/BHttpConnectionBase.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/BHttpConnectionBase.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/BHttpConnectionBase.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/BHttpConnectionBase.java Sat Dec  3 09:47:13 2016
@@ -47,11 +47,10 @@ import org.apache.hc.core5.http.HttpEnti
 import org.apache.hc.core5.http.HttpHeaders;
 import org.apache.hc.core5.http.HttpMessage;
 import org.apache.hc.core5.http.ProtocolVersion;
-import org.apache.hc.core5.http.Supplier;
+import org.apache.hc.core5.function.Supplier;
 import org.apache.hc.core5.http.config.H1Config;
 import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
 import org.apache.hc.core5.http.impl.BasicHttpTransportMetrics;
-import org.apache.hc.core5.http.impl.IncomingHttpEntity;
 import org.apache.hc.core5.http.io.BHttpConnection;
 import org.apache.hc.core5.http.io.SessionInputBuffer;
 import org.apache.hc.core5.http.io.SessionOutputBuffer;
@@ -128,7 +127,7 @@ class BHttpConnectionBase implements BHt
         return this.version;
     }
 
-    SocketHolder getSocketHolder() {
+    protected SocketHolder getSocketHolder() {
         return this.socketHolderRef.get();
     }
 

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/ChunkedOutputStream.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/ChunkedOutputStream.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/ChunkedOutputStream.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/ChunkedOutputStream.java Sat Dec  3 09:47:13 2016
@@ -36,7 +36,7 @@ import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.StreamClosedException;
 import org.apache.hc.core5.http.io.SessionOutputBuffer;
 import org.apache.hc.core5.http.message.BasicLineFormatter;
-import org.apache.hc.core5.http.Supplier;
+import org.apache.hc.core5.function.Supplier;
 import org.apache.hc.core5.util.Args;
 import org.apache.hc.core5.util.CharArrayBuffer;
 

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/HttpRequestExecutor.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/HttpRequestExecutor.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/HttpRequestExecutor.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/HttpRequestExecutor.java Sat Dec  3 09:47:13 2016
@@ -33,6 +33,7 @@ import org.apache.hc.core5.annotation.Co
 import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.ConnectionReuseStrategy;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpEntity;
 import org.apache.hc.core5.http.HttpException;
@@ -40,6 +41,8 @@ import org.apache.hc.core5.http.HttpHead
 import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
 import org.apache.hc.core5.http.io.HttpClientConnection;
 import org.apache.hc.core5.http.protocol.HttpContext;
 import org.apache.hc.core5.http.protocol.HttpCoreContext;
@@ -65,19 +68,30 @@ public class HttpRequestExecutor {
     public static final int DEFAULT_WAIT_FOR_CONTINUE = 3000;
 
     private final int waitForContinue;
+    private final ConnectionReuseStrategy connReuseStrategy;
+    private final Http1StreamListener streamListener;
 
     /**
      * Creates new instance of HttpRequestExecutor.
      *
      * @since 4.3
      */
-    public HttpRequestExecutor(final int waitForContinue) {
+    public HttpRequestExecutor(
+            final int waitForContinue,
+            final ConnectionReuseStrategy connReuseStrategy,
+            final Http1StreamListener streamListener) {
         super();
         this.waitForContinue = Args.positive(waitForContinue, "Wait for continue time");
+        this.connReuseStrategy = connReuseStrategy != null ? connReuseStrategy : DefaultConnectionReuseStrategy.INSTANCE;
+        this.streamListener = streamListener;
+    }
+
+    public HttpRequestExecutor(final ConnectionReuseStrategy connReuseStrategy) {
+        this(DEFAULT_WAIT_FOR_CONTINUE, connReuseStrategy, null);
     }
 
     public HttpRequestExecutor() {
-        this(DEFAULT_WAIT_FOR_CONTINUE);
+        this(DEFAULT_WAIT_FOR_CONTINUE, null, null);
     }
 
     /**
@@ -128,6 +142,9 @@ public class HttpRequestExecutor {
             context.setAttribute(HttpCoreContext.HTTP_CONNECTION, conn);
 
             conn.sendRequestHeader(request);
+            if (streamListener != null) {
+                streamListener.onRequestHead(conn, request);
+            }
             final HttpEntity entity = request.getEntity();
             if (entity != null) {
                 final Header expect = request.getFirstHeader(HttpHeaders.EXPECT);
@@ -138,6 +155,9 @@ public class HttpRequestExecutor {
                     // Don't wait for a 100-continue response forever. On timeout, send the entity.
                     if (conn.isDataAvailable(this.waitForContinue)) {
                         response = conn.receiveResponseHeader();
+                        if (streamListener != null) {
+                            streamListener.onResponseHead(conn, response);
+                        }
                         final int status = response.getCode();
                         if (status < HttpStatus.SC_SUCCESS) {
                             if (status != HttpStatus.SC_CONTINUE) {
@@ -163,6 +183,9 @@ public class HttpRequestExecutor {
 
             while (response == null || response.getCode() < HttpStatus.SC_OK) {
                 response = conn.receiveResponseHeader();
+                if (streamListener != null) {
+                    streamListener.onResponseHead(conn, response);
+                }
                 if (canResponseHaveBody(request, response)) {
                     conn.receiveResponseEntity(response);
                 }
@@ -237,4 +260,30 @@ public class HttpRequestExecutor {
         processor.process(response, response.getEntity(), context);
     }
 
-} // class HttpRequestExecutor
+    /**
+     * Determines whether the connection can be kept alive and is safe to be re-used for subsequent message exchanges.
+     *
+     * @param request current request object.
+     * @param response  current response object.
+     * @param connection actual connection.
+     * @param context current context.
+     * @return {@code true} is the connection can be kept-alive and re-used.
+     * @throws IOException in case of an I/O error.
+     */
+    public boolean keepAlive(
+            final ClassicHttpRequest request,
+            final ClassicHttpResponse response,
+            final HttpClientConnection connection,
+            final HttpContext context) throws IOException {
+        Args.notNull(connection, "HTTP connection");
+        Args.notNull(request, "HTTP request");
+        Args.notNull(response, "HTTP response");
+        Args.notNull(context, "HTTP context");
+        final boolean keepAlive = connReuseStrategy.keepAlive(request, response, context);
+        if (streamListener != null) {
+            streamListener.onExchangeComplete(connection, keepAlive);
+        }
+        return keepAlive;
+    }
+
+}

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/HttpService.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/HttpService.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/HttpService.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/HttpService.java Sat Dec  3 09:47:13 2016
@@ -35,6 +35,7 @@ import org.apache.hc.core5.annotation.Th
 import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.ConnectionReuseStrategy;
+import org.apache.hc.core5.http.ContentType;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpEntity;
 import org.apache.hc.core5.http.HttpException;
@@ -47,11 +48,11 @@ import org.apache.hc.core5.http.Protocol
 import org.apache.hc.core5.http.ProtocolVersion;
 import org.apache.hc.core5.http.UnsupportedHttpVersionException;
 import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
 import org.apache.hc.core5.http.io.HttpExpectationVerifier;
 import org.apache.hc.core5.http.io.HttpRequestHandler;
 import org.apache.hc.core5.http.io.HttpRequestHandlerMapper;
 import org.apache.hc.core5.http.io.HttpServerConnection;
-import org.apache.hc.core5.http.ContentType;
 import org.apache.hc.core5.http.io.entity.StringEntity;
 import org.apache.hc.core5.http.protocol.HttpContext;
 import org.apache.hc.core5.http.protocol.HttpCoreContext;
@@ -82,15 +83,16 @@ public class HttpService {
 
     private final HttpProcessor processor;
     private final HttpRequestHandlerMapper handlerMapper;
-    private final ConnectionReuseStrategy connStrategy;
+    private final ConnectionReuseStrategy connReuseStrategy;
     private final HttpResponseFactory<ClassicHttpResponse> responseFactory;
     private final HttpExpectationVerifier expectationVerifier;
+    private final Http1StreamListener streamListener;
 
     /**
      * Create a new HTTP service.
      *
      * @param processor the processor to use on requests and responses
-     * @param connStrategy the connection reuse strategy. If {@code null}
+     * @param connReuseStrategy the connection reuse strategy. If {@code null}
      *   {@link DefaultConnectionReuseStrategy#INSTANCE} will be used.
      * @param responseFactory  the response factory. If {@code null}
      *   {@link DefaultClassicHttpResponseFactory#INSTANCE} will be used.
@@ -101,25 +103,27 @@ public class HttpService {
      */
     public HttpService(
             final HttpProcessor processor,
-            final ConnectionReuseStrategy connStrategy,
+            final ConnectionReuseStrategy connReuseStrategy,
             final HttpResponseFactory<ClassicHttpResponse> responseFactory,
             final HttpRequestHandlerMapper handlerMapper,
-            final HttpExpectationVerifier expectationVerifier) {
+            final HttpExpectationVerifier expectationVerifier,
+            final Http1StreamListener streamListener) {
         super();
         this.processor =  Args.notNull(processor, "HTTP processor");
-        this.connStrategy = connStrategy != null ? connStrategy :
+        this.connReuseStrategy = connReuseStrategy != null ? connReuseStrategy :
             DefaultConnectionReuseStrategy.INSTANCE;
         this.responseFactory = responseFactory != null ? responseFactory :
             DefaultClassicHttpResponseFactory.INSTANCE;
         this.handlerMapper = handlerMapper;
         this.expectationVerifier = expectationVerifier;
+        this.streamListener = streamListener;
     }
 
     /**
      * Create a new HTTP service.
      *
      * @param processor the processor to use on requests and responses
-     * @param connStrategy the connection reuse strategy. If {@code null}
+     * @param connReuseStrategy the connection reuse strategy. If {@code null}
      *   {@link DefaultConnectionReuseStrategy#INSTANCE} will be used.
      * @param responseFactory  the response factory. If {@code null}
      *   {@link DefaultClassicHttpResponseFactory#INSTANCE} will be used.
@@ -129,10 +133,10 @@ public class HttpService {
      */
     public HttpService(
             final HttpProcessor processor,
-            final ConnectionReuseStrategy connStrategy,
+            final ConnectionReuseStrategy connReuseStrategy,
             final HttpResponseFactory<ClassicHttpResponse> responseFactory,
             final HttpRequestHandlerMapper handlerMapper) {
-        this(processor, connStrategy, responseFactory, handlerMapper, null);
+        this(processor, connReuseStrategy, responseFactory, handlerMapper, null, null);
     }
 
     /**
@@ -145,7 +149,7 @@ public class HttpService {
      */
     public HttpService(
             final HttpProcessor processor, final HttpRequestHandlerMapper handlerMapper) {
-        this(processor, null, null, handlerMapper, null);
+        this(processor, null, null, handlerMapper);
     }
 
     /**
@@ -163,6 +167,9 @@ public class HttpService {
             final HttpContext context) throws IOException, HttpException {
 
         final ClassicHttpRequest request = conn.receiveRequestHeader();
+        if (streamListener != null) {
+            streamListener.onRequestHead(conn, request);
+        }
         ClassicHttpResponse response = null;
         try {
             try {
@@ -187,6 +194,9 @@ public class HttpService {
                         // Send 1xx response indicating the server expectations
                         // have been met
                         conn.sendResponseHeader(ack);
+                        if (streamListener != null) {
+                            streamListener.onResponseHead(conn, ack);
+                        }
                         conn.flush();
                     } else {
                         response = ack;
@@ -207,6 +217,9 @@ public class HttpService {
             this.processor.process(response, response.getEntity(), context);
 
             conn.sendResponseHeader(response);
+            if (streamListener != null) {
+                streamListener.onResponseHead(conn, response);
+            }
             if (canResponseHaveBody(request, response)) {
                 conn.sendResponseEntity(response);
             }
@@ -220,7 +233,11 @@ public class HttpService {
                     instream.close();
                 }
             }
-            if (!this.connStrategy.keepAlive(request, response, context)) {
+            final boolean keepAlive = this.connReuseStrategy.keepAlive(request, response, context);
+            if (streamListener != null) {
+                streamListener.onExchangeComplete(conn, keepAlive);
+            }
+            if (!keepAlive) {
                 conn.close();
             }
         } finally {

Copied: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/IncomingHttpEntity.java (from r1772397, httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/IncomingHttpEntity.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/IncomingHttpEntity.java?p2=httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/IncomingHttpEntity.java&p1=httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/IncomingHttpEntity.java&r1=1772397&r2=1772441&rev=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/IncomingHttpEntity.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/IncomingHttpEntity.java Sat Dec  3 09:47:13 2016
@@ -25,7 +25,7 @@
  *
  */
 
-package org.apache.hc.core5.http.impl;
+package org.apache.hc.core5.http.impl.io;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -34,16 +34,10 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.hc.core5.http.Header;
-import org.apache.hc.core5.http.impl.io.EmptyInputStream;
+import org.apache.hc.core5.function.Supplier;
 import org.apache.hc.core5.http.io.entity.AbstractImmutableHttpEntity;
-import org.apache.hc.core5.http.Supplier;
 
-/**
- * Represents entity received from an open connection.
- *
- * @since 5.0
- */
-public class IncomingHttpEntity extends AbstractImmutableHttpEntity {
+class IncomingHttpEntity extends AbstractImmutableHttpEntity {
 
     private final InputStream content;
     private final long len;
@@ -51,7 +45,7 @@ public class IncomingHttpEntity extends
     private final Header contentType;
     private final Header contentEncoding;
 
-    public IncomingHttpEntity(final InputStream content, final long len, final boolean chunked, final Header contentType, final Header contentEncoding) {
+    IncomingHttpEntity(final InputStream content, final long len, final boolean chunked, final Header contentType, final Header contentEncoding) {
         this.content = content;
         this.len = len;
         this.chunked = chunked;

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/IncomingHttpEntity.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/IncomingHttpEntity.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/IncomingHttpEntity.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/HttpRequester.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/HttpRequester.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/HttpRequester.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/HttpRequester.java Sat Dec  3 09:47:13 2016
@@ -28,36 +28,67 @@ package org.apache.hc.core5.http.impl.io
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
+import javax.net.ssl.SSLSocketFactory;
+
+import org.apache.hc.core5.function.Callback;
 import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.ConnectionClosedException;
-import org.apache.hc.core5.http.ConnectionReuseStrategy;
+import org.apache.hc.core5.http.ConnectionRequestTimeoutException;
 import org.apache.hc.core5.http.HttpEntity;
 import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.config.SocketConfig;
+import org.apache.hc.core5.http.impl.PoolEntryHolder;
+import org.apache.hc.core5.http.impl.io.DefaultBHttpClientConnectionFactory;
 import org.apache.hc.core5.http.impl.io.HttpRequestExecutor;
+import org.apache.hc.core5.http.io.EofSensorInputStream;
+import org.apache.hc.core5.http.io.EofSensorWatcher;
 import org.apache.hc.core5.http.io.HttpClientConnection;
+import org.apache.hc.core5.http.io.HttpConnectionFactory;
 import org.apache.hc.core5.http.io.ResponseHandler;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.io.entity.HttpEntityWrapper;
 import org.apache.hc.core5.http.protocol.HttpContext;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.pool.ConnPoolControl;
+import org.apache.hc.core5.pool.ControlledConnPool;
+import org.apache.hc.core5.pool.PoolEntry;
 import org.apache.hc.core5.util.Args;
 
 /**
  * @since 5.0
  */
-public class HttpRequester {
+public class HttpRequester implements AutoCloseable {
 
     private final HttpRequestExecutor requestExecutor;
     private final HttpProcessor httpProcessor;
-    private final ConnectionReuseStrategy connStrategy;
+    private final ControlledConnPool<HttpHost, HttpClientConnection> connPool;
+    private final HttpConnectionFactory<? extends HttpClientConnection> connectFactory;
+    private final SSLSocketFactory sslSocketFactory;
 
-    public HttpRequester(
+    HttpRequester(
             final HttpRequestExecutor requestExecutor,
             final HttpProcessor httpProcessor,
-            final ConnectionReuseStrategy connStrategy) {
-        this.requestExecutor = requestExecutor;
-        this.httpProcessor = httpProcessor;
-        this.connStrategy = connStrategy;
+            final ControlledConnPool<HttpHost, HttpClientConnection> connPool,
+            final HttpConnectionFactory<? extends HttpClientConnection> connectFactory,
+            final SSLSocketFactory sslSocketFactory) {
+        this.requestExecutor = Args.notNull(requestExecutor, "Request executor");
+        this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
+        this.connPool = Args.notNull(connPool, "Connection pool");
+        this.connectFactory = connectFactory != null ? connectFactory : DefaultBHttpClientConnectionFactory.INSTANCE;
+        this.sslSocketFactory = sslSocketFactory;
     }
 
     public ClassicHttpResponse execute(
@@ -81,23 +112,11 @@ public class HttpRequester {
             final ClassicHttpRequest request,
             final ClassicHttpResponse response,
             final HttpContext context) throws IOException {
-        Args.notNull(connection, "HTTP connection");
-        Args.notNull(request, "HTTP request");
-        Args.notNull(response, "HTTP response");
-        Args.notNull(context, "HTTP context");
-        final HttpEntity entity = response.getEntity();
-        if (entity != null && entity.isStreaming()) {
-            final InputStream instream = entity.getContent();
-            if (instream != null) {
-                instream.close();
-            }
-        }
-        if (connStrategy.keepAlive(request, response, context)) {
-            return true;
-        } else {
+        final boolean keepAlive = requestExecutor.keepAlive(request, response, connection, context);
+        if (!keepAlive) {
             connection.close();
-            return false;
         }
+        return keepAlive;
     }
 
     public <T> T execute(
@@ -106,9 +125,203 @@ public class HttpRequester {
             final HttpContext context,
             final ResponseHandler<T> responseHandler) throws HttpException, IOException {
         final ClassicHttpResponse response = execute(connection, request, context);
-        final T result = responseHandler.handleResponse(response);
-        keepAlive(connection, request, response, context);
-        return result;
+        try {
+            final T result = responseHandler.handleResponse(response);
+            EntityUtils.consume(response.getEntity());
+            final boolean keepAlive = requestExecutor.keepAlive(request, response, connection, context);
+            if (!keepAlive) {
+                connection.close();
+            }
+            return result;
+        } catch (HttpException | IOException | RuntimeException ex) {
+            connection.shutdown();
+            throw ex;
+        } finally {
+            response.close();
+        }
+    }
+
+    private Socket createSocket(final HttpHost host) throws IOException {
+        final String scheme = host.getSchemeName();
+        if ("https".equalsIgnoreCase(scheme)) {
+            return (sslSocketFactory != null ? sslSocketFactory : SSLSocketFactory.getDefault()).createSocket();
+        } else {
+            return new Socket();
+        }
+    }
+
+    private SocketAddress toEndpoint(final HttpHost host) {
+        int port = host.getPort();
+        if (port < 0) {
+            final String scheme = host.getSchemeName();
+            if ("http".equalsIgnoreCase(scheme)) {
+                port = 80;
+            } else if ("https".equalsIgnoreCase(scheme)) {
+                port = 443;
+            }
+        }
+        final InetAddress address = host.getAddress();
+        if (address != null) {
+            return new InetSocketAddress(address, port);
+        } else {
+            return new InetSocketAddress(host.getHostName(), port);
+        }
+    }
+
+    public ClassicHttpResponse execute(
+            final HttpHost targetHost,
+            final ClassicHttpRequest request,
+            final SocketConfig socketConfig,
+            final HttpContext context) throws HttpException, IOException {
+        Args.notNull(targetHost, "HTTP host");
+        Args.notNull(request, "HTTP request");
+        Args.notNull(context, "HTTP context");
+        final Future<PoolEntry<HttpHost, HttpClientConnection>> leaseFuture = connPool.lease(targetHost, null, null);
+        final PoolEntry<HttpHost, HttpClientConnection> poolEntry;
+        try {
+            poolEntry = leaseFuture.get(socketConfig.getConnectTimeout(), TimeUnit.MILLISECONDS);
+        } catch (InterruptedException ex) {
+            throw new InterruptedIOException(ex.getMessage());
+        } catch (ExecutionException ex) {
+            throw new HttpException("Unexpected failure leasing connection", ex);
+        } catch (TimeoutException ex) {
+            throw new ConnectionRequestTimeoutException("Connection request timeout");
+        }
+        final PoolEntryHolder<HttpHost, HttpClientConnection> connectionHolder = new PoolEntryHolder<>(
+                connPool,
+                poolEntry,
+                new Callback<HttpClientConnection>() {
+
+                    @Override
+                    public void execute(final HttpClientConnection conn) {
+                        try {
+                            conn.shutdown();
+                        } catch (IOException ignore) {
+                        }
+                    }
+                });
+        try {
+            HttpClientConnection connection = poolEntry.getConnection();
+            if (connection == null) {
+                final Socket socket = createSocket(targetHost);
+                connection = connectFactory.createConnection(socket);
+                poolEntry.assignConnection(connection);
+                socket.connect(toEndpoint(targetHost), socketConfig.getConnectTimeout());
+            }
+            final ClassicHttpResponse response = execute(connection, request, context);
+            final HttpEntity entity = response.getEntity();
+            if (entity != null) {
+                response.setEntity(new HttpEntityWrapper(entity) {
+
+                    private void releaseConnection() throws IOException {
+                        if (connectionHolder.isReleased()) {
+                            return;
+                        }
+                        try {
+                            final HttpClientConnection localConn = poolEntry.getConnection();
+                            if (localConn != null) {
+                                if (requestExecutor.keepAlive(request, response, localConn, context)) {
+                                    if (super.isStreaming()) {
+                                        final InputStream content = super.getContent();
+                                        if (content != null) {
+                                            content.close();
+                                        }
+                                    }
+                                    connectionHolder.markReusable();
+                                }
+                            }
+                        } finally {
+                            connectionHolder.releaseConnection();
+                        }
+                    }
+
+                    private void abortConnection() {
+                        connectionHolder.releaseConnection();
+                    }
+
+                    @Override
+                    public boolean isStreaming() {
+                        return true;
+                    }
+
+                    @Override
+                    public InputStream getContent() throws IOException {
+                        return new EofSensorInputStream(super.getContent(), new EofSensorWatcher() {
+
+                            @Override
+                            public boolean eofDetected(final InputStream wrapped) throws IOException {
+                                releaseConnection();
+                                return false;
+                            }
+
+                            @Override
+                            public boolean streamClosed(final InputStream wrapped) throws IOException {
+                                releaseConnection();
+                                return false;
+                            }
+
+                            @Override
+                            public boolean streamAbort(final InputStream wrapped) throws IOException {
+                                abortConnection();
+                                return false;
+                            }
+
+                        });
+                    }
+
+                    @Override
+                    public void writeTo(final OutputStream outstream) throws IOException {
+                        try {
+                            if (outstream != null) {
+                                super.writeTo(outstream);
+                            }
+                            close();
+                        } catch (final IOException | RuntimeException ex) {
+                            abortConnection();
+                        }
+                    }
+
+                    @Override
+                    public void close() throws IOException {
+                        releaseConnection();
+                    }
+
+                });
+            }
+            return response;
+        } catch (HttpException | IOException | RuntimeException ex) {
+            connectionHolder.abortConnection();
+            throw ex;
+        }
+    }
+
+    public <T> T  execute(
+            final HttpHost targetHost,
+            final ClassicHttpRequest request,
+            final SocketConfig socketConfig,
+            final HttpContext context,
+            final ResponseHandler<T> responseHandler) throws HttpException, IOException {
+        final ClassicHttpResponse response = execute(targetHost, request, socketConfig, context);
+        try {
+            final T result = responseHandler.handleResponse(response);
+            EntityUtils.consume(response.getEntity());
+            return result;
+        } finally {
+            response.close();
+        }
+    }
+
+    public ConnPoolControl<HttpHost> getConnPoolControl() {
+        return connPool;
+    }
+
+    public void shutdown() {
+        connPool.shutdown();
+    }
+
+    @Override
+    public void close() throws Exception {
+        connPool.close();
     }
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/HttpServer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/HttpServer.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/HttpServer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/HttpServer.java Sat Dec  3 09:47:13 2016
@@ -48,7 +48,7 @@ import org.apache.hc.core5.http.io.HttpS
 /**
  * @since 4.4
  */
-public class HttpServer {
+public class HttpServer implements AutoCloseable {
 
     enum Status { READY, ACTIVE, STOPPING }
 
@@ -175,4 +175,9 @@ public class HttpServer {
         }
     }
 
+    @Override
+    public void close() throws Exception {
+        shutdown(5, TimeUnit.SECONDS);
+    }
+
 }

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/RequesterBootstrap.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/RequesterBootstrap.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/RequesterBootstrap.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/RequesterBootstrap.java Sat Dec  3 09:47:13 2016
@@ -26,20 +26,38 @@
  */
 package org.apache.hc.core5.http.impl.io.bootstrap;
 
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SSLSocketFactory;
+
 import org.apache.hc.core5.http.ConnectionReuseStrategy;
+import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
 import org.apache.hc.core5.http.impl.HttpProcessors;
+import org.apache.hc.core5.http.impl.io.DefaultBHttpClientConnectionFactory;
 import org.apache.hc.core5.http.impl.io.HttpRequestExecutor;
+import org.apache.hc.core5.http.io.HttpClientConnection;
+import org.apache.hc.core5.http.io.HttpConnectionFactory;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.pool.ConnPoolListener;
+import org.apache.hc.core5.pool.StrictConnPool;
 
 /**
  * @since 5.0
  */
 public class RequesterBootstrap {
 
-    private HttpRequestExecutor requestExecutor;
     private HttpProcessor httpProcessor;
-    private ConnectionReuseStrategy connStrategy;
+    private ConnectionReuseStrategy connReuseStrategy;
+    private HttpConnectionFactory<? extends HttpClientConnection> connectFactory;
+    private SSLSocketFactory sslSocketFactory;
+    private int defaultMaxPerRoute;
+    private int maxTotal;
+    private long timeToLive;
+    private TimeUnit timeUnit;
+    private Http1StreamListener streamListener;
+    private ConnPoolListener<HttpHost> connPoolListener;
 
     private RequesterBootstrap() {
     }
@@ -60,23 +78,62 @@ public class RequesterBootstrap {
      * Assigns {@link ConnectionReuseStrategy} instance.
      */
     public final RequesterBootstrap setConnectionReuseStrategy(final ConnectionReuseStrategy connStrategy) {
-        this.connStrategy = connStrategy;
+        this.connReuseStrategy = connStrategy;
         return this;
     }
 
-    /**
-     * Assigns {@link HttpRequestExecutor} instance.
-     */
-    public final RequesterBootstrap setHttpRequestExecutor(final HttpRequestExecutor requestExecutor) {
-        this.requestExecutor = requestExecutor;
+    public final RequesterBootstrap setConnectFactory(final HttpConnectionFactory<? extends HttpClientConnection> connectFactory) {
+        this.connectFactory = connectFactory;
+        return this;
+    }
+
+    public final RequesterBootstrap setSslSocketFactory(final SSLSocketFactory sslSocketFactory) {
+        this.sslSocketFactory = sslSocketFactory;
+        return this;
+    }
+
+    public final RequesterBootstrap setDefaultMaxPerRoute(final int defaultMaxPerRoute) {
+        this.defaultMaxPerRoute = defaultMaxPerRoute;
+        return this;
+    }
+
+    public final RequesterBootstrap setMaxTotal(final int maxTotal) {
+        this.maxTotal = maxTotal;
+        return this;
+    }
+
+    public final RequesterBootstrap setTimeToLive(final long timeToLive, final TimeUnit timeUnit) {
+        this.timeToLive = timeToLive;
+        this.timeUnit = timeUnit;
+        return this;
+    }
+
+    public final RequesterBootstrap setStreamListener(final Http1StreamListener streamListener) {
+        this.streamListener = streamListener;
+        return this;
+    }
+
+    public final RequesterBootstrap setConnPoolListener(final ConnPoolListener<HttpHost> connPoolListener) {
+        this.connPoolListener = connPoolListener;
         return this;
     }
 
     public HttpRequester create() {
+        final HttpRequestExecutor requestExecutor = new HttpRequestExecutor(
+                HttpRequestExecutor.DEFAULT_WAIT_FOR_CONTINUE,
+                connReuseStrategy != null ? connReuseStrategy : DefaultConnectionReuseStrategy.INSTANCE,
+                streamListener);
+        final StrictConnPool<HttpHost, HttpClientConnection> connPool = new StrictConnPool<>(
+                defaultMaxPerRoute > 0 ? defaultMaxPerRoute : 20,
+                maxTotal > 0 ? maxTotal : 50,
+                timeToLive, timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS,
+                connPoolListener);
         return new HttpRequester(
-                requestExecutor != null ? requestExecutor : new HttpRequestExecutor(),
+                requestExecutor,
                 httpProcessor != null ? httpProcessor : HttpProcessors.client(),
-                connStrategy != null ? connStrategy : DefaultConnectionReuseStrategy.INSTANCE);
+                connPool,
+                connectFactory != null ? connectFactory : DefaultBHttpClientConnectionFactory.INSTANCE,
+                sslSocketFactory);
     }
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/ServerBootstrap.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/ServerBootstrap.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/ServerBootstrap.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/ServerBootstrap.java Sat Dec  3 09:47:13 2016
@@ -37,10 +37,11 @@ import org.apache.hc.core5.http.ClassicH
 import org.apache.hc.core5.http.ConnectionReuseStrategy;
 import org.apache.hc.core5.http.ExceptionListener;
 import org.apache.hc.core5.http.HttpResponseFactory;
-import org.apache.hc.core5.http.impl.HttpProcessors;
 import org.apache.hc.core5.http.config.ConnectionConfig;
 import org.apache.hc.core5.http.config.SocketConfig;
 import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
+import org.apache.hc.core5.http.impl.HttpProcessors;
 import org.apache.hc.core5.http.impl.io.DefaultBHttpServerConnection;
 import org.apache.hc.core5.http.impl.io.DefaultBHttpServerConnectionFactory;
 import org.apache.hc.core5.http.impl.io.DefaultClassicHttpResponseFactory;
@@ -72,6 +73,7 @@ public class ServerBootstrap {
     private SSLServerSetupHandler sslSetupHandler;
     private HttpConnectionFactory<? extends DefaultBHttpServerConnection> connectionFactory;
     private ExceptionListener exceptionListener;
+    private Http1StreamListener streamListener;
 
     private ServerBootstrap() {
     }
@@ -220,6 +222,14 @@ public class ServerBootstrap {
         return this;
     }
 
+    /**
+     * Assigns {@link ExceptionListener} instance.
+     */
+    public final ServerBootstrap setStreamListener(final Http1StreamListener streamListener) {
+        this.streamListener = streamListener;
+        return this;
+    }
+
     public HttpServer create() {
 
         HttpProcessor httpProcessorCopy = this.httpProcessor;
@@ -250,7 +260,7 @@ public class ServerBootstrap {
 
         final HttpService httpService = new HttpService(
                 httpProcessorCopy, connStrategyCopy, responseFactoryCopy, handlerMapperCopy,
-                this.expectationVerifier);
+                this.expectationVerifier, this.streamListener);
 
         ServerSocketFactory serverSocketFactoryCopy = this.serverSocketFactory;
         if (serverSocketFactoryCopy == null) {

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java Sat Dec  3 09:47:13 2016
@@ -55,6 +55,7 @@ import org.apache.hc.core5.http.config.H
 import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
 import org.apache.hc.core5.http.impl.BasicHttpTransportMetrics;
 import org.apache.hc.core5.http.impl.ConnSupport;
+import org.apache.hc.core5.http.impl.ConnectionListener;
 import org.apache.hc.core5.http.nio.ContentDecoder;
 import org.apache.hc.core5.http.nio.ContentEncoder;
 import org.apache.hc.core5.http.nio.NHttpMessageParser;

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandlerFactory.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandlerFactory.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandlerFactory.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandlerFactory.java Sat Dec  3 09:47:13 2016
@@ -35,8 +35,10 @@ import org.apache.hc.core5.http.HttpRequ
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.config.ConnectionConfig;
 import org.apache.hc.core5.http.config.H1Config;
+import org.apache.hc.core5.http.impl.ConnectionListener;
 import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
 import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
 import org.apache.hc.core5.http.nio.NHttpMessageParserFactory;
 import org.apache.hc.core5.http.nio.NHttpMessageWriterFactory;
 import org.apache.hc.core5.http.protocol.HttpProcessor;

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexer.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamDuplexer.java Sat Dec  3 09:47:13 2016
@@ -48,8 +48,10 @@ import org.apache.hc.core5.http.config.C
 import org.apache.hc.core5.http.config.H1Config;
 import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
 import org.apache.hc.core5.http.impl.BasicHttpTransportMetrics;
+import org.apache.hc.core5.http.impl.ConnectionListener;
 import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
 import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
 import org.apache.hc.core5.http.nio.ContentDecoder;
 import org.apache.hc.core5.http.nio.ContentEncoder;
 import org.apache.hc.core5.http.nio.NHttpMessageParser;

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandlerFactory.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandlerFactory.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandlerFactory.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandlerFactory.java Sat Dec  3 09:47:13 2016
@@ -36,8 +36,10 @@ import org.apache.hc.core5.http.HttpRequ
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.config.ConnectionConfig;
 import org.apache.hc.core5.http.config.H1Config;
+import org.apache.hc.core5.http.impl.ConnectionListener;
 import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
 import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
 import org.apache.hc.core5.http.nio.HandlerFactory;
 import org.apache.hc.core5.http.nio.NHttpMessageParserFactory;

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexer.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamDuplexer.java Sat Dec  3 09:47:13 2016
@@ -46,8 +46,10 @@ import org.apache.hc.core5.http.config.C
 import org.apache.hc.core5.http.config.H1Config;
 import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
 import org.apache.hc.core5.http.impl.BasicHttpTransportMetrics;
+import org.apache.hc.core5.http.impl.ConnectionListener;
 import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
 import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
 import org.apache.hc.core5.http.nio.ContentDecoder;
 import org.apache.hc.core5.http.nio.ContentEncoder;

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/bootstrap/AsyncRequester.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/bootstrap/AsyncRequester.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/bootstrap/AsyncRequester.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/bootstrap/AsyncRequester.java Sat Dec  3 09:47:13 2016
@@ -32,13 +32,14 @@ import java.net.SocketAddress;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.hc.core5.function.Callback;
 import org.apache.hc.core5.http.ExceptionListener;
 import org.apache.hc.core5.net.NamedEndpoint;
 import org.apache.hc.core5.reactor.ConnectionInitiator;
 import org.apache.hc.core5.reactor.DefaultConnectingIOReactor;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
 import org.apache.hc.core5.reactor.IOReactorConfig;
-import org.apache.hc.core5.reactor.IOSessionCallback;
+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;
@@ -48,7 +49,7 @@ public class AsyncRequester extends IORe
     public AsyncRequester(
             final IOReactorConfig ioReactorConfig,
             final ExceptionListener exceptionListener,
-            final IOSessionCallback sessionShutdownCallback) {
+            final Callback<IOSession> sessionShutdownCallback) {
         super(ioReactorConfig,
                 exceptionListener,
                 new ThreadFactoryImpl("connector", true),
@@ -74,7 +75,7 @@ public class AsyncRequester extends IORe
             final NamedEndpoint remoteEndpoint,
             final long timeout,
             final TimeUnit timeUnit,
-            final SessionRequestCallback callback) throws InterruptedException {
+            final SessionRequestCallback callback) {
         Args.notNull(remoteEndpoint, "Remote endpoint");
         Args.notNull(timeUnit, "Time unit");
         final SessionRequest  sessionRequest = reactor().connect(remoteEndpoint, null, null, callback);

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/bootstrap/AsyncServer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/bootstrap/AsyncServer.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/bootstrap/AsyncServer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/bootstrap/AsyncServer.java Sat Dec  3 09:47:13 2016
@@ -32,11 +32,12 @@ import java.net.InetSocketAddress;
 import java.util.Set;
 import java.util.concurrent.ThreadFactory;
 
+import org.apache.hc.core5.function.Callback;
 import org.apache.hc.core5.http.ExceptionListener;
 import org.apache.hc.core5.reactor.DefaultListeningIOReactor;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
 import org.apache.hc.core5.reactor.IOReactorConfig;
-import org.apache.hc.core5.reactor.IOSessionCallback;
+import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.reactor.ListenerEndpoint;
 
 public class AsyncServer extends IOReactorExecutor<DefaultListeningIOReactor> {
@@ -44,7 +45,7 @@ public class AsyncServer extends IOReact
     public AsyncServer(
             final IOReactorConfig ioReactorConfig,
             final ExceptionListener exceptionListener,
-            final IOSessionCallback sessionShutdownCallback) {
+            final Callback<IOSession> sessionShutdownCallback) {
         super(ioReactorConfig,
                 exceptionListener,
                 new ThreadFactoryImpl("listener"),

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/bootstrap/AsyncServerExchangeHandlerRegistry.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/bootstrap/AsyncServerExchangeHandlerRegistry.java?rev=1772441&r1=1772440&r2=1772441&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/bootstrap/AsyncServerExchangeHandlerRegistry.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/bootstrap/AsyncServerExchangeHandlerRegistry.java Sat Dec  3 09:47:13 2016
@@ -34,7 +34,7 @@ import java.util.concurrent.ConcurrentMa
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpStatus;
-import org.apache.hc.core5.http.Supplier;
+import org.apache.hc.core5.function.Supplier;
 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
 import org.apache.hc.core5.http.nio.HandlerFactory;
 import org.apache.hc.core5.http.nio.support.ImmediateResponseExchangeHandler;