Author: germuska Date: Mon Apr 2 12:29:21 2007 New Revision: 524895 URL: http://svn.apache.org/viewvc?view=rev&rev=524895 Log: STR-487 - support upload of multiple files with a single HTTP parameter name. The ActionForm class receiving multiple files must use java.util.List for the property type.
Modified: struts/struts1/branches/STRUTS_1_3_BRANCH/core/src/main/java/org/apache/struts/upload/CommonsMultipartRequestHandler.java struts/struts1/branches/STRUTS_1_3_BRANCH/core/src/main/java/org/apache/struts/util/RequestUtils.java Modified: struts/struts1/branches/STRUTS_1_3_BRANCH/core/src/main/java/org/apache/struts/upload/CommonsMultipartRequestHandler.java URL: http://svn.apache.org/viewvc/struts/struts1/branches/STRUTS_1_3_BRANCH/core/src/main/java/org/apache/struts/upload/CommonsMultipartRequestHandler.java?view=diff&rev=524895&r1=524894&r2=524895 ============================================================================== --- struts/struts1/branches/STRUTS_1_3_BRANCH/core/src/main/java/org/apache/struts/upload/CommonsMultipartRequestHandler.java (original) +++ struts/struts1/branches/STRUTS_1_3_BRANCH/core/src/main/java/org/apache/struts/upload/CommonsMultipartRequestHandler.java Mon Apr 2 12:29:21 2007 @@ -41,6 +41,7 @@ import java.io.InputStream; import java.io.Serializable; +import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.List; @@ -244,10 +245,16 @@ public void rollback() { Iterator iter = elementsFile.values().iterator(); + Object o; while (iter.hasNext()) { - FormFile formFile = (FormFile) iter.next(); - - formFile.destroy(); + o = iter.next(); + if (o instanceof List) { + for (Iterator i = ((List)o).iterator(); i.hasNext(); ) { + ((FormFile)i.next()).destroy(); + } + } else { + ((FormFile)o).destroy(); + } } } @@ -448,8 +455,22 @@ protected void addFileParameter(FileItem item) { FormFile formFile = new CommonsFormFile(item); - elementsFile.put(item.getFieldName(), formFile); - elementsAll.put(item.getFieldName(), formFile); + String name = item.getFieldName(); + if (elementsFile.containsKey(name)) { + Object o = elementsFile.get(name); + if (o instanceof List) { + ((List)o).add(formFile); + } else { + List list = new ArrayList(); + list.add((FormFile)o); + list.add(formFile); + elementsFile.put(name, list); + elementsAll.put(name, list); + } + } else { + elementsFile.put(name, formFile); + elementsAll.put(name, formFile); + } } // ---------------------------------------------------------- Inner Classes Modified: struts/struts1/branches/STRUTS_1_3_BRANCH/core/src/main/java/org/apache/struts/util/RequestUtils.java URL: http://svn.apache.org/viewvc/struts/struts1/branches/STRUTS_1_3_BRANCH/core/src/main/java/org/apache/struts/util/RequestUtils.java?view=diff&rev=524895&r1=524894&r2=524895 ============================================================================== --- struts/struts1/branches/STRUTS_1_3_BRANCH/core/src/main/java/org/apache/struts/util/RequestUtils.java (original) +++ struts/struts1/branches/STRUTS_1_3_BRANCH/core/src/main/java/org/apache/struts/util/RequestUtils.java Mon Apr 2 12:29:21 2007 @@ -21,6 +21,7 @@ package org.apache.struts.util; import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.Globals; @@ -32,6 +33,7 @@ import org.apache.struts.config.FormBeanConfig; import org.apache.struts.config.ForwardConfig; import org.apache.struts.config.ModuleConfig; +import org.apache.struts.upload.FormFile; import org.apache.struts.upload.MultipartRequestHandler; import org.apache.struts.upload.MultipartRequestWrapper; @@ -40,13 +42,16 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; +import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; +import java.util.List; import java.util.Locale; import java.util.Map; @@ -451,6 +456,7 @@ if (isMultipart) { parameterValue = multipartParameters.get(name); + parameterValue = rationalizeMultipleFileProperty(bean, name, parameterValue); } else { parameterValue = request.getParameterValues(name); } @@ -479,6 +485,46 @@ } /** + * <p>If the given form bean can accept multiple FormFile objects but the user only uploaded a single, then + * the property will not match the form bean type. This method performs some simple checks to try to accommodate + * that situation.</p> + * @param bean + * @param name + * @param parameterValue + * @return + * @throws ServletException if the introspection has any errors. + */ + private static Object rationalizeMultipleFileProperty(Object bean, String name, Object parameterValue) throws ServletException { + if (!(parameterValue instanceof FormFile)) return parameterValue; + + FormFile formFileValue = (FormFile) parameterValue; + try { + Class propertyType = PropertyUtils.getPropertyType(bean, name); + + if (propertyType.isAssignableFrom(List.class)) { + ArrayList list = new ArrayList(1); + list.add(formFileValue); + return list; + } + + if (propertyType.isArray() && propertyType.getComponentType().equals(FormFile.class)) { + return new FormFile[] { formFileValue }; + } + + } catch (IllegalAccessException e) { + throw new ServletException(e); + } catch (InvocationTargetException e) { + throw new ServletException(e); + } catch (NoSuchMethodException e) { + throw new ServletException(e); + } + + // no changes + return parameterValue; + + } + + /** * <p>Try to locate a multipart request handler for this request. First, * look for a mapping-specific handler stored for us under an attribute. * If one is not present, use the global multipart handler, if there is