hc-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ol...@apache.org
Subject svn commit: r1421309 - in /httpcomponents/httpclient/trunk/httpclient/src: main/java/org/apache/http/impl/client/ main/java/org/apache/http/impl/conn/ test/java/org/apache/http/impl/conn/
Date Thu, 13 Dec 2012 14:22:30 GMT
Author: olegk
Date: Thu Dec 13 14:22:28 2012
New Revision: 1421309

URL: http://svn.apache.org/viewvc?rev=1421309&view=rev
Log:
Added methods to set SocketConfig and ConnectionConfig for PoolingHttpClientConnectionManager and HttpClientBuilder

Removed:
    httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/conn/HttpClientConnectionManagerBase.java
    httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/conn/TestHttpClientConnectionManagerBase.java
Modified:
    httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java
    httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java
    httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java
    httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/conn/TestPoolingHttpClientConnectionManager.java

Modified: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java?rev=1421309&r1=1421308&r2=1421309&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java (original)
+++ httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java Thu Dec 13 14:22:28 2012
@@ -60,8 +60,10 @@ import org.apache.http.client.protocol.R
 import org.apache.http.client.protocol.RequestExpectContinue;
 import org.apache.http.client.protocol.ResponseContentEncoding;
 import org.apache.http.client.protocol.ResponseProcessCookies;
+import org.apache.http.config.ConnectionConfig;
 import org.apache.http.config.Lookup;
 import org.apache.http.config.RegistryBuilder;
+import org.apache.http.config.SocketConfig;
 import org.apache.http.conn.ConnectionKeepAliveStrategy;
 import org.apache.http.conn.HttpClientConnectionManager;
 import org.apache.http.conn.SchemePortResolver;
@@ -125,7 +127,7 @@ import org.apache.http.util.VersionInfo;
  *  <li>http.nonProxyHosts</li>
  *  <li>http.keepAlive</li>
  *  <li>http.maxConnections</li>
- *  <li>http.user</li>
+ *  <li>http.agent</li>
  * </ul>
  * </p>
  *
@@ -164,7 +166,9 @@ public class HttpClientBuilder {
     private CredentialsProvider credentialsProvider;
     private String userAgent;
     private Collection<? extends Header> defaultHeaders;
-    private RequestConfig defaultConfig;
+    private SocketConfig defaultSocketConfig;
+    private ConnectionConfig defaultConnectionConfig;
+    private RequestConfig defaultRequestConfig;
 
     private boolean systemProperties;
     private boolean redirectHandlingDisabled;
@@ -379,8 +383,18 @@ public class HttpClientBuilder {
         return this;
     }
 
-    public final HttpClientBuilder setDefaultConfig(final RequestConfig defaultConfig) {
-        this.defaultConfig = defaultConfig;
+    public final HttpClientBuilder setDefaultSocketConfig(final SocketConfig config) {
+        this.defaultSocketConfig = config;
+        return this;
+    }
+
+    public final HttpClientBuilder setDefaultConnectionConfig(final ConnectionConfig config) {
+        this.defaultConnectionConfig = config;
+        return this;
+    }
+
+    public final HttpClientBuilder setDefaultRequestConfig(final RequestConfig config) {
+        this.defaultRequestConfig = config;
         return this;
     }
 
@@ -438,6 +452,12 @@ public class HttpClientBuilder {
                         .register("http", PlainSocketFactory.getSocketFactory())
                         .register("https", sslSocketFactory)
                         .build());
+            if (defaultSocketConfig != null) {
+                poolingmgr.setDefaultSocketConfig(defaultSocketConfig);
+            }
+            if (defaultConnectionConfig != null) {
+                poolingmgr.setDefaultConnectionConfig(defaultConnectionConfig);
+            }
             if (systemProperties) {
                 String s = System.getProperty("http.keepAlive");
                 if ("true".equalsIgnoreCase(s)) {
@@ -659,7 +679,7 @@ public class HttpClientBuilder {
                 authSchemeRegistry,
                 defaultCookieStore,
                 defaultCredentialsProvider,
-                defaultConfig != null ? defaultConfig : RequestConfig.DEFAULT);
+                defaultRequestConfig != null ? defaultRequestConfig : RequestConfig.DEFAULT);
     }
 
 }

Modified: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java?rev=1421309&r1=1421308&r2=1421309&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java (original)
+++ httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/conn/CPool.java Thu Dec 13 14:22:28 2012
@@ -26,7 +26,6 @@
  */
 package org.apache.http.impl.conn;
 
-import java.io.IOException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 
@@ -52,9 +51,10 @@ class CPool extends AbstractConnPool<Htt
     private final TimeUnit tunit;
 
     public CPool(
+            final ConnFactory<HttpRoute, SocketClientConnection> connFactory,
             final int defaultMaxPerRoute, final int maxTotal,
             final long timeToLive, final TimeUnit tunit) {
-        super(new InternalConnFactory(), defaultMaxPerRoute, maxTotal);
+        super(connFactory, defaultMaxPerRoute, maxTotal);
         this.timeToLive = timeToLive;
         this.tunit = tunit;
     }
@@ -65,12 +65,4 @@ class CPool extends AbstractConnPool<Htt
         return new CPoolEntry(this.log, id, route, conn, this.timeToLive, this.tunit);
     }
 
-    static class InternalConnFactory implements ConnFactory<HttpRoute, SocketClientConnection> {
-
-        public SocketClientConnection create(final HttpRoute route) throws IOException {
-            return new SocketClientConnectionImpl(8 * 1024);
-        }
-
-    }
-
 }

Modified: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java?rev=1421309&r1=1421308&r2=1421309&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java (original)
+++ httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java Thu Dec 13 14:22:28 2012
@@ -27,22 +27,40 @@
 package org.apache.http.impl.conn;
 
 import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.http.HttpClientConnection;
