You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2009/06/08 05:28:43 UTC

svn commit: r782515 - in /myfaces/tomahawk/trunk: core/src/main/java/org/apache/myfaces/component/html/util/ core/src/main/java/org/apache/myfaces/custom/fileupload/ core/src/main/java/org/apache/myfaces/webapp/filter/ core/src/main/java/org/apache/myf...

Author: lu4242
Date: Mon Jun  8 03:28:42 2009
New Revision: 782515

URL: http://svn.apache.org/viewvc?rev=782515&view=rev
Log:
TOMAHAWK-1420 uploadThresholdSize seems to be ignored and TOMAHAWK-1381 HtmlInputFileUpload does not fail gracefully when filesize exceeds uploadMaxFileSize web.xml value (duplicated issue TOMAHAWK-1305 No error when file is uploaded larger than uploadMaxFileSize) (Thanks to Phillip Webb for help with ServletCacheFileSizeErrorsFileUpload code)

Added:
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/portlet/PortletChacheFileSizeErrorsFileUpload.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/servlet/ServletChacheFileSizeErrorsFileUpload.java
    myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/custom/fileupload/
    myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/custom/fileupload/AbstractHtmlInputFileUpload.java   (with props)
Modified:
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/component/html/util/MultipartFilter.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/fileupload/AbstractHtmlInputFileUpload.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/fileupload/HtmlFileUploadRenderer.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/ExtensionsFilter.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/MultipartRequestWrapper.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/MultipartRequestWrapperConfig.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/PortletMultipartRequestWrapper.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/TomahawkFacesContextWrapper.java

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/component/html/util/MultipartFilter.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/component/html/util/MultipartFilter.java?rev=782515&r1=782514&r2=782515&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/component/html/util/MultipartFilter.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/component/html/util/MultipartFilter.java Mon Jun  8 03:28:42 2009
@@ -29,7 +29,7 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.commons.fileupload.FileUpload;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
 import org.apache.myfaces.webapp.filter.MultipartRequestWrapper;
 
 
@@ -45,18 +45,32 @@
 public class MultipartFilter implements Filter
 {
 
+    private int uploadMaxSize = 100 * 1024 * 1024; // 100 MB
+    
     private int uploadMaxFileSize = 100 * 1024 * 1024; // 10 MB
 
     private int uploadThresholdSize = 1 * 1024 * 1024; // 1 MB
 
     private String uploadRepositoryPath = null; //standard temp directory
-
+    
+    private boolean cacheFileSizeErrors = false;
 
     public void init(FilterConfig filterConfig)
     {
         uploadMaxFileSize = resolveSize(filterConfig.getInitParameter("uploadMaxFileSize"), uploadMaxFileSize);
+        String param = filterConfig.getInitParameter("uploadMaxSize");
+        if (param != null)
+        {
+            uploadMaxSize = resolveSize(param, uploadMaxSize);
+        }
+        else
+        {
+            //If not set, default to uploadMaxFileSize
+            uploadMaxSize = resolveSize(param, uploadMaxFileSize);
+        }
         uploadThresholdSize = resolveSize(filterConfig.getInitParameter("uploadThresholdSize"), uploadThresholdSize);
         uploadRepositoryPath = filterConfig.getInitParameter("uploadRepositoryPath");
+        cacheFileSizeErrors = getBooleanValue(filterConfig.getInitParameter("cacheFileSizeErrors"), false);
     }
 
 
@@ -88,7 +102,14 @@
         }
         return numberParam;
     }
