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