You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by ms...@locus.apache.org on 2000/11/09 21:44:19 UTC

cvs commit: jakarta-struts/src/share/org/apache/struts/util BeanUtils.java

mschachter    00/11/09 12:44:19

  Modified:    src/share/org/apache/struts/action ActionServlet.java
               src/share/org/apache/struts/util BeanUtils.java
  Log:
  - added set and get methods for various upload-related parameters in
  ActionServet
  - added initUpload() method for initializing upload-related parameters
  through web.xml, modified init() to call on initUpload()
  - modified processPopulate() to set the servlet of the form instance, and
  to pass some temporary contextual arguments to
  BeanUtils.populate() through the current request
  - modified BeanUtils.populate(bean,prefix,suffix,request) to check the
  content type of the request for multipart content, and parse
  accordingly.  for non-multipart requests, there are no changes to the
  method
  - modified BeanUtils.populate(bean,properties) to insure that there is no
  attempted conversion of objects of type FormFile when populating bean
  properties
  
  Multipart Requests should now be functional within struts, an example app
  demonstrating how to utilize this feature will be out soon, accompanied
  by documentation.
  
  Revision  Changes    Path
  1.33      +190 -5    jakarta-struts/src/share/org/apache/struts/action/ActionServlet.java
  
  Index: ActionServlet.java
  ===================================================================
  RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/action/ActionServlet.java,v
  retrieving revision 1.32
  retrieving revision 1.33
  diff -u -r1.32 -r1.33
  --- ActionServlet.java	2000/11/04 01:53:22	1.32
  +++ ActionServlet.java	2000/11/09 20:44:19	1.33
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/action/ActionServlet.java,v 1.32 2000/11/04 01:53:22 craigmcc Exp $
  - * $Revision: 1.32 $
  - * $Date: 2000/11/04 01:53:22 $
  + * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/action/ActionServlet.java,v 1.33 2000/11/09 20:44:19 mschachter Exp $
  + * $Revision: 1.33 $
  + * $Date: 2000/11/09 20:44:19 $
    *
    * ====================================================================
    *
  @@ -200,7 +200,7 @@
    * </ul>
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.32 $ $Date: 2000/11/04 01:53:22 $
  + * @version $Revision: 1.33 $ $Date: 2000/11/09 20:44:19 $
    */
   
   public class ActionServlet
  @@ -327,8 +327,37 @@
        * Are we using the new configuration file format?
        */
       protected boolean validate = false;
  +    
  +        /**
  +     * The size in bytes of the buffer used to read files from a client upload
  +     */
  +    protected int bufferSize = 4096;
  +    
  +    /**
  +     * The maximum size allowed for a client upload.  A suffix of "K"
  +     * represents Kilobytes, a suffix of "M" represents "Megabytes", 
  +     * a suffix of "G" represents Gigabytes, and no suffix is taken
  +     * as bytes.
  +     */
  +    protected String maxFileSize = "250M";
  +    
  +    /**
  +     * The MultipartRequestHandler class name used for handling
  +     * multipart form requests.  This is the global default value,
  +     * the handler can also be set in individual mapping entries
  +     */
  +    protected String multipartClass = "org.apache.struts.upload.DiskMultipartRequestHandler";
  +    
  +    /**
  +     * The directory used to store temporary files for the DiskMultipartRequestHandler
  +     * multipart implementation
  +     */
  +    protected String tempDir;
   
   
  +
  +
  +
       // ---------------------------------------------------- HttpServlet Methods
   
   
  @@ -366,6 +395,7 @@
   	    throw new UnavailableException
   		(internal.getMessage("configIO", config));
   	}
  +        initUpload();
   	initOther();
   
       }
  @@ -483,6 +513,18 @@
   	return (mappings.findMapping(path));
   
       }
  +    
  +    /** 
  +     * Get the buffer size (how large of a chunk of data is
  +     * recieved by the input stream at once) used for file
  +     * uploading.
  +     * 
  +     * @return The size in bytes of the buffer
  +     */
  +    public int getBufferSize() {
  +        return bufferSize;
  +    }
  +
   
   
       /**
  @@ -526,6 +568,25 @@
   	return (this.mappingClass);
   
       }
  +    
  +    
  +    /**
  +     * Get the maximum file size.  See {@link #setMaxFileSize(java.lang.String) setMaxFileSize}
  +     * for information on the number format used.
  +     */
  +    public String getMaxFileSize() {
  +        return maxFileSize;
  +    }
  +    
  +    /**
  +     * Get the class name of the MultipartRequestHandler implementation
  +     * 
  +     * @return A qualified classname of the MultipartRequestHandler implementation
  +     */
  +     public String getMultipartClass() {
  +        return multipartClass;
  +    }
  +
   
   
       /**
  @@ -536,6 +597,16 @@
   	return (application);
   
       }
  +    
  +    /**
  +     * Get the directory used to temporarily store form files
  +     *
  +     * @return A platform-dependant String representing the path to the temporary directory
  +     */
  +    public String getTempDir() {
  +        return tempDir;
  +    }
  +
   
   
       /**
  @@ -617,6 +688,18 @@
   
       }
   
  +    
  +    /** 
  +     * Set the buffer size (how large of a chunk of data is
  +     * recieved by the input stream at once) used for file
  +     * uploading.
  +     *
  +     * @param bufferSize The size in bytes of the buffer
  +     */
  +    public void setBufferSize(int bufferSize) {
  +        this.bufferSize = bufferSize;
  +    }
  +
   
       /**
        * Set the Java class name of the class used to instantiate
  @@ -655,6 +738,39 @@
           this.mappingClass = mappingClass;
   
       }
  +    
  +    /**
  +     * Set the maximum file size that a client can upload,  number String with a trailing
  +     * letter indicating the size.  "K" indicates "kilobytes", "M" indicates "megabytes",
  +     * "G" indicates "gigabytes".  If there's no trailing letter the suffix is assumed to
  +     * indicate the number is in bytes.  For example, to set a maximum file size of
  +     * 500 megabytes, you'd call <code>setMaxFileSize</code>("<i>500M</i>").
  +     *
  +     * @param maxFileSize A String representing the maximum file size.
  +     */
  +    public void setMaxFileSize(String maxFileSize) {
  +        this.maxFileSize = maxFileSize;
  +    }
  +    
  +    /**
  +     * Set the class name of the MultipartRequestHandler implementation
  +     *
  +     * @param multipartClass A qualified classname of the MultipartRequestHandler implementation
  +     */
  +    public void setMultipartClass(String multipartClass) {
  +        this.multipartClass = multipartClass;
  +    }
  +
  +    
  +    /**
  +     * Set the directory used to temporarily store files for MultipartRequestHandler
  +     * implementations that write to the disk
  +     *
  +     * @param tempDir A platform-dependant String representing the path to the temporary directory
  +     */
  +    public void setTempDir(String tempDir) {
  +        this.tempDir = tempDir;
  +    }
   
   
       // ------------------------------------------------------ Protected Methods
  @@ -1007,8 +1123,58 @@
   	getServletContext().setAttribute(Action.MAPPINGS_KEY, mappings);
   
       }
  +    
  +    
  +    /**
  +     * Initialize upload parameters and "bufferSize", "multipartClass",
  +     * "maxFileSize", "tempDir"
  +     *
  +     * @exception ServletException if there are invalid parameters
  +     */
  +    protected void initUpload() throws ServletException {
  +      
  +        //buffer size
  +        String bufferValue = getServletConfig().getInitParameter("bufferSize");
  +        
  +        if ((bufferValue != null) && (bufferValue.length() > 0)) {
  +            int oldBufferSize = bufferSize;
  +            try {
  +                bufferSize = Integer.parseInt(bufferValue, 10);
  +            }
  +            catch (NumberFormatException nfe) {
  +                if (debug > 0) {
  +                    log("initUpload(): invalid value \"" + bufferSize + "\" for " +
  +                        "init-parameter \"buffer size\"" +
  +                        ", defaulting to \"" + oldBufferSize + "\"");
  +                }
  +                bufferSize = oldBufferSize;
  +            }
  +        }
  +        
  +        //multipart class
  +        String classValue = getServletConfig().getInitParameter("multipartClass");
  +        
  +        if ((classValue != null) && (classValue.length() > 0)) {
  +            multipartClass = classValue;
  +        }
  +        
  +        //maximum file size
  +        String maxsizeValue = getServletConfig().getInitParameter("maxFileSize");
  +        
  +        if ((maxsizeValue != null) && (maxsizeValue.length() > 0)) {
  +            maxFileSize = maxsizeValue;
  +        }
  +        
  +        //temp directory
  +        String tempDirValue = getServletConfig().getInitParameter("tempDir");
  +        
  +        if ((tempDirValue != null) && (tempDirValue.length() > 0)) {
  +            tempDir = tempDirValue;
  +        }
  +    }
   
   
  +
       /**
        * Process an HTTP request.
        *
  @@ -1152,7 +1318,6 @@
               try {
                   Class clazz = Class.forName(className);
                   instance = (ActionForm) clazz.newInstance();
  -                instance.setServlet(this);
               } catch (Throwable t) {
                   log("Error creating ActionForm instance of class '" +
                       className + "'", t);
  @@ -1416,11 +1581,21 @@
   
           if (formInstance == null)
               return;
  +        //set the servlet of the ActionForm
  +        formInstance.setServlet(this);
   
           // Populate the bean properties of this ActionForm instance
           if (debug >= 1)
               log(" Populating bean properties from this request");
           formInstance.reset(mapping, request);
  +        //place the mapping's multipart request handler class
  +        //into the request to be read by the BeanUtils.populate
  +        //method in the event of a multipart request
  +        request.setAttribute("org.apache.struts.action.mapping.multipartclass", 
  +                                mapping.getMultipartClass());
  +        //also pass the mapping through the request
  +        request.setAttribute("org.apache.struts.action.mapping.instance",
  +                                mapping);
           BeanUtils.populate(formInstance, mapping.getPrefix(),
                              mapping.getSuffix(), request);
   
  @@ -1474,6 +1649,16 @@
               if (debug >= 1)
                   log("  No errors detected, accepting input");
               return (true);
  +        }
  +        
  +        //does our form have a multipart request?
  +        if (formInstance.getMultipartRequestHandler() != null) {
  +            //rollback the request
  +            if (debug > 1) {
  +                log("  Rolling back the multipart request");
  +            }
  +            
  +            formInstance.getMultipartRequestHandler().rollback();
           }
   
   	// Save our error messages and return to the input form if possible
  
  
  
  1.14      +122 -7    jakarta-struts/src/share/org/apache/struts/util/BeanUtils.java
  
  Index: BeanUtils.java
  ===================================================================
  RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/BeanUtils.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- BeanUtils.java	2000/09/23 23:19:33	1.13
  +++ BeanUtils.java	2000/11/09 20:44:19	1.14
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/BeanUtils.java,v 1.13 2000/09/23 23:19:33 craigmcc Exp $
  - * $Revision: 1.13 $
  - * $Date: 2000/09/23 23:19:33 $
  + * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/BeanUtils.java,v 1.14 2000/11/09 20:44:19 mschachter Exp $
  + * $Revision: 1.14 $
  + * $Date: 2000/11/09 20:44:19 $
    *
    * ====================================================================
    *
  @@ -77,14 +77,20 @@
   import javax.servlet.http.HttpServletRequest;
   import javax.servlet.jsp.PageContext;
   
  +import org.apache.struts.action.ActionForm;
  +import org.apache.struts.action.ActionServlet;
  +import org.apache.struts.action.ActionMapping;
  +import org.apache.struts.upload.FormFile;
  +import org.apache.struts.upload.MultipartRequestHandler;
   
  +
   /**
    * Utility methods for populating JavaBeans properties via reflection.
    *
    * @author Craig R. McClanahan
    * @author Ralph Schaer
    * @author Chris Audley
  - * @version $Revision: 1.13 $ $Date: 2000/09/23 23:19:33 $
  + * @version $Revision: 1.14 $ $Date: 2000/11/09 20:44:19 $
    */
   
   public final class BeanUtils {
  @@ -617,8 +623,109 @@
   	throws ServletException {
   
   	// Build a list of relevant request parameters from this request
  -	Hashtable properties = new Hashtable();
  -	Enumeration names = request.getParameterNames();
  +        Hashtable properties = new Hashtable();
  +        //Enumeration of parameter names
  +        Enumeration names = null;
  +        //Hashtable for multipart values
  +        Hashtable multipartElements = null;
  +        
  +        boolean isMultipart = false;
  +        
  +        if (request.getContentType().startsWith("multipart/form-data")) {
  +            isMultipart = true;
  +            //initialize a MultipartRequestHandler
  +            MultipartRequestHandler multipart = null;
  +            
  +            //get an instance of ActionServlet
  +            ActionServlet servlet;
  +            
  +            if (bean instanceof ActionForm) {
  +                
  +                servlet = ((ActionForm) bean).getServlet();
  +            }
  +            else {
  +                throw new ServletException("bean that's supposed to be " +
  +                    "populated from a multipart request is not of type " +
  +                    "\"org.apache.struts.action.ActionForm\", but type " +
  +                    "\"" + bean.getClass().getName() + "\"");
  +            }
  +            String multipartClass = (String)
  +                                request.getAttribute("org.apache.struts.action.mapping.multipartclass");
  +            
  +            request.removeAttribute("org.apache.struts.action.mapping.multipartclass");
  +            
  +            if (multipartClass != null) {
  +                //try to initialize the mapping specific request handler
  +                try {
  +                    multipart = (MultipartRequestHandler) Class.forName(multipartClass).newInstance();
  +                }
  +                catch (ClassNotFoundException cnfe) {
  +                    servlet.log("MultipartRequestHandler class \"" + 
  +                                 multipartClass + "\" in mapping class not found, " +
  +                                 "defaulting to global multipart class");
  +                }
  +                catch (InstantiationException ie) {
  +                    servlet.log("InstantiaionException when instantiating " +
  +                                "MultipartRequestHandler \"" + multipartClass + "\", " +
  +                                "defaulting to global multipart class, exception: " +
  +                                ie.getMessage());
  +                }
  +                catch (IllegalAccessException iae) {
  +                    servlet.log("IllegalAccessException when instantiating " +
  +                                "MultipartRequestHandler \"" + multipartClass + "\", " +
  +                                "defaulting to global multipart class, exception: " +
  +                                iae.getMessage());
  +                }
  +            }
  +            
  +            if (multipart == null) {
  +                //try to initialize the global multipart class
  +                try {
  +                    multipart = (MultipartRequestHandler) Class.forName(servlet.getMultipartClass()).newInstance();
  +                }
  +                catch (ClassNotFoundException cnfe) {
  +                    throw new ServletException("Cannot find multipart class \"" +
  +                                               servlet.getMultipartClass() + "\"" +
  +                                               ", exception: " + cnfe.getMessage());
  +                }
  +                catch (InstantiationException ie) {
  +                    throw new ServletException("InstantiaionException when instantiating " +
  +                                               "multipart class \"" + servlet.getMultipartClass() +
  +                                               "\", exception: " + ie.getMessage());
  +                }
  +                catch (IllegalAccessException iae) {
  +                    throw new ServletException("IllegalAccessException when instantiating " +
  +                                               "multipart class \"" + servlet.getMultipartClass() +
  +                                               "\", exception: " + iae.getMessage());
  +                }
  +            }
  +            
  +            
  +            //set the multipart request handler for our ActionForm
  +            //if the bean isn't an ActionForm, an exception would have been
  +            //thrown earlier, so it's safe to assume that our bean is
  +            //in fact an ActionForm
  +            ((ActionForm) bean).setMultipartRequestHandler(multipart);
  +            
  +            //set servlet and mapping info            
  +            multipart.setServlet(servlet);            
  +            multipart.setMapping((ActionMapping) 
  +                request.getAttribute("org.apache.struts.action.mapping.instance"));
  +            request.removeAttribute("org.apache.struts.action.mapping.instance");
  +            
  +            //initialize request class handler
  +            multipart.handleRequest(request);
  +            
  +            //retrive form values and put into properties
  +            multipartElements = multipart.getAllElements();
  +            names = multipartElements.keys();
  +        }
  +        
  +        if (!isMultipart) {        
  +            names = request.getParameterNames();
  +        }
  +        
  +        
   	while (names.hasMoreElements()) {
   	    String name = (String) names.nextElement();
   	    String stripped = name;
  @@ -636,7 +743,12 @@
   		stripped =
   		  stripped.substring(0, stripped.length() - suffix.length());
   	    }
  -	    properties.put(stripped, request.getParameterValues(name));
  +            if (isMultipart) {
  +                properties.put(stripped, multipartElements.get(name));
  +            }
  +            else {
  +                properties.put(stripped, request.getParameterValues(name));
  +            }
   	}
   
   	// Set the corresponding properties of our bean
  @@ -735,6 +847,9 @@
   		if (value instanceof String) {
   		    parameters[0] = convert((String) value,
   					    parameterTypes[0]);
  +                }
  +                else if (value instanceof FormFile) {
  +		      	parameters[0] = value;
   		} else {
   		    parameters[0] = convert( ((String[]) value)[0],
   					     parameterTypes[0]);
  
  
  

RE: cvs commit: jakarta-struts/src/share/org/apache/struts/util BeanUtils.java

Posted by Andrew Boyko <ab...@fabgear.com>.
Hi there.  I'm having a problem with the new multipart stuff
when populating an ActionForm from a GET (no body -> no content type).

This should fix it... there's nothing fundamentally illegitimate
about using GET method with ActionForms, is there?

Looking forward to replacing my terrible multipart form + Resin +
Struts hack code with this new stuff (now that Resin 1.2 allows you 
to disable its previously automatically enabled multipart handling)...

Andy Boyko   aboyko@fabgear.com


diff -c -r1.14 BeanUtils.java
*** BeanUtils.java      2000/11/09 20:44:19     1.14
--- BeanUtils.java      2000/11/10 20:34:15
***************
*** 631,637 ****

          boolean isMultipart = false;

!         if (request.getContentType().startsWith("multipart/form-data")) {
              isMultipart = true;
              //initialize a MultipartRequestHandler
              MultipartRequestHandler multipart = null;
--- 631,639 ----

          boolean isMultipart = false;

!         if (request.getContentType() != null &&
!             request.getContentType().startsWith("multipart/form-data")) {
!
              isMultipart = true;
              //initialize a MultipartRequestHandler
              MultipartRequestHandler multipart = null;