View Javadoc

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