Date: 2005-03-02T11:40:38
   Editor: DakotaJack
   Wiki: Apache Struts Wiki
   Page: StrutsUpload
   URL: http://wiki.apache.org/struts/StrutsUpload

   no comment

Change Log:

------------------------------------------------------------------------------
@@ -1,151 +1,33 @@
-##language:en
 == Introduction ==
 
-I have tried to discuss ways to make life easy for everyone in the Struts 
upload area, i.e. for the default application and for alternative applications. 
 As things stand, the default application is fairly wedded deep into the 
framework itself, which, I think, is unnecessary and which, I think, stifles 
chances to explore other options.  There is nothing wrong, of course, with the 
Struts upload application and this is not a criticism.  I would, myself, like 
to be able to use the !ActionForm with a more "detailed" or more 
"sophisticated" application.  If we can get by that hurdle, I would be happy to 
donate the code to Struts, if anyone wants it.  Getting by that hurdle is not 
made easier by my apparent difficulties communicating what I am trying to do to 
the committers.  They seem to think I am asking someone else to do something.  
I am not.  Anyway, if anyone has time to read all the following, that would be 
best.  If someone does not have the time, let me say that I am beginning by 
suggesting a different approach to the present !MultipartRequestHandler and 
!MultipartRequestWrapper, as well as to where wrapper and handler classes are 
introduced into the framework.  I have tried to build a wrapper (facade) and a 
handler which will be agnostic towards any particular solutions, unlike the 
present wrapper and handler.  The wrapper/facade is not sufficient to pass to 
the Action as the request.  It is not even a wrapper in that sense.  Nor, I 
think, would that be desireable.  However, if one wants to do that, I will 
provide a true wrapper connected to the code by implementing the facade methods 
in a wrapper in addition to the regular !HttpServletRequest and !ServletRequest 
methods.  On to the code, then.  Any questions would be welcome: [EMAIL 
PROTECTED]
+This wiki page is an attempt to open some serious dialogue on providing a 
multipart request API in the Struts framework that will work for the default 
Struts upload application as well as alternative implementations and 
applications.  Presently alternative implementations have to forego using 
ActionForm because the populate method of RequestUtils necessitates using the 
default MultipartRequestWrapper and the default MultipartRequestHandler.  
 
-== Struts Multipart Processing in Struts v1.2.6 for Upload Applications ==
+I have suggested using an alternative MultipartRequestHandler which will 
promote alternative ideas and have supplanted the MultipartRequestWrapper with 
a MultipartData interface.  If the committers want to continue passing the 
MultipartRequestWrapper to the Action, then this can be accomplished by passing 
the implementation of the MultipartData interface to the 
MultipartRequestWrapper.  
 
-The present code in Struts v1.2.6 and before is tied to the "default" or 
"existing" upload application supplied in the Struts jar file.  By "tied" I 
mean that the code is coupled to that application such that it unnecessarily 
impedes the development of competing or alternative implementations.  This is 
not a criticism of the default application.  Rather, it is a desire to decouple 
a particular implementation which is not a very sophisticated upload 
application, from the framework.  This is not a hard thing to do, and hopefully 
this wiki page will start a discussion of how that might be achieved, if 
desireable.  As things stand, people regularly have to build around the 
multipart processing in Struts rather than benefit from it.  What is proposed 
here hopefully would provide a basis for keeping what is good about the present 
application while allowing other alternatives to be used too.
+I would strongly suggest, however, not wrapping the multipart request and 
getting the appropriate multipart data from the ActionForm alone.  
 
-The changes suggested here can easily be implemented as is.  I am going to, 
however, first present the ideas and then see if anyone is interested in going 
further.  
+Below you will find suggested alternatives to the existing wrapper and 
handler.  The suggestion is to provide two Globals fields to identify the 
MultipartData and MultipartRequestHandler which would be set in the mapping for 
whatever UploadAction subclass of Action is implemented.
 
