Hey Mike In order to avoid double buffering, one can simply provide a request body via setRequestBody(InputStream) AND setRequestContentLength(int) to an integer value other than CONTENT_LENGTH_AUTO. The request body content will be read out of the InputStream without having to be stored in a intermediary buffer
Cheers Oleg On Wed, 2003-01-29 at 19:03, Michael Becke wrote: > Hi Oleg, > > Just a quick question. Why do we want to keep from having to calculate > the content length? Is this just for the case of when the Post content > is set via setRequestBody(InputStream)? > > Thanks, > > Mike > > Kalnichevski, Oleg wrote: > > 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] > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] -- Oleg Kalnichevski <[EMAIL PROTECTED]> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]