/** * Tests the MultiThreadedHttpConnectionManager's ability to restrict the maximum number of * connections. */ public void testMaxConnections() { MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); connectionManager.getParams().setDefaultMaxConnectionsPerHost(1); connectionManager.getParams().setMaxTotalConnections(2); HostConfiguration host1 = new HostConfiguration(); host1.setHost("host1", -1, "http"); HostConfiguration host2 = new HostConfiguration(); host2.setHost("host2", -1, "http"); HttpConnection connection1 = connectionManager.getConnection(host1); HttpConnection connection2 = connectionManager.getConnection(host2); try { // this should fail quickly since the connection has not been released connectionManager.getConnectionWithTimeout(host2, 100); fail("ConnectionPoolTimeoutException should not be available"); } catch (ConnectionPoolTimeoutException e) { // this should throw an exception } // release one of the connections connection2.releaseConnection(); connection2 = null; try { // there should be a connection available now connection2 = connectionManager.getConnectionWithTimeout(host2, 100); } catch (ConnectionPoolTimeoutException e) { e.printStackTrace(); fail("a httpConnection should have been available: " + e); } }
/** Tests the MultiThreadedHttpConnectionManager's ability to reclaim unused connections. */ public void testConnectionReclaiming() { MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); connectionManager.getParams().setDefaultMaxConnectionsPerHost(1); connectionManager.getParams().setMaxTotalConnections(1); HostConfiguration host1 = new HostConfiguration(); host1.setHost("host1", -1, "http"); HostConfiguration host2 = new HostConfiguration(); host2.setHost("host2", -1, "http"); HttpConnection connection = connectionManager.getConnection(host1); // now release this connection connection.releaseConnection(); connection = null; try { // the connection from host1 should be reclaimed connection = connectionManager.getConnectionWithTimeout(host2, 100); } catch (ConnectTimeoutException e) { e.printStackTrace(); fail("a httpConnection should have been available: " + e); } }
public void testGetConnection() { MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager(); HostConfiguration hostConfiguration = new HostConfiguration(); hostConfiguration.setHost("www.nosuchserver.com", 80, "http"); // Create a new connection HttpConnection conn = mgr.getConnection(hostConfiguration); // Validate the connection properties assertEquals("Host", "www.nosuchserver.com", conn.getHost()); assertEquals("Port", 80, conn.getPort()); // Release the connection mgr.releaseConnection(conn); // Create a new connection hostConfiguration.setHost("www.nosuchserver.com", -1, "https"); conn = mgr.getConnection(hostConfiguration); // Validate the connection properties assertEquals("Host", "www.nosuchserver.com", conn.getHost()); assertEquals("Port", 443, conn.getPort()); // Release the connection mgr.releaseConnection(conn); // Create a new connection hostConfiguration.setHost("www.nowhere.org", 8080, "http"); conn = mgr.getConnection(hostConfiguration); // Validate the connection properties assertEquals("Host", "www.nowhere.org", conn.getHost()); assertEquals("Port", 8080, conn.getPort()); // Release the connection mgr.releaseConnection(conn); }
/** * Obtem a timeline publica. Nao necessita de autenticacao, basicamente é um GET na URL * http://twitter.com/statuses/public_timeline.xml */ public String getPublicTimeline() throws Exception { HttpClient client = new HttpClient(); // get para obter a timeline publica GetMethod get = new GetMethod("/statuses/public_timeline.xml"); // Criando o host, para onde sera enviada a requisicao HostConfiguration host = client.getHostConfiguration(); host.setHost(new URI("http://twitter.com")); // executando o get na url de timeline publica do twitter client.executeMethod(host, get); // obtendo a resposta return get.getResponseBodyAsString(); }
public void testHostReusePreference() { final MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); connectionManager.getParams().setDefaultMaxConnectionsPerHost(1); connectionManager.getParams().setMaxTotalConnections(1); final HostConfiguration host1 = new HostConfiguration(); host1.setHost("host1", -1, "http"); final HostConfiguration host2 = new HostConfiguration(); host2.setHost("host2", -1, "http"); HttpConnection connection = connectionManager.getConnection(host1); GetConnectionThread getHost1 = new GetConnectionThread(host1, connectionManager, 200); GetConnectionThread getHost2 = new GetConnectionThread(host2, connectionManager, 200); getHost2.start(); getHost1.start(); // give the threads some time to startup try { Thread.sleep(100); } catch (InterruptedException e1) { e1.printStackTrace(); } // after the connection to host1 is released it should be given to getHost1 connection.releaseConnection(); connection = null; try { getHost1.join(); getHost2.join(); } catch (InterruptedException e) { e.printStackTrace(); } assertNotSame( "Connection should have been given to someone", getHost1.getConnection(), getHost2.getConnection()); assertNotNull("Connection should have been given to host1", getHost1.getConnection()); assertNull("Connection should NOT have been given to host2", getHost2.getConnection()); }
public void testTimeout() { MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager(); mgr.getParams().setDefaultMaxConnectionsPerHost(2); try { HostConfiguration hostConfig = new HostConfiguration(); hostConfig.setHost("www.nosuchserver.com", 80, "http"); HttpConnection conn1 = mgr.getConnection(hostConfig); HttpConnection conn2 = mgr.getConnection(hostConfig); HttpConnection conn3 = mgr.getConnectionWithTimeout(hostConfig, 1000); fail("Expected an HttpException."); } catch (ConnectTimeoutException e) { // Expected result } }
/** * Tests that {@link MultiThreadedHttpConnectionManager#shutdown()} closes all resources and makes * the connection manger unusable. */ public void testShutdown() { MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); connectionManager.getParams().setDefaultMaxConnectionsPerHost(1); connectionManager.getParams().setMaxTotalConnections(1); HostConfiguration host1 = new HostConfiguration(); host1.setHost("host1", -1, "http"); // hold on to the only connection HttpConnection connection = connectionManager.getConnection(host1); // wait for a connection on another thread GetConnectionThread getConn = new GetConnectionThread(host1, connectionManager, 0); getConn.start(); connectionManager.shutdown(); // now release this connection, this should close the connection, but have no other effect connection.releaseConnection(); connection = null; try { getConn.join(); } catch (InterruptedException e) { e.printStackTrace(); } // this thread should have caught an exception without getting a connection assertNull("Not connection should have been checked out", getConn.getConnection()); assertNotNull("There should have been an exception", getConn.getException()); try { connectionManager.getConnection(host1); fail("An exception should have occurred"); } catch (Exception e) { // this is expected } }
protected void initHttpClient() { if (MockServer.isTestMode()) { return; } HostConfiguration hostConfiguration = new HostConfiguration(); hostConfiguration.setHost( diamondConfigure.getDomainNameList().get(this.domainNamePos.get()), diamondConfigure.getPort()); MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); connectionManager.closeIdleConnections(diamondConfigure.getPollingIntervalTime() * 10); HttpConnectionManagerParams params = new HttpConnectionManagerParams(); params.setStaleCheckingEnabled(diamondConfigure.isConnectionStaleCheckingEnabled()); params.setMaxConnectionsPerHost(hostConfiguration, diamondConfigure.getMaxHostConnections()); params.setMaxTotalConnections(diamondConfigure.getMaxTotalConnections()); params.setConnectionTimeout(diamondConfigure.getConnectionTimeout()); params.setSoTimeout(60 * 1000); connectionManager.setParams(params); httpClient = new HttpClient(connectionManager); httpClient.setHostConfiguration(hostConfiguration); }
/** * Creates a new HTTP connection for the given host configuration. * * @param hostConfiguration the host/proxy/protocol to use */ public HttpConnection(HostConfiguration hostConfiguration) { this( hostConfiguration.getProxyHost(), hostConfiguration.getProxyPort(), hostConfiguration.getHost(), hostConfiguration.getPort(), hostConfiguration.getProtocol()); this.localAddress = hostConfiguration.getLocalAddress(); }
public void testHostConfiguration() { HostConfiguration hc1 = new HostConfiguration(); hc1.setHost("http", 80, "http"); HostConfiguration hc2 = new HostConfiguration(); hc2.setHost("http", 80, "http"); assertTrue(hc1.equals(hc2)); assertTrue(hc2.equals(hc1)); }
/** * Tests the MultiThreadedHttpConnectionManager's ability to restrict the maximum number of * connections per host. */ public void testMaxConnectionsPerHost() throws Exception { MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); connectionManager.getParams().setDefaultMaxConnectionsPerHost(1); connectionManager.getParams().setMaxTotalConnections(100); HostConfiguration host1 = new HostConfiguration(); host1.setHost("host1", -1, "http"); HostConfiguration host2 = new HostConfiguration(); host2.setHost("host2", -1, "http"); HostConfiguration host3 = new HostConfiguration(); host3.setHost("host3", -1, "http"); connectionManager.getParams().setMaxConnectionsPerHost(host1, 3); connectionManager.getParams().setMaxConnectionsPerHost(host2, 2); // Host1 HttpConnection connection1 = connectionManager.getConnectionWithTimeout(host1, 1000); HttpConnection connection2 = connectionManager.getConnectionWithTimeout(host1, 1000); HttpConnection connection3 = connectionManager.getConnectionWithTimeout(host1, 1000); try { // this should fail quickly since the connection has not been released connectionManager.getConnectionWithTimeout(host1, 100); fail("ConnectionPoolTimeoutException should not be available"); } catch (ConnectionPoolTimeoutException e) { // expected } // Host2 connection1 = connectionManager.getConnectionWithTimeout(host2, 1000); connection2 = connectionManager.getConnectionWithTimeout(host2, 1000); try { // this should fail quickly since the connection has not been released connectionManager.getConnectionWithTimeout(host2, 100); fail("ConnectionPoolTimeoutException should not be available"); } catch (ConnectionPoolTimeoutException e) { // expected } // Host3 (should use the default per host value) connection1 = connectionManager.getConnectionWithTimeout(host3, 1000); try { // this should fail quickly since the connection has not been released connectionManager.getConnectionWithTimeout(host3, 100); fail("ConnectionPoolTimeoutException should not be available"); } catch (ConnectionPoolTimeoutException e) { // expected } }
public HttpConnection getConnection(HostConfiguration hostConfiguration) { // make sure the host and proxy are correct for this connection // close it and set the values if they are not if (!hostConfiguration.hostEquals(connection) || !hostConfiguration.proxyEquals(connection)) { if (connection.isOpen()) { connection.close(); } connection.setHost(hostConfiguration.getHost()); connection.setPort(hostConfiguration.getPort()); connection.setProtocol(hostConfiguration.getProtocol()); connection.setLocalAddress(hostConfiguration.getLocalAddress()); connection.setProxyHost(hostConfiguration.getProxyHost()); connection.setProxyPort(hostConfiguration.getProxyPort()); } else { finishLastResponse(connection); } connectionReleased = false; return connection; }
/** * @param since last modified time to use * @param req * @param url if null, ignored * @param redirCount number of redirs we've done */ public static HttpData getDataOnce( HttpServletRequest req, HttpServletResponse res, long since, String surl, int redirCount, int timeout) throws IOException, HttpException, DataSourceException, MalformedURLException { HttpMethodBase request = null; HostConfiguration hcfg = new HostConfiguration(); /* [todo hqm 2006-02-01] Anyone know why this code was here? It is setting the mime type to something which just confuses the DHTML parser. if (res != null) { res.setContentType("application/x-www-form-urlencoded;charset=UTF-8"); } */ try { // TODO: [2002-01-09 bloch] cope with cache-control // response headers (no-store, no-cache, must-revalidate, // proxy-revalidate). if (surl == null) { surl = getURL(req); } if (surl == null || surl.equals("")) { throw new MalformedURLException( /* (non-Javadoc) * @i18n.test * @org-mes="url is empty or null" */ org.openlaszlo.i18n.LaszloMessages.getMessage( HTTPDataSource.class.getName(), "051018-312")); } String reqType = ""; String headers = ""; if (req != null) { reqType = req.getParameter("reqtype"); headers = req.getParameter("headers"); } boolean isPost = false; mLogger.debug("reqtype = " + reqType); if (reqType != null && reqType.equals("POST")) { request = new LZPostMethod(); request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); isPost = true; mLogger.debug("setting POST req method"); } else if (reqType != null && reqType.equals("PUT")) { request = new LZPutMethod(); // todo [hqm 2007] treat PUT like POST? isPost = true; mLogger.debug("setting PUT req method"); } else if (reqType != null && reqType.equals("DELETE")) { request = new LZDeleteMethod(); mLogger.debug("setting DELETE req method"); } else { mLogger.debug("setting GET (default) req method"); request = new LZGetMethod(); } request.setHttp11(mUseHttp11); // Proxy the request headers if (req != null) { LZHttpUtils.proxyRequestHeaders(req, request); } // Set headers from query string if (headers != null && headers.length() > 0) { StringTokenizer st = new StringTokenizer(headers, "\n"); while (st.hasMoreTokens()) { String h = st.nextToken(); int i = h.indexOf(":"); if (i > -1) { String n = h.substring(0, i); String v = h.substring(i + 2, h.length()); request.setRequestHeader(n, v); mLogger.debug( /* (non-Javadoc) * @i18n.test * @org-mes="setting header " + p[0] + "=" + p[1] */ org.openlaszlo.i18n.LaszloMessages.getMessage( HTTPDataSource.class.getName(), "051018-359", new Object[] {n, v})); } } } mLogger.debug("Parsing url"); URI uri = LZHttpUtils.newURI(surl); try { hcfg.setHost(uri); } catch (Exception e) { throw new MalformedURLException( /* (non-Javadoc) * @i18n.test * @org-mes="can't form uri from " + p[0] */ org.openlaszlo.i18n.LaszloMessages.getMessage( HTTPDataSource.class.getName(), "051018-376", new Object[] {surl})); } // This gets us the url-encoded (escaped) path and query string String path = uri.getEscapedPath(); String query = uri.getEscapedQuery(); mLogger.debug( /* (non-Javadoc) * @i18n.test * @org-mes="encoded path: " + p[0] */ org.openlaszlo.i18n.LaszloMessages.getMessage( HTTPDataSource.class.getName(), "051018-389", new Object[] {path})); mLogger.debug( /* (non-Javadoc) * @i18n.test * @org-mes="encoded query: " + p[0] */ org.openlaszlo.i18n.LaszloMessages.getMessage( HTTPDataSource.class.getName(), "051018-397", new Object[] {query})); // This call takes a decoded (unescaped) path request.setPath(path); boolean hasQuery = (query != null && query.length() > 0); String rawcontent = null; // Newer rawpost protocol puts lzpostbody as a separate // top level query arg in the request. rawcontent = req.getParameter("lzpostbody"); if (isPost) { // Older rawpost protocol put the "lzpostbody" arg // embedded in the "url" args's query args if (rawcontent == null && hasQuery) { rawcontent = findQueryArg("lzpostbody", query); } if (rawcontent != null) { // Get the unescaped query string ((EntityEnclosingMethod) request).setRequestBody(rawcontent); } else if (hasQuery) { StringTokenizer st = new StringTokenizer(query, "&"); while (st.hasMoreTokens()) { String it = st.nextToken(); int i = it.indexOf("="); if (i > 0) { String n = it.substring(0, i); String v = it.substring(i + 1, it.length()); // POST encodes values during request ((PostMethod) request).addParameter(n, URLDecoder.decode(v, "UTF-8")); } else { mLogger.warn( /* (non-Javadoc) * @i18n.test * @org-mes="ignoring bad token (missing '=' char) in query string: " + p[0] */ org.openlaszlo.i18n.LaszloMessages.getMessage( HTTPDataSource.class.getName(), "051018-429", new Object[] {it})); } } } } else { // This call takes an encoded (escaped) query string request.setQueryString(query); } // Put in the If-Modified-Since headers if (since != -1) { String lms = LZHttpUtils.getDateString(since); request.setRequestHeader(LZHttpUtils.IF_MODIFIED_SINCE, lms); mLogger.debug( /* (non-Javadoc) * @i18n.test * @org-mes="proxying lms: " + p[0] */ org.openlaszlo.i18n.LaszloMessages.getMessage( HTTPDataSource.class.getName(), "051018-450", new Object[] {lms})); } mLogger.debug( /* (non-Javadoc) * @i18n.test * @org-mes="setting up http client" */ org.openlaszlo.i18n.LaszloMessages.getMessage( HTTPDataSource.class.getName(), "051018-460")); HttpClient htc = null; if (mConnectionMgr != null) { htc = new HttpClient(mConnectionMgr); } else { htc = new HttpClient(); } htc.setHostConfiguration(hcfg); // This is the data timeout mLogger.debug( /* (non-Javadoc) * @i18n.test * @org-mes="timeout set to " + p[0] */ org.openlaszlo.i18n.LaszloMessages.getMessage( HTTPDataSource.class.getName(), "051018-478", new Object[] {new Integer(timeout)})); htc.setTimeout(timeout); // Set connection timeout the same htc.setConnectionTimeout(mConnectionTimeout); // Set timeout for getting a connection htc.setHttpConnectionFactoryTimeout(mConnectionPoolTimeout); // TODO: [2003-03-05 bloch] this should be more configurable (per app?) if (!isPost) { request.setFollowRedirects(mFollowRedirects > 0); } long t1 = System.currentTimeMillis(); mLogger.debug("starting remote request"); int rc = htc.executeMethod(hcfg, request); String status = HttpStatus.getStatusText(rc); if (status == null) { status = "" + rc; } mLogger.debug( /* (non-Javadoc) * @i18n.test * @org-mes="remote response status: " + p[0] */ org.openlaszlo.i18n.LaszloMessages.getMessage( HTTPDataSource.class.getName(), "051018-504", new Object[] {status})); HttpData data = null; if (isRedirect(rc) && mFollowRedirects > redirCount) { String loc = request.getResponseHeader("Location").toString(); String hostURI = loc.substring(loc.indexOf(": ") + 2, loc.length()); mLogger.info( /* (non-Javadoc) * @i18n.test * @org-mes="Following URL from redirect: " + p[0] */ org.openlaszlo.i18n.LaszloMessages.getMessage( HTTPDataSource.class.getName(), "051018-517", new Object[] {hostURI})); long t2 = System.currentTimeMillis(); if (timeout > 0) { timeout -= (t2 - t1); if (timeout < 0) { throw new InterruptedIOException( /* (non-Javadoc) * @i18n.test * @org-mes=p[0] + " timed out after redirecting to " + p[1] */ org.openlaszlo.i18n.LaszloMessages.getMessage( HTTPDataSource.class.getName(), "051018-529", new Object[] {surl, loc})); } } data = getDataOnce(req, res, since, hostURI, redirCount++, timeout); } else { data = new HttpData(request, rc); } if (req != null && res != null) { // proxy response headers LZHttpUtils.proxyResponseHeaders(request, res, req.isSecure()); } return data; } catch (ConnectTimeoutException ce) { // Transduce to an InterrupedIOException, since lps takes these to be timeouts. if (request != null) { request.releaseConnection(); } throw new InterruptedIOException( /* (non-Javadoc) * @i18n.test * @org-mes="connecting to " + p[0] + ":" + p[1] + " timed out beyond " + p[2] + " msecs." */ org.openlaszlo.i18n.LaszloMessages.getMessage( HTTPDataSource.class.getName(), "051018-557", new Object[] { hcfg.getHost(), new Integer(hcfg.getPort()), new Integer(mConnectionTimeout) })); } catch (HttpRecoverableException hre) { if (request != null) { request.releaseConnection(); } throw hre; } catch (HttpException e) { if (request != null) { request.releaseConnection(); } throw e; } catch (IOException ie) { if (request != null) { request.releaseConnection(); } throw ie; } catch (RuntimeException e) { if (request != null) { request.releaseConnection(); } throw e; } }
/** * Process the redirect response. * * @return <code>true</code> if the redirect was successful */ private boolean processRedirectResponse(final HttpMethod method) throws RedirectException { // get the location header to find out where to redirect to Header locationHeader = method.getResponseHeader("location"); if (locationHeader == null) { // got a redirect response, but no location header LOG.error("Received redirect response " + method.getStatusCode() + " but no location header"); return false; } String location = locationHeader.getValue(); if (LOG.isDebugEnabled()) { LOG.debug("Redirect requested to location '" + location + "'"); } // rfc2616 demands the location value be a complete URI // Location = "Location" ":" absoluteURI URI redirectUri = null; URI currentUri = null; try { currentUri = new URI( this.conn.getProtocol().getScheme(), null, this.conn.getHost(), this.conn.getPort(), method.getPath()); String charset = method.getParams().getUriCharset(); redirectUri = new URI(location, true, charset); if (redirectUri.isRelativeURI()) { if (this.params.isParameterTrue(HttpClientParams.REJECT_RELATIVE_REDIRECT)) { LOG.warn("Relative redirect location '" + location + "' not allowed"); return false; } else { // location is incomplete, use current values for defaults LOG.debug("Redirect URI is not absolute - parsing as relative"); redirectUri = new URI(currentUri, redirectUri); } } else { // Reset the default params method.getParams().setDefaults(this.params); } method.setURI(redirectUri); hostConfiguration.setHost(redirectUri); } catch (URIException ex) { throw new InvalidRedirectLocationException( "Invalid redirect location: " + location, location, ex); } if (this.params.isParameterFalse(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS)) { if (this.redirectLocations == null) { this.redirectLocations = new HashSet(); } this.redirectLocations.add(currentUri); try { if (redirectUri.hasQuery()) { redirectUri.setQuery(null); } } catch (URIException e) { // Should never happen return false; } if (this.redirectLocations.contains(redirectUri)) { throw new CircularRedirectException("Circular redirect to '" + redirectUri + "'"); } } if (LOG.isDebugEnabled()) { LOG.debug( "Redirecting from '" + currentUri.getEscapedURI() + "' to '" + redirectUri.getEscapedURI()); } // And finally invalidate the actual authentication scheme method.getHostAuthState().invalidate(); return true; }
/** * Executes the method associated with this method director. * * @throws IOException * @throws HttpException */ public void executeMethod(final HttpMethod method) throws IOException, HttpException { if (method == null) { throw new IllegalArgumentException("Method may not be null"); } // Link all parameter collections to form the hierarchy: // Global -> HttpClient -> HostConfiguration -> HttpMethod this.hostConfiguration.getParams().setDefaults(this.params); method.getParams().setDefaults(this.hostConfiguration.getParams()); // Generate default request headers Collection defaults = (Collection) this.hostConfiguration.getParams().getParameter(HostParams.DEFAULT_HEADERS); if (defaults != null) { Iterator i = defaults.iterator(); while (i.hasNext()) { method.addRequestHeader((Header) i.next()); } } try { int maxRedirects = this.params.getIntParameter(HttpClientParams.MAX_REDIRECTS, 100); for (int redirectCount = 0; ; ) { // make sure the connection we have is appropriate if (this.conn != null && !hostConfiguration.hostEquals(this.conn)) { this.conn.setLocked(false); this.conn.releaseConnection(); this.conn = null; } // get a connection, if we need one if (this.conn == null) { this.conn = connectionManager.getConnectionWithTimeout( hostConfiguration, this.params.getConnectionManagerTimeout()); this.conn.setLocked(true); if (this.params.isAuthenticationPreemptive() || this.state.isAuthenticationPreemptive()) { LOG.debug("Preemptively sending default basic credentials"); method.getHostAuthState().setPreemptive(); method.getHostAuthState().setAuthAttempted(true); if (this.conn.isProxied() && !this.conn.isSecure()) { method.getProxyAuthState().setPreemptive(); method.getProxyAuthState().setAuthAttempted(true); } } } authenticate(method); executeWithRetry(method); if (this.connectMethod != null) { fakeResponse(method); break; } boolean retry = false; if (isRedirectNeeded(method)) { if (processRedirectResponse(method)) { retry = true; ++redirectCount; if (redirectCount >= maxRedirects) { LOG.error("Narrowly avoided an infinite loop in execute"); throw new RedirectException("Maximum redirects (" + maxRedirects + ") exceeded"); } if (LOG.isDebugEnabled()) { LOG.debug("Execute redirect " + redirectCount + " of " + maxRedirects); } } } if (isAuthenticationNeeded(method)) { if (processAuthenticationResponse(method)) { LOG.debug("Retry authentication"); retry = true; } } if (!retry) { break; } // retry - close previous stream. Caution - this causes // responseBodyConsumed to be called, which may also close the // connection. if (method.getResponseBodyAsStream() != null) { method.getResponseBodyAsStream().close(); } } // end of retry loop } finally { if (this.conn != null) { this.conn.setLocked(false); } // If the response has been fully processed, return the connection // to the pool. Use this flag, rather than other tests (like // responseStream == null), as subclasses, might reset the stream, // for example, reading the entire response into a file and then // setting the file as the stream. if ((releaseConnection || method.getResponseBodyAsStream() == null) && this.conn != null) { this.conn.releaseConnection(); } } }