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.51 diff -u -r1.51 HttpConnection.java --- java/org/apache/commons/httpclient/HttpConnection.java 13 Mar 2003 01:33:07 -0000 1.51 +++ java/org/apache/commons/httpclient/HttpConnection.java 31 Mar 2003 04:47:20 -0000 @@ -63,6 +63,7 @@ package org.apache.commons.httpclient; +import java.io.FilterOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -100,7 +101,7 @@ * * @author Rod Waldhoff * @author Sean C. Sullivan - * @author Ortwin Gl� + * @author Ortwin Gl�ck * @author Jeff Dever * @author Mike Bowler * @author Oleg Kalnichevski @@ -542,8 +543,9 @@ socket.setTcpNoDelay(soNodelay); socket.setSoTimeout(soTimeout); inputStream = socket.getInputStream(); - outputStream = socket.getOutputStream(); + outputStream = new WrappedOutputStream(socket.getOutputStream()); isOpen = true; + used = false; } catch (IOException e) { // Connection wasn't opened properly // so close everything out @@ -638,12 +640,11 @@ throws IOException, IllegalStateException { LOG.trace("enter HttpConnection.getRequestOutputStream(boolean)"); - assertOpen(); + OutputStream out = getRequestOutputStream(); if (useChunking) { - return new ChunkedOutputStream(outputStream); - } else { - return outputStream; + out = new ChunkedOutputStream(out); } + return out; } /** @@ -743,6 +744,8 @@ try { outputStream.write(data, offset, length); + } catch (HttpRecoverableException hre) { + throw hre; } catch (SocketException se) { LOG.debug( "HttpConnection: Socket exception while writing data", @@ -766,19 +769,8 @@ public void writeLine(byte[] data) throws IOException, IllegalStateException, HttpRecoverableException { LOG.trace("enter HttpConnection.writeLine(byte[])"); - - assertOpen(); - - try { - outputStream.write(data); - writeLine(); - } catch (SocketException se) { - LOG.info("SocketException while writing data to output", se); - throw new HttpRecoverableException(se.toString()); - } catch (IOException ioe) { - LOG.info("IOException while writing data to output", ioe); - throw ioe; - } + write(data); + writeLine(); } /** @@ -792,16 +784,7 @@ public void writeLine() throws IOException, IllegalStateException, HttpRecoverableException { LOG.trace("enter HttpConnection.writeLine()"); - - try { - outputStream.write(CRLF); - } catch (SocketException se) { - LOG.warn("HttpConnection: Socket exception while writing data", se); - throw new HttpRecoverableException(se.toString()); - } catch (IOException ioe) { - LOG.warn("HttpConnection: IO exception while writing data", ioe); - throw ioe; - } + write(CRLF); } /** @@ -922,6 +905,8 @@ // connections so we want to close them after one use close(); } + // we are assuming that the connection will only be released once used + used = true; if (httpConnectionManager != null) { httpConnectionManager.releaseConnection(this); } @@ -1046,6 +1031,55 @@ } } + /** + * A wrapper for output streams that closes the connection and converts to recoverable + * exceptions as appropriable when an IOException occurs. + */ + private class WrappedOutputStream extends FilterOutputStream { + + /** + * @param out the output stream to wrap + */ + public WrappedOutputStream(OutputStream out) { + super(out); + } + + /** + * Closes the connection and conditionally converts exception to recoverable. + * @param ioe the exception that occurred + * @return the exception to be thrown + */ + private IOException handleException(IOException ioe) { + HttpConnection.this.close(); + if (used) { + LOG.debug( + "Output exception occurred on a used connection. Will treat as recoverable.", + ioe + ); + return new HttpRecoverableException(ioe.toString()); + } else { + return ioe; + } + } + + public void write(int b) throws IOException { + try { + super.write(b); + } catch (IOException ioe) { + throw handleException(ioe); + } + } + + public void flush() throws IOException { + try { + super.flush(); + } catch (IOException ioe) { + throw handleException(ioe); + } + } + + } + // ------------------------------------------------------- Static Variable /** "\r\n", as bytes. */ @@ -1054,7 +1088,11 @@ /** Log object for this class. */ private static final Log LOG = LogFactory.getLog(HttpConnection.class); - // ----------------------------------------------------- Instance Variables + // ----------------------------------------------------- Instance Variables + + /** A flag indicating if this connection has been used since being opened */ + private boolean used = false; + /** My host. */ private String hostName = null;