KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jodd > servlet > upload > MultipartRequest


1 // Copyright (c) 2003-2007, Jodd Team (jodd.sf.net). All Rights Reserved.
2

3 package jodd.servlet.upload;
4
5 import jodd.servlet.ServletUtil;
6 import jodd.servlet.upload.impl.MemoryFileUpload;
7
8 import javax.servlet.http.HttpServletRequest JavaDoc;
9 import java.io.IOException JavaDoc;
10 import java.io.UnsupportedEncodingException JavaDoc;
11 import java.util.*;
12
13 /**
14  * Handles multipart requests and extract uploaded files and parameters from
15  * it. Multipart forms should be defined as:
16  * <p>
17  *
18  * <code>
19  * &lt;form method="post" enctype="multipart/form-data" accept-charset="<i>charset</i>"...
20  * </code>
21  *
22  * <p>
23  * "accept-charset" may be used in case when jsp page uses specific
24  * encoding. If default encoding is used, this attribute is not required.
25  *
26  * <p>
27  * MultipleRequest class may be created in two ways:<br>
28  * 1) with the constructors, when user must prevent instatiating more than once;<br>
29  * 2) using staic factory methods, which always return valid MultipleRequest instance.
30  *
31  * <p>
32  * This class loads complete request. To prevent big uploads (and potential
33  * DoS attacks) check content length <b>before</b> loading.
34  */

