mbecke      2004/05/11 20:07:03

  Modified:    httpclient/src/java/org/apache/commons/httpclient/methods
                        PostMethod.java EntityEnclosingMethod.java
                        RequestEntity.java InputStreamRequestEntity.java
                        ByteArrayRequestEntity.java
               httpclient release_notes.txt
  Added:       httpclient/src/java/org/apache/commons/httpclient/methods
                        StringRequestEntity.java
  Log:
  Moved/added content type handling to RequestEntity.
  
  PR: 28645
  Submitted by: Michael Becke and Oleg Kalnichevski
  
  Revision  Changes    Path
  1.55      +13 -38    
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java
  
  Index: PostMethod.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java,v
  retrieving revision 1.54
  retrieving revision 1.55
  diff -u -r1.54 -r1.55
  --- PostMethod.java   28 Apr 2004 02:23:17 -0000      1.54
  +++ PostMethod.java   12 May 2004 03:07:03 -0000      1.55
  @@ -29,13 +29,9 @@
   
   package org.apache.commons.httpclient.methods;
   
  -import java.io.IOException;
   import java.util.Iterator;
   import java.util.Vector;
   
  -import org.apache.commons.httpclient.HttpConnection;
  -import org.apache.commons.httpclient.HttpException;
  -import org.apache.commons.httpclient.HttpState;
   import org.apache.commons.httpclient.NameValuePair;
   import org.apache.commons.httpclient.util.EncodingUtil;
   import org.apache.commons.logging.Log;
  @@ -162,9 +158,16 @@
        */
       protected RequestEntity generateRequestEntity() {
           if (!this.params.isEmpty()) {
  +            // Use a ByteArrayRequestEntity instead of a StringRequestEntity.
  +            // This is to avoid potential encoding issues.  Form url encoded strings
  +            // are ASCII by definition but the content type may not be.  Treating 
the content
  +            // as bytes allows us to keep the current charset without worrying 
about how
  +            // this charset will effect the encoding of the form url encoded string.
               String content = EncodingUtil.formUrlEncode(getParameters(), 
getRequestCharSet());
  -            ByteArrayRequestEntity entity = new ByteArrayRequestEntity();
  -            entity.setContent(EncodingUtil.getAsciiBytes(content));
  +            ByteArrayRequestEntity entity = new ByteArrayRequestEntity(
  +                EncodingUtil.getAsciiBytes(content),
  +                FORM_URL_ENCODED_CONTENT_TYPE
  +            );
               return entity;
           } else {
               return super.generateRequestEntity();
  @@ -400,33 +403,5 @@
           }
           clearRequestBody();
           addParameters(parametersBody);
  -    }
  -
  -    /**
  -     * Adds <tt>Content Type: application/x-www-form-urlencoded</tt> header in
  -     * addition to the "standard" set of headers, if no <tt>Content Type</tt>
  -     * header has been set by the user 
  -     * 
  -     * @param state the [EMAIL PROTECTED] HttpState state} information associated 
with this method
  -     * @param conn the [EMAIL PROTECTED] HttpConnection connection} used to execute
  -     *        this HTTP method
  -     *
  -     * @throws IOException if an I/O (transport) error occurs. Some transport 
exceptions
  -     *                     can be recovered from.
  -     * @throws HttpException  if a protocol exception occurs. Usually protocol 
exceptions 
  -     *                    cannot be recovered from.
  -     *
  -     * @since 2.0
  -     */
  -    protected void addRequestHeaders(HttpState state, HttpConnection conn)
  -    throws IOException, HttpException {
  -        super.addRequestHeaders(state, conn);
  -
  -        if (!this.params.isEmpty()) {
  -            //there are some parameters, so set the contentType header
  -            if (getRequestHeader("Content-Type") == null) {
  -                setRequestHeader("Content-Type", FORM_URL_ENCODED_CONTENT_TYPE);
  -            }
  -        }
       }
   }
  
  
  
  1.34      +44 -15    
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java
  
  Index: EntityEnclosingMethod.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- EntityEnclosingMethod.java        8 May 2004 10:12:07 -0000       1.33
  +++ EntityEnclosingMethod.java        12 May 2004 03:07:03 -0000      1.34
  @@ -34,12 +34,12 @@
   import java.io.OutputStream;
   
   import org.apache.commons.httpclient.ChunkedOutputStream;
  +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.HttpVersion;
   import org.apache.commons.httpclient.ProtocolException;
  -import org.apache.commons.httpclient.util.EncodingUtil;
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
   
  @@ -60,12 +60,14 @@
       /**
        * The content length will be calculated automatically. This implies
        * buffering of the content.
  +     * @deprecated Use [EMAIL PROTECTED] 
InputStreamRequestEntity#CONTENT_LENGTH_AUTO}.
        */
       public static final long CONTENT_LENGTH_AUTO = -2;
   
       /**
        * The request will use chunked transfer encoding. Content length is not
        * calculated and the content is not buffered.<br>
  +     * @deprecated Use [EMAIL PROTECTED] #setContentChunked(boolean)}.
        */
       public static final long CONTENT_LENGTH_CHUNKED = -1;
   
  @@ -167,19 +169,17 @@
           if (requestBody != null) {
               // use the request body, if it exists.
               // this is just for backwards compatability
  -            ByteArrayRequestEntity entity = new ByteArrayRequestEntity();
  -            entity.setContent(requestBody);
  -            this.requestEntity = entity;
  +            this.requestEntity = new ByteArrayRequestEntity(requestBody);
           } else if (this.requestStream != null) {
  -            InputStreamRequestEntity entity = new InputStreamRequestEntity();
  -            entity.setContent(requestStream);
  -            entity.setContentLength(requestContentLength);
  +            this.requestEntity = new InputStreamRequestEntity(
  +                requestStream, 
  +                requestContentLength);
               this.requestStream = null;
  -            this.requestEntity = entity;
           } else if (this.requestString != null) {
  -            ByteArrayRequestEntity entity = new ByteArrayRequestEntity();
  -            entity.setContent(EncodingUtil.getBytes(this.requestString, 
getRequestCharSet()));
  -            this.requestEntity = entity;
  +            this.requestEntity = new StringRequestEntity(
  +                requestString,
  +                null,
  +                getRequestCharSet());
           }
   
           return this.requestEntity;
  @@ -238,6 +238,25 @@
           this.requestContentLength = length;
       }
   
  +    /* (non-Javadoc)
  +     * @see org.apache.commons.httpclient.HttpMethodBase#getRequestCharSet()
  +     */
  +    public String getRequestCharSet() {
  +        if (getRequestHeader("Content-Type") == null) {
  +            // check the content type from request entity
  +            // We can't call getRequestEntity() since it will probably call
  +            // this method.
  +            if (this.requestEntity != null) {
  +                return getContentCharSet(
  +                    new Header("Content-Type", requestEntity.getContentType()));
  +            } else {
  +                return super.getRequestCharSet();
  +            }
  +        } else {
  +            return super.getRequestCharSet();
  +        }
  +    }
  +
       /**
        * Sets length information about the request body.
        *
  @@ -330,7 +349,17 @@
   
           super.addRequestHeaders(state, conn);
           addContentLengthRequestHeader(state, conn);
  +
  +        // only use the content type of the request entity if it has not already 
been
  +        // set manually
  +        if (getRequestHeader("Content-Type") == null) {
  +            RequestEntity requestEntity = getRequestEntity();
  +            if (requestEntity != null && requestEntity.getContentType() != null) {
  +                setRequestHeader("Content-Type", requestEntity.getContentType());
  +            }
  +        }
       }
  +    
       /**
        * Generates <tt>Content-Length</tt> or <tt>Transfer-Encoding: Chunked</tt>
        * request header, as long as no <tt>Content-Length</tt> request header
  
  
  
  1.2       +11 -3     
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/RequestEntity.java
  
  Index: RequestEntity.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/RequestEntity.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- RequestEntity.java        28 Apr 2004 02:23:17 -0000      1.1
  +++ RequestEntity.java        12 May 2004 03:07:03 -0000      1.2
  @@ -56,4 +56,12 @@
        */
       long getContentLength();
       
  +    /**
  +     * Gets the entity's content type.  This content type will be used as the value 
for the
  +     * "Content-Type" header.
  +     * @return
  +     * @see org.apache.commons.httpclient.HttpMethod#setRequestHeader(String, 
String)
  +     */
  +    String getContentType();
  +    
   }
  
  
  
  1.2       +70 -28    
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java
  
  Index: InputStreamRequestEntity.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- InputStreamRequestEntity.java     28 Apr 2004 02:23:17 -0000      1.1
  +++ InputStreamRequestEntity.java     12 May 2004 03:07:03 -0000      1.2
  @@ -43,21 +43,83 @@
    */
   public class InputStreamRequestEntity implements RequestEntity {
   
  +    /**
  +     * The content length will be calculated automatically. This implies
  +     * buffering of the content.
  +     */
  +    public static final int CONTENT_LENGTH_AUTO = -2;
  +    
       private static final Log LOG = 
LogFactory.getLog(InputStreamRequestEntity.class);
       
  -    private long contentLength = EntityEnclosingMethod.CONTENT_LENGTH_AUTO;
  +    private long contentLength;
       
  -    private InputStream content = null;
  +    private InputStream content;
   
       /** The buffered request body, if any. */
       private byte[] buffer = null;
  +    
  +    /** The content type */
  +    private String contentType;
   
       /**
  -     * Creates a new InputStreamRequestEntity with no content.
  +     * Creates a new InputStreamRequestEntity with the given content and a content 
type of
  +     * [EMAIL PROTECTED] RequestEntity#CONTENT_LENGTH_AUTO}.
  +     * @param content The content to set.
        */
  -    public InputStreamRequestEntity() {
  +    public InputStreamRequestEntity(InputStream content) {
  +        this(content, null);
  +    }
  +    
  +    /**
  +     * Creates a new InputStreamRequestEntity with the given content, content type, 
and a 
  +     * content length of [EMAIL PROTECTED] RequestEntity#CONTENT_LENGTH_AUTO}.
  +     * @param content The content to set.
  +     * @param contentType The type of the content, or <code>null</code>.
  +     */
  +    public InputStreamRequestEntity(InputStream content, String contentType) {
  +        this(content, CONTENT_LENGTH_AUTO, contentType);
  +    }
  +
  +    /**
  +     * Creates a new InputStreamRequestEntity with the given content and content 
length.
  +     * @param content The content to set.
  +     * @param contentLength The content size in bytes or any of 
  +     *  [EMAIL PROTECTED] EntityEnclosingMethod#CONTENT_LENGTH_AUTO 
CONTENT_LENGTH_AUTO},
  +     *  [EMAIL PROTECTED] EntityEnclosingMethod#CONTENT_LENGTH_CHUNKED 
CONTENT_LENGTH_CHUNKED}. If the number 
  +     *  of bytes or <code>CONTENT_LENGTH_CHUNKED</code> is specified the content 
will not be 
  +     *  buffered when [EMAIL PROTECTED] #getContentLength()} is called.
  +     */
  +    public InputStreamRequestEntity(InputStream content, long contentLength) {
  +        this(content, contentLength, null);
  +    }
  +    
  +    /**
  +     * Creates a new InputStreamRequestEntity with the given content, content 
length, and 
  +     * content type.
  +     * @param content The content to set.
  +     * @param contentLength The content size in bytes or any of 
  +     *  [EMAIL PROTECTED] EntityEnclosingMethod#CONTENT_LENGTH_AUTO 
CONTENT_LENGTH_AUTO},
  +     *  [EMAIL PROTECTED] EntityEnclosingMethod#CONTENT_LENGTH_CHUNKED 
CONTENT_LENGTH_CHUNKED}. If the number 
  +     *  of bytes or <code>CONTENT_LENGTH_CHUNKED</code> is specified the content 
will not be 
  +     *  buffered when [EMAIL PROTECTED] #getContentLength()} is called.
  +     * @param contentType The type of the content, or <code>null</code>.
  +     */
  +    public InputStreamRequestEntity(InputStream content, long contentLength, String 
contentType) {
  +        if (content == null) {
  +            throw new IllegalArgumentException("The content cannot be null");
  +        }
  +        this.content = content;
  +        this.contentLength = contentLength;
  +        this.contentType = contentType;
       }
   
  +    /* (non-Javadoc)
  +     * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType()
  +     */
  +    public String getContentType() {
  +        return contentType;
  +    }
  +    
       /**
        * Buffers request body input stream.
        */
  @@ -125,37 +187,17 @@
        * @see #setContentLength(long)
        */
       public long getContentLength() {
  -        if (contentLength == EntityEnclosingMethod.CONTENT_LENGTH_AUTO && buffer == 
null) {
  +        if (contentLength == CONTENT_LENGTH_AUTO && buffer == null) {
               bufferContent();
           }
           return contentLength;
       }
   
       /**
  -     * Sets the content length.
  -     * 
  -     * @param contentLength The content size in bytes or any of 
  -     * [EMAIL PROTECTED] EntityEnclosingMethod#CONTENT_LENGTH_AUTO 
CONTENT_LENGTH_AUTO},
  -     * [EMAIL PROTECTED] EntityEnclosingMethod#CONTENT_LENGTH_CHUNKED 
CONTENT_LENGTH_CHUNKED}. If the number 
  -     * of bytes or <code>CONTENT_LENGTH_CHUNKED</code> is specified the content 
will not be 
  -     * buffered when [EMAIL PROTECTED] #getContentLength()} is called.
  -     */
  -    public void setContentLength(long contentLength) {
  -        this.contentLength = contentLength;
  -    }
  -
  -    /**
        * @return Returns the content.
        */
       public InputStream getContent() {
           return content;
  -    }
  -
  -    /**
  -     * @param inputStream The content to set.
  -     */
  -    public void setContent(InputStream inputStream) {
  -        this.content = inputStream;
       }
   
   }
  
  
  
  1.2       +30 -19    
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/ByteArrayRequestEntity.java
  
  Index: ByteArrayRequestEntity.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/ByteArrayRequestEntity.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ByteArrayRequestEntity.java       28 Apr 2004 02:23:17 -0000      1.1
  +++ ByteArrayRequestEntity.java       12 May 2004 03:07:03 -0000      1.2
  @@ -41,12 +41,29 @@
       /** The content */
       private byte[] content;
       
  +    /** The content type */
  +    private String contentType;
  +
  +    /**
  +     * Creates a new entity with the given content.
  +     * @param content The content to set.
  +     */
  +    public ByteArrayRequestEntity(byte[] content) {
  +        this(content, null);
  +    }
  +    
       /**
  -     * Creates a new entity with no content.  The content must be set before this 
entity can be 
  -     * used. 
  +     * Creates a new entity with the given content and content type.
  +     * @param content The content to set.
  +     * @param contentType The content type to set or <code>null</code>.
        */
  -    public ByteArrayRequestEntity() {
  +    public ByteArrayRequestEntity(byte[] content, String contentType) {
           super();
  +        if (content == null) {
  +            throw new IllegalArgumentException("The content cannot be null");
  +        }
  +        this.content = content;
  +        this.contentType = contentType;
       }
   
       /**
  @@ -57,12 +74,16 @@
       }
   
       /* (non-Javadoc)
  +     * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType()
  +     */
  +    public String getContentType() {
  +        return contentType;
  +    }
  +    
  +    /* (non-Javadoc)
        * @see 
org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream)
        */
       public void writeRequest(OutputStream out) throws IOException {
  -        if (content == null) {
  -            throw new IllegalStateException("Content must be set before entity is 
written");
  -        }
           out.write(content);
       }
   
  @@ -78,16 +99,6 @@
        */
       public byte[] getContent() {
           return content;
  -    }
  -
  -    /**
  -     * @param content The content to set.
  -     */
  -    public void setContent(byte[] content) {
  -        if (content == null) {
  -            throw new IllegalArgumentException("The content cannot be null");
  -        }
  -        this.content = content;
       }
   
   }
  
  
  
  1.1                  
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/StringRequestEntity.java
  
  Index: StringRequestEntity.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/StringRequestEntity.java,v
 1.1 2004/05/12 03:07:03 mbecke Exp $
   * $Revision: 1.1 $
   * $Date: 2004/05/12 03:07:03 $
   *
   * ====================================================================
   *
   *  Copyright 2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   * ====================================================================
   *
   * 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.IOException;
  import java.io.OutputStream;
  import java.io.OutputStreamWriter;
  import java.io.Writer;
  
  import org.apache.commons.httpclient.HeaderElement;
  import org.apache.commons.httpclient.NameValuePair;
  
  /**
   * A RequestEntity that contains a String.
   */
  public class StringRequestEntity implements RequestEntity {
  
      /** The content */
      private String content;
      
      /** The charset */
      private String charset;
  
      /** The content type (i.e. text/html; charset=EUC-JP). */
      private String contentType;
      
  
      /**
       * Creates a new entity with the given content
       *  
       * @param content The content to set.
       */
      public StringRequestEntity(String content) {
          this(content, null, null);
      }
  
      /**
       * Creates a new entity with the given content, content type, and charset.
       *  
       * @param content The content to set.
       * @param contentType The type of the content, or <code>null</code>.  The value 
retured 
       *   by [EMAIL PROTECTED] #getContentType()}.  If this content type contains a 
charset and the charset
       *   parameter is null, the content's type charset will be used.
       * @param charset The charset of the content, or <code>null</code>.  Used to 
convert the 
       *   content to bytes.  If the content type does not contain a charset and 
charset is not null,
       *   then the charset will be appended to the content type.
       */
      public StringRequestEntity(String content, String contentType, String charset) {
          super();
          if (content == null) {
              throw new IllegalArgumentException("The content cannot be null");
          }
          
          this.content = content;
          this.contentType = contentType;
          this.charset = charset;
          
          // resolve the content type and the charset
          if (contentType != null) {
              HeaderElement[] values = HeaderElement.parseElements(contentType);
              NameValuePair charsetPair = null;
              for (int i = 0; i < values.length; i++) {
                  if ((charsetPair = values[i].getParameterByName("charset")) != null) 
{
                      // charset found
                      break;
                  }
              }
              if (charset == null && charsetPair != null) {
                  // use the charset from the content type
                  this.charset = charsetPair.getValue();
              } else if (charset != null && charsetPair == null) {
                  // append the charset to the content type
                  this.contentType = contentType + "; charset=" + charset; 
              }
          }
      }
  
      /* (non-Javadoc)
       * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType()
       */
      public String getContentType() {
          return contentType;
      }
  
      /**
       * @return <code>true</code>
       */
      public boolean isRepeatable() {
          return true;
      }
  
      /* (non-Javadoc)
       * @see 
org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream)
       */
      public void writeRequest(OutputStream out) throws IOException {
          Writer writer = null;
          if (this.charset != null) {
              writer = new OutputStreamWriter(out, this.charset); 
          } else {
              writer = new OutputStreamWriter(out); 
          }
          writer.write(content);
          writer.flush();
      }
  
      /**
       * @return The length of the content.
       */
      public long getContentLength() {
          return content.length();
      }
  
      /**
       * @return Returns the content.
       */
      public String getContent() {
          return this.content;
      }
  
      /**
       * @return Returns the charset used to convert the content to bytes. 
<code>null</code> if
       * no charset as been specified.
       */
      public String getCharset() {
          return charset;
      }
  }
  
  
  
  1.24      +3 -0      jakarta-commons/httpclient/release_notes.txt
  
  Index: release_notes.txt
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/httpclient/release_notes.txt,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- release_notes.txt 11 May 2004 20:48:12 -0000      1.23
  +++ release_notes.txt 12 May 2004 03:07:03 -0000      1.24
  @@ -50,6 +50,9 @@
   Changes on the CVS trunk:
   -------------------------
   
  + * 28645 - Moved/added content type handling to the RequestEntity.
  +           Contributed by Michael Becke <mbecke at apache.org>, Oleg Kalnichevski 
<olegk at apache.org>
  +
    * 20288 - Added ability to abort execution of HTTP methods
              Contributed by Oleg Kalnichevski <olegk at apache.org>
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to