001: /*
002: * Copyright (c) 2002-2006 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.webwork.dispatcher.multipart;
006:
007: import com.opensymphony.webwork.config.Configuration;
008: import com.opensymphony.webwork.dispatcher.WebWorkRequestWrapper;
009: import com.opensymphony.webwork.WebWorkConstants;
010: import com.opensymphony.webwork.util.ClassLoaderUtils;
011: import org.apache.commons.logging.Log;
012: import org.apache.commons.logging.LogFactory;
013:
014: import javax.servlet.http.HttpServletRequest;
015: import java.io.File;
016: import java.lang.reflect.Constructor;
017: import java.lang.reflect.InvocationTargetException;
018: import java.util.*;
019:
020: /**
021: * Parses a multipart request and provides a wrapper around the request. The parsing implementation used
022: * depends on the <tt>webwork.multipart.parser</tt> setting. It should be set to a class which
023: * extends {@link com.opensymphony.webwork.dispatcher.multipart.MultiPartRequest}. <p>
024: * <p/>
025: * Webwork ships with three implementations,
026: * {@link com.opensymphony.webwork.dispatcher.multipart.PellMultiPartRequest}, and
027: * {@link com.opensymphony.webwork.dispatcher.multipart.CosMultiPartRequest} and
028: * {@link com.opensymphony.webwork.dispatcher.multipart.JakartaMultiPartRequest}. The Jakarta implementation
029: * is the default. The <tt>webwork.multipart.parser</tt> property should be set to <tt>jakarta</tt> for the
030: * Jakarta implementation, <tt>pell</tt> for the Pell implementation and <tt>cos</tt> for the Jason Hunter
031: * implementation. <p>
032: * <p/>
033: * The files are uploaded when the object is instantiated. If there are any errors they are logged using
034: * {@link #addError(String)}. An action handling a multipart form should first check {@link #hasErrors()}
035: * before doing any other processing. <p>
036: *
037: * @author Matt Baldree
038: */
039: public class MultiPartRequestWrapper extends WebWorkRequestWrapper {
040: protected static final Log log = LogFactory
041: .getLog(MultiPartRequestWrapper.class);
042:
043: Collection errors;
044: MultiPartRequest multi;
045:
046: /**
047: * Instantiates the appropriate MultiPartRequest parser implementation and processes the data.
048: *
049: * @param request the servlet request object
050: * @param saveDir directory to save the file(s) to
051: * @param maxSize maximum file size allowed
052: */
053: public MultiPartRequestWrapper(HttpServletRequest request,
054: String saveDir, int maxSize) {
055: super (request);
056:
057: if (request instanceof MultiPartRequest) {
058: multi = (MultiPartRequest) request;
059: } else {
060: String parser = Configuration
061: .getString(WebWorkConstants.WEBWORK_MULTIPART_PARSER);
062:
063: // If it's not set, use Jakarta
064: if (parser.equals("")) {
065: log
066: .warn("Property webwork.multipart.parser not set."
067: + " Using com.opensymphony.webwork.dispatcher.multipart.JakartaMultiPartRequest");
068: parser = "com.opensymphony.webwork.dispatcher.multipart.JakartaMultiPartRequest";
069: }
070: // legacy support for old style property values
071: else if (parser.equals("pell")) {
072: parser = "com.opensymphony.webwork.dispatcher.multipart.PellMultiPartRequest";
073: } else if (parser.equals("cos")) {
074: parser = "com.opensymphony.webwork.dispatcher.multipart.CosMultiPartRequest";
075: } else if (parser.equals("jakarta")) {
076: parser = "com.opensymphony.webwork.dispatcher.multipart.JakartaMultiPartRequest";
077: }
078:
079: try {
080: Class baseClazz = com.opensymphony.webwork.dispatcher.multipart.MultiPartRequest.class;
081:
082: Class clazz = ClassLoaderUtils.loadClass(parser,
083: MultiPartRequestWrapper.class);
084:
085: // make sure it extends MultiPartRequest
086: if (!baseClazz.isAssignableFrom(clazz)) {
087: addError("Class '" + parser
088: + "' does not extend MultiPartRequest");
089:
090: return;
091: }
092:
093: // get the constructor
094: Constructor ctor = clazz
095: .getDeclaredConstructor(new Class[] {
096: ClassLoaderUtils
097: .loadClass(
098: "javax.servlet.http.HttpServletRequest",
099: MultiPartRequestWrapper.class),
100: java.lang.String.class, int.class });
101:
102: // build the parameter list
103: Object[] parms = new Object[] { request, saveDir,
104: new Integer(maxSize) };
105:
106: // instantiate it
107: multi = (MultiPartRequest) ctor.newInstance(parms);
108: for (Iterator iter = multi.getErrors().iterator(); iter
109: .hasNext();) {
110: String error = (String) iter.next();
111: addError(error);
112: }
113: } catch (ClassNotFoundException e) {
114: log.error(e.toString(), e);
115: addError("Class: " + parser + " not found.");
116: } catch (NoSuchMethodException e) {
117: log.error(e.toString(), e);
118: addError("Constructor error for " + parser + ": " + e);
119: } catch (InstantiationException e) {
120: log.error(e.toString(), e);
121: addError("Error instantiating " + parser + ": " + e);
122: } catch (IllegalAccessException e) {
123: log.error(e.toString(), e);
124: addError("Access errror for " + parser + ": " + e);
125: } catch (InvocationTargetException e) {
126: // This is a wrapper for any exceptions thrown by the constructor called from newInstance
127: log.error(e.toString(), e);
128: addError(e.getTargetException().toString());
129: }
130: }
131: }
132:
133: /**
134: * @deprecated use {@link #getFileParameterNames()} instead
135: */
136: public Enumeration getFileNames() {
137: return getFileParameterNames();
138: }
139:
140: /**
141: * Get an enumeration of the parameter names for uploaded files
142: *
143: * @return enumeration of parameter names for uploaded files
144: */
145: public Enumeration getFileParameterNames() {
146: if (multi == null) {
147: return null;
148: }
149:
150: return multi.getFileParameterNames();
151: }
152:
153: /**
154: * @deprecated use {@link #getContentTypes(String)} instead
155: */
156: public String getContentType(String fieldName) {
157: String[] contentTypes = getContentTypes(fieldName);
158: if (contentTypes != null && contentTypes.length > 0) {
159: return contentTypes[0];
160: }
161:
162: return null;
163: }
164:
165: /**
166: * Get an array of content encoding for the specified input field name or <tt>null</tt> if
167: * no content type was specified.
168: *
169: * @param name input field name
170: * @return an array of content encoding for the specified input field name
171: */
172: public String[] getContentTypes(String name) {
173: if (multi == null) {
174: return null;
175: }
176:
177: return multi.getContentType(name);
178: }
179:
180: /**
181: * @deprecated use {@link #getFiles(String)} instead
182: */
183: public File getFile(String fieldName) {
184: File[] files = getFiles(fieldName);
185: if (files != null && files.length > 0) {
186: return files[0];
187: }
188:
189: return null;
190: }
191:
192: /**
193: * Get a {@link java.io.File[]} for the given input field name.
194: *
195: * @param fieldName input field name
196: * @return a File[] object for files associated with the specified input field name
197: */
198: public File[] getFiles(String fieldName) {
199: if (multi == null) {
200: return null;
201: }
202:
203: return multi.getFile(fieldName);
204: }
205:
206: /**
207: * Get a String array of the file names for uploaded files
208: *
209: * @return a String[] of file names for uploaded files
210: */
211: public String[] getFileNames(String fieldName) {
212: if (multi == null) {
213: return null;
214: }
215:
216: return multi.getFileNames(fieldName);
217: }
218:
219: /**
220: * @deprecated use {@link #getFileSystemNames(String)} instead
221: */
222: public String getFilesystemName(String fieldName) {
223: String[] names = getFileSystemNames(fieldName);
224: if (names != null && names.length > 0) {
225: return names[0];
226: }
227:
228: return null;
229: }
230:
231: /**
232: * Get the filename(s) of the file(s) uploaded for the given input field name.
233: * Returns <tt>null</tt> if the file is not found.
234: *
235: * @param fieldName input field name
236: * @return the filename(s) of the file(s) uploaded for the given input field name or
237: * <tt>null</tt> if name not found.
238: */
239: public String[] getFileSystemNames(String fieldName) {
240: if (multi == null) {
241: return null;
242: }
243:
244: return multi.getFilesystemName(fieldName);
245: }
246:
247: /**
248: * @see javax.servlet.http.HttpServletRequest#getParameter(String)
249: */
250: public String getParameter(String name) {
251: return ((multi == null) || (multi.getParameter(name) == null)) ? super
252: .getParameter(name)
253: : multi.getParameter(name);
254: }
255:
256: /**
257: * @see javax.servlet.http.HttpServletRequest#getParameterMap()
258: */
259: public Map getParameterMap() {
260: Map map = new HashMap();
261: Enumeration enumeration = getParameterNames();
262:
263: while (enumeration.hasMoreElements()) {
264: String name = (String) enumeration.nextElement();
265: map.put(name, this .getParameterValues(name));
266: }
267:
268: return map;
269: }
270:
271: /**
272: * @see javax.servlet.http.HttpServletRequest#getParameterNames()
273: */
274: public Enumeration getParameterNames() {
275: if (multi == null) {
276: return super .getParameterNames();
277: } else {
278: return mergeParams(multi.getParameterNames(), super
279: .getParameterNames());
280: }
281: }
282:
283: /**
284: * @see javax.servlet.http.HttpServletRequest#getParameterValues(String)
285: */
286: public String[] getParameterValues(String name) {
287: return ((multi == null) || (multi.getParameterValues(name) == null)) ? super
288: .getParameterValues(name)
289: : multi.getParameterValues(name);
290: }
291:
292: /**
293: * Returns <tt>true</tt> if any errors occured when parsing the HTTP multipart request, <tt>false</tt> otherwise.
294: *
295: * @return <tt>true</tt> if any errors occured when parsing the HTTP multipart request, <tt>false</tt> otherwise.
296: */
297: public boolean hasErrors() {
298: if ((errors == null) || errors.isEmpty()) {
299: return false;
300: } else {
301: return true;
302: }
303: }
304:
305: /**
306: * Returns a collection of any errors generated when parsing the multipart request.
307: *
308: * @return the error Collection.
309: */
310: public Collection getErrors() {
311: return errors;
312: }
313:
314: /**
315: * Adds an error message.
316: *
317: * @param anErrorMessage the error message to report.
318: */
319: protected void addError(String anErrorMessage) {
320: if (errors == null) {
321: errors = new ArrayList();
322: }
323:
324: errors.add(anErrorMessage);
325: }
326:
327: /**
328: * Merges 2 enumeration of parameters as one.
329: *
330: * @param params1 the first enumeration.
331: * @param params2 the second enumeration.
332: * @return a single Enumeration of all elements from both Enumerations.
333: */
334: protected Enumeration mergeParams(Enumeration params1,
335: Enumeration params2) {
336: Vector temp = new Vector();
337:
338: while (params1.hasMoreElements()) {
339: temp.add(params1.nextElement());
340: }
341:
342: while (params2.hasMoreElements()) {
343: temp.add(params2.nextElement());
344: }
345:
346: return temp.elements();
347: }
348: }
|