You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ma...@apache.org on 2010/04/01 10:03:30 UTC

svn commit: r929879 - in /myfaces/trinidad/trunk: trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/ trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/ trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/ tri...

Author: matzew
Date: Thu Apr  1 08:03:29 2010
New Revision: 929879

URL: http://svn.apache.org/viewvc?rev=929879&view=rev
Log:
TRINIDAD-1757 - Allow (or support) decorator pattern for the UploadedFileProcessor

thanks to Girish Kumar Balachandran for the patch

Added:
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/ChainedUploadedFileProcessor.java
    myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/ProfanityScanner.java
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/upload/CompositeUploadedFileProcessorImpl.java
Modified:
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UploadedFileProcessor.java
    myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/UIBean.java
    myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/trinidad-config.xml
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/ConfigParser.java
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/upload/UploadedFileProcessorImpl.java

Added: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/ChainedUploadedFileProcessor.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/ChainedUploadedFileProcessor.java?rev=929879&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/ChainedUploadedFileProcessor.java (added)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/ChainedUploadedFileProcessor.java Thu Apr  1 08:03:29 2010
@@ -0,0 +1,105 @@
+/*
+ *  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.trinidad.webapp;
+
+import java.io.IOException;
+import org.apache.myfaces.trinidad.model.UploadedFile;
+
+/**
+ * Interface responsible for processing file uploads by multiple processors one
+ * after another in a chained fashion. An Apache Trinidad application could have
+ * multiple <code>ChainedUploadedFileProcessor</code> instances. A composite UploadedFileProcessor
+ * is accessible from the {@link org.apache.myfaces.trinidad.context.RequestContext},
+ * but will be invoked automatically by the framework as needed. Developers
+ * can implement this interface and chain many of them up together using space
+ * separated class names in <code>trinidad-config.xml</code> file under
+ * <code>uploaded-file-processor</code> element. The order in which the processors
+ * will be instantated and called will be the same as how it appears inside the element.
+ * <p>
+ * To configure file uploads, the default instance supports three context
+ * initialization parameters :
+ * <ul>
+ * <li>org.apache.myfaces.trinidad.UPLOAD_MAX_MEMORY: the maximum amount of memory
+ *  that can be used in a single request to store
+ *  uploaded files. (Default of 100K)
+ * <li>org.apache.myfaces.trinidad.UPLOAD_MAX_DISK_SPACE: the maximum amount of
+ *  disk space that can be used in a single request to store
+ *  uploaded files.  (Default of 2000K)
+ * <li>org.apache.myfaces.trinidad.UPLOAD_TEMP_DIR: the name of a directory
+ *   to store temporary files.  (Defaults to the user's temporary directory)
+ * </ul>
+ * 
+ * @see org.apache.myfaces.trinidad.model.UploadedFile
+ */
+public interface ChainedUploadedFileProcessor extends UploadedFileProcessor
+{
+  /**
+   * Initialize the ChainedUploadedFileProcessor with access to the current
+   * web application context. The order of call is same as it
+   * appears in trinidad-config.xml
+   *
+   * @param context the current ServletContext or PortletContext
+   */
+  public void init(Object context);
+
+  /**
+   * Process a single uploaded file.  An implementation of this
+   *   method must process an incoming <code>UploadedFile</code> object
+   *   and return a new <code>UploadedFile</code> instance that will
+   *   remain valid for the duration of this request.  The properties of the incoming
+   *   <code>UploadedFile</code> object depends on the implementation detail of
+   *   the previous ChainedUploadedFileProcessor in the chain. In general all the
+   *   implementations must strive to return a <code>UploadedFile</code> that
+   *   should at the least comply to following:
+   *  <ul>
+   *    <li>{@link UploadedFile#getInputStream} may only be called once</li>
+   *    <li>{@link UploadedFile#getLength} returns length as it should be available</li>
+   *    <li>{@link UploadedFile#getFilename} may have been internationalized;  users should not
+   *      rely on its value, but simply use it unmodified in the
+   *      outgoing <code>UploadedFile</code></li>
+   *  </ul>
+   *  <p>
+   *  First ChainedUploadedFileProcessor in the list gets an <code>UploadedFile</code> implementation
+   *  from the framework with the above properties and the following few more:
+   *  <ul>
+   *    <li>{@link UploadedFile#getInputStream} may be called multiple times. Each call gives a new InputStream</li>
+   *    <li>{@link UploadedFile#getLength} returns length</li>
+   *  </ul>
+   *  Due to the above properties, if there was no change made to the underlying stream
+   *  significantly by the current ChainedUploadedFileProcessor, this <code>UploadedFile</code> object could
+   *  be returned intact for subsequent processing by the framework. This avoids creation of
+   *  new <code>UploadedFile</code> for simple ChainedUploadedFileProcessor implementations.
+   *  </p>
+   *  <p>
+   *  The framework guarantees that {@link UploadedFile#dispose}</code> will be called before
+   *  the request completes for each UploadedFile returned by every ChainedUploadedFileProcessor.
+   *  The order in which dispose() will be called is the revers of the order
+   *  they are declared in trinidad-config.xml. If same UploadedFile
+   *  was returned by more than one processors, dispose() will be called only once
+   *  on it. Any exception that happenes during dispose() call will be logged
+   *  as warning and the processing continues with the rest of the UploadedFile(s).
+   *  </p>
+   * @param request the current servlet or portlet request
+   * @param file a temporary file object
+   * @return a new instance of UploadedFile.  It is legal to return null,
+   *   in which case the file will not be available later in the request.
+   */
+  public UploadedFile processFile(
+    Object request, UploadedFile file) throws IOException;
+}

