Index: java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java,v retrieving revision 1.8 diff -u -r1.8 MultiThreadedHttpConnectionManager.java --- java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java 30 Jan 2003 05:01:54 -0000 1.8 +++ java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java 17 Feb 2003 21:54:32 -0000 @@ -63,14 +63,19 @@ package org.apache.commons.httpclient; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; +import java.net.SocketException; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; +import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -95,13 +100,13 @@ * HostConnectionPool}s */ private final Map mapHosts = new HashMap(); - + /** Maximum number of connections allowed */ private int maxConnections = 2; // Per RFC 2616 sec 8.1.4 /** mapping from reference to hostConfiguration */ private final Map referenceToHostConfig; - + /** * the reference queue used to track when HttpConnections are lost to the * garbage collector @@ -165,7 +170,7 @@ */ public HttpConnection getConnection(HostConfiguration hostConfiguration, long timeout) throws HttpException { - + LOG.trace("enter HttpConnectionManager.getConnection(HostConfiguration, long)"); if (hostConfiguration == null) { @@ -184,7 +189,9 @@ hostConfiguration, timeout ); - return conn; + // wrap the connection in an adapter so we can ensure it is used + // only once + return new HttpConnectionAdapter(conn); } /** @@ -305,9 +312,17 @@ public void releaseConnection(HttpConnection conn) { LOG.trace("enter HttpConnectionManager.releaseConnection(HttpConnection)"); + if (conn instanceof HttpConnectionAdapter) { + // connections given out are wrapped in an HttpConnectionAdapter + conn = ((HttpConnectionAdapter) conn).getWrappedConnection(); + } else { + // this is okay, when an HttpConnectionAdapter is released + // is releases the real connection + } + // make sure that the response has been read. SimpleHttpConnectionManager.finishLastResponse(conn); - + HostConfiguration connectionConfiguration = new HostConfiguration(); connectionConfiguration.setHost(conn.getHost(), conn.getPort(), conn.getProtocol()); @@ -320,8 +335,7 @@ + connectionConfiguration); } - final HostConnectionPool listConnections - = getConnectionPool(connectionConfiguration); + final HostConnectionPool listConnections = getConnectionPool(connectionConfiguration); synchronized (listConnections) { // Put the connect back in the available list and notify a waiter listConnections.freeConnections.addFirst(conn); @@ -342,7 +356,7 @@ private class HostConnectionPool { /** The list of free connections */ private LinkedList freeConnections = new LinkedList(); - + /** The number of created connections */ private int numConnections = 0; } @@ -460,4 +474,375 @@ } } + /** + * An HttpConnection wrapper that ensures a connection cannot be used + * once released. + */ + private static class HttpConnectionAdapter extends HttpConnection { + + // the wrapped connection + private HttpConnection wrappedConnection; + + /** + * Creates a new HttpConnectionAdapter. + * @param connection the connection to be wrapped + */ + public HttpConnectionAdapter(HttpConnection connection) { + super(connection.getHost(), connection.getPort(), connection.getProtocol()); + this.wrappedConnection = connection; + } + + /** + * Tests if the wrapped connection is still available. + * @return boolean + */ + protected boolean hasConnection() { + return wrappedConnection != null; + } + + /** + * @return HttpConnection + */ + HttpConnection getWrappedConnection() { + return wrappedConnection; + } + + public void close() { + if (hasConnection()) { + wrappedConnection.close(); + } else { + // do nothing + } + } + + public String getHost() { + if (hasConnection()) { + return wrappedConnection.getHost(); + } else { + return null; + } + } + + public HttpConnectionManager getHttpConnectionManager() { + if (hasConnection()) { + return wrappedConnection.getHttpConnectionManager(); + } else { + return null; + } + } + + public InputStream getLastResponseInputStream() { + if (hasConnection()) { + return wrappedConnection.getLastResponseInputStream(); + } else { + return null; + } + } + + public int getPort() { + if (hasConnection()) { + return wrappedConnection.getPort(); + } else { + return -1; + } + } + + public Protocol getProtocol() { + if (hasConnection()) { + return wrappedConnection.getProtocol(); + } else { + return null; + } + } + + public String getProxyHost() { + if (hasConnection()) { + return wrappedConnection.getProxyHost(); + } else { + return null; + } + } + + public int getProxyPort() { + if (hasConnection()) { + return wrappedConnection.getProxyPort(); + } else { + return -1; + } + } + + public OutputStream getRequestOutputStream() + throws IOException, IllegalStateException { + if (hasConnection()) { + return wrappedConnection.getRequestOutputStream(); + } else { + return null; + } + } + + public OutputStream getRequestOutputStream(boolean useChunking) + throws IOException, IllegalStateException { + if (hasConnection()) { + return wrappedConnection.getRequestOutputStream(useChunking); + } else { + return null; + } + } + + public InputStream getResponseInputStream() + throws IOException, IllegalStateException { + if (hasConnection()) { + return wrappedConnection.getResponseInputStream(); + } else { + return null; + } + } + + public InputStream getResponseInputStream(HttpMethod method) + throws IOException, IllegalStateException { + if (hasConnection()) { + return wrappedConnection.getResponseInputStream(method); + } else { + return null; + } + } + + public boolean isOpen() { + if (hasConnection()) { + return wrappedConnection.isOpen(); + } else { + return false; + } + } + + public boolean isProxied() { + if (hasConnection()) { + return wrappedConnection.isProxied(); + } else { + return false; + } + } + + public boolean isResponseAvaliable() throws IOException { + if (hasConnection()) { + return wrappedConnection.isResponseAvaliable(); + } else { + return false; + } + } + + public boolean isSecure() { + if (hasConnection()) { + return wrappedConnection.isSecure(); + } else { + return false; + } + } + + public boolean isTransparent() { + if (hasConnection()) { + return wrappedConnection.isTransparent(); + } else { + return false; + } + } + + public void open() throws IOException { + if (hasConnection()) { + wrappedConnection.open(); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void print(String data) + throws IOException, IllegalStateException, HttpRecoverableException { + if (hasConnection()) { + wrappedConnection.print(data); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void printLine() + throws IOException, IllegalStateException, HttpRecoverableException { + if (hasConnection()) { + wrappedConnection.printLine(); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void printLine(String data) + throws IOException, IllegalStateException, HttpRecoverableException { + if (hasConnection()) { + wrappedConnection.printLine(data); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public String readLine() throws IOException, IllegalStateException { + if (hasConnection()) { + return wrappedConnection.readLine(); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void releaseConnection() { + if (hasConnection()) { + HttpConnection wrappedConnection = this.wrappedConnection; + this.wrappedConnection = null; + wrappedConnection.releaseConnection(); + } else { + // do nothing + } + } + + public void setConnectionTimeout(int timeout) { + if (hasConnection()) { + wrappedConnection.setConnectionTimeout(timeout); + } else { + // do nothing + } + } + + public void setHost(String host) throws IllegalStateException { + if (hasConnection()) { + wrappedConnection.setHost(host); + } else { + // do nothing + } + } + + public void setHttpConnectionManager(HttpConnectionManager httpConnectionManager) { + if (hasConnection()) { + wrappedConnection.setHttpConnectionManager(httpConnectionManager); + } else { + // do nothing + } + } + + public void setLastResponseInputStream(InputStream inStream) { + if (hasConnection()) { + wrappedConnection.setLastResponseInputStream(inStream); + } else { + // do nothing + } + } + + public void setPort(int port) throws IllegalStateException { + if (hasConnection()) { + wrappedConnection.setPort(port); + } else { + // do nothing + } + } + + public void setProtocol(Protocol protocol) { + if (hasConnection()) { + wrappedConnection.setProtocol(protocol); + } else { + // do nothing + } + } + + public void setProxyHost(String host) throws IllegalStateException { + if (hasConnection()) { + wrappedConnection.setProxyHost(host); + } else { + // do nothing + } + } + + public void setProxyPort(int port) throws IllegalStateException { + if (hasConnection()) { + wrappedConnection.setProxyPort(port); + } else { + // do nothing + } + } + + public void setSecure(boolean secure) throws IllegalStateException { + if (hasConnection()) { + wrappedConnection.setSecure(secure); + } else { + // do nothing + } + } + + public void setSoTimeout(int timeout) + throws SocketException, IllegalStateException { + if (hasConnection()) { + wrappedConnection.setSoTimeout(timeout); + } else { + // do nothing + } + } + + public void shutdownOutput() { + if (hasConnection()) { + wrappedConnection.shutdownOutput(); + } else { + // do nothing + } + } + + public void tunnelCreated() throws IllegalStateException, IOException { + if (hasConnection()) { + wrappedConnection.tunnelCreated(); + } else { + // do nothing + } + } + + public boolean waitForResponse(long timeout_ms) + throws IOException, IllegalStateException { + if (hasConnection()) { + return wrappedConnection.waitForResponse(timeout_ms); + } else { + return false; + } + } + + public void write(byte[] data, int offset, int length) + throws IOException, IllegalStateException, HttpRecoverableException { + if (hasConnection()) { + wrappedConnection.write(data, offset, length); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void write(byte[] data) + throws IOException, IllegalStateException, HttpRecoverableException { + if (hasConnection()) { + wrappedConnection.write(data); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void writeLine() + throws IOException, IllegalStateException, HttpRecoverableException { + if (hasConnection()) { + wrappedConnection.writeLine(); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + public void writeLine(byte[] data) + throws IOException, IllegalStateException, HttpRecoverableException { + if (hasConnection()) { + wrappedConnection.writeLine(data); + } else { + throw new IllegalStateException("Connection has been released"); + } + } + + } + } + Index: test/org/apache/commons/httpclient/TestHttpConnectionManager.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java,v retrieving revision 1.4 diff -u -r1.4 TestHttpConnectionManager.java --- test/org/apache/commons/httpclient/TestHttpConnectionManager.java 23 Jan 2003 22:48:27 -0000 1.4 +++ test/org/apache/commons/httpclient/TestHttpConnectionManager.java 17 Feb 2003 21:54:34 -0000 @@ -298,34 +298,6 @@ } } - - public void testGetMultipleConnections() { - HttpConnectionManager mgr = new MultiThreadedHttpConnectionManager(); - - HostConfiguration hostConfig1 = new HostConfiguration(); - hostConfig1.setHost("www.nosuchserver.com", 80, "http"); - - HostConfiguration hostConfig2 = new HostConfiguration(); - hostConfig2.setHost("www.nosuchserver.com", -1, "http"); - - HostConfiguration hostConfig3 = new HostConfiguration(); - hostConfig3.setHost("www.nosuchserver.com", -1, "http"); - - // Create a new connection - HttpConnection conn1 = mgr.getConnection(hostConfig1); - // Release the connection - mgr.releaseConnection(conn1); - - // Get the same connection again - HttpConnection conn2 = mgr.getConnection(hostConfig2); - assertEquals("Same connection", conn1, conn2); - // don't release yet - - // Get another new connection - HttpConnection conn3 = mgr.getConnection(hostConfig3); - assertTrue(conn2 != conn3); - - } public void testTimeout() {