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