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 [EMAIL PROTECTED] * * 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: <mailto:commons-dev-unsubscribe@;jakarta.apache.org> For additional commands, e-mail: <mailto:commons-dev-help@;jakarta.apache.org>