From e9ca02ccffe8a7cc233e107dcd4823fb179ca8d5 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 4 Nov 2012 07:41:01 +0000 Subject: [PATCH] Replaced HttpResponseWrapper with a dynamic proxy git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1405510 13f79535-47bb-0310-9956-ffa450edef68 --- .../client/builder/BackoffStrategyExec.java | 5 +- .../impl/client/builder/ClientExecChain.java | 8 +- .../client/builder/HttpResponseProxy.java | 100 ++++++ .../client/builder/HttpResponseWrapper.java | 290 ------------------ .../impl/client/builder/MainClientExec.java | 7 +- .../impl/client/builder/ProtocolExec.java | 5 +- .../impl/client/builder/RedirectExec.java | 13 +- .../client/builder/ResponseEntityWrapper.java | 136 ++++++++ .../http/impl/client/builder/RetryExec.java | 3 +- .../builder/ServiceUnavailableRetryExec.java | 7 +- 10 files changed, 265 insertions(+), 309 deletions(-) create mode 100644 httpclient/src/main/java/org/apache/http/impl/client/builder/HttpResponseProxy.java delete mode 100644 httpclient/src/main/java/org/apache/http/impl/client/builder/HttpResponseWrapper.java create mode 100644 httpclient/src/main/java/org/apache/http/impl/client/builder/ResponseEntityWrapper.java diff --git a/httpclient/src/main/java/org/apache/http/impl/client/builder/BackoffStrategyExec.java b/httpclient/src/main/java/org/apache/http/impl/client/builder/BackoffStrategyExec.java index 66f099f5d..31521d2cb 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/builder/BackoffStrategyExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/builder/BackoffStrategyExec.java @@ -34,6 +34,7 @@ import org.apache.http.HttpException; import org.apache.http.annotation.ThreadSafe; import org.apache.http.client.BackoffManager; import org.apache.http.client.ConnectionBackoffStrategy; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.protocol.HttpContext; @@ -67,7 +68,7 @@ class BackoffStrategyExec implements ClientExecChain { this.backoffManager = backoffManager; } - public HttpResponseWrapper execute( + public CloseableHttpResponse execute( final HttpRoute route, final HttpRequestWrapper request, final HttpContext context, @@ -81,7 +82,7 @@ class BackoffStrategyExec implements ClientExecChain { if (context == null) { throw new IllegalArgumentException("HTTP context may not be null"); } - HttpResponseWrapper out = null; + CloseableHttpResponse out = null; try { out = this.requestExecutor.execute(route, request, context, execAware); } catch (Exception ex) { diff --git a/httpclient/src/main/java/org/apache/http/impl/client/builder/ClientExecChain.java b/httpclient/src/main/java/org/apache/http/impl/client/builder/ClientExecChain.java index 9e6660bf8..91556d925 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/builder/ClientExecChain.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/builder/ClientExecChain.java @@ -30,6 +30,7 @@ package org.apache.http.impl.client.builder; import java.io.IOException; import org.apache.http.HttpException; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.protocol.HttpContext; @@ -41,15 +42,14 @@ import org.apache.http.protocol.HttpContext; *

* Important: please note it is required for decorators that implement post execution aspects * or response post-processing of any sort to release resources associated with the response - * by calling {@link HttpResponseWrapper#releaseConnection()} or {@link HttpResponseWrapper#close()} - * methods in case of an I/O, protocol or runtime exception, or in case the response is not - * propagated to the caller. + * by calling {@link HttpResponseProxy#close()} methods in case of an I/O, protocol or runtime + * exception, or in case the response is not propagated to the caller. * * @since 4.3 */ interface ClientExecChain { - HttpResponseWrapper execute( + CloseableHttpResponse execute( HttpRoute route, HttpRequestWrapper request, HttpContext context, diff --git a/httpclient/src/main/java/org/apache/http/impl/client/builder/HttpResponseProxy.java b/httpclient/src/main/java/org/apache/http/impl/client/builder/HttpResponseProxy.java new file mode 100644 index 000000000..17aa884ba --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/impl/client/builder/HttpResponseProxy.java @@ -0,0 +1,100 @@ +/* + * ==================================================================== + * 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 + * . + * + */ + +package org.apache.http.impl.client.builder; + +import java.io.IOException; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.annotation.NotThreadSafe; +import org.apache.http.client.methods.CloseableHttpResponse; + +/** + * A proxy class for {@link HttpResponse} that can be used to release client connection + * associated with the original response. + * + * @since 4.3 + */ +@NotThreadSafe +class HttpResponseProxy implements InvocationHandler { + + private final HttpResponse original; + private final ConnectionReleaseTriggerImpl connReleaseTrigger; + + private HttpResponseProxy( + final HttpResponse original, + final ConnectionReleaseTriggerImpl connReleaseTrigger) { + super(); + this.original = original; + this.connReleaseTrigger = connReleaseTrigger; + HttpEntity entity = original.getEntity(); + if (entity != null && entity.isStreaming() && connReleaseTrigger != null) { + this.original.setEntity(new ResponseEntityWrapper(entity, connReleaseTrigger)); + } + } + + public void close() throws IOException { + if (this.connReleaseTrigger != null) { + this.connReleaseTrigger.abortConnection(); + } + } + + public Object invoke( + final Object proxy, final Method method, final Object[] args) throws Throwable { + String mname = method.getName(); + if (mname.equals("close")) { + close(); + return null; + } else { + try { + return method.invoke(original, args); + } catch (InvocationTargetException ex) { + Throwable cause = ex.getCause(); + if (cause != null) { + throw cause; + } else { + throw ex; + } + } + } + } + + public static CloseableHttpResponse newProxy( + final HttpResponse original, + final ConnectionReleaseTriggerImpl connReleaseTrigger) { + return (CloseableHttpResponse) Proxy.newProxyInstance( + HttpResponseProxy.class.getClassLoader(), + new Class[] { CloseableHttpResponse.class }, + new HttpResponseProxy(original, connReleaseTrigger)); + } + +} diff --git a/httpclient/src/main/java/org/apache/http/impl/client/builder/HttpResponseWrapper.java b/httpclient/src/main/java/org/apache/http/impl/client/builder/HttpResponseWrapper.java deleted file mode 100644 index 91b859714..000000000 --- a/httpclient/src/main/java/org/apache/http/impl/client/builder/HttpResponseWrapper.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * ==================================================================== - * 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 - * . - * - */ - -package org.apache.http.impl.client.builder; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.SocketException; -import java.util.Locale; - -import org.apache.http.Header; -import org.apache.http.HeaderIterator; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.ProtocolVersion; -import org.apache.http.StatusLine; -import org.apache.http.annotation.NotThreadSafe; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.conn.ConnectionReleaseTrigger; -import org.apache.http.conn.EofSensorInputStream; -import org.apache.http.conn.EofSensorWatcher; -import org.apache.http.entity.HttpEntityWrapper; -import org.apache.http.params.HttpParams; -import org.apache.http.util.EntityUtils; - -/** - * A wrapper class for {@link HttpResponse} that can be used to manage client connection - * associated with the original response. - * - * @since 4.3 - */ -@NotThreadSafe -class HttpResponseWrapper implements CloseableHttpResponse, ConnectionReleaseTrigger { - - private final HttpResponse original; - private final ConnectionReleaseTriggerImpl connReleaseTrigger; - private HttpEntity entity; - - private HttpResponseWrapper( - final HttpResponse original, - final ConnectionReleaseTriggerImpl connReleaseTrigger) { - super(); - this.original = original; - this.connReleaseTrigger = connReleaseTrigger; - HttpEntity entity = original.getEntity(); - if (connReleaseTrigger != null && entity != null && entity.isStreaming()) { - this.entity = new EntityWrapper(entity); - } - } - - public HttpResponse getOriginal() { - return this.original; - } - - public ProtocolVersion getProtocolVersion() { - return this.original.getProtocolVersion(); - } - - public boolean containsHeader(final String name) { - return this.original.containsHeader(name); - } - - public Header[] getHeaders(final String name) { - return this.original.getHeaders(name); - } - - public Header getFirstHeader(final String name) { - return this.original.getFirstHeader(name); - } - - public Header getLastHeader(final String name) { - return this.original.getLastHeader(name); - } - - public Header[] getAllHeaders() { - return this.original.getAllHeaders(); - } - - public void addHeader(final Header header) { - this.original.addHeader(header); - } - - public void addHeader(final String name, final String value) { - this.original.addHeader(name, value); - } - - public void setHeader(final Header header) { - this.original.setHeader(header); - } - - public void setHeader(String name, String value) { - this.original.setHeader(name, value); - } - - public void setHeaders(final Header[] headers) { - this.original.setHeaders(headers); - } - - public void removeHeader(final Header header) { - this.original.removeHeader(header); - } - - public void removeHeaders(final String name) { - this.original.removeHeaders(name); - } - - public HeaderIterator headerIterator() { - return this.original.headerIterator(); - } - - public HeaderIterator headerIterator(final String name) { - return this.original.headerIterator(name); - } - - public HttpParams getParams() { - return this.original.getParams(); - } - - public void setParams(final HttpParams params) { - this.original.setParams(params); - } - - public StatusLine getStatusLine() { - return this.original.getStatusLine(); - } - - public void setStatusLine(final StatusLine statusline) { - this.original.setStatusLine(statusline); - } - - public void setStatusLine(final ProtocolVersion ver, int code) { - this.original.setStatusLine(ver, code); - } - - public void setStatusLine(final ProtocolVersion ver, int code, final String reason) { - this.original.setStatusLine(ver, code, reason); - } - - public void setStatusCode(int code) throws IllegalStateException { - this.original.setStatusCode(code); - } - - public void setReasonPhrase(final String reason) throws IllegalStateException { - this.original.setReasonPhrase(reason); - } - - public Locale getLocale() { - return this.original.getLocale(); - } - - public void setLocale(final Locale loc) { - this.original.setLocale(loc); - } - - public HttpEntity getEntity() { - return this.entity; - } - - public void setEntity(final HttpEntity entity) { - this.entity = entity; - } - - private void cleanup() throws IOException { - if (this.connReleaseTrigger != null) { - this.connReleaseTrigger.abortConnection(); - } - } - - public void releaseConnection() throws IOException { - if (this.connReleaseTrigger != null) { - try { - if (this.connReleaseTrigger.isReusable()) { - HttpEntity entity = this.original.getEntity(); - if (entity != null) { - EntityUtils.consume(entity); - } - this.connReleaseTrigger.releaseConnection(); - } - } finally { - cleanup(); - } - } - } - - public void abortConnection() throws IOException { - cleanup(); - } - - public void close() throws IOException { - cleanup(); - } - - class EntityWrapper extends HttpEntityWrapper implements EofSensorWatcher { - - public EntityWrapper(final HttpEntity entity) { - super(entity); - } - - @Override - public boolean isRepeatable() { - return false; - } - - @Override - public InputStream getContent() throws IOException { - return new EofSensorInputStream(this.wrappedEntity.getContent(), this); - } - - @Deprecated - @Override - public void consumeContent() throws IOException { - releaseConnection(); - } - - @Override - public void writeTo(final OutputStream outstream) throws IOException { - this.wrappedEntity.writeTo(outstream); - releaseConnection(); - } - - public boolean eofDetected(final InputStream wrapped) throws IOException { - try { - // there may be some cleanup required, such as - // reading trailers after the response body: - wrapped.close(); - releaseConnection(); - } finally { - cleanup(); - } - return false; - } - - public boolean streamClosed(InputStream wrapped) throws IOException { - try { - boolean open = connReleaseTrigger != null && !connReleaseTrigger.isReleased(); - // this assumes that closing the stream will - // consume the remainder of the response body: - try { - wrapped.close(); - releaseConnection(); - } catch (SocketException ex) { - if (open) { - throw ex; - } - } - } finally { - cleanup(); - } - return false; - } - - public boolean streamAbort(InputStream wrapped) throws IOException { - cleanup(); - return false; - } - - } - - public static HttpResponseWrapper wrap( - final HttpResponse response, - final ConnectionReleaseTriggerImpl connReleaseTrigger) { - return new HttpResponseWrapper(response, connReleaseTrigger); - } - -} diff --git a/httpclient/src/main/java/org/apache/http/impl/client/builder/MainClientExec.java b/httpclient/src/main/java/org/apache/http/impl/client/builder/MainClientExec.java index 01dc67286..6828de0f1 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/builder/MainClientExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/builder/MainClientExec.java @@ -49,6 +49,7 @@ import org.apache.http.auth.AuthState; import org.apache.http.client.AuthenticationStrategy; import org.apache.http.client.NonRepeatableRequestException; import org.apache.http.client.UserTokenHandler; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.params.HttpClientParams; import org.apache.http.client.protocol.ClientContext; @@ -167,7 +168,7 @@ class MainClientExec implements ClientExecChain { this.userTokenHandler = userTokenHandler; } - public HttpResponseWrapper execute( + public CloseableHttpResponse execute( final HttpRoute route, final HttpRequestWrapper request, final HttpContext context, @@ -352,9 +353,9 @@ class MainClientExec implements ClientExecChain { if (entity == null || !entity.isStreaming()) { // connection not needed and (assumed to be) in re-usable state releaseTrigger.releaseConnection(); - return HttpResponseWrapper.wrap(response, null); + return HttpResponseProxy.newProxy(response, null); } else { - return HttpResponseWrapper.wrap(response, releaseTrigger); + return HttpResponseProxy.newProxy(response, releaseTrigger); } } catch (ConnectionShutdownException ex) { InterruptedIOException ioex = new InterruptedIOException( diff --git a/httpclient/src/main/java/org/apache/http/impl/client/builder/ProtocolExec.java b/httpclient/src/main/java/org/apache/http/impl/client/builder/ProtocolExec.java index ef204ce49..2f821c52e 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/builder/ProtocolExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/builder/ProtocolExec.java @@ -39,6 +39,7 @@ import org.apache.http.ProtocolException; import org.apache.http.annotation.ThreadSafe; import org.apache.http.auth.AuthState; import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.protocol.ClientContext; import org.apache.http.client.utils.URIUtils; @@ -100,7 +101,7 @@ class ProtocolExec implements ClientExecChain { } } - public HttpResponseWrapper execute( + public CloseableHttpResponse execute( final HttpRoute route, final HttpRequestWrapper request, final HttpContext context, @@ -148,7 +149,7 @@ class ProtocolExec implements ClientExecChain { this.httpProcessor.process(request, context); - HttpResponseWrapper response = this.requestExecutor.execute(route, request, context, execAware); + CloseableHttpResponse response = this.requestExecutor.execute(route, request, context, execAware); try { // Run response protocol interceptors context.setAttribute(ExecutionContext.HTTP_RESPONSE, response); diff --git a/httpclient/src/main/java/org/apache/http/impl/client/builder/RedirectExec.java b/httpclient/src/main/java/org/apache/http/impl/client/builder/RedirectExec.java index 7d6c1118c..43bf28c42 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/builder/RedirectExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/builder/RedirectExec.java @@ -41,6 +41,7 @@ import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthState; import org.apache.http.client.RedirectException; import org.apache.http.client.RedirectStrategy; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.params.ClientPNames; import org.apache.http.client.params.HttpClientParams; @@ -49,6 +50,7 @@ import org.apache.http.conn.routing.HttpRoute; import org.apache.http.conn.routing.HttpRoutePlanner; import org.apache.http.params.HttpParams; import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EntityUtils; /** * The following parameters can be used to customize the behavior of this @@ -89,7 +91,7 @@ class RedirectExec implements ClientExecChain { this.redirectStrategy = redirectStrategy; } - public HttpResponseWrapper execute( + public CloseableHttpResponse execute( final HttpRoute route, final HttpRequestWrapper request, final HttpContext context, @@ -108,7 +110,7 @@ class RedirectExec implements ClientExecChain { HttpRoute currentRoute = route; HttpRequestWrapper currentRequest = request; for (int redirectCount = 0;;) { - HttpResponseWrapper response = requestExecutor.execute( + CloseableHttpResponse response = requestExecutor.execute( currentRoute, currentRequest, context, execAware); try { if (HttpClientParams.isRedirecting(params) && @@ -157,7 +159,8 @@ class RedirectExec implements ClientExecChain { if (this.log.isDebugEnabled()) { this.log.debug("Redirecting to '" + uri + "' via " + currentRoute); } - response.releaseConnection(); + EntityUtils.consume(response.getEntity()); + response.close(); } else { return response; } @@ -171,9 +174,11 @@ class RedirectExec implements ClientExecChain { // Protocol exception related to a direct. // The underlying connection may still be salvaged. try { - response.releaseConnection(); + EntityUtils.consume(response.getEntity()); } catch (IOException ioex) { this.log.debug("I/O error while releasing connection", ioex); + } finally { + response.close(); } throw ex; } diff --git a/httpclient/src/main/java/org/apache/http/impl/client/builder/ResponseEntityWrapper.java b/httpclient/src/main/java/org/apache/http/impl/client/builder/ResponseEntityWrapper.java new file mode 100644 index 000000000..fff998e07 --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/impl/client/builder/ResponseEntityWrapper.java @@ -0,0 +1,136 @@ +/* + * ==================================================================== + * 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 + * . + * + */ + +package org.apache.http.impl.client.builder; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.SocketException; + +import org.apache.http.HttpEntity; +import org.apache.http.annotation.NotThreadSafe; +import org.apache.http.conn.EofSensorInputStream; +import org.apache.http.conn.EofSensorWatcher; +import org.apache.http.entity.HttpEntityWrapper; +import org.apache.http.util.EntityUtils; + +/** + * A wrapper class for {@link HttpEntity} encloded in a response message. + * + * @since 4.3 + */ +@NotThreadSafe +class ResponseEntityWrapper extends HttpEntityWrapper implements EofSensorWatcher { + + private final ConnectionReleaseTriggerImpl connReleaseTrigger; + + public ResponseEntityWrapper( + final HttpEntity entity, + final ConnectionReleaseTriggerImpl connReleaseTrigger) { + super(entity); + this.connReleaseTrigger = connReleaseTrigger; + } + + private void cleanup() throws IOException { + if (this.connReleaseTrigger != null) { + this.connReleaseTrigger.abortConnection(); + } + } + + public void releaseConnection() throws IOException { + if (this.connReleaseTrigger != null) { + try { + if (this.connReleaseTrigger.isReusable()) { + EntityUtils.consume(this.wrappedEntity); + this.connReleaseTrigger.releaseConnection(); + } + } finally { + cleanup(); + } + } + } + + @Override + public boolean isRepeatable() { + return false; + } + + @Override + public InputStream getContent() throws IOException { + return new EofSensorInputStream(this.wrappedEntity.getContent(), this); + } + + @Deprecated + @Override + public void consumeContent() throws IOException { + releaseConnection(); + } + + @Override + public void writeTo(final OutputStream outstream) throws IOException { + this.wrappedEntity.writeTo(outstream); + releaseConnection(); + } + + public boolean eofDetected(final InputStream wrapped) throws IOException { + try { + // there may be some cleanup required, such as + // reading trailers after the response body: + wrapped.close(); + releaseConnection(); + } finally { + cleanup(); + } + return false; + } + + public boolean streamClosed(InputStream wrapped) throws IOException { + try { + boolean open = connReleaseTrigger != null && !connReleaseTrigger.isReleased(); + // this assumes that closing the stream will + // consume the remainder of the response body: + try { + wrapped.close(); + releaseConnection(); + } catch (SocketException ex) { + if (open) { + throw ex; + } + } + } finally { + cleanup(); + } + return false; + } + + public boolean streamAbort(InputStream wrapped) throws IOException { + cleanup(); + return false; + } + +} diff --git a/httpclient/src/main/java/org/apache/http/impl/client/builder/RetryExec.java b/httpclient/src/main/java/org/apache/http/impl/client/builder/RetryExec.java index 4839383bf..30ab88ea0 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/builder/RetryExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/builder/RetryExec.java @@ -37,6 +37,7 @@ import org.apache.http.HttpRequest; import org.apache.http.annotation.NotThreadSafe; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.NonRepeatableRequestException; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.conn.routing.HttpRoute; @@ -66,7 +67,7 @@ class RetryExec implements ClientExecChain { this.retryHandler = retryHandler; } - public HttpResponseWrapper execute( + public CloseableHttpResponse execute( final HttpRoute route, final HttpRequestWrapper request, final HttpContext context, diff --git a/httpclient/src/main/java/org/apache/http/impl/client/builder/ServiceUnavailableRetryExec.java b/httpclient/src/main/java/org/apache/http/impl/client/builder/ServiceUnavailableRetryExec.java index d93b8d9ad..2f7d4ca56 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/builder/ServiceUnavailableRetryExec.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/builder/ServiceUnavailableRetryExec.java @@ -35,6 +35,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.http.HttpException; import org.apache.http.annotation.ThreadSafe; import org.apache.http.client.ServiceUnavailableRetryStrategy; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.protocol.HttpContext; @@ -68,17 +69,17 @@ class ServiceUnavailableRetryExec implements ClientExecChain { this.retryStrategy = retryStrategy; } - public HttpResponseWrapper execute( + public CloseableHttpResponse execute( final HttpRoute route, final HttpRequestWrapper request, final HttpContext context, final HttpExecutionAware execAware) throws IOException, HttpException { for (int c = 1;; c++) { - HttpResponseWrapper response = this.requestExecutor.execute( + CloseableHttpResponse response = this.requestExecutor.execute( route, request, context, execAware); try { if (this.retryStrategy.retryRequest(response, c, context)) { - response.releaseConnection(); + response.close(); long nextInterval = this.retryStrategy.getRetryInterval(); try { this.log.trace("Wait for " + nextInterval);