001: /*
002: * $Id: JakartaMultiPartRequest.java 559304 2007-07-25 03:39:12Z jholmes $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021: package org.apache.struts2.dispatcher.multipart;
022:
023: import java.io.File;
024: import java.io.IOException;
025: import java.io.InputStream;
026: import java.util.ArrayList;
027: import java.util.Collections;
028: import java.util.Enumeration;
029: import java.util.HashMap;
030: import java.util.List;
031: import java.util.Map;
032:
033: import javax.servlet.http.HttpServletRequest;
034:
035: import org.apache.commons.fileupload.FileItem;
036: import org.apache.commons.fileupload.FileUploadException;
037: import org.apache.commons.fileupload.RequestContext;
038: import org.apache.commons.fileupload.disk.DiskFileItem;
039: import org.apache.commons.fileupload.disk.DiskFileItemFactory;
040: import org.apache.commons.fileupload.servlet.ServletFileUpload;
041: import org.apache.commons.logging.Log;
042: import org.apache.commons.logging.LogFactory;
043: import org.apache.struts2.StrutsConstants;
044:
045: import com.opensymphony.xwork2.inject.Inject;
046:
047: /**
048: * Multipart form data request adapter for Jakarta Commons Fileupload package.
049: *
050: */
051: public class JakartaMultiPartRequest implements MultiPartRequest {
052:
053: static final Log log = LogFactory.getLog(MultiPartRequest.class);
054:
055: // maps parameter name -> List of FileItem objects
056: private Map<String, List<FileItem>> files = new HashMap<String, List<FileItem>>();
057: // maps parameter name -> List of param values
058: private Map<String, List<String>> params = new HashMap<String, List<String>>();
059: // any errors while processing this request
060: private List<String> errors = new ArrayList<String>();
061:
062: private long maxSize;
063:
064: @Inject(StrutsConstants.STRUTS_MULTIPART_MAXSIZE)
065: public void setMaxSize(String maxSize) {
066: this .maxSize = Long.parseLong(maxSize);
067: }
068:
069: /**
070: * Creates a new request wrapper to handle multi-part data using methods adapted from Jason Pell's
071: * multipart classes (see class description).
072: *
073: * @param saveDir the directory to save off the file
074: * @param servletRequest the request containing the multipart
075: * @throws java.io.IOException is thrown if encoding fails.
076: */
077: public void parse(HttpServletRequest servletRequest, String saveDir)
078: throws IOException {
079: DiskFileItemFactory fac = new DiskFileItemFactory();
080: // Make sure that the data is written to file
081: fac.setSizeThreshold(0);
082: if (saveDir != null) {
083: fac.setRepository(new File(saveDir));
084: }
085:
086: // Parse the request
087: try {
088: ServletFileUpload upload = new ServletFileUpload(fac);
089: upload.setSizeMax(maxSize);
090: List items = upload
091: .parseRequest(createRequestContext(servletRequest));
092:
093: for (Object item1 : items) {
094: FileItem item = (FileItem) item1;
095: if (log.isDebugEnabled())
096: log.debug("Found item " + item.getFieldName());
097: if (item.isFormField()) {
098: log.debug("Item is a normal form field");
099: 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: // note: see http://jira.opensymphony.com/browse/WW-633
107: // basically, in some cases the charset may be null, so
108: // we're just going to try to "other" method (no idea if this
109: // will work)
110: String charset = servletRequest
111: .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: // Skip file uploads that don't have a file name - meaning that no file was selected.
122: if (item.getName() == null
123: || item.getName().trim().length() < 1) {
124: log
125: .debug("No file has been uploaded for the field: "
126: + item.getFieldName());
127: continue;
128: }
129:
130: List<FileItem> values;
131: if (files.get(item.getFieldName()) != null) {
132: values = files.get(item.getFieldName());
133: } else {
134: values = new ArrayList<FileItem>();
135: }
136:
137: values.add(item);
138: files.put(item.getFieldName(), values);
139: }
140: }
141: } catch (FileUploadException e) {
142: log.error(e);
143: errors.add(e.getMessage());
144: }
145: }
146:
147: /* (non-Javadoc)
148: * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFileParameterNames()
149: */
150: public Enumeration<String> getFileParameterNames() {
151: return Collections.enumeration(files.keySet());
152: }
153:
154: /* (non-Javadoc)
155: * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getContentType(java.lang.String)
156: */
157: public String[] getContentType(String fieldName) {
158: List items = (List) files.get(fieldName);
159:
160: if (items == null) {
161: return null;
162: }
163:
164: List<String> contentTypes = new ArrayList<String>(items.size());
165: for (int i = 0; i < items.size(); i++) {
166: FileItem fileItem = (FileItem) items.get(i);
167: contentTypes.add(fileItem.getContentType());
168: }
169:
170: return (String[]) contentTypes.toArray(new String[contentTypes
171: .size()]);
172: }
173:
174: /* (non-Javadoc)
175: * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFile(java.lang.String)
176: */
177: public File[] getFile(String fieldName) {
178: List items = (List) files.get(fieldName);
179:
180: if (items == null) {
181: return null;
182: }
183:
184: List<File> fileList = new ArrayList<File>(items.size());
185: for (int i = 0; i < items.size(); i++) {
186: DiskFileItem fileItem = (DiskFileItem) items.get(i);
187: fileList.add(fileItem.getStoreLocation());
188: }
189:
190: return (File[]) fileList.toArray(new File[fileList.size()]);
191: }
192:
193: /* (non-Javadoc)
194: * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFileNames(java.lang.String)
195: */
196: public String[] getFileNames(String fieldName) {
197: List<FileItem> items = files.get(fieldName);
198:
199: if (items == null) {
200: return null;
201: }
202:
203: List<String> fileNames = new ArrayList<String>(items.size());
204: for (int i = 0; i < items.size(); i++) {
205: DiskFileItem fileItem = (DiskFileItem) items.get(i);
206: fileNames.add(getCanonicalName(fileItem.getName()));
207: }
208:
209: return (String[]) fileNames
210: .toArray(new String[fileNames.size()]);
211: }
212:
213: /* (non-Javadoc)
214: * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFilesystemName(java.lang.String)
215: */
216: public String[] getFilesystemName(String fieldName) {
217: List items = (List) files.get(fieldName);
218:
219: if (items == null) {
220: return null;
221: }
222:
223: List<String> fileNames = new ArrayList<String>(items.size());
224: for (int i = 0; i < items.size(); i++) {
225: DiskFileItem fileItem = (DiskFileItem) items.get(i);
226: fileNames.add(fileItem.getStoreLocation().getName());
227: }
228:
229: return (String[]) fileNames
230: .toArray(new String[fileNames.size()]);
231: }
232:
233: /* (non-Javadoc)
234: * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameter(java.lang.String)
235: */
236: public String getParameter(String name) {
237: List v = (List) params.get(name);
238: if (v != null && v.size() > 0) {
239: return (String) v.get(0);
240: }
241:
242: return null;
243: }
244:
245: /* (non-Javadoc)
246: * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameterNames()
247: */
248: public Enumeration<String> getParameterNames() {
249: return Collections.enumeration(params.keySet());
250: }
251:
252: /* (non-Javadoc)
253: * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameterValues(java.lang.String)
254: */
255: public String[] getParameterValues(String name) {
256: List<String> v = params.get(name);
257: if (v != null && v.size() > 0) {
258: return (String[]) v.toArray(new String[v.size()]);
259: }
260:
261: return null;
262: }
263:
264: /* (non-Javadoc)
265: * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getErrors()
266: */
267: public List getErrors() {
268: return errors;
269: }
270:
271: /**
272: * Returns the canonical name of the given file.
273: *
274: * @param filename the given file
275: * @return the canonical name of the given file
276: */
277: private String getCanonicalName(String filename) {
278: int forwardSlash = filename.lastIndexOf("/");
279: int backwardSlash = filename.lastIndexOf("\\");
280: if (forwardSlash != -1 && forwardSlash > backwardSlash) {
281: filename = filename.substring(forwardSlash + 1, filename
282: .length());
283: } else if (backwardSlash != -1 && backwardSlash >= forwardSlash) {
284: filename = filename.substring(backwardSlash + 1, filename
285: .length());
286: }
287:
288: return filename;
289: }
290:
291: /**
292: * Creates a RequestContext needed by Jakarta Commons Upload.
293: *
294: * @param req the request.
295: * @return a new request context.
296: */
297: private RequestContext createRequestContext(
298: final HttpServletRequest req) {
299: return new RequestContext() {
300: public String getCharacterEncoding() {
301: return req.getCharacterEncoding();
302: }
303:
304: public String getContentType() {
305: return req.getContentType();
306: }
307:
308: public int getContentLength() {
309: return req.getContentLength();
310: }
311:
312: public InputStream getInputStream() throws IOException {
313: return req.getInputStream();
314: }
315: };
316: }
317:
318: }
|