commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jsde...@apache.org
Subject cvs commit: jakarta-commons/httpclient/src/test/org/apache/commons/httpclient TestHttpConnectionManager.java
Date Thu, 20 Feb 2003 01:03:57 GMT
jsdever     2003/02/19 17:03:57

  Modified:    httpclient/src/java/org/apache/commons/httpclient
                        MultiThreadedHttpConnectionManager.java
               httpclient/src/test/org/apache/commons/httpclient
                        TestHttpConnectionManager.java
  Log:
  Fix for the Request/Response race condition bug.
  
  Bugzilla: http://nagoya.apache.org/bugzilla/show_bug.cgi?id=13463
  Contributed by: Micheal Becke
  
  This fix was taken from the bug as attachement 4908.
  Mike became a committer today!
  
  Revision  Changes    Path
  1.9       +396 -11   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.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- MultiThreadedHttpConnectionManager.java	30 Jan 2003 05:01:54 -0000	1.8
  +++ MultiThreadedHttpConnectionManager.java	20 Feb 2003 01:03:56 -0000	1.9
  @@ -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");
  +            }
  +        }
  +
  +    }
  +
   }
  +
  
  
  
  1.5       +4 -32     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.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- TestHttpConnectionManager.java	23 Jan 2003 22:48:27 -0000	1.4
  +++ TestHttpConnectionManager.java	20 Feb 2003 01:03:57 -0000	1.5
  @@ -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()
       {
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message