1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.struts.upload;
22
23 import org.apache.commons.fileupload.DiskFileUpload;
24 import org.apache.commons.fileupload.disk.DiskFileItem;
25 import org.apache.commons.fileupload.FileItem;
26 import org.apache.commons.fileupload.FileUploadException;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.struts.Globals;
30 import org.apache.struts.action.ActionMapping;
31 import org.apache.struts.action.ActionServlet;
32 import org.apache.struts.config.ModuleConfig;
33
34 import javax.servlet.ServletContext;
35 import javax.servlet.ServletException;
36 import javax.servlet.http.HttpServletRequest;
37
38 import java.io.File;
39 import java.io.FileNotFoundException;
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.io.Serializable;
43
44 import java.util.ArrayList;
45 import java.util.Hashtable;
46 import java.util.Iterator;
47 import java.util.List;
48
49
50
51
52
53
54
55
56
57 public class CommonsMultipartRequestHandler implements MultipartRequestHandler {
58
59
60
61
62
63
64 public static final long DEFAULT_SIZE_MAX = 250 * 1024 * 1024;
65
66
67
68
69
70
71 public static final int DEFAULT_SIZE_THRESHOLD = 256 * 1024;
72
73
74
75
76
77
78 protected static Log log =
79 LogFactory.getLog(CommonsMultipartRequestHandler.class);
80
81
82
83
84 private Hashtable elementsAll;
85
86
87
88
89 private Hashtable elementsFile;
90
91
92
93
94 private Hashtable elementsText;
95
96
97
98
99 private ActionMapping mapping;
100
101
102
103
104 private ActionServlet servlet;
105
106
107
108
109
110
111
112
113 public ActionServlet getServlet() {
114 return this.servlet;
115 }
116
117
118
119
120
121
122 public void setServlet(ActionServlet servlet) {
123 this.servlet = servlet;
124 }
125
126
127
128
129
130
131
132 public ActionMapping getMapping() {
133 return this.mapping;
134 }
135
136
137
138
139
140
141
142 public void setMapping(ActionMapping mapping) {
143 this.mapping = mapping;
144 }
145
146
147
148
149
150
151
152
153
154
155 public void handleRequest(HttpServletRequest request)
156 throws ServletException {
157
158 ModuleConfig ac =
159 (ModuleConfig) request.getAttribute(Globals.MODULE_KEY);
160
161
162 DiskFileUpload upload = new DiskFileUpload();
163
164
165
166 upload.setHeaderEncoding(request.getCharacterEncoding());
167
168
169 upload.setSizeMax(getSizeMax(ac));
170
171
172 upload.setSizeThreshold((int) getSizeThreshold(ac));
173
174
175 upload.setRepositoryPath(getRepositoryPath(ac));
176
177
178 elementsText = new Hashtable();
179 elementsFile = new Hashtable();
180 elementsAll = new Hashtable();
181
182
183 List items = null;
184
185 try {
186 items = upload.parseRequest(request);
187 } catch (DiskFileUpload.SizeLimitExceededException e) {
188
189 request.setAttribute(MultipartRequestHandler.ATTRIBUTE_MAX_LENGTH_EXCEEDED,
190 Boolean.TRUE);
191
192 return;
193 } catch (FileUploadException e) {
194 log.error("Failed to parse multipart request", e);
195 throw new ServletException(e);
196 }
197
198
199 Iterator iter = items.iterator();
200
201 while (iter.hasNext()) {
202 FileItem item = (FileItem) iter.next();
203
204 if (item.isFormField()) {
205 addTextParameter(request, item);
206 } else {
207 addFileParameter(item);
208 }
209 }
210 }
211
212
213
214
215
216
217
218 public Hashtable getTextElements() {
219 return this.elementsText;
220 }
221
222
223
224
225
226
227
228 public Hashtable getFileElements() {
229 return this.elementsFile;
230 }
231
232
233
234
235
236
237
238 public Hashtable getAllElements() {
239 return this.elementsAll;
240 }
241
242
243
244
245 public void rollback() {
246 Iterator iter = elementsFile.values().iterator();
247
248 Object o;
249 while (iter.hasNext()) {
250 o = iter.next();
251 if (o instanceof List) {
252 for (Iterator i = ((List)o).iterator(); i.hasNext(); ) {
253 ((FormFile)i.next()).destroy();
254 }
255 } else {
256 ((FormFile)o).destroy();
257 }
258 }
259 }
260
261
262
263
264 public void finish() {
265 rollback();
266 }
267
268
269
270
271
272
273
274
275
276
277
278 protected long getSizeMax(ModuleConfig mc) {
279 return convertSizeToBytes(mc.getControllerConfig().getMaxFileSize(),
280 DEFAULT_SIZE_MAX);
281 }
282
283
284
285
286
287
288
289
290 protected long getSizeThreshold(ModuleConfig mc) {
291 return convertSizeToBytes(mc.getControllerConfig().getMemFileSize(),
292 DEFAULT_SIZE_THRESHOLD);
293 }
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309 protected long convertSizeToBytes(String sizeString, long defaultSize) {
310 int multiplier = 1;
311
312 if (sizeString.endsWith("K")) {
313 multiplier = 1024;
314 } else if (sizeString.endsWith("M")) {
315 multiplier = 1024 * 1024;
316 } else if (sizeString.endsWith("G")) {
317 multiplier = 1024 * 1024 * 1024;
318 }
319
320 if (multiplier != 1) {
321 sizeString = sizeString.substring(0, sizeString.length() - 1);
322 }
323
324 long size = 0;
325
326 try {
327 size = Long.parseLong(sizeString);
328 } catch (NumberFormatException nfe) {
329 log.warn("Invalid format for file size ('" + sizeString
330 + "'). Using default.");
331 size = defaultSize;
332 multiplier = 1;
333 }
334
335 return (size * multiplier);
336 }
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353 protected String getRepositoryPath(ModuleConfig mc) {
354
355 String tempDir = mc.getControllerConfig().getTempDir();
356
357
358 if ((tempDir == null) || (tempDir.length() == 0)) {
359 if (servlet != null) {
360 ServletContext context = servlet.getServletContext();
361 File tempDirFile =
362 (File) context.getAttribute("javax.servlet.context.tempdir");
363
364 tempDir = tempDirFile.getAbsolutePath();
365 }
366
367
368 if ((tempDir == null) || (tempDir.length() == 0)) {
369 tempDir = System.getProperty("java.io.tmpdir");
370 }
371 }
372
373 if (log.isTraceEnabled()) {
374 log.trace("File upload temp dir: " + tempDir);
375 }
376
377 return tempDir;
378 }
379
380
381
382
383
384
385
386
387
388
389 protected void addTextParameter(HttpServletRequest request, FileItem item) {
390 String name = item.getFieldName();
391 String value = null;
392 boolean haveValue = false;
393 String encoding = null;
394
395 if (item instanceof DiskFileItem) {
396 encoding = ((DiskFileItem)item).getCharSet();
397 if (log.isDebugEnabled()) {
398 log.debug("DiskFileItem.getCharSet=[" + encoding + "]");
399 }
400 }
401
402 if (encoding == null) {
403 encoding = request.getCharacterEncoding();
404 if (log.isDebugEnabled()) {
405 log.debug("request.getCharacterEncoding=[" + encoding + "]");
406 }
407 }
408
409 if (encoding != null) {
410 try {
411 value = item.getString(encoding);
412 haveValue = true;
413 } catch (Exception e) {
414
415 }
416 }
417
418 if (!haveValue) {
419 try {
420 value = item.getString("ISO-8859-1");
421 } catch (java.io.UnsupportedEncodingException uee) {
422 value = item.getString();
423 }
424
425 haveValue = true;
426 }
427
428 if (request instanceof MultipartRequestWrapper) {
429 MultipartRequestWrapper wrapper = (MultipartRequestWrapper) request;
430
431 wrapper.setParameter(name, value);
432 }
433
434 String[] oldArray = (String[]) elementsText.get(name);
435 String[] newArray;
436
437 if (oldArray != null) {
438 newArray = new String[oldArray.length + 1];
439 System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
440 newArray[oldArray.length] = value;
441 } else {
442 newArray = new String[] { value };
443 }
444
445 elementsText.put(name, newArray);
446 elementsAll.put(name, newArray);
447 }
448
449
450
451
452
453
454
455 protected void addFileParameter(FileItem item) {
456 FormFile formFile = new CommonsFormFile(item);
457
458 String name = item.getFieldName();
459 if (elementsFile.containsKey(name)) {
460 Object o = elementsFile.get(name);
461 if (o instanceof List) {
462 ((List)o).add(formFile);
463 } else {
464 List list = new ArrayList();
465 list.add((FormFile)o);
466 list.add(formFile);
467 elementsFile.put(name, list);
468 elementsAll.put(name, list);
469 }
470 } else {
471 elementsFile.put(name, formFile);
472 elementsAll.put(name, formFile);
473 }
474 }
475
476
477
478
479
480
481
482
483
484
485 static class CommonsFormFile implements FormFile, Serializable {
486
487
488
489
490 FileItem fileItem;
491
492
493
494
495
496
497
498 public CommonsFormFile(FileItem fileItem) {
499 this.fileItem = fileItem;
500 }
501
502
503
504
505
506
507 public String getContentType() {
508 return fileItem.getContentType();
509 }
510
511
512
513
514
515
516
517 public void setContentType(String contentType) {
518 throw new UnsupportedOperationException(
519 "The setContentType() method is not supported.");
520 }
521
522
523
524
525
526
527 public int getFileSize() {
528 return (int) fileItem.getSize();
529 }
530
531
532
533
534
535
536
537 public void setFileSize(int filesize) {
538 throw new UnsupportedOperationException(
539 "The setFileSize() method is not supported.");
540 }
541
542
543
544
545
546
547 public String getFileName() {
548 return getBaseFileName(fileItem.getName());
549 }
550
551
552
553
554
555
556
557 public void setFileName(String fileName) {
558 throw new UnsupportedOperationException(
559 "The setFileName() method is not supported.");
560 }
561
562
563
564
565
566
567
568
569
570
571
572
573
574 public byte[] getFileData()
575 throws FileNotFoundException, IOException {
576 return fileItem.get();
577 }
578
579
580
581
582
583
584
585
586
587 public InputStream getInputStream()
588 throws FileNotFoundException, IOException {
589 return fileItem.getInputStream();
590 }
591
592
593
594
595
596
597 public void destroy() {
598 fileItem.delete();
599 }
600
601
602
603
604
605
606
607
608
609
610
611 protected String getBaseFileName(String filePath) {
612
613 String fileName = new File(filePath).getName();
614
615
616 int colonIndex = fileName.indexOf(":");
617
618 if (colonIndex == -1) {
619
620 colonIndex = fileName.indexOf("\\\\");
621 }
622
623 int backslashIndex = fileName.lastIndexOf("\\");
624
625 if ((colonIndex > -1) && (backslashIndex > -1)) {
626
627
628 fileName = fileName.substring(backslashIndex + 1);
629 }
630
631 return fileName;
632 }
633
634
635
636
637
638
639 public String toString() {
640 return getFileName();
641 }
642 }
643 }