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 List<FileItem> values;
119 if (files.get(item.getFieldName()) != null) {
120 values = files.get(item.getFieldName());
121 } else {
122 values = new ArrayList<FileItem>();
123 }
124
125 values.add(item);
126 files.put(item.getFieldName(), values);
127 }
128 }
129 } catch (FileUploadException e) {
130 log.error(e);
131 errors.add(e.getMessage());
132 }
133 }
134
135
136
137
138 public Enumeration<String> getFileParameterNames() {
139 return Collections.enumeration(files.keySet());
140 }
141
142
143
144
145 public String[] getContentType(String fieldName) {
146 List items = (List) files.get(fieldName);
147
148 if (items == null) {
149 return null;
150 }
151
152 List<String> contentTypes = new ArrayList<String>(items.size());
153 for (int i = 0; i < items.size(); i++) {
154 FileItem fileItem = (FileItem) items.get(i);
155 contentTypes.add(fileItem.getContentType());
156 }
157
158 return (String[]) contentTypes.toArray(new String[contentTypes.size()]);
159 }
160
161
162
163
164 public File[] getFile(String fieldName) {
165 List items = (List) files.get(fieldName);
166
167 if (items == null) {
168 return null;
169 }
170
171 List<File> fileList = new ArrayList<File>(items.size());
172 for (int i = 0; i < items.size(); i++) {
173 DiskFileItem fileItem = (DiskFileItem) items.get(i);
174 fileList.add(fileItem.getStoreLocation());
175 }
176
177 return (File[]) fileList.toArray(new File[fileList.size()]);
178 }
179
180
181
182
183 public String[] getFileNames(String fieldName) {
184 List<FileItem> items = files.get(fieldName);
185
186 if (items == null) {
187 return null;
188 }
189
190 List<String> fileNames = new ArrayList<String>(items.size());
191 for (int i = 0; i < items.size(); i++) {
192 DiskFileItem fileItem = (DiskFileItem) items.get(i);
193 fileNames.add(getCanonicalName(fileItem.getName()));
194 }
195
196 return (String[]) fileNames.toArray(new String[fileNames.size()]);
197 }
198
199
200
201
202 public String[] getFilesystemName(String fieldName) {
203 List items = (List) files.get(fieldName);
204
205 if (items == null) {
206 return null;
207 }
208
209 List<String> fileNames = new ArrayList<String>(items.size());
210 for (int i = 0; i < items.size(); i++) {
211 DiskFileItem fileItem = (DiskFileItem) items.get(i);
212 fileNames.add(fileItem.getStoreLocation().getName());
213 }
214
215 return (String[]) fileNames.toArray(new String[fileNames.size()]);
216 }
217
218
219
220
221 public String getParameter(String name) {
222 List v = (List) params.get(name);
223 if (v != null && v.size() > 0) {
224 return (String) v.get(0);
225 }
226
227 return null;
228 }
229
230
231
232
233 public Enumeration<String> getParameterNames() {
234 return Collections.enumeration(params.keySet());
235 }
236
237
238
239
240 public String[] getParameterValues(String name) {
241 List<String> v = params.get(name);
242 if (v != null && v.size() > 0) {
243 return (String[]) v.toArray(new String[v.size()]);
244 }
245
246 return null;
247 }
248
249
250
251
252 public List getErrors() {
253 return errors;
254 }
255
256 /***
257 * Returns the canonical name of the given file.
258 *
259 * @param filename the given file
260 * @return the canonical name of the given file
261 */
262 private String getCanonicalName(String filename) {
263 int forwardSlash = filename.lastIndexOf("/");
264 int backwardSlash = filename.lastIndexOf("//");
265 if (forwardSlash != -1 && forwardSlash > backwardSlash) {
266 filename = filename.substring(forwardSlash + 1, filename.length());
267 } else if (backwardSlash != -1 && backwardSlash >= forwardSlash) {
268 filename = filename.substring(backwardSlash + 1, filename.length());
269 }
270
271 return filename;
272 }
273
274 /***
275 * Creates a RequestContext needed by Jakarta Commons Upload.
276 *
277 * @param req the request.
278 * @return a new request context.
279 */
280 private RequestContext createRequestContext(final HttpServletRequest req) {
281 return new RequestContext() {
282 public String getCharacterEncoding() {
283 return req.getCharacterEncoding();
284 }
285
286 public String getContentType() {
287 return req.getContentType();
288 }
289
290 public int getContentLength() {
291 return req.getContentLength();
292 }
293
294 public InputStream getInputStream() throws IOException {
295 return req.getInputStream();
296 }
297 };
298 }
299
300 }