diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/AbstractClientConnAdapter.java b/httpclient/src/main/java/org/apache/http/impl/conn/AbstractClientConnAdapter.java
index 19f9fee72..802af2489 100644
--- a/httpclient/src/main/java/org/apache/http/impl/conn/AbstractClientConnAdapter.java
+++ b/httpclient/src/main/java/org/apache/http/impl/conn/AbstractClientConnAdapter.java
@@ -66,7 +66,10 @@ import org.apache.http.protocol.HttpContext;
* expected to tolerate multiple calls to the release method.
*
* @since 4.0
+ *
+ * @deprecated do not use
*/
+@Deprecated
@NotThreadSafe
public abstract class AbstractClientConnAdapter implements ManagedClientConnection, HttpContext {
diff --git a/httpclient/src/test/java/org/apache/http/impl/client/TestAbortHandling.java b/httpclient/src/test/java/org/apache/http/impl/client/TestAbortHandling.java
deleted file mode 100644
index fb105e42d..000000000
--- a/httpclient/src/test/java/org/apache/http/impl/client/TestAbortHandling.java
+++ /dev/null
@@ -1,108 +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;
-
-import java.io.IOException;
-import java.util.concurrent.CountDownLatch;
-
-import org.apache.http.HttpException;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.localserver.BasicServerTestBase;
-import org.apache.http.localserver.LocalTestServer;
-import org.apache.http.protocol.BasicHttpContext;
-import org.apache.http.protocol.ExecutionContext;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.protocol.HttpRequestHandler;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Tests for Abort handling.
- */
-public class TestAbortHandling extends BasicServerTestBase {
-
- @Before
- public void setUp() throws Exception {
- this.localServer = new LocalTestServer(null, null);
- this.localServer.registerDefaultHandlers();
- this.localServer.start();
- this.httpclient = new DefaultHttpClient();
- }
-
- @Test
- public void testAbortRetry_HTTPCLIENT_1120() throws Exception {
- int port = this.localServer.getServiceAddress().getPort();
- final CountDownLatch wait = new CountDownLatch(1);
-
- this.localServer.register("*", new HttpRequestHandler(){
- public void handle(HttpRequest request, HttpResponse response,
- HttpContext context) throws HttpException, IOException {
- try {
- wait.countDown(); // trigger abort
- Thread.sleep(2000); // allow time for abort to happen
- response.setStatusCode(HttpStatus.SC_OK);
- StringEntity entity = new StringEntity("Whatever");
- response.setEntity(entity);
- } catch (Exception e) {
- response.setStatusCode(HttpStatus.SC_REQUEST_TIMEOUT);
- }
- }});
-
- String s = "http://localhost:" + port + "/path";
- final HttpGet httpget = new HttpGet(s);
-
- Thread t = new Thread() {
- @Override
- public void run(){
- try {
- wait.await();
- } catch (InterruptedException e) {
- }
- httpget.abort();
- }
- };
-
- t.start();
-
- HttpContext context = new BasicHttpContext();
- try {
- this.httpclient.execute(getServerHttp(), httpget, context);
- } catch (IOException e) {
- }
-
- HttpRequest reqWrapper = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
- Assert.assertNotNull("Request should exist",reqWrapper);
- Assert.assertEquals(1,((RequestWrapper) reqWrapper).getExecCount());
- }
-
- // TODO add similar test for connection abort
-}
diff --git a/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultClientRequestDirector.java b/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultClientRequestDirector.java
index a03757967..0afe4c233 100644
--- a/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultClientRequestDirector.java
+++ b/httpclient/src/test/java/org/apache/http/impl/client/TestDefaultClientRequestDirector.java
@@ -27,10 +27,6 @@ package org.apache.http.impl.client;
import java.io.ByteArrayInputStream;
import java.io.IOException;
-import java.net.ConnectException;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
import org.apache.http.Header;
import org.apache.http.HttpClientConnection;
@@ -40,33 +36,16 @@ import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
-import org.apache.http.ProtocolVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.NonRepeatableRequestException;
-import org.apache.http.client.methods.AbortableHttpRequest;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.ClientConnectionRequest;
-import org.apache.http.conn.ConnectionPoolTimeoutException;
-import org.apache.http.conn.ConnectionReleaseTrigger;
-import org.apache.http.conn.ManagedClientConnection;
-import org.apache.http.conn.routing.HttpRoute;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.conn.ClientConnAdapterMockup;
-import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.localserver.BasicServerTestBase;
import org.apache.http.localserver.LocalTestServer;
-import org.apache.http.message.BasicHeader;
-import org.apache.http.mockup.SocketFactoryMockup;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
@@ -90,441 +69,6 @@ public class TestDefaultClientRequestDirector extends BasicServerTestBase {
this.httpclient = new DefaultHttpClient();
}
- /**
- * Tests that if abort is called on an {@link AbortableHttpRequest} while
- * {@link DefaultRequestDirector} is allocating a connection, that the
- * connection is properly aborted.
- */
- @Test
- public void testAbortInAllocate() throws Exception {
- CountDownLatch connLatch = new CountDownLatch(1);
- CountDownLatch awaitLatch = new CountDownLatch(1);
- final ConMan conMan = new ConMan(connLatch, awaitLatch);
- final AtomicReference throwableRef = new AtomicReference();
- final CountDownLatch getLatch = new CountDownLatch(1);
- final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
- final HttpContext context = new BasicHttpContext();
- final HttpGet httpget = new HttpGet("http://www.example.com/a");
-
- new Thread(new Runnable() {
- public void run() {
- try {
- client.execute(httpget, context);
- } catch(Throwable t) {
- throwableRef.set(t);
- } finally {
- getLatch.countDown();
- }
- }
- }).start();
-
- Assert.assertTrue("should have tried to get a connection", connLatch.await(1, TimeUnit.SECONDS));
-
- httpget.abort();
-
- Assert.assertTrue("should have finished get request", getLatch.await(1, TimeUnit.SECONDS));
- Assert.assertTrue("should be instanceof IOException, was: " + throwableRef.get(),
- throwableRef.get() instanceof IOException);
- Assert.assertTrue("cause should be InterruptedException, was: " + throwableRef.get().getCause(),
- throwableRef.get().getCause() instanceof InterruptedException);
- }
-
- /**
- * Tests that an abort called after the connection has been retrieved
- * but before a release trigger is set does still abort the request.
- */
- @Test
- public void testAbortAfterAllocateBeforeRequest() throws Exception {
- this.localServer.register("*", new BasicService());
-
- CountDownLatch releaseLatch = new CountDownLatch(1);
- SchemeRegistry registry = new SchemeRegistry();
- registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
-
- PoolingClientConnectionManager conMan = new PoolingClientConnectionManager(registry);
- final AtomicReference throwableRef = new AtomicReference();
- final CountDownLatch getLatch = new CountDownLatch(1);
- final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
- final HttpContext context = new BasicHttpContext();
- final HttpGet httpget = new CustomGet("a", releaseLatch);
-
- new Thread(new Runnable() {
- public void run() {
- try {
- client.execute(getServerHttp(), httpget, context);
- } catch(Throwable t) {
- throwableRef.set(t);
- } finally {
- getLatch.countDown();
- }
- }
- }).start();
-
- Thread.sleep(100); // Give it a little time to proceed to release...
-
- httpget.abort();
-
- releaseLatch.countDown();
-
- Assert.assertTrue("should have finished get request", getLatch.await(1, TimeUnit.SECONDS));
- Assert.assertTrue("should be instanceof IOException, was: " + throwableRef.get(),
- throwableRef.get() instanceof IOException);
- }
-
- /**
- * Tests that an abort called completely before execute
- * still aborts the request.
- */
- @Test
- public void testAbortBeforeExecute() throws Exception {
- this.localServer.register("*", new BasicService());
-
- SchemeRegistry registry = new SchemeRegistry();
- registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
-
- PoolingClientConnectionManager conMan = new PoolingClientConnectionManager(registry);
- final AtomicReference throwableRef = new AtomicReference();
- final CountDownLatch getLatch = new CountDownLatch(1);
- final CountDownLatch startLatch = new CountDownLatch(1);
- final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
- final HttpContext context = new BasicHttpContext();
- final HttpGet httpget = new HttpGet("a");
-
- new Thread(new Runnable() {
- public void run() {
- try {
- try {
- if(!startLatch.await(1, TimeUnit.SECONDS))
- throw new RuntimeException("Took too long to start!");
- } catch(InterruptedException interrupted) {
- throw new RuntimeException("Never started!", interrupted);
- }
- client.execute(getServerHttp(), httpget, context);
- } catch(Throwable t) {
- throwableRef.set(t);
- } finally {
- getLatch.countDown();
- }
- }
- }).start();
-
- httpget.abort();
- startLatch.countDown();
-
- Assert.assertTrue("should have finished get request", getLatch.await(1, TimeUnit.SECONDS));
- Assert.assertTrue("should be instanceof IOException, was: " + throwableRef.get(),
- throwableRef.get() instanceof IOException);
- }
-
- /**
- * Tests that an abort called after a redirect has found a new host
- * still aborts in the correct place (while trying to get the new
- * host's route, not while doing the subsequent request).
- */
- @Test
- public void testAbortAfterRedirectedRoute() throws Exception {
- final int port = this.localServer.getServiceAddress().getPort();
- this.localServer.register("*", new BasicRedirectService(port));
-
- SchemeRegistry registry = new SchemeRegistry();
- registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
-
- CountDownLatch connLatch = new CountDownLatch(1);
- CountDownLatch awaitLatch = new CountDownLatch(1);
- ConnMan4 conMan = new ConnMan4(registry, connLatch, awaitLatch);
- final AtomicReference throwableRef = new AtomicReference();
- final CountDownLatch getLatch = new CountDownLatch(1);
- final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
- final HttpContext context = new BasicHttpContext();
- final HttpGet httpget = new HttpGet("a");
-
- new Thread(new Runnable() {
- public void run() {
- try {
- HttpHost host = new HttpHost("127.0.0.1", port);
- client.execute(host, httpget, context);
- } catch(Throwable t) {
- throwableRef.set(t);
- } finally {
- getLatch.countDown();
- }
- }
- }).start();
-
- Assert.assertTrue("should have tried to get a connection", connLatch.await(1, TimeUnit.SECONDS));
-
- httpget.abort();
-
- Assert.assertTrue("should have finished get request", getLatch.await(1, TimeUnit.SECONDS));
- Assert.assertTrue("should be instanceof IOException, was: " + throwableRef.get(),
- throwableRef.get() instanceof IOException);
- Assert.assertTrue("cause should be InterruptedException, was: " + throwableRef.get().getCause(),
- throwableRef.get().getCause() instanceof InterruptedException);
- }
-
-
- /**
- * Tests that if a socket fails to connect, the allocated connection is
- * properly released back to the connection manager.
- */
- @Test
- public void testSocketConnectFailureReleasesConnection() throws Exception {
- final ConnMan2 conMan = new ConnMan2();
- final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
- final HttpContext context = new BasicHttpContext();
- final HttpGet httpget = new HttpGet("http://www.example.com/a");
-
- try {
- client.execute(httpget, context);
- Assert.fail("expected IOException");
- } catch(IOException expected) {}
-
- Assert.assertNotNull(conMan.allocatedConnection);
- Assert.assertSame(conMan.allocatedConnection, conMan.releasedConnection);
- }
-
- private static class BasicService implements HttpRequestHandler {
- public void handle(final HttpRequest request,
- final HttpResponse response,
- final HttpContext context) throws HttpException, IOException {
- response.setStatusCode(200);
- response.setEntity(new StringEntity("Hello World"));
- }
- }
-
- private static class BasicRedirectService implements HttpRequestHandler {
- private int statuscode = HttpStatus.SC_SEE_OTHER;
- private int port;
-
- public BasicRedirectService(int port) {
- this.port = port;
- }
-
- public void handle(final HttpRequest request,
- final HttpResponse response, final HttpContext context)
- throws HttpException, IOException {
- ProtocolVersion ver = request.getRequestLine().getProtocolVersion();
- response.setStatusLine(ver, this.statuscode);
- response.addHeader(new BasicHeader("Location", "http://localhost:"
- + this.port + "/newlocation/"));
- response.addHeader(new BasicHeader("Connection", "close"));
- }
- }
-
- private static class ConnMan4 extends PoolingClientConnectionManager {
- private final CountDownLatch connLatch;
- private final CountDownLatch awaitLatch;
-
- public ConnMan4(SchemeRegistry schreg,
- CountDownLatch connLatch, CountDownLatch awaitLatch) {
- super(schreg);
- this.connLatch = connLatch;
- this.awaitLatch = awaitLatch;
- }
-
- @Override
- public ClientConnectionRequest requestConnection(HttpRoute route, Object state) {
- // If this is the redirect route, stub the return value
- // so-as to pretend the host is waiting on a slot...
- if(route.getTargetHost().getHostName().equals("localhost")) {
- final Thread currentThread = Thread.currentThread();
-
- return new ClientConnectionRequest() {
-
- public void abortRequest() {
- currentThread.interrupt();
- }
-
- public ManagedClientConnection getConnection(
- long timeout, TimeUnit tunit)
- throws InterruptedException,
- ConnectionPoolTimeoutException {
- connLatch.countDown(); // notify waiter that we're getting a connection
-
- // zero usually means sleep forever, but CountDownLatch doesn't interpret it that way.
- if(timeout == 0)
- timeout = Integer.MAX_VALUE;
-
- if(!awaitLatch.await(timeout, tunit))
- throw new ConnectionPoolTimeoutException();
-
- return new ClientConnAdapterMockup(ConnMan4.this);
- }
- };
- } else {
- return super.requestConnection(route, state);
- }
- }
- }
-
-
- static class ConnMan2 implements ClientConnectionManager {
-
- private ManagedClientConnection allocatedConnection;
- private ManagedClientConnection releasedConnection;
-
- public ConnMan2() {
- }
-
- public void closeIdleConnections(long idletime, TimeUnit tunit) {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public void closeExpiredConnections() {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public ManagedClientConnection getConnection(HttpRoute route) {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public ManagedClientConnection getConnection(HttpRoute route,
- long timeout, TimeUnit tunit) {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public ClientConnectionRequest requestConnection(
- final HttpRoute route,
- final Object state) {
-
- return new ClientConnectionRequest() {
-
- public void abortRequest() {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public ManagedClientConnection getConnection(
- long timeout, TimeUnit unit)
- throws InterruptedException,
- ConnectionPoolTimeoutException {
- allocatedConnection = new ClientConnAdapterMockup(ConnMan2.this) {
- @Override
- public void open(HttpRoute route, HttpContext context,
- HttpParams params) throws IOException {
- throw new ConnectException();
- }
- };
- return allocatedConnection;
- }
- };
- }
-
- public HttpParams getParams() {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public SchemeRegistry getSchemeRegistry() {
- SchemeRegistry registry = new SchemeRegistry();
- registry.register(new Scheme("http", 80, new SocketFactoryMockup(null)));
- return registry;
- }
-
- public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
- this.releasedConnection = conn;
- }
-
- public void shutdown() {
- throw new UnsupportedOperationException("just a mockup");
- }
- }
-
- static class ConMan implements ClientConnectionManager {
- private final CountDownLatch connLatch;
- private final CountDownLatch awaitLatch;
-
- public ConMan(CountDownLatch connLatch, CountDownLatch awaitLatch) {
- this.connLatch = connLatch;
- this.awaitLatch = awaitLatch;
- }
-
- public void closeIdleConnections(long idletime, TimeUnit tunit) {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public void closeExpiredConnections() {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public ManagedClientConnection getConnection(HttpRoute route) {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public ManagedClientConnection getConnection(HttpRoute route,
- long timeout, TimeUnit tunit) {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public ClientConnectionRequest requestConnection(
- final HttpRoute route,
- final Object state) {
-
- final Thread currentThread = Thread.currentThread();
-
- return new ClientConnectionRequest() {
-
- public void abortRequest() {
- currentThread.interrupt();
- }
-
- public ManagedClientConnection getConnection(
- long timeout, TimeUnit tunit)
- throws InterruptedException,
- ConnectionPoolTimeoutException {
- connLatch.countDown(); // notify waiter that we're getting a connection
-
- // zero usually means sleep forever, but CountDownLatch doesn't interpret it that way.
- if(timeout == 0)
- timeout = Integer.MAX_VALUE;
-
- if(!awaitLatch.await(timeout, tunit))
- throw new ConnectionPoolTimeoutException();
-
- return new ClientConnAdapterMockup(ConMan.this);
- }
- };
- }
-
- public HttpParams getParams() {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public SchemeRegistry getSchemeRegistry() {
- SchemeRegistry registry = new SchemeRegistry();
- registry.register(new Scheme("http", 80, new SocketFactoryMockup(null)));
- return registry;
- }
-
- public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public void shutdown() {
- throw new UnsupportedOperationException("just a mockup");
- }
- }
-
- private static class CustomGet extends HttpGet {
- private final CountDownLatch releaseTriggerLatch;
-
- public CustomGet(String uri, CountDownLatch releaseTriggerLatch) {
- super(uri);
- this.releaseTriggerLatch = releaseTriggerLatch;
- }
-
- @Override
- public void setReleaseTrigger(ConnectionReleaseTrigger releaseTrigger) throws IOException {
- try {
- if(!releaseTriggerLatch.await(1, TimeUnit.SECONDS))
- throw new RuntimeException("Waited too long...");
- } catch(InterruptedException ie) {
- throw new RuntimeException(ie);
- }
-
- super.setReleaseTrigger(releaseTrigger);
- }
-
- }
-
private static class SimpleService implements HttpRequestHandler {
public SimpleService() {
diff --git a/httpclient/src/test/java/org/apache/http/impl/conn/ClientConnAdapterMockup.java b/httpclient/src/test/java/org/apache/http/impl/conn/ClientConnAdapterMockup.java
deleted file mode 100644
index 5f77e3a7a..000000000
--- a/httpclient/src/test/java/org/apache/http/impl/conn/ClientConnAdapterMockup.java
+++ /dev/null
@@ -1,81 +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.conn;
-
-import java.io.IOException;
-
-import org.apache.http.HttpHost;
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.routing.HttpRoute;
-import org.apache.http.params.HttpParams;
-import org.apache.http.protocol.HttpContext;
-
-
-/**
- * Mockup connection adapter.
- */
-public class ClientConnAdapterMockup extends AbstractClientConnAdapter {
-
- public ClientConnAdapterMockup(ClientConnectionManager mgr) {
- super(mgr, null);
- }
-
- public void close() {
- }
-
- public HttpRoute getRoute() {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public void layerProtocol(HttpContext context, HttpParams params) {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public void open(HttpRoute route, HttpContext context, HttpParams params) throws IOException {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public void shutdown() {
- }
-
- public void tunnelTarget(boolean secure, HttpParams params) {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public void tunnelProxy(HttpHost next, boolean secure, HttpParams params) {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public Object getState() {
- throw new UnsupportedOperationException("just a mockup");
- }
-
- public void setState(Object state) {
- throw new UnsupportedOperationException("just a mockup");
- }
-}
diff --git a/httpclient/src/test/java/org/apache/http/impl/conn/TestAbortHandling.java b/httpclient/src/test/java/org/apache/http/impl/conn/TestAbortHandling.java
new file mode 100644
index 000000000..14c242442
--- /dev/null
+++ b/httpclient/src/test/java/org/apache/http/impl/conn/TestAbortHandling.java
@@ -0,0 +1,510 @@
+/*
+ * ====================================================================
+ *
+ * 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.conn;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.http.HttpException;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.ProtocolVersion;
+import org.apache.http.client.methods.AbortableHttpRequest;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.ClientConnectionRequest;
+import org.apache.http.conn.ConnectionPoolTimeoutException;
+import org.apache.http.conn.ConnectionReleaseTrigger;
+import org.apache.http.conn.ManagedClientConnection;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.scheme.PlainSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.client.DefaultRequestDirector;
+import org.apache.http.impl.client.RequestWrapper;
+import org.apache.http.localserver.BasicServerTestBase;
+import org.apache.http.localserver.LocalTestServer;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.mockup.SocketFactoryMockup;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.ExecutionContext;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpRequestHandler;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+/**
+ * Tests for Abort handling.
+ */
+public class TestAbortHandling extends BasicServerTestBase {
+
+ @Before
+ public void setUp() throws Exception {
+ this.localServer = new LocalTestServer(null, null);
+ this.localServer.registerDefaultHandlers();
+ this.localServer.start();
+ this.httpclient = new DefaultHttpClient();
+ }
+
+ @Test
+ public void testAbortRetry_HTTPCLIENT_1120() throws Exception {
+ int port = this.localServer.getServiceAddress().getPort();
+ final CountDownLatch wait = new CountDownLatch(1);
+
+ this.localServer.register("*", new HttpRequestHandler(){
+ public void handle(HttpRequest request, HttpResponse response,
+ HttpContext context) throws HttpException, IOException {
+ try {
+ wait.countDown(); // trigger abort
+ Thread.sleep(2000); // allow time for abort to happen
+ response.setStatusCode(HttpStatus.SC_OK);
+ StringEntity entity = new StringEntity("Whatever");
+ response.setEntity(entity);
+ } catch (Exception e) {
+ response.setStatusCode(HttpStatus.SC_REQUEST_TIMEOUT);
+ }
+ }});
+
+ String s = "http://localhost:" + port + "/path";
+ final HttpGet httpget = new HttpGet(s);
+
+ Thread t = new Thread() {
+ @Override
+ public void run(){
+ try {
+ wait.await();
+ } catch (InterruptedException e) {
+ }
+ httpget.abort();
+ }
+ };
+
+ t.start();
+
+ HttpContext context = new BasicHttpContext();
+ try {
+ this.httpclient.execute(getServerHttp(), httpget, context);
+ } catch (IllegalStateException e) {
+ } catch (IOException e) {
+ }
+
+ HttpRequest reqWrapper = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
+ Assert.assertNotNull("Request should exist",reqWrapper);
+ Assert.assertEquals(1,((RequestWrapper) reqWrapper).getExecCount());
+ }
+
+ /**
+ * Tests that if abort is called on an {@link AbortableHttpRequest} while
+ * {@link DefaultRequestDirector} is allocating a connection, that the
+ * connection is properly aborted.
+ */
+ @Test
+ public void testAbortInAllocate() throws Exception {
+ CountDownLatch connLatch = new CountDownLatch(1);
+ CountDownLatch awaitLatch = new CountDownLatch(1);
+ final ConMan conMan = new ConMan(connLatch, awaitLatch);
+ final AtomicReference throwableRef = new AtomicReference();
+ final CountDownLatch getLatch = new CountDownLatch(1);
+ final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
+ final HttpContext context = new BasicHttpContext();
+ final HttpGet httpget = new HttpGet("http://www.example.com/a");
+
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ client.execute(httpget, context);
+ } catch(Throwable t) {
+ throwableRef.set(t);
+ } finally {
+ getLatch.countDown();
+ }
+ }
+ }).start();
+
+ Assert.assertTrue("should have tried to get a connection", connLatch.await(1, TimeUnit.SECONDS));
+
+ httpget.abort();
+
+ Assert.assertTrue("should have finished get request", getLatch.await(1, TimeUnit.SECONDS));
+ Assert.assertTrue("should be instanceof IOException, was: " + throwableRef.get(),
+ throwableRef.get() instanceof IOException);
+ Assert.assertTrue("cause should be InterruptedException, was: " + throwableRef.get().getCause(),
+ throwableRef.get().getCause() instanceof InterruptedException);
+ }
+
+ /**
+ * Tests that an abort called after the connection has been retrieved
+ * but before a release trigger is set does still abort the request.
+ */
+ @Test
+ public void testAbortAfterAllocateBeforeRequest() throws Exception {
+ this.localServer.register("*", new BasicService());
+
+ CountDownLatch releaseLatch = new CountDownLatch(1);
+ SchemeRegistry registry = new SchemeRegistry();
+ registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
+
+ PoolingClientConnectionManager conMan = new PoolingClientConnectionManager(registry);
+ final AtomicReference throwableRef = new AtomicReference();
+ final CountDownLatch getLatch = new CountDownLatch(1);
+ final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
+ final HttpContext context = new BasicHttpContext();
+ final HttpGet httpget = new CustomGet("a", releaseLatch);
+
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ client.execute(getServerHttp(), httpget, context);
+ } catch(Throwable t) {
+ throwableRef.set(t);
+ } finally {
+ getLatch.countDown();
+ }
+ }
+ }).start();
+
+ Thread.sleep(100); // Give it a little time to proceed to release...
+
+ httpget.abort();
+
+ releaseLatch.countDown();
+
+ Assert.assertTrue("should have finished get request", getLatch.await(1, TimeUnit.SECONDS));
+ Assert.assertTrue("should be instanceof IOException, was: " + throwableRef.get(),
+ throwableRef.get() instanceof IOException);
+ }
+
+ /**
+ * Tests that an abort called completely before execute
+ * still aborts the request.
+ */
+ @Test
+ public void testAbortBeforeExecute() throws Exception {
+ this.localServer.register("*", new BasicService());
+
+ SchemeRegistry registry = new SchemeRegistry();
+ registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
+
+ PoolingClientConnectionManager conMan = new PoolingClientConnectionManager(registry);
+ final AtomicReference throwableRef = new AtomicReference();
+ final CountDownLatch getLatch = new CountDownLatch(1);
+ final CountDownLatch startLatch = new CountDownLatch(1);
+ final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
+ final HttpContext context = new BasicHttpContext();
+ final HttpGet httpget = new HttpGet("a");
+
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ try {
+ if(!startLatch.await(1, TimeUnit.SECONDS))
+ throw new RuntimeException("Took too long to start!");
+ } catch(InterruptedException interrupted) {
+ throw new RuntimeException("Never started!", interrupted);
+ }
+ client.execute(getServerHttp(), httpget, context);
+ } catch(Throwable t) {
+ throwableRef.set(t);
+ } finally {
+ getLatch.countDown();
+ }
+ }
+ }).start();
+
+ httpget.abort();
+ startLatch.countDown();
+
+ Assert.assertTrue("should have finished get request", getLatch.await(1, TimeUnit.SECONDS));
+ Assert.assertTrue("should be instanceof IOException, was: " + throwableRef.get(),
+ throwableRef.get() instanceof IOException);
+ }
+
+ /**
+ * Tests that an abort called after a redirect has found a new host
+ * still aborts in the correct place (while trying to get the new
+ * host's route, not while doing the subsequent request).
+ */
+ @Test
+ public void testAbortAfterRedirectedRoute() throws Exception {
+ final int port = this.localServer.getServiceAddress().getPort();
+ this.localServer.register("*", new BasicRedirectService(port));
+
+ SchemeRegistry registry = new SchemeRegistry();
+ registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
+
+ CountDownLatch connLatch = new CountDownLatch(1);
+ CountDownLatch awaitLatch = new CountDownLatch(1);
+ ConnMan4 conMan = new ConnMan4(registry, connLatch, awaitLatch);
+ final AtomicReference throwableRef = new AtomicReference();
+ final CountDownLatch getLatch = new CountDownLatch(1);
+ final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
+ final HttpContext context = new BasicHttpContext();
+ final HttpGet httpget = new HttpGet("a");
+
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ HttpHost host = new HttpHost("127.0.0.1", port);
+ client.execute(host, httpget, context);
+ } catch(Throwable t) {
+ throwableRef.set(t);
+ } finally {
+ getLatch.countDown();
+ }
+ }
+ }).start();
+
+ Assert.assertTrue("should have tried to get a connection", connLatch.await(1, TimeUnit.SECONDS));
+
+ httpget.abort();
+
+ Assert.assertTrue("should have finished get request", getLatch.await(1, TimeUnit.SECONDS));
+ Assert.assertTrue("should be instanceof IOException, was: " + throwableRef.get(),
+ throwableRef.get() instanceof IOException);
+ Assert.assertTrue("cause should be InterruptedException, was: " + throwableRef.get().getCause(),
+ throwableRef.get().getCause() instanceof InterruptedException);
+ }
+
+
+ /**
+ * Tests that if a socket fails to connect, the allocated connection is
+ * properly released back to the connection manager.
+ */
+ @Test
+ public void testSocketConnectFailureReleasesConnection() throws Exception {
+ ManagedClientConnection conn = Mockito.mock(ManagedClientConnection.class);
+ Mockito.doThrow(new ConnectException()).when(conn).open(
+ Mockito.any(HttpRoute.class),
+ Mockito.any(HttpContext.class),
+ Mockito.any(HttpParams.class));
+ ClientConnectionRequest connrequest = Mockito.mock(ClientConnectionRequest.class);
+ Mockito.when(connrequest.getConnection(
+ Mockito.anyInt(), Mockito.any(TimeUnit.class))).thenReturn(conn);
+ ClientConnectionManager connmgr = Mockito.mock(ClientConnectionManager.class);
+
+ SchemeRegistry schemeRegistry = SchemeRegistryFactory.createDefault();
+
+ Mockito.when(connmgr.requestConnection(
+ Mockito.any(HttpRoute.class), Mockito.any())).thenReturn(connrequest);
+ Mockito.when(connmgr.getSchemeRegistry()).thenReturn(schemeRegistry);
+
+ final DefaultHttpClient client = new DefaultHttpClient(connmgr, new BasicHttpParams());
+ final HttpContext context = new BasicHttpContext();
+ final HttpGet httpget = new HttpGet("http://www.example.com/a");
+
+ try {
+ client.execute(httpget, context);
+ Assert.fail("expected IOException");
+ } catch(IOException expected) {}
+
+ Mockito.verify(conn).abortConnection();
+ }
+
+ private static class BasicService implements HttpRequestHandler {
+ public void handle(final HttpRequest request,
+ final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
+ response.setStatusCode(200);
+ response.setEntity(new StringEntity("Hello World"));
+ }
+ }
+
+ private static class BasicRedirectService implements HttpRequestHandler {
+ private int statuscode = HttpStatus.SC_SEE_OTHER;
+ private int port;
+
+ public BasicRedirectService(int port) {
+ this.port = port;
+ }
+
+ public void handle(final HttpRequest request,
+ final HttpResponse response, final HttpContext context)
+ throws HttpException, IOException {
+ ProtocolVersion ver = request.getRequestLine().getProtocolVersion();
+ response.setStatusLine(ver, this.statuscode);
+ response.addHeader(new BasicHeader("Location", "http://localhost:"
+ + this.port + "/newlocation/"));
+ response.addHeader(new BasicHeader("Connection", "close"));
+ }
+ }
+
+ private static class ConnMan4 extends PoolingClientConnectionManager {
+ private final CountDownLatch connLatch;
+ private final CountDownLatch awaitLatch;
+
+ public ConnMan4(SchemeRegistry schreg,
+ CountDownLatch connLatch, CountDownLatch awaitLatch) {
+ super(schreg);
+ this.connLatch = connLatch;
+ this.awaitLatch = awaitLatch;
+ }
+
+ @Override
+ public ClientConnectionRequest requestConnection(HttpRoute route, Object state) {
+ // If this is the redirect route, stub the return value
+ // so-as to pretend the host is waiting on a slot...
+ if(route.getTargetHost().getHostName().equals("localhost")) {
+ final Thread currentThread = Thread.currentThread();
+
+ return new ClientConnectionRequest() {
+
+ public void abortRequest() {
+ currentThread.interrupt();
+ }
+
+ public ManagedClientConnection getConnection(
+ long timeout, TimeUnit tunit)
+ throws InterruptedException,
+ ConnectionPoolTimeoutException {
+ connLatch.countDown(); // notify waiter that we're getting a connection
+
+ // zero usually means sleep forever, but CountDownLatch doesn't interpret it that way.
+ if(timeout == 0)
+ timeout = Integer.MAX_VALUE;
+
+ if(!awaitLatch.await(timeout, tunit))
+ throw new ConnectionPoolTimeoutException();
+
+ return Mockito.mock(ManagedClientConnection.class);
+ }
+ };
+ } else {
+ return super.requestConnection(route, state);
+ }
+ }
+ }
+
+
+ static class ConMan implements ClientConnectionManager {
+ private final CountDownLatch connLatch;
+ private final CountDownLatch awaitLatch;
+
+ public ConMan(CountDownLatch connLatch, CountDownLatch awaitLatch) {
+ this.connLatch = connLatch;
+ this.awaitLatch = awaitLatch;
+ }
+
+ public void closeIdleConnections(long idletime, TimeUnit tunit) {
+ throw new UnsupportedOperationException("just a mockup");
+ }
+
+ public void closeExpiredConnections() {
+ throw new UnsupportedOperationException("just a mockup");
+ }
+
+ public ManagedClientConnection getConnection(HttpRoute route) {
+ throw new UnsupportedOperationException("just a mockup");
+ }
+
+ public ManagedClientConnection getConnection(HttpRoute route,
+ long timeout, TimeUnit tunit) {
+ throw new UnsupportedOperationException("just a mockup");
+ }
+
+ public ClientConnectionRequest requestConnection(
+ final HttpRoute route,
+ final Object state) {
+
+ final Thread currentThread = Thread.currentThread();
+
+ return new ClientConnectionRequest() {
+
+ public void abortRequest() {
+ currentThread.interrupt();
+ }
+
+ public ManagedClientConnection getConnection(
+ long timeout, TimeUnit tunit)
+ throws InterruptedException,
+ ConnectionPoolTimeoutException {
+ connLatch.countDown(); // notify waiter that we're getting a connection
+
+ // zero usually means sleep forever, but CountDownLatch doesn't interpret it that way.
+ if(timeout == 0)
+ timeout = Integer.MAX_VALUE;
+
+ if(!awaitLatch.await(timeout, tunit))
+ throw new ConnectionPoolTimeoutException();
+
+ return Mockito.mock(ManagedClientConnection.class);
+ }
+ };
+ }
+
+ public HttpParams getParams() {
+ throw new UnsupportedOperationException("just a mockup");
+ }
+
+ public SchemeRegistry getSchemeRegistry() {
+ SchemeRegistry registry = new SchemeRegistry();
+ registry.register(new Scheme("http", 80, new SocketFactoryMockup(null)));
+ return registry;
+ }
+
+ public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
+ throw new UnsupportedOperationException("just a mockup");
+ }
+
+ public void shutdown() {
+ throw new UnsupportedOperationException("just a mockup");
+ }
+ }
+
+ private static class CustomGet extends HttpGet {
+ private final CountDownLatch releaseTriggerLatch;
+
+ public CustomGet(String uri, CountDownLatch releaseTriggerLatch) {
+ super(uri);
+ this.releaseTriggerLatch = releaseTriggerLatch;
+ }
+
+ @Override
+ public void setReleaseTrigger(ConnectionReleaseTrigger releaseTrigger) throws IOException {
+ try {
+ if(!releaseTriggerLatch.await(1, TimeUnit.SECONDS))
+ throw new RuntimeException("Waited too long...");
+ } catch(InterruptedException ie) {
+ throw new RuntimeException(ie);
+ }
+
+ super.setReleaseTrigger(releaseTrigger);
+ }
+
+ }
+
+}
diff --git a/httpclient/src/test/java/org/apache/http/impl/conn/TestTSCCMNoServer.java b/httpclient/src/test/java/org/apache/http/impl/conn/TestTSCCMNoServer.java
index c570945e0..3624de402 100644
--- a/httpclient/src/test/java/org/apache/http/impl/conn/TestTSCCMNoServer.java
+++ b/httpclient/src/test/java/org/apache/http/impl/conn/TestTSCCMNoServer.java
@@ -41,6 +41,7 @@ import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.junit.Assert;
import org.junit.Test;
+import org.mockito.Mockito;
/**
* Tests for ThreadSafeClientConnManager
that do not require
@@ -211,7 +212,8 @@ public class TestTSCCMNoServer {
// expected
}
try {
- mgr.releaseConnection(new ClientConnAdapterMockup(null), -1, null);
+ ManagedClientConnection conn = Mockito.mock(ManagedClientConnection.class);
+ mgr.releaseConnection(conn, -1, null);
Assert.fail("foreign connection adapter not detected");
} catch (IllegalArgumentException iax) {
// expected