commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From d...@apache.org
Subject cvs commit: jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods PostMethod.java
Date Wed, 10 Jul 2002 11:33:29 GMT
dion        2002/07/10 04:33:29

  Modified:    httpclient/src/java/org/apache/commons/httpclient/methods
                        PostMethod.java
  Log:
  Fix for bug 10634 kindly provided by Jeffrey Dever.
  Cleanups and tests also provided.
  
  Revision  Changes    Path
  1.11      +179 -137  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.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- PostMethod.java	10 Jul 2002 04:54:58 -0000	1.10
  +++ PostMethod.java	10 Jul 2002 11:33:29 -0000	1.11
  @@ -62,23 +62,39 @@
   
   package org.apache.commons.httpclient.methods;
   
  -import java.io.*;
  -import java.util.*;
   import org.apache.commons.httpclient.HttpState;
   import org.apache.commons.httpclient.HttpConnection;
   import org.apache.commons.httpclient.HttpMethodBase;
   import org.apache.commons.httpclient.HttpException;
   import org.apache.commons.httpclient.URIUtil;
   import org.apache.commons.httpclient.NameValuePair;
  -import java.util.Iterator;
  -import java.util.HashMap;
  -import java.util.List;
  +import org.apache.commons.httpclient.Header;
   import org.apache.commons.httpclient.log.Log;
   import org.apache.commons.httpclient.log.LogSource;
   
  +import java.util.Vector;
  +import java.io.IOException;
  +import java.util.Iterator;
  +import java.util.List;
  +
   /**
    * POST Method.
  + * This class encapsulates the HTTP POST specification.  According to
  + * <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
  + * <blockquote>The POST method is used to request that the origin server accept the
  + * entity enclosed in the request as a new subordinate of the resource
  + * identified by the Request-URI in the Request-Line. POST is designed
  + * to allow a uniform method to cover the following functions:
  + * <ul><li>Annotation of existing resources;
  + *     <li>Posting a message to a bulletin board, newsgroup, mailing list,
  + *         or similar group of articles;
  + *     <li>Providing a block of data, such as the result of submitting a
  + *         form, to a data-handling process;
  + *     <li>Extending a database through an append operation.
  + * </ul>
  + * </blockquote>
    *
  + * @author <a href="mailto:jsdever@sympatico.ca">Jeffrey Dever</a>
    * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
    * @author <a href="mailto:dsale@us.britannica.com">Doug Sale</a>
    */
  @@ -103,7 +119,7 @@
       }
   
       /**
  -     * Constructor.
  +     * Path and temp directory constructor.
        * @param path the path to request
        * @param tempDir directory to store temp files in
        */
  @@ -112,7 +128,7 @@
       }
   
       /**
  -     * Constructor.
  +     * Path, temp directory and temp file constructor.
        * @param path the path to request
        * @param tempDir directory to store temp files in
        * @param tempFile file to store temporary data in
  @@ -121,7 +137,8 @@
           super(path, tempDir, tempFile);
       }
   
  -    // ----------------------------------------------------- HttpMethod Methods
  +
  +    // ----------------------------------------------------- Instance Methods
   
       /**
        * Returns <tt>"POST"</tt>.
  @@ -142,71 +159,62 @@
       }
   
       /**
  -     * Overrides method of {@link HttpMethodBase}
  -     * to throw {@link IllegalStateException} if
  -     * my request body has already been
  -     * {@link #generateRequestBody generated}
  -     * or {@link #setRequestBody set}.
  +     * Set the value of parameter with parameterName to parameterValue.
  +     * Does not preserve the initial insertion order.
        *
        * @throws IllegalStateException if my request body has already been generated.
  +     * @deprecated use #removeParameter followed by #setParameter
        */
       public void setParameter(String parameterName, String parameterValue) {
           if(null != requestBody) {
               throw new IllegalStateException("Request body already generated.");
           }
  -        parameters.put(parameterName,parameterValue);
  +        removeParameter(parameterName, parameterValue);
  +        addParameter(parameterName, parameterValue);
       }
   
       /**
        * Add a new parameter to be used in the POST request body.
        *
  -     * @param parameterName The parameter name to add.
  -     * @param parameterValue The parameter value to add.
  +     * @param paramName The parameter name to add.
  +     * @param paramValue The parameter value to add.
        * @throws IllegalStateException if my request body has already been generated.
  +     * @throws IllegalArgumentException if either argument is null
        */
  -    public void addParameter(String parameterName, String parameterValue) {
  +    public void addParameter(String paramName, String paramValue) {
           if(null != requestBody) {
               throw new IllegalStateException("Request body already generated.");
           }
  -        Object old = parameters.put(parameterName,parameterValue);
  -        if(null != old) {
  -            List v = null;
  -            if(old instanceof String) {
  -                v = new ArrayList();
  -                v.add(old);
  -            } else if(old instanceof List) {
  -                v = (List)old;
  -            } else {
  -                throw new ClassCastException("Didn't expect to find " +
  -                                             old.getClass().getName() +
  -                                             " as parameter value for \"" +
  -                                             parameterName + "\"");
  -            }
  -            v.add(parameterValue);
  -            parameters.put(parameterName,v);
  +        if (paramName == null || paramValue == null){
  +            throw new IllegalArgumentException("Arguments to addParameter(String, String)
cannot be null");
  +        }else{
  +            parameters.add(new NameValuePair(paramName, paramValue));
           }
       }
   
   
       /**
        * Add a new parameter to be used in the POST request body.
  -     * Logs a warning if the parameter argument is null.
        *
        * @param parameter The parameter to add.
        * @throws IllegalStateException if my request body has already been generated.
  -     * @see #addParameter(java.lang.String,java.lang.String)
  +     * @throws IllegalArgumentException if the argument is null or contains null values
  +     * @see #addParameter(String,String)
        * @since 2.0
        */
  -    public void addParameter(NameValuePair parameter) {
  -        if(null == parameter){
  -            log.warn("Attempt to addParameter(null) ignored");
  +    public void addParameter(NameValuePair param) {
  +        if(null != requestBody) {
  +            throw new IllegalStateException("Request body already generated.");
  +        }
  +        if(null == param){
  +            throw new IllegalArgumentException("Argument to addParameter(NameValuePair)
cannot be null");
           }else{
  -            addParameter(parameter.getName(), parameter.getValue());
  +            addParameter(param.getName(), param.getValue());
           }
       }
   
       /**
  -     * Add a list of parameters to be used in the POST request body.
  +     * Add an Array of parameters to be used in the POST request body.
        * Logs a warning if the parameters argument is null.
        *
        * @param parameter The array of parameters to add.
  @@ -215,6 +223,9 @@
        * @since 2.0
        */
       public void addParameters(NameValuePair[] parameters) {
  +        if(null != requestBody) {
  +            throw new IllegalStateException("Request body already generated.");
  +        }
           if(null == parameters){
               log.warn("Attempt to addParameters(null) ignored");
           }else{
  @@ -227,98 +238,112 @@
   
       /**
        * Gets the parameter of the specified name.
  -     * The returned object is new and is <b>not</b> a refrence to any 
  -     * internal data members.
  +     * If there exists more than one parameter with the name paramName,
  +     * then only the first one is returned.
        * 
        * @return If a parameter exists with the name argument, the coresponding
        * NameValuePair is returned.  Otherwise null.
        * @since 2.0
        */
  -    public NameValuePair getParameter(String name){
  -        String value = null;
  -        try{
  -            value = (String)parameters.get(name);
  -        }catch (ClassCastException e){
  -            log.warn("Object of non-string type has been added as a parameter");
  -            value = null;
  -        }
  -        if (name == null || value == null){
  +    public NameValuePair getParameter(String paramName){
  +        if (paramName == null){
               return null;
  -        }else{
  -            return new NameValuePair(name, value);
           }
  +        Iterator iter = parameters.iterator();
  +        while(iter.hasNext()){
  +            NameValuePair parameter = (NameValuePair)iter.next();
  +            if (paramName.equals(parameter.getName())){
  +                return parameter;
  +            }
  +        }
  +        return null;
       }
   
       /**
        * Gets the parameters currently added to the PostMethod.
  -     * The returned object is new and is <b>not</b> a refrence to any 
  -     * internal data members.
  +     * If there are no parameters, a valid array is returned with
  +     * zero elements.
  +     * The returned array object contains an array of pointers to 
  +     * the internal data members.
  +     * TODO: is it ok to return internal data?
        * 
        * @return An array of the current parameters
        * @see #getParameter(java.lang.String);
        * @since 2.0
        */
       public NameValuePair[] getParameters(){
  -        Set keySet = parameters.keySet();
  -        Object[] keyArray = keySet.toArray();
  -        int numKeys = keyArray.length;
  -        NameValuePair[] nvPairs = new NameValuePair[numKeys];
  -        Object key;
  -        for (int i=0; i<numKeys; i++){
  -            nvPairs[i] = this.getParameter((String)keyArray[i]);
  -        }
  -        return nvPairs;
  +        int numPairs = parameters.size();
  +        Object[] objectArr= parameters.toArray();
  +        NameValuePair[] nvPairArr = new NameValuePair[numPairs];
  +        for(int i=0; i<numPairs; i++){
  +            nvPairArr[i] = (NameValuePair)objectArr[i];
  +        }
  +        return nvPairArr;
       }
   
       /**
  -     * Overrides method of {@link HttpMethodBase}
  -     * to throw {@link IllegalStateException} if
  -     * my request body has already been
  -     * {@link #generateRequestBody generated}
  -     * or {@link #setRequestBody set}.
  -     *
  +     * 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 is ignored.
  +     * 
  +     * @param paramName The parameter name to remove.
  +     * @return true if at least one parameter was removed
        * @throws IllegalStateException if my request body has already been generated.
        */
  -    public void removeParameter(String paramName) {
  +    public boolean removeParameter(String paramName) {
           if(null != requestBody) {
               throw new IllegalStateException("Request body already generated.");
           }
  -        parameters.remove(paramName);
  +        if (paramName == null){
  +            throw new IllegalArgumentException("Argument passed to removeParameter(String)
cannot be null");
  +        }
  +        boolean removed = true;
  +        Iterator iter = parameters.iterator();
  +        while(iter.hasNext()){
  +            NameValuePair pair = (NameValuePair)iter.next();
  +            if (paramName.equals(pair.getName())){
  +                iter.remove();
  +                removed = true;
  +            }
  +        }
  +        return removed;
       }
   
       /**
  -     * Overrides method of {@link HttpMethodBase}
  -     * to throw {@link IllegalStateException} if
  -     * my request body has already been
  -     * {@link #generateRequestBody generated}
  -     * or {@link #setRequestBody set}.
  +     * Removes all parameter with the given paramName and paramValue.
  +     * If there is more than one parameter with the given paramName, only
  +     * one is removed.  If there are none, then the request is ignored.
        *
  +     * @param paramName The parameter name to remove.
  +     * @param paramValue The parameter value to remove.
  +     * @return true if a parameter was removed.
        * @throws IllegalStateException if my request body has already been generated.
        */
  -    public void removeParameter(String paramName, String paramValue) {
  +    public boolean removeParameter(String paramName, String paramValue) {
           if(null != requestBody) {
               throw new IllegalStateException("Request body already generated.");
           }
  -        Object old = parameters.get(paramName);
  -        if(null != old) {
  -            if(paramValue.equals(old)) {
  -                parameters.remove(paramName);
  -            } else if(old instanceof List) {
  -                List list = (List)old;
  -                if(list.remove(paramValue)) {
  -                    if(list.isEmpty()) {
  -                        parameters.remove(paramName);
  -                    } else if(list.size() == 1) {
  -                        parameters.put(paramName,list.get(0));
  -                    } else {
  -                        parameters.put(paramValue,list);
  -                    }
  -                }
  +        if (paramName == null || paramValue == null){
  +            throw new IllegalArgumentException("Argument passed to removeParameter(String,String)
cannot be null");
  +        }
  +        Iterator iter = parameters.iterator();
  +        while(iter.hasNext()){
  +            NameValuePair pair = (NameValuePair)iter.next();
  +            if (paramName.equals(pair.getName()) && paramValue.equals(pair.getValue())){
  +                iter.remove();
  +                return true;
               }
           }
  +        return false;
       }
   
  -    /**
  +    /** 
  +     * 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}.
  +     * 
        * @throws IllegalStateException if request params have been added
        */
       public void setRequestBody(String body) {
  @@ -329,21 +354,42 @@
       }
   
       /**
  -     * Override method of {@link HttpMethodBase}
  -     * to also add <tt>Content-Type</tt> header
  +     * 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 String getRequestBody() {
  +        if(requestBody != null){
  +            return requestBody;
  +        }else if (!parameters.isEmpty()){
  +            return generateRequestBody(parameters);
  +        }else{
  +            return null;
  +        }
  +    }
  +
  +
  +    /**
  +     * Override method of {@link HttpMethodBase} to also add <tt>Content-Type</tt>
header
        * when appropriate.
        */
       protected void addRequestHeaders(HttpState state, HttpConnection conn) throws IOException,
HttpException {
           super.addRequestHeaders(state,conn);
  -        if(!parameters.isEmpty()) {
  -            setRequestHeader("Content-Type","application/x-www-form-urlencoded");
  +        if(!parameters.isEmpty()) { //there are some parameters, so set the contentType
header
  +            setRequestHeader(CONTENT_TYPE);
           }
       }
   
       /**
        * Override method of {@link HttpMethodBase}
  -     * to write request parameters as the
  -     * request body.
  +     * to write request parameters as the request body.
  +     * 
  +     * <p>Once this method has been invoked,  the request parameters 
  +     * cannot be altered until I am {@link #recycle recycled}.
  +     *
  +     * @return always returns true
        */
       protected boolean writeRequestBody(HttpState state, HttpConnection conn) throws IOException,
HttpException {
           log.debug("PostMethod.writeRequestBody(HttpState,HttpConnection)");
  @@ -358,9 +404,7 @@
        * Override method of {@link HttpMethodBase}
        * to return the length of the request body.
        *
  -     * Once this method has been invoked,
  -     * the request parameters cannot be altered
  -     * until I am {@link #recycle recycled}.
  +     @return number of bytes in the request body
        */
       protected int getRequestContentLength() {
           if(null == requestBody) {
  @@ -369,45 +413,43 @@
           return requestBody.getBytes().length;
       }
   
  -    protected String generateRequestBody(Map params) {
  -        if (!params.isEmpty()) {
  -            StringBuffer sb = new StringBuffer();
  -            Iterator it = parameters.keySet().iterator();
  -            while(it.hasNext()) {
  -                String name = (String)(it.next());
  -                Object value = parameters.get(name);
  -                if(value instanceof List) {
  -                    List list = (List)value;
  -                    Iterator valit = list.iterator();
  -                    while(valit.hasNext()) {
  -                        if(sb.length() > 0) { sb.append("&"); }
  -                        sb.append(URIUtil.encode(name,URIUtil.queryStringValueSafe(),true));
  -                        Object val2 = valit.next();
  -                        if(null != val2) {
  -                            sb.append("=");
  -                            sb.append(URIUtil.encode(String.valueOf(val2),URIUtil.queryStringValueSafe(),true));
  -                        }
  -                    }
  -                } else {
  -                    if(sb.length() > 0) { sb.append("&"); }
  -                    sb.append(URIUtil.encode(name,URIUtil.queryStringValueSafe()));
  -                    if(null != value) {
  -                        sb.append("=");
  -                        sb.append(URIUtil.encode(String.valueOf(value),URIUtil.queryStringValueSafe(),true));
  -                    }
  -                }
  +
  +    // -------------------------------------------------------------- Class Methods
  +
  +    /** 
  +     * Encode the list of parameters into a urlencoded string.
  +     *
  +     * TODO: consider moving this out into URIUtil.
  +     * @return urlencoded string
  +     */
  +    static String generateRequestBody(List params) {
  +        Iterator it = params.iterator();
  +        StringBuffer sb = new StringBuffer();
  +        while(it.hasNext()) {
  +            NameValuePair parameter = (NameValuePair)it.next();
  +            //TODO: make sure these encodings conform to the RFC
  +            sb.append(URIUtil.encode(parameter.getName(), URIUtil.queryStringValueSafe(),
false));
  +            sb.append("=");
  +            sb.append(URIUtil.encode(parameter.getValue(), URIUtil.queryStringValueSafe(),
true));
  +            if (it.hasNext()){ 
  +                sb.append("&");
               }
  -            return sb.toString();
  -        } else {
  -            return "";
           }
  +        return sb.toString();
       }
   
  +
  +    // -------------------------------------------------------------- Instance Variables

  +
       private String requestBody = null;
  -    private HashMap parameters = new HashMap();
  +    private Vector parameters = new Vector();
  +
   
       // -------------------------------------------------------------- Constants
   
       /** <tt>org.apache.commons.httpclient.methods.PostMethod</tt> log. */
       private static final Log log = LogSource.getInstance("org.apache.commons.httpclient.methods.PostMethod");
  +
  +    /** The Content-Type header for www-form-urlcoded. */
  +    static final Header CONTENT_TYPE = new Header ("Content-Type","application/x-www-form-urlencoded");
   }
  
  
  

--
To unsubscribe, e-mail:   <mailto:commons-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:commons-dev-help@jakarta.apache.org>


Mime
View raw message