Modified: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UploadedFileProcessor.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UploadedFileProcessor.java?rev=929879&r1=929878&r2=929879&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UploadedFileProcessor.java (original)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/webapp/UploadedFileProcessor.java Thu Apr  1 08:03:29 2010
@@ -24,8 +24,10 @@ import org.apache.myfaces.trinidad.model
 
 /**
  * Interface responsible for processing file uploads.  An Apache Trinidad
- * application has a single <code>UploadedFileProcessor</code> instance.
- * It is accessible from the {@link org.apache.myfaces.trinidad.context.RequestContext},
+ * application has a single <code>UploadedFileProcessor</code> instance. For
+ * more simpler, multiple chained UploadedFileProcessor option please look at
+ * {@link  org.apache.myfaces.trinidad.webapp.ChainedUploadedFileProcessor}.
+ * UploadedFileProcessor is accessible from the {@link org.apache.myfaces.trinidad.context.RequestContext},
  * but will be invoked automatically by the framework as needed.  Developers
  * can replace the standard processor using the
  * <code>trinidad-config.xml</code> file.

Added: myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/ProfanityScanner.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/ProfanityScanner.java?rev=929879&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/ProfanityScanner.java (added)
+++ myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/ProfanityScanner.java Thu Apr  1 08:03:29 2010
@@ -0,0 +1,76 @@
+/*
+ *  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.trinidaddemo;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.myfaces.trinidad.model.UploadedFile;
+import org.apache.myfaces.trinidad.webapp.ChainedUploadedFileProcessor;
+
+/**
+ * This class checks if the uploaded file contains the word "crap" in it and
+ * rejects if found.
+ * 
+ */
+public class ProfanityScanner implements ChainedUploadedFileProcessor
+{
+
+  public void init(Object context)
+  {
+    _LOG.log(Level.INFO, "ProfanityScanner just got initialized...");
+  }
+
+  public UploadedFile processFile(Object request, UploadedFile file) throws IOException
+  {
+    _LOG.log(Level.INFO, "Scanning for profanity...");
+
+    BufferedReader br = new BufferedReader(new InputStreamReader(file.getInputStream()));
+    String line;
+    try
+    {
+      while ((line = br.readLine()) != null)
+      {
+        if (line.indexOf("crap") != -1)
+        {
+          throw new IOException("ProfanityScanner rejected this file as " +
+                  "it contained the word \"crap\" in it!!!\n" + request);
+        }
+      }
+    }
+    finally
+    {
+      br.close();
+    }
+    
+    _LOG.log(Level.INFO, "Done Scanning for profanity...");
+    
+    /**
+     * Since we did not change anything in the Inputstream we got from the parameter
+     * its ok to return the same object. The file argument is backed by the buffer
+     * hence subsequent processors will be able to access the stream again.
+     */
+    return file;
+  }
+
+  static private final Logger _LOG =
+          Logger.getLogger(ProfanityScanner.class.getName());
+}

