View Javadoc
1   /**
2    * Copyright 2014 Internet2
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  /*
17   * $Header: /home/hagleyj/i2mi/grouper-misc/grouperClient/src/ext/edu/internet2/middleware/grouperClientExt/org/apache/commons/httpclient/methods/MultipartPostMethod.java,v 1.1 2008-11-30 10:57:19 mchyzer Exp $
18   * $Revision: 1.1 $
19   * $Date: 2008-11-30 10:57:19 $
20   *
21   * ====================================================================
22   *
23   *  Licensed to the Apache Software Foundation (ASF) under one or more
24   *  contributor license agreements.  See the NOTICE file distributed with
25   *  this work for additional information regarding copyright ownership.
26   *  The ASF licenses this file to You under the Apache License, Version 2.0
27   *  (the "License"); you may not use this file except in compliance with
28   *  the License.  You may obtain a copy of the License at
29   *
30   *      http://www.apache.org/licenses/LICENSE-2.0
31   *
32   *  Unless required by applicable law or agreed to in writing, software
33   *  distributed under the License is distributed on an "AS IS" BASIS,
34   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35   *  See the License for the specific language governing permissions and
36   *  limitations under the License.
37   * ====================================================================
38   *
39   * This software consists of voluntary contributions made by many
40   * individuals on behalf of the Apache Software Foundation.  For more
41   * information on the Apache Software Foundation, please see
42   * <http://www.apache.org/>.
43   *
44   */
45  
46  package edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.methods;
47  
48  import java.io.File;
49  import java.io.FileNotFoundException;
50  import java.io.IOException;
51  import java.io.OutputStream;
52  import java.util.ArrayList;
53  import java.util.List;
54  
55  import edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.HttpConnection;
56  import edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.HttpException;
57  import edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.HttpState;
58  import edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.methods.multipart.FilePart;
59  import edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.methods.multipart.Part;
60  import edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.methods.multipart.StringPart;
61  import edu.internet2.middleware.grouperClientExt.org.apache.commons.logging.Log;
62  import edu.internet2.middleware.grouperClientExt.org.apache.commons.logging.LogFactory;
63  
64  /**
65   * Implements the HTTP multipart POST method.
66   * <p>
67   * The HTTP multipart POST method is defined in section 3.3 of
68   * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC1867</a>:
69   * <blockquote>
70   * The media-type multipart/form-data follows the rules of all multipart
71   * MIME data streams as outlined in RFC 1521. The multipart/form-data contains 
72   * a series of parts. Each part is expected to contain a content-disposition 
73   * header where the value is "form-data" and a name attribute specifies 
74   * the field name within the form, e.g., 'content-disposition: form-data; 
75   * name="xxxxx"', where xxxxx is the field name corresponding to that field.
76   * Field names originally in non-ASCII character sets may be encoded using 
77   * the method outlined in RFC 1522.
78   * </blockquote>
79   * </p>
80   * <p>
81   *
82   * @author <a href="mailto:mattalbright@yahoo.com">Matthew Albright</a>
83   * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
84   * @author <a href="mailto:adrian@ephox.com">Adrian Sutton</a>
85   * @author <a href="mailto:mdiggory@latte.harvard.edu">Mark Diggory</a>
86   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
87   * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
88   *
89   * @since 2.0
90   * 
91   * @deprecated Use {@link edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity}
92   * in conjunction with {@link edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.methods.PostMethod} instead.
93   */
94  public class MultipartPostMethod extends ExpectContinueMethod {
95  
96      /** The Content-Type for multipart/form-data. */
97      public static final String MULTIPART_FORM_CONTENT_TYPE = 
98          "multipart/form-data";
99  
100     /** Log object for this class. */
101     private static final Log LOG = LogFactory.getLog(MultipartPostMethod.class);
102 
103     /** The parameters for this method */
104     private final List parameters = new ArrayList();
105 
106     /**
107      * No-arg constructor.
108      */
109     public MultipartPostMethod() {
110         super();
111     }
112 
113     /**
114      * Constructor specifying a URI.
115      *
116      * @param uri either an absolute or relative URI
117      */
118     public MultipartPostMethod(String uri) {
119         super(uri);
120     }
121 
122     /**
123      * Returns <tt>true</tt> 
124      * 
125      * @return <tt>true</tt>
126      * 
127      * @since 2.0beta1
128      */
129     protected boolean hasRequestContent() {
130         return true;
131     }
132 
133     /**
134      * Returns <tt>"POST"</tt>.
135      * @return <tt>"POST"</tt>
136      */
137     public String getName() {
138         return "POST";
139     }
140 
141     /**
142      * Adds a text field part
143      * 
144      * @param parameterName The name of the parameter.
145      * @param parameterValue The value of the parameter.
146      */
147     public void addParameter(String parameterName, String parameterValue) {
148         LOG.trace("enter addParameter(String parameterName, String parameterValue)");
149         Part param = new StringPart(parameterName, parameterValue);
150         parameters.add(param);
151     }
152 
153     /**
154      * Adds a binary file part
155      * 
156      * @param parameterName The name of the parameter
157      * @param parameterFile The name of the file.
158      * @throws FileNotFoundException If the file cannot be found.
159      */
160     public void addParameter(String parameterName, File parameterFile) 
161     throws FileNotFoundException {
162         LOG.trace("enter MultipartPostMethod.addParameter(String parameterName, "
163             + "File parameterFile)");
164         Part param = new FilePart(parameterName, parameterFile);
165         parameters.add(param);
166     }
167 
168     /**
169      * Adds a binary file part with the given file name
170      * 
171      * @param parameterName The name of the parameter
172      * @param fileName The file name
173      * @param parameterFile The file
174      * @throws FileNotFoundException If the file cannot be found.
175      */
176     public void addParameter(String parameterName, String fileName, File parameterFile) 
177     throws FileNotFoundException {
178         LOG.trace("enter MultipartPostMethod.addParameter(String parameterName, "
179             + "String fileName, File parameterFile)");
180         Part param = new FilePart(parameterName, fileName, parameterFile);
181         parameters.add(param);
182     }
183         
184     /**
185      * Adds a part.
186      * 
187      * @param part The part to add.
188      */
189     public void addPart (final Part part) {
190         LOG.trace("enter addPart(Part part)");
191         parameters.add(part);
192     }
193 
194     /**
195      * Returns all parts.
196      * 
197      * @return an array of containing all parts
198      */
199     public Part[] getParts() {
200         return (Part/grouperClientExt/org/apache/commons/httpclient/methods/multipart/Part.html#Part">Part[]) parameters.toArray(new Part[parameters.size()]);
201     }
202 
203     /**
204      * Adds a <tt>Content-Length</tt> request header, as long as no 
205      * <tt>Content-Length</tt> request header already exists.
206      *
207      * @param state current state of http requests
208      * @param conn the connection to use for I/O
209      *
210      * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
211      *                     can be recovered from.
212      * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
213      *                    cannot be recovered from.
214      * 
215      * @since 3.0
216      */
217     protected void addContentLengthRequestHeader(HttpState state,
218                                                  HttpConnection conn)
219     throws IOException, HttpException {
220         LOG.trace("enter EntityEnclosingMethod.addContentLengthRequestHeader("
221                   + "HttpState, HttpConnection)");
222 
223         if (getRequestHeader("Content-Length") == null) { 
224             long len = getRequestContentLength();
225             addRequestHeader("Content-Length", String.valueOf(len));
226         }
227         removeRequestHeader("Transfer-Encoding");
228     }
229 
230     /**
231      * Adds a <tt>Content-Type</tt> request header.
232      *
233      * @param state current state of http requests
234      * @param conn the connection to use for I/O
235      *
236      * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
237      *                     can be recovered from.
238      * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
239      *                    cannot be recovered from.
240      * 
241      * @since 3.0
242      */
243     protected void addContentTypeRequestHeader(HttpState state,
244                                                  HttpConnection conn)
245     throws IOException, HttpException {
246         LOG.trace("enter EntityEnclosingMethod.addContentTypeRequestHeader("
247                   + "HttpState, HttpConnection)");
248 
249         if (!parameters.isEmpty()) {
250             StringBuffer buffer = new StringBuffer(MULTIPART_FORM_CONTENT_TYPE);
251             if (Part.getBoundary() != null) {
252                 buffer.append("; boundary=");
253                 buffer.append(Part.getBoundary());
254             }
255             setRequestHeader("Content-Type", buffer.toString());
256         }
257     }
258 
259     /**
260      * Populates the request headers map to with additional 
261      * {@link edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.Header headers} to be submitted to 
262      * the given {@link HttpConnection}.
263      *
264      * <p>
265      * This implementation adds tt>Content-Length</tt> and <tt>Content-Type</tt>
266      * headers, when appropriate.
267      * </p>
268      *
269      * <p>
270      * Subclasses may want to override this method to to add additional
271      * headers, and may choose to invoke this implementation (via
272      * <tt>super</tt>) to add the "standard" headers.
273      * </p>
274      *
275      * @param state the {@link HttpState state} information associated with this method
276      * @param conn the {@link HttpConnection connection} used to execute
277      *        this HTTP method
278      *
279      * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
280      *                     can be recovered from.
281      * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
282      *                    cannot be recovered from.
283      *
284      * @see #writeRequestHeaders
285      */
286     protected void addRequestHeaders(HttpState state, HttpConnection conn) 
287     throws IOException, HttpException {
288         LOG.trace("enter MultipartPostMethod.addRequestHeaders(HttpState state, "
289             + "HttpConnection conn)");
290         super.addRequestHeaders(state, conn);
291         addContentLengthRequestHeader(state, conn);
292         addContentTypeRequestHeader(state, conn);
293     }
294 
295     /**
296      * Writes the request body to the given {@link HttpConnection connection}.
297      *
298      * @param state the {@link HttpState state} information associated with this method
299      * @param conn the {@link HttpConnection connection} used to execute
300      *        this HTTP method
301      *
302      * @return <tt>true</tt>
303      *
304      * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
305      *                     can be recovered from.
306      * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
307      *                    cannot be recovered from.
308      */
309     protected boolean writeRequestBody(HttpState state, HttpConnection conn) 
310     throws IOException, HttpException {
311         LOG.trace("enter MultipartPostMethod.writeRequestBody(HttpState state, "
312             + "HttpConnection conn)");
313         OutputStream out = conn.getRequestOutputStream();
314         Part.sendParts(out, getParts());
315         return true;
316     }
317 
318     /**
319      * <p>Return the length of the request body.</p>
320      *
321      * <p>Once this method has been invoked, the request parameters cannot be
322      * altered until the method is {@link #recycle recycled}.</p>
323      * 
324      * @return The request content length.
325      */
326     protected long getRequestContentLength() throws IOException {
327         LOG.trace("enter MultipartPostMethod.getRequestContentLength()");
328         return Part.getLengthOfParts(getParts());
329     }
330 
331 
332     /**
333      * Recycles the HTTP method so that it can be used again.
334      * Note that all of the instance variables will be reset
335      * once this method has been called. This method will also
336      * release the connection being used by this HTTP method.
337      * 
338      * @see #releaseConnection()
339      * 
340      * @deprecated no longer supported and will be removed in the future
341      *             version of HttpClient
342      */
343     public void recycle() {
344         LOG.trace("enter MultipartPostMethod.recycle()");
345         super.recycle();
346         parameters.clear();
347     }
348 }