oglueck 2003/01/21 01:47:26 Modified: httpclient/src/java/org/apache/commons/httpclient HostConfiguration.java HttpConnection.java HttpConnectionManager.java MultiThreadedHttpConnectionManager.java SimpleHttpConnectionManager.java httpclient/src/java/org/apache/commons/httpclient/protocol Protocol.java httpclient/src/test/org/apache/commons/httpclient TestHttpConnectionManager.java Log: connection pool now includes protocol Contributed by: Oleg Kalnichevski and Michael Becke Revision Changes Path 1.6 +48 -13 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HostConfiguration.java Index: HostConfiguration.java =================================================================== RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HostConfiguration.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- HostConfiguration.java 16 Jan 2003 13:28:39 -0000 1.5 +++ HostConfiguration.java 21 Jan 2003 09:47:26 -0000 1.6 @@ -300,24 +300,59 @@ /** * @see java.lang.Object#equals(java.lang.Object) */ - public boolean equals(Object o) { + public synchronized boolean equals(Object o) { if ( o instanceof HostConfiguration ) { + // shortcut if we're comparing with ourselves + if ( o == this ) return true; + HostConfiguration config = (HostConfiguration)o; - return ( - proxyPort == config.getProxyPort() - && ( - proxyHost == null - ? config.getProxyHost() == null - : proxyHost.equals( config.getProxyHost() ) - ) - && getHostURL().equals( config.getHostURL() ) - ); + if ( hostSet ) { + if ( + !host.equalsIgnoreCase( config.getHost() ) + || port != config.getPort() + || !protocol.equals( config.getProtocol() ) + ) { + // either host, port or protocol don't match + return false; + } + } else if ( config.isHostSet() ) { + return false; + } + if ( proxyHost != null ) { + if ( + !proxyHost.equalsIgnoreCase( config.getProxyHost() ) + || proxyPort != config.getProxyPort() + ) { + // either proxyHost or proxyPort don't match + return false; + } + } else if ( config.getProxyHost() != null ) { + return false; + } + + // everything matches + return true; } else { return false; + } + + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + + if ( host != null ) { + return host.hashCode(); + } else if ( proxyHost != null ) { + return proxyHost.hashCode(); + } else { + return super.hashCode(); } } 1.33 +19 -4 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnection.java Index: HttpConnection.java =================================================================== RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnection.java,v retrieving revision 1.32 retrieving revision 1.33 diff -u -r1.32 -r1.33 --- HttpConnection.java 19 Jan 2003 15:05:15 -0000 1.32 +++ HttpConnection.java 21 Jan 2003 09:47:26 -0000 1.33 @@ -156,6 +156,21 @@ ); } + /** + * Creates a new HttpConnection. + * + * @param hostConfiguration the host/proxy/protocol to use + */ + public HttpConnection( HostConfiguration hostConfiguration ) { + this( + hostConfiguration.getProxyHost(), + hostConfiguration.getProxyPort(), + hostConfiguration.getHost(), + hostConfiguration.getPort(), + hostConfiguration.getProtocol() + ); + } + public HttpConnection( String proxyHost, int proxyPort, 1.13 +5 -7 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnectionManager.java Index: HttpConnectionManager.java =================================================================== RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnectionManager.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- HttpConnectionManager.java 3 Dec 2002 05:46:15 -0000 1.12 +++ HttpConnectionManager.java 21 Jan 2003 09:47:26 -0000 1.13 @@ -62,7 +62,6 @@ package org.apache.commons.httpclient; -import java.net.MalformedURLException; /** * An interface for classes that manage HttpConnections. @@ -88,8 +87,7 @@ * * @see HttpConnection#setHttpConnectionManager(HttpConnectionManager) */ - public HttpConnection getConnection(HostConfiguration hostConfiguration) - throws MalformedURLException; + public HttpConnection getConnection(HostConfiguration hostConfiguration); /** * Gets an HttpConnection for a given host configuration. If a connection is @@ -112,7 +110,7 @@ * @see HttpConnection#setHttpConnectionManager(HttpConnectionManager) */ public HttpConnection getConnection(HostConfiguration hostConfiguration, long timeout) - throws HttpException, MalformedURLException; + throws HttpException; /** * Releases the given HttpConnection for use by other requests. 1.5 +73 -80 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java Index: MultiThreadedHttpConnectionManager.java =================================================================== RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- MultiThreadedHttpConnectionManager.java 16 Jan 2003 13:28:39 -0000 1.4 +++ MultiThreadedHttpConnectionManager.java 21 Jan 2003 09:47:26 -0000 1.5 @@ -64,18 +64,16 @@ import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; -import java.net.MalformedURLException; 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; /** - * Manages a set of HttpConnections for various host:ports. + * Manages a set of HttpConnections for various HostConfigurations. * * @author <a href="mailto:[EMAIL PROTECTED]">Michael Becke</a> * @author Eric Johnson @@ -92,8 +90,8 @@ private Map mapHosts = new HashMap(); private int maxConnections = 2; // Per RFC 2616 sec 8.1.4 - // mapping from reference to hostPort - private Map referenceToHostPort; + // mapping from reference to hostConfiguration + private Map referenceToHostConfig; // the reference queue used to track when HttpConnections are lost to the // garbage collector private ReferenceQueue referenceQueue; @@ -103,7 +101,7 @@ */ public MultiThreadedHttpConnectionManager() { - this.referenceToHostPort = Collections.synchronizedMap( new HashMap() ); + this.referenceToHostConfig = Collections.synchronizedMap( new HashMap() ); this.referenceQueue = new ReferenceQueue(); new ReferenceQueueThread().start(); @@ -111,19 +109,22 @@ } /** - * Set the maximum number of connections allowed for a given host:port. - * Per RFC 2616 section 8.1.4, this value defaults to 2. + * Sets the maximum number of connections allowed for a given + * HostConfiguration. Per RFC 2616 section 8.1.4, this value defaults to 2. * - * @param maxConnections - number of connections allowed for each host:port + * @param maxConnections the number of connections allowed for each + * hostConfiguration */ public void setMaxConnectionsPerHost(int maxConnections) { this.maxConnections = maxConnections; } /** - * Get the maximum number of connections allowed for a given host:port. + * Gets the maximum number of connections allowed for a given + * hostConfiguration. * - * @return The maximum number of connections allowed for a given host:port. + * @return The maximum number of connections allowed for a given + * hostConfiguration. */ public int getMaxConnectionsPerHost() { return maxConnections; @@ -132,8 +133,7 @@ /** * @see HttpConnectionManager#getConnection(HostConfiguration) */ - public HttpConnection getConnection(HostConfiguration hostConfiguration) - throws MalformedURLException { + public HttpConnection getConnection(HostConfiguration hostConfiguration) { while( true ) { try { @@ -152,35 +152,23 @@ * @see HttpConnectionManager#getConnection(HostConfiguration, long) */ public HttpConnection getConnection(HostConfiguration hostConfiguration, long timeout) - throws HttpException, MalformedURLException { + throws HttpException { log.trace("enter HttpConnectionManager.getConnection(HostConfiguration, long)"); if (hostConfiguration == null) { - throw new MalformedURLException("hostConfiguration is null"); + throw new IllegalArgumentException("hostConfiguration is null"); } - // Get the protocol and port (use default port if not specified) - Protocol protocol = hostConfiguration.getProtocol(); - String host = hostConfiguration.getHost(); - int port = protocol.resolvePort( hostConfiguration.getPort() ); - - String hostAndPort = host + ":" + port; - if (log.isDebugEnabled()) { - log.debug("HttpConnectionManager.getConnection: key = " - + hostAndPort); + log.debug("HttpConnectionManager.getConnection: config = " + + hostConfiguration + ", timeout = " + timeout); } - // Look for a list of connections for the given host:port - HostConnectionPool connectionPool = getConnectionPool(hostAndPort); - + // we get the connection pool with a clone of the hostConfiguration + // so that it cannot be changed once the connecton has been retrieved HttpConnection conn = getConnection( - connectionPool, - host, - port, - protocol, - hostConfiguration.getProxyHost(), - hostConfiguration.getProxyPort(), + getConnectionPool( new HostConfiguration( hostConfiguration ) ), + hostConfiguration, timeout ); @@ -193,10 +181,7 @@ * maxConnections have been created in the connectionPool. * * @param connectionPool - * @param host - * @param port - * @param proxyHost - * @param proxyPort + * @param hostConfiguration * @param timeout the number of milliseconds to wait for a connection, 0 to * wait indefinitely * @@ -207,11 +192,7 @@ */ private HttpConnection getConnection( HostConnectionPool connectionPool, - String host, - int port, - Protocol protocol, - String proxyHost, - int proxyPort, + HostConfiguration hostConfiguration, long timeout ) throws HttpException { @@ -226,23 +207,17 @@ if (connectionPool.freeConnections.size() > 0) { connection = (HttpConnection)connectionPool.freeConnections.removeFirst(); } else { - // get number of connections to host:port + // get number of connections hostConfig if (connectionPool.numConnections < maxConnections) { // Create a new connection - connection = new HttpConnection( - proxyHost, - proxyPort, - host, - port, - protocol - ); + connection = new HttpConnection( hostConfiguration ); connection.setHttpConnectionManager( this ); connectionPool.numConnections++; // add a weak reference to this connection - referenceToHostPort.put( + referenceToHostConfig.put( new WeakReference( connection, referenceQueue ), - host + ":" + port + hostConfiguration ); } else { @@ -275,37 +250,37 @@ } /** - * Get the pool (list) of connections available for the given host and port + * Get the pool (list) of connections available for the given hostConfig. * - * @param hostAndPort the key for the connection pool - * @return a pool (list) of connections available for the given key + * @param hostConfiguration the configuraton for the connection pool + * @return a pool (list) of connections available for the given config */ - private HostConnectionPool getConnectionPool(String hostAndPort) { + private HostConnectionPool getConnectionPool(HostConfiguration hostConfiguration) { log.trace("enter HttpConnectionManager.getConnections(String)"); - // Look for a list of connections for the given host:port + // Look for a list of connections for the given config HostConnectionPool listConnections = null; synchronized (mapHosts) { - listConnections = (HostConnectionPool) mapHosts.get(hostAndPort); + listConnections = (HostConnectionPool) mapHosts.get(hostConfiguration); if (listConnections == null) { - // First time for this host:port + // First time for this config listConnections = new HostConnectionPool(); - mapHosts.put(hostAndPort, listConnections); + mapHosts.put(hostConfiguration, listConnections); } } return listConnections; } /** - * Get the number of connections in use for the key + * Get the number of connections in use for this configuration. * - * @param hostAndPort the key that connections are tracked on - * @return the number of connections in use for the given key + * @param hostConfiguration the key that connections are tracked on + * @return the number of connections in use */ - public int getConnectionsInUse(String hostAndPort) { + public int getConnectionsInUse(HostConfiguration hostConfiguration) { log.trace("enter HttpConnectionManager.getConnectionsInUse(String)"); - HostConnectionPool connectionPool = getConnectionPool(hostAndPort); + HostConnectionPool connectionPool = getConnectionPool(hostConfiguration); synchronized( connectionPool ) { return connectionPool.numConnections; } @@ -314,31 +289,48 @@ /** * Make the given HttpConnection available for use by other requests. - * If another thread is blocked in getConnection() waiting for a connection - * for this host:port, they will be woken up. + * If another thread is blocked in getConnection() that could use this + * connection, it will be woken up. * - * @param conn - The HttpConnection to make available. + * @param conn the HttpConnection to make available. */ public void releaseConnection(HttpConnection conn) { log.trace("enter HttpConnectionManager.releaseConnection(HttpConnection)"); // make sure that the response has been read. SimpleHttpConnectionManager.finishLastResponse(conn); - String host = conn.getHost(); - int port = conn.getPort(); - String key = host + ":" + port; + + HostConfiguration connectionConfiguration = new HostConfiguration(); + connectionConfiguration.setHost( + conn.getHost(), + conn.getPort(), + conn.getProtocol() + ); + if ( conn.getProxyHost() != null ) { + connectionConfiguration.setProxy( + conn.getProxyHost(), + conn.getProxyPort() + ); + } if(log.isDebugEnabled()){ - log.debug("HttpConnectionManager.releaseConnection: Release connection for " + host + ":" + port); + log.debug( + "HttpConnectionManager.releaseConnection: Release connection for " + + connectionConfiguration + ); } - HostConnectionPool listConnections = getConnectionPool(key); + HostConnectionPool listConnections = getConnectionPool( + connectionConfiguration + ); synchronized(listConnections){ // Put the connect back in the available list and notify a waiter listConnections.freeConnections.addFirst(conn); if ( listConnections.numConnections == 0 ) { // for some reason this connection pool didn't already exist - log.error("connection pool not found for host: " + key); + log.error( + "connection pool not found for: " + connectionConfiguration + ); listConnections.numConnections = 1; } listConnections.notify(); @@ -377,9 +369,10 @@ Reference ref = referenceQueue.remove(); if ( ref != null ) { - String hostPort = (String)referenceToHostPort.get(ref); - referenceToHostPort.remove(ref); - HostConnectionPool connectionPool = getConnectionPool(hostPort); + HostConfiguration config = (HostConfiguration) + referenceToHostConfig.get(ref); + referenceToHostConfig.remove(ref); + HostConnectionPool connectionPool = getConnectionPool(config); synchronized( connectionPool ) { connectionPool.numConnections--; connectionPool.notify(); 1.6 +6 -10 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/SimpleHttpConnectionManager.java Index: SimpleHttpConnectionManager.java =================================================================== RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/SimpleHttpConnectionManager.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- SimpleHttpConnectionManager.java 16 Jan 2003 13:28:39 -0000 1.5 +++ SimpleHttpConnectionManager.java 21 Jan 2003 09:47:26 -0000 1.6 @@ -61,9 +61,8 @@ */ package org.apache.commons.httpclient; -import java.net.MalformedURLException; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; import org.apache.commons.httpclient.protocol.Protocol; @@ -92,17 +91,14 @@ /** * @see org.apache.commons.httpclient.HttpConnectionManager#getConnection(HostConfiguration) */ - public HttpConnection getConnection(HostConfiguration hostConfiguration) - throws MalformedURLException { - + public HttpConnection getConnection(HostConfiguration hostConfiguration) { return getConnection(hostConfiguration, 0); } /** * @see org.apache.commons.httpclient.HttpConnectionManager#getConnection(HostConfiguration, long) */ - public HttpConnection getConnection(HostConfiguration hostConfiguration, long timeout) - throws MalformedURLException { + public HttpConnection getConnection(HostConfiguration hostConfiguration, long timeout) { Protocol protocol = hostConfiguration.getProtocol(); String host = hostConfiguration.getHost(); 1.2 +31 -2 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/protocol/Protocol.java Index: Protocol.java =================================================================== RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/protocol/Protocol.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- Protocol.java 16 Jan 2003 13:28:40 -0000 1.1 +++ Protocol.java 21 Jan 2003 09:47:26 -0000 1.2 @@ -301,4 +301,33 @@ return scheme + ":" + defaultPort; } + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + + if ( obj instanceof Protocol ) { + + Protocol p = (Protocol)obj; + + return ( + defaultPort == p.getDefaultPort() + && scheme.equalsIgnoreCase( p.getScheme() ) + && secure == p.isSecure() + && socketFactory.equals( p.getSocketFactory() ) + ); + + } else { + return false; + } + + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return scheme.hashCode(); + } + } 1.3 +42 -54 jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java Index: TestHttpConnectionManager.java =================================================================== RCS file: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- TestHttpConnectionManager.java 3 Dec 2002 05:46:16 -0000 1.2 +++ TestHttpConnectionManager.java 21 Jan 2003 09:47:26 -0000 1.3 @@ -63,7 +63,6 @@ package org.apache.commons.httpclient; import java.io.IOException; -import java.net.MalformedURLException; import junit.framework.Test; import junit.framework.TestSuite; @@ -118,36 +117,31 @@ HostConfiguration hostConfiguration = new HostConfiguration(); hostConfiguration.setHost("www.nosuchserver.com", 80, "http"); - try{ - // Create a new connection - HttpConnection conn = mgr.getConnection(hostConfiguration); - // Validate the connection properties - assertEquals("Host", "www.nosuchserver.com", conn.getHost()); - assertEquals("Port", 80, conn.getPort()); - // Release the connection - mgr.releaseConnection(conn); - - // Create a new connection - hostConfiguration.setHost("www.nosuchserver.com", -1, "https"); - conn = mgr.getConnection(hostConfiguration); - // Validate the connection properties - assertEquals("Host", "www.nosuchserver.com", conn.getHost()); - assertEquals("Port", 443, conn.getPort()); - // Release the connection - mgr.releaseConnection(conn); - - // Create a new connection - hostConfiguration.setHost("www.nowhere.org", 8080, "http"); - conn = mgr.getConnection(hostConfiguration); - // Validate the connection properties - assertEquals("Host", "www.nowhere.org", conn.getHost()); - assertEquals("Port", 8080, conn.getPort()); - // Release the connection - mgr.releaseConnection(conn); - - }catch(MalformedURLException e){ - fail("Caught unexpected MalformedURLException (" + e.toString() + ")"); - } + // Create a new connection + HttpConnection conn = mgr.getConnection(hostConfiguration); + // Validate the connection properties + assertEquals("Host", "www.nosuchserver.com", conn.getHost()); + assertEquals("Port", 80, conn.getPort()); + // Release the connection + mgr.releaseConnection(conn); + + // Create a new connection + hostConfiguration.setHost("www.nosuchserver.com", -1, "https"); + conn = mgr.getConnection(hostConfiguration); + // Validate the connection properties + assertEquals("Host", "www.nosuchserver.com", conn.getHost()); + assertEquals("Port", 443, conn.getPort()); + // Release the connection + mgr.releaseConnection(conn); + + // Create a new connection + hostConfiguration.setHost("www.nowhere.org", 8080, "http"); + conn = mgr.getConnection(hostConfiguration); + // Validate the connection properties + assertEquals("Host", "www.nowhere.org", conn.getHost()); + assertEquals("Port", 8080, conn.getPort()); + // Release the connection + mgr.releaseConnection(conn); } @@ -317,24 +311,20 @@ HostConfiguration hostConfig3 = new HostConfiguration(); hostConfig3.setHost("www.nosuchserver.com", -1, "http"); - try{ - // 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); + // 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); - }catch(MalformedURLException e){ - fail("Caught unexpected MalformedURLException (" + e.toString() + ")"); - } } public void testTimeout() @@ -350,8 +340,6 @@ HttpConnection conn3 = mgr.getConnection(hostConfig, 5000); fail("Expected an HttpException."); - }catch(MalformedURLException e){ - fail("Caught unexpected MalformedURLException (" + e.toString() + ")"); }catch(HttpException e){ //Expected result }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>