Bug fixes:

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=11095

Changelog:

- Abstract EntityEnclosingMethod class has been introduced to encapsulate common 
behaviour of all entity enclosing methods 
- Limited "Expect: 100-continue" support in all entity enclosing methods (HttpClient 
hangs indefinitely if status code 100 is not sent when expected)
- Support for chunk encoded requests in all entity enclosing methods
- More robust (or so I'd like to hope) request content buffering logic
- PostMethod inherited from EntityEnclosingMethod class
- PutMethod inherited from EntityEnclosingMethod class

To be done next:

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=11653
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=14731

Feedback, critique welcome as always. Feel free to start throwing bad tomatoes at me

Cheers

Oleg
Index: java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java
===================================================================
RCS file: java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java
diff -N java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java       29 Jan 
+2003 16:12:02 -0000
@@ -0,0 +1,512 @@
+/*
+ * $Header: 
+/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/GetMethod.java,v
+ 1.21 2003/01/23 22:48:06 jsdever Exp $
+ * $Revision: 1.21 $
+ * $Date: 2003/01/23 22:48:06 $
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2003 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", "Commons", 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.methods;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.io.Reader;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.commons.httpclient.HttpConstants;
+import org.apache.commons.httpclient.HttpConnection;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpState;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.ChunkedOutputStream;
+import org.apache.commons.httpclient.ContentLengthInputStream;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * This abstract class serves as a foundation for all HTTP methods 
+ * that can enclose an entity within requests 
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]";>Remy Maucherat</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]";>Doug Sale</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]";>Jeff Dever</a>
+ * @author Ortwin Glück
+ * @author <a href="mailto:[EMAIL PROTECTED]";>Oleg Kalnichevski</a>
+ * @since 2.0
+ */
+
+public abstract class EntityEnclosingMethod extends GetMethod
+{
+    // ----------------------------------------- Static variables/initializers
+
+    /**
+     * The content length will be calculated automatically. This implies
+     * buffering of the content.
+     */
+    public static final int CONTENT_LENGTH_AUTO = -2;
+
+    /**
+     * The request will use chunked transfer encoding. Content length is not
+     * calculated and the content is not buffered.<br>
+     */
+    public static final int CONTENT_LENGTH_CHUNKED = -1;
+
+    /** Log object for this class. */
+    private static final Log log = LogFactory.getLog(EntityEnclosingMethod.class);
+
+    /** The buffered request body, if any. */
+    private byte[] buffer = null;
+
+    /** The unbuffered request body, if any. */
+    private InputStream requestBodyStream = null;
+
+    /** Counts how often the request was sent to the server. */
+    private int repeatCount = 0;
+
+    /** The content length of the <code>requestBodyStream</code> or one of
+     *  <code>CONTENT_LENGTH_AUTO</code> and <code>CONTENT_LENGTH_CHUNKED</code>.
+     */
+    private int requestContentLength = CONTENT_LENGTH_AUTO;
+
+    private boolean useExpectHeader = true;
+    
+    // ----------------------------------------------------------- Constructors
+
+    /**
+     * No-arg constructor.
+     *
+     * @since 2.0
+     */
+    public EntityEnclosingMethod() {
+        super();
+        setFollowRedirects(false);
+    }
+
+    /**
+     * Constructor specifying a URI.
+     *
+     * @param uri either an absolute or relative URI
+     *
+     * @since 2.0
+     */
+    public EntityEnclosingMethod(String uri) {
+        super(uri);
+        setFollowRedirects(false);
+    }
+
+    /**
+     * Constructor specifying a URI and a tempDir.
+     *
+     * @param uri either an absolute or relative URI
+     * @param tempDir directory to store temp files in
+     *
+     * @since 2.0
+     */
+    public EntityEnclosingMethod(String uti, String tempDir) {
+        super(uti, tempDir);
+        setFollowRedirects(false);
+    }
+
+    /**
+     * Constructor specifying a URI, tempDir and tempFile.
+     *
+     * @param uri either an absolute or relative URI
+     * @param tempDir directory to store temp files in
+     * @param tempFile file to store temporary data in
+     *
+     * @since 2.0
+     */
+    public EntityEnclosingMethod(String uri, String tempDir, String tempFile) {
+        super(uri, tempDir, tempFile);
+        setFollowRedirects(false);
+    }
+
+
+    /**
+     * Returns the useExpectHeader.
+     * @return boolean
+     */
+    public boolean getUseExpectHeader()
+    {
+        return this.useExpectHeader;
+    }
+
+    /**
+     * Sets the useExpectHeader.
+     * @param useExpectHeader The useExpectHeader to set
+     */
+    public void setUseExpectHeader(boolean value)
+    {
+        this.useExpectHeader = value;
+    }
+
+    /** 
+     * Returns true if request body has been buffered. Otherwise returns false.
+     *
+     * @since 2.0
+     */
+    
+    protected boolean hasBufferedRequestBody() {
+        return this.buffer != null;
+    }
+
+    /** 
+     * Returns true if request body has been set. Otherwise returns false.
+     *
+     * @since 2.0
+     */
+
+    protected boolean hasRequestBody() {
+        return (this.requestBodyStream != null) || (this.buffer != null);
+    }
+
+    /**
+     * 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
+     * time. This means that the HttpClient can not perform authorization
+     * 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
+     *        Content-Length header of the request will be used. In this case
+     *        the user is responsible to supply the correct content length.
+     *        If CONTENT_LENGTH_AUTO is specified the request will be buffered
+     *        before it is sent over the network.
+     *
+     * @since 2.0
+     */
+
+    public void setRequestContentLength(int length) {
+        log.trace("enter EntityEnclosingMethod.setRequestContentLength(int)");
+        this.requestContentLength = length;
+    }
+
+    /**
+     * 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() {
+        log.trace("enter EntityEnclosingMethod.getRequestContentLength()");
+
+        if (this.requestContentLength != CONTENT_LENGTH_AUTO) {
+            return this.requestContentLength;
+        }
+        bufferContent();
+        if (this.buffer != null) {
+            return this.buffer.length;
+        }
+        else {
+            return 0;
+        }
+    }
+
+    /**
+     * Sets the request body to be the specified inputstream.
+     *
+     * @param body Request body content as {@link java.io.InputStream}
+     *
+     * @since 2.0
+     */
+
+    public void setRequestBody(InputStream body) {
+        log.trace("enter EntityEnclosingMethod.setRequestBody(InputStream)");
+        this.requestBodyStream = body;
+        this.buffer = null;
+    }
+
+    /**
+     * Gets the request body as a stream.
+     *
+     * @return The request body {@link java.io.InputStream} if it has been set.
+     *
+     * @throws IllegalStateException if request body is not buferred
+     * 
+     * @since 2.0
+     */
+
+    public InputStream getRequestBody() {
+        log.trace("enter EntityEnclosingMethod.getRequestBody()");
+        if (this.buffer != null) {
+            return new ByteArrayInputStream(this.buffer); 
+        }
+        else {
+            return this.requestBodyStream;
+        }
+    }
+
+    /**
+     * Sets the request body to be the specified string.
+     *
+     * @param body Request body content as a string
+     *
+     * @since 2.0
+     */
+
+    public void setRequestBody(String body) {
+        log.trace("enter EntityEnclosingMethod.setRequestBody(String)");
+
+        if (body == null) {
+            this.requestBodyStream = null;
+            this.buffer = null;
+            return;
+        }
+        this.buffer = HttpConstants.getContentBytes(body, getRequestCharSet());
+    }
+
+    /**
+     * Gets the request body as a string.
+     *
+     * @return the request body as a string
+     * 
+     * @throws IOException when i/o errors occur reading the request
+     * @throws IllegalStateException if request body is not buferred
+     *
+     * @since 2.0
+     */
+
+    public String getRequestBodyAsString() throws IOException {
+        log.trace("enter EntityEnclosingMethod.getRequestBodyAsString()");
+        Reader instream = null;
+        try {
+            instream = new InputStreamReader(getRequestBody(), getRequestCharSet());
+        }
+        catch(UnsupportedEncodingException e) {
+            if (log.isWarnEnabled()) {
+                log.warn("Unsupported encoding: " + e.getMessage());
+            }
+            instream = new InputStreamReader(getRequestBody());
+        }
+        StringBuffer buffer = new StringBuffer();
+        char[] tmp = new char[4096];
+        int l = 0;
+        while((l = instream.read(tmp)) >= 0) {
+            buffer.append(tmp, 0, l);
+        }
+        return buffer.toString();
+    }
+
+
+    /**
+     * Override the method of {@link HttpMethodBase}
+     * to set the <tt>Expect</tt> header if it has
+     * not already been set, in addition to the "standard"
+     * set of headers.
+     *
+     * @throws HttpException when a protocol error occurs or state is invalid
+     * @throws IOException when i/o errors occur reading the response
+     * 
+     * @since 2.0
+     */
+
+    protected void addRequestHeaders(HttpState state, HttpConnection conn)
+    throws IOException, HttpException {
+        log.trace("enter EntityEnclosingMethod.addRequestHeaders(HttpState, 
+HttpConnection)");
+        
+        if (!isHttp11() && getUseExpectHeader()) {
+            throw new HttpException(
+                "100-continue not allowed for HTTP/1.0");
+        }
+
+        super.addRequestHeaders(state, conn);
+        // Send expectation header, provided there's something to be sent
+        if(isHttp11() && hasRequestBody()) {
+            if (getRequestHeader("Expect") == null) {
+                setRequestHeader("Expect", "100-continue");
+            }
+        }
+    }
+
+    /**
+     * 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 the client state
+     * @param conn the connection to write to
+     *
+     * @return <tt>true</tt>
+     * @throws IOException when i/o errors occur reading the response
+     * @throws HttpException when a protocol error occurs or state is invalid
+     *
+     * @since 2.0
+     */
+    
+    protected boolean writeRequestBody(HttpState state, HttpConnection conn)
+    throws IOException, HttpException {
+        log.trace(
+            "enter EntityEnclosingMethod.writeRequestBody(HttpState, 
+HttpConnection)");
+        
+        if (getStatusLine() == null) {
+             return false;
+        }
+        if (getRequestHeader("Expect") != null) {
+            if (getStatusLine().getStatusCode() != HttpStatus.SC_CONTINUE) {
+                return false;
+            }
+        }
+
+        int contentLength = getRequestContentLength();
+
+        if ((contentLength == CONTENT_LENGTH_CHUNKED) && !isHttp11()) {
+            throw new HttpException(
+                "Chunked transfer encoding not allowed for HTTP/1.0");
+        }
+        InputStream instream = getRequestBody();
+        if (instream == null) {
+            return true;
+        }
+
+        if ((this.repeatCount > 0) && (this.buffer == null)) {
+            throw new HttpException(
+                "Unbuffered entity enclosing request can not be repeated.");
+        }
+
+        this.repeatCount++;
+
+        OutputStream outstream = conn.getRequestOutputStream();
+        if (contentLength == CONTENT_LENGTH_CHUNKED) {
+            outstream = new ChunkedOutputStream(outstream);
+        }
+        if (contentLength >= 0) {
+            // don't need a watcher here - we're reading from something local,
+            // not server-side.
+            instream = new ContentLengthInputStream(instream, contentLength);
+        }
+
+        byte[] tmp = new byte[4096];
+        int total = 0;
+        int i = 0;
+        while ((i = instream.read(tmp)) >= 0) {
+            outstream.write(tmp, 0, i);
+            total += i;
+        }
+        // This is hardly the most elegant solution to closing chunked stream
+        if (outstream instanceof ChunkedOutputStream) {
+            ((ChunkedOutputStream)outstream).writeClosingChunk();
+        }
+        if ((contentLength > 0) && (total < contentLength)) {
+            throw new IOException("Unexpected end of input stream after "
+                + total + " bytes (expected " + contentLength + " bytes)");
+        }
+        return true;
+    }
+
+    /**
+     * Override method of {@link org.apache.commons.httpclient.HttpMethodBase}
+     * to clear my request body.
+     *
+     * @since 2.0
+     */
+    public void recycle() {
+        log.trace("enter EntityEnclosingMethod.recycle()");
+        super.recycle();
+        this.requestContentLength = CONTENT_LENGTH_AUTO;
+        this.requestBodyStream = null;
+        this.buffer = null;
+        this.repeatCount = 0;
+    }
+
+    /**
+     * Buffers the request body and calculates the content length. If the
+     * method was called earlier it returns immediately.
+     *
+     * @since 2.0
+     */
+    
+    protected void bufferContent() {
+        log.trace("enter EntityEnclosingMethod.bufferContent()");
+
+        if (this.buffer != null) {
+            return;
+        }
+        if (this.requestBodyStream == null) {
+            return;
+        }
+        try {
+            ByteArrayOutputStream tmp = new ByteArrayOutputStream();
+            byte[] data = new byte[4096];
+            int l = 0;
+            while ((l = this.requestBodyStream.read(data)) >= 0) {
+                tmp.write(data, 0, l);
+            }
+            this.buffer = tmp.toByteArray();
+            this.requestBodyStream = null;
+        } catch (IOException e) {
+            if (log.isErrorEnabled()) {
+                log.error(e.toString(), e );
+            }
+            this.buffer = null;
+            this.requestBodyStream = null;
+        }
+    }
+}
Index: java/org/apache/commons/httpclient/methods/PostMethod.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java,v
retrieving revision 1.34
diff -u -r1.34 PostMethod.java
--- java/org/apache/commons/httpclient/methods/PostMethod.java  28 Jan 2003 22:25:26 
-0000      1.34
+++ java/org/apache/commons/httpclient/methods/PostMethod.java  29 Jan 2003 16:12:02 
+-0000
@@ -1,8 +1,7 @@
 /*
- * $Header: 
/home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java,v
 1.34 2003/01/28 22:25:26 jsdever Exp $
- * $Revision: 1.34 $
- * $Date: 2003/01/28 22:25:26 $
- *
+ * $Header: 
+/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java,v
+ 1.33 2003/01/23 22:48:08 jsdever Exp $
+ * $Revision: 1.33 $
+ * $Date: 2003/01/23 22:48:08 $
  * ====================================================================
  *
  * The Apache Software License, Version 1.1
@@ -60,27 +59,21 @@
  * [Additional notices, if required by prior licensing conditions]
  *
  */
-
 package org.apache.commons.httpclient.methods;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
+import java.io.ByteArrayInputStream;
+import java.util.Vector;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Vector;
-
 import org.apache.commons.httpclient.HttpConstants;
-import org.apache.commons.httpclient.Header;
 import org.apache.commons.httpclient.HttpConnection;
 import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.HttpState;
+import org.apache.commons.httpclient.Header;
 import org.apache.commons.httpclient.NameValuePair;
 import org.apache.commons.httpclient.URIException;
-import org.apache.commons.httpclient.ChunkedOutputStream;
-import org.apache.commons.httpclient.ContentLengthInputStream;
 import org.apache.commons.httpclient.util.URIUtil;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -116,54 +109,24 @@
  * @author <a href="mailto:[EMAIL PROTECTED]";>Remy Maucherat</a>
  * @author <a href="mailto:[EMAIL PROTECTED]";>Doug Sale</a>
  * @author <a href="mailto:[EMAIL PROTECTED]";>Jeff Dever</a>
- * @author Ortwin Gl�
- * @author <a href="mailto:[EMAIL PROTECTED]";>Mike Bowler</a>
+ * @author Ortwin Glück
+ * @author <a href="mailto:[EMAIL PROTECTED]";>Oleg Kalnichevski</a>
  * @since 1.0
  */
-public class PostMethod extends GetMethod {
-    //~ Static variables/initializers 
������������������������������������������
-
-    /**
-     * The content length will be calculated automatically. This implies
-     * buffering of the content.
-     */
-    public static final int CONTENT_LENGTH_AUTO = -2;
-
-    /**
-     * The request will use chunked transfer encoding. Content length is not
-     * calculated and the content is not buffered.<br>
-     */
-    public static final int CONTENT_LENGTH_CHUNKED = -1;
-
+public class PostMethod extends EntityEnclosingMethod {
     // -------------------------------------------------------------- Constants
 
     /** Log object for this class. */
-    private static final Log LOG = LogFactory.getLog(PostMethod.class);
+    private static final Log log = LogFactory.getLog(PostMethod.class);
 
     /** The Content-Type header for www-form-urlcoded. */
-    private 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. */
-    protected ByteArrayOutputStream buffer = null;
-
-    /** The unbuffered request body. */
-    protected InputStream requestBody = null;
-
     /** The buffered request body consisting of <code>NameValuePair</code>s */
     protected Vector parameters = new Vector();
 
-    /** Counts how often the request was sent to the server. */
-    protected int repeatCount = 0;
-
-    /**
-     * The content length of the <code>requestBody</code> or one of
-     * <code>{@link #CONTENT_LENGTH_AUTO}</code> and
-     * <code>{@link #CONTENT_LENGTH_CHUNKED}</code>.
-     */
-    protected int requestContentLength = CONTENT_LENGTH_AUTO;
-
-    //~ Constructors 
�����������������������������������������������������������
+    // ----------------------------------------------------------- Constructors
 
     /**
      * No-arg constructor.
@@ -195,8 +158,8 @@
      *
      * @since 1.0
      */
-    public PostMethod(String uri, String tempDir) {
-        super(uri, tempDir);
+    public PostMethod(String uti, String tempDir) {
+        super(uti, tempDir);
         setFollowRedirects(false);
     }
 
@@ -216,8 +179,6 @@
 
     // ----------------------------------------------------------- Constructors
 
-    //~ Methods 
����������������������������������������������������������������
-
     /**
      * A POST request can only be redirected if input is buffered. Overrides
      * method of {@link org.apache.commons.httpclient.HttpMethodBase}.
@@ -228,11 +189,7 @@
      * @since 2.0
      */
     public boolean getFollowRedirects() {
-        if (!super.getFollowRedirects()) {
-            return false;
-        }
-
-        return (buffer != null);
+        return (hasBufferedRequestBody() && super.getFollowRedirects());
     }
 
     // ----------------------------------------------------- Instance Methods
@@ -252,24 +209,23 @@
      * Set the value of parameter with parameterName to parameterValue. Does
      * not preserve the initial insertion order.
      *
-     * @param parameterName DOCUMENT ME!
-     * @param parameterValue DOCUMENT ME!
+     * @param parameterName name of the parameter
+     * @param parameterValue value of the parameter
      *
      * @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)}.
      */
-    public void setParameter(String parameterName, String parameterValue) 
-        throws IllegalStateException {
-        LOG.trace("enter PostMethod.setParameter(String, String)");
+    public void setParameter(String parameterName, String parameterValue) {
+        log.trace("enter PostMethod.setParameter(String, String)");
 
-        if (null != requestBody) {
+        if (hasRequestBody()) {
             throw new IllegalStateException("Request body already generated.");
         }
-
         removeParameter(parameterName, parameterValue);
         addParameter(parameterName, parameterValue);
     }
@@ -278,7 +234,7 @@
      * 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!
+     * @param paramName name of the parameter
      *
      * @return If a parameter exists with the name argument, the coresponding
      *         NameValuePair is returned.  Otherwise null.
@@ -286,7 +242,7 @@
      * @since 2.0
      */
     public NameValuePair getParameter(String paramName) {
-        LOG.trace("enter PostMethod.getParameter(String)");
+        log.trace("enter PostMethod.getParameter(String)");
 
         if (paramName == null) {
             return null;
@@ -301,7 +257,6 @@
                 return parameter;
             }
         }
-
         return null;
     }
 
@@ -317,7 +272,7 @@
      * @see #getParameter(java.lang.String)
      */
     public NameValuePair[] getParameters() {
-        LOG.trace("enter PostMethod.getParameters()");
+        log.trace("enter PostMethod.getParameters()");
 
         int numPairs = parameters.size();
         Object[] objectArr = parameters.toArray();
@@ -331,142 +286,6 @@
     }
 
     /**
-     * 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) throws IllegalStateException {
-        LOG.trace("enter PostMethod.setRequestBody(String)");
-
-        if (!parameters.isEmpty()) {
-            throw new IllegalStateException(
-                "Request parameters have already been added.");
-        }
-
-        if (body == null) {
-            this.requestBody = null;
-            return;
-        }
-
-        this.requestBody = new ByteArrayInputStream(
-          HttpConstants.getContentBytes(body, getRequestCharSet()));
-    }
-
-    /**
-     * 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) throws IllegalStateException {
-        LOG.trace("enter PostMethod.getRequestBody(InputStream)");
-
-        if (!parameters.isEmpty()) {
-            throw new IllegalStateException(
-                "Request parameters have already been added.");
-        }
-
-        this.requestBody = body;
-    }
-
-    /**
-     * 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() {
-        LOG.trace("enter PostMethod.getRequestBody()");
-
-        if (requestBody != null) {
-            return requestBody;
-        } else if (!parameters.isEmpty()) {
-            return generateRequestBody(parameters);
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Return the request body as a string.
-     *
-     * @return the request body as a string
-     * @throws IOException If an IO problem occurs.
-     *
-     * @since 2.0
-     */
-    public String getRequestBodyAsString() throws IOException {
-        LOG.trace("enter PostMethod.getRequestBodyAsString()");
-
-        StringBuffer buffer = new StringBuffer();
-        InputStream requestBody = getRequestBody();
-        int data = requestBody.read();
-
-        while (data != -1) {
-            buffer.append((char) data);
-            data = requestBody.read();
-        }
-
-        return buffer.toString();
-    }
-
-    /**
-     * 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
-     * time. This means that the HttpClient can not perform authorization
-     * 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
-     *        Content-Length header of the request will be used. In this case
-     *        the user is responsible to supply the correct content length.
-     *        If CONTENT_LENGTH_AUTO is specified the request will be buffered
-     *        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) 
-        throws RuntimeException {
-        //TODO: We should be throwing a more specific exception than this.
-            
-        LOG.trace("enter PostMethod.setRequestContentLength(int)");
-
-        if ((length == CONTENT_LENGTH_CHUNKED) && !isHttp11()) {
-            throw new RuntimeException(
-                "Chunked transfer encoding not allowed for HTTP/1.0");
-        }
-
-        requestContentLength = length;
-    }
-
-    /**
      * Add a new parameter to be used in the POST request body.
      *
      * @param paramName The parameter name to add.
@@ -478,12 +297,10 @@
      *
      * @since 1.0
      */
-    public void addParameter(String paramName, String paramValue) 
-        throws IllegalStateException, IllegalArgumentException {
-            
-        LOG.trace("enter PostMethod.addParameter(String, String)");
+    public void addParameter(String paramName, String paramValue) {
+        log.trace("enter PostMethod.addParameter(String, String)");
 
-        if (null != requestBody) {
+        if (hasRequestBody()) {
             throw new IllegalStateException("Request body already generated.");
         }
 
@@ -508,18 +325,14 @@
      * @since 2.0
      * @see #addParameter(String,String)
      */
-    public void addParameter(NameValuePair param) 
-        throws IllegalStateException, IllegalArgumentException {
-            
-        LOG.trace("enter PostMethod.addParameter(NameValuePair)");
+    public void addParameter(NameValuePair param) {
+        log.trace("enter PostMethod.addParameter(NameValuePair)");
 
-        if (null != requestBody) {
+        if (hasRequestBody()) {
             throw new IllegalStateException("Request body already generated.");
         }
-
-        if (null == param) {
-            throw new IllegalArgumentException(
-                "Argument to addParameter(NameValuePair) cannot be null");
+        if (param == null) {
+            throw new IllegalArgumentException("NameValuePair may not be null");
         } else {
             addParameter(param.getName(), param.getValue());
         }
@@ -537,17 +350,14 @@
      * @since 2.0
      * @see #addParameter(org.apache.commons.httpclient.NameValuePair)
      */
-    public void addParameters(NameValuePair[] parameters) 
-        throws IllegalStateException {
-            
-        LOG.trace("enter PostMethod.addParameters(NameValuePair[])");
+    public void addParameters(NameValuePair[] parameters) {
+        log.trace("enter PostMethod.addParameters(NameValuePair[])");
 
-        if (null != requestBody) {
+        if (hasRequestBody()) {
             throw new IllegalStateException("Request body already generated.");
         }
-
-        if (null == parameters) {
-            LOG.warn("Attempt to addParameters(null) ignored");
+        if (parameters == null) {
+            log.warn("Attempt to addParameters(null) ignored");
         } else {
             for (int i = 0; i < parameters.length; i++) {
                 addParameter(parameters[i]);
@@ -556,22 +366,6 @@
     }
 
     /**
-     * Override method of {@link org.apache.commons.httpclient.HttpMethodBase}
-     * to clear my request body.
-     *
-     * @since 1.0
-     */
-    public void recycle() {
-        LOG.trace("enter PostMethod.recycle()");
-        super.recycle();
-        requestBody = null;
-        requestContentLength = CONTENT_LENGTH_AUTO;
-        buffer = null;
-        repeatCount = 0;
-        parameters.clear();
-    }
-
-    /**
      * Removes all parameters with the given paramName. If there is more than
      * 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
@@ -587,20 +381,16 @@
      *
      * @since 2.0
      */
-    public boolean removeParameter(String paramName) 
-        throws IllegalArgumentException, IllegalStateException {
-            
-        LOG.trace("enter PostMethod.removeParameter(String)");
+    public boolean removeParameter(String paramName) {
+        log.trace("enter PostMethod.removeParameter(String)");
 
-        if (null != requestBody) {
+        if (hasRequestBody()) {
             throw new IllegalStateException("Request body already generated.");
         }
-
         if (paramName == null) {
             throw new IllegalArgumentException(
                 "Argument passed to removeParameter(String) cannot be null");
         }
-
         boolean removed = true;
         Iterator iter = parameters.iterator();
 
@@ -612,7 +402,6 @@
                 removed = true;
             }
         }
-
         return removed;
     }
 
@@ -632,19 +421,17 @@
      *
      * @since 2.0
      */
-    public boolean removeParameter(String paramName, String paramValue)
-        throws IllegalArgumentException, IllegalStateException {
-            
-        LOG.trace("enter PostMethod.removeParameter(String, String)");
+    public boolean removeParameter(String paramName, String paramValue) {
+        log.trace("enter PostMethod.removeParameter(String, String)");
 
-        if (null != requestBody) {
+        if (hasRequestBody()) {
             throw new IllegalStateException("Request body already generated.");
         }
-
-        if ((paramName == null) || (paramValue == null)) {
-            throw new IllegalArgumentException(
-                "Argument passed to removeParameter(String,String) cannot be "
-                + "null");
+        if (paramName == null) {
+            throw new IllegalArgumentException("Parameter name may not be null");
+        }
+        if (paramValue == null) {
+            throw new IllegalArgumentException("Parameter value may not be null");
         }
 
         Iterator iter = parameters.iterator();
@@ -655,221 +442,220 @@
             if (paramName.equals(pair.getName())
                 && paramValue.equals(pair.getValue())) {
                 iter.remove();
-
                 return true;
             }
         }
-
         return false;
     }
 
     /**
-     * Override method of {@link org.apache.commons.httpclient.HttpMethodBase}
-     * to return the length of the request body.
+     * Encode the list of parameters into a query string.
      *
-     * @return number of bytes in the request body
+     * @param params the list of query name and value
+     *
+     * @return the query string
      *
      * @since 2.0
      */
-    protected int getRequestContentLength() {
-        LOG.trace("enter PostMethod.getRequestContentLength()");
+    protected static String generateRequestBody(List params) {
+        log.trace("enter PostMethod.generateRequestBodyAsString(List)");
 
-        if (null == requestBody) {
-            requestBody = generateRequestBody(parameters);
-            bufferContent();
-        }
-
-        if (requestContentLength != CONTENT_LENGTH_AUTO) {
-            return requestContentLength;
-        }
+        Iterator it = params.iterator();
+        StringBuffer buff = new StringBuffer();
 
-        bufferContent();
+        while (it.hasNext()) {
+            NameValuePair parameter = (NameValuePair) it.next();
 
-        return requestContentLength;
+            String queryName = null;
+            try {
+                queryName = URIUtil.encodeWithinQuery(parameter.getName());
+            } catch (URIException urie) {
+                log.error("encoding error within query name", urie);
+                queryName = parameter.getName();
+            }
+            buff.append(queryName).append("=");
+            String queryValue = null;
+            try {
+                queryValue = URIUtil.encodeWithinQuery(parameter.getValue());
+            } catch (URIException urie) {
+                log.error("encoding error within query value", urie);
+                queryValue = parameter.getValue();
+            }
+            buff.append(queryValue);
+            if (it.hasNext()) {
+                buff.append("&");
+            }
+        }
+        return buff.toString();
     }
 
     /**
-     * Override method of {@link org.apache.commons.httpclient.HttpMethodBase}
-     * to  also add <tt>Content-Type</tt> header when appropriate.
+     * Sets the request body to be the specified string.
      *
-     * @param state DOCUMENT ME!
-     * @param conn DOCUMENT ME!
-     * @throws IOException DOCUMENT ME!
-     * @throws HttpException DOCUMENT ME!
+     * <p>
+     * Once this method has been invoked,  the request parameters  cannot be
+     * altered until I am {@link #recycle recycled}.
+     * </p>
+     *
+     * @param body Request body content as a string
+     *
+     * @throws IllegalStateException if request params have been added
      *
      * @since 2.0
      */
-    protected void addRequestHeaders(HttpState state, HttpConnection conn)
-    throws IOException, HttpException {
-        super.addRequestHeaders(state, conn);
+    public void setRequestBody(String body) {
+        log.trace("enter PostMethod.setRequestBody(String)");
 
         if (!parameters.isEmpty()) {
-            //there are some parameters, so set the contentType header
-            setRequestHeader(CONTENT_TYPE);
+            throw new IllegalStateException(
+                "Request parameters have already been added.");
         }
+        super.setRequestBody(body);
     }
 
     /**
-     * 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.
+     * Sets the request body to be the specified inputstream.
      *
-     * @param state DOCUMENT ME!
-     * @param conn DOCUMENT ME!
+     * <p>
+     * Once this method has been invoked,  the request parameters  cannot be
+     * altered until I am {@link #recycle recycled}.
+     * </p>
      *
-     * @return always returns true
+     * @param body Request body content as {@link java.io.InputStream}
      *
-     * @throws IOException if the stream ends before the specified content
-     *         length. <p>
-     * @throws HttpException DOCUMENT ME!
+     * @throws IllegalStateException if request params have been added
      *
      * @since 2.0
      */
-    protected boolean writeRequestBody(HttpState state, HttpConnection conn)
-    throws IOException, HttpException {
-        LOG.trace(
-            "enter PostMethod.writeRequestBody(HttpState, HttpConnection)");
+    public void setRequestBody(InputStream body) {
+        log.trace("enter PostMethod.getRequestBody(InputStream)");
 
-        if (null == requestBody) {
-            requestBody = generateRequestBody(parameters);
+        if (!parameters.isEmpty()) {
+            throw new IllegalStateException(
+                "Request parameters have already been added.");
         }
+        super.setRequestBody(body);
+    }
 
-        if ((repeatCount > 0) && (buffer == null)) {
-            throw new HttpException(
-                "Sorry, unbuffered POST request can not be repeated.");
+    /**
+     * 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() {
+        log.trace("enter PostMethod.getRequestBody()");
+        if (!parameters.isEmpty()) {
+            return new ByteArrayInputStream(
+              HttpConstants.getContentBytes(
+                generateRequestBody(parameters), getRequestCharSet()));
         }
+        else {
+            return super.getRequestBody();
+        }
+    }
 
-        repeatCount++;
-
-        InputStream instream = this.requestBody;
-        OutputStream outstream = conn.getRequestOutputStream();
+    /**
+     * Gets the request body string as it would be if it was executed.
+     *
+     * @return the request body as a string
+     * 
+     * @throws IOException when i/o errors occur reading the request
+     *
+     * @since 2.0
+     */
 
-        if (this.requestContentLength == CONTENT_LENGTH_CHUNKED) {
-            outstream = new ChunkedOutputStream(outstream);
+    public String getRequestBodyAsString() throws IOException {
+        log.trace("enter PostMethod.getRequestBody()");
+        if (!parameters.isEmpty()) {
+            return generateRequestBody(parameters);
         }
-        if (this.requestContentLength >= 0) {
-            // don't need a watcher here - we're reading from something local,
-            // not server-side.
-            instream = new ContentLengthInputStream(instream, 
this.requestContentLength);
+        else {
+            return super.getRequestBodyAsString();
         }
+    }
 
-        byte[] tmp = new byte[4096];
-        int total = 0;
-        int i = 0;
-        while ((i = instream.read(tmp)) >= 0) {
-            outstream.write(tmp, 0, i);
-            total += i;
-        }
-        if (outstream instanceof ChunkedOutputStream) {
-            ((ChunkedOutputStream) outstream).writeClosingChunk();
-        }
-        if ((this.requestContentLength > 0) && (total < this.requestContentLength)) {
-            throw new IOException("Unexpected end of input stream after "
-                + total + " bytes (expected " 
-                + this.requestContentLength + " bytes)");
-        }
+    /**
+     * 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() {
+        log.trace("enter PostMethod.getRequestContentLength()");
 
-        if (buffer != null) {
-            //restore buffered content for repeated requests
-            requestBody = new ByteArrayInputStream(buffer.toByteArray());
+        if (!hasRequestBody()) {
+            super.setRequestBody(generateRequestBody(parameters));
+            bufferContent();
         }
-
-        return true;
+        return super.getRequestContentLength();
     }
 
-
     /**
-     * Encode the list of parameters into a query stream.
-     *
-     * @param params the list of query name and value
+     * Override method of {@link org.apache.commons.httpclient.HttpMethodBase}
+     * to  also add <tt>Content-Type</tt> header when appropriate.
      *
-     * @return the query stream
+     * @param state the client state
+     * @param conn the {@link HttpConnection} the headers will eventually be
+     *        written to
+     * @throws IOException when an error occurs writing the request
+     * @throws HttpException when a HTTP protocol error occurs
      *
-     * @since 1.0
+     * @since 2.0
      */
-    protected InputStream generateRequestBody(List params) {
-        LOG.trace("enter PostMethod.generateRequestBody(List)");
-        String body = generateRequestBodyAsString(params);
+    
+    protected void addRequestHeaders(HttpState state, HttpConnection conn)
+    throws IOException, HttpException {
+        super.addRequestHeaders(state, conn);
 
-        return new ByteArrayInputStream(
-          HttpConstants.getContentBytes(body, getRequestCharSet()));
+        if (!parameters.isEmpty()) {
+            //there are some parameters, so set the contentType header
+            setRequestHeader(CONTENT_TYPE);
+        }
     }
 
-
-    // ------------------------------------------------------------Class Methods
-
     /**
-     * Encode the list of parameters into a query string.
+     * 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 the client state
+     * @param conn the connection to write to
      *
-     * @param params the list of query name and value
+     * @return always returns true
      *
-     * @return the query string
+     * @throws IOException if the stream ends before the specified content
+     *         length. <p>
+     * @throws HttpException when a protocol error occurs or state is invalid
      *
      * @since 2.0
      */
-    protected static String generateRequestBodyAsString(List params) {
-        LOG.trace("enter PostMethod.generateRequestBodyAsString(List)");
 
-        Iterator it = params.iterator();
-        StringBuffer buff = new StringBuffer();
-
-        while (it.hasNext()) {
-            NameValuePair parameter = (NameValuePair) it.next();
+    protected boolean writeRequestBody(HttpState state, HttpConnection conn)
+    throws IOException, HttpException {
+        log.trace(
+            "enter PostMethod.writeRequestBody(HttpState, HttpConnection)");
 
-            String queryName = null;
-            try {
-                queryName = URIUtil.encodeWithinQuery(parameter.getName());
-            } catch (URIException urie) {
-                LOG.error("encoding error within query name", urie);
-                queryName = parameter.getName();
-            }
-            buff.append(queryName).append("=");
-            String queryValue = null;
-            try {
-                queryValue = URIUtil.encodeWithinQuery(parameter.getValue());
-            } catch (URIException urie) {
-                LOG.error("encoding error within query value", urie);
-                queryValue = parameter.getValue();
-            }
-            buff.append(queryValue);
-            if (it.hasNext()) {
-                buff.append("&");
-            }
+        if (!hasRequestBody()) {
+            super.setRequestBody(generateRequestBody(parameters));
         }
-        return buff.toString();
+        return super.writeRequestBody(state, conn);
     }
 
     /**
-     * Buffers the request body and calculates the content length. If the
-     * method was called earlier it returns immediately.
+     * Override method of {@link org.apache.commons.httpclient.HttpMethodBase}
+     * to clear my request body.
      *
      * @since 1.0
      */
-    private void bufferContent() {
-        LOG.trace("enter PostMethod.bufferContent()");
-
-        if (buffer != null) {
-            return;
-        }
-
-        try {
-            buffer = new ByteArrayOutputStream();
-
-            byte[] data = new byte[10000];
-            int l = requestBody.read(data);
-            int total = 0;
-
-            while (l > 0) {
-                buffer.write(data, 0, l);
-                total += l;
-                l = requestBody.read(data);
-            }
-
-            requestBody = new ByteArrayInputStream(buffer.toByteArray());
-            requestContentLength = total;
-        } catch (IOException e) {
-            requestBody = null;
-            requestContentLength = 0;
-        }
+    public void recycle() {
+        log.trace("enter PostMethod.recycle()");
+        super.recycle();
+        this.parameters.clear();
     }
+
 }
Index: java/org/apache/commons/httpclient/methods/PutMethod.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PutMethod.java,v
retrieving revision 1.20
diff -u -r1.20 PutMethod.java
--- java/org/apache/commons/httpclient/methods/PutMethod.java   28 Jan 2003 22:25:28 
-0000      1.20
+++ java/org/apache/commons/httpclient/methods/PutMethod.java   29 Jan 2003 16:12:02 
+-0000
@@ -1,8 +1,7 @@
 /*
- * $Header: 
/home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PutMethod.java,v
 1.20 2003/01/28 22:25:28 jsdever Exp $
- * $Revision: 1.20 $
- * $Date: 2003/01/28 22:25:28 $
- *
+ * $Header: 
+/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PutMethod.java,v
+ 1.19 2003/01/23 22:48:09 jsdever Exp $
+ * $Revision: 1.19 $
+ * $Date: 2003/01/23 22:48:09 $
  * ====================================================================
  *
  * The Apache Software License, Version 1.1
@@ -63,34 +62,15 @@
 
 package org.apache.commons.httpclient.methods;
 
-import org.apache.commons.httpclient.HttpConstants;
-import org.apache.commons.httpclient.HttpConnection;
-import org.apache.commons.httpclient.HttpException;
-import org.apache.commons.httpclient.HttpMethodBase;
-import org.apache.commons.httpclient.HttpState;
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URL;
-
-
 /**
  * PUT Method.
  *
  * @author <a href="mailto:[EMAIL PROTECTED]";>Remy Maucherat</a>
- * @author <a href="mailto:[EMAIL PROTECTED]";>Mike Bowler</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]";>Oleg Kalnichevski</a>
  *
  * @since 1.0
  */
-public class PutMethod extends HttpMethodBase {
+public class PutMethod extends EntityEnclosingMethod {
 
 
     // ----------------------------------------------------------- Constructors
@@ -118,28 +98,6 @@
         setFollowRedirects(false);
     }
 
-
-    // ------------------------------------------------------- Instance Methods
-
-
-    /**
-     * Request body content to be sent.
-     */
-    private byte[] data = null;
-
-
-    /**
-    * Request body content to be sent.
-     */
-    private File file = null;
-
-
-    /**
-     * Request body content to be sent.
-     */
-    private URL url = null;
-
-
     // --------------------------------------------------------- Public Methods
 
     /**
@@ -151,187 +109,4 @@
     public String getName() {
         return "PUT";
     }
-
-    /**
-     * Set my request body content to the contents of a file.
-     *
-     * @param file The file
-     * @throws IOException if an IO problem occurs
-     * @since 2.0
-     */
-    public void setRequestBody(File file) throws IOException {
-        checkNotUsed();
-        this.file = file;
-    }
-
-    /**
-     * Set my request body content to the resource at the specified URL.
-     *
-     * @param url The URL
-     * @throws IOException If an IO problem occurs.
-     * @since 2.0
-     */
-    public void setRequestBody(URL url) throws IOException {
-        checkNotUsed();
-        this.url = url;
-    }
-
-    /**
-     * Set my request body content to the contents of a byte array.
-     *
-     * @param bodydata The new content.
-     * @since 2.0
-     */
-    public void setRequestBody(byte[] bodydata) {
-        checkNotUsed();
-        this.data = bodydata;
-    }
-
-    /**
-     * Set my request body content to the contents of a string.
-     *
-     * @param bodydata The new content
-     * @since 2.0
-     */
-    public void setRequestBody(String bodydata) {
-        checkNotUsed();
-        setRequestBody(HttpConstants.getContentBytes(bodydata, getRequestCharSet()));
-    }
-
-    /**
-     * Set my request body content to the contents of an input stream. The
-     * contents will be buffered into memory. To upload large entities, it is
-     * recommended to first buffer the data into a temporary file, and then send
-     * that file.
-     *
-     * @param is The input stream.
-     * @throws IOException If an IO problem occurs
-     * @since 2.0
-     */
-    public void setRequestBody(InputStream is) throws IOException {
-        LOG.trace("enter PutMethod.setRequestBody(InputStream)");
-
-        checkNotUsed();
-        byte[] buffer = new byte[4096];
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
-        int nb = 0;
-        while (true) {
-            nb = is.read(buffer);
-            if (nb == -1) {
-                break;
-            }
-            os.write(buffer, 0, nb);
-        }
-        data = os.toByteArray();
-    }
-
-
-    // ------------------------------------------------- HttpMethodBase Methods
-
-    /**
-     * Override the method of {@link HttpMethodBase} to set the <tt>Expect</tt>
-     * header if it has not already been set, in addition to the "standard" set
-     * of headers.
-     * 
-     * @param state The state.
-     * @param conn The connection.
-     * @throws IOException If an IO problem occurs
-     * @throws HttpException Never.
-     * @since 2.0
-     */
-    protected void addRequestHeaders(HttpState state, HttpConnection conn)
-    throws IOException, HttpException {
-        // TODO: Determine why this method is declared to throw HttpException
-        // since it never actually does throw it.
-        LOG.trace("enter PutMethod.addRequestHeaders(HttpState, HttpConnection)");
-
-        super.addRequestHeaders(state, conn);
-        // Send expectation header
-        if (isHttp11() && null == getRequestHeader("expect")) {
-            setRequestHeader("Expect", "100-continue");
-        }
-    }
-
-    /**
-     * Override the method of {@link HttpMethodBase} to not send any data until
-     * the <tt>100 Continue</tt> status has not be read.
-     *
-     * @param state The state
-     * @param conn The connection
-     * @return true if the data was written.
-     * @throws IOException If an IO problem occurs
-     * @throws HttpException This doesn't ever seem to be thrown.
-     * @since 2.0
-     */
-    protected boolean writeRequestBody(HttpState state, HttpConnection conn)
-    throws IOException, HttpException {
-        LOG.trace("enter PutMethod.writeRequestBody(HttpState, HttpConnection)");
-         if (getStatusLine() == null) {
-             return false;
-         }
-         if (null != getRequestHeader("expect") 
-             && getStatusLine().getStatusCode() != HttpStatus.SC_CONTINUE) {
-            return false;
-        }
-        OutputStream out = conn.getRequestOutputStream((isHttp11() 
-            && (null == getRequestHeader("Content-Length"))));
-
-        InputStream inputStream = null;
-        if (file != null && file.exists()) {
-            inputStream = new FileInputStream(file);
-        } else if (url != null) {
-            inputStream = url.openConnection().getInputStream();
-        } else if (data != null) {
-            inputStream = new ByteArrayInputStream(data);
-        } else {
-            return true;
-        }
-
-        byte[] buffer = new byte[4096];
-        int nb = 0;
-        while (true) {
-            nb = inputStream.read(buffer);
-            if (nb == -1) {
-                break;
-            }
-            out.write(buffer, 0, nb);
-        }
-        out.flush();
-        return true;
-    }
-
-    /**
-     * Override the method of {@link HttpMethodBase}
-     * to return the appropriate content length.
-     *
-     * @return the content length
-     * @since 2.0
-     */
-    protected int getRequestContentLength() {
-        LOG.trace("enter PutMethod.getRequestContentLength()");
-
-        if (null != data) {
-            return data.length;
-        } else if (null != file && file.exists()) {
-            return (int) (file.length());
-        } else if (url != null) {
-            return -1;
-        } else {
-            return 0;
-        }
-    }
-
-    /**
-     *
-     * @since 1.0
-     */
-    public void recycle() {
-        super.recycle();
-        data = null;
-        url = null;
-        file = null;
-    }
-
-    /** Log object for this class. */
-    private static final Log LOG = LogFactory.getLog(PutMethod.class);
 }
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to