You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by og...@apache.org on 2002/11/12 10:58:23 UTC

cvs commit: jakarta-commons/httpclient/src/test/org/apache/commons/httpclient TestHttpConnection.java

oglueck     2002/11/12 01:58:23

  Modified:    httpclient/src/java/org/apache/commons/httpclient
                        HttpClient.java HttpConnection.java
               httpclient/src/java/org/apache/commons/httpclient/methods
                        PostMethod.java
               httpclient/src/test/org/apache/commons/httpclient
                        TestHttpConnection.java
  Added:       httpclient/src/java/org/apache/commons/httpclient/util
                        TimeoutController.java
  Log:
  Added connection timeout (bug #10973)
  and corrected some whitespace
  
  Revision  Changes    Path
  1.60      +36 -23    jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpClient.java
  
  Index: HttpClient.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpClient.java,v
  retrieving revision 1.59
  retrieving revision 1.60
  diff -u -r1.59 -r1.60
  --- HttpClient.java	21 Oct 2002 14:15:38 -0000	1.59
  +++ HttpClient.java	12 Nov 2002 09:58:22 -0000	1.60
  @@ -116,6 +116,8 @@
   
       private int timeoutInMilliseconds = 0;
   
  +    private int connectionTimeout = 0;
  +
       // ------------------------------------------------------------- Properties
   
       /**
  @@ -152,16 +154,26 @@
   
       /**
        * Sets the SO_TIMEOUT which is the timeout for waiting for data.
  -     * 
  +     *
        * A timeout value of zero is interpreted as an infinite timeout.
  -     * 
  +     *
        * @param newTimeoutInMilliseconds Timeout in milliseconds
  -     * 
  +     *
        */
       public void setTimeout(int newTimeoutInMilliseconds) {
           this.timeoutInMilliseconds = newTimeoutInMilliseconds;
       }
   
  +    /**
  +     * Sets the timeout until a connection is etablished. A value of 0 means
  +     * the timeout is not used. The default value is 0.
  +     * @see HttpConnection#setConnectionTimeout(int)
  +     * @param newTimeoutInMilliseconds Timeout in milliseconds.
  +     */
  +    public void setConnectionTimeout(int newTimeoutInMilliseconds) {
  +       this.connectionTimeout = newTimeoutInMilliseconds;
  +    }
  +
       // --------------------------------------------------------- Public Methods
   
       /**
  @@ -175,7 +187,7 @@
        * @see #startSession(String, int, Credentials, boolean)
        * @see #startSession(String, int, String, int)
        * @see #endSession()
  -     * 
  +     *
        */
       public void startSession(String host, int port) {
           log.trace("enter HttpClient.startSession(String, int)");
  @@ -214,13 +226,13 @@
        * @param host the host to connect to
        * @param port the port to connect to
        * @param creds the default credentials to use
  -     * 
  +     *
        * @see #startSession(String, int, boolean)
        * @see #startSession(String, int)
        * @see #startSession(String, int, Credentials, boolean)
        * @see #startSession(String, int, String, int)
        * @see #endSession()
  -     * 
  +     *
        */
       public void startSession(String host, int port, Credentials creds) {
           log.trace("enter HttpClient.startSession(String, int, Credentials)");
  @@ -237,22 +249,22 @@
        * @param port the port to connect to
        * @param creds the default credentials to use
        * @param https when <code>true</code>, create an HTTPS session
  -     * 
  +     *
        * @see #startSession(String, int, boolean)
        * @see #startSession(String, int)
        * @see #startSession(String, int, Credentials)
        * @see #startSession(String, int, String, int)
        * @see #endSession()
  -     * 
  +     *
        */
       public void startSession(String host, int port, Credentials creds, boolean https) {
           log.trace("enter HttpClient.startSession(String, int, Credentials, boolean)");
   
           if (log.isDebugEnabled()) {
               log.debug(
  -                "Starting HttpClient session" 
  -		+ " Host:" + host
  -	       	+ " Port:" + port + " Credentials:" + creds
  +                "Starting HttpClient session"
  +                + " Host:" + host
  +                + " Port:" + port + " Credentials:" + creds
                   + " HTTPS:" + https);
           }
           getState().setCredentials(null, creds);
  @@ -331,14 +343,14 @@
           log.trace("enter HttpClient.startSession(String, int, Credentials, boolean)");
   
           if ("https".equalsIgnoreCase(url.getProtocol())) {
  -	    startSession(url.getHost(), url.getPort() == -1 ? 443
  -		  : url.getPort(), true);
  +        startSession(url.getHost(), url.getPort() == -1 ? 443
  +          : url.getPort(), true);
           } else if ("http".equalsIgnoreCase(url.getProtocol())) {
               startSession(url.getHost(), url.getPort() == -1 ? 80
  -		  : url.getPort(), false);
  +          : url.getPort(), false);
           } else {
               throw new IllegalArgumentException("Protocol " + url.getProtocol()
  -		  + " not supported in URL " + url);
  +          + " not supported in URL " + url);
           }
       }
   
  @@ -391,7 +403,7 @@
        * Start an HTTP session with the server specified
        * by the given <i>host</i> and <i>port</i>
        * via the given <i>proxyhost</i> and <i>proxyport</i>.
  -     * 
  +     *
        * @param host the host to connect to
        * @param port the port to connect to
        * @param proxyhost the proxy host to connect via
  @@ -416,7 +428,7 @@
        * @throws java.io.IOException if an I/O error occurs
        * @throws HttpException if a protocol exception occurs
        * @throws IllegalStateException if the session has not been started
  -     * 
  +     *
        */
       public synchronized int executeMethod(HttpMethod method)
           throws IOException, HttpException, IllegalStateException  {
  @@ -434,6 +446,7 @@
           if (!connection.isOpen()) {
               connection.setSSLSocketFactory(sslSocketFactory);
               connection.setSoTimeout(timeoutInMilliseconds);
  +            connection.setConnectionTimeout(connectionTimeout);
               connection.open();
               if (connection.isProxied() && connection.isSecure()) {
                   method = new ConnectMethod(method);
  @@ -453,9 +466,9 @@
        * @see #startSession(java.net.URL)
        * @see #startSession(java.net.URL, Credentials)
        * @see #startSession(String, int, String, int)
  -     * 
  +     *
        * @throws java.io.IOException when i/o errors occur closing the connection
  -     * 
  +     *
        */
       public void endSession() throws IOException {
           log.trace("enter HttpClient.endSession()");
  
  
  
  1.24      +133 -64   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.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- HttpConnection.java	31 Oct 2002 07:45:34 -0000	1.23
  +++ HttpConnection.java	12 Nov 2002 09:58:22 -0000	1.24
  @@ -62,6 +62,7 @@
   
   package org.apache.commons.httpclient;
   
  +import org.apache.commons.httpclient.util.TimeoutController;
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
   
  @@ -130,7 +131,7 @@
        * @param port the port I should connect to
        * @param secure when <tt>true</tt>, connect via HTTPS (SSL)
        */
  -    public HttpConnection(String proxyHost, int proxyPort, String host, 
  +    public HttpConnection(String proxyHost, int proxyPort, String host,
       int port, boolean secure) {
           if  (log.isDebugEnabled()){
               log.debug("HttpConnectionManager.getConnection:  creating "
  @@ -311,13 +312,15 @@
        * Set my {@link Socket}'s timeout, via {@link Socket#setSoTimeout}.  If the
        * connection is already open, the SO_TIMEOUT is changed.  If no connection
        * is open, then subsequent connections will use the timeout value.
  +     * <p>
  +     * Note: This is not a connection timeout but a timeout on network traffic!
        *
        * @param timeout the timeout value
        * @throws SocketException - if there is an error in the underlying
        * protocol, such as a TCP error.
        * @throws IllegalStateException if I am not connected
        */
  -    public void setSoTimeout(int timeout) 
  +    public void setSoTimeout(int timeout)
       throws SocketException, IllegalStateException {
           log.debug("HttpConnection.setSoTimeout("+ timeout +")");
           _so_timeout = timeout;
  @@ -327,6 +330,16 @@
       }
   
       /**
  +     * Sets the connection timeout. This is the maximum time that may be spent
  +     * until a connection is established. The connection will fail after this
  +     * amount of time.
  +     * @param timeout The timeout in milliseconds. 0 means timeout is not used.
  +     */
  +    public void setConnectionTimeout(int timeout) {
  +        this.connect_timeout = timeout;
  +    }
  +
  +    /**
        * Open this connection to the current host and port
        * (via a proxy if so configured).
        *
  @@ -338,16 +351,38 @@
           assertNotOpen(); // ??? is this worth doing?
           try {
               if (null == _socket) {
  -                String host = (null == _proxyHost) ? _host : _proxyHost;
  -                int port = (null == _proxyHost) ? _port : _proxyPort;
  +                final String host = (null == _proxyHost) ? _host : _proxyHost;
  +                final int port = (null == _proxyHost) ? _port : _proxyPort;
                   if (isSecure() && !isProxied()) {
                       if (sslSocketFactory == null) {
                           sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
                       }
  -                    _socket = (new SocketCreator()).createSocket(host,port);
  +                    if (connect_timeout == 0) {
  +                        _socket = (new SocketCreator()).createSocket(host,port);
  +                    } else {
  +                        SocketTask task = new SocketTask() {
  +                            public void doit() throws IOException {
  +                                s = (new SocketCreator()).createSocket(host,port);
  +                            }
  +                        };
  +                        TimeoutController.execute(task, connect_timeout);
  +                        _socket = task.s;
  +                        if (task.exception != null) throw task.exception;
  +                    }
                       _usingSecureSocket = true;
                   } else {
  -                    _socket = new Socket(host,port);
  +                    if (connect_timeout == 0) {
  +                        _socket = new Socket(host,port);
  +                    } else {
  +                        SocketTask task = new SocketTask() {
  +                            public void doit() throws IOException {
  +                                s = new Socket(host,port);
  +                            }
  +                        };
  +                        TimeoutController.execute(task, connect_timeout);
  +                        _socket = task.s;
  +                        if (task.exception != null) throw task.exception;
  +                    }
                       _usingSecureSocket = false;
                   }
               }
  @@ -360,6 +395,13 @@
               // so close everything out
               closeSocketAndStreams();
               throw e;
  +        } catch (TimeoutController.TimeoutException e) {
  +            if (log.isWarnEnabled()) {
  +                log.warn("The host "+ _host +":"+ _port +" (or proxy "+
  +                 _proxyHost +":"+ _proxyPort +") did not accept the connection "+
  +                 "within timeout of "+ connect_timeout +" milliseconds");
  +            }
  +            throw new ConnectionTimeoutException();
           }
       }
   
  @@ -378,11 +420,11 @@
           log.trace("enter HttpConnection.tunnelCreated()");
   
           if (!isSecure() || !isProxied()) {
  -	    throw new IllegalStateException("Connection must be secure and proxied to use this feature");
  -	}
  +        throw new IllegalStateException("Connection must be secure and proxied to use this feature");
  +    }
           if (_usingSecureSocket) {
  -	    throw new IllegalStateException("Already using a secure socket");
  -	}
  +        throw new IllegalStateException("Already using a secure socket");
  +    }
   
           if (sslSocketFactory == null) {
               sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
  @@ -407,7 +449,7 @@
       }
   
       /**
  -     * Return a {@link RequestOutputStream} suitable for writing (possibly 
  +     * Return a {@link RequestOutputStream} suitable for writing (possibly
        * chunked) bytes to my {@link OutputStream}.
        *
        * @throws IllegalStateException if I am not connected
  @@ -422,7 +464,7 @@
       }
   
       /**
  -     * Return a {@link RequestOutputStream} suitable for writing (possibly 
  +     * Return a {@link RequestOutputStream} suitable for writing (possibly
        * chunked) bytes to my {@link OutputStream}.
        *
        * @param useChunking when <tt>true</tt> the chunked transfer-encoding will
  @@ -432,7 +474,7 @@
        * @return a stream to write the request to
        * @deprecated Use new ChunkedOutputStream(httpConnecion.getRequestOutputStream());
        */
  -    public OutputStream getRequestOutputStream(boolean useChunking) 
  +    public OutputStream getRequestOutputStream(boolean useChunking)
           throws IOException, IllegalStateException {
           log.trace("enter HttpConnection.getRequestOutputStream(boolean)");
   
  @@ -445,7 +487,7 @@
       }
   
       /**
  -     * Return a {@link ResponseInputStream} suitable for reading (possibly 
  +     * Return a {@link ResponseInputStream} suitable for reading (possibly
        * chunked) bytes from my {@link InputStream}.
        * <p>
        * If the given {@link HttpMethod} contains
  @@ -457,15 +499,15 @@
        * @throws IllegalStateException if I am not connected
        * @throws IOException if an I/O problem occurs
        * @return a stream to read the response from
  -     * @deprecated Use getResponseInputStream() instead. 
  +     * @deprecated Use getResponseInputStream() instead.
        */
  -    public InputStream getResponseInputStream(HttpMethod method) 
  +    public InputStream getResponseInputStream(HttpMethod method)
       throws IOException, IllegalStateException {
           log.trace("enter HttpConnection.getResponseInputStream(HttpMethod)");
           return getResponseInputStream();
       }
   
  -    public InputStream getResponseInputStream() 
  +    public InputStream getResponseInputStream()
       throws IOException, IllegalStateException {
           log.trace("enter HttpConnection.getResponseInputStream()");
           assertOpen();
  @@ -476,12 +518,12 @@
        * Write the specified bytes to my output stream.
        *
        * @param data the data to be written
  -     * @throws HttpRecoverableException if a SocketException occurs 
  +     * @throws HttpRecoverableException if a SocketException occurs
        * @throws IllegalStateException if not connected
        * @throws IOException if an I/O problem occurs
  -     * @see #write(byte[],int,int) 
  +     * @see #write(byte[],int,int)
        */
  -    public void write(byte[] data) 
  +    public void write(byte[] data)
       throws IOException, IllegalStateException, HttpRecoverableException {
           log.trace("enter HttpConnection.write(byte[])");
           this.write(data, 0, data.length);
  @@ -489,8 +531,8 @@
   
   
       /**
  -     * Write <i>length</i> bytes in <i>data</i> starting at 
  -     * <i>offset</i> to my output stream. 
  +     * Write <i>length</i> bytes in <i>data</i> starting at
  +     * <i>offset</i> to my output stream.
        *
        * The general contract for
        * write(b, off, len) is that some of the bytes in the array b are written
  @@ -500,11 +542,11 @@
        * @param data array containing the data to be written.
        * @param offset the start offset in the data.
        * @param length the number of bytes to write.
  -     * @throws HttpRecoverableException if a SocketException occurs 
  +     * @throws HttpRecoverableException if a SocketException occurs
        * @throws IllegalStateException if not connected
        * @throws IOException if an I/O problem occurs
        */
  -    public void write(byte[] data, int offset, int length) 
  +    public void write(byte[] data, int offset, int length)
       throws IOException, IllegalStateException, HttpRecoverableException {
           log.trace("enter HttpConnection.write(byte[], int, int)");
   
  @@ -546,13 +588,13 @@
        * @throws IllegalStateException if I am not connected
        * @throws IOException if an I/O problem occurs
        */
  -    public void writeLine(byte[] data) 
  +    public void writeLine(byte[] data)
       throws IOException, IllegalStateException, HttpRecoverableException {
           log.trace("enter HttpConnection.writeLine(byte[])");
   
           assertOpen();
           if(wireLog.isDebugEnabled() && (data.length > 0)) {
  -	    String data_str =  new String(data);
  +             String data_str =  new String(data);
               wireLog.debug(">> \"" + data_str.trim() + "\" [\\r\\n]" );
           }
           try{
  @@ -575,7 +617,7 @@
        * @throws IllegalStateException if I am not connected
        * @throws IOException if an I/O problem occurs
        */
  -    public void writeLine() 
  +    public void writeLine()
       throws IOException, IllegalStateException, HttpRecoverableException {
           log.trace("enter HttpConnection.writeLine()");
   
  @@ -600,14 +642,14 @@
        * @throws IllegalStateException if I am not connected
        * @throws IOException if an I/O problem occurs
        */
  -    public void print(String data) 
  +    public void print(String data)
       throws IOException, IllegalStateException, HttpRecoverableException {
           log.trace("enter HttpConnection.print(String)");
           write(data.getBytes());
       }
   
       /**
  -     * Write the specified String (as bytes), followed by 
  +     * Write the specified String (as bytes), followed by
        * <tt>"\r\n".getBytes()</tt> to my output stream.
        *
        * @param data the data to be written
  @@ -675,7 +717,7 @@
       /**
        * Shutdown my {@link Socket}'s output, via {@link Socket#shutdownOutput}.
        */
  -    public void shutdownOutput() { 
  +    public void shutdownOutput() {
           log.trace("enter HttpConnection.shutdownOutput()");
   
           try {
  @@ -710,42 +752,42 @@
        */
       protected void closeSocketAndStreams() {
           log.trace("enter HttpConnection.closeSockedAndStreams()");
  -        
  +
           if (null != _input) {
  -	        try {
  -	            _input.close();
  -	        } catch(Exception ex) {
  -		    log.debug("Exception caught when closing input", ex);
  -	            // ignored
  -	        }
  -	        _input = null;
  -        }
  -
  -		if (null != _output) {
  -	        try {
  -	            _output.close();
  -	        } catch(Exception ex) {
  -		    log.debug("Exception caught when closing output", ex);
  -	            // ignored
  -	        }
  -	        _output = null;
  -		}
  -
  -		if (null != _socket) {
  -	        try {
  -	            _socket.close();
  -	        } catch(Exception ex) {
  -		    log.debug("Exception caught when closing socket", ex);
  -	            // ignored
  -	        }
  -	        _socket = null;
  -		}
  +            try {
  +                _input.close();
  +            } catch(Exception ex) {
  +            log.debug("Exception caught when closing input", ex);
  +                // ignored
  +            }
  +            _input = null;
  +        }
  +
  +        if (null != _output) {
  +            try {
  +                _output.close();
  +            } catch(Exception ex) {
  +            log.debug("Exception caught when closing output", ex);
  +                // ignored
  +            }
  +            _output = null;
  +        }
  +
  +        if (null != _socket) {
  +            try {
  +                _socket.close();
  +            } catch(Exception ex) {
  +            log.debug("Exception caught when closing socket", ex);
  +                // ignored
  +            }
  +            _socket = null;
  +        }
           _open = false;
           _tunnelEstablished = false;
           _usingSecureSocket = false;
       }
   
  -    /** 
  +    /**
        * Throw an {@link IllegalStateException} if I am connected.
        *
        * @throws IllegalStateException if connected
  @@ -769,6 +811,31 @@
           }
       }
   
  +    // -- Timeout Exception
  +    /**
  +     * Signals that a timeout occured while opening the socket.
  +     */
  +    public class ConnectionTimeoutException extends IOException {
  +        public ConnectionTimeoutException() {
  +        }
  +    }
  +
  +    // -- Helper
  +    private abstract class SocketTask implements Runnable {
  +        public Socket s;
  +        public IOException exception;
  +
  +        public abstract void doit() throws IOException;
  +
  +        public void run() {
  +            try {
  +                doit();
  +            } catch(IOException e) {
  +                exception = e;
  +            }
  +        }
  +    }
  +
       // -- javax.net binary isolation
   
       private class SocketCreator {
  @@ -814,4 +881,6 @@
       private boolean _usingSecureSocket = false;
       /** Whether I am tunneling a proxy or not */
       private boolean _tunnelEstablished = false;
  +    /** Timeout until connection established (Socket created). 0 means no timeout. */
  +    private int connect_timeout = 0;
   }
  
  
  
  1.27      +73 -74    jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java
  
  Index: PostMethod.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- PostMethod.java	28 Oct 2002 14:20:30 -0000	1.26
  +++ PostMethod.java	12 Nov 2002 09:58:23 -0000	1.27
  @@ -91,7 +91,7 @@
    * enclosed in the request as a new subordinate of the resource identified by
    * the Request-URI in the Request-Line. POST is designed to allow a uniform
    * method to cover the following functions:
  - * 
  + *
    * <ul>
    * <li>
    * Annotation of existing resources;
  @@ -108,9 +108,9 @@
    * Extending a database through an append operation.
    * </li>
    * </ul>
  - * 
  + *
    * </blockquote>
  - * 
  + *
    * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
    * @author <a href="mailto:dsale@us.britannica.com">Doug Sale</a>
    * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
  @@ -138,7 +138,7 @@
       private static final Log log = LogFactory.getLog(PostMethod.class);
   
       /** The Content-Type header for www-form-urlcoded. */
  -    static final Header CONTENT_TYPE = new Header("Content-Type", 
  +    static final Header CONTENT_TYPE = new Header("Content-Type",
           "application/x-www-form-urlencoded");
   
       /** The buffered request body. */
  @@ -162,7 +162,7 @@
   
       /**
        * No-arg constructor.
  -     * 
  +     *
        * @since 1.0
        */
       public PostMethod() {
  @@ -172,9 +172,9 @@
   
       /**
        * Path-setting constructor.
  -     * 
  +     *
        * @param path the path to request
  -     * 
  +     *
        * @since 1.0
        */
       public PostMethod(String path) {
  @@ -184,10 +184,10 @@
   
       /**
        * Path and temp directory constructor.
  -     * 
  +     *
        * @param path the path to request
        * @param tempDir directory to store temp files in
  -     * 
  +     *
        * @since 1.0
        */
       public PostMethod(String path, String tempDir) {
  @@ -197,11 +197,11 @@
   
       /**
        * Path, temp directory and temp file constructor.
  -     * 
  +     *
        * @param path the path to request
        * @param tempDir directory to store temp files in
        * @param tempFile file to store temporary data in
  -     * 
  +     *
        * @since 1.0
        */
       public PostMethod(String path, String tempDir, String tempFile) {
  @@ -216,10 +216,10 @@
       /**
        * A POST request can only be redirected if input is buffered. Overrides
        * method of {@link org.apache.commons.httpclient.HttpMethodBase}.
  -     * 
  +     *
        * @return true if request is buffered and <code>setFollowRedirects</code>
        *         was set to <code>true</code>.
  -     * 
  +     *
        * @since 2.0
        */
       public boolean getFollowRedirects() {
  @@ -234,9 +234,9 @@
   
       /**
        * Returns <tt>"POST"</tt>.
  -     * 
  +     *
        * @return <tt>"POST"</tt>
  -     * 
  +     *
        * @since 2.0
        */
       public String getName() {
  @@ -246,13 +246,13 @@
       /**
        * Set the value of parameter with parameterName to parameterValue. Does
        * not preserve the initial insertion order.
  -     * 
  +     *
        * @param parameterName DOCUMENT ME!
        * @param parameterValue DOCUMENT ME!
  -     * 
  +     *
        * @throws IllegalStateException if my request body has already been
        *         generated.
  -     * 
  +     *
        * @since 2.0
        * @deprecated use {@link #removeParameter(String,String)} followed by
        *             {@link #addParameter(String,String)}.
  @@ -271,12 +271,12 @@
       /**
        * Gets the parameter of the specified name. If there exists more than one
        * parameter with the name paramName, then only the first one is returned.
  -     * 
  +     *
        * @param paramName DOCUMENT ME!
  -     * 
  +     *
        * @return If a parameter exists with the name argument, the coresponding
        *         NameValuePair is returned.  Otherwise null.
  -     * 
  +     *
        * @since 2.0
        */
       public NameValuePair getParameter(String paramName) {
  @@ -304,9 +304,9 @@
        * parameters, a valid array is returned with zero elements. The returned
        * array object contains an array of pointers to  the internal data
        * members. TODO: is it ok to return internal data?
  -     * 
  +     *
        * @return An array of the current parameters
  -     * 
  +     *
        * @since 2.0
        * @see #getParameter(java.lang.String)
        */
  @@ -326,16 +326,16 @@
   
       /**
        * Sets the request body to be the specified string.
  -     * 
  +     *
        * <p>
        * Once this method has been invoked,  the request parameters  cannot be
        * altered until I am {@link #recycle recycled}.
        * </p>
  -     * 
  +     *
        * @param body Request content as a string
  -     * 
  +     *
        * @throws IllegalStateException if request params have been added
  -     * 
  +     *
        * @since 2.0
        */
       public void setRequestBody(String body) {
  @@ -354,8 +354,7 @@
           byte[] tmp = null;
           try {
               tmp = body.getBytes(getRequestCharSet());
  -        }
  -        catch(UnsupportedEncodingException e) {
  +        } catch(UnsupportedEncodingException e) {
               if (log.isWarnEnabled()) {
                   log.warn("Unsupported request body charset: " + e.getMessage());
               }
  @@ -366,16 +365,16 @@
   
       /**
        * Sets the request body to be the specified inputstream.
  -     * 
  +     *
        * <p>
        * Once this method has been invoked,  the request parameters  cannot be
        * altered until I am {@link #recycle recycled}.
        * </p>
  -     * 
  +     *
        * @param body DOCUMENT ME!
  -     * 
  +     *
        * @throws IllegalStateException if request params have been added
  -     * 
  +     *
        * @since 2.0
        */
       public void setRequestBody(InputStream body) {
  @@ -391,10 +390,10 @@
   
       /**
        * Gets the requestBody as it would be if it was executed.
  -     * 
  +     *
        * @return The request body if it has been set.  The generated  request
        *         body from the paramters if they exist.  Null otherwise.
  -     * 
  +     *
        * @since 2.0
        */
       public InputStream getRequestBody() {
  @@ -411,10 +410,10 @@
   
       /**
        * DOCUMENT ME!
  -     * 
  +     *
        * @return the request body as a string
        * @throws IOException DOCUMENT ME!
  -     * 
  +     *
        * @since 2.0
        */
       public String getRequestBodyAsString() throws IOException {
  @@ -434,7 +433,7 @@
   
       /**
        * Sets length information about the request body.
  -     * 
  +     *
        * <p>
        * Note: If you specify a content length the request is unbuffered. This
        * prevents redirection and automatic retry if a request fails the first
  @@ -442,7 +441,7 @@
        * automatically but will throw an Exception. You will have to set the
        * necessary 'Authorization' or 'Proxy-Authorization' headers manually.
        * </p>
  -     * 
  +     *
        * @param length size in bytes or any of CONTENT_LENGTH_AUTO,
        *        CONTENT_LENGTH_CHUNKED. If number of bytes or CONTENT_LENGTH_CHUNKED
        *        is specified the content will not be buffered internally and the
  @@ -452,7 +451,7 @@
        *        before it is sent over the network.
        * @throws RuntimeException if chunked transfer encoding is requested for
        *         a HTTP 1.0 request
  -     * 
  +     *
        * @since 2.0
        */
       public void setRequestContentLength(int length) {
  @@ -468,14 +467,14 @@
   
       /**
        * Add a new parameter to be used in the POST request body.
  -     * 
  +     *
        * @param paramName The parameter name to add.
        * @param paramValue The parameter value to add.
  -     * 
  +     *
        * @throws IllegalStateException if my request body has already been
        *         generated.
        * @throws IllegalArgumentException if either argument is null
  -     * 
  +     *
        * @since 1.0
        */
       public void addParameter(String paramName, String paramValue) {
  @@ -495,14 +494,14 @@
   
       /**
        * Add a new parameter to be used in the POST request body.
  -     * 
  +     *
        * @param param The parameter to add.
  -     * 
  +     *
        * @throws IllegalStateException if my request body has already been
        *         generated.
        * @throws IllegalArgumentException if the argument is null or contains
        *         null values
  -     * 
  +     *
        * @since 2.0
        * @see #addParameter(String,String)
        */
  @@ -524,12 +523,12 @@
       /**
        * Add an Array of parameters to be used in the POST request body. Logs a
        * warning if the parameters argument is null.
  -     * 
  +     *
        * @param parameters The array of parameters to add.
  -     * 
  +     *
        * @throws IllegalStateException if my request body has already been
        *         generated.
  -     * 
  +     *
        * @since 2.0
        * @see #addParameter(org.apache.commons.httpclient.NameValuePair)
        */
  @@ -552,7 +551,7 @@
       /**
        * Override method of {@link org.apache.commons.httpclient.HttpMethodBase}
        * to clear my request body.
  -     * 
  +     *
        * @since 1.0
        */
       public void recycle() {
  @@ -569,15 +568,15 @@
        * one parameter with the given paramName, all of them are removed.  If
        * there is just one, it is removed.  If there are none, then the request
        * is ignored.
  -     * 
  +     *
        * @param paramName The parameter name to remove.
  -     * 
  +     *
        * @return true if at least one parameter was removed
  -     * 
  +     *
        * @throws IllegalStateException if my request body has already been
        *         generated.
        * @throws IllegalArgumentException When the parameter name passed is null
  -     * 
  +     *
        * @since 2.0
        */
       public boolean removeParameter(String paramName) {
  @@ -611,16 +610,16 @@
        * Removes all parameter with the given paramName and paramValue. If there
        * is more than one parameter with the given paramName, only one is
        * removed.  If there are none, then the request is ignored.
  -     * 
  +     *
        * @param paramName The parameter name to remove.
        * @param paramValue The parameter value to remove.
  -     * 
  +     *
        * @return true if a parameter was removed.
  -     * 
  +     *
        * @throws IllegalStateException if my request body has already been
        *         generated.
        * @throws IllegalArgumentException when param name or value are null
  -     * 
  +     *
        * @since 2.0
        */
       public boolean removeParameter(String paramName, String paramValue) {
  @@ -655,9 +654,9 @@
       /**
        * Override method of {@link org.apache.commons.httpclient.HttpMethodBase}
        * to return the length of the request body.
  -     * 
  +     *
        * @return number of bytes in the request body
  -     * 
  +     *
        * @since 2.0
        */
       protected int getRequestContentLength() {
  @@ -680,19 +679,19 @@
       /**
        * Override method of {@link org.apache.commons.httpclient.HttpMethodBase}
        * to  also add <tt>Content-Type</tt> header when appropriate.
  -     * 
  +     *
        * @param state DOCUMENT ME!
        * @param conn DOCUMENT ME!
        * @throws IOException DOCUMENT ME!
        * @throws HttpException DOCUMENT ME!
  -     * 
  +     *
        * @since 2.0
        */
       protected void addRequestHeaders(HttpState state, HttpConnection conn)
       throws IOException, HttpException {
           super.addRequestHeaders(state, conn);
   
  -        if (!parameters.isEmpty()) { 
  +        if (!parameters.isEmpty()) {
               //there are some parameters, so set the contentType header
               setRequestHeader(CONTENT_TYPE);
           }
  @@ -702,16 +701,16 @@
        * Override method of {@link org.apache.commons.httpclient.HttpMethodBase}
        * to write request parameters as the request body.  The input stream will
        * be truncated after the specified content length.
  -     * 
  +     *
        * @param state DOCUMENT ME!
        * @param conn DOCUMENT ME!
  -     * 
  +     *
        * @return always returns true
  -     * 
  +     *
        * @throws IOException if the stream ends before the specified content
        *         length. <p>
        * @throws HttpException DOCUMENT ME!
  -     * 
  +     *
        * @since 2.0
        */
       protected boolean writeRequestBody(HttpState state, HttpConnection conn)
  @@ -764,11 +763,11 @@
   
       /**
        * Encode the list of parameters into a query stream.
  -     * 
  +     *
        * @param params the list of query name and value
  -     * 
  +     *
        * @return the query stream
  -     * 
  +     *
        * @since 1.0
        */
       static InputStream generateRequestBody(List params) {
  @@ -807,7 +806,7 @@
       /**
        * Buffers the request body and calculates the content length. If the
        * method was called earlier it returns immediately.
  -     * 
  +     *
        * @since 1.0
        */
       private void bufferContent() {
  
  
  
  1.1                  jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/util/TimeoutController.java
  
  Index: TimeoutController.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/util/TimeoutController.java,v 1.1 2002/11/12 09:58:23 oglueck Exp $
   * $Revision: 1.1 $
   * $Date: 2002/11/12 09:58:23 $
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "HttpClient", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * 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
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.commons.httpclient.util;
  
  /**
   * <p>
   * Executes a task with a specified timeout.
   * </p>
   * @author Ortwin Gl�ck
   * @version $Revision: 1.1 $
   * @since 2.0
   */
  
  public final class TimeoutController {
  
      /**
       * Do not instantiate objects of this class. Methods are static.
       */
      private TimeoutController() {
      }
  
      /**
       * Executes <code>task</code>. Waits for <code>timeout</code>
       * milliseconds for the task to end and returns. If the task does not return
       * in time, the thread is interrupted and an Exception is thrown.
       * The caller should override the Thread.interrupt() method to something that
       * quickly makes the thread die or use Thread.isInterrupted().
       * @param task The thread to execute
       * @param timeout The timeout in milliseconds. 0 means to wait forever.
       * @throws TimeoutException if the timeout passes and the thread does not return.
       */
      public static void execute(Thread task, long timeout) throws TimeoutException {
          task.start();
          try {
              task.join(timeout);
          } catch(InterruptedException e) {
              /* if somebody interrupts us he knows what he is doing */
          }
          if (task.isAlive()) {
              task.interrupt();
              throw new TimeoutException();
          }
      }
  
      /**
       * Executes <code>task</code> in a new deamon Thread and waits for the timeout.
       * @param task The task to execute
       * @param timeout The timeout in milliseconds. 0 means to wait forever.
       * @throws TimeoutException if the timeout passes and the thread does not return.
       */
      public static void execute(Runnable task, long timeout) throws TimeoutException {
          Thread t = new Thread(task, "Timeout guard");
          t.setDaemon(true);
          execute(t, timeout);
      }
  
      /**
       * Signals that the task timed out.
       */
      public static class TimeoutException extends Exception {
          public TimeoutException() {
          }
      }
  }
  
  
  1.2       +35 -22    jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestHttpConnection.java
  
  Index: TestHttpConnection.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestHttpConnection.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TestHttpConnection.java	8 Sep 2002 05:43:27 -0000	1.1
  +++ TestHttpConnection.java	12 Nov 2002 09:58:23 -0000	1.2
  @@ -69,12 +69,12 @@
   
   /**
    *
  - * Unit tests for {@link HttpConnection}.  
  + * Unit tests for {@link HttpConnection}.
    *
    * @author Sean C. Sullivan
  - * 
  + *
    * @version $Id$
  - * 
  + *
    */
   public class TestHttpConnection extends TestCase {
       // ----------------------------------------------------- Instance Variables
  @@ -101,48 +101,61 @@
   
       public void testConstructThenClose() {
           HttpConnection conn = new HttpConnection("localhost", 8080);
  -		conn.close();
  -		assertTrue( ! conn.isOpen() );
  +        conn.close();
  +        assertTrue( ! conn.isOpen() );
  +    }
  +
  +    public void testConnTimeout() {
  +        HttpConnection conn = new HttpConnection("localhost", 8080);
  +        // 1 ms is short enough to make this fail
  +        conn.setConnectionTimeout(1);
  +        try {
  +            conn.open();
  +            fail("Should have timed out");
  +        } catch(IOException e) {
  +            assertTrue(e instanceof HttpConnection.ConnectionTimeoutException);
  +            /* should fail */
  +        }
       }
   
   
       public void testForIllegalStateExceptions() {
           HttpConnection conn = new HttpConnection("localhost", 8080);
  -        
  +
           try {
  -        	OutputStream out = conn.getRequestOutputStream();
  -        	fail("getRequestOutputStream did not throw the expected exception");
  +            OutputStream out = conn.getRequestOutputStream();
  +            fail("getRequestOutputStream did not throw the expected exception");
           }
           catch (IllegalStateException expected) {
  -        	// this exception is expected
  +            // this exception is expected
           }
           catch (IOException ex) {
  -        	fail("getRequestOutputStream did not throw the expected exception");
  +            fail("getRequestOutputStream did not throw the expected exception");
           }
  -        
  +
           try {
  -        	OutputStream out = conn.getRequestOutputStream(true);
  -        	fail("getRequestOutputStream(true) did not throw the expected exception");
  +            OutputStream out = conn.getRequestOutputStream(true);
  +            fail("getRequestOutputStream(true) did not throw the expected exception");
           }
           catch (IllegalStateException expected) {
  -        	// this exception is expected
  +            // this exception is expected
           }
           catch (IOException ex) {
  -        	fail("getRequestOutputStream(true) did not throw the expected exception");
  +            fail("getRequestOutputStream(true) did not throw the expected exception");
           }
  -        
  +
           try {
  -        	InputStream in = conn.getResponseInputStream(new PostMethod());
  -        	fail("getResponseInputStream() did not throw the expected exception");
  +            InputStream in = conn.getResponseInputStream(new PostMethod());
  +            fail("getResponseInputStream() did not throw the expected exception");
           }
           catch (IllegalStateException expected) {
  -        	// this exception is expected
  +            // this exception is expected
           }
           catch (IOException ex) {
  -        	fail("getResponseInputStream() did not throw the expected exception");
  +            fail("getResponseInputStream() did not throw the expected exception");
           }
  -        
  -        
  +
  +
       }
   
   }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>