+import org.apache.http.HttpHost;
 import org.apache.http.annotation.ThreadSafe;
+import org.apache.http.config.ConnectionConfig;
+import org.apache.http.config.Lookup;
 import org.apache.http.config.Registry;
 import org.apache.http.config.RegistryBuilder;
+import org.apache.http.config.SocketConfig;
+import org.apache.http.conn.ConnectionPoolTimeoutException;
+import org.apache.http.conn.ConnectionRequest;
 import org.apache.http.conn.DnsResolver;
+import org.apache.http.conn.HttpClientConnectionManager;
+import org.apache.http.conn.HttpConnectionFactory;
 import org.apache.http.conn.SchemePortResolver;
+import org.apache.http.conn.SocketClientConnection;
 import org.apache.http.conn.routing.HttpRoute;
 import org.apache.http.conn.socket.ConnectionSocketFactory;
 import org.apache.http.conn.socket.PlainSocketFactory;
 import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.pool.ConnFactory;
 import org.apache.http.pool.ConnPoolControl;
 import org.apache.http.pool.PoolStats;
+import org.apache.http.protocol.HttpContext;
 
 /**
  * <tt>ClientConnectionPoolManager</tt> maintains a pool of
@@ -63,11 +81,13 @@ import org.apache.http.pool.PoolStats;
  * @since 4.3
  */
 @ThreadSafe
