@Override
    public Session<?> borrow(final BackgroundActionState callback) throws BackgroundException {
        final int numActive = pool.getNumActive();
        if(numActive > POOL_WARNING_THRESHOLD) {
            log.warn(String.format("Possibly large number of open connections (%d) in pool %s", numActive, this));
        }
        try {
            while(!callback.isCanceled()) {
                try {
                    if(log.isInfoEnabled()) {
                        log.info(String.format("Borrow session from pool %s", this));
                    }
                    final Session<?> session = pool.borrowObject();
                    if(log.isInfoEnabled()) {
                        log.info(String.format("Borrowed session %s from pool %s", session, this));
                    }
                    if(DISCONNECTED == features) {
                        features = new StatelessSessionPool(connect, session, transcript, registry);
                    }
                    return session.withListener(transcript);
                }
                catch(IllegalStateException e) {
                    throw new ConnectionCanceledException(e);
                }
                catch(NoSuchElementException e) {
                    if(pool.isClosed()) {
                        throw new ConnectionCanceledException(e);
                    }
                    final Throwable cause = e.getCause();
                    if(null == cause) {
                        log.warn(String.format("Timeout borrowing session from pool %s. Wait for another %dms", this, BORROW_MAX_WAIT_INTERVAL));
                        // Timeout
                        continue;
                    }
                    if(cause instanceof BackgroundException) {
                        final BackgroundException failure = (BackgroundException) cause;
                        log.warn(String.format("Failure %s obtaining connection for %s", failure, this));
                        if(diagnostics.determine(failure) == FailureDiagnostics.Type.network) {
                            final int max = Math.max(1, pool.getMaxIdle() - 1);
                            log.warn(String.format("Lower maximum idle pool size to %d connections.", max));
                            pool.setMaxIdle(max);
                            // Clear pool from idle connections
                            pool.clear();
                        }
                        throw failure;
                    }
                    log.error(String.format("Borrowing session from pool %s failed with %s", this, e));
                    throw new DefaultExceptionMappingService().map(cause);
                }
            }
            throw new ConnectionCanceledException();
        }
        catch(BackgroundException e) {
            throw e;
        }
        catch(Exception e) {
            if(e.getCause() instanceof BackgroundException) {
                throw ((BackgroundException) e.getCause());
            }
            throw new BackgroundException(e.getMessage(), e);
        }
    }
@Test(expected = ConnectionRefusedException.class)
    public void testConnectRefuse() throws Exception {
        final DefaultSessionPool pool = new DefaultSessionPool(new TestLoginConnectionService() {
            @Override
            public boolean check(final Session<?> session, final CancelCallback callback) throws BackgroundException {
                throw new ConnectionRefusedException("t", new RuntimeException());
            }
        }, new DisabledX509TrustManager(), new DefaultX509KeyManager(),
            new DefaultVaultRegistry(new DisabledPasswordCallback()), new DisabledTranscriptListener(), new Host(new TestProtocol(), "t"));
        pool.borrow(BackgroundActionState.running);
    }