-I am going to suggest changes in multipart processing in Struts v1.2.6 and 
forward.  Equivalent changes are suggested for the chain implementations of 
!RequestProcessor. 
+The point of all this is shown in the implementation of the 
MultipartRequestHandler below.  As you can see, this alternative, while costing 
nothing, allows us to make our applications as sophisticated as we want by 
varying the input parameters to the handleRequest(Object []) method of the 
MultipartRequestHandler.  In our example, we (1) pass in information with 
"maxFileSize" and "repositoryPath" to tell the handler what to do; (2) pass in 
Maps "parameterNames" and "files" as well as the "encoding" paramenter to be 
initialized by the handler; (3) pass in a List of monitors to be embedded in 
wrappers of the commons file upload package FileItem, DiskFileUpload, etc.
 
-Let's first see that the present state of v1.2.6 is.  Multipart processing in 
Struts v1.2.6 is fairly simple even if a bit "discombobbled".  The relevant 
classes are:
+== Suggested Code ==
 
- 1. Globals
- 2. !ActionForm
- 3. !RequestProcessor
- 4. !IncludeAction
- 5. !ActionConfig
- 6. !ConfigHelper
- 7. !ConfigHelperInterface
- 8. !ControllerConfig
- 9. !RequestUtils
-
-Let's follow the bouncing-ball like in the old time silent movie sing-alongs.  
The first thing to happen in the process method of !RequestProcessor in Struts 
v1.2.6 is the wrapping of the request, if relevant, in a 
!MultipartRequestWrapper with:
-
-=== RequestProcessor ===
-
-{{{
-request = processMultipart(request);
-}}} 
-
-This is a pretty simple operation/method.
-
-{{{    
-protected HttpServletRequest processMultipart(HttpServletRequest request) {
-  if (!"POST".equalsIgnoreCase(request.getMethod())) {
-    return (request);
-  }
-        
-  String contentType = request.getContentType();
-  if ((contentType != null) &&
-      contentType.startsWith("multipart/form-data")) {
-    return (new MultipartRequestWrapper(request));
-  } else {
-    return (request);
-  }
-}
-}}}
-
-The reason for wrapping the request at this point is not clear, or even a 
mistake.  The resultant !MultipartRequestWrapper is not initialized, i.e. the 
state is not set.  However, in some places, because Struts v1.2.6 is Servlet 
2.2 compatible, the wrapper must be unwrapped, e.g. where the request must be 
accessed for forwards and includes, cf. doForward(...) and doInclude(...) in 
!RequestProcessor.  
-
-If the multipart request wrapper did not implement the !HttpServletRequest, 
none of these difficulties with the differences between Servlet v2.2 and v2.3 
would exist.  I will suggest an alternative to avoid this.  There is a wise 
preference of composition to inheritance in coding generally, but in this case 
we do not even need composition, much less inheritance.  This will be revisited 
below.  
-
-This is just extra coding with no value.  In !ConfigHelper this leads somehow 
to the !MultipartRequestWrapper and the !MultiparRequestHandler in Struts 
v1.2.6 getting confused.  The following code is in !ConfigHelper:
-
-{{{
-public MultipartRequestWrapper getMultipartRequestWrapper() {
-  if (this.request == null) {
-    return null;
-  }
-  return (MultipartRequestWrapper) 
this.request.getAttribute(Globals.MULTIPART_KEY);
-}
-}}}
-
-
-However, the class which is persisted under Globals.MULTIPART_KEY is the 
!MultipartRequestHandler and not the !MultipartRequestWrapper.  This code can 
be, and I understand will be, jettisoned entirely.  
-
-Let's look briefly at the !MultipartRequestWrapper in the upload application, 
which here has insinuated itself into the Struts framework code unnecessarily.
-
-==== EXISTING MultipartRequestWrapper ====
+=== MultipartRequestHandler ===
 
 {{{
-public class MultipartRequestWrapper implements HttpServletRequest {
-  protected Map parameters;
-  protected HttpServletRequest request;
-  
-  public MultipartRequestWrapper(HttpServletRequest request) {
-    this.request = request;
-    this.parameters = new HashMap();
-  }
-  
-  public void setParameter(String name, String value) {
-    String[] mValue = (String[]) parameters.get(name);
-    if (mValue == null) {
-      mValue = new String[0];
-    }
-    String[] newValue = new String[mValue.length + 1];
-    System.arraycopy(mValue, 0, newValue, 0, mValue.length);
-    newValue[mValue.length] = value;
-    
-    parameters.put(name, newValue);
-  }
-  
-  public String getParameter(String name) {
-    String value = request.getParameter(name);
-    if (value == null) {
-      String[] mValue = (String[]) parameters.get(name);
-      if ((mValue != null) && (mValue.length > 0)) {
-        value = mValue[0];
-      }
-    }
-    return value;
-  }
-  
-  public Enumeration getParameterNames() {
-    Enumeration baseParams = request.getParameterNames();
-    Vector list = new Vector();
-    while (baseParams.hasMoreElements()) {
-      list.add(baseParams.nextElement());
-    }
-    Collection multipartParams = parameters.keySet();
-    Iterator iterator = multipartParams.iterator();
-    while (iterator.hasNext()) {
-      list.add(iterator.next());
-    }
-    return Collections.enumeration(list);
-  }
-  
-  public String[] getParameterValues(String name) {
-    String[] value = request.getParameterValues(name);
-    if (value == null) {
-      value = (String[]) parameters.get(name);
-    }
-    return value;
-  }
-  
-  public HttpServletRequest getRequest() {
-    return request;
-  }
-  
-  //WRAPPER IMPLEMENTATIONS OF SERVLET REQUEST METHODS
-  .....
-  //WRAPPER IMPLEMENTATIONS OF HTTPSERVLETREQUEST METHODS
-  .....
-  //SERVLET 2.3 EMPTY METHODS
-  .....
+public interface MultipartRequestHandler {
+  public void handleRequest(Object [] params) throws IOException;
+  public void setServlet(ActionServlet servlet);
+  public void setMapping(ActionMapping mapping);
+  public ActionServlet getServlet();
+  public ActionMapping getMapping();
 }
-
 }}}
 
-We will see that can do the same thing, and more, with the far less intrusive 
and hugely more flexible.  I add "Upload" to the class names in the following 
for purposes of ease of discussion.  (I realize that we might need a real 
wrapper for a request object, so I call the following code a "facade", which it 
is.  However, if a real wrapper is needed, to pass to the Action, which I don't 
think is a good idea, actually, then we can do so by including this class in 
that wrapper to get the values of the methods in our facade.
-
-==== SUGGESTED UploadMultipartFacade ====
+=== MultipartData ===
 
 {{{
-public interface UploadMultipartFacade {
+public interface MultipartData {
   public Iterator getParameterNames();
   public String   getParameter(String name);
   public String[] getParameterValues(String name);
@@ -153,146 +35,43 @@
 }
 }}}
 
-In addition to the flexibility, etc. of this interface, it also gives us what 
we wanted from such wrapper: the files! But, let's continue down the request 
processing chain in Struts v1.2.6.
-
-The next relevant code is in the processPopulate(...) method of 
!RequestProcessor.  Early on in processPopulate(...) we find the value of 
Globals.MULTIPART_KEY being set.  There is no need to do this so early, which 
just restricts options, and the reason might be that there is confusion about 
which class is covered by the key.  At any rate, shortly thereafter 
!RequestUtils' method populate(...) is called, and this is the first relevant 
code.  This is where, unfortunately, I think, the !ActionForm gets 
unnecessarily wedded to the !MultipartRequestWrapper and 
!MultipartRequestHandler.  The populate method has as parameters !ActionForm, 
String (mapping.getPrefix()), String (mapping getSuffix()), and 
!HttpServletRequest (which has been cast to !MultipartRequestWrapper but no 
state has been set in !MultipartRequestWrapper, so that is irrelevant.  The 
code is just what I call a "cuffudgal", which means generally that there is no 
particular rhyme or reason to where the code is placed.  This is not meant as a 
criticism of anyone, but only of the code.  Presumably code can be criticized 
without being uncivil?
-
-=== RequestUtils ===
-
-with the !RequestUtils populate(...) method, the Struts v1.2.6 upload 
application !MultipartRequestHandler enters the picture.  The populate method 
is:
+=== MultipartUtil ===
 
 {{{
-public static void populate(
-               Object bean,
-               String prefix,
-               String suffix,
-               HttpServletRequest request)
-               throws ServletException {
-  HashMap properties = new HashMap();
-  Enumeration names = null;
-  Map multipartParameters = null;
-
-  String contentType = request.getContentType();
-  String method = request.getMethod();
-  boolean isMultipart = false;
-
-  if ((contentType != null)
-       && (contentType.startsWith("multipart/form-data"))
-       && (method.equalsIgnoreCase("POST"))) {
-    ActionServletWrapper servlet;
-    if (bean instanceof ActionForm) {
-      servlet = ((ActionForm) bean).getServletWrapper();
-    } else {
-      throw new ServletException("bean that's supposed to be "
-                                       + "populated from a multipart request 
is not of type "
-                                       + 
"\"org.apache.struts.action.ActionForm\", but type "
-                                       + "\""
-                                       + bean.getClass().getName()
-                                       + "\"");
-    }
-    MultipartRequestHandler multipartHandler = getMultipartHandler(request);
-   (ActionForm) bean).setMultipartRequestHandler(multipartHandler);
-    if (multipartHandler != null) {
-      isMultipart = true;
-      servlet.setServletFor(multipartHandler);
-      multipartHandler.setMapping(
-        (ActionMapping) request.getAttribute(Globals.MAPPING_KEY));
-      multipartHandler.handleRequest(request);
-      Boolean maxLengthExceeded =
-        (Boolean) request.getAttribute(
-           MultipartRequestHandler.ATTRIBUTE_MAX_LENGTH_EXCEEDED);
-      if ((maxLengthExceeded != null) && (maxLengthExceeded.booleanValue())) {
-        return;
-      }
-      multipartParameters = getAllParametersForMultipartRequest(
-                                       request, multipartHandler);
-      names = Collections.enumeration(multipartParameters.keySet());
+public class MultipartUtil {
+  public  static final String MULTIPART_FORM_DATA = "multipart/form-data";
+  public  static final String CONTENT_TYPE        = "Content-Type";
+
+  public static boolean isMultipartFormData(HttpServletRequest req) {
+    String contentType        = null;
+    String headerContentType  = req.getHeader(CONTENT_TYPE);
+    String requestContentType = req.getContentType();
+
+    if(headerContentType == null && requestContentType != null) {
+      contentType = requestContentType;
+    } else if(requestContentType == null && headerContentType != null) {
+      contentType = headerContentType;
+    } else if(headerContentType != null && requestContentType != null) {
+      contentType = headerContentType.length() <= requestContentType.length() 
? requestContentType : headerContentType;
     }
-  }
-
-  if (!isMultipart) {
-    names = request.getParameterNames();
-  }
-
-  while (names.hasMoreElements()) {
-    String name = (String) names.nextElement();
-    String stripped = name;
-    if (prefix != null) {
-      if (!stripped.startsWith(prefix)) {
-        continue;
-      }
-      stripped = stripped.substring(prefix.length());
-    }
-    if (suffix != null) {
-      if (!stripped.endsWith(suffix)) {
-        continue;
-      }
-      stripped = stripped.substring(0, stripped.length() - suffix.length());
-    }
-    Object parameterValue = null;
-    if (isMultipart) {
-      parameterValue = multipartParameters.get(name);
-    } else {
-      parameterValue = request.getParameterValues(name);
-    }
-    if (!(stripped.startsWith("org.apache.struts."))) {
-      properties.put(stripped, parameterValue);
-    }
-  }
 
-  try {
-    BeanUtils.populate(bean, properties);
-  } catch(Exception e) {
-    throw new ServletException("BeanUtils.populate", e);
+    return contentType != null && 
contentType.toLowerCase().startsWith(MULTIPART_FORM_DATA);
   }
 }
 }}}
 
-
-The multipart request handler has the following code:
-
-==== EXISTING MultipartRequestHandler ====
-
-{{{
-public interface MultipartRequestHandler {
-  public static final String ATTRIBUTE_MAX_LENGTH_EXCEEDED = 
"org.apache.struts.upload.MaxLengthExceeded";
-  public void setServlet(ActionServlet servlet);
-  public void setMapping(ActionMapping mapping);
-  public ActionServlet getServlet();
-  public ActionMapping getMapping();
-  public void handleRequest(HttpServletRequest request) throws 
ServletException;
-  public Hashtable getTextElements();
-  public Hashtable getFileElements();
-}
-}}}
-
-With due respect and deference to whomever coded this handler, it does way too 
much.  What we need is a request handler that will handle the request and get 
what the multipart request wrapper needs to do its work.  All the rest just 
ties the class down in the middle of the framework.  These details should be in 
the application, if wanted, but not in the framework.  I would suggest, rather, 
the following interface:
-
-==== SUGGESTED UploadMultipartRequestHandler ====
+=== UploadMultipartData ===
 
 {{{
-public interface UploadMultipartRequestHandler {
-  public void handleRequest(Object [] params) throws IOException;
-}
-}}}
-
-The only params that the handleRequest(...) method "must" take are two maps: 
one for parameter names and one for files in the !UploadMultipartFacade.  The 
interface as defined allows one to create whatever other decorating params as 
one desires.  I do the following in my coding, which puts the maximum file 
size, encoding, and repository/store path into the mix and initializes a list 
of monitors/listeners as well as the maps of parameter names and files needed 
by the !UploadMultipartFacade:
-
-First the !UploadMultipartFacadeImpl and then the !MultipartRequestHandlerImpl:
-
-==== SUGGESTED UploadMultipartFacadeImpl ====
-
-{{{
-
-public class UploadMultipartFacadeImpl
-    implements UploadMultipartFacade {
+public class UploadMultipartData
+    implements MultipartData {
   private Map parameterNames;
   private Map files;
 
-  public UploadMultipartFacadeImpl(HttpServletRequest req,
-                                           List               monitors,
-                                           int                fileSizeLimit,
-                                           String             encoding)
+  public UploadMultipartData(HttpServletRequest req,
+                             List               monitors,
+                             int                fileSizeLimit,
+                             String             encoding)
       throws UploadException,
              IOException {
 
@@ -303,11 +82,15 @@
     parameterNames = Collections.synchronizedMap(new HashMap(89));
     files          = Collections.synchronizedMap(new HashMap(89));
 
-    UploadMultipartRequestHandler umrh = new 
UploadMultipartRequestHandlerImpl();
-
-    Object [] objects = new Object [] { req,monitors, new 
Integer(fileSizeLimit),parameterNames,files, UploadConstant.PARSER_TEMP_DIR, 
encoding };
+    MultipartRequestHandler handler = new UploadMultipartRequestHandler();
 
-    umrh.handleRequest(objects);
+    Object [] objects = new Object [] { req,monitors,
+                                        new Integer(fileSizeLimit),
+                                        parameterNames,
+                                        files,
+                                        UploadConstant.PARSER_TEMP_DIR,
+                                        encoding };
+    handler.handleRequest(objects);
   }
 
   public Iterator getParameterNames() {
@@ -338,14 +121,15 @@
 }
 }}}
 
-==== SUGGESTED UploadMultipartRequestHandlerImpl ====
+=== UploadMultipartRequestHandler ===
 
 {{{
+public class UploadMultipartRequestHandler
+    implements MultipartRequestHandler {
+  private ActionMapping mapping;
+  private ActionServlet servlet;
 
-public class UploadMultipartRequestHandlerImpl
-    implements UploadMultipartRequestHandler {
-
-  public UploadMultipartRequestHandlerImpl() {
+  public UploadMultipartRequestHandler() {
   }
 
   public void handleRequest(Object [] params)
@@ -372,21 +156,21 @@
     ufiFactory.setMonitors(monitors);
     ufiFactory.setCustom(req.getContentLength());
 
-    DiskFileUpload cdfu = new DiskFileUpload();
+    DiskFileUpload dfu = new DiskFileUpload();
 
-    cdfu.setFileItemFactory(ufiFactory);
-    cdfu.setSizeMax(maxFileSize);
-    cdfu.setSizeThreshold(UploadConstant.BUFFER_SIZE);
-    cdfu.setRepositoryPath(repositoryPath);
+    dfu.setFileItemFactory(ufiFactory);
+    dfu.setSizeMax(maxFileSize);
+    dfu.setSizeThreshold(UploadConstant.BUFFER_SIZE);
+    dfu.setRepositoryPath(repositoryPath);
 
     if(encoding != null) {
-      cdfu.setHeaderEncoding(encoding);
+      dfu.setHeaderEncoding(encoding);
     }
 
     List list = null;
 
     try {
-      list = cdfu.parseRequest(req);
+      list = dfu.parseRequest(req);
     } catch(FileUploadException cfue) {
       throw new IOException(cfue.getMessage());
     }
@@ -394,15 +178,15 @@
     Object obj = null;
 
     for(Iterator iterator = list.iterator(); iterator.hasNext();) {
-      FileItem cfi       = (FileItem)iterator.next();
-      String          fieldName = cfi.getFieldName();
+      FileItem fi       = (FileItem)iterator.next();
+      String          fieldName = fi.getFieldName();
 
-      if(cfi.isFormField()) {
+      if(fi.isFormField()) {
         String data = null;
         if(encoding != null) {
-          data = cfi.getString(encoding);
+          data = fi.getString(encoding);
         } else {
-          data = cfi.getString();
+          data = fi.getString();
         }
 
         List names = (List)parameterNames.get(fieldName);
@@ -414,9 +198,9 @@
 
         names.add(data);
       } else {
-        String name = cfi.getName();
+        String name = fi.getName();
         if(name != null) {
-          UploadFile fuuf = new UploadFileImpl(cfi);
+          FormFile uf = new UploadFormFile(fi);
           name = name.replace('\\', '/');
           int j = name.lastIndexOf("/");
 
@@ -424,302 +208,82 @@
             name = name.substring(j + 1, name.length());
           }
 
-          fuuf.setFileName(name);
-          fuuf.setContentType(cfi.getContentType());
-          fuuf.setFileSize(cfi.getSize());
-          files.put(fieldName, fuuf);
+          uf.setFileName(name);
+          uf.setFileContentType(fi.getContentType());
+          uf.setFileSize(fi.getSize());
+          files.put(fieldName, uf);
         }
       }
     }
   }
-}
-
-}}}
-
-Essentially, this way of coding the internals of the framework to service 
potential upload applications maximizes the potential for alternative 
implementations, etc.  
-
-I think this is a good place to stop, and to see if discussions are possible 
on this.  I have built and entire application, utilizing wrappers around 
commons fileupload classes, with the multipart facade and multipart request 
handler classes in my upload directory which can be discussed further, if there 
is any interest.
-
-My eyes are going buggy from reading this, so I will do a lot of the cleanup 
of typos later.  Any notes on those or anything else would be appreciated.
-
-Jack
-
-------
-
-The implementation of the !MultimpartRequestHandler in Strust upload is:
 
-{{{
-public class CommonsMultipartRequestHandler implements MultipartRequestHandler 
{
-  public static final long DEFAULT_SIZE_MAX = 250 * 1024 * 1024;
-  public static final int DEFAULT_SIZE_THRESHOLD = 256 * 1024;
-  protected static Log log = LogFactory.getLog(
-      CommonsMultipartRequestHandler.class);
-  private Hashtable elementsAll;
-  private Hashtable elementsFile;
-  private Hashtable elementsText;
-  private ActionMapping mapping;
-  private ActionServlet servlet;
-  
   public ActionServlet getServlet() {
     return this.servlet;
   }
-  
+
   public void setServlet(ActionServlet servlet) {
     this.servlet = servlet;
   }
-  
+
   public ActionMapping getMapping() {
     return this.mapping;
   }
-  
+
   public void setMapping(ActionMapping mapping) {
     this.mapping = mapping;
   }
-  
-  public void handleRequest(HttpServletRequest request)
-      throws ServletException {
-    ModuleConfig ac = (ModuleConfig) request.getAttribute(
-        Globals.MODULE_KEY);
-    DiskFileUpload upload = new DiskFileUpload();
-    upload.setHeaderEncoding(request.getCharacterEncoding());
-    upload.setSizeMax(getSizeMax(ac));
-    upload.setSizeThreshold((int) getSizeThreshold(ac));
-    upload.setRepositoryPath(getRepositoryPath(ac));
-    elementsText = new Hashtable();
-    elementsFile = new Hashtable();
-    elementsAll = new Hashtable();
-
+}
+}}}
 
-    List items = null;
-    try {
-      items = upload.parseRequest(request);
-    } catch (DiskFileUpload.SizeLimitExceededException e) {
-      request.setAttribute(
-          MultipartRequestHandler.ATTRIBUTE_MAX_LENGTH_EXCEEDED,
-          Boolean.TRUE);
-      return;
-    } catch (FileUploadException e) {
-      log.error("Failed to parse multipart request", e);
-      throw new ServletException(e);
-    }
-    
-    Iterator iter = items.iterator();
-    while (iter.hasNext()) {
-      FileItem item = (FileItem) iter.next();
 
-      if (item.isFormField()) {
-        addTextParameter(request, item);
-      } else {
-        addFileParameter(item);
-      }
-    }
-  }
-  
-  public Hashtable getTextElements() {
-    return this.elementsText;
-  }
-  
-  public Hashtable getFileElements() {
-    return this.elementsFile;
-  }
-  
-  public Hashtable getAllElements() {
-    return this.elementsAll;
-  }
-  
-  public void rollback() {
-    Iterator iter = elementsFile.values().iterator();
+=== FormFile ===
 
-    while (iter.hasNext()) {
-      FormFile formFile = (FormFile) iter.next();
+{{{
+public abstract class FormFile
+    implements Serializable {
+  private String fileContentType;
+  private String fileName;
+  private long   fileSize;
 
-      formFile.destroy();
-    }
-  }
-  
-  public void finish() {
-    rollback();
-  }
-  
-  protected long getSizeMax(ModuleConfig mc) {
-    return convertSizeToBytes(
-        mc.getControllerConfig().getMaxFileSize(),
-        DEFAULT_SIZE_MAX);
-  }
-  
-  protected long getSizeThreshold(ModuleConfig mc) {
-    return convertSizeToBytes(
-        mc.getControllerConfig().getMemFileSize(),
-        DEFAULT_SIZE_THRESHOLD);
-  }
-  
-  protected long convertSizeToBytes(String sizeString, long defaultSize) {
-    int multiplier = 1;
-
-    if (sizeString.endsWith("K")) {
-      multiplier = 1024;
-    } else if (sizeString.endsWith("M")) {
-      multiplier = 1024 * 1024;
-    } else if (sizeString.endsWith("G")) {
-      multiplier = 1024 * 1024 * 1024;
-    }
-    if (multiplier != 1) {
-      sizeString = sizeString.substring(0, sizeString.length() - 1);
-    }
-    
-    long size = 0;
-    try {
-      size = Long.parseLong(sizeString);
-    } catch (NumberFormatException nfe) {
-      log.warn("Invalid format for file size ('" + sizeString +
-          "'). Using default.");
-      size = defaultSize;
-      multiplier = 1;
-    }
-        
-    return (size * multiplier);
+  public FormFile(String fileName,
+                  String fileContentType,
+                  long   fileSize) {
+    this.fileSize        = -1L;
+    this.fileName        = fileName;
+    this.fileContentType = fileContentType;
+    this.fileSize        = fileSize;
   }
-  
-  protected String getRepositoryPath(ModuleConfig mc) {
-
-    // First, look for an explicitly defined temp dir.
-    String tempDir = mc.getControllerConfig().getTempDir();
-
-    // If none, look for a container specified temp dir.
-    if (tempDir == null || tempDir.length() == 0) {
-      if (servlet != null) {
-        ServletContext context = servlet.getServletContext();
-        File tempDirFile = (File) context.getAttribute(
-            "javax.servlet.context.tempdir");
-        tempDir = tempDirFile.getAbsolutePath();
-      }
-
-      // If none, pick up the system temp dir.
-      if (tempDir == null || tempDir.length() == 0) {
-        tempDir = System.getProperty("java.io.tmpdir");
-      }
-    }
 
-    if (log.isTraceEnabled()) {
-      log.trace("File upload temp dir: " + tempDir);
-    }
+  public FormFile() {
+    this(null, null, -1L);
+  }
 
-    return tempDir;
+  public long getFileSize() {
+    return fileSize;
   }
-  
-  protected void addTextParameter(HttpServletRequest request, FileItem item) {
-    String name = item.getFieldName();
-    String value = null;
-    boolean haveValue = false;
-    String encoding = request.getCharacterEncoding();
-
-    if (encoding != null) {
-      try {
-        value = item.getString(encoding);
-        haveValue = true;
-      } catch (Exception e) {
-        // Handled below, since haveValue is false.
-      }
-    }
-    if (!haveValue) {
-      try {
-         value = item.getString("ISO-8859-1");
-      } catch (java.io.UnsupportedEncodingException uee) {
-         value = item.getString();
-      }
-      haveValue = true;
-    }
 
-    if (request instanceof MultipartRequestWrapper) {
-      MultipartRequestWrapper wrapper = (MultipartRequestWrapper) request;
-      wrapper.setParameter(name, value);
-    }
+  public void setFileSize(long fileSize) {
+    this.fileSize = fileSize;
+  }
 
-    String[] oldArray = (String[]) elementsText.get(name);
-    String[] newArray;
+  public String getFileName() {
+    return fileName;
+  }
 
-    if (oldArray != null) {
-      newArray = new String[oldArray.length + 1];
-      System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
-      newArray[oldArray.length] = value;
-    } else {
-      newArray = new String[] { value };
-    }
+  public void setFileName(String fileName) {
+    this.fileName = fileName;
+  }
 
-    elementsText.put(name, newArray);
-    elementsAll.put(name, newArray);
+  public String getFileContentType() {
+    return fileContentType;
   }
-  
-  protected void addFileParameter(FileItem item) {
-    FormFile formFile = new CommonsFormFile(item);
-
-    elementsFile.put(item.getFieldName(), formFile);
-    elementsAll.put(item.getFieldName(), formFile);
-  }
-  
-  static class CommonsFormFile implements FormFile, Serializable {
-               FileItem fileItem;public CommonsFormFile(FileItem fileItem) {
-      this.fileItem = fileItem;
-    }
-    
-    public String getContentType() {
-      return fileItem.getContentType();
-    }
-    
-    public void setContentType(String contentType) {
-      throw new UnsupportedOperationException(
-          "The setContentType() method is not supported.");
-    }
-    
-    public int getFileSize() {
-      return (int)fileItem.getSize();
-    }
-    
-    public void setFileSize(int filesize) {
-      throw new UnsupportedOperationException(
-          "The setFileSize() method is not supported.");
-    }
-    
-    public String getFileName() {
-      return getBaseFileName(fileItem.getName());
-    }
-    
-    public void setFileName(String fileName) {
-      throw new UnsupportedOperationException(
-          "The setFileName() method is not supported.");
-    }
-    
-    public byte[] getFileData() throws FileNotFoundException, IOException {
-      return fileItem.get();
-    }
-    
-    public InputStream getInputStream() throws FileNotFoundException, 
IOException {
-      return fileItem.getInputStream();
-    }
-    
-    public void destroy() {
-      fileItem.delete();
-    }
-    
-    protected String getBaseFileName(String filePath) {
-      String fileName = new File(filePath).getName();
-      int colonIndex = fileName.indexOf(":");
-      if (colonIndex == -1) {
-        colonIndex = fileName.indexOf("\\\\");
-      }
-      int backslashIndex = fileName.lastIndexOf("\\");
 
-      if (colonIndex > -1 && backslashIndex > -1) {
-        fileName = fileName.substring(backslashIndex + 1);
-      }
-      return fileName;
-    }
-    
-    public String toString() {
-      return getFileName();
-    }
+  public void setFileContentType(String fileContentType) {
+    this.fileContentType = fileContentType;
   }
+
+  public abstract byte[]      getFileData();
+  public abstract InputStream getFileInputStream();
+  public abstract void        reset();
 }
 }}}
-
------

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to