View Javadoc

1   /*
2    * $HeadURL: https://svn.apache.org/repos/asf/httpcomponents/oac.hc3x/trunk/src/java/org/apache/commons/httpclient/methods/PostMethod.java $
3    * $Revision$
4    * $Date$
5    *
6    * ====================================================================
7    *
8    *  Licensed to the Apache Software Foundation (ASF) under one or more
9    *  contributor license agreements.  See the NOTICE file distributed with
10   *  this work for additional information regarding copyright ownership.
11   *  The ASF licenses this file to You under the Apache License, Version 2.0
12   *  (the "License"); you may not use this file except in compliance with
13   *  the License.  You may obtain a copy of the License at
14   *
15   *      http://www.apache.org/licenses/LICENSE-2.0
16   *
17   *  Unless required by applicable law or agreed to in writing, software
18   *  distributed under the License is distributed on an "AS IS" BASIS,
19   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   *  See the License for the specific language governing permissions and
21   *  limitations under the License.
22   * ====================================================================
23   *
24   * This software consists of voluntary contributions made by many
25   * individuals on behalf of the Apache Software Foundation.  For more
26   * information on the Apache Software Foundation, please see
27   * <http://www.apache.org/>.
28   *
29   */
30  
31  package org.apache.commons.httpclient.methods;
32  
33  import java.util.Iterator;
34  import java.util.Vector;
35  
36  import org.apache.commons.httpclient.NameValuePair;
37  import org.apache.commons.httpclient.util.EncodingUtil;
38  import org.apache.commons.logging.Log;
39  import org.apache.commons.logging.LogFactory;
40  
41  /***
42   * Implements the HTTP POST method.
43   * <p>
44   * The HTTP POST method is defined in section 9.5 of 
45   * <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a>:
46   * <blockquote>
47   * The POST method is used to request that the origin server accept the entity
48   * enclosed in the request as a new subordinate of the resource identified by
49   * the Request-URI in the Request-Line. POST is designed to allow a uniform
50   * method to cover the following functions:
51   * <ul>
52   *   <li>Annotation of existing resources</li>
53   *   <li>Posting a message to a bulletin board, newsgroup, mailing list, or 
54   *     similar group of articles</li>
55   *   <li>Providing a block of data, such as the result of submitting a form,
56   *     to a data-handling process</li>
57   *   <li>Extending a database through an append operation</li>
58   * </ul>
59   * </blockquote>
60   * </p>
61   *
62   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
63   * @author <a href="mailto:dsale@us.britannica.com">Doug Sale</a>
64   * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
65   * @author Ortwin Gl???ck
66   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
67   * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
68   *
69   * @version $Revision$
70   * @since 1.0
71   */
72  public class PostMethod extends EntityEnclosingMethod {
73      // -------------------------------------------------------------- Constants
74  
75      /*** Log object for this class. */
76      private static final Log LOG = LogFactory.getLog(PostMethod.class);
77  
78      /*** The Content-Type for www-form-urlencoded. */
79      public static final String FORM_URL_ENCODED_CONTENT_TYPE = 
80          "application/x-www-form-urlencoded";
81  
82      /*** 
83       * The buffered request body consisting of <code>NameValuePair</code>s. 
84       */
85      private Vector params = new Vector();
86  
87      // ----------------------------------------------------------- Constructors
88  
89      /***
90       * No-arg constructor.
91       *
92       * @since 1.0
93       */
94      public PostMethod() {
95          super();
96      }
97  
98      /***
99       * Constructor specifying a URI.
100      *
101      * @param uri either an absolute or relative URI
102      *
103      * @since 1.0
104      */
105     public PostMethod(String uri) {
106         super(uri);
107     }
108 
109     // ----------------------------------------------------- Instance Methods
110 
111     /***
112      * Returns <tt>"POST"</tt>.
113      *
114      * @return <tt>"POST"</tt>
115      *
116      * @since 2.0
117      */
118     public String getName() {
119         return "POST";
120     }
121 
122 
123     /***
124      * Returns <tt>true</tt> if there is a request body to be sent.
125      * 
126      * <P>This method must be overwritten by sub-classes that implement
127      * alternative request content input methods
128      * </p>
129      * 
130      * @return boolean
131      * 
132      * @since 2.0beta1
133      */
134     protected boolean hasRequestContent() {
135         LOG.trace("enter PostMethod.hasRequestContent()");
136         if (!this.params.isEmpty()) {
137             return true;
138         } else {
139             return super.hasRequestContent();
140         }
141     }
142 
143     /***
144      * Clears request body.
145      * 
146      * <p>This method must be overwritten by sub-classes that implement
147      * alternative request content input methods</p>
148      * 
149      * @since 2.0beta1
150      */
151     protected void clearRequestBody() {
152         LOG.trace("enter PostMethod.clearRequestBody()");
153         this.params.clear();
154         super.clearRequestBody();
155     }
156 
157     /***
158      * Generates a request entity from the post parameters, if present.  Calls
159      * {@link EntityEnclosingMethod#generateRequestBody()} if parameters have not been set.
160      * 
161      * @since 3.0
162      */
163     protected RequestEntity generateRequestEntity() {
164         if (!this.params.isEmpty()) {
165             // Use a ByteArrayRequestEntity instead of a StringRequestEntity.
166             // This is to avoid potential encoding issues.  Form url encoded strings
167             // are ASCII by definition but the content type may not be.  Treating the content
168             // as bytes allows us to keep the current charset without worrying about how
169             // this charset will effect the encoding of the form url encoded string.
170             String content = EncodingUtil.formUrlEncode(getParameters(), getRequestCharSet());
171             ByteArrayRequestEntity entity = new ByteArrayRequestEntity(
172                 EncodingUtil.getAsciiBytes(content),
173                 FORM_URL_ENCODED_CONTENT_TYPE
174             );
175             return entity;
176         } else {
177             return super.generateRequestEntity();
178         }
179     }
180     
181     /***
182      * Sets the value of parameter with parameterName to parameterValue. This method
183      * does not preserve the initial insertion order.
184      *
185      * @param parameterName name of the parameter
186      * @param parameterValue value of the parameter
187      *
188      * @since 2.0
189      */
190     public void setParameter(String parameterName, String parameterValue) {
191         LOG.trace("enter PostMethod.setParameter(String, String)");
192 
193         removeParameter(parameterName);
194         addParameter(parameterName, parameterValue);
195     }
196 
197     /***
198      * Gets the parameter of the specified name. If there exists more than one
199      * parameter with the name paramName, then only the first one is returned.
200      *
201      * @param paramName name of the parameter
202      *
203      * @return If a parameter exists with the name argument, the coresponding
204      *         NameValuePair is returned.  Otherwise null.
205      *
206      * @since 2.0
207      * 
208      */
209     public NameValuePair getParameter(String paramName) {
210         LOG.trace("enter PostMethod.getParameter(String)");
211 
212         if (paramName == null) {
213             return null;
214         }
215 
216         Iterator iter = this.params.iterator();
217 
218         while (iter.hasNext()) {
219             NameValuePair parameter = (NameValuePair) iter.next();
220 
221             if (paramName.equals(parameter.getName())) {
222                 return parameter;
223             }
224         }
225         return null;
226     }
227 
228     /***
229      * Gets the parameters currently added to the PostMethod. If there are no
230      * parameters, a valid array is returned with zero elements. The returned
231      * array object contains an array of pointers to  the internal data
232      * members.
233      *
234      * @return An array of the current parameters
235      *
236      * @since 2.0
237      * 
238      */
239     public NameValuePair[] getParameters() {
240         LOG.trace("enter PostMethod.getParameters()");
241 
242         int numPairs = this.params.size();
243         Object[] objectArr = this.params.toArray();
244         NameValuePair[] nvPairArr = new NameValuePair[numPairs];
245 
246         for (int i = 0; i < numPairs; i++) {
247             nvPairArr[i] = (NameValuePair) objectArr[i];
248         }
249 
250         return nvPairArr;
251     }
252 
253     /***
254      * Adds a new parameter to be used in the POST request body.
255      *
256      * @param paramName The parameter name to add.
257      * @param paramValue The parameter value to add.
258      *
259      * @throws IllegalArgumentException if either argument is null
260      *
261      * @since 1.0
262      */
263     public void addParameter(String paramName, String paramValue) 
264     throws IllegalArgumentException {
265         LOG.trace("enter PostMethod.addParameter(String, String)");
266 
267         if ((paramName == null) || (paramValue == null)) {
268             throw new IllegalArgumentException(
269                 "Arguments to addParameter(String, String) cannot be null");
270         }
271         super.clearRequestBody();
272         this.params.add(new NameValuePair(paramName, paramValue));
273     }
274 
275     /***
276      * Adds a new parameter to be used in the POST request body.
277      *
278      * @param param The parameter to add.
279      *
280      * @throws IllegalArgumentException if the argument is null or contains
281      *         null values
282      *
283      * @since 2.0
284      */
285     public void addParameter(NameValuePair param) 
286     throws IllegalArgumentException {
287         LOG.trace("enter PostMethod.addParameter(NameValuePair)");
288 
289         if (param == null) {
290             throw new IllegalArgumentException("NameValuePair may not be null");
291         }
292         addParameter(param.getName(), param.getValue());
293     }
294 
295     /***
296      * Adds an array of parameters to be used in the POST request body. Logs a
297      * warning if the parameters argument is null.
298      *
299      * @param parameters The array of parameters to add.
300      *
301      * @since 2.0
302      */
303     public void addParameters(NameValuePair[] parameters) {
304         LOG.trace("enter PostMethod.addParameters(NameValuePair[])");
305 
306         if (parameters == null) {
307             LOG.warn("Attempt to addParameters(null) ignored");
308         } else {
309             super.clearRequestBody();
310             for (int i = 0; i < parameters.length; i++) {
311                 this.params.add(parameters[i]);
312             }
313         }
314     }
315 
316     /***
317      * Removes all parameters with the given paramName. If there is more than
318      * one parameter with the given paramName, all of them are removed.  If
319      * there is just one, it is removed.  If there are none, then the request
320      * is ignored.
321      *
322      * @param paramName The parameter name to remove.
323      *
324      * @return true if at least one parameter was removed
325      *
326      * @throws IllegalArgumentException When the parameter name passed is null
327      *
328      * @since 2.0
329      */
330     public boolean removeParameter(String paramName) 
331     throws IllegalArgumentException {
332         LOG.trace("enter PostMethod.removeParameter(String)");
333 
334         if (paramName == null) {
335             throw new IllegalArgumentException(
336                 "Argument passed to removeParameter(String) cannot be null");
337         }
338         boolean removed = false;
339         Iterator iter = this.params.iterator();
340 
341         while (iter.hasNext()) {
342             NameValuePair pair = (NameValuePair) iter.next();
343 
344             if (paramName.equals(pair.getName())) {
345                 iter.remove();
346                 removed = true;
347             }
348         }
349         return removed;
350     }
351 
352     /***
353      * Removes all parameter with the given paramName and paramValue. If there
354      * is more than one parameter with the given paramName, only one is
355      * removed.  If there are none, then the request is ignored.
356      *
357      * @param paramName The parameter name to remove.
358      * @param paramValue The parameter value to remove.
359      *
360      * @return true if a parameter was removed.
361      *
362      * @throws IllegalArgumentException when param name or value are null
363      *
364      * @since 2.0
365      */
366     public boolean removeParameter(String paramName, String paramValue) 
367     throws IllegalArgumentException {
368         LOG.trace("enter PostMethod.removeParameter(String, String)");
369 
370         if (paramName == null) {
371             throw new IllegalArgumentException("Parameter name may not be null");
372         }
373         if (paramValue == null) {
374             throw new IllegalArgumentException("Parameter value may not be null");
375         }
376 
377         Iterator iter = this.params.iterator();
378 
379         while (iter.hasNext()) {
380             NameValuePair pair = (NameValuePair) iter.next();
381 
382             if (paramName.equals(pair.getName())
383                 && paramValue.equals(pair.getValue())) {
384                 iter.remove();
385                 return true;
386             }
387         }
388 
389         return false;
390     }
391 
392     /***
393      * Sets an array of parameters to be used in the POST request body
394      *
395      * @param parametersBody The array of parameters to add.
396      *
397      * @throws IllegalArgumentException when param parameters are null
398      * 
399      * @since 2.0beta1
400      */
401     public void setRequestBody(NameValuePair[] parametersBody)
402     throws IllegalArgumentException {
403         LOG.trace("enter PostMethod.setRequestBody(NameValuePair[])");
404 
405         if (parametersBody == null) {
406             throw new IllegalArgumentException("Array of parameters may not be null");
407         }
408         clearRequestBody();
409         addParameters(parametersBody);
410     }
411 }