Index: java/org/apache/commons/httpclient/HttpConnection.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnection.java,v retrieving revision 1.101 diff -u -r1.101 HttpConnection.java --- java/org/apache/commons/httpclient/HttpConnection.java 6 Oct 2004 17:32:03 -0000 1.101 +++ java/org/apache/commons/httpclient/HttpConnection.java 10 Oct 2004 16:40:40 -0000 @@ -46,6 +46,7 @@ import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.httpclient.util.ExceptionUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -424,8 +425,10 @@ * false otherwise. * * @see #isStale() + * + * @since 3.0 */ - public boolean closeIfStale() { + public boolean closeIfStale() throws IOException { if (used && isOpen && isStale()) { LOG.debug("Connection is stale, closing..."); close(); @@ -485,10 +488,12 @@ * {@link BufferedInputStream}, so although data might be read, what is visible * to clients of the connection will not change with this call.true if the connection is already closed, or a read would * fail. */ - protected boolean isStale() { + protected boolean isStale() throws IOException { boolean isStale = true; if (isOpen) { // the connection is open, but now we have to see if we can read it @@ -512,6 +517,9 @@ } } } catch (InterruptedIOException e) { + if (!ExceptionUtil.isSocketTimeoutException(e)) { + throw e; + } // aha - the connection is NOT stale - continue on! } catch (IOException e) { // oops - the connection is stale, the read or soTimeout failed. @@ -889,6 +897,9 @@ LOG.debug("Input data not available"); } } catch (InterruptedIOException e) { + if (!ExceptionUtil.isSocketTimeoutException(e)) { + throw e; + } if (LOG.isDebugEnabled()) { LOG.debug("Input data not available after " + timeout + " ms"); } Index: java/org/apache/commons/httpclient/HttpMethodBase.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v retrieving revision 1.218 diff -u -r1.218 HttpMethodBase.java --- java/org/apache/commons/httpclient/HttpMethodBase.java 7 Oct 2004 16:14:15 -0000 1.218 +++ java/org/apache/commons/httpclient/HttpMethodBase.java 10 Oct 2004 16:40:47 -0000 @@ -43,6 +43,7 @@ import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.httpclient.util.EncodingUtil; +import org.apache.commons.httpclient.util.ExceptionUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -1941,6 +1942,9 @@ return; } } catch (InterruptedIOException e) { + if (!ExceptionUtil.isSocketTimeoutException(e)) { + throw e; + } // Most probably Expect header is not recongnized // Remove the header to signal the method // that it's okay to go ahead with sending data Index: java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java,v retrieving revision 1.45 diff -u -r1.45 MultiThreadedHttpConnectionManager.java --- java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java 6 Oct 2004 17:32:04 -0000 1.45 +++ java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java 10 Oct 2004 16:40:51 -0000 @@ -1274,7 +1274,7 @@ } } - public boolean closeIfStale() { + public boolean closeIfStale() throws IOException { if (hasConnection()) { return wrappedConnection.closeIfStale(); } else { Index: java/org/apache/commons/httpclient/util/ExceptionUtil.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/util/ExceptionUtil.java,v retrieving revision 1.4 diff -u -r1.4 ExceptionUtil.java --- java/org/apache/commons/httpclient/util/ExceptionUtil.java 13 May 2004 04:01:22 -0000 1.4 +++ java/org/apache/commons/httpclient/util/ExceptionUtil.java 10 Oct 2004 16:40:52 -0000 @@ -28,6 +28,7 @@ */ package org.apache.commons.httpclient.util; +import java.io.InterruptedIOException; import java.lang.reflect.Method; import org.apache.commons.logging.Log; @@ -47,8 +48,11 @@ private static final Log LOG = LogFactory.getLog(ExceptionUtil.class); /** A reference to Throwable's initCause method, or null if it's not there in this JVM */ - static private final Method initCause = getInitCauseMethod(); + static private final Method INIT_CAUSE_METHOD = getInitCauseMethod(); + /** A reference to SocketTimeoutExceptionClass class, or null if it's not there in this JVM */ + static private final Class SOCKET_TIMEOUT_CLASS = SocketTimeoutExceptionClass(); + /** * Returns a Method allowing access to * {@link Throwable.initCause(Throwable) initCause} method of {@link Throwable}, @@ -67,6 +71,20 @@ } } + /** + * Returns SocketTimeoutExceptionClass or null if the class + * does not exist. + * + * @return SocketTimeoutExceptionClass, or null if unavailable. + */ + static private Class SocketTimeoutExceptionClass() { + try { + return Class.forName("java.net.SocketTimeoutException"); + } catch (ClassNotFoundException e) { + return null; + } + } + /** * If we're running on JDK 1.4 or later, initialize the cause for the given throwable. * @@ -74,12 +92,30 @@ * @param cause The cause of the throwable. */ public static void initCause(Throwable throwable, Throwable cause) { - if (initCause != null) { + if (INIT_CAUSE_METHOD != null) { try { - initCause.invoke(throwable, new Object[] { cause }); + INIT_CAUSE_METHOD.invoke(throwable, new Object[] { cause }); } catch (Exception e) { LOG.warn("Exception invoking Throwable.initCause", e); } + } + } + + /** + * If SocketTimeoutExceptionClass is defined, returns true only if the + * exception is an instance of SocketTimeoutExceptionClass. If + * SocketTimeoutExceptionClass is undefined, always returns true. + * + * @param e an instance of InterruptedIOException class. + * + * @return true if the exception signals socket timeout, false + * otherwise. + */ + public static boolean isSocketTimeoutException(final InterruptedIOException e) { + if (SOCKET_TIMEOUT_CLASS != null) { + return SOCKET_TIMEOUT_CLASS.isInstance(e); + } else { + return true; } } }