-public class PoolingHttpClientConnectionManager extends HttpClientConnectionManagerBase {
+public class PoolingHttpClientConnectionManager implements HttpClientConnectionManager {
 
     private final Log log = LogFactory.getLog(getClass());
 
+    private final ConfigData configData;
     private final CPool pool;
+    private final HttpClientConnectionOperator connectionOperator;
 
     private static Registry<ConnectionSocketFactory> getDefaultRegistry() {
         return RegistryBuilder.<ConnectionSocketFactory>create()
@@ -81,42 +101,51 @@ public class PoolingHttpClientConnection
     }
 
     public PoolingHttpClientConnectionManager(final long timeToLive, final TimeUnit tunit) {
-        this(getDefaultRegistry(), timeToLive, tunit);
+        this(getDefaultRegistry(), null, timeToLive, tunit);
     }
 
     public PoolingHttpClientConnectionManager(
             final Registry<ConnectionSocketFactory> socketFactoryRegistry) {
-        this(socketFactoryRegistry, -1, TimeUnit.MILLISECONDS);
+        this(socketFactoryRegistry, null, -1, TimeUnit.MILLISECONDS);
     }
 
     public PoolingHttpClientConnectionManager(
             final Registry<ConnectionSocketFactory> socketFactoryRegistry,
             final DnsResolver dnsResolver) {
-        this(socketFactoryRegistry, null, dnsResolver, -1, TimeUnit.MILLISECONDS);
+        this(socketFactoryRegistry, null, null, dnsResolver, -1, TimeUnit.MILLISECONDS);
     }
 
     public PoolingHttpClientConnectionManager(
             final Registry<ConnectionSocketFactory> socketFactoryRegistry,
+            final HttpConnectionFactory<SocketClientConnection> connFactory,
             final long timeToLive, final TimeUnit tunit) {
-        this(new CPool(2, 20, timeToLive, tunit), socketFactoryRegistry, null, null);
+        this(socketFactoryRegistry, connFactory, null, null, timeToLive, tunit);
     }
 
     public PoolingHttpClientConnectionManager(
             final Registry<ConnectionSocketFactory> socketFactoryRegistry,
+            final HttpConnectionFactory<SocketClientConnection> connFactory,
             final SchemePortResolver schemePortResolver,
             final DnsResolver dnsResolver,
             final long timeToLive, final TimeUnit tunit) {
-        this(new CPool(2, 20, timeToLive, tunit),
+        super();
+        this.configData = new ConfigData();
+        this.pool = new CPool(
+                new InternalConnectionFactory(this.configData, connFactory), 2, 20, timeToLive, tunit);
+        this.connectionOperator = new HttpClientConnectionOperator(
                 socketFactoryRegistry, schemePortResolver, dnsResolver);
     }
 
     PoolingHttpClientConnectionManager(
             final CPool pool,
-            final Registry<ConnectionSocketFactory> socketFactoryRegistry,
+            final Lookup<ConnectionSocketFactory> socketFactoryRegistry,
             final SchemePortResolver schemePortResolver,
             final DnsResolver dnsResolver) {
-        super(pool, socketFactoryRegistry, schemePortResolver, dnsResolver);
+        super();
+        this.configData = new ConfigData();
         this.pool = pool;
+        this.connectionOperator = new HttpClientConnectionOperator(
+                socketFactoryRegistry, schemePortResolver, dnsResolver);
     }
 
     @Override
@@ -160,39 +189,137 @@ public class PoolingHttpClientConnection
         return buf.toString();
     }
 
-    @Override
-    protected void onConnectionLeaseRequest(final HttpRoute route, final Object state) {
+    public ConnectionRequest requestConnection(
+            final HttpRoute route,
+            final Object state) {
+        if (route == null) {
+            throw new IllegalArgumentException("HTTP route may not be null");
+        }
         if (this.log.isDebugEnabled()) {
             this.log.debug("Connection request: " + format(route, state) + formatStats(route));
         }
+        final Future<CPoolEntry> future = this.pool.lease(route, state, null);
+        return new ConnectionRequest() {
+
+            public boolean cancel() {
+                return future.cancel(true);
+            }
+
+            public HttpClientConnection get(
+                    final long timeout,
+                    final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException {
+                return leaseConnection(future, timeout, tunit);
+            }
+
+        };
+
     }
 
-    @Override
-    protected void onConnectionLease(final CPoolEntry entry) {
-        if (this.log.isDebugEnabled()) {
-            this.log.debug("Connection leased: " + format(entry) + formatStats(entry.getRoute()));
+    protected HttpClientConnection leaseConnection(
+            final Future<CPoolEntry> future,
+            final long timeout,
+            final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException {
+        CPoolEntry entry;
+        try {
+            entry = future.get(timeout, tunit);
+            if (entry == null || future.isCancelled()) {
+                throw new InterruptedException();
+            }
+            if (entry.getConnection() == null) {
+                throw new IllegalStateException("Pool entry with no connection");
+            }
+            if (this.log.isDebugEnabled()) {
+                this.log.debug("Connection leased: " + format(entry) + formatStats(entry.getRoute()));
+            }
+            return CPoolProxy.newProxy(entry);
+        } catch (ExecutionException ex) {
+            Throwable cause = ex.getCause();
+            if (cause == null) {
+                cause = ex;
+            }
+            InterruptedException intex = new InterruptedException();
+            intex.initCause(cause);
+            throw intex;
+        } catch (TimeoutException ex) {
+            throw new ConnectionPoolTimeoutException("Timeout waiting for connection from pool");
         }
     }
 
-    @Override
-    protected void onConnectionKeepAlive(final CPoolEntry entry) {
-        if (this.log.isDebugEnabled()) {
-            long keepalive = entry.getExpiry();
-            String s;
-            if (keepalive > 0) {
-                s = "for " + (double) keepalive / 1000 + " seconds";
-            } else {
-                s = "indefinitely";
+    public void releaseConnection(
+            final HttpClientConnection managedConn,
+            final Object state,
+            final long keepalive, final TimeUnit tunit) {
+        if (managedConn == null) {
+            throw new IllegalArgumentException("Managed connection may not be null");
+        }
+        synchronized (managedConn) {
+            CPoolEntry entry = CPoolProxy.detach(managedConn);
+            if (entry == null) {
+                return;
+            }
+            SocketClientConnection conn = entry.getConnection();
+            try {
+                if (conn.isOpen()) {
+                    entry.setState(state);
+                    entry.updateExpiry(keepalive, tunit != null ? tunit : TimeUnit.MILLISECONDS);
+                    if (this.log.isDebugEnabled()) {
+                        String s;
+                        if (keepalive > 0) {
+                            s = "for " + (double) keepalive / 1000 + " seconds";
+                        } else {
+                            s = "indefinitely";
+                        }
+                        this.log.debug("Connection " + format(entry) + " can be kept alive " + s);
+                    }
+                }
+            } finally {
+                this.pool.release(entry, conn.isOpen());
+                if (this.log.isDebugEnabled()) {
+                    this.log.debug("Connection released: " + format(entry) + formatStats(entry.getRoute()));
+                }
             }
-            this.log.debug("Connection " + format(entry) + " can be kept alive " + s);
         }
     }
 
-    @Override
-    protected void onConnectionRelease(final CPoolEntry entry) {
-        if (this.log.isDebugEnabled()) {
-            this.log.debug("Connection released: " + format(entry) + formatStats(entry.getRoute()));
+    public void connect(
+            final HttpClientConnection managedConn,
+            final HttpHost host,
+            final InetAddress local,
+            final int connectTimeout,
+            final HttpContext context) throws IOException {
+        if (managedConn == null) {
+            throw new IllegalArgumentException("Connection may not be null");
+        }
+        SocketClientConnection conn;
+        synchronized (managedConn) {
+            CPoolEntry entry = CPoolProxy.getPoolEntry(managedConn);
+            conn = entry.getConnection();
+        }
+        SocketConfig socketConfig = this.configData.getSocketConfig(host);
+        if (socketConfig == null) {
+            socketConfig = this.configData.getDefaultSocketConfig();
+        }
+        if (socketConfig == null) {
+            socketConfig = SocketConfig.DEFAULT;
+        }
+        InetSocketAddress localAddress = local != null ? new InetSocketAddress(local, 0) : null;
+        this.connectionOperator.connect(
+                conn, host, localAddress, connectTimeout, socketConfig, context);
+    }
+
+    public void upgrade(
+            final HttpClientConnection managedConn,
+            final HttpHost host,
+            final HttpContext context) throws IOException {
+        if (managedConn == null) {
+            throw new IllegalArgumentException("Connection may not be null");
+        }
+        SocketClientConnection conn;
+        synchronized (managedConn) {
+            CPoolEntry entry = CPoolProxy.getPoolEntry(managedConn);
+            conn = entry.getConnection();
         }
+        this.connectionOperator.upgrade(conn, host, context);
     }
 
     public void shutdown() {
@@ -249,4 +376,116 @@ public class PoolingHttpClientConnection
         return this.pool.getStats(route);
     }
 
-}
+    public SocketConfig getDefaultSocketConfig() {
+        return this.configData.getDefaultSocketConfig();
+    }
+
+    public void setDefaultSocketConfig(final SocketConfig defaultSocketConfig) {
+        this.configData.setDefaultSocketConfig(defaultSocketConfig);
+    }
+
+    public ConnectionConfig getDefaultConnectionConfig() {
+        return this.configData.getDefaultConnectionConfig();
+    }
+
+    public void setDefaultConnectionConfig(final ConnectionConfig defaultConnectionConfig) {
+        this.configData.setDefaultConnectionConfig(defaultConnectionConfig);
+    }
+
+    public SocketConfig getSocketConfig(final HttpHost host) {
+        return this.configData.getSocketConfig(host);
+    }
+
+    public void setSocketConfig(final HttpHost host, final SocketConfig socketConfig) {
+        this.configData.setSocketConfig(host, socketConfig);
+    }
+
+    public ConnectionConfig getConnectionConfig(final HttpHost host) {
+        return this.configData.getConnectionConfig(host);
+    }
+
+    public void setConnectionConfig(final HttpHost host, final ConnectionConfig connectionConfig) {
+        this.configData.setConnectionConfig(host, connectionConfig);
+    }
+
+    static class ConfigData {
+
+        private final Map<HttpHost, SocketConfig> socketConfigMap;
+        private final Map<HttpHost, ConnectionConfig> connectionConfigMap;
+        private volatile SocketConfig defaultSocketConfig;
+        private volatile ConnectionConfig defaultConnectionConfig;
+
+        ConfigData() {
+            super();
+            this.socketConfigMap = new ConcurrentHashMap<HttpHost, SocketConfig>();
+            this.connectionConfigMap = new ConcurrentHashMap<HttpHost, ConnectionConfig>();
+        }
+
+        public SocketConfig getDefaultSocketConfig() {
+            return this.defaultSocketConfig;
+        }
+
+        public void setDefaultSocketConfig(final SocketConfig defaultSocketConfig) {
+            this.defaultSocketConfig = defaultSocketConfig;
+        }
+
+        public ConnectionConfig getDefaultConnectionConfig() {
+            return this.defaultConnectionConfig;
+        }
+
+        public void setDefaultConnectionConfig(final ConnectionConfig defaultConnectionConfig) {
+            this.defaultConnectionConfig = defaultConnectionConfig;
+        }
+
+        public SocketConfig getSocketConfig(final HttpHost host) {
+            return this.socketConfigMap.get(host);
+        }
+
+        public void setSocketConfig(final HttpHost host, final SocketConfig socketConfig) {
+            this.socketConfigMap.put(host, socketConfig);
+        }
+
+        public ConnectionConfig getConnectionConfig(final HttpHost host) {
+            return this.connectionConfigMap.get(host);
+        }
+
+        public void setConnectionConfig(final HttpHost host, final ConnectionConfig connectionConfig) {
+            this.connectionConfigMap.put(host, connectionConfig);
+        }
+
+    }
+
+    static class InternalConnectionFactory implements ConnFactory<HttpRoute, SocketClientConnection> {
+
+        private final ConfigData configData;
+        private final HttpConnectionFactory<SocketClientConnection> connFactory;
+
+        InternalConnectionFactory(
+                final ConfigData configData,
+                final HttpConnectionFactory<SocketClientConnection> connFactory) {
+            super();
+            this.configData = configData != null ? configData : new ConfigData();
+            this.connFactory = connFactory != null ? connFactory :
+                DefaultClientConnectionFactory.INSTANCE;
+        }
+
+        public SocketClientConnection create(final HttpRoute route) throws IOException {
+            ConnectionConfig config = null;
+            if (route.getProxyHost() != null) {
+                config = this.configData.getConnectionConfig(route.getProxyHost());
+            }
+            if (config == null) {
+                config = this.configData.getConnectionConfig(route.getTargetHost());
+            }
+            if (config == null) {
+                config = this.configData.getDefaultConnectionConfig();
+            }
+            if (config == null) {
+                config = ConnectionConfig.DEFAULT;
+            }
+            return this.connFactory.create(config);
+        }
+
+    }
+
+}
\ No newline at end of file

Modified: httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/conn/TestPoolingHttpClientConnectionManager.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/conn/TestPoolingHttpClientConnectionManager.java?rev=1421309&r1=1421308&r2=1421309&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/conn/TestPoolingHttpClientConnectionManager.java (original)
+++ httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/conn/TestPoolingHttpClientConnectionManager.java Thu Dec 13 14:22:28 2012
@@ -27,15 +27,25 @@
 
 package org.apache.http.impl.conn;
 
+import java.net.Socket;
+import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
+import org.apache.commons.logging.LogFactory;
 import org.apache.http.HttpClientConnection;
 import org.apache.http.HttpHost;
+import org.apache.http.config.Lookup;
 import org.apache.http.conn.ConnectionRequest;
 import org.apache.http.conn.ConnectionPoolTimeoutException;
-import org.apache.http.conn.HttpClientConnectionManager;
+import org.apache.http.conn.DnsResolver;
+import org.apache.http.conn.SchemePortResolver;
+import org.apache.http.conn.SocketClientConnection;
 import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.protocol.HttpContext;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
 
@@ -44,500 +54,136 @@ import org.mockito.Mockito;
  */
 public class TestPoolingHttpClientConnectionManager {
 
-    private static HttpClientConnection getConnection(
-            final HttpClientConnectionManager mgr,
-            final HttpRoute route,
-            long timeout,
-            TimeUnit unit) throws ConnectionPoolTimeoutException, InterruptedException {
-        ConnectionRequest connRequest = mgr.requestConnection(route, null);
-        return connRequest.get(timeout, unit);
-    }
-
-    private static HttpClientConnection getConnection(
-            final HttpClientConnectionManager mgr,
-            final HttpRoute route) throws ConnectionPoolTimeoutException, InterruptedException {
-        ConnectionRequest connRequest = mgr.requestConnection(route, null);
-        return connRequest.get(0, null);
-    }
-
-    @Test(expected=IllegalArgumentException.class)
-    public void testIllegalConstructor() {
-        new PoolingHttpClientConnectionManager(null);
-    }
-
-    @Test(expected=IllegalArgumentException.class)
-    public void testGetConnection()
-            throws InterruptedException, ConnectionPoolTimeoutException {
-        PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager();
-
-        HttpHost target = new HttpHost("www.test.invalid", 80, "http");
-        HttpRoute route = new HttpRoute(target, null, false);
-
-        HttpClientConnection conn = getConnection(mgr, route);
-        Assert.assertNotNull(conn);
-        Assert.assertFalse(conn.isOpen());
-
-        mgr.releaseConnection(conn, null, -1, null);
-
-        try {
-            getConnection(mgr, null);
-        } finally {
-            mgr.shutdown();
-        }
-    }
-
-    // testTimeout in 3.x TestHttpConnectionManager is redundant
-    // several other tests here rely on timeout behavior
-    @Test
-    public void testMaxConnTotal()
-            throws InterruptedException, ConnectionPoolTimeoutException {
-
-        PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager();
-        mgr.setMaxTotal(2);
-        mgr.setDefaultMaxPerRoute(1);
-
-        HttpHost target1 = new HttpHost("www.test1.invalid", 80, "http");
-        HttpRoute route1 = new HttpRoute(target1, null, false);
-        HttpHost target2 = new HttpHost("www.test2.invalid", 80, "http");
-        HttpRoute route2 = new HttpRoute(target2, null, false);
-
-        HttpClientConnection conn1 = getConnection(mgr, route1);
-        Assert.assertNotNull(conn1);
-        HttpClientConnection conn2 = getConnection(mgr, route2);
-        Assert.assertNotNull(conn2);
-
-        try {
-            // this should fail quickly, connection has not been released
-            getConnection(mgr, route2, 100L, TimeUnit.MILLISECONDS);
-            Assert.fail("ConnectionPoolTimeoutException should have been thrown");
-        } catch (ConnectionPoolTimeoutException e) {
-            // expected
-        }
-
-        // release one of the connections
-        mgr.releaseConnection(conn2, null, -1, null);
-        conn2 = null;
-
-        // there should be a connection available now
-        try {
-            getConnection(mgr, route2, 100L, TimeUnit.MILLISECONDS);
-        } catch (ConnectionPoolTimeoutException cptx) {
-            Assert.fail("connection should have been available: " + cptx);
-        }
-
-        mgr.shutdown();
-    }
-
-    @Test
-    public void testMaxConnPerHost() throws Exception {
-
-        HttpHost target1 = new HttpHost("www.test1.invalid", 80, "http");
-        HttpRoute route1 = new HttpRoute(target1, null, false);
-        HttpHost target2 = new HttpHost("www.test2.invalid", 80, "http");
-        HttpRoute route2 = new HttpRoute(target2, null, false);
-        HttpHost target3 = new HttpHost("www.test3.invalid", 80, "http");
-        HttpRoute route3 = new HttpRoute(target3, null, false);
-
-        PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager();
-        mgr.setMaxTotal(100);
-        mgr.setDefaultMaxPerRoute(1);
-        mgr.setMaxPerRoute(route2, 2);
-        mgr.setMaxPerRoute(route3, 3);
-
-        // route 3, limit 3
-        HttpClientConnection conn1 =
-            getConnection(mgr, route3, 10L, TimeUnit.MILLISECONDS);
-        Assert.assertNotNull(conn1);
-        HttpClientConnection conn2 =
-            getConnection(mgr, route3, 10L, TimeUnit.MILLISECONDS);
-        Assert.assertNotNull(conn2);
-        HttpClientConnection conn3 =
-            getConnection(mgr, route3, 10L, TimeUnit.MILLISECONDS);
-        Assert.assertNotNull(conn3);
-        try {
-            // should fail quickly, connection has not been released
-            getConnection(mgr, route3, 10L, TimeUnit.MILLISECONDS);
-            Assert.fail("ConnectionPoolTimeoutException should have been thrown");
-        } catch (ConnectionPoolTimeoutException e) {
-            // expected
-        }
-
-        // route 2, limit 2
-        conn1 = getConnection(mgr, route2, 10L, TimeUnit.MILLISECONDS);
-        conn2 = getConnection(mgr, route2, 10L, TimeUnit.MILLISECONDS);
-        try {
-            // should fail quickly, connection has not been released
-            getConnection(mgr, route2, 10L, TimeUnit.MILLISECONDS);
-            Assert.fail("ConnectionPoolTimeoutException should have been thrown");
-        } catch (ConnectionPoolTimeoutException e) {
-            // expected
-        }
-
-        // route 1, should use default limit of 1
-        conn1 = getConnection(mgr, route1, 10L, TimeUnit.MILLISECONDS);
-        try {
-            // should fail quickly, connection has not been released
-            getConnection(mgr, route1, 10L, TimeUnit.MILLISECONDS);
-            Assert.fail("ConnectionPoolTimeoutException should have been thrown");
-        } catch (ConnectionPoolTimeoutException e) {
-            // expected
-        }
-        // check releaseConnection with invalid arguments
-        try {
-            mgr.releaseConnection(null, null, -1, null);
-            Assert.fail("null connection adapter not detected");
-        } catch (IllegalArgumentException iax) {
-            // expected
-        }
-        try {
-            HttpClientConnection conn = Mockito.mock(HttpClientConnection.class);
-            mgr.releaseConnection(conn, null, -1, null);
-            Assert.fail("foreign connection adapter not detected");
-        } catch (IllegalArgumentException iax) {
-            // expected
-        }
-
-        mgr.shutdown();
+    private SocketClientConnection conn;
+    private Socket socket;
+    private ConnectionSocketFactory plainSocketFactory;
+    private Lookup<ConnectionSocketFactory> socketFactoryRegistry;
+    private SchemePortResolver schemePortResolver;
+    private DnsResolver dnsResolver;
+    private Future<CPoolEntry> future;
+    private CPool pool;
+    private PoolingHttpClientConnectionManager mgr;
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void setup() throws Exception {
+        conn = Mockito.mock(SocketClientConnection.class);
+        socket = Mockito.mock(Socket.class);
+        plainSocketFactory = Mockito.mock(ConnectionSocketFactory.class);
+        socketFactoryRegistry = Mockito.mock(Lookup.class);
+        schemePortResolver = Mockito.mock(SchemePortResolver.class);
+        dnsResolver = Mockito.mock(DnsResolver.class);
+        pool = Mockito.mock(CPool.class);
+        future = Mockito.mock(Future.class);
+        mgr = new PoolingHttpClientConnectionManager(
+                pool, socketFactoryRegistry, schemePortResolver, dnsResolver);
     }
 
     @Test
-    public void testReleaseConnection() throws Exception {
+    public void testLeaseRelease() throws Exception {
+        HttpHost target = new HttpHost("localhost");
+        HttpRoute route = new HttpRoute(target);
+
+        CPoolEntry entry = new CPoolEntry(LogFactory.getLog(getClass()), "id", route, conn,
+                -1, TimeUnit.MILLISECONDS);
+
+        Mockito.when(future.isCancelled()).thenReturn(Boolean.FALSE);
+        Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory);
+        Mockito.when(schemePortResolver.resolve(target)).thenReturn(80);
+        Mockito.when(plainSocketFactory.createSocket(Mockito.<HttpContext>any())).thenReturn(socket);
+
+        Mockito.when(future.isCancelled()).thenReturn(false);
+        Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
+        Mockito.when(pool.lease(route, null, null)).thenReturn(future);
 
-        PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager();
-        mgr.setMaxTotal(3);
-        mgr.setDefaultMaxPerRoute(1);
-
-        HttpHost target1 = new HttpHost("www.test1.invalid", 80, "http");
-        HttpRoute route1 = new HttpRoute(target1, null, false);
-        HttpHost target2 = new HttpHost("www.test2.invalid", 80, "http");
-        HttpRoute route2 = new HttpRoute(target2, null, false);
-        HttpHost target3 = new HttpHost("www.test3.invalid", 80, "http");
-        HttpRoute route3 = new HttpRoute(target3, null, false);
-
-        // the first three allocations should pass
-        HttpClientConnection conn1 =
-            getConnection(mgr, route1, 10L, TimeUnit.MILLISECONDS);
-        HttpClientConnection conn2 =
-            getConnection(mgr, route2, 10L, TimeUnit.MILLISECONDS);
-        HttpClientConnection conn3 =
-            getConnection(mgr, route3, 10L, TimeUnit.MILLISECONDS);
+        ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
+        HttpClientConnection conn1 = connRequest1.get(1, TimeUnit.SECONDS);
         Assert.assertNotNull(conn1);
-        Assert.assertNotNull(conn2);
-        Assert.assertNotNull(conn3);
+        Assert.assertFalse(conn1.isOpen());
+        Assert.assertNotSame(conn, conn1);
 
-        // obtaining another connection for either of the three should fail
-        // this is somehow redundant with testMaxConnPerHost
-        try {
-            getConnection(mgr, route1, 10L, TimeUnit.MILLISECONDS);
-            Assert.fail("ConnectionPoolTimeoutException should have been thrown");
-        } catch (ConnectionPoolTimeoutException e) {
-            // expected
-        }
-        try {
-            getConnection(mgr, route2, 10L, TimeUnit.MILLISECONDS);
-            Assert.fail("ConnectionPoolTimeoutException should have been thrown");
-        } catch (ConnectionPoolTimeoutException e) {
-            // expected
-        }
-        try {
-            getConnection(mgr, route3, 10L, TimeUnit.MILLISECONDS);
-            Assert.fail("ConnectionPoolTimeoutException should have been thrown");
-        } catch (ConnectionPoolTimeoutException e) {
-            // expected
-        }
-
-        // now release one and check that exactly that one can be obtained then
-        mgr.releaseConnection(conn2, null, -1, null);
-        conn2 = null;
-        try {
-            getConnection(mgr, route1, 10L, TimeUnit.MILLISECONDS);
-            Assert.fail("ConnectionPoolTimeoutException should have been thrown");
-        } catch (ConnectionPoolTimeoutException e) {
-            // expected
-        }
-        // this one succeeds
-        conn2 = getConnection(mgr, route2, 10L, TimeUnit.MILLISECONDS);
-        Assert.assertNotNull(conn2);
-        try {
-            getConnection(mgr, route3, 10L, TimeUnit.MILLISECONDS);
-            Assert.fail("ConnectionPoolTimeoutException should have been thrown");
-        } catch (ConnectionPoolTimeoutException e) {
-            // expected
-        }
+        mgr.releaseConnection(conn1, null, 0, TimeUnit.MILLISECONDS);
 
-        mgr.shutdown();
+        Mockito.verify(pool).release(entry, false);
     }
 
-    @Test
-    public void testDeleteClosedConnections() throws Exception {
-        PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager();
-
-        HttpHost target = new HttpHost("www.test.invalid", 80, "http");
-        HttpRoute route = new HttpRoute(target, null, false);
-
-        HttpClientConnection conn = getConnection(mgr, route);
+    @Test(expected=InterruptedException.class)
+    public void testLeaseFutureCancelled() throws Exception {
+        HttpHost target = new HttpHost("localhost");
+        HttpRoute route = new HttpRoute(target);
 
-        Assert.assertEquals(1, mgr.getTotalStats().getLeased());
-        Assert.assertEquals(1, mgr.getStats(route).getLeased());
-        mgr.releaseConnection(conn, null, -1, null);
+        CPoolEntry entry = new CPoolEntry(LogFactory.getLog(getClass()), "id", route, conn,
+                -1, TimeUnit.MILLISECONDS);
 
-        Assert.assertEquals(0, mgr.getTotalStats().getAvailable());
-        Assert.assertEquals(0, mgr.getStats(route).getAvailable());
-
-        mgr.shutdown();
-    }
-
-    @Test
-    public void testShutdown() throws Exception {
-        // 3.x: TestHttpConnectionManager.testShutdown
+        Mockito.when(future.isCancelled()).thenReturn(Boolean.TRUE);
+        Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
+        Mockito.when(pool.lease(route, null, null)).thenReturn(future);
 
-        PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager();
-        mgr.setMaxTotal(1);
-        mgr.setDefaultMaxPerRoute(1);
-
-        HttpHost target = new HttpHost("www.test.invalid", 80, "http");
-        HttpRoute route = new HttpRoute(target, null, false);
-
-        // get the only connection, then start an extra thread
-        // on shutdown, the extra thread should get an exception
-
-        HttpClientConnection conn =
-            getConnection(mgr, route, 1L, TimeUnit.MILLISECONDS);
-        GetConnThread gct = new GetConnThread(mgr, route, 0L); // no timeout
-        gct.start();
-        Thread.sleep(100); // give extra thread time to block
-
-
-        mgr.shutdown();
-
-        // First release the connection. If the manager keeps working
-        // despite the shutdown, this will deblock the extra thread.
-        // The release itself should turn into a no-op, without exception.
-        mgr.releaseConnection(conn, null, -1, null);
-
-
-        gct.join(10000);
-        Assert.assertNull("thread should not have obtained connection",
-                   gct.getConnection());
-        Assert.assertNotNull("thread should have gotten an exception",
-                      gct.getException());
-        Assert.assertSame("thread got wrong exception",
-                InterruptedException.class, gct.getException().getClass());
-
-        // the manager is down, we should not be able to get a connection
-        try {
-            getConnection(mgr, route, 1L, TimeUnit.MILLISECONDS);
-            Assert.fail("shut-down manager does not raise exception");
-        } catch (IllegalStateException isx) {
-            // expected
-        }
+        ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
+        connRequest1.get(1, TimeUnit.SECONDS);
     }
 
-    @Test
-    public void testInterruptThread() throws Exception {
-        // 3.x: TestHttpConnectionManager.testWaitingThreadInterrupted
-
-        PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager();
-        mgr.setMaxTotal(1);
-
-        HttpHost target = new HttpHost("www.test.invalid", 80, "http");
-        HttpRoute route = new HttpRoute(target, null, false);
+    @Test(expected=ConnectionPoolTimeoutException.class)
+    public void testLeaseFutureTimeout() throws Exception {
+        HttpHost target = new HttpHost("localhost");
+        HttpRoute route = new HttpRoute(target);
 
-        // get the only connection, then start an extra thread
-        HttpClientConnection conn =
-            getConnection(mgr, route, 1L, TimeUnit.MILLISECONDS);
-        GetConnThread gct = new GetConnThread(mgr, route, 0L); // no timeout
-        gct.start();
-        Thread.sleep(100); // give extra thread time to block
-
-
-        // interrupt the thread, it should cancel waiting with an exception
-        gct.interrupt();
-
-
-        gct.join(10000);
-        Assert.assertNotNull("thread should have gotten an exception",
-                      gct.getException());
-        Assert.assertSame("thread got wrong exception",
-                   InterruptedException.class,
-                   gct.getException().getClass());
-
-        // make sure the manager is still working
-        try {
-            getConnection(mgr, route, 10L, TimeUnit.MILLISECONDS);
-            Assert.fail("should have gotten a timeout");
-        } catch (ConnectionPoolTimeoutException e) {
-            // expected
-        }
-
-        mgr.releaseConnection(conn, null, -1, null);
-        // this time: no exception
-        conn = getConnection(mgr, route, 10L, TimeUnit.MILLISECONDS);
-        Assert.assertNotNull("should have gotten a connection", conn);
+        Mockito.when(future.isCancelled()).thenReturn(Boolean.TRUE);
+        Mockito.when(future.get(1, TimeUnit.SECONDS)).thenThrow(new TimeoutException());
+        Mockito.when(pool.lease(route, null, null)).thenReturn(future);
 
-        mgr.shutdown();
+        ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
+        connRequest1.get(1, TimeUnit.SECONDS);
     }
 
     @Test
-    public void testReusePreference() throws Exception {
-        // 3.x: TestHttpConnectionManager.testHostReusePreference
+    public void testReleaseReusable() throws Exception {
+        HttpHost target = new HttpHost("localhost");
+        HttpRoute route = new HttpRoute(target);
 
-        PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager();
-        mgr.setMaxTotal(1);
+        CPoolEntry entry = Mockito.spy(new CPoolEntry(LogFactory.getLog(getClass()), "id", route, conn,
+                -1, TimeUnit.MILLISECONDS));
 
-        HttpHost target1 = new HttpHost("www.test1.invalid", 80, "http");
-        HttpRoute route1 = new HttpRoute(target1, null, false);
-        HttpHost target2 = new HttpHost("www.test2.invalid", 80, "http");
-        HttpRoute route2 = new HttpRoute(target2, null, false);
-
-        // get the only connection, then start two extra threads
-        HttpClientConnection conn =
-            getConnection(mgr, route1, 1L, TimeUnit.MILLISECONDS);
-        GetConnThread gct1 = new GetConnThread(mgr, route1, 1000L);
-        GetConnThread gct2 = new GetConnThread(mgr, route2, 1000L);
-
-        // the second thread is started first, to distinguish the
-        // route-based reuse preference from first-come, first-served
-        gct2.start();
-        Thread.sleep(100); // give the thread time to block
-        gct1.start();
-        Thread.sleep(100); // give the thread time to block
-
-
-        // releasing the connection for route1 should deblock thread1
-        // the other thread gets a timeout
-        mgr.releaseConnection(conn, null, -1, null);
-
-        gct1.join(10000);
-        gct2.join(10000);
-
-        Assert.assertNotNull("thread 1 should have gotten a connection",
-                      gct1.getConnection());
-        Assert.assertNull   ("thread 2 should NOT have gotten a connection",
-                      gct2.getConnection());
+        Mockito.when(future.isCancelled()).thenReturn(Boolean.FALSE);
+        Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
+        Mockito.when(pool.lease(route, null, null)).thenReturn(future);
+        Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE);
 
-        mgr.shutdown();
-    }
+        ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
+        HttpClientConnection conn1 = connRequest1.get(1, TimeUnit.SECONDS);
+        Assert.assertNotNull(conn1);
+        Assert.assertTrue(conn1.isOpen());
 
-    @Test
-    public void testAbortAfterRequestStarts() throws Exception {
-        PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager();
-        mgr.setMaxTotal(1);
-
-        HttpHost target = new HttpHost("www.test.invalid", 80, "http");
-        HttpRoute route = new HttpRoute(target, null, false);
-
-        // get the only connection, then start an extra thread
-        HttpClientConnection conn = getConnection(mgr, route, 1L, TimeUnit.MILLISECONDS);
-        ConnectionRequest request = mgr.requestConnection(route, null);
-        GetConnThread gct = new GetConnThread(request, route, 0L); // no timeout
-        gct.start();
-        Thread.sleep(100); // give extra thread time to block
-
-        request.cancel();
-
-        gct.join(10000);
-        Assert.assertNotNull("thread should have gotten an exception",
-                      gct.getException());
-        Assert.assertSame("thread got wrong exception",
-                   InterruptedException.class,
-                   gct.getException().getClass());
-
-        // make sure the manager is still working
-        try {
-            getConnection(mgr, route, 10L, TimeUnit.MILLISECONDS);
-            Assert.fail("should have gotten a timeout");
-        } catch (ConnectionPoolTimeoutException e) {
-            // expected
-        }
-
-        mgr.releaseConnection(conn, null, -1, null);
-        // this time: no exception
-        conn = getConnection(mgr, route, 10L, TimeUnit.MILLISECONDS);
-        Assert.assertNotNull("should have gotten a connection", conn);
+        mgr.releaseConnection(conn1, "some state", 0, TimeUnit.MILLISECONDS);
 
-        mgr.shutdown();
+        Mockito.verify(pool).release(entry, true);
+        Mockito.verify(entry).setState("some state");
+        Mockito.verify(entry).updateExpiry(Mockito.anyLong(), Mockito.eq(TimeUnit.MILLISECONDS));
     }
 
     @Test
-    public void testAbortBeforeRequestStarts() throws Exception {
-        PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager();
-        mgr.setMaxTotal(1);
-
-        HttpHost target = new HttpHost("www.test.invalid", 80, "http");
-        HttpRoute route = new HttpRoute(target, null, false);
-
-        // get the only connection, then start an extra thread
-        HttpClientConnection conn = getConnection(mgr, route, 1L, TimeUnit.MILLISECONDS);
-        ConnectionRequest request = mgr.requestConnection(route, null);
-        request.cancel();
-
-        GetConnThread gct = new GetConnThread(request, route, 0L); // no timeout
-        gct.start();
-        Thread.sleep(100); // give extra thread time to block
-
-        gct.join(10000);
-        Assert.assertNotNull("thread should have gotten an exception",
-                      gct.getException());
-        Assert.assertSame("thread got wrong exception",
-                   InterruptedException.class,
-                   gct.getException().getClass());
-
-        // make sure the manager is still working
-        try {
-            getConnection(mgr, route, 10L, TimeUnit.MILLISECONDS);
-            Assert.fail("should have gotten a timeout");
-        } catch (ConnectionPoolTimeoutException e) {
-            // expected
-        }
-
-        mgr.releaseConnection(conn, null, -1, null);
-        // this time: no exception
-        conn = getConnection(mgr, route, 10L, TimeUnit.MILLISECONDS);
-        Assert.assertNotNull("should have gotten a connection", conn);
-
-        mgr.shutdown();
-    }
+    public void testReleaseNonReusable() throws Exception {
+        HttpHost target = new HttpHost("localhost");
+        HttpRoute route = new HttpRoute(target);
 
-    public class GetConnThread extends Thread {
+        CPoolEntry entry = Mockito.spy(new CPoolEntry(LogFactory.getLog(getClass()), "id", route, conn,
+                -1, TimeUnit.MILLISECONDS));
 
-        private final ConnectionRequest connRequest;
-        private final long timeout;
+        Mockito.when(future.isCancelled()).thenReturn(Boolean.FALSE);
+        Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
+        Mockito.when(pool.lease(route, null, null)).thenReturn(future);
+        Mockito.when(conn.isOpen()).thenReturn(Boolean.FALSE);
 
-        private volatile HttpClientConnection connection;
-        private volatile Exception exception;
+        ConnectionRequest connRequest1 = mgr.requestConnection(route, null);
+        HttpClientConnection conn1 = connRequest1.get(1, TimeUnit.SECONDS);
+        Assert.assertNotNull(conn1);
+        Assert.assertFalse(conn1.isOpen());
 
-        public GetConnThread(
-                final HttpClientConnectionManager mgr,
-                final HttpRoute route, long timeout) {
-            this(mgr.requestConnection(route, null), route, timeout);
-        }
-
-        public GetConnThread(
-                final ConnectionRequest connRequest,
-                final HttpRoute route, long timeout) {
-            super();
-            this.connRequest = connRequest;
-            this.timeout = timeout;
-        }
-
-        @Override
-        public void run() {
-            try {
-                connection = connRequest.get(timeout, TimeUnit.MILLISECONDS);
-            } catch (Exception ex) {
-                exception = ex;
-            }
-        }
-
-        public Throwable getException() {
-            return exception;
-        }
-
-        public HttpClientConnection getConnection() {
-            return connection;
-        }
+        mgr.releaseConnection(conn1, "some state", 0, TimeUnit.MILLISECONDS);
 
+        Mockito.verify(pool).release(entry, false);
+        Mockito.verify(entry, Mockito.never()).setState(Mockito.anyObject());
+        Mockito.verify(entry, Mockito.never()).updateExpiry(Mockito.anyLong(), Mockito.eq(TimeUnit.MILLISECONDS));
     }
 
 }



Mime
View raw message