Modified: myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/UIBean.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/UIBean.java?rev=929879&r1=929878&r2=929879&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/UIBean.java (original)
+++ myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/UIBean.java Thu Apr  1 08:03:29 2010
@@ -59,7 +59,7 @@ public class UIBean
     _panelPage = panelPage;
   }
 
-  public void fileUploaded(ValueChangeEvent event)
+  public void fileUploaded(ValueChangeEvent event) throws IOException
   {
     UploadedFile file = (UploadedFile) event.getNewValue();
     if (file != null)
@@ -67,7 +67,8 @@ public class UIBean
       FacesContext context = FacesContext.getCurrentInstance();
       FacesMessage message = new FacesMessage(
          "Uploaded file " + file.getFilename() +
-         " (" + file.getLength() + " bytes)");
+         " (" + file.getLength() + " bytes)"+". Bytes available to read: " +
+         file.getInputStream().available());
       context.addMessage(event.getComponent().getClientId(context), message);
     }
   }

Modified: myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/trinidad-config.xml
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/trinidad-config.xml?rev=929879&r1=929878&r2=929879&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/trinidad-config.xml (original)
+++ myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/trinidad-config.xml Thu Apr  1 08:03:29 2010
@@ -33,6 +33,9 @@
   <skin-family>#{prefs.proxy.skinFamily}</skin-family>  
 
 
+  <uploaded-file-processor>org.apache.myfaces.trinidaddemo.ProfanityScanner org.apache.myfaces.trinidaddemo.ProfanityScanner</uploaded-file-processor>
+
+  <!--uploaded-file-processor>org.apache.myfaces.trinidaddemo.ProfanityScanner</uploaded-file-processor-->
 
   <!--
   <output-mode>portlet</output-mode>

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/ConfigParser.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/ConfigParser.java?rev=929879&r1=929878&r2=929879&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/ConfigParser.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/ConfigParser.java Thu Apr  1 08:03:29 2010
@@ -20,6 +20,9 @@ package org.apache.myfaces.trinidadinter
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.StringTokenizer;
@@ -36,8 +39,9 @@ import org.apache.myfaces.trinidad.conte
 import org.apache.myfaces.trinidad.context.RequestContext;
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidad.util.ClassLoaderUtils;
+import org.apache.myfaces.trinidad.webapp.ChainedUploadedFileProcessor;
 import org.apache.myfaces.trinidad.webapp.UploadedFileProcessor;
-import org.apache.myfaces.trinidadinternal.config.upload.UploadedFileProcessorImpl;
+import org.apache.myfaces.trinidadinternal.config.upload.CompositeUploadedFileProcessorImpl;
 import org.apache.myfaces.trinidadinternal.context.RequestContextBean;
 import org.apache.myfaces.trinidadinternal.util.nls.LocaleUtils;
 import org.apache.myfaces.trinidadinternal.util.DateUtils;
@@ -102,29 +106,78 @@ public class ConfigParser
       }
     }
 
-    String className = (String)
+    String classNameString = (String)
       bean.getProperty(RequestContextBean.UPLOADED_FILE_PROCESSOR_KEY);
