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