1 /*
2 * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java,v 1.42 2003/04/19 22:29:32 mbecke Exp $
3 * $Revision: 1.42 $
4 * $Date: 2003/04/19 22:29:32 $
5 *
6 * ====================================================================
7 *
8 * The Apache Software License, Version 1.1
9 *
10 * Copyright (c) 1999-2003 The Apache Software Foundation. All rights
11 * reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in
22 * the documentation and/or other materials provided with the
23 * distribution.
24 *
25 * 3. The end-user documentation included with the redistribution, if
26 * any, must include the following acknowlegement:
27 * "This product includes software developed by the
28 * Apache Software Foundation (http://www.apache.org/)."
29 * Alternately, this acknowlegement may appear in the software itself,
30 * if and wherever such third-party acknowlegements normally appear.
31 *
32 * 4. The names "The Jakarta Project", "Commons", and "Apache Software
33 * Foundation" must not be used to endorse or promote products derived
34 * from this software without prior written permission. For written
35 * permission, please contact apache@apache.org.
36 *
37 * 5. Products derived from this software may not be called "Apache"
38 * nor may "Apache" appear in their names without prior written
39 * permission of the Apache Group.
40 *
41 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 * ====================================================================
54 *
55 * This software consists of voluntary contributions made by many
56 * individuals on behalf of the Apache Software Foundation. For more
57 * information on the Apache Software Foundation, please see
58 * <http://www.apache.org/>.
59 *
60 * [Additional notices, if required by prior licensing conditions]
61 *
62 */
63 package org.apache.commons.httpclient.methods;
64
65 import java.io.IOException;
66 import java.util.Iterator;
67 import java.util.Vector;
68
69 import org.apache.commons.httpclient.HttpConnection;
70 import org.apache.commons.httpclient.HttpConstants;
71 import org.apache.commons.httpclient.HttpException;
72 import org.apache.commons.httpclient.HttpState;
73 import org.apache.commons.httpclient.NameValuePair;
74 import org.apache.commons.httpclient.URIException;
75 import org.apache.commons.httpclient.util.URIUtil;
76 import org.apache.commons.logging.Log;
77 import org.apache.commons.logging.LogFactory;
78
79 /***
80 * Implements the HTTP POST specification.
81 * <p>
82 * The HTTP POST method is defined in section 8.3 of
83 * <a href="http://www.ietf.org/rfc/rfc1945.txt">RFC1945</a>:
84 * <blockquote>
85 * The POST method is used to request that the origin server accept the entity
86 * enclosed in the request as a new subordinate of the resource identified by
87 * the Request-URI in the Request-Line. POST is designed to allow a uniform
88 * method to cover the following functions:
89 * <ul>
90 * <li>Annotation of existing resources</li>
91 * <li>Posting a message to a bulletin board, newsgroup, mailing list, or
92 * similar group of articles</li>
93 * <li>Providing a block of data, such as the result of submitting a form,
94 * to a data-handling process</li>
95 * <li>Extending a database through an append operation</li>
96 * </ul>
97 * </blockquote>
98 * </p>
99 *
100 * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
101 * @author <a href="mailto:dsale@us.britannica.com">Doug Sale</a>
102 * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
103 * @author Ortwin Gl�ck
104 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
105 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
106 *
107 * @version $Revision: 1.42 $
108 * @since 1.0
109 */
110 public class PostMethod extends EntityEnclosingMethod {
111 // -------------------------------------------------------------- Constants
112
113 /*** Log object for this class. */
114 private static final Log LOG = LogFactory.getLog(PostMethod.class);
115
116 /*** The Content-Type for www-form-urlcoded. */
117 public static final String FORM_URL_ENCODED_CONTENT_TYPE =
118 "application/x-www-form-urlencoded";
119
120 /***
121 * The buffered request body consisting of <code>NameValuePair</code>s.
122 */
123 private Vector params = new Vector();
124
125 // ----------------------------------------------------------- Constructors
126
127 /***
128 * No-arg constructor.
129 *
130 * @since 1.0
131 */
132 public PostMethod() {
133 super();
134 }
135
136 /***
137 * Constructor specifying a URI.
138 *
139 * @param uri either an absolute or relative URI
140 *
141 * @since 1.0
142 */
143 public PostMethod(String uri) {
144 super(uri);
145 }
146
147 /***
148 * Constructor specifying a URI and a tempDir.
149 *
150 * @param uri either an absolute or relative URI
151 * @param tempDir directory to store temp files in
152 *
153 * @deprecated the client is responsible for disk I/O
154 * @since 1.0
155 */
156 public PostMethod(String uri, String tempDir) {
157 super(uri, tempDir);
158 }
159
160 /***
161 * Constructor specifying a URI, tempDir and tempFile.
162 *
163 * @param uri either an absolute or relative URI
164 * @param tempDir directory to store temp files in
165 * @param tempFile file to store temporary data in
166 *
167 * @deprecated the client is responsible for disk I/O
168 * @since 1.0
169 */
170 public PostMethod(String uri, String tempDir, String tempFile) {
171 super(uri, tempDir, tempFile);
172 }
173
174 // ----------------------------------------------------- Instance Methods
175
176 /***
177 * Returns <tt>"POST"</tt>.
178 *
179 * @return <tt>"POST"</tt>
180 *
181 * @since 2.0
182 */
183 public String getName() {
184 return "POST";
185 }
186
187
188 /***
189 * Returns <tt>true</tt> if there is a request body to be sent.
190 *
191 * <P>This method must be overwritten by sub-classes that implement
192 * alternative request content input methods
193 * </p>
194 *
195 * @return boolean
196 *
197 * @since 2.0beta1
198 */
199 protected boolean hasRequestContent() {
200 LOG.trace("enter PostMethod.hasRequestContent()");
201 if (!this.params.isEmpty()) {
202 return true;
203 } else {
204 return super.hasRequestContent();
205 }
206 }
207
208 /***
209 * Clears request body.
210 *
211 * <p>This method must be overwritten by sub-classes that implement
212 * alternative request content input methods</p>
213 *
214 * @since 2.0beta1
215 */
216 protected void clearRequestBody() {
217 LOG.trace("enter PostMethod.clearRequestBody()");
218 this.params.clear();
219 super.clearRequestBody();
220 }
221
222
223 /***
224 * Generates request body.
225 *
226 * <p>This method must be overwritten by sub-classes that implement
227 * alternative request content input methods
228 * </p>
229 *
230 * @return request body as an array of bytes. If the request content
231 * has not been set, returns <tt>null</null>.
232 *
233 * @since 2.0beta1
234 */
235 protected byte[] generateRequestBody() {
236 LOG.trace("enter PostMethod.renerateRequestBody()");
237 if (!this.params.isEmpty()) {
238 String charset = getRequestCharSet();
239 StringBuffer buff = new StringBuffer();
240
241 for (int i = 0; i < this.params.size(); i++) {
242 if (i > 0) {
243 buff.append("&");
244 }
245 NameValuePair parameter = (NameValuePair) this.params.get(i);
246 String queryName = null;
247 try {
248 queryName = URIUtil.encodeWithinQuery(parameter.getName(), charset);
249 } catch (URIException e) {
250 if (LOG.isWarnEnabled()) {
251 LOG.warn("Encosing error: " + e.toString());
252 }
253 queryName = parameter.getName();
254 }
255
256 buff.append(queryName).append("=");
257 String queryValue = null;
258
259 try {
260 queryValue = URIUtil.encodeWithinQuery(parameter.getValue(), charset);
261 } catch (URIException e) {
262 if (LOG.isWarnEnabled()) {
263 LOG.warn("Encosing error: " + e.toString());
264 }
265 queryValue = parameter.getValue();
266 }
267 buff.append(queryValue);
268 }
269 return HttpConstants.getContentBytes(buff.toString());
270 } else {
271 return super.generateRequestBody();
272 }
273 }
274
275
276 /***
277 * Set the value of parameter with parameterName to parameterValue. Does
278 * not preserve the initial insertion order.
279 *
280 * @param parameterName name of the parameter
281 * @param parameterValue value of the parameter
282 *
283 * @since 2.0
284 */
285 public void setParameter(String parameterName, String parameterValue) {
286 LOG.trace("enter PostMethod.setParameter(String, String)");
287
288 removeParameter(parameterName, parameterValue);
289 addParameter(parameterName, parameterValue);
290 }
291
292 /***
293 * Gets the parameter of the specified name. If there exists more than one
294 * parameter with the name paramName, then only the first one is returned.
295 *
296 * @param paramName name of the parameter
297 *
298 * @return If a parameter exists with the name argument, the coresponding
299 * NameValuePair is returned. Otherwise null.
300 *
301 * @since 2.0
302 *
303 */
304 public NameValuePair getParameter(String paramName) {
305 LOG.trace("enter PostMethod.getParameter(String)");
306
307 if (paramName == null) {
308 return null;
309 }
310
311 Iterator iter = this.params.iterator();
312
313 while (iter.hasNext()) {
314 NameValuePair parameter = (NameValuePair) iter.next();
315
316 if (paramName.equals(parameter.getName())) {
317 return parameter;
318 }
319 }
320 return null;
321 }
322
323 /***
324 * Gets the parameters currently added to the PostMethod. If there are no
325 * parameters, a valid array is returned with zero elements. The returned
326 * array object contains an array of pointers to the internal data
327 * members.
328 *
329 * @return An array of the current parameters
330 *
331 * @since 2.0
332 *
333 */
334 public NameValuePair[] getParameters() {
335 LOG.trace("enter PostMethod.getParameters()");
336
337 int numPairs = this.params.size();
338 Object[] objectArr = this.params.toArray();
339 NameValuePair[] nvPairArr = new NameValuePair[numPairs];
340
341 for (int i = 0; i < numPairs; i++) {
342 nvPairArr[i] = (NameValuePair) objectArr[i];
343 }
344
345 return nvPairArr;
346 }
347
348 /***
349 * Add a new parameter to be used in the POST request body.
350 *
351 * @param paramName The parameter name to add.
352 * @param paramValue The parameter value to add.
353 *
354 * @throws IllegalArgumentException if either argument is null
355 *
356 * @since 1.0
357 */
358 public void addParameter(String paramName, String paramValue)
359 throws IllegalArgumentException {
360 LOG.trace("enter PostMethod.addParameter(String, String)");
361
362 if ((paramName == null) || (paramValue == null)) {
363 throw new IllegalArgumentException(
364 "Arguments to addParameter(String, String) cannot be null");
365 }
366 super.clearRequestBody();
367 this.params.add(new NameValuePair(paramName, paramValue));
368 }
369
370 /***
371 * Add a new parameter to be used in the POST request body.
372 *
373 * @param param The parameter to add.
374 *
375 * @throws IllegalArgumentException if the argument is null or contains
376 * null values
377 *
378 * @since 2.0
379 */
380 public void addParameter(NameValuePair param)
381 throws IllegalArgumentException {
382 LOG.trace("enter PostMethod.addParameter(NameValuePair)");
383
384 if (param == null) {
385 throw new IllegalArgumentException("NameValuePair may not be null");
386 }
387 addParameter(param.getName(), param.getValue());
388 }
389
390 /***
391 * Add an Array of parameters to be used in the POST request body. Logs a
392 * warning if the parameters argument is null.
393 *
394 * @param parameters The array of parameters to add.
395 *
396 * @since 2.0
397 */
398 public void addParameters(NameValuePair[] parameters) {
399 LOG.trace("enter PostMethod.addParameters(NameValuePair[])");
400
401 if (parameters == null) {
402 LOG.warn("Attempt to addParameters(null) ignored");
403 } else {
404 for (int i = 0; i < parameters.length; i++) {
405 addParameter(parameters[i]);
406 }
407 }
408 }
409
410 /***
411 * Removes all parameters with the given paramName. If there is more than
412 * one parameter with the given paramName, all of them are removed. If
413 * there is just one, it is removed. If there are none, then the request
414 * is ignored.
415 *
416 * @param paramName The parameter name to remove.
417 *
418 * @return true if at least one parameter was removed
419 *
420 * @throws IllegalArgumentException When the parameter name passed is null
421 *
422 * @since 2.0
423 */
424 public boolean removeParameter(String paramName)
425 throws IllegalArgumentException {
426 LOG.trace("enter PostMethod.removeParameter(String)");
427
428 if (paramName == null) {
429 throw new IllegalArgumentException(
430 "Argument passed to removeParameter(String) cannot be null");
431 }
432 boolean removed = true;
433 Iterator iter = this.params.iterator();
434
435 while (iter.hasNext()) {
436 NameValuePair pair = (NameValuePair) iter.next();
437
438 if (paramName.equals(pair.getName())) {
439 iter.remove();
440 removed = true;
441 }
442 }
443 return removed;
444 }
445
446 /***
447 * Removes all parameter with the given paramName and paramValue. If there
448 * is more than one parameter with the given paramName, only one is
449 * removed. If there are none, then the request is ignored.
450 *
451 * @param paramName The parameter name to remove.
452 * @param paramValue The parameter value to remove.
453 *
454 * @return true if a parameter was removed.
455 *
456 * @throws IllegalArgumentException when param name or value are null
457 *
458 * @since 2.0
459 */
460 public boolean removeParameter(String paramName, String paramValue)
461 throws IllegalArgumentException {
462 LOG.trace("enter PostMethod.removeParameter(String, String)");
463
464 if (paramName == null) {
465 throw new IllegalArgumentException("Parameter name may not be null");
466 }
467 if (paramValue == null) {
468 throw new IllegalArgumentException("Parameter value may not be null");
469 }
470
471 Iterator iter = this.params.iterator();
472
473 while (iter.hasNext()) {
474 NameValuePair pair = (NameValuePair) iter.next();
475
476 if (paramName.equals(pair.getName())
477 && paramValue.equals(pair.getValue())) {
478 iter.remove();
479 return true;
480 }
481 }
482
483 return false;
484 }
485
486 /***
487 * Set an Array of parameters to be used in the POST request body
488 *
489 * @param parametersBody The array of parameters to add.
490 *
491 * @throws IllegalArgumentException when param parameters are null
492 *
493 * @since 2.0beta1
494 */
495 public void setRequestBody(NameValuePair[] parametersBody)
496 throws IllegalArgumentException {
497 LOG.trace("enter PostMethod.setRequestBody(NameValuePair[])");
498
499 if (parametersBody == null) {
500 throw new IllegalArgumentException("Array of parameters may not be null");
501 }
502 clearRequestBody();
503 addParameters(parametersBody);
504 }
505
506 /***
507 * Override method of {@link org.apache.commons.httpclient.HttpMethodBase}
508 * to also add <tt>Content-Type</tt> header when appropriate.
509 *
510 * @param state the client state
511 * @param conn the {@link HttpConnection} the headers will eventually be
512 * written to
513 * @throws IOException when an error occurs writing the request
514 * @throws HttpException when a HTTP protocol error occurs
515 *
516 * @since 2.0
517 */
518 protected void addRequestHeaders(HttpState state, HttpConnection conn)
519 throws IOException, HttpException {
520 super.addRequestHeaders(state, conn);
521
522 if (!this.params.isEmpty()) {
523 //there are some parameters, so set the contentType header
524 if (getRequestHeader("Content-Type") == null) {
525 setRequestHeader("Content-Type", FORM_URL_ENCODED_CONTENT_TYPE);
526 }
527 }
528 }
529
530 }
This page was automatically generated by Maven