Commits

Anonymous committed 9b8632c

WW-610: MultiPartRequestWrapper should support multiple files with the same name (jakarta supports this, pell and cos do not)

git-svn-id: http://svn.opensymphony.com/svn/webwork/trunk@502573baa09-0c28-0410-bef9-dab3c582ae83

Comments (0)

Files changed (8)

lib/core/commons-fileupload.jar

Binary file added.

lib/core/libraries.txt

+commons-fileupload.jar - Apache Commons Fil Upload version 1.0
 commons-logging.jar - Apache Commons Logging version ???
 cos-multipart.jar - Cos Multipart File Upload version ???
 mail.jar - Mail API version ???

src/java/com/opensymphony/webwork/default.properties

 
 ### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data
 #webwork.multipart.parser=cos
+#webwork.multipart.parser=jakarta
 webwork.multipart.parser=pell
 # uses javax.servlet.context.tempdir by default
 webwork.multipart.saveDir=

src/java/com/opensymphony/webwork/dispatcher/multipart/CosMultiPartRequest.java

 
 import com.oreilly.servlet.MultipartRequest;
 
+import javax.servlet.http.HttpServletRequest;
 import java.io.File;
 import java.io.IOException;
-
 import java.util.Enumeration;
 
-import javax.servlet.http.HttpServletRequest;
-
 
 /**
  * Multipart form data request adapter for Jason Hunter's
      * Creates a new request wrapper to handle multi-part data using methods adapted from the COS
      * multipart classes (see class description).
      *
-     * @param maxSize maximum size post allowed
-     * @param saveDir the directory to save off the file
+     * @param maxSize        maximum size post allowed
+     * @param saveDir        the directory to save off the file
      * @param servletRequest the request containing the multipart
      */
     public CosMultiPartRequest(HttpServletRequest servletRequest, String saveDir, int maxSize) throws IOException {
 
     //~ Methods ////////////////////////////////////////////////////////////////
 
-    public String getContentType(String name) {
-        return multi.getContentType(name);
+    public Enumeration getFileParameterNames() {
+        return multi.getFileNames();
     }
 
-    public File getFile(String name) {
-        return multi.getFile(name);
+    public String[] getContentType(String fieldName) {
+        return new String[]{multi.getContentType(fieldName)};
     }
 
-    public Enumeration getFileNames() {
-        return multi.getFileNames();
+    public File[] getFile(String fieldName) {
+        return new File[]{multi.getFile(fieldName)};
+    }
+
+    public String[] getFileNames(String fieldName) {
+        return new String[]{multi.getFile(fieldName).getName()};
     }
 
-    public String getFilesystemName(String name) {
-        return multi.getFilesystemName(name);
+    public String[] getFilesystemName(String name) {
+        return new String[]{multi.getFilesystemName(name)};
     }
 
     public String getParameter(String name) {
     /**
      * Set the encoding for the uploaded parameters. This needs to be set if you are using character sets
      * other than ASCII.<p>
-     *
+     * <p/>
      * The encoding is looked up from the configuration setting 'webwork.i18n.encoding'.  This is usually set in
      * default.properties and webwork.properties.
      */

src/java/com/opensymphony/webwork/dispatcher/multipart/MultiPartRequest.java

 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import javax.servlet.http.HttpServletRequest;
 import java.io.File;
-
 import java.util.Enumeration;
 
-import javax.servlet.http.HttpServletRequest;
-
 
 /**
  * Abstract wrapper class HTTP requests to handle multi-part data. <p>
     }
 
     /**
-     * Returns the content type of the specified file (as supplied by the client browser), or
-     * <tt>null</tt> if the file was not included.
+     * Returns an enumeration of the parameter names for uploaded files
+     *
+     * @return an enumeration of the parameter names for uploaded files
+     */
+    public abstract Enumeration getFileParameterNames();
+
+    /**
+     * Returns the content type(s) of the file(s) associated with the specified field name
+     * (as supplied by the client browser), or <tt>null</tt> if no files are associated with the
+     * given field name.
      *
-     * @param name the name of the file to check
-     * @return the file's content type or <tt>null</tt> if no content type was specified.
+     * @param fieldName input field name
+     * @return an array of content encoding for the specified input field name or <tt>null</tt> if
+     *         no content type was specified.
      */
-    public abstract String getContentType(String name);
+    public abstract String[] getContentType(String fieldName);
 
     /**
-     * Returns a {@link java.io.File} object for the filename specified or <tt>null</tt> if the
-     * file was not found.
+     * Returns a {@link java.io.File} object for the filename specified or <tt>null</tt> if no files
+     * are associated with the given field name.
      *
-     * @param name the name of the file
-     * @return the File object associated with the given name or <tt>null</tt> if it doesn't exist.
+     * @param fieldName input field name
+     * @return a File[] object for files associated with the specified input field name
      */
-    public abstract File getFile(String name);
+    public abstract File[] getFile(String fieldName);
 
     /**
-     * Returns a String name list of all uploaded files.
+     * Returns a String[] of file names for files associated with the specified input field name
      *
-     * @return an enumeration of filenames (Strings).
+     * @param fieldName input field name
+     * @return a String[] of file names for files associated with the specified input field name
      */
-    public abstract Enumeration getFileNames();
+    public abstract String[] getFileNames(String fieldName);
 
     /**
-     * Returns the file system name of the given file name.
+     * Returns the file system name(s) of files associated with the given field name or
+     * <tt>null</tt> if no files are associated with the given field name.
      *
-     * @param name the name of the file uploaded.
-     * @return the file system name of the given file name.
+     * @param fieldName input field name
+     * @return the file system name(s) of files associated with the given field name
      */
-    public abstract String getFilesystemName(String name);
+    public abstract String[] getFilesystemName(String fieldName);
 
     /**
      * Returns the specified request parameter.

src/java/com/opensymphony/webwork/dispatcher/multipart/MultiPartRequestWrapper.java

 package com.opensymphony.webwork.dispatcher.multipart;
 
 import com.opensymphony.webwork.config.Configuration;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
 import java.io.File;
 import java.io.IOException;
-
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
-
 import java.util.*;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-
 
 /**
  * Parses a multipart request and provides a wrapper around the request. The parsing implementation used
  * depends on the <tt>webwork.multipart.parser</tt> setting. It should be set to a class which
  * extends {@link com.opensymphony.webwork.dispatcher.multipart.MultiPartRequest}. <p>
  * <p/>
- * Webwork ships with two implementations,
- * {@link com.opensymphony.webwork.dispatcher.multipart.PellMultiPartRequest} and
- * {@link com.opensymphony.webwork.dispatcher.multipart.CosMultiPartRequest}. The Pell implementation
+ * Webwork ships with three implementations,
+ * {@link com.opensymphony.webwork.dispatcher.multipart.PellMultiPartRequest}, and
+ * {@link com.opensymphony.webwork.dispatcher.multipart.CosMultiPartRequest} and
+ * {@link com.opensymphony.webwork.dispatcher.multipart.JakartaMultiPartRequest}. The Pell implementation
  * is the default. The <tt>webwork.multipart.parser</tt> property should be set to <tt>pell</tt> for
  * the Pell implementation and <tt>cos</tt> for the Jason Hunter implementation. <p>
  * <p/>
 
             // If it's not set, use Pell
             if (parser.equals("")) {
-                log.warn("Property webwork.multipart.parser not set." + " Using com.opensymphony.webwork.dispatcher.multipart.PellMultiPartRequest");
+                log.warn("Property webwork.multipart.parser not set." +
+                        " Using com.opensymphony.webwork.dispatcher.multipart.PellMultiPartRequest");
                 parser = "com.opensymphony.webwork.dispatcher.multipart.PellMultiPartRequest";
             }
-
             // legacy support for old style property values
-            if (parser.equals("pell")) {
+            else if (parser.equals("pell")) {
                 parser = "com.opensymphony.webwork.dispatcher.multipart.PellMultiPartRequest";
             } else if (parser.equals("cos")) {
                 parser = "com.opensymphony.webwork.dispatcher.multipart.CosMultiPartRequest";
+            } else if (parser.equals("jakarta")) {
+                parser = "com.opensymphony.webwork.dispatcher.multipart.JakartaMultiPartRequest";
             }
 
             try {
                 }
 
                 // get the constructor
-                Constructor ctor = clazz.getDeclaredConstructor(new Class[] {
-                        Class.forName("javax.servlet.http.HttpServletRequest"),
-                        java.lang.String.class, int.class
-                    });
+                Constructor ctor = clazz.getDeclaredConstructor(new Class[]{
+                    Class.forName("javax.servlet.http.HttpServletRequest"),
+                    java.lang.String.class, int.class
+                });
 
                 // build the parameter list
-                Object[] parms = new Object[] {
+                Object[] parms = new Object[]{
                     request, saveDir, new Integer(maxSize)
                 };
 
     //~ Methods ////////////////////////////////////////////////////////////////
 
     /**
-     * Get the content encoding type for the given file name. Name is the name field on the input tag.
+     * @deprecated use {@link #getFileParameterNames()} instead
+     */
+    public Enumeration getFileNames() {
+        return getFileParameterNames();
+    }
+
+    /**
+     * Get an enumeration of the parameter names for uploaded files
      *
-     * @param name uploaded filename.
-     * @return content encoding for file name
+     * @return enumeration of parameter names for uploaded files
      */
-    public String getContentType(String name) {
+    public Enumeration getFileParameterNames() {
         if (multi == null) {
             return null;
         }
 
-        return multi.getContentType(name);
+        return multi.getFileParameterNames();
     }
 
     /**
-     * Returns a collection of any errors generated when parsing the multipart request.
+     * @deprecated use {@link #getContentTypes(String)} instead
+     */
+    public String getContentType(String fieldName) {
+        String[] contentTypes = getContentTypes(fieldName);
+        if (contentTypes != null && contentTypes.length > 0) {
+            return contentTypes[0];
+        }
+
+        return null;
+    }
+
+
+    /**
+     * Get an array of content encoding for the specified input field name or <tt>null</tt> if
+     * no content type was specified.
      *
-     * @return the error Collection.
+     * @param name input field name
+     * @return an array of content encoding for the specified input field name
      */
-    public Collection getErrors() {
-        return errors;
+    public String[] getContentTypes(String name) {
+        if (multi == null) {
+            return null;
+        }
+
+        return multi.getContentType(name);
     }
 
     /**
-     * Get a {@link java.io.File} for the give file name. Name is the name field on the input tag.
+     * @deprecated use {@link #getFiles(String)} instead
+     */
+    public File getFile(String fieldName) {
+        File[] files = getFiles(fieldName);
+        if (files != null && files.length > 0) {
+            return files[0];
+        }
+
+        return null;
+    }
+
+    /**
+     * Get a {@link java.io.File[]} for the given input field name.
      *
-     * @param name uploaded filename
-     * @return File object for file name
+     * @param fieldName input field name
+     * @return a File[] object for files associated with the specified input field name
      */
-    public File getFile(String name) {
+    public File[] getFiles(String fieldName) {
         if (multi == null) {
             return null;
         }
 
-        return multi.getFile(name);
+        return multi.getFile(fieldName);
     }
 
     /**
-     * Get an enumeration of the filenames uploaded
+     * Get a String array of the file names for uploaded files
      *
-     * @return enumeration of filenames
+     * @return a String[] of file names for uploaded files
      */
-    public Enumeration getFileNames() {
+    public String[] getFileNames(String fieldName) {
         if (multi == null) {
             return null;
         }
 
-        return multi.getFileNames();
+        return multi.getFileNames(fieldName);
+    }
+
+    /**
+     * @deprecated use {@link #getFileSystemNames(String)} instead
+     */
+    public String getFilesystemName(String fieldName) {
+        String[] names = getFileSystemNames(fieldName);
+        if (names != null && names.length > 0) {
+            return names[0];
+        }
+
+        return null;
     }
 
     /**
-     * Get the filename of the file uploaded for the given input field name. Returns <tt>null</tt> if the
-     * file is not found.
+     * Get the filename(s) of the file(s) uploaded for the given input field name.
+     * Returns <tt>null</tt> if the file is not found.
      *
-     * @param name uploaded filename
-     * @return the file system name of the given file or <tt>null</tt> if name not found.
+     * @param fieldName input field name
+     * @return the filename(s) of the file(s) uploaded for the given input field name or
+     *         <tt>null</tt> if name not found.
      */
-    public String getFilesystemName(String name) {
+    public String[] getFileSystemNames(String fieldName) {
         if (multi == null) {
             return null;
         }
 
-        return multi.getFilesystemName(name);
+        return multi.getFilesystemName(fieldName);
     }
 
     /**
     }
 
     /**
+     * Returns a collection of any errors generated when parsing the multipart request.
+     *
+     * @return the error Collection.
+     */
+    public Collection getErrors() {
+        return errors;
+    }
+
+    /**
      * Adds an error message.
      *
      * @param anErrorMessage the error message to report.

src/java/com/opensymphony/webwork/dispatcher/multipart/PellMultiPartRequest.java

 package com.opensymphony.webwork.dispatcher.multipart;
 
 import com.opensymphony.webwork.config.Configuration;
-
 import http.utils.multipartrequest.ServletMultipartRequest;
 
+import javax.servlet.http.HttpServletRequest;
 import java.io.File;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
-
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
 
-import javax.servlet.http.HttpServletRequest;
-
 
 /**
  * Multipart form data request adapter for Jason Pell's multipart utils package.
 
     //~ Methods ////////////////////////////////////////////////////////////////
 
-    public String getContentType(String name) {
-        return multi.getContentType(name);
+    public Enumeration getFileParameterNames() {
+        return multi.getFileParameterNames();
     }
 
-    public File getFile(String name) {
-        return multi.getFile(name);
+    public String[] getContentType(String fieldName) {
+        return new String[]{multi.getContentType(fieldName)};
     }
 
-    public Enumeration getFileNames() {
-        return multi.getFileParameterNames();
+    public File[] getFile(String fieldName) {
+        return new File[]{multi.getFile(fieldName)};
+    }
+
+    public String[] getFileNames(String fieldName) {
+
+        // TODO - not sure about this - is this the filename of the actual file or
+        // TODO - the uploaded filename as provided by the browser?
+        // TODO - Not sure what version of Pell this class uses as it doesn't seem to be the latest
+        return new String[]{multi.getFile(fieldName).getName()};
     }
 
-    public String getFilesystemName(String name) {
-        return multi.getFileSystemName(name);
+    public String[] getFilesystemName(String fieldName) {
+        return new String[]{multi.getFileSystemName(fieldName)};
     }
 
     public String getParameter(String name) {

src/java/com/opensymphony/webwork/interceptor/FileUploadInterceptor.java

 
 import com.opensymphony.webwork.ServletActionContext;
 import com.opensymphony.webwork.dispatcher.multipart.MultiPartRequestWrapper;
-
 import com.opensymphony.xwork.Action;
 import com.opensymphony.xwork.ActionInvocation;
 import com.opensymphony.xwork.ValidationAware;
 import com.opensymphony.xwork.interceptor.Interceptor;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import java.io.File;
-
 import java.util.Collection;
 import java.util.Enumeration;
 import java.util.Iterator;
             }
         }
 
-        Enumeration e = multiWrapper.getFileNames();
+        Enumeration e = multiWrapper.getFileParameterNames();
 
         // Bind allowed Files
         while (e.hasMoreElements()) {
             String inputName = (String) e.nextElement();
 
             // get the content type
-            String contentType = multiWrapper.getContentType(inputName);
+            String[] contentType = multiWrapper.getContentTypes(inputName);
 
             // get the name of the file from the input tag
-            String fileName = multiWrapper.getFilesystemName(inputName);
+            String[] fileName = multiWrapper.getFileNames(inputName);
 
             // Get a File object for the uploaded File
-            File file = multiWrapper.getFile(inputName);
+            File[] file = multiWrapper.getFiles(inputName);
 
-            log.info("file " + inputName + " " + contentType + " " + fileName + " " + file);
+            if (file != null) {
+                for (int i = 0; i < file.length; i++) {
+                    log.info("file " + inputName + " " + contentType[i] + " " + fileName[i] + " " + file[i]);
+                }
+            }
 
             // If it's null the upload failed
             if (file == null) {
                 if (validation != null) {
-                    validation.addFieldError(inputName, "Could not upload file. Perhaps it is too large?");
+                    validation.addFieldError(inputName, "Could not upload file(s). Perhaps it is too large?");
                 }
 
                 log.error("Error uploading: " + fileName);
         String result = invocation.invoke();
 
         // cleanup
-        e = multiWrapper.getFileNames();
+        e = multiWrapper.getFileParameterNames();
 
         while (e.hasMoreElements()) {
             String inputValue = (String) e.nextElement();
-            File file = multiWrapper.getFile(inputValue);
-            log.info("removing file " + inputValue + " " + file);
+            File[] file = multiWrapper.getFiles(inputValue);
+            for (int i = 0; i < file.length; i++) {
+                File f = file[i];
+                log.info("removing file " + inputValue + " " + f);
 
-            if ((file != null) && file.isFile()) {
-                file.delete();
+                if ((f != null) && f.isFile()) {
+                    f.delete();
+                }
             }
         }