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:
Oleg Kalnichevski 2013-01-13 17:56:11 +00:00
parent 3a073e8ed8
commit 6a8961cc29
8 changed files with 70 additions and 72 deletions

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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()) {

View File

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

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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(),

View File

@ -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();
}
}