+    
+    private static boolean getBooleanValue(String initParameter, boolean defaultVal)
+    {
+        if(initParameter == null || initParameter.trim().length()==0)
+            return defaultVal;
 
+        return (initParameter.equalsIgnoreCase("on") || initParameter.equals("1") || initParameter.equalsIgnoreCase("true"));
+    }
 
     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
     {
@@ -101,9 +122,10 @@
         HttpServletRequest httpRequest = (HttpServletRequest) request;
 
         // For multipart/form-data requests
-        if (FileUpload.isMultipartContent(httpRequest))
+        if (ServletFileUpload.isMultipartContent(httpRequest))
         {
-            chain.doFilter(new MultipartRequestWrapper(httpRequest, uploadMaxFileSize, uploadThresholdSize, uploadRepositoryPath), response);
+            chain.doFilter(new MultipartRequestWrapper(httpRequest, uploadMaxFileSize, 
+                    uploadThresholdSize, uploadRepositoryPath, uploadMaxSize , cacheFileSizeErrors), response);
         } else
         {
             chain.doFilter(request, response);

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/fileupload/AbstractHtmlInputFileUpload.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/fileupload/AbstractHtmlInputFileUpload.java?rev=782515&r1=782514&r2=782515&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/fileupload/AbstractHtmlInputFileUpload.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/fileupload/AbstractHtmlInputFileUpload.java Mon Jun  8 03:28:42 2009
@@ -60,6 +60,7 @@
         implements UserRoleAware, AlignProperty
 {
     private static final String SIZE_LIMIT_EXCEEDED = "sizeLimitExceeded";
+    private static final String FILE_SIZE_LIMIT_EXCEEDED = "fileSizeLimitExceeded";
     private static final String FILEUPLOAD_MAX_SIZE = "org.apache.myfaces.custom.fileupload.maxSize";
     private static final String FILEUPLOAD_EXCEPTION = "org.apache.myfaces.custom.fileupload.exception";
     public static final String COMPONENT_TYPE = "org.apache.myfaces.HtmlInputFileUpload";
@@ -84,10 +85,17 @@
     /**
      * This setting was intended to allow control over how the contents of the
      * file get temporarily stored during processing.
-     * <p>
-     * However it appears that this is only half-implemented, and not at all
-     * documented. It is therefore recommended that this not be used.
-     * </p>
+     * <p> It allows three options<p>
+     * <ul>
+     * <li>"default": The file is handled on memory while the file size is below 
+     * uploadThresholdSize value, otherwise is handled on disk or file storage when
+     * decode occur (set submitted value)</li>
+     * <li>"memory": The file is loaded to memory when decode occur 
+     * (set submitted value). In other words, before set the uploaded file as 
+     * submitted value it is loaded to memory. Use with caution, because it
+     * could cause OutOfMemory exceptions when the uploaded files are too big. </li>
+     * <li>"file": The file is handled on disk or file storage.</li>
+     * </ul>
      * 
      * @JSFProperty
      */
@@ -127,8 +135,10 @@
               String exception =
                 (String) context.getExternalContext().getRequestMap().get(FILEUPLOAD_EXCEPTION);
               
-              if(exception != null ) {
-                if(exception.equals(SIZE_LIMIT_EXCEEDED)) {
+              if(exception != null )
+              {
+                if(exception.equals(SIZE_LIMIT_EXCEEDED))
+                {
                   Integer maxSize =
                     (Integer) context.getExternalContext().getRequestMap().get(FILEUPLOAD_MAX_SIZE);
                   MessageUtils.addMessage(FacesMessage.SEVERITY_ERROR,
@@ -136,7 +146,38 @@
                                       maxSize},
                               getClientId(context), context);
                   setValid(false);
-                }else {
+                }
+                else if (FILE_SIZE_LIMIT_EXCEEDED.equals(exception))
+                {
+                    Integer maxSize =
+                        (Integer) context.getExternalContext().getRequestMap().get(FILEUPLOAD_MAX_SIZE);
+                    if (maxSize != null)
+                    {
+                        MessageUtils.addMessage(FacesMessage.SEVERITY_ERROR,
+                                SIZE_LIMIT_MESSAGE_ID, new Object[] { getId(),
+                                        maxSize},
+                                getClientId(context), context);
+                    }
+                    else
+                    {
+                        maxSize = (Integer) context.getExternalContext().getRequestMap().get(
+                                "org.apache.myfaces.custom.fileupload."+this.getClientId(context)+".maxSize");
+                        if (maxSize != null)
+                        {
+                            MessageUtils.addMessage(FacesMessage.SEVERITY_ERROR,
+                                    SIZE_LIMIT_MESSAGE_ID, new Object[] { getId(),
+                                            maxSize},
+                                    getClientId(context), context);
+                        }
+                        //else
+                        //{
+                            //Ignore because this exception belongs to other component
+                        //}
+                    }
+                    setValid(false);
+                }
+                else 
+                {
                   throw new IllegalStateException("other exceptions not handled yet, exception : "+exception);
                 }
              }

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/fileupload/HtmlFileUploadRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/fileupload/HtmlFileUploadRenderer.java?rev=782515&r1=782514&r2=782515&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/fileupload/HtmlFileUploadRenderer.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/fileupload/HtmlFileUploadRenderer.java Mon Jun  8 03:28:42 2009
@@ -107,6 +107,49 @@
         }
     }
 
+    private void setSubmittedValueForImplementation(
+        FacesContext facesContext, UIComponent uiComponent, FileItem fileItem)
+    {
+        try
+        {
+            UploadedFile upFile;
+            String implementation =
+                ((HtmlInputFileUpload)uiComponent).getStorage();
+            if (implementation == null || implementation.length() == 0)
+            {
+                implementation = "default";
+            }
+            if (("memory").equals(implementation))
+            {
+                upFile = new UploadedFileDefaultMemoryImpl(fileItem);
+            }
+            else if (("default").equals(implementation))
+            {
+                if (fileItem.isInMemory())
+                {
+                    upFile = new UploadedFileDefaultMemoryImpl(fileItem);
+                }
+                else
+                {
+                    upFile = new UploadedFileDefaultFileImpl(fileItem);                    
+                }
+            }
+            else //"file" case
+            {
+                upFile = new UploadedFileDefaultFileImpl(fileItem);
+            }
+
+            ((HtmlInputFileUpload)uiComponent).setSubmittedValue(upFile);
+            ((HtmlInputFileUpload)uiComponent).setValid(true);
+        }
+        catch (IOException ioe)
+        {
+            throw new FacesException(
+                "Exception while processing file upload for file-input : "
+                    + uiComponent.getClientId(facesContext), ioe);
+        }
+    }
+
     /**
      * Handle the postback of a form containing a fileUpload component.
      * <p>
@@ -136,18 +179,7 @@
             }
             if (fileItem != null)
             {
-                try{
-                    UploadedFile upFile;
-                    String implementation = ((HtmlInputFileUpload) uiComponent).getStorage();
-                    if( implementation == null || ("memory").equals( implementation ) )
-                        upFile = new UploadedFileDefaultMemoryImpl( fileItem );
-                    else
-                        upFile = new UploadedFileDefaultFileImpl( fileItem );
-                    ((HtmlInputFileUpload)uiComponent).setSubmittedValue(upFile);
-                    ((HtmlInputFileUpload)uiComponent).setValid(true);
-                }catch(IOException ioe){
-                    throw new FacesException("Exception while processing file upload for file-input : " + uiComponent.getClientId(facesContext),ioe);
-                }
+                setSubmittedValueForImplementation(facesContext, uiComponent, fileItem);
             }
             return;
         }
@@ -175,18 +207,7 @@
                 FileItem fileItem = mpReq.getFileItem(paramName);
                 if (fileItem != null)
                 {
-                    try{
-                        UploadedFile upFile;
-                        String implementation = ((HtmlInputFileUpload) uiComponent).getStorage();
-                        if( implementation == null || ("memory").equals( implementation ) )
-                            upFile = new UploadedFileDefaultMemoryImpl( fileItem );
-                        else
-                            upFile = new UploadedFileDefaultFileImpl( fileItem );
-                        ((HtmlInputFileUpload)uiComponent).setSubmittedValue(upFile);
-                        ((HtmlInputFileUpload)uiComponent).setValid(true);
-                    }catch(IOException ioe){
-                      throw new FacesException("Exception while processing file upload for file-input : " + uiComponent.getClientId(facesContext),ioe);
-                    }
+                    setSubmittedValueForImplementation(facesContext, uiComponent, fileItem);
                 }
             }
         }

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/ExtensionsFilter.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/ExtensionsFilter.java?rev=782515&r1=782514&r2=782515&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/ExtensionsFilter.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/ExtensionsFilter.java Mon Jun  8 03:28:42 2009
@@ -30,7 +30,7 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.commons.fileupload.FileUpload;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.renderkit.html.util.AddResource;
@@ -142,12 +142,16 @@
 public class ExtensionsFilter implements Filter {
 
     private Log log = LogFactory.getLog(ExtensionsFilter.class);
+    
+    private int _uploadMaxSize = 100 * 1024 * 1024; // 100 MB
 
     private int _uploadMaxFileSize = 100 * 1024 * 1024; // 100 MB
 
     private int _uploadThresholdSize = 1 * 1024 * 1024; // 1 MB
 
     private String _uploadRepositoryPath = null; //standard temp directory
+    
+    private boolean _cacheFileSizeErrors = false; 
 
     private ServletContext _servletContext;
 
@@ -162,6 +166,8 @@
      * <li>uploadMaxFileSize</li>
      * <li>uploadThresholdSize</li>
      * <li>uploadRepositoryPath</li>
+     * <li>uploadMaxSize</li>
+     * <li>cacheFileSizeErrors</li>
      * </ul>
      * </p>
      * <p>
@@ -191,6 +197,17 @@
      * 
      * Sets the directory in which temporary files (ie caches for those uploaded files that
      * are larger than uploadThresholdSize) are to be stored.
+     * 
+     * <h2>uploadMaxSize</h2>
+     * 
+     * Sets the maximum allowable size for the current request. If not set, its value is the 
+     * value set on uploadMaxFileSize param. 
+     * 
+     * <h2>cacheFileSizeErrors</h2>
+     * 
+     * Catch and swallow FileSizeLimitExceededExceptions in order to return as
+     * many usable items as possible.
+     * 
      */
     public void init(FilterConfig filterConfig) {
         // Note that the code here to extract FileUpload configuration params is not actually used.
@@ -206,11 +223,25 @@
 
         _uploadMaxFileSize = resolveSize(param, _uploadMaxFileSize);
 
+        param = filterConfig.getInitParameter("uploadMaxSize");
+
+        if (param != null)
+        {
+            _uploadMaxSize = resolveSize(param, _uploadMaxSize);
+        }
+        else
+        {
+            //If not set, default to uploadMaxFileSize
+            _uploadMaxSize = resolveSize(param, _uploadMaxFileSize);
+        }
+        
         param = filterConfig.getInitParameter("uploadThresholdSize");
 
         _uploadThresholdSize = resolveSize(param, _uploadThresholdSize);
 
         _uploadRepositoryPath = filterConfig.getInitParameter("uploadRepositoryPath");
+        
+        _cacheFileSizeErrors = getBooleanValue(filterConfig.getInitParameter("cacheFileSizeErrors"), false);
 
         _servletContext = filterConfig.getServletContext();
     }
@@ -238,6 +269,14 @@
         }
         return numberParam;
     }