-    if (className != null)
+    if (classNameString != null)
     {
-      className = className.trim();
+      classNameString = classNameString.trim();
 
+      //check if this contains multiple class names for chained processors usecase.
+      // Usually the class named are separated by space char.
+      String classNames[] = classNameString.split("[ ]+");
+      if(classNames.length == 1)
+      {
+        //This could be a single processor full override usecase or a chained
+        //processor usecase that has only one processor.
       try
       {
-        Class<?> clazz = ClassLoaderUtils.loadClass(className);
+          Class<UploadedFileProcessor> clazz = (Class<UploadedFileProcessor>)
+                  ClassLoaderUtils.loadClass(classNames[0]);
+          if(ChainedUploadedFileProcessor.class.isAssignableFrom(clazz))
+          {
+            //this single chained processor case
+            ChainedUploadedFileProcessor cufp[] =
+            {
+              (ChainedUploadedFileProcessor) clazz.newInstance()
+            };
         bean.setProperty(RequestContextBean.UPLOADED_FILE_PROCESSOR_KEY,
+                  new CompositeUploadedFileProcessorImpl(Arrays.asList(cufp)));
+          }
+          else
+          {
+            //this is full override usecase
+            bean.setProperty(RequestContextBean.UPLOADED_FILE_PROCESSOR_KEY,
                          clazz.newInstance());
       }
+          
+
+        }
       catch (Exception e)
       {
         _LOG.severe("CANNOT_INSTANTIATE_UPLOADEDFILEPROCESSOR", e);
         bean.setProperty(RequestContextBean.UPLOADED_FILE_PROCESSOR_KEY,
-                         new UploadedFileProcessorImpl());
+                  new CompositeUploadedFileProcessorImpl());
+      }
+    }
+    else
+    {
+        try
+        {
+          //chained processors usecase, Multiple processors
+          List<ChainedUploadedFileProcessor> processors =
+                  new ArrayList<ChainedUploadedFileProcessor>(classNames.length);
+          for (String className : classNames)
+          {
+            Class<ChainedUploadedFileProcessor> clazz =
+                    (Class<ChainedUploadedFileProcessor>) ClassLoaderUtils.loadClass(className);
+            processors.add(clazz.newInstance());
+          }
+      bean.setProperty(RequestContextBean.UPLOADED_FILE_PROCESSOR_KEY,
+                  new CompositeUploadedFileProcessorImpl(processors));
+    }
+        catch(Exception e)
+        {
+          _LOG.severe("CANNOT_INSTANTIATE_UPLOADEDFILEPROCESSOR", e);
+          bean.setProperty(RequestContextBean.UPLOADED_FILE_PROCESSOR_KEY,
+                  new CompositeUploadedFileProcessorImpl());
+        }
       }
     }
     else
     {
+      //nothing specified, hence use default.
       bean.setProperty(RequestContextBean.UPLOADED_FILE_PROCESSOR_KEY,
-                       new UploadedFileProcessorImpl());
+              new CompositeUploadedFileProcessorImpl());
     }
 
     UploadedFileProcessor ufp = (UploadedFileProcessor)

