Renamed ConnectionReleaseTriggerImpl to ConnectionHolder
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1432677 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3a073e8ed8
commit
6a8961cc29
|
@ -39,12 +39,12 @@ import org.apache.http.conn.ConnectionReleaseTrigger;
|
|||
import org.apache.http.conn.HttpClientConnectionManager;
|
||||
|
||||
/**
|
||||
* Internal {@link ConnectionReleaseTrigger} implementation.
|
||||
* Internal connection holder.
|
||||
*
|
||||
* @since 4.3
|
||||
*/
|
||||
@ThreadSafe
|
||||
class ConnectionReleaseTriggerImpl implements ConnectionReleaseTrigger, Cancellable, Closeable {
|
||||
class ConnectionHolder implements ConnectionReleaseTrigger, Cancellable, Closeable {
|
||||
|
||||
private final Log log;
|
||||
|
||||
|
@ -57,7 +57,7 @@ class ConnectionReleaseTriggerImpl implements ConnectionReleaseTrigger, Cancella
|
|||
|
||||
private volatile boolean released;
|
||||
|
||||
public ConnectionReleaseTriggerImpl(
|
||||
public ConnectionHolder(
|
||||
final Log log,
|
||||
final HttpClientConnectionManager manager,
|
||||
final HttpClientConnection managedConn) {
|
|
@ -186,15 +186,14 @@ public class MainClientExec implements ClientExecChain {
|
|||
}
|
||||
}
|
||||
|
||||
ConnectionReleaseTriggerImpl releaseTrigger = new ConnectionReleaseTriggerImpl(
|
||||
this.log, this.connManager, managedConn);
|
||||
ConnectionHolder connHolder = new ConnectionHolder(this.log, this.connManager, managedConn);
|
||||
try {
|
||||
if (execAware != null) {
|
||||
if (execAware.isAborted()) {
|
||||
releaseTrigger.abortConnection();
|
||||
connHolder.abortConnection();
|
||||
throw new RequestAbortedException("Request aborted");
|
||||
} else {
|
||||
execAware.setCancellable(releaseTrigger);
|
||||
execAware.setCancellable(connHolder);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -264,15 +263,15 @@ public class MainClientExec implements ClientExecChain {
|
|||
}
|
||||
this.log.debug("Connection can be kept alive " + s);
|
||||
}
|
||||
releaseTrigger.setValidFor(duration, TimeUnit.MILLISECONDS);
|
||||
releaseTrigger.markReusable();
|
||||
connHolder.setValidFor(duration, TimeUnit.MILLISECONDS);
|
||||
connHolder.markReusable();
|
||||
} else {
|
||||
releaseTrigger.markNonReusable();
|
||||
connHolder.markNonReusable();
|
||||
}
|
||||
|
||||
if (needAuthentication(
|
||||
targetAuthState, proxyAuthState, route, request, response, context)) {
|
||||
if (releaseTrigger.isReusable()) {
|
||||
if (connHolder.isReusable()) {
|
||||
// Make sure the response body is fully consumed, if present
|
||||
HttpEntity entity = response.getEntity();
|
||||
EntityUtils.consume(entity);
|
||||
|
@ -306,17 +305,17 @@ public class MainClientExec implements ClientExecChain {
|
|||
context.setAttribute(ClientContext.USER_TOKEN, userToken);
|
||||
}
|
||||
if (userToken != null) {
|
||||
releaseTrigger.setState(userToken);
|
||||
connHolder.setState(userToken);
|
||||
}
|
||||
|
||||
// check for entity, release connection if possible
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity == null || !entity.isStreaming()) {
|
||||
// connection not needed and (assumed to be) in re-usable state
|
||||
releaseTrigger.releaseConnection();
|
||||
connHolder.releaseConnection();
|
||||
return Proxies.enhanceResponse(response, null);
|
||||
} else {
|
||||
return Proxies.enhanceResponse(response, releaseTrigger);
|
||||
return Proxies.enhanceResponse(response, connHolder);
|
||||
}
|
||||
} catch (ConnectionShutdownException ex) {
|
||||
InterruptedIOException ioex = new InterruptedIOException(
|
||||
|
@ -324,13 +323,13 @@ public class MainClientExec implements ClientExecChain {
|
|||
ioex.initCause(ex);
|
||||
throw ioex;
|
||||
} catch (HttpException ex) {
|
||||
releaseTrigger.abortConnection();
|
||||
connHolder.abortConnection();
|
||||
throw ex;
|
||||
} catch (IOException ex) {
|
||||
releaseTrigger.abortConnection();
|
||||
connHolder.abortConnection();
|
||||
throw ex;
|
||||
} catch (RuntimeException ex) {
|
||||
releaseTrigger.abortConnection();
|
||||
connHolder.abortConnection();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,8 +132,7 @@ public class MinimalClientExec implements ClientExecChain {
|
|||
throw new RequestAbortedException("Request aborted", interrupted);
|
||||
}
|
||||
|
||||
ConnectionReleaseTriggerImpl releaseTrigger = new ConnectionReleaseTriggerImpl(
|
||||
log, connManager, managedConn);
|
||||
ConnectionHolder releaseTrigger = new ConnectionHolder(log, connManager, managedConn);
|
||||
try {
|
||||
if (execAware != null) {
|
||||
if (execAware.isAborted()) {
|
||||
|
|
|
@ -83,11 +83,11 @@ class Proxies {
|
|||
|
||||
public static CloseableHttpResponse enhanceResponse(
|
||||
final HttpResponse original,
|
||||
final ConnectionReleaseTriggerImpl connReleaseTrigger) {
|
||||
final ConnectionHolder connHolder) {
|
||||
return (CloseableHttpResponse) Proxy.newProxyInstance(
|
||||
ResponseProxyHandler.class.getClassLoader(),
|
||||
new Class<?>[] { CloseableHttpResponse.class },
|
||||
new ResponseProxyHandler(original, connReleaseTrigger));
|
||||
new ResponseProxyHandler(original, connHolder));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,11 +46,11 @@ import org.apache.http.entity.HttpEntityWrapper;
|
|||
@NotThreadSafe
|
||||
class ResponseEntityWrapper extends HttpEntityWrapper implements EofSensorWatcher {
|
||||
|
||||
private final ConnectionReleaseTriggerImpl connReleaseTrigger;
|
||||
private final ConnectionHolder connReleaseTrigger;
|
||||
|
||||
public ResponseEntityWrapper(
|
||||
final HttpEntity entity,
|
||||
final ConnectionReleaseTriggerImpl connReleaseTrigger) {
|
||||
final ConnectionHolder connReleaseTrigger) {
|
||||
super(entity);
|
||||
this.connReleaseTrigger = connReleaseTrigger;
|
||||
}
|
||||
|
|
|
@ -57,23 +57,23 @@ class ResponseProxyHandler implements InvocationHandler {
|
|||
}
|
||||
|
||||
private final HttpResponse original;
|
||||
private final ConnectionReleaseTriggerImpl connReleaseTrigger;
|
||||
private final ConnectionHolder connHolder;
|
||||
|
||||
ResponseProxyHandler(
|
||||
final HttpResponse original,
|
||||
final ConnectionReleaseTriggerImpl connReleaseTrigger) {
|
||||
final ConnectionHolder connHolder) {
|
||||
super();
|
||||
this.original = original;
|
||||
this.connReleaseTrigger = connReleaseTrigger;
|
||||
this.connHolder = connHolder;
|
||||
HttpEntity entity = original.getEntity();
|
||||
if (entity != null && entity.isStreaming() && connReleaseTrigger != null) {
|
||||
this.original.setEntity(new ResponseEntityWrapper(entity, connReleaseTrigger));
|
||||
if (entity != null && entity.isStreaming() && connHolder != null) {
|
||||
this.original.setEntity(new ResponseEntityWrapper(entity, connHolder));
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (this.connReleaseTrigger != null) {
|
||||
this.connReleaseTrigger.abortConnection();
|
||||
if (this.connHolder != null) {
|
||||
this.connHolder.abortConnection();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,31 +38,31 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
public class TestConnectionReleaseTriggerImpl {
|
||||
public class TestConnectionHolder {
|
||||
|
||||
private Log log;
|
||||
private HttpClientConnectionManager mgr;
|
||||
private HttpClientConnection conn;
|
||||
private ConnectionReleaseTriggerImpl releaseTrigger;
|
||||
private ConnectionHolder connHolder;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
log = Mockito.mock(Log.class);
|
||||
mgr = Mockito.mock(HttpClientConnectionManager.class);
|
||||
conn = Mockito.mock(HttpClientConnection.class);
|
||||
releaseTrigger = new ConnectionReleaseTriggerImpl(log, mgr, conn);
|
||||
connHolder = new ConnectionHolder(log, mgr, conn);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbortConnection() throws Exception {
|
||||
releaseTrigger.abortConnection();
|
||||
connHolder.abortConnection();
|
||||
|
||||
Assert.assertTrue(releaseTrigger.isReleased());
|
||||
Assert.assertTrue(connHolder.isReleased());
|
||||
|
||||
Mockito.verify(conn).shutdown();
|
||||
Mockito.verify(mgr).releaseConnection(conn, null, 0, TimeUnit.MILLISECONDS);
|
||||
|
||||
releaseTrigger.abortConnection();
|
||||
connHolder.abortConnection();
|
||||
|
||||
Mockito.verify(conn, Mockito.times(1)).shutdown();
|
||||
Mockito.verify(mgr, Mockito.times(1)).releaseConnection(
|
||||
|
@ -76,9 +76,9 @@ public class TestConnectionReleaseTriggerImpl {
|
|||
public void testAbortConnectionIOError() throws Exception {
|
||||
Mockito.doThrow(new IOException()).when(conn).shutdown();
|
||||
|
||||
releaseTrigger.abortConnection();
|
||||
connHolder.abortConnection();
|
||||
|
||||
Assert.assertTrue(releaseTrigger.isReleased());
|
||||
Assert.assertTrue(connHolder.isReleased());
|
||||
|
||||
Mockito.verify(conn).shutdown();
|
||||
Mockito.verify(mgr).releaseConnection(conn, null, 0, TimeUnit.MILLISECONDS);
|
||||
|
@ -86,14 +86,14 @@ public class TestConnectionReleaseTriggerImpl {
|
|||
|
||||
@Test
|
||||
public void testCancell() throws Exception {
|
||||
Assert.assertTrue(releaseTrigger.cancel());
|
||||
Assert.assertTrue(connHolder.cancel());
|
||||
|
||||
Assert.assertTrue(releaseTrigger.isReleased());
|
||||
Assert.assertTrue(connHolder.isReleased());
|
||||
|
||||
Mockito.verify(conn).shutdown();
|
||||
Mockito.verify(mgr).releaseConnection(conn, null, 0, TimeUnit.MILLISECONDS);
|
||||
|
||||
Assert.assertFalse(releaseTrigger.cancel());
|
||||
Assert.assertFalse(connHolder.cancel());
|
||||
|
||||
Mockito.verify(conn, Mockito.times(1)).shutdown();
|
||||
Mockito.verify(mgr, Mockito.times(1)).releaseConnection(
|
||||
|
@ -105,18 +105,18 @@ public class TestConnectionReleaseTriggerImpl {
|
|||
|
||||
@Test
|
||||
public void testReleaseConnectionReusable() throws Exception {
|
||||
releaseTrigger.setState("some state");
|
||||
releaseTrigger.setValidFor(100, TimeUnit.SECONDS);
|
||||
releaseTrigger.markReusable();
|
||||
connHolder.setState("some state");
|
||||
connHolder.setValidFor(100, TimeUnit.SECONDS);
|
||||
connHolder.markReusable();
|
||||
|
||||
releaseTrigger.releaseConnection();
|
||||
connHolder.releaseConnection();
|
||||
|
||||
Assert.assertTrue(releaseTrigger.isReleased());
|
||||
Assert.assertTrue(connHolder.isReleased());
|
||||
|
||||
Mockito.verify(conn, Mockito.never()).close();
|
||||
Mockito.verify(mgr).releaseConnection(conn, "some state", 100, TimeUnit.SECONDS);
|
||||
|
||||
releaseTrigger.releaseConnection();
|
||||
connHolder.releaseConnection();
|
||||
|
||||
Mockito.verify(mgr, Mockito.times(1)).releaseConnection(
|
||||
Mockito.<HttpClientConnection>any(),
|
||||
|
@ -127,18 +127,18 @@ public class TestConnectionReleaseTriggerImpl {
|
|||
|
||||
@Test
|
||||
public void testReleaseConnectionNonReusable() throws Exception {
|
||||
releaseTrigger.setState("some state");
|
||||
releaseTrigger.setValidFor(100, TimeUnit.SECONDS);
|
||||
releaseTrigger.markNonReusable();
|
||||
connHolder.setState("some state");
|
||||
connHolder.setValidFor(100, TimeUnit.SECONDS);
|
||||
connHolder.markNonReusable();
|
||||
|
||||
releaseTrigger.releaseConnection();
|
||||
connHolder.releaseConnection();
|
||||
|
||||
Assert.assertTrue(releaseTrigger.isReleased());
|
||||
Assert.assertTrue(connHolder.isReleased());
|
||||
|
||||
Mockito.verify(conn, Mockito.times(1)).close();
|
||||
Mockito.verify(mgr).releaseConnection(conn, null, 0, TimeUnit.MILLISECONDS);
|
||||
|
||||
releaseTrigger.releaseConnection();
|
||||
connHolder.releaseConnection();
|
||||
|
||||
Mockito.verify(mgr, Mockito.times(1)).releaseConnection(
|
||||
Mockito.<HttpClientConnection>any(),
|
|
@ -43,7 +43,7 @@ public class TestResponseEntityWrapper {
|
|||
|
||||
private InputStream instream;
|
||||
private HttpEntity entity;
|
||||
private ConnectionReleaseTriggerImpl releaseTrigger;
|
||||
private ConnectionHolder connHolder;
|
||||
private ResponseEntityWrapper wrapper;
|
||||
|
||||
@Before
|
||||
|
@ -51,83 +51,83 @@ public class TestResponseEntityWrapper {
|
|||
instream = Mockito.mock(InputStream.class);
|
||||
entity = Mockito.mock(HttpEntity.class);
|
||||
Mockito.when(entity.getContent()).thenReturn(instream);
|
||||
releaseTrigger = Mockito.mock(ConnectionReleaseTriggerImpl.class);
|
||||
wrapper = new ResponseEntityWrapper(entity, releaseTrigger);
|
||||
connHolder = Mockito.mock(ConnectionHolder.class);
|
||||
wrapper = new ResponseEntityWrapper(entity, connHolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReusableEntityStreamClosed() throws Exception {
|
||||
Mockito.when(entity.isStreaming()).thenReturn(true);
|
||||
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
|
||||
Mockito.when(connHolder.isReusable()).thenReturn(true);
|
||||
EntityUtils.consume(wrapper);
|
||||
|
||||
Mockito.verify(instream, Mockito.times(1)).close();
|
||||
Mockito.verify(releaseTrigger).releaseConnection();
|
||||
Mockito.verify(connHolder).releaseConnection();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReusableEntityStreamClosedIOError() throws Exception {
|
||||
Mockito.when(entity.isStreaming()).thenReturn(true);
|
||||
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
|
||||
Mockito.when(connHolder.isReusable()).thenReturn(true);
|
||||
Mockito.doThrow(new IOException()).when(instream).close();
|
||||
try {
|
||||
EntityUtils.consume(wrapper);
|
||||
Assert.fail("IOException expected");
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
Mockito.verify(releaseTrigger).abortConnection();
|
||||
Mockito.verify(connHolder).abortConnection();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEntityStreamClosedIOErrorAlreadyReleased() throws Exception {
|
||||
Mockito.when(entity.isStreaming()).thenReturn(true);
|
||||
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
|
||||
Mockito.when(releaseTrigger.isReleased()).thenReturn(true);
|
||||
Mockito.when(connHolder.isReusable()).thenReturn(true);
|
||||
Mockito.when(connHolder.isReleased()).thenReturn(true);
|
||||
Mockito.doThrow(new SocketException()).when(instream).close();
|
||||
EntityUtils.consume(wrapper);
|
||||
Mockito.verify(releaseTrigger).abortConnection();
|
||||
Mockito.verify(connHolder).abortConnection();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReusableEntityWriteTo() throws Exception {
|
||||
OutputStream outstream = Mockito.mock(OutputStream.class);
|
||||
Mockito.when(entity.isStreaming()).thenReturn(true);
|
||||
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
|
||||
Mockito.when(connHolder.isReusable()).thenReturn(true);
|
||||
wrapper.writeTo(outstream);
|
||||
Mockito.verify(releaseTrigger).releaseConnection();
|
||||
Mockito.verify(connHolder).releaseConnection();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReusableEntityWriteToIOError() throws Exception {
|
||||
OutputStream outstream = Mockito.mock(OutputStream.class);
|
||||
Mockito.when(entity.isStreaming()).thenReturn(true);
|
||||
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
|
||||
Mockito.when(connHolder.isReusable()).thenReturn(true);
|
||||
Mockito.doThrow(new IOException()).when(entity).writeTo(outstream);
|
||||
try {
|
||||
wrapper.writeTo(outstream);
|
||||
Assert.fail("IOException expected");
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
Mockito.verify(releaseTrigger, Mockito.never()).releaseConnection();
|
||||
Mockito.verify(releaseTrigger).abortConnection();
|
||||
Mockito.verify(connHolder, Mockito.never()).releaseConnection();
|
||||
Mockito.verify(connHolder).abortConnection();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReusableEntityEndOfStream() throws Exception {
|
||||
Mockito.when(instream.read()).thenReturn(-1);
|
||||
Mockito.when(entity.isStreaming()).thenReturn(true);
|
||||
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
|
||||
Mockito.when(connHolder.isReusable()).thenReturn(true);
|
||||
InputStream content = wrapper.getContent();
|
||||
Assert.assertEquals(-1, content.read());
|
||||
Mockito.verify(instream).close();
|
||||
Mockito.verify(releaseTrigger).releaseConnection();
|
||||
Mockito.verify(connHolder).releaseConnection();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReusableEntityEndOfStreamIOError() throws Exception {
|
||||
Mockito.when(instream.read()).thenReturn(-1);
|
||||
Mockito.when(entity.isStreaming()).thenReturn(true);
|
||||
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
|
||||
Mockito.when(connHolder.isReusable()).thenReturn(true);
|
||||
Mockito.doThrow(new IOException()).when(instream).close();
|
||||
InputStream content = wrapper.getContent();
|
||||
try {
|
||||
|
@ -135,7 +135,7 @@ public class TestResponseEntityWrapper {
|
|||
Assert.fail("IOException expected");
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
Mockito.verify(releaseTrigger).abortConnection();
|
||||
Mockito.verify(connHolder).abortConnection();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue