@Override
 public void connect(
     final HttpClientConnection managedConn,
     final HttpRoute route,
     final int connectTimeout,
     final HttpContext context)
     throws IOException {
   Args.notNull(managedConn, "Managed Connection");
   Args.notNull(route, "HTTP route");
   final ManagedHttpClientConnection conn;
   synchronized (managedConn) {
     final CPoolEntry entry = CPoolProxy.getPoolEntry(managedConn);
     conn = entry.getConnection();
   }
   final HttpHost host;
   if (route.getProxyHost() != null) {
     host = route.getProxyHost();
   } else {
     host = route.getTargetHost();
   }
   final InetSocketAddress localAddress = route.getLocalSocketAddress();
   SocketConfig socketConfig = this.configData.getSocketConfig(host);
   if (socketConfig == null) {
     socketConfig = this.configData.getDefaultSocketConfig();
   }
   if (socketConfig == null) {
     socketConfig = SocketConfig.DEFAULT;
   }
   this.connectionOperator.connect(
       conn, host, localAddress, connectTimeout, socketConfig, context);
 }
 @Override
 public void routeComplete(
     final HttpClientConnection managedConn, final HttpRoute route, final HttpContext context)
     throws IOException {
   Args.notNull(managedConn, "Managed Connection");
   Args.notNull(route, "HTTP route");
   synchronized (managedConn) {
     final CPoolEntry entry = CPoolProxy.getPoolEntry(managedConn);
     entry.markRouteComplete();
   }
 }
 @Override
 public void upgrade(
     final HttpClientConnection managedConn, final HttpRoute route, final HttpContext context)
     throws IOException {
   Args.notNull(managedConn, "Managed Connection");
   Args.notNull(route, "HTTP route");
   final ManagedHttpClientConnection conn;
   synchronized (managedConn) {
     final CPoolEntry entry = CPoolProxy.getPoolEntry(managedConn);
     conn = entry.getConnection();
   }
   this.connectionOperator.upgrade(conn, route.getTargetHost(), context);
 }
 protected HttpClientConnection leaseConnection(
     final Future<CPoolEntry> future, final long timeout, final TimeUnit tunit)
     throws InterruptedException, ExecutionException, ConnectionPoolTimeoutException {
   final CPoolEntry entry;
   try {
     entry = future.get(timeout, tunit);
     if (entry == null || future.isCancelled()) {
       throw new InterruptedException();
     }
     Asserts.check(entry.getConnection() != null, "Pool entry with no connection");
     if (this.log.isDebugEnabled()) {
       this.log.debug("Connection leased: " + format(entry) + formatStats(entry.getRoute()));
     }
     return CPoolProxy.newProxy(entry);
   } catch (final TimeoutException ex) {
     throw new ConnectionPoolTimeoutException("Timeout waiting for connection from pool");
   }
 }
 @Override
 public void releaseConnection(
     final HttpClientConnection managedConn,
     final Object state,
     final long keepalive,
     final TimeUnit tunit) {
   Args.notNull(managedConn, "Managed connection");
   synchronized (managedConn) {
     final CPoolEntry entry = CPoolProxy.detach(managedConn);
     if (entry == null) {
       return;
     }
     final ManagedHttpClientConnection conn = entry.getConnection();
     try {
       if (conn.isOpen()) {
         final TimeUnit effectiveUnit = tunit != null ? tunit : TimeUnit.MILLISECONDS;
         entry.setState(state);
         entry.updateExpiry(keepalive, effectiveUnit);
         if (this.log.isDebugEnabled()) {
           final String s;
           if (keepalive > 0) {
             s = "for " + (double) effectiveUnit.toMillis(keepalive) / 1000 + " seconds";
           } else {
             s = "indefinitely";
           }
           this.log.debug("Connection " + format(entry) + " can be kept alive " + s);
         }
       }
     } finally {
       this.pool.release(entry, conn.isOpen() && entry.isRouteComplete());
       if (this.log.isDebugEnabled()) {
         this.log.debug("Connection released: " + format(entry) + formatStats(entry.getRoute()));
       }
     }
   }
 }