1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.dispatcher.multipart;
23
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.Enumeration;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33
34 import javax.servlet.http.HttpServletRequest;
35
36 import org.apache.commons.fileupload.FileItem;
37 import org.apache.commons.fileupload.FileUploadException;
38 import org.apache.commons.fileupload.RequestContext;
39 import org.apache.commons.fileupload.disk.DiskFileItem;
40 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
41 import org.apache.commons.fileupload.servlet.ServletFileUpload;
42 import org.apache.struts2.StrutsConstants;
43
44 import com.opensymphony.xwork2.inject.Inject;
45 import com.opensymphony.xwork2.util.logging.Logger;
46 import com.opensymphony.xwork2.util.logging.LoggerFactory;
47
48 /***
49 * Multipart form data request adapter for Jakarta Commons Fileupload package.
50 */
51 public class JakartaMultiPartRequest implements MultiPartRequest {
52
53 static final Logger LOG = LoggerFactory.getLogger(MultiPartRequest.class);
54
55
56 protected Map<String,List<FileItem>> files = new HashMap<String,List<FileItem>>();
57
58
59 protected Map<String,List<String>> params = new HashMap<String,List<String>>();
60
61
62 protected List<String> errors = new ArrayList<String>();
63
64 protected long maxSize;
65
66 @Inject(StrutsConstants.STRUTS_MULTIPART_MAXSIZE)
67 public void setMaxSize(String maxSize) {
68 this.maxSize = Long.parseLong(maxSize);
69 }
70
71 /***
72 * Creates a new request wrapper to handle multi-part data using methods adapted from Jason Pell's
73 * multipart classes (see class description).
74 *
75 * @param saveDir the directory to save off the file
76 * @param servletRequest the request containing the multipart
77 * @throws java.io.IOException is thrown if encoding fails.
78 */
79 public void parse(HttpServletRequest servletRequest, String saveDir)
80 throws IOException {
81 DiskFileItemFactory fac = new DiskFileItemFactory();
82
83 fac.setSizeThreshold(0);
84 if (saveDir != null) {
85 fac.setRepository(new File(saveDir));
86 }
87
88
89 try {
90 ServletFileUpload upload = new ServletFileUpload(fac);
91 upload.setSizeMax(maxSize);
92
93 List items = upload.parseRequest(createRequestContext(servletRequest));
94
95 for (Object item1 : items) {
96 FileItem item = (FileItem) item1;
97 if (LOG.isDebugEnabled()) LOG.debug("Found item " + item.getFieldName());
98 if (item.isFormField()) {
99 LOG.debug("Item is a normal form field");
100 List<String> values;
101 if (params.get(item.getFieldName()) != null) {
102 values = params.get(item.getFieldName());
103 } else {
104 values = new ArrayList<String>();
105 }
106
107
108
109
110
111 String charset = servletRequest.getCharacterEncoding();
112 if (charset != null) {
113 values.add(item.getString(charset));
114 } else {
115 values.add(item.getString());
116 }
117 params.put(item.getFieldName(), values);
118 } else {
119 LOG.debug("Item is a file upload");
120
121
122 if (item.getName() == null || item.getName().trim().length() < 1) {
123 LOG.debug("No file has been uploaded for the field: " + item.getFieldName());
124 continue;
125 }
126
127 List<FileItem> values;
128 if (files.get(item.getFieldName()) != null) {
129 values = files.get(item.getFieldName());
130 } else {
131 values = new ArrayList<FileItem>();
132 }
133
134 values.add(item);
135 files.put(item.getFieldName(), values);
136 }
137 }
138 } catch (FileUploadException e) {
139 LOG.warn("Unable to parse request", e);
140 errors.add(e.getMessage());
141 }
142 }
143
144
145
146
147 public Enumeration<String> getFileParameterNames() {
148 return Collections.enumeration(files.keySet());
149 }
150
151
152
153
154 public String[] getContentType(String fieldName) {
155 List<FileItem> items = files.get(fieldName);
156
157 if (items == null) {
158 return null;
159 }
160
161 List<String> contentTypes = new ArrayList<String>(items.size());
162 for (FileItem fileItem : items) {
163 contentTypes.add(fileItem.getContentType());
164 }
165
166 return contentTypes.toArray(new String[contentTypes.size()]);
167 }
168
169
170
171
172 public File[] getFile(String fieldName) {
173 List<FileItem> items = files.get(fieldName);
174
175 if (items == null) {
176 return null;
177 }
178
179 List<File> fileList = new ArrayList<File>(items.size());
180 for (FileItem fileItem : items) {
181 fileList.add(((DiskFileItem) fileItem).getStoreLocation());
182 }
183
184 return fileList.toArray(new File[fileList.size()]);
185 }
186
187
188
189
190 public String[] getFileNames(String fieldName) {
191 List<FileItem> items = files.get(fieldName);
192
193 if (items == null) {
194 return null;
195 }
196
197 List<String> fileNames = new ArrayList<String>(items.size());
198 for (FileItem fileItem : items) {
199 fileNames.add(getCanonicalName(fileItem.getName()));
200 }
201
202 return fileNames.toArray(new String[fileNames.size()]);
203 }
204
205
206
207
208 public String[] getFilesystemName(String fieldName) {
209 List<FileItem> items = files.get(fieldName);
210
211 if (items == null) {
212 return null;
213 }
214
215 List<String> fileNames = new ArrayList<String>(items.size());
216 for (FileItem fileItem : items) {
217 fileNames.add(((DiskFileItem) fileItem).getStoreLocation().getName());
218 }
219
220 return fileNames.toArray(new String[fileNames.size()]);
221 }
222
223
224
225
226 public String getParameter(String name) {
227 List<String> v = params.get(name);
228 if (v != null && v.size() > 0) {
229 return v.get(0);
230 }
231
232 return null;
233 }
234
235
236
237
238 public Enumeration<String> getParameterNames() {
239 return Collections.enumeration(params.keySet());
240 }
241
242
243
244
245 public String[] getParameterValues(String name) {
246 List<String> v = params.get(name);
247 if (v != null && v.size() > 0) {
248 return v.toArray(new String[v.size()]);
249 }
250
251 return null;
252 }
253
254
255
256
257 public List getErrors() {
258 return errors;
259 }
260
261 /***
262 * Returns the canonical name of the given file.
263 *
264 * @param filename the given file
265 * @return the canonical name of the given file
266 */
267 private String getCanonicalName(String filename) {
268 int forwardSlash = filename.lastIndexOf("/");
269 int backwardSlash = filename.lastIndexOf("//");
270 if (forwardSlash != -1 && forwardSlash > backwardSlash) {
271 filename = filename.substring(forwardSlash + 1, filename.length());
272 } else if (backwardSlash != -1 && backwardSlash >= forwardSlash) {
273 filename = filename.substring(backwardSlash + 1, filename.length());
274 }
275
276 return filename;
277 }
278
279 /***
280 * Creates a RequestContext needed by Jakarta Commons Upload.
281 *
282 * @param req the request.
283 * @return a new request context.
284 */
285 private RequestContext createRequestContext(final HttpServletRequest req) {
286 return new RequestContext() {
287 public String getCharacterEncoding() {
288 return req.getCharacterEncoding();
289 }
290
291 public String getContentType() {
292 return req.getContentType();
293 }
294
295 public int getContentLength() {
296 return req.getContentLength();
297 }
298
299 public InputStream getInputStream() throws IOException {
300 InputStream in = req.getInputStream();
301 if (in == null) {
302 throw new IOException("Missing content in the request");
303 }
304 return req.getInputStream();
305 }
306 };
307 }
308
309 }