35 public class MultipartRequest {
36
37     // ---------------------------------------------------------------- properties
38

39     private Map requestParameters;
40     private Map requestFiles;
41     private HttpServletRequest JavaDoc request;
42     private String JavaDoc characterEncoding;
43     private FileUploadFactory fileUploadFactory;
44
45     /**
46      * Returns actual http servlet request instance.
47      */

48     public HttpServletRequest JavaDoc getServletRequest() {
49         return request;
50     }
51
52     /**
53      * Returns request content length. Usually used before loading, to check the upload size.
54      */

55     public int getContentLength() {
56         return request.getContentLength();
57     }
58
59     /**
60      * Returns current encoding.
61      */

62     public String JavaDoc getCharacterEncoding() {
63         return characterEncoding;
64     }
65
66     // ---------------------------------------------------------------- constructors
67

68
69     /**
70      * @see #MultipartRequest(javax.servlet.http.HttpServletRequest, FileUploadFactory, String)
71      */

72     public MultipartRequest(HttpServletRequest JavaDoc request) {
73         this(request, null, null);
74     }
75
76     /**
77      * @see #MultipartRequest(javax.servlet.http.HttpServletRequest, FileUploadFactory, String)
78      */

79     public MultipartRequest(HttpServletRequest JavaDoc request, FileUploadFactory fileUploadFactory) {
80         this(request, fileUploadFactory, null);
81     }
82
83     /**
84      * @see #MultipartRequest(javax.servlet.http.HttpServletRequest, FileUploadFactory, String)
85      */

86     public MultipartRequest(HttpServletRequest JavaDoc request, String JavaDoc encoding) {
87         this(request, null, encoding);
88     }
89
90     /**
91      * Creates new Multipart request with form encoding and file upload factory.
92      * After construction stream is <b>not</b> yet parsed! Use {@link #parseMultipartRequest()} or
93      * {@link #parseRequest()} to parse before further usage.
94      *
95      * <p>
96      * If not specified, character encoding is read from the request.
97      *
98      * <p>
99      * Multiple instantiation doesn't work, since input stream can be parsed just once.
100      * Still, if it is needed, use {@link #getInstance(javax.servlet.http.HttpServletRequest, FileUploadFactory, String)}
101      * instead.
102      *
103      * @param request http request
104      * @param encoding form encoding or <code>null</code>
105      * @param fileUploadFactory file factory, or <code>null</code> for default factory
106      */

107     public MultipartRequest(HttpServletRequest JavaDoc request, FileUploadFactory fileUploadFactory, String JavaDoc encoding) {
108         this.request = request;
109         if (encoding != null) {
110             this.characterEncoding = encoding;
111         } else {
112             this.characterEncoding = request.getCharacterEncoding();
113         }
114         this.fileUploadFactory = (fileUploadFactory == null ? new MemoryFileUpload.Factory() : fileUploadFactory);
115     }
116
117     // ---------------------------------------------------------------- factories
118

119     private static String JavaDoc MREQ_ATTR_NAME = "jodd.servlet.upload.MultipartRequest";
120
121     /**
122      * Returns a new instance of MultipleRequest if it was not created before during current request.
123      */

124     public static MultipartRequest getInstance(HttpServletRequest JavaDoc request, FileUploadFactory fileUploadFactory, String JavaDoc encoding) {
125         MultipartRequest mreq = (MultipartRequest) request.getAttribute(MREQ_ATTR_NAME);
126         if (mreq == null) {
127             mreq = new MultipartRequest(request, fileUploadFactory, encoding);
128             request.setAttribute(MREQ_ATTR_NAME, mreq);
129         }
130         return mreq;
131     }
132
133     /**
134      * Returns parsed instance of MultipartRequest.
135      */

136     public static MultipartRequest getParsedInstance(HttpServletRequest JavaDoc request, FileUploadFactory fileUploadFactory, String JavaDoc encoding) throws IOException JavaDoc {
137         MultipartRequest mreq = getInstance(request, fileUploadFactory, encoding);
138         if (mreq.isLoaded() == false) {
139             mreq.parseRequest();
140         }
141         return mreq;
142     }
143
144     public static MultipartRequest getInstance(HttpServletRequest JavaDoc request, String JavaDoc encoding) {
145         return getInstance(request, null, encoding);
146     }
147     public static MultipartRequest getParsedInstance(HttpServletRequest JavaDoc request, String JavaDoc encoding) throws IOException JavaDoc {
148         MultipartRequest mreq = getInstance(request, null, encoding);
149         if (mreq.isLoaded() == false) {
150             mreq.parseRequest();
151         }
152         return mreq;
153     }
154
155
156     public static MultipartRequest getInstance(HttpServletRequest JavaDoc request, FileUploadFactory fileUploadFactory) {
157         return getInstance(request, fileUploadFactory, null);
158     }
159     public static MultipartRequest getParsedInstance(HttpServletRequest JavaDoc request, FileUploadFactory fileUploadFactory) throws IOException JavaDoc {
160         MultipartRequest mreq = getInstance(request, fileUploadFactory, null);
161         if (mreq.isLoaded() == false) {
162             mreq.parseRequest();
163         }
164         return mreq;
165     }
166
167     public static MultipartRequest getInstance(HttpServletRequest JavaDoc request) {
168         return getInstance(request, null, null);
169     }
170     public static MultipartRequest getParsedInstance(HttpServletRequest JavaDoc request) throws IOException JavaDoc {
171         MultipartRequest mreq = getInstance(request, null, null);
172         if (mreq.isLoaded() == false) {
173             mreq.parseRequest();
174         }
175         return mreq;
176     }
177
178     // ---------------------------------------------------------------- load
179

180     private boolean loaded = false;
181
182     /**
183      * Returns <code>true</code> if multipart request is already loaded.
184      */

185     public boolean isLoaded() {
186         return loaded;
187     }
188
189     /**
190      * Loads and parse multipart request. It <b>doesn't</b> check if request is multipart.
191      * Must be called on same request at most <b>once</b>.
192      */

193     public void parseMultipartRequest() throws IOException JavaDoc {
194         if (loaded == true) {
195             throw new IOException JavaDoc("Multipart request already loaded and parsed.");
196         }
197         loaded = true;
198         parseRequestStream(request, characterEncoding);
199     }
200
201     /**
202      * Checks if request if multipart and parse it. If request is not multipart it
203      * copies all parameters, to make usage the same in both cases.
204      *
205      * @see MultipartRequestWrapper
206      */

207     public void parseRequest() throws IOException JavaDoc {
208         if (loaded == true) {
209             throw new IOException JavaDoc("Multipart request already loaded and parsed.");
210         }
211         loaded = true;
212         if (ServletUtil.isMultipartRequest(request) == true) {
213             parseRequestStream(request, characterEncoding);
214         } else {
215             requestParameters = new HashMap();
216             requestFiles = new HashMap();
217             Enumeration names = request.getParameterNames();
218             while (names.hasMoreElements()) {
219                 String JavaDoc paramName = (String JavaDoc) names.nextElement();
220                 String JavaDoc[] values = request.getParameterValues(paramName);
221                 requestParameters.put(paramName, values);
222             }
223         }
224     }
225
226     // ---------------------------------------------------------------- parameters
227

228
229     /**
230      * Returns single value of a parameter. If parameter name is used for
231      * more then one parameter, only the first one will be returned.
232      *
233      * @return parameter value, or <code>null</code> if not found
234      */

235     public String JavaDoc getParameter(String JavaDoc paramName) {
236         String JavaDoc[] values = (String JavaDoc[]) requestParameters.get(paramName);
237         if ((values != null) && (values.length > 0)) {
238             return values[0];
239         }
240         return null;
241     }
242
243     /**
244      * Returns the names of the parameters contained in this request.
245      */

246     public Set getParameterNames() {
247         return requestParameters.keySet();
248     }
249
250     /**
251      * Returns all values all of the values the given request parameter has.
252      */

253     public String JavaDoc[] getParameterValues(String JavaDoc paramName) {
254         return (String JavaDoc[]) requestParameters.get(paramName);
255     }
256
257
258     /**
259      * Returns uploaded file.
260      * @param paramName parameter name of the uploaded file
261      * @return uploaded file or <code>null</code> if parameter name not found
262      */

263     public FileUpload getFile(String JavaDoc paramName) {
264         FileUpload[] values = (FileUpload[]) requestFiles.get(paramName);
265         if ((values != null) && (values.length > 0)) {
266             return values[0];
267         }
268         return null;
269     }
270
271
272     /**
273      * Returns all uploaded files the given request parameter has.
274      */

275     public FileUpload[] getFiles(String JavaDoc paramName) {
276         return (FileUpload[]) requestFiles.get(paramName);
277     }
278
279     /**
280      * Returns parameter names of all uploaded files.
281      */

282     public Set getFileParameterNames() {
283         return requestFiles.keySet();
284     }
285
286
287     // ---------------------------------------------------------------- load and extract
288

289     private void put(Map destination, String JavaDoc name, Object JavaDoc value) {
290         ArrayList valuesList = (ArrayList) destination.get(name);
291         if (valuesList == null) {
292             valuesList = new ArrayList();
293             destination.put(name, valuesList);
294         }
295         valuesList.add(value);
296     }
297
298     /**
299      * Extracts uploaded files and parameters from the request data.
300      */

301     protected void parseRequestStream(HttpServletRequest JavaDoc request, String JavaDoc encoding) throws IOException JavaDoc {
302         requestParameters = new HashMap();
303         requestFiles = new HashMap();
304
305         MultipartRequestInputStream input = new MultipartRequestInputStream(request.getInputStream());
306         input.readBoundary();
307         while (true) {
308             FileUploadHeader header = input.readDataHeader(encoding);
309             if (header == null) {
310                 break;
311             }
312
313             if (header.isFile && (header.fileName.length() > 0)) {
314                 if (header.contentType.indexOf("application/x-macbinary") > 0) {
315                     input.skipBytes(128);
316                 }
317                 FileUpload newFile = fileUploadFactory.create(input);
318                 newFile.processStream();
319                 put(requestFiles, header.formFieldName, newFile);
320             } else {
321                 MemoryFileUpload newFile = new MemoryFileUpload(input);
322                 newFile.processStream();
323                 if (header.isFile == true) {
324                     // file was specified, but no name was provided, therefore it was not uploaded.
325
newFile.uploaded = false;
326                     put(requestFiles, header.formFieldName, newFile);
327                 } else {
328                     // no file, therefore it is regular form parameter.
329
String JavaDoc value = null;
330                     if (encoding != null) {
331                         try {
332                             value = new String JavaDoc(newFile.getFileData(), encoding);
333                         } catch (UnsupportedEncodingException JavaDoc ucex) {
334                             value = null;
335                         }
336                     }
337                     if (value == null) {
338                         value = new String JavaDoc(newFile.getFileData());
339                     }
340                     put(requestParameters, header.formFieldName, value);
341                 }
342             }
343             input.skipBytes(1);
344             input.mark(1);
345             if (input.readByte() == '-') {
346                 input.reset();
347                 break;
348             }
349             input.reset();
350         }
351
352         // convert lists into arrays
353
Iterator names = requestParameters.keySet().iterator();
354         while (names.hasNext()) {
355             String JavaDoc paramName = (String JavaDoc) names.next();
356             ArrayList valuesList = (ArrayList) requestParameters.get(paramName);
357             if (valuesList != null) {
358                 String JavaDoc[] result = new String JavaDoc[valuesList.size()];
359                 for (int i = 0; i < result.length; i++) {
360                     result[i] = (String JavaDoc) valuesList.get(i);
361                 }
362                 requestParameters.put(paramName, result);
363             }
364         }
365         names = requestFiles.keySet().iterator();
366         while (names.hasNext()) {
367             String JavaDoc paramName = (String JavaDoc) names.next();
368             ArrayList valuesList = (ArrayList) requestFiles.get(paramName);
369             if (valuesList != null) {
370                 FileUpload[] result = new FileUpload[valuesList.size()];
371                 for (int i = 0; i < result.length; i++) {
372                     result[i] = (FileUpload) valuesList.get(i);
373                 }
374                 requestFiles.put(paramName, result);
375             }
376         }
377     }
378 }
Popular Tags