Added: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/upload/CompositeUploadedFileProcessorImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/upload/CompositeUploadedFileProcessorImpl.java?rev=929879&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/upload/CompositeUploadedFileProcessorImpl.java (added)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/upload/CompositeUploadedFileProcessorImpl.java Thu Apr  1 08:03:29 2010
@@ -0,0 +1,474 @@
+/*
+ *  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.trinidadinternal.config.upload;
+
+
+import java.io.File;
+import java.io.IOException;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.PortletContext;
+import javax.portlet.PortletRequest;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+
+import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.apache.myfaces.trinidad.model.UploadedFile;
+import org.apache.myfaces.trinidad.util.ClassLoaderUtils;
+import org.apache.myfaces.trinidad.webapp.UploadedFileProcessor;
+import org.apache.myfaces.trinidadinternal.context.external.PortletApplicationMap;
+import org.apache.myfaces.trinidadinternal.context.external.PortletInitParameterMap;
+import org.apache.myfaces.trinidadinternal.context.external.PortletRequestMap;
+import org.apache.myfaces.trinidadinternal.context.external.ServletApplicationMap;
+import org.apache.myfaces.trinidadinternal.context.external.ServletInitParameterMap;
+import org.apache.myfaces.trinidadinternal.context.external.ServletRequestMap;
+
+/**
+ * This is the default implementaion of UploadedFileProcessor. It works with
+ * multiple ChainedUploadedFileProcessor declared in trinidad-config.xml by dispatching
+ * the lifecycle calls to them in the order of declaration.
+ **/
+public class CompositeUploadedFileProcessorImpl implements UploadedFileProcessor
+{
+
+  public CompositeUploadedFileProcessorImpl()
+  {
+    chainedProcessors = Collections.emptyList();
+  }
+
+  public CompositeUploadedFileProcessorImpl(
+          List<? extends UploadedFileProcessor> chainedProcessors)
+  {
+    this.chainedProcessors = chainedProcessors;
+  }
+
+  @Override
+  public void init(Object context)
+  {
+    _init(context);
+    for(UploadedFileProcessor processor: chainedProcessors)
+    {
+      //call other chained processor's init
+      processor.init(context);
+    }
+
+  }
+
+  @Override
+  public UploadedFile processFile(Object request, UploadedFile tempFile) throws IOException
+  {
+    //NOTE: The following optimization was suggested at one point:
+    // Check if there are any processors in the list. If yes then call _processFile
+    // else just return tempFile we got. Calling _processFile buffers the entire
+    // file content. tempFile arg however is not buffered. If there are no
+    // ChainedUploadedFileProcessor in the list, then there is no need to buffer.
+    // BUT, the call to getLength() and dispose() on tempFile fails.
+    // This is becasue, the impl of these 2 methods are not complete -
+    // Bug - https://issues.apache.org/jira/browse/TRINIDAD-1765
+    // This bug could not be fixed due to the explanatio in the bug.
+
+    //call _processFile first. This will create the auto buffer that we want.
+    UploadedFile original = _processFile(request, tempFile);
+    if(chainedProcessors.isEmpty())
+    {
+      return original;
+    }
+    else
+    {
+      List<UploadedFile> files = new ArrayList<UploadedFile>(chainedProcessors.size()+1);
+      files.add(original);
+      for(UploadedFileProcessor processor: chainedProcessors)
+      {
+        original = processor.processFile(request, original);
+        files.add(original);
+      }
+      //the dispose order should be reverse!
+      Collections.reverse(files);
+      return new WrappedUploadedFileImpl(original, files);
+    }
+  }
+
+
+  /**
+   * Wrapper around UploadedFileImpl to listen for dispose() call and dispatch to
+   * other UploadedFileImpls returned by other chained processors
+   */
+  private static class WrappedUploadedFileImpl implements UploadedFile{
+
+    public WrappedUploadedFileImpl(UploadedFile original, List<UploadedFile> files)
+    {
+      this.original = original;
+      this.files = files;
+    }
+
+    public void dispose()
+    {
+      try
+      {
+        original.dispose();
+      }
+      catch(Exception e)
+      {
+        _LOG.warning("Exception while disposing!", e);
+        //log and continue disposing the rest.
+      }
+      if(!files.isEmpty())
+      {
+        List<UploadedFile> disposed = new ArrayList<UploadedFile>();
+        disposed.add(original);
+        for(UploadedFile file: files)
+        {
+          if(!disposed.contains(file))
+          {
+            try
+            {
+              file.dispose();
+            }
+            catch(Exception e)
+            {
+              _LOG.warning("Exception while disposing!", e);
+              //log and continue disposing the rest.
+            }
+            disposed.add(file);
+          }
+        }
+      }
+    }
+
+    public String getFilename()
+    {
+      return original.getFilename();
+    }
+
+    public String getContentType()
+    {
+      return original.getContentType();
+    }
+
+    public long getLength()
+    {
+      return original.getLength();
+    }
+
+    public Object getOpaqueData()
+    {
+      return original.getOpaqueData();
+    }
+
+    public InputStream getInputStream() throws IOException
+    {
+      return original.getInputStream();
+    }
+
+    private final UploadedFile original;
+    private final List<UploadedFile> files;
+  }
+
+  private void _init(Object context)
+  {
+    ContextInfo info;
+    if(_PORTLET_CONTEXT_CLASS != null && _PORTLET_CONTEXT_CLASS.isInstance(context))
+    {
+      info = _getPortletContextInfo(context);
+    }
+    else
+    {
+      info = _getServletContextInfo(context);
+    }
+
+    //
+    // Get MaxMemory and TempDir properties from servlet init params
+    //
+    if (_maxMemory == -1)
+    {
+      String maxMemory = info.initParams.get(MAX_MEMORY_PARAM_NAME);
+      if (maxMemory != null)
+      {
+        try
+        {
+          _maxMemory = Long.parseLong(maxMemory);
+        }
+        catch (NumberFormatException nfe)
+        {
+          _maxMemory = _DEFAULT_MAX_MEMORY;
+        }
+      }
+      else
+      {
+        _maxMemory = _DEFAULT_MAX_MEMORY;
+      }
+    }
+
+    if (_maxDiskSpace == -1)
+    {
+      String maxDiskSpace = info.initParams.get(MAX_DISK_SPACE_PARAM_NAME);
+      if (maxDiskSpace != null)
+      {
+        try
+        {
+          _maxDiskSpace = Long.parseLong(maxDiskSpace);
+        }
+        catch (NumberFormatException nfe)
+        {
+          _maxDiskSpace = _DEFAULT_MAX_DISK_SPACE;
+        }
+      }
+      else
+      {
+        _maxDiskSpace = _DEFAULT_MAX_DISK_SPACE;
+      }
+    }
+
+    if (_tempDir == null)
+    {
+      _tempDir = info.initParams.get(TEMP_DIR_PARAM_NAME);
+      // Use the webapp temporary directory if the temporary directory
+      // has not been explicitly set.
+      if (_tempDir == null)
+      {
+        File tempDirFile = (File)
+          info.attributes.get("javax.servlet.context.tempdir");
+        if (tempDirFile != null)
+          _tempDir = tempDirFile.getAbsolutePath();
+      }
+    }
+  }
+
+  private UploadedFile _processFile(
+      Object request, UploadedFile tempFile) throws IOException
+  {
+    RequestInfo info = _getRequestInfo(request);
+    int contentLength = getContentLength(request);
+    Map<String, Object> requestMap;
+
+    if (_isPortletRequestClass(request))
+      requestMap = _getPortletRequestMap(request);
+    else
+      requestMap = _getServletRequestMap(request);
+
+    Long maxMemory = (Long)requestMap.get(MAX_MEMORY_PARAM_NAME);
+    Long maxDiskSpace = (Long)requestMap.get(MAX_DISK_SPACE_PARAM_NAME);
+    String tempDir = (String)requestMap.get(TEMP_DIR_PARAM_NAME);
+
+    if (maxMemory != null)
+    {
+      _maxMemory = maxMemory;
+    }
+
+    if (maxDiskSpace != null)
+    {
+      _maxDiskSpace = maxDiskSpace;
+    }
+
+    if (tempDir != null)
+      _tempDir = tempDir;
+
+    if(contentLength>_maxDiskSpace)
+    {
+      return new ErrorFile();
+    }
+    // Process one new file, loading only as much as can fit
+    // in the remaining memory and disk space.
+    UploadedFileImpl file = new UploadedFileImpl();
+    try
+    {
+      file.loadFile(tempFile,
+                    _maxMemory - info.totalBytesInMemory,
+                    _maxDiskSpace - info.totalBytesOnDisk,
+                    _tempDir);
+    }
+    catch(IOException ioe)
+    {
+      _LOG.severe(ioe);
+      return new ErrorFile();
+    }
+
+    // Keep a tally of how much we've stored in memory and on disk.
+    long length = file.getLength();
+    if (file.__isInMemory())
+    {
+      info.totalBytesInMemory += length;
+    }
+    else
+    {
+      info.totalBytesOnDisk += length;
+    }
+
+    return file;
+  }
+
+  private int getContentLength(Object request)
+  {
+    int length = -1;
+    if (_isPortletRequestClass(request))
+    {
+      length = _getPortletRequestLength(request);
+    }
+    else
+    {
+      length = _getServletRequestLength(request);
+    }
+
+    return length;
+  }
+
+  private RequestInfo _getRequestInfo(Object request)
+  {
+    Map<String, Object> attributes;
+    if (_isPortletRequestClass(request))
+    {
+      attributes = _getPortletRequestMap(request);
+    }
+    else
+    {
+      attributes = _getServletRequestMap(request);
+    }
+
+
+    RequestInfo info = (RequestInfo) attributes.get(_REQUEST_INFO_KEY);
+
+    if (info == null)
+    {
+      info = new RequestInfo();
+      attributes.put(_REQUEST_INFO_KEY, info);
+    }
+
+    return info;
+  }
+
+  private boolean _isPortletRequestClass(Object request)
+  {
+    return (_PORTLET_REQUEST_CLASS != null && _PORTLET_REQUEST_CLASS.isInstance(request));
+  }
+
+  private static final ContextInfo _getServletContextInfo(final Object context)
+  {
+    assert(context instanceof ServletContext);
+
+    final ServletContext sContext = (ServletContext)context;
+    return new ContextInfo(
+             new ServletInitParameterMap(sContext),
+             new ServletApplicationMap(sContext));
+  }
+
+  private static final ContextInfo _getPortletContextInfo(final Object context)
+  {
+    assert(context instanceof PortletContext);
+
+    final PortletContext pContext = (PortletContext)context;
+    return new ContextInfo(
+             new PortletInitParameterMap(pContext),
+             new PortletApplicationMap(pContext));
+  }
+
+  private static final Map<String, Object> _getServletRequestMap(final Object request)
+  {
+    assert(request instanceof ServletRequest);
+
+    return new ServletRequestMap((ServletRequest) request);
+  }
+
+  private static final Map<String, Object> _getPortletRequestMap(final Object request)
+  {
+    assert(request instanceof PortletRequest);
+
+    return new PortletRequestMap((PortletRequest) request);
+  }
+
+  private static final int _getServletRequestLength(final Object request)
+  {
+    assert(request instanceof ServletRequest);
+
+    return ((ServletRequest) request).getContentLength();
+  }
+
+  private static final int _getPortletRequestLength(final Object request)
+  {
+    if (!(request instanceof ActionRequest))
+      return -1;
+
+    return ((ActionRequest) request).getContentLength();
+  }
+
+  static private class RequestInfo
+  {
+    public long totalBytesInMemory;
+    public long totalBytesOnDisk;
+  }
+
+  static private class ContextInfo
+  {
+    public ContextInfo(Map<String,String> init, Map<String, Object> attrib)
+    {
+      initParams= init;
+      attributes = attrib;
+    }
+
+    public Map<String, String> initParams;
+    public Map<String, Object> attributes;
+  }
+
+  private long   _maxMemory = -1;
+  private long   _maxDiskSpace = -1;
+  private String _tempDir = null;
+
+  private static final long _DEFAULT_MAX_MEMORY = 102400;
+  private static final long _DEFAULT_MAX_DISK_SPACE = 2048000;
+
+  private static final String _REQUEST_INFO_KEY = CompositeUploadedFileProcessorImpl.class.getName()+
+    ".UploadedFilesInfo";
+
+  private static final TrinidadLogger _LOG =
+    TrinidadLogger.createTrinidadLogger(CompositeUploadedFileProcessorImpl.class);
+
+  private static final Class<?>        _PORTLET_CONTEXT_CLASS;
+  private static final Class<?>       _PORTLET_REQUEST_CLASS;
+
+  static
+  {
+    Class<?> context;
+    Class<?> request;
+    try
+    {
+      context = ClassLoaderUtils.loadClass("javax.portlet.PortletContext");
+      request = ClassLoaderUtils.loadClass("javax.portlet.PortletRequest");
+    }
+    catch (final ClassNotFoundException e)
+    {
+      _LOG
+          .fine("Portlet API is not available on the classpath.  Portlet configurations are disabled.");
+      context = null;
+      request = null;
+    }
+
+    _PORTLET_CONTEXT_CLASS = context;
+    _PORTLET_REQUEST_CLASS = request;
+  }
+
+
+  private final List<? extends UploadedFileProcessor> chainedProcessors;
+ 
+}

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/upload/UploadedFileProcessorImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/upload/UploadedFileProcessorImpl.java?rev=929879&r1=929878&r2=929879&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/upload/UploadedFileProcessorImpl.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/upload/UploadedFileProcessorImpl.java Thu Apr  1 08:03:29 2010
@@ -41,7 +41,11 @@ import org.apache.myfaces.trinidadintern
 import org.apache.myfaces.trinidadinternal.context.external.ServletInitParameterMap;
 import org.apache.myfaces.trinidadinternal.context.external.ServletRequestMap;
 
-
+/**
+ * @deprecated This implementation is merged to CompositeUploadedFileProcessorImpl.
+ * This class will be removed in the next release.
+ * 
+ */
 public class UploadedFileProcessorImpl implements UploadedFileProcessor
 {
   public UploadedFileProcessorImpl()