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);