+    
+    private static boolean getBooleanValue(String initParameter, boolean defaultVal)
+    {
+        if(initParameter == null || initParameter.trim().length()==0)
+            return defaultVal;
+
+        return (initParameter.equalsIgnoreCase("on") || initParameter.equals("1") || initParameter.equalsIgnoreCase("true"));
+    }
 
     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
 
@@ -279,8 +318,9 @@
 
         // For multipart/form-data requests
         // This is done by TomahawkFacesContextWrapper
-        if (FileUpload.isMultipartContent(httpRequest)) {
-            extendedRequest = new MultipartRequestWrapper(httpRequest, _uploadMaxFileSize, _uploadThresholdSize, _uploadRepositoryPath);
+        if (ServletFileUpload.isMultipartContent(httpRequest)) {
+            extendedRequest = new MultipartRequestWrapper(httpRequest, _uploadMaxFileSize, 
+                    _uploadThresholdSize, _uploadRepositoryPath, _uploadMaxSize, _cacheFileSizeErrors);
         }
         
         try

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/MultipartRequestWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/MultipartRequestWrapper.java?rev=782515&r1=782514&r2=782515&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/MultipartRequestWrapper.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/MultipartRequestWrapper.java Mon Jun  8 03:28:42 2009
@@ -18,6 +18,7 @@
  */
 package org.apache.myfaces.webapp.filter;
 
+import java.io.File;
 import java.io.UnsupportedEncodingException;
 import java.util.Collections;
 import java.util.Enumeration;
@@ -29,13 +30,14 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
 
-import org.apache.commons.fileupload.DefaultFileItemFactory;
-import org.apache.commons.fileupload.DiskFileUpload;
 import org.apache.commons.fileupload.FileItem;
 import org.apache.commons.fileupload.FileUploadBase;
 import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.webapp.filter.servlet.ServletChacheFileSizeErrorsFileUpload;
 
 /**
  * @since 1.1.7
@@ -51,52 +53,132 @@
 
     HttpServletRequest request = null;
     HashMap parametersMap = null;
-    DiskFileUpload fileUpload = null;
+    ServletFileUpload fileUpload = null;
     HashMap fileItems = null;
+    int maxFileSize;
     int maxSize;
     int thresholdSize;
     String repositoryPath;
+    boolean cacheFileSizeErrors;
 
     public MultipartRequestWrapper(HttpServletRequest request,
-                                   int maxSize, int thresholdSize,
+                                   int maxFileSize, int thresholdSize,
                                    String repositoryPath){
         super( request );
         this.request = request;
-        this.maxSize = maxSize;
+        this.maxFileSize = maxFileSize;
         this.thresholdSize = thresholdSize;
         this.repositoryPath = repositoryPath;
+        //Default values
+        this.maxSize = maxFileSize;
+        this.cacheFileSizeErrors = false;
+    }
+    
+    public MultipartRequestWrapper(HttpServletRequest request,
+            int maxFileSize, int thresholdSize,
+            String repositoryPath, int maxRequestSize, boolean cacheFileSizeErrors){
+        super( request );
+        this.request = request;
+        this.maxFileSize = maxFileSize;
+        this.maxSize = maxRequestSize;
+        this.thresholdSize = thresholdSize;
+        this.repositoryPath = repositoryPath;
+        this.cacheFileSizeErrors = cacheFileSizeErrors;
     }
 
     private void parseRequest() {
-        fileUpload = new DiskFileUpload();
-        fileUpload.setFileItemFactory(new DefaultFileItemFactory());
+        if (cacheFileSizeErrors)
+        {
+            fileUpload = new ServletChacheFileSizeErrorsFileUpload();
+        }
+        else
+        {
+            fileUpload = new ServletFileUpload();
+        }
+        //fileUpload.setFileItemFactory(new DefaultFileItemFactory()); //USE DiskFileItemFactory
         fileUpload.setSizeMax(maxSize);
+        fileUpload.setFileSizeMax(maxFileSize);
 
-        fileUpload.setSizeThreshold(thresholdSize);
+        //fileUpload.setSizeThreshold(thresholdSize); //Pass thresholdSize as param for DiskFileItemFactory
 
+        //if(repositoryPath != null && repositoryPath.trim().length()>0)
+        //    fileUpload.setRepositoryPath(repositoryPath);
+        
         if(repositoryPath != null && repositoryPath.trim().length()>0)
-            fileUpload.setRepositoryPath(repositoryPath);
+        {
+            fileUpload.setFileItemFactory(
+                    new DiskFileItemFactory(thresholdSize,
+                            new File(repositoryPath)));
+        }
+        else
+        {
+            fileUpload.setFileItemFactory(
+                    new DiskFileItemFactory(thresholdSize,
+                            new File(System.getProperty("java.io.tmpdir"))));
+        }
 
         String charset = request.getCharacterEncoding();
         fileUpload.setHeaderEncoding(charset);
 
 
         List requestParameters = null;
-        try{
-            requestParameters = fileUpload.parseRequest(request);
-        } catch (FileUploadBase.SizeLimitExceededException e) {
-
+        
+        try
+        {
+            if (cacheFileSizeErrors)
+            {
+                requestParameters = ((ServletChacheFileSizeErrorsFileUpload) fileUpload).
+                    parseRequestCatchingFileSizeErrors(request, fileUpload);
+            }
+            else
+            {
+                requestParameters = fileUpload.parseRequest(request);
+            }
+        }
+        catch (FileUploadBase.FileSizeLimitExceededException e)
+        {
+            // Since commons-fileupload does not allow to continue processing files
+            // if this exception is thrown, we can't do anything else.
+            // So, the current request is rejected and we can't restore state, so 
+            // this request is dealt like a new request, but note that caching the params
+            // below it is possible to detect if the current request has been aborted
+            // or not.
+            // Note that if cacheFileSizeErrors is true, this is not thrown, so the request
+            // is not aborted unless other different error occur.
             request.setAttribute(
-                "org.apache.myfaces.custom.fileupload.exception","sizeLimitExceeded");
+                    "org.apache.myfaces.custom.fileupload.exception","fileSizeLimitExceeded");
             request.setAttribute("org.apache.myfaces.custom.fileupload.maxSize",
-                new Integer(maxSize));
+                    new Integer((int)maxFileSize));
+            
+            if (log.isWarnEnabled())
+                log.warn("FileSizeLimitExceededException while uploading file.", e);
             
             requestParameters = Collections.EMPTY_LIST;
-
-        }catch(FileUploadException fue){
-            log.error("Exception while uploading file.", fue);
+        }
+        catch (FileUploadBase.SizeLimitExceededException e)
+        {
+            // This exception is thrown when the max request size has been reached.
+            // In this case, the current request is rejected. The current 
+            // request is dealt like a new request, but note that caching the params below
+            // params it is possible to detect if the current request has been aborted
+            // or not.
+            request.setAttribute(
+                "org.apache.myfaces.custom.fileupload.exception","sizeLimitExceeded");
+            request.setAttribute("org.apache.myfaces.custom.fileupload.maxSize",
+                new Integer((int)maxSize));
+            
+            if (log.isWarnEnabled())
+                log.warn("SizeLimitExceededException while uploading file.", e);
+            
             requestParameters = Collections.EMPTY_LIST;
         }
+        catch(FileUploadException fue)
+        {
+            if (log.isErrorEnabled())
+                log.error("Exception while uploading file.", fue);
+            
+            requestParameters = Collections.EMPTY_LIST;
+        }        
 
         parametersMap = new HashMap( requestParameters.size() );
         fileItems = new HashMap();

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/MultipartRequestWrapperConfig.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/MultipartRequestWrapperConfig.java?rev=782515&r1=782514&r2=782515&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/MultipartRequestWrapperConfig.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/MultipartRequestWrapperConfig.java Mon Jun  8 03:28:42 2009
@@ -33,14 +33,17 @@
 class MultipartRequestWrapperConfig
 {
     
+    private int _uploadMaxSize = 100 * 1024 * 1024; // 10 MB
     private int _uploadMaxFileSize = 100 * 1024 * 1024; // 10 MB
     private int _uploadThresholdSize = 1 * 1024 * 1024; // 1 MB
     private String _uploadRepositoryPath = null; //standard temp directory 
+    private boolean _cacheFileSizeErrors = false;
     
+    private static final String UPLOAD_MAX_SIZE = "org.apache.myfaces.UPLOAD_MAX_SIZE";
     private static final String UPLOAD_MAX_FILE_SIZE = "org.apache.myfaces.UPLOAD_MAX_FILE_SIZE";
     private static final String UPLOAD_THRESHOLD_SIZE = "org.apache.myfaces.UPLOAD_THRESHOLD_SIZE"; 
     private static final String UPLOAD_MAX_REPOSITORY_PATH = "org.apache.myfaces.UPLOAD_MAX_REPOSITORY_PATH";  
-    
+    private static final String UPLOAD_CACHE_FILE_SIZE_ERRORS = "org.apache.myfaces.UPLOAD_CACHE_FILE_SIZE_ERRORS";
     private static final String MULTIPART_REQUEST_WRAPPER_CONFIG = MultipartRequestWrapperConfig.class.getName();
     
     private MultipartRequestWrapperConfig() {}
@@ -76,6 +79,24 @@
         return numberParam;
     }
     
+    private static boolean getBooleanValue(String initParameter, boolean defaultVal)
+    {
+        if(initParameter == null || initParameter.trim().length()==0)
+            return defaultVal;
+
+        return (initParameter.equalsIgnoreCase("on") || initParameter.equals("1") || initParameter.equalsIgnoreCase("true"));
+    }
+    
+    public int getUploadMaxSize()
+    {
+        return _uploadMaxSize;
+    }
+
+    public void setUploadMaxSize(int uploadMaxSize)
+    {
+        this._uploadMaxSize = uploadMaxSize;
+    }
+
     public int getUploadMaxFileSize()
     {
         return _uploadMaxFileSize;
@@ -104,7 +125,17 @@
     public void setUploadRepositoryPath(String uploadRepositoryPath)
     {
         this._uploadRepositoryPath = uploadRepositoryPath;
-    }    
+    }
+    
+    public boolean isCacheFileSizeErrors()
+    {
+        return _cacheFileSizeErrors;
+    }
+    
+    public void setCacheFileSizeErrors(boolean cacheFileSizeErrors)
+    {
+        this._cacheFileSizeErrors = cacheFileSizeErrors;
+    }
 
     public static MultipartRequestWrapperConfig getMultipartRequestWrapperConfig(
             ExternalContext context)
@@ -127,6 +158,21 @@
     
                 config._uploadMaxFileSize = resolveSize(param,
                         config._uploadMaxFileSize);
+                
+                param = servletContext
+                    .getInitParameter(UPLOAD_MAX_SIZE);
+
+                if (param != null)
+                {
+                    config._uploadMaxSize = resolveSize(param,
+                            config._uploadMaxSize);
+                }
+                else
+                {
+                    //If not set, default to uploadMaxFileSize
+                    config._uploadMaxSize = resolveSize(param,
+                            config._uploadMaxFileSize);
+                }
     
                 param = servletContext.getInitParameter(UPLOAD_THRESHOLD_SIZE);
     
@@ -135,7 +181,10 @@
     
                 config._uploadRepositoryPath = servletContext
                         .getInitParameter(UPLOAD_MAX_REPOSITORY_PATH);
-    
+
+                config._cacheFileSizeErrors = getBooleanValue(servletContext
+                        .getInitParameter(UPLOAD_CACHE_FILE_SIZE_ERRORS), false);
+                
                 context.getApplicationMap().put(MULTIPART_REQUEST_WRAPPER_CONFIG,
                         config);
             }
@@ -148,6 +197,21 @@
         
                 config._uploadMaxFileSize = resolveSize(param,
                         config._uploadMaxFileSize);
+                
+                param = PortletUtils.getContextInitParameter(
+                        portletContext, UPLOAD_MAX_SIZE);
+
+                if (param != null)
+                {
+                    config._uploadMaxSize = resolveSize(param,
+                            config._uploadMaxSize);
+                }
+                else
+                {
+                    //If not set, default to uploadMaxFileSize
+                    config._uploadMaxSize = resolveSize(param,
+                            config._uploadMaxFileSize);
+                }
         
                 param = PortletUtils.getContextInitParameter(
                         portletContext, UPLOAD_THRESHOLD_SIZE);
@@ -157,10 +221,13 @@
         
                 config._uploadRepositoryPath = PortletUtils.getContextInitParameter(
                         portletContext,UPLOAD_MAX_REPOSITORY_PATH);
+                
+                config._cacheFileSizeErrors = getBooleanValue(PortletUtils
+                        .getContextInitParameter(portletContext, 
+                                UPLOAD_CACHE_FILE_SIZE_ERRORS), false);
         
                 context.getApplicationMap().put(MULTIPART_REQUEST_WRAPPER_CONFIG,
                         config);
-                
             }
         }
 

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/PortletMultipartRequestWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/PortletMultipartRequestWrapper.java?rev=782515&r1=782514&r2=782515&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/PortletMultipartRequestWrapper.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/PortletMultipartRequestWrapper.java Mon Jun  8 03:28:42 2009
@@ -37,6 +37,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.webapp.filter.portlet.ActionRequestWrapper;
+import org.apache.myfaces.webapp.filter.portlet.PortletChacheFileSizeErrorsFileUpload;
 
 /**
  * @since 1.1.8
@@ -54,24 +55,50 @@
     HashMap parametersMap = null;
     PortletFileUpload fileUpload = null;
     HashMap fileItems = null;
+    int maxFileSize;
     int maxSize;
     int thresholdSize;
     String repositoryPath;
+    boolean cacheFileSizeErrors;
 
     public PortletMultipartRequestWrapper(Object request,
-                                   int maxSize, int thresholdSize,
+                                   int maxFileSize, int thresholdSize,
                                    String repositoryPath){
         super((ActionRequest) request );
         this.request = (ActionRequest) request;
-        this.maxSize = maxSize;
+        this.maxFileSize = maxFileSize;
         this.thresholdSize = thresholdSize;
         this.repositoryPath = repositoryPath;
+        //Default values
+        this.maxSize = maxFileSize;
+        this.cacheFileSizeErrors = false;
     }
+    
+    public PortletMultipartRequestWrapper(Object request,
+            int maxFileSize, int thresholdSize,
+            String repositoryPath, int maxRequestSize, boolean cacheFileSizeErrors){
+        super((ActionRequest) request );
+        this.request = (ActionRequest) request;
+        this.maxFileSize = maxFileSize;
+        this.maxSize = maxRequestSize;
+        this.thresholdSize = thresholdSize;
+        this.repositoryPath = repositoryPath;
+        this.cacheFileSizeErrors = cacheFileSizeErrors;
+    }
+
 
     private void parseRequest() {
-        fileUpload = new PortletFileUpload();
+        if (cacheFileSizeErrors)
+        {
+            fileUpload = new PortletChacheFileSizeErrorsFileUpload();
+        }
+        else
+        {
+            fileUpload = new PortletFileUpload();
+        }
 
         fileUpload.setSizeMax(maxSize);
+        fileUpload.setFileSizeMax(maxFileSize);
 
         //fileUpload.setSizeThreshold(thresholdSize);
 
@@ -88,27 +115,69 @@
                     new DiskFileItemFactory(thresholdSize,
                             new File(System.getProperty("java.io.tmpdir"))));
         }
-        
+
         String charset = request.getCharacterEncoding();
         fileUpload.setHeaderEncoding(charset);
 
 
         List requestParameters = null;
-        try{
-            requestParameters = fileUpload.parseRequest(request);
-        } catch (FileUploadBase.SizeLimitExceededException e) {
-
+        
+        try
+        {
+            if (cacheFileSizeErrors)
+            {
+                requestParameters = ((PortletChacheFileSizeErrorsFileUpload) fileUpload).
+                    parseRequestCatchingFileSizeErrors(request, fileUpload);
+            }
+            else
+            {
+                requestParameters = fileUpload.parseRequest(request);
+            }
+        }
+        catch (FileUploadBase.FileSizeLimitExceededException e)
+        {
+            // Since commons-fileupload does not allow to continue processing files
+            // if this exception is thrown, we can't do anything else.
+            // So, the current request is rejected and we can't restore state, so 
+            // this request is dealt like a new request, but note that caching the params
+            // below it is possible to detect if the current request has been aborted
+            // or not.
+            // Note that if cacheFileSizeErrors is true, this is not thrown, so the request
+            // is not aborted unless other different error occur.
             request.setAttribute(
-                "org.apache.myfaces.custom.fileupload.exception","sizeLimitExceeded");
+                    "org.apache.myfaces.custom.fileupload.exception","fileSizeLimitExceeded");
             request.setAttribute("org.apache.myfaces.custom.fileupload.maxSize",
-                new Integer(maxSize));
+                    new Integer((int)maxFileSize));
+            
+            if (log.isWarnEnabled())
+                log.warn("FileSizeLimitExceededException while uploading file.", e);
             
             requestParameters = Collections.EMPTY_LIST;
-
-        }catch(FileUploadException fue){
-            log.error("Exception while uploading file.", fue);
+        }
+        catch (FileUploadBase.SizeLimitExceededException e)
+        {
+            // This exception is thrown when the max request size has been reached.
+            // In this case, the current request is rejected. The current 
+            // request is dealt like a new request, but note that caching the params below
+            // params it is possible to detect if the current request has been aborted
+            // or not.
+            request.setAttribute(
+                "org.apache.myfaces.custom.fileupload.exception","sizeLimitExceeded");
+            request.setAttribute("org.apache.myfaces.custom.fileupload.maxSize",
+                new Integer((int)maxSize));
+            
+            if (log.isWarnEnabled())
+                log.warn("SizeLimitExceededException while uploading file.", e);
+            
             requestParameters = Collections.EMPTY_LIST;
         }
+        catch(FileUploadException fue)
+        {
+            if (log.isErrorEnabled())
+                log.error("Exception while uploading file.", fue);
+            
+            requestParameters = Collections.EMPTY_LIST;
+        }        
 
         parametersMap = new HashMap( requestParameters.size() );
         fileItems = new HashMap();
@@ -239,4 +308,4 @@
     {
       return WWW_FORM_URLENCODED_TYPE;
     }     
-}
\ No newline at end of file
+}

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/TomahawkFacesContextWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/TomahawkFacesContextWrapper.java?rev=782515&r1=782514&r2=782515&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/TomahawkFacesContextWrapper.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/TomahawkFacesContextWrapper.java Mon Jun  8 03:28:42 2009
@@ -34,7 +34,7 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.commons.fileupload.FileUpload;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
 import org.apache.myfaces.renderkit.html.util.AddResource;
 import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
 import org.apache.myfaces.tomahawk.util.ExternalContextUtils;
@@ -83,6 +83,8 @@
  * <li>org.apache.myfaces.UPLOAD_MAX_FILE_SIZE</li>
  * <li>org.apache.myfaces.UPLOAD_THRESHOLD_SIZE</li>
  * <li>org.apache.myfaces.UPLOAD_MAX_REPOSITORY_PATH</li>
+ * <li>org.apache.myfaces.UPLOAD_MAX_SIZE</li>
+ * <li>org.apache.myfaces.UPLOAD_CACHE_FILE_SIZE_ERRORS</li>
  * </ul>
  * 
  * @since 1.1.7
@@ -129,7 +131,8 @@
                         .getExternalContext());
 
                 extendedRequest = new PortletMultipartRequestWrapper( portletRequest, config.getUploadMaxFileSize(),
-                        config.getUploadThresholdSize(), config.getUploadRepositoryPath());
+                        config.getUploadThresholdSize(), config.getUploadRepositoryPath(),
+                        config.getUploadMaxSize(), config.isCacheFileSizeErrors());
             }
             
             AddResource addResource= AddResourceFactory.getInstance(this);
@@ -160,7 +163,7 @@
             
             boolean multipartContent = false;
            
-            if (FileUpload.isMultipartContent(httpRequest)) {
+            if (ServletFileUpload.isMultipartContent(httpRequest)) {
                 multipartContent = true;
                 
                 MultipartRequestWrapperConfig config = MultipartRequestWrapperConfig
@@ -168,7 +171,8 @@
                                 .getExternalContext());                
                 
                 extendedRequest = new MultipartRequestWrapper(httpRequest, config.getUploadMaxFileSize(),
-                        config.getUploadThresholdSize(), config.getUploadRepositoryPath());
+                        config.getUploadThresholdSize(), config.getUploadRepositoryPath(), 
+                        config.getUploadMaxSize(), config.isCacheFileSizeErrors());
                 
             }
 

Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/portlet/PortletChacheFileSizeErrorsFileUpload.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/portlet/PortletChacheFileSizeErrorsFileUpload.java?rev=782515&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/portlet/PortletChacheFileSizeErrorsFileUpload.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/portlet/PortletChacheFileSizeErrorsFileUpload.java Mon Jun  8 03:28:42 2009
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.webapp.filter.portlet;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.portlet.ActionRequest;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.FileItemHeaders;
+import org.apache.commons.fileupload.FileItemHeadersSupport;
+import org.apache.commons.fileupload.FileItemIterator;
+import org.apache.commons.fileupload.FileItemStream;
+import org.apache.commons.fileupload.FileUpload;
+import org.apache.commons.fileupload.FileUploadBase;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.RequestContext;
+import org.apache.commons.fileupload.portlet.PortletFileUpload;
+import org.apache.commons.fileupload.portlet.PortletRequestContext;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.fileupload.util.LimitedInputStream;
+import org.apache.commons.fileupload.util.Streams;
+
+/**
+ * Custom implementation of PortletFileUpload intended to parse request but it
+ * catch and swallow FileSizeLimitExceededExceptions in order to return as
+ * many usable items as possible.
+ * 
+ * <p>
+ * NOTE: This class should be used(instantiated) only by 
+ * PortletMultipartRequestWrapper. By that reason, it could be changed
+ * or removed in the future.
+ * </p>
+ * 
+ * @since 1.1.9
+ * @author Phillip Webb
+ * @author Leonardo Uribe (latest modification by $Author: lu4242 $)
+ * @version $Revision: 703744 $ $Date: 2008-10-11 17:28:20 -0500 (Sat, 11 Oct 2008) $
+ *
+ */
+public class PortletChacheFileSizeErrorsFileUpload extends PortletFileUpload
+{
+   
+    public PortletChacheFileSizeErrorsFileUpload()
+    {
+        super();
+    }
+    
+    public PortletChacheFileSizeErrorsFileUpload(FileItemFactory fileItemFactory)
+    {
+        super(fileItemFactory);
+    }
+        
+    /**
+     * Determine the length of an uploaded file as indicated by the header.
+     * 
+     * @param pHeaders
+     * @return length or -1
+     */
+    private long getContentLength(FileItemHeaders pHeaders) {
+        try {
+            return Long.parseLong(pHeaders.getHeader(FileUploadBase.CONTENT_LENGTH));
+        } catch (Exception e) {
+            return -1;
+        }
+    }    
+
+    /**
+     * Similar to {@link ServletFileUpload#parseRequest(RequestContext)} but will
+     * catch and swallow FileSizeLimitExceededExceptions in order to return as
+     * many usable items as possible.
+     * 
+     * @param fileUpload
+     * @return List of {@link FileItem} excluding any that exceed max size.  
+     * @throws FileUploadException
+     */
+    public List parseRequestCatchingFileSizeErrors(ActionRequest request, FileUpload fileUpload)
+            throws FileUploadException
+    {
+        try
+        {
+            List items = new ArrayList();
+            
+            // The line below throws a SizeLimitExceededException (wrapped by a
+            // FileUploadIOException) if the request is longer than the max size
+            // allowed by fileupload requests (FileUpload.getSizeMax)
+            // But note that if the request does not send proper headers this check
+            // just will not do anything and we still have to check it again.
+            FileItemIterator iter = fileUpload
+                    .getItemIterator(new PortletRequestContext(request));
+
+            FileItemFactory fac = fileUpload.getFileItemFactory();
+            if (fac == null)
+            {
+                throw new NullPointerException(
+                        "No FileItemFactory has been set.");
+            }
+            
+            long maxFileSize = this.getFileSizeMax();
+            long maxSize = this.getSizeMax();
+            boolean checkMaxSize = false;
+            
+            if (maxFileSize == -1L)
+            {
+                //The max allowed file size should be approximate to the maxSize
+                maxFileSize = maxSize;
+            }
+            if (maxSize != -1L)
+            {
+                checkMaxSize = true;
+            }
+            
+            while (iter.hasNext())
+            {
+                final FileItemStream item = iter.next();
+                FileItem fileItem = fac.createItem(item.getFieldName(), item
+                        .getContentType(), item.isFormField(), item.getName());
+
+                long allowedLimit = 0L;
+                try
+                {
+                    if (maxFileSize != -1L || checkMaxSize)
+                    {
+                        if (checkMaxSize)
+                        {
+                            allowedLimit = maxSize > maxFileSize ? maxFileSize : maxSize;
+                        }
+                        else
+                        {
+                            //Just put the limit
+                            allowedLimit = maxFileSize;
+                        }
+                        
+                        long contentLength = getContentLength(item.getHeaders());
+
+                        //If we have a content length in the header we can use it
+                        if (contentLength != -1L && contentLength > allowedLimit)
+                        {
+                            throw new FileUploadIOException(
+                                    new FileSizeLimitExceededException(
+                                            "The field "
+                                                    + item.getFieldName()
+                                                    + " exceeds its maximum permitted "
+                                                    + " size of " + allowedLimit
+                                                    + " characters.",
+                                            contentLength, allowedLimit));
+                        }
+
+                        //Otherwise we must limit the input as it arrives (NOTE: we cannot rely
+                        //on commons upload to throw this exception as it will close the 
+                        //underlying stream
+                        final InputStream itemInputStream = item.openStream();
+                        
+                        InputStream limitedInputStream = new LimitedInputStream(
+                                itemInputStream, allowedLimit)
+                        {
+                            protected void raiseError(long pSizeMax, long pCount)
+                                    throws IOException
+                            {
+                                throw new FileUploadIOException(
+                                        new FileSizeLimitExceededException(
+                                                "The field "
+                                                        + item.getFieldName()
+                                                        + " exceeds its maximum permitted "
+                                                        + " size of "
+                                                        + pSizeMax
+                                                        + " characters.",
+                                                pCount, pSizeMax));
+                            }
+                        };
+
+                        //Copy from the limited stream
+                        long bytesCopied = Streams.copy(limitedInputStream, fileItem
+                                .getOutputStream(), true);
+                        
+                        // Decrement the bytesCopied values from maxSize, so the next file copied 
+                        // takes into account this value when allowedLimit var is calculated
+                        // Note the invariant before the line is maxSize >= bytesCopied, since if this
+                        // is not true a FileUploadIOException is thrown first.
+                        maxSize -= bytesCopied;
+                    }
+                    else
+                    {
+                        //We can just copy the data
+                        Streams.copy(item.openStream(), fileItem
+                                .getOutputStream(), true);
+                    }
+                }
+                catch (FileUploadIOException e)
+                {
+                    try
+                    {
+                        throw (FileUploadException) e.getCause();
+                    }
+                    catch (FileUploadBase.FileSizeLimitExceededException se)
+                    {
+                        request
+                                .setAttribute(
+                                        "org.apache.myfaces.custom.fileupload.exception",
+                                        "fileSizeLimitExceeded");
+                        String fieldName = fileItem.getFieldName();
+                        request.setAttribute(
+                                "org.apache.myfaces.custom.fileupload."+fieldName+".maxSize",
+                                new Integer((int)allowedLimit));
+                    }
+                }
+                catch (IOException e)
+                {
+                    throw new IOFileUploadException("Processing of "
+                            + FileUploadBase.MULTIPART_FORM_DATA
+                            + " request failed. " + e.getMessage(), e);
+                }
+                if (fileItem instanceof FileItemHeadersSupport)
+                {
+                    final FileItemHeaders fih = item.getHeaders();
+                    ((FileItemHeadersSupport) fileItem).setHeaders(fih);
+                }
+                if (fileItem != null)
+                {
+                    items.add(fileItem);
+                }
+            }
+            return items;
+        }
+        catch (FileUploadIOException e)
+        {
+            throw (FileUploadException) e.getCause();
+        }
+        catch (IOException e)
+        {
+            throw new FileUploadException(e.getMessage(), e);
+        }
+    }
+}

Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/servlet/ServletChacheFileSizeErrorsFileUpload.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/servlet/ServletChacheFileSizeErrorsFileUpload.java?rev=782515&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/servlet/ServletChacheFileSizeErrorsFileUpload.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/webapp/filter/servlet/ServletChacheFileSizeErrorsFileUpload.java Mon Jun  8 03:28:42 2009
@@ -0,0 +1,253 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.webapp.filter.servlet;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.FileItemHeaders;
+import org.apache.commons.fileupload.FileItemHeadersSupport;
+import org.apache.commons.fileupload.FileItemIterator;
+import org.apache.commons.fileupload.FileItemStream;
+import org.apache.commons.fileupload.FileUpload;
+import org.apache.commons.fileupload.FileUploadBase;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.RequestContext;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.fileupload.servlet.ServletRequestContext;
+import org.apache.commons.fileupload.util.LimitedInputStream;
+import org.apache.commons.fileupload.util.Streams;
+
+/**
+ * Custom implementation of ServletFileUpload intended to parse request but it
+ * catch and swallow FileSizeLimitExceededExceptions in order to return as
+ * many usable items as possible.
+ * 
+ * <p>
+ * NOTE: This class should be used(instantiated) only by 
+ * ServletMultipartRequestWrapper. By that reason, it could be changed
+ * or removed in the future.
+ * </p>
+ * 
+ * @since 1.1.9
+ * @author Phillip Webb
+ * @author Leonardo Uribe (latest modification by $Author: lu4242 $)
+ * @version $Revision: 703744 $ $Date: 2008-10-11 17:28:20 -0500 (Sat, 11 Oct 2008) $
+ *
+ */
+public class ServletChacheFileSizeErrorsFileUpload extends ServletFileUpload
+{
+   
+    public ServletChacheFileSizeErrorsFileUpload()
+    {
+        super();
+    }
+    
+    public ServletChacheFileSizeErrorsFileUpload(FileItemFactory fileItemFactory)
+    {
+        super(fileItemFactory);
+    }
+        
+    /**
+     * Determine the length of an uploaded file as indicated by the header.
+     * 
+     * @param pHeaders
+     * @return length or -1
+     */
+    private long getContentLength(FileItemHeaders pHeaders) {
+        try {
+            return Long.parseLong(pHeaders.getHeader(FileUploadBase.CONTENT_LENGTH));
+        } catch (Exception e) {
+            return -1;
+        }
+    }    
+
+    /**
+     * Similar to {@link ServletFileUpload#parseRequest(RequestContext)} but will
+     * catch and swallow FileSizeLimitExceededExceptions in order to return as
+     * many usable items as possible.
+     * 
+     * @param fileUpload
+     * @return List of {@link FileItem} excluding any that exceed max size.  
+     * @throws FileUploadException
+     */
+    public List parseRequestCatchingFileSizeErrors(HttpServletRequest request, FileUpload fileUpload)
+            throws FileUploadException
+    {
+        try
+        {
+            List items = new ArrayList();
+            
+            // The line below throws a SizeLimitExceededException (wrapped by a
+            // FileUploadIOException) if the request is longer than the max size
+            // allowed by fileupload requests (FileUpload.getSizeMax)
+            // But note that if the request does not send proper headers this check
+            // just will not do anything and we still have to check it again.
+            FileItemIterator iter = fileUpload
+                    .getItemIterator(new ServletRequestContext(request));
+
+            FileItemFactory fac = fileUpload.getFileItemFactory();
+            if (fac == null)
+            {
+                throw new NullPointerException(
+                        "No FileItemFactory has been set.");
+            }
+            
+            long maxFileSize = this.getFileSizeMax();
+            long maxSize = this.getSizeMax();
+            boolean checkMaxSize = false;
+            
+            if (maxFileSize == -1L)
+            {
+                //The max allowed file size should be approximate to the maxSize
+                maxFileSize = maxSize;
+            }
+            if (maxSize != -1L)
+            {
+                checkMaxSize = true;
+            }
+            
+            while (iter.hasNext())
+            {
+                final FileItemStream item = iter.next();
+                FileItem fileItem = fac.createItem(item.getFieldName(), item
+                        .getContentType(), item.isFormField(), item.getName());
+
+                long allowedLimit = 0L;
+                try
+                {
+                    if (maxFileSize != -1L || checkMaxSize)
+                    {
+                        if (checkMaxSize)
+                        {
+                            allowedLimit = maxSize > maxFileSize ? maxFileSize : maxSize;
+                        }
+                        else
+                        {
+                            //Just put the limit
+                            allowedLimit = maxFileSize;
+                        }
+                        
+                        long contentLength = getContentLength(item.getHeaders());
+
+                        //If we have a content length in the header we can use it
+                        if (contentLength != -1L && contentLength > allowedLimit)
+                        {
+                            throw new FileUploadIOException(
+                                    new FileSizeLimitExceededException(
+                                            "The field "
+                                                    + item.getFieldName()
+                                                    + " exceeds its maximum permitted "
+                                                    + " size of " + allowedLimit
+                                                    + " characters.",
+                                            contentLength, allowedLimit));
+                        }
+
+                        //Otherwise we must limit the input as it arrives (NOTE: we cannot rely
+                        //on commons upload to throw this exception as it will close the 
+                        //underlying stream
+                        final InputStream itemInputStream = item.openStream();
+                        
+                        InputStream limitedInputStream = new LimitedInputStream(
+                                itemInputStream, allowedLimit)
+                        {
+                            protected void raiseError(long pSizeMax, long pCount)
+                                    throws IOException
+                            {
+                                throw new FileUploadIOException(
+                                        new FileSizeLimitExceededException(
+                                                "The field "
+                                                        + item.getFieldName()
+                                                        + " exceeds its maximum permitted "
+                                                        + " size of "
+                                                        + pSizeMax
+                                                        + " characters.",
+                                                pCount, pSizeMax));
+                            }
+                        };
+
+                        //Copy from the limited stream
+                        long bytesCopied = Streams.copy(limitedInputStream, fileItem
+                                .getOutputStream(), true);
+                        
+                        // Decrement the bytesCopied values from maxSize, so the next file copied 
+                        // takes into account this value when allowedLimit var is calculated
+                        // Note the invariant before the line is maxSize >= bytesCopied, since if this
+                        // is not true a FileUploadIOException is thrown first.
+                        maxSize -= bytesCopied;
+                    }
+                    else
+                    {
+                        //We can just copy the data
+                        Streams.copy(item.openStream(), fileItem
+                                .getOutputStream(), true);
+                    }
+                }
+                catch (FileUploadIOException e)
+                {
+                    try
+                    {
+                        throw (FileUploadException) e.getCause();
+                    }
+                    catch (FileUploadBase.FileSizeLimitExceededException se)
+                    {
+                        request
+                                .setAttribute(
+                                        "org.apache.myfaces.custom.fileupload.exception",
+                                        "fileSizeLimitExceeded");
+                        String fieldName = fileItem.getFieldName();
+                        request.setAttribute(
+                                "org.apache.myfaces.custom.fileupload."+fieldName+".maxSize",
+                                new Integer((int)allowedLimit));
+                    }
+                }
+                catch (IOException e)
+                {
+                    throw new IOFileUploadException("Processing of "
+                            + FileUploadBase.MULTIPART_FORM_DATA
+                            + " request failed. " + e.getMessage(), e);
+                }
+                if (fileItem instanceof FileItemHeadersSupport)
+                {
+                    final FileItemHeaders fih = item.getHeaders();
+                    ((FileItemHeadersSupport) fileItem).setHeaders(fih);
+                }
+                if (fileItem != null)
+                {
+                    items.add(fileItem);
+                }
+            }
+            return items;
+        }
+        catch (FileUploadIOException e)
+        {
+            throw (FileUploadException) e.getCause();
+        }
+        catch (IOException e)
+        {
+            throw new FileUploadException(e.getMessage(), e);
+        }
+    }
+}

Added: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/custom/fileupload/AbstractHtmlInputFileUpload.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/custom/fileupload/AbstractHtmlInputFileUpload.java?rev=782515&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/custom/fileupload/AbstractHtmlInputFileUpload.java (added)
+++ myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/custom/fileupload/AbstractHtmlInputFileUpload.java Mon Jun  8 03:28:42 2009
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.fileupload;
+
+import javax.el.ValueExpression;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.component.html.HtmlInputText;
+import javax.faces.context.FacesContext;
+
+import org.apache.myfaces.component.AlignProperty;
+import org.apache.myfaces.component.UserRoleAware;
+import org.apache.myfaces.component.UserRoleUtils;
+import org.apache.myfaces.shared_tomahawk.util.MessageUtils;
+
+/**
+ * Creates a file-selection widget in the rendered page which allows a user to select
+ * a file for uploading to the server.
+ * <p>
+ * When the page is selected (using a command component such as commandButton), the
+ * currently selected file contents are included in the data posted to the server.
+ * The contents are cached somewhere, and an object of type UploadedFile will then
+ * be assigned to the property pointed to by the "value" expression of this component.
+ * </p>
+ * <p>
+ * You must enable the Tomahawk ExtensionsFilter to make this component work (see web.xml).
+ * </p> 
+ * <p>
+ * Also, don't forget to set the form's attribute "enctype" to "multipart/form-data". 
+ * See "examples/web/fileupload.jsp" for an example!
+ * </p> 
+ * <p>
+ * Unless otherwise specified, all attributes accept static values or EL expressions.
+ * </p>
+ * 
+ * @JSFComponent
+ *   name = "t:inputFileUpload"
+ *   class = "org.apache.myfaces.custom.fileupload.HtmlInputFileUpload"
+ *   tagClass = "org.apache.myfaces.custom.fileupload.HtmlInputFileUploadTag"
+ * @since 1.1.7
+ * @author Manfred Geiler (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractHtmlInputFileUpload
+        extends HtmlInputText
+        implements UserRoleAware, AlignProperty
+{
+    private static final String SIZE_LIMIT_EXCEEDED = "sizeLimitExceeded";
+    private static final String FILE_SIZE_LIMIT_EXCEEDED = "fileSizeLimitExceeded";
+    private static final String FILEUPLOAD_MAX_SIZE = "org.apache.myfaces.custom.fileupload.maxSize";
+    private static final String FILEUPLOAD_EXCEPTION = "org.apache.myfaces.custom.fileupload.exception";
+    public static final String COMPONENT_TYPE = "org.apache.myfaces.HtmlInputFileUpload";
+    public static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.FileUpload";
+    public static final String SIZE_LIMIT_MESSAGE_ID = "org.apache.myfaces.FileUpload.SIZE_LIMIT";
+
+    public AbstractHtmlInputFileUpload()
+    {
+        setRendererType(DEFAULT_RENDERER_TYPE);
+    }
+
+    public void setUploadedFile(UploadedFile upFile)
+    {
+        setValue(upFile);
+    }
+
+    public UploadedFile getUploadedFile()
+    {
+        return (UploadedFile)getValue();
+    }
+    
+    /**
+     * This setting was intended to allow control over how the contents of the
+     * file get temporarily stored during processing.
+     * <p> It allows three options<p>
+     * <ul>
+     * <li>"default": The file is handled on memory while the file size is below 
+     * uploadThresholdSize value, otherwise is handled on disk or file storage when
+     * decode occur (set submitted value)</li>
+     * <li>"memory": The file is loaded to memory when decode occur 
+     * (set submitted value). In other words, before set the uploaded file as 
+     * submitted value it is loaded to memory. Use with caution, because it
+     * could cause OutOfMemory exceptions when the uploaded files are too big. </li>
+     * <li>"file": The file is handled on disk or file storage.</li>
+     * </ul>
+     * 
+     * @JSFProperty
+     */
+    public abstract String getStorage();
+
+    /**
+     * This property appears to have no purpose at all. It certainly has no
+     * documentation.
+     * 
+     * @JSFProperty
+     */
+    public abstract String getAccept();
+
+    /**
+     * An EL expression to which an UploadedFile object will be assigned on postback
+     * if the user specified a file to upload to the server.
+     * 
+     * @JSFProperty
+     */
+    public Object getValue()
+    {
+        return super.getValue();
+    }
+
+    public boolean isRendered()
+    {
+        if (!UserRoleUtils.isVisibleOnUserRole(this)) return false;
+        return super.isRendered();
+    }
+    
+    protected void validateValue(FacesContext context, Object convertedValue)
+    {
+        super.validateValue(context, convertedValue);
+        
+        if (isValid())
+        {
+              String exception =
+                (String) context.getExternalContext().getRequestMap().get(FILEUPLOAD_EXCEPTION);
+              
+              if(exception != null )
+              {
+                if(exception.equals(SIZE_LIMIT_EXCEEDED))
+                {
+                  Integer maxSize =
+                    (Integer) context.getExternalContext().getRequestMap().get(FILEUPLOAD_MAX_SIZE);
+                  MessageUtils.addMessage(FacesMessage.SEVERITY_ERROR,
+                              SIZE_LIMIT_MESSAGE_ID, new Object[] { getLabel(context, this),
+                                      maxSize},
+                              getClientId(context), context);
+                  setValid(false);
+                }
+                else if (FILE_SIZE_LIMIT_EXCEEDED.equals(exception))
+                {
+                    Integer maxSize =
+                        (Integer) context.getExternalContext().getRequestMap().get(FILEUPLOAD_MAX_SIZE);
+                    if (maxSize != null)
+                    {
+                        MessageUtils.addMessage(FacesMessage.SEVERITY_ERROR,
+                                SIZE_LIMIT_MESSAGE_ID, new Object[] { getLabel(context, this),
+                                        maxSize},
+                                getClientId(context), context);
+                    }
+                    else
+                    {
+                        maxSize = (Integer) context.getExternalContext().getRequestMap().get(
+                                "org.apache.myfaces.custom.fileupload."+this.getClientId(context)+".maxSize");
+                        if (maxSize != null)
+                        {
+                            MessageUtils.addMessage(FacesMessage.SEVERITY_ERROR,
+                                    SIZE_LIMIT_MESSAGE_ID, new Object[] { getLabel(context, this),
+                                            maxSize},
+                                    getClientId(context), context);
+                        }
+                        //else
+                        //{
+                            //Ignore because this exception belongs to other component
+                        //}
+                    }
+                    setValid(false);
+                }
+                else 
+                {
+                  throw new IllegalStateException("other exceptions not handled yet, exception : "+exception);
+                }
+             }
+         }
+     }
+    
+    //TODO: Move this method to org.apache.myfaces.shared.util.MessageUtils
+    private static String getLabel(FacesContext facesContext, UIComponent component) {
+        Object label = component.getAttributes().get("label");
+        if(label != null)
+            return label.toString();
+        
+        ValueExpression expression = component.getValueExpression("label");
+        if(expression != null)
+            return expression.getExpressionString();
+            //return (String)expression.getValue(facesContext.getELContext());
+        
+        //If no label is not specified, use clientId
+        return component.getClientId( facesContext );
+    }
+}

Propchange: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/custom/fileupload/AbstractHtmlInputFileUpload.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/custom/fileupload/AbstractHtmlInputFileUpload.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL