1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts2.dispatcher.multipart;
19
20 import java.io.File;
21 import java.lang.reflect.Constructor;
22 import java.lang.reflect.InvocationTargetException;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Enumeration;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.Map;
29 import java.util.Vector;
30
31 import javax.servlet.http.HttpServletRequest;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.struts2.StrutsConstants;
36 import org.apache.struts2.config.Settings;
37 import org.apache.struts2.dispatcher.StrutsRequestWrapper;
38 import org.apache.struts2.util.ClassLoaderUtils;
39
40
41 /***
42 * Parses a multipart request and provides a wrapper around the request. The parsing implementation used
43 * depends on the <tt>struts.multipart.parser</tt> setting. It should be set to a class which
44 * extends {@link org.apache.struts2.dispatcher.multipart.MultiPartRequest}. <p>
45 * <p/>
46 * Struts ships with three implementations,
47 * {@link org.apache.struts2.dispatcher.multipart.PellMultiPartRequest}, and
48 * {@link org.apache.struts2.dispatcher.multipart.CosMultiPartRequest} and
49 * {@link org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest}. The Jakarta implementation
50 * is the default. The <tt>struts.multipart.parser</tt> property should be set to <tt>jakarta</tt> for the
51 * Jakarta implementation, <tt>pell</tt> for the Pell implementation and <tt>cos</tt> for the Jason Hunter
52 * implementation. <p>
53 * <p/>
54 * The files are uploaded when the object is instantiated. If there are any errors they are logged using
55 * {@link #addError(String)}. An action handling a multipart form should first check {@link #hasErrors()}
56 * before doing any other processing. <p>
57 *
58 */
59 public class MultiPartRequestWrapper extends StrutsRequestWrapper {
60 protected static final Log log = LogFactory.getLog(MultiPartRequestWrapper.class);
61
62 Collection errors;
63 MultiPartRequest multi;
64
65 /***
66 * Instantiates the appropriate MultiPartRequest parser implementation and processes the data.
67 *
68 * @param request the servlet request object
69 * @param saveDir directory to save the file(s) to
70 * @param maxSize maximum file size allowed
71 */
72 public MultiPartRequestWrapper(HttpServletRequest request, String saveDir, int maxSize) {
73 super(request);
74
75 if (request instanceof MultiPartRequest) {
76 multi = (MultiPartRequest) request;
77 } else {
78 String parser = Settings.get(StrutsConstants.STRUTS_MULTIPART_PARSER);
79
80
81 if (parser.equals("")) {
82 log.warn("Property struts.multipart.parser not set." +
83 " Using org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest");
84 parser = "org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest";
85 }
86
87 else if (parser.equals("pell")) {
88 parser = "org.apache.struts2.dispatcher.multipart.PellMultiPartRequest";
89 } else if (parser.equals("cos")) {
90 parser = "org.apache.struts2.dispatcher.multipart.CosMultiPartRequest";
91 } else if (parser.equals("jakarta")) {
92 parser = "org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest";
93 }
94
95 try {
96 Class baseClazz = org.apache.struts2.dispatcher.multipart.MultiPartRequest.class;
97
98 Class clazz = ClassLoaderUtils.loadClass(parser, MultiPartRequestWrapper.class);
99
100
101 if (!baseClazz.isAssignableFrom(clazz)) {
102 addError("Class '" + parser + "' does not extend MultiPartRequest");
103
104 return;
105 }
106
107
108 Constructor ctor = clazz.getDeclaredConstructor(new Class[]{
109 ClassLoaderUtils.loadClass("javax.servlet.http.HttpServletRequest", MultiPartRequestWrapper.class),
110 java.lang.String.class, int.class
111 });
112
113
114 Object[] parms = new Object[]{
115 request, saveDir, new Integer(maxSize)
116 };
117
118
119 multi = (MultiPartRequest) ctor.newInstance(parms);
120 for (Iterator iter = multi.getErrors().iterator(); iter.hasNext();) {
121 String error = (String) iter.next();
122 addError(error);
123 }
124 } catch (ClassNotFoundException e) {
125 addError("Class: " + parser + " not found.");
126 } catch (NoSuchMethodException e) {
127 addError("Constructor error for " + parser + ": " + e);
128 } catch (InstantiationException e) {
129 addError("Error instantiating " + parser + ": " + e);
130 } catch (IllegalAccessException e) {
131 addError("Access errror for " + parser + ": " + e);
132 } catch (InvocationTargetException e) {
133
134 addError(e.getTargetException().toString());
135 }
136 }
137 }
138
139 /***
140 * Get an enumeration of the parameter names for uploaded files
141 *
142 * @return enumeration of parameter names for uploaded files
143 */
144 public Enumeration<String> getFileParameterNames() {
145 if (multi == null) {
146 return null;
147 }
148
149 return multi.getFileParameterNames();
150 }
151
152 /***
153 * Get an array of content encoding for the specified input field name or <tt>null</tt> if
154 * no content type was specified.
155 *
156 * @param name input field name
157 * @return an array of content encoding for the specified input field name
158 */
159 public String[] getContentTypes(String name) {
160 if (multi == null) {
161 return null;
162 }
163
164 return multi.getContentType(name);
165 }
166
167 /***
168 * Get a {@link java.io.File[]} for the given input field name.
169 *
170 * @param fieldName input field name
171 * @return a File[] object for files associated with the specified input field name
172 */
173 public File[] getFiles(String fieldName) {
174 if (multi == null) {
175 return null;
176 }
177
178 return multi.getFile(fieldName);
179 }
180
181 /***
182 * Get a String array of the file names for uploaded files
183 *
184 * @return a String[] of file names for uploaded files
185 */
186 public String[] getFileNames(String fieldName) {
187 if (multi == null) {
188 return null;
189 }
190
191 return multi.getFileNames(fieldName);
192 }
193
194 /***
195 * Get the filename(s) of the file(s) uploaded for the given input field name.
196 * Returns <tt>null</tt> if the file is not found.
197 *
198 * @param fieldName input field name
199 * @return the filename(s) of the file(s) uploaded for the given input field name or
200 * <tt>null</tt> if name not found.
201 */
202 public String[] getFileSystemNames(String fieldName) {
203 if (multi == null) {
204 return null;
205 }
206
207 return multi.getFilesystemName(fieldName);
208 }
209
210 /***
211 * @see javax.servlet.http.HttpServletRequest#getParameter(String)
212 */
213 public String getParameter(String name) {
214 return ((multi == null) || (multi.getParameter(name) == null)) ? super.getParameter(name) : multi.getParameter(name);
215 }
216
217 /***
218 * @see javax.servlet.http.HttpServletRequest#getParameterMap()
219 */
220 public Map getParameterMap() {
221 Map map = new HashMap();
222 Enumeration enumeration = getParameterNames();
223
224 while (enumeration.hasMoreElements()) {
225 String name = (String) enumeration.nextElement();
226 map.put(name, this.getParameterValues(name));
227 }
228
229 return map;
230 }
231
232 /***
233 * @see javax.servlet.http.HttpServletRequest#getParameterNames()
234 */
235 public Enumeration getParameterNames() {
236 if (multi == null) {
237 return super.getParameterNames();
238 } else {
239 return mergeParams(multi.getParameterNames(), super.getParameterNames());
240 }
241 }
242
243 /***
244 * @see javax.servlet.http.HttpServletRequest#getParameterValues(String)
245 */
246 public String[] getParameterValues(String name) {
247 return ((multi == null) || (multi.getParameterValues(name) == null)) ? super.getParameterValues(name) : multi.getParameterValues(name);
248 }
249
250 /***
251 * Returns <tt>true</tt> if any errors occured when parsing the HTTP multipart request, <tt>false</tt> otherwise.
252 *
253 * @return <tt>true</tt> if any errors occured when parsing the HTTP multipart request, <tt>false</tt> otherwise.
254 */
255 public boolean hasErrors() {
256 if ((errors == null) || errors.isEmpty()) {
257 return false;
258 } else {
259 return true;
260 }
261 }
262
263 /***
264 * Returns a collection of any errors generated when parsing the multipart request.
265 *
266 * @return the error Collection.
267 */
268 public Collection getErrors() {
269 return errors;
270 }
271
272 /***
273 * Adds an error message.
274 *
275 * @param anErrorMessage the error message to report.
276 */
277 protected void addError(String anErrorMessage) {
278 if (errors == null) {
279 errors = new ArrayList();
280 }
281
282 errors.add(anErrorMessage);
283 }
284
285 /***
286 * Merges 2 enumeration of parameters as one.
287 *
288 * @param params1 the first enumeration.
289 * @param params2 the second enumeration.
290 * @return a single Enumeration of all elements from both Enumerations.
291 */
292 protected Enumeration mergeParams(Enumeration params1, Enumeration params2) {
293 Vector temp = new Vector();
294
295 while (params1.hasMoreElements()) {
296 temp.add(params1.nextElement());
297 }
298
299 while (params2.hasMoreElements()) {
300 temp.add(params2.nextElement());
301 }
302
303 return temp.elements();
304 }
305 }