You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2006/06/08 17:35:58 UTC

svn commit: r412780 [4/5] - in /tomcat/tc6.0.x/trunk/java/org/apache: catalina/manager/ catalina/manager/host/ tomcat/util/http/fileupload/

Added: tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/host/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/host/LocalStrings.properties?rev=412780&view=auto
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/host/LocalStrings.properties (added)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/host/LocalStrings.properties Thu Jun  8 08:35:56 2006
@@ -0,0 +1,59 @@
+hostManagerServlet.cannotInvoke=Cannot invoke host manager servlet through invoker
+hostManagerServlet.noCommand=FAIL - No command was specified
+hostManagerServlet.unknownCommand=FAIL - Unknown command {0}
+hostManagerServlet.noWrapper=Container has not called setWrapper() for this servlet
+hostManagerServlet.invalidHostName=FAIL - Invalid host name {0} was specified
+hostManagerServlet.alreadyHost=FAIL - Host already exists with host name {0}
+hostManagerServlet.managerXml=FAIL - Couldn't install manager.xml
+hostManagerServlet.exception=FAIL - Encountered exception {0}
+hostManagerServlet.add=OK - Host {0} added
+hostManagerServlet.addFailed=FAIL - Failed to add host {0}
+hostManagerServlet.cannotRemoveOwnHost=FAIL - Cannot remove own host {0}
+hostManagerServlet.remove=OK - Removed host {0}
+hostManagerServlet.removeFailed=FAIL - Failed to remove host {0}
+hostManagerServlet.listed=OK - Listed hosts
+hostManagerServlet.listitem={0}:{1}
+hostManagerServlet.cannotStartOwnHost=FAIL - Cannot start own host {0}
+hostManagerServlet.started=OK - Host {0} started
+hostManagerServlet.startFailed=FAIL - Failed to start host {0}
+hostManagerServlet.cannotStopOwnHost=FAIL - Cannot stop own host {0}
+hostManagerServlet.stopped=OK - Host {0} stopped
+hostManagerServlet.stopFailed=FAIL - Failed to stop host {0}
+
+htmlHostManagerServlet.title=Tomcat Virtual Host Manager
+htmlHostManagerServlet.messageLabel=Message:
+htmlHostManagerServlet.manager=Host Manager
+htmlHostManagerServlet.list=List Virtual Hosts
+htmlHostManagerServlet.helpHtmlManagerFile=html-host-manager-howto.html
+htmlHostManagerServlet.helpHtmlManager=HTML Host Manager Help (Coming Soon!)
+htmlHostManagerServlet.helpManagerFile=host-manager-howto.html
+htmlHostManagerServlet.helpManager=Host Manager Help
+htmlHostManagerServlet.hostName=Host name
+htmlHostManagerServlet.hostAliases=Host aliases
+htmlHostManagerServlet.hostTasks=Commands
+htmlHostManagerServlet.hostsStart=Start
+htmlHostManagerServlet.hostsStop=Stop
+htmlHostManagerServlet.hostsRemove=Remove
+htmlHostManagerServlet.addTitle=Add Virtual Host
+htmlHostManagerServlet.addHost=Host
+htmlHostManagerServlet.addName=Name:
+htmlHostManagerServlet.addAliases=Aliases:
+htmlHostManagerServlet.addAppBase=App base:
+htmlHostManagerServlet.addManager=Manager App
+htmlHostManagerServlet.addAutoDeploy=AutoDeploy
+htmlHostManagerServlet.addDeployOnStartup=DeployOnStartup
+htmlHostManagerServlet.addDeployXML=DeployXML
+htmlHostManagerServlet.addUnpackWARs=UnpackWARs
+htmlHostManagerServlet.addXmlNamespaceAware=XmlNamespaceAware
+htmlHostManagerServlet.addXmlValidation=XmlValidation
+htmlHostManagerServlet.addButton=Add
+htmlHostManagerServlet.serverTitle=Server Information
+htmlHostManagerServlet.serverVersion=Tomcat Version
+htmlHostManagerServlet.serverJVMVersion=JVM Version
+htmlHostManagerServlet.serverJVMVendor=JVM Vendor
+htmlHostManagerServlet.serverOSName=OS Name
+htmlHostManagerServlet.serverOSVersion=OS Version
+htmlHostManagerServlet.serverOSArch=OS Architecture
+
+statusServlet.title=Server Status
+statusServlet.complete=Complete Server Status

Propchange: tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/host/LocalStrings.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DefaultFileItem.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DefaultFileItem.java?rev=412780&view=auto
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DefaultFileItem.java (added)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DefaultFileItem.java Thu Jun  8 08:35:56 2006
@@ -0,0 +1,607 @@
+/*
+ * Copyright 2001-2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.tomcat.util.http.fileupload;
+
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+
+/**
+ * <p> The default implementation of the
+ * {@link org.apache.tomcat.util.http.fileupload.FileItem FileItem} interface.
+ *
+ * <p> After retrieving an instance of this class from a {@link
+ * org.apache.tomcat.util.http.fileupload.DiskFileUpload DiskFileUpload} instance (see
+ * {@link org.apache.tomcat.util.http.fileupload.DiskFileUpload
+ * #parseRequest(javax.servlet.http.HttpServletRequest)}), you may
+ * either request all contents of file at once using {@link #get()} or
+ * request an {@link java.io.InputStream InputStream} with
+ * {@link #getInputStream()} and process the file without attempting to load
+ * it into memory, which may come handy with large files.
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:sean@informage.net">Sean Legassick</a>
+ * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:jmcnally@apache.org">John McNally</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ * @author Sean C. Sullivan
+ *
+ * @version $Id: DefaultFileItem.java,v 1.21 2003/06/24 05:45:15 martinc Exp $
+ */
+public class DefaultFileItem
+    implements FileItem
+{
+
+    // ----------------------------------------------------------- Data members
+
+
+    /**
+     * Counter used in unique identifier generation.
+     */
+    private static int counter = 0;
+
+
+    /**
+     * The name of the form field as provided by the browser.
+     */
+    private String fieldName;
+
+
+    /**
+     * The content type passed by the browser, or <code>null</code> if
+     * not defined.
+     */
+    private String contentType;
+
+
+    /**
+     * Whether or not this item is a simple form field.
+     */
+    private boolean isFormField;
+
+
+    /**
+     * The original filename in the user's filesystem.
+     */
+    private String fileName;
+
+
+    /**
+     * The threshold above which uploads will be stored on disk.
+     */
+    private int sizeThreshold;
+
+
+    /**
+     * The directory in which uploaded files will be stored, if stored on disk.
+     */
+    private File repository;
+
+
+    /**
+     * Cached contents of the file.
+     */
+    private byte[] cachedContent;
+
+
+    /**
+     * Output stream for this item.
+     */
+    private DeferredFileOutputStream dfos;
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Constructs a new <code>DefaultFileItem</code> instance.
+     *
+     * @param fieldName     The name of the form field.
+     * @param contentType   The content type passed by the browser or
+     *                      <code>null</code> if not specified.
+     * @param isFormField   Whether or not this item is a plain form field, as
+     *                      opposed to a file upload.
+     * @param fileName      The original filename in the user's filesystem, or
+     *                      <code>null</code> if not specified.
+     * @param sizeThreshold The threshold, in bytes, below which items will be
+     *                      retained in memory and above which they will be
+     *                      stored as a file.
+     * @param repository    The data repository, which is the directory in
+     *                      which files will be created, should the item size
+     *                      exceed the threshold.
+     */
+    DefaultFileItem(String fieldName, String contentType, boolean isFormField,
+                    String fileName, int sizeThreshold, File repository)
+    {
+        this.fieldName = fieldName;
+        this.contentType = contentType;
+        this.isFormField = isFormField;
+        this.fileName = fileName;
+        this.sizeThreshold = sizeThreshold;
+        this.repository = repository;
+    }
+
+
+    // ------------------------------- Methods from javax.activation.DataSource
+
+
+    /**
+     * Returns an {@link java.io.InputStream InputStream} that can be
+     * used to retrieve the contents of the file.
+     *
+     * @return An {@link java.io.InputStream InputStream} that can be
+     *         used to retrieve the contents of the file.
+     *
+     * @exception IOException if an error occurs.
+     */
+    public InputStream getInputStream()
+        throws IOException
+    {
+        if (!dfos.isInMemory())
+        {
+            return new FileInputStream(dfos.getFile());
+        }
+
+        if (cachedContent == null)
+        {
+            cachedContent = dfos.getData();
+        }
+        return new ByteArrayInputStream(cachedContent);
+    }
+
+
+    /**
+     * Returns the content type passed by the browser or <code>null</code> if
+     * not defined.
+     *
+     * @return The content type passed by the browser or <code>null</code> if
+     *         not defined.
+     */
+    public String getContentType()
+    {
+        return contentType;
+    }
+
+
+    /**
+     * Returns the original filename in the client's filesystem.
+     *
+     * @return The original filename in the client's filesystem.
+     */
+    public String getName()
+    {
+        return fileName;
+    }
+
+
+    // ------------------------------------------------------- FileItem methods
+
+
+    /**
+     * Provides a hint as to whether or not the file contents will be read
+     * from memory.
+     *
+     * @return <code>true</code> if the file contents will be read
+     *         from memory; <code>false</code> otherwise.
+     */
+    public boolean isInMemory()
+    {
+        return (dfos.isInMemory());
+    }
+
+
+    /**
+     * Returns the size of the file.
+     *
+     * @return The size of the file, in bytes.
+     */
+    public long getSize()
+    {
+        if (cachedContent != null)
+        {
+            return cachedContent.length;
+        }
+        else if (dfos.isInMemory())
+        {
+            return dfos.getData().length;
+        }
+        else
+        {
+            return dfos.getFile().length();
+        }
+    }
+
+
+    /**
+     * Returns the contents of the file as an array of bytes.  If the
+     * contents of the file were not yet cached in memory, they will be
+     * loaded from the disk storage and cached.
+     *
+     * @return The contents of the file as an array of bytes.
+     */
+    public byte[] get()
+    {
+        if (dfos.isInMemory())
+        {
+            if (cachedContent == null)
+            {
+                cachedContent = dfos.getData();
+            }
+            return cachedContent;
+        }
+
+        byte[] fileData = new byte[(int) getSize()];
+        FileInputStream fis = null;
+
+        try
+        {
+            fis = new FileInputStream(dfos.getFile());
+            fis.read(fileData);
+        }
+        catch (IOException e)
+        {
+            fileData = null;
+        }
+        finally
+        {
+            if (fis != null)
+            {
+                try
+                {
+                    fis.close();
+                }
+                catch (IOException e)
+                {
+                    // ignore
+                }
+            }
+        }
+
+        return fileData;
+    }
+
+
+    /**
+     * Returns the contents of the file as a String, using the specified
+     * encoding.  This method uses {@link #get()} to retrieve the
+     * contents of the file.
+     *
+     * @param encoding The character encoding to use.
+     *
+     * @return The contents of the file, as a string.
+     *
+     * @exception UnsupportedEncodingException if the requested character
+     *                                         encoding is not available.
+     */
+    public String getString(String encoding)
+        throws UnsupportedEncodingException
+    {
+        return new String(get(), encoding);
+    }
+
+
+    /**
+     * Returns the contents of the file as a String, using the default
+     * character encoding.  This method uses {@link #get()} to retrieve the
+     * contents of the file.
+     *
+     * @return The contents of the file, as a string.
+     */
+    public String getString()
+    {
+        return new String(get());
+    }
+
+
+    /**
+     * A convenience method to write an uploaded item to disk. The client code
+     * is not concerned with whether or not the item is stored in memory, or on
+     * disk in a temporary location. They just want to write the uploaded item
+     * to a file.
+     * <p>
+     * This implementation first attempts to rename the uploaded item to the
+     * specified destination file, if the item was originally written to disk.
+     * Otherwise, the data will be copied to the specified file.
+     * <p>
+     * This method is only guaranteed to work <em>once</em>, the first time it
+     * is invoked for a particular item. This is because, in the event that the
+     * method renames a temporary file, that file will no longer be available
+     * to copy or rename again at a later time.
+     *
+     * @param file The <code>File</code> into which the uploaded item should
+     *             be stored.
+     *
+     * @exception Exception if an error occurs.
+     */
+    public void write(File file) throws Exception
+    {
+        if (isInMemory())
+        {
+            FileOutputStream fout = null;
+            try
+            {
+                fout = new FileOutputStream(file);
+                fout.write(get());
+            }
+            finally
+            {
+                if (fout != null)
+                {
+                    fout.close();
+                }
+            }
+        }
+        else
+        {
+            File outputFile = getStoreLocation();
+            if (outputFile != null)
+            {
+                /*
+                 * The uploaded file is being stored on disk
+                 * in a temporary location so move it to the
+                 * desired file.
+                 */
+                if (!outputFile.renameTo(file))
+                {
+                    BufferedInputStream in = null;
+                    BufferedOutputStream out = null;
+                    try
+                    {
+                        in = new BufferedInputStream(
+                            new FileInputStream(outputFile));
+                        out = new BufferedOutputStream(
+                                new FileOutputStream(file));
+                        byte[] bytes = new byte[2048];
+                        int s = 0;
+                        while ((s = in.read(bytes)) != -1)
+                        {
+                            out.write(bytes, 0, s);
+                        }
+                    }
+                    finally
+                    {
+                        try
+                        {
+                            in.close();
+                        }
+                        catch (IOException e)
+                        {
+                            // ignore
+                        }
+                        try
+                        {
+                            out.close();
+                        }
+                        catch (IOException e)
+                        {
+                            // ignore
+                        }
+                    }
+                }
+            }
+            else
+            {
+                /*
+                 * For whatever reason we cannot write the
+                 * file to disk.
+                 */
+                throw new FileUploadException(
+                    "Cannot write uploaded file to disk!");
+            }
+        }
+    }
+
+
+    /**
+     * Deletes the underlying storage for a file item, including deleting any
+     * associated temporary disk file. Although this storage will be deleted
+     * automatically when the <code>FileItem</code> instance is garbage
+     * collected, this method can be used to ensure that this is done at an
+     * earlier time, thus preserving system resources.
+     */
+    public void delete()
+    {
+        cachedContent = null;
+        File outputFile = getStoreLocation();
+        if (outputFile != null && outputFile.exists())
+        {
+            outputFile.delete();
+        }
+    }
+
+
+    /**
+     * Returns the name of the field in the multipart form corresponding to
+     * this file item.
+     *
+     * @return The name of the form field.
+     *
+     * @see #setFieldName(java.lang.String)
+     *
+     */
+    public String getFieldName()
+    {
+        return fieldName;
+    }
+
+
+    /**
+     * Sets the field name used to reference this file item.
+     *
+     * @param fieldName The name of the form field.
+     *
+     * @see #getFieldName()
+     *
+     */
+    public void setFieldName(String fieldName)
+    {
+        this.fieldName = fieldName;
+    }
+
+
+    /**
+     * Determines whether or not a <code>FileItem</code> instance represents
+     * a simple form field.
+     *
+     * @return <code>true</code> if the instance represents a simple form
+     *         field; <code>false</code> if it represents an uploaded file.
+     *
+     * @see #setFormField(boolean)
+     *
+     */
+    public boolean isFormField()
+    {
+        return isFormField;
+    }
+
+
+    /**
+     * Specifies whether or not a <code>FileItem</code> instance represents
+     * a simple form field.
+     *
+     * @param state <code>true</code> if the instance represents a simple form
+     *              field; <code>false</code> if it represents an uploaded file.
+     *
+     * @see #isFormField()
+     *
+     */
+    public void setFormField(boolean state)
+    {
+        isFormField = state;
+    }
+
+
+    /**
+     * Returns an {@link java.io.OutputStream OutputStream} that can
+     * be used for storing the contents of the file.
+     *
+     * @return An {@link java.io.OutputStream OutputStream} that can be used
+     *         for storing the contensts of the file.
+     *
+     * @exception IOException if an error occurs.
+     */
+    public OutputStream getOutputStream()
+        throws IOException
+    {
+        if (dfos == null)
+        {
+            File outputFile = getTempFile();
+            dfos = new DeferredFileOutputStream(sizeThreshold, outputFile);
+        }
+        return dfos;
+    }
+
+
+    // --------------------------------------------------------- Public methods
+
+
+    /**
+     * Returns the {@link java.io.File} object for the <code>FileItem</code>'s
+     * data's temporary location on the disk. Note that for
+     * <code>FileItem</code>s that have their data stored in memory,
+     * this method will return <code>null</code>. When handling large
+     * files, you can use {@link java.io.File#renameTo(java.io.File)} to
+     * move the file to new location without copying the data, if the
+     * source and destination locations reside within the same logical
+     * volume.
+     *
+     * @return The data file, or <code>null</code> if the data is stored in
+     *         memory.
+     */
+    public File getStoreLocation()
+    {
+        return dfos.getFile();
+    }
+
+
+    // ------------------------------------------------------ Protected methods
+
+
+    /**
+     * Removes the file contents from the temporary storage.
+     */
+    protected void finalize()
+    {
+        File outputFile = dfos.getFile();
+
+        if (outputFile != null && outputFile.exists())
+        {
+            outputFile.delete();
+        }
+    }
+
+
+    /**
+     * Creates and returns a {@link java.io.File File} representing a uniquely
+     * named temporary file in the configured repository path.
+     *
+     * @return The {@link java.io.File File} to be used for temporary storage.
+     */
+    protected File getTempFile()
+    {
+        File tempDir = repository;
+        if (tempDir == null)
+        {
+            tempDir = new File(System.getProperty("java.io.tmpdir"));
+        }
+
+        String fileName = "upload_" + getUniqueId() + ".tmp";
+
+        File f = new File(tempDir, fileName);
+        f.deleteOnExit();
+        return f;
+    }
+
+
+    // -------------------------------------------------------- Private methods
+
+
+    /**
+     * Returns an identifier that is unique within the class loader used to
+     * load this class, but does not have random-like apearance.
+     *
+     * @return A String with the non-random looking instance identifier.
+     */
+    private static String getUniqueId()
+    {
+        int current;
+        synchronized (DefaultFileItem.class)
+        {
+            current = counter++;
+        }
+        String id = Integer.toString(current);
+
+        // If you manage to get more than 100 million of ids, you'll
+        // start getting ids longer than 8 characters.
+        if (current < 100000000)
+        {
+            id = ("00000000" + id).substring(id.length());
+        }
+        return id;
+    }
+
+}

Propchange: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DefaultFileItem.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DefaultFileItemFactory.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DefaultFileItemFactory.java?rev=412780&view=auto
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DefaultFileItemFactory.java (added)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DefaultFileItemFactory.java Thu Jun  8 08:35:56 2006
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2001-2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.tomcat.util.http.fileupload;
+
+import java.io.File;
+
+
+/**
+ * <p>The default {@link org.apache.tomcat.util.http.fileupload.FileItemFactory}
+ * implementation. This implementation creates
+ * {@link org.apache.tomcat.util.http.fileupload.FileItem} instances which keep their
+ * content either in memory, for smaller items, or in a temporary file on disk,
+ * for larger items. The size threshold, above which content will be stored on
+ * disk, is configurable, as is the directory in which temporary files will be
+ * created.</p>
+ *
+ * <p>If not otherwise configured, the default configuration values are as
+ * follows:
+ * <ul>
+ *   <li>Size threshold is 10KB.</li>
+ *   <li>Repository is the system default temp directory, as returned by
+ *       <code>System.getProperty("java.io.tmpdir")</code>.</li>
+ * </ul>
+ * </p>
+ *
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ *
+ * @version $Id: DefaultFileItemFactory.java,v 1.2 2003/05/31 22:31:08 martinc Exp $
+ */
+public class DefaultFileItemFactory implements FileItemFactory
+{
+
+    // ----------------------------------------------------- Manifest constants
+
+
+    /**
+     * The default threshold above which uploads will be stored on disk.
+     */
+    public static final int DEFAULT_SIZE_THRESHOLD = 10240;
+
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The directory in which uploaded files will be stored, if stored on disk.
+     */
+    private File repository;
+
+
+    /**
+     * The threshold above which uploads will be stored on disk.
+     */
+    private int sizeThreshold = DEFAULT_SIZE_THRESHOLD;
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Constructs an unconfigured instance of this class. The resulting factory
+     * may be configured by calling the appropriate setter methods.
+     */
+    public DefaultFileItemFactory()
+    {
+    }
+
+
+    /**
+     * Constructs a preconfigured instance of this class.
+     *
+     * @param sizeThreshold The threshold, in bytes, below which items will be
+     *                      retained in memory and above which they will be
+     *                      stored as a file.
+     * @param repository    The data repository, which is the directory in
+     *                      which files will be created, should the item size
+     *                      exceed the threshold.
+     */
+    public DefaultFileItemFactory(int sizeThreshold, File repository)
+    {
+        this.sizeThreshold = sizeThreshold;
+        this.repository = repository;
+    }
+
+
+    // ------------------------------------------------------------- Properties
+
+
+    /**
+     * Returns the directory used to temporarily store files that are larger
+     * than the configured size threshold.
+     *
+     * @return The directory in which temporary files will be located.
+     *
+     * @see #setRepository(java.io.File)
+     *
+     */
+    public File getRepository()
+    {
+        return repository;
+    }
+
+
+    /**
+     * Sets the directory used to temporarily store files that are larger
+     * than the configured size threshold.
+     *
+     * @param repository The directory in which temporary files will be located.
+     *
+     * @see #getRepository()
+     *
+     */
+    public void setRepository(File repository)
+    {
+        this.repository = repository;
+    }
+
+
+    /**
+     * Returns the size threshold beyond which files are written directly to
+     * disk. The default value is 1024 bytes.
+     *
+     * @return The size threshold, in bytes.
+     *
+     * @see #setSizeThreshold(int)
+     */
+    public int getSizeThreshold()
+    {
+        return sizeThreshold;
+    }
+
+
+    /**
+     * Sets the size threshold beyond which files are written directly to disk.
+     *
+     * @param sizeThreshold The size threshold, in bytes.
+     *
+     * @see #getSizeThreshold()
+     *
+     */
+    public void setSizeThreshold(int sizeThreshold)
+    {
+        this.sizeThreshold = sizeThreshold;
+    }
+
+
+    // --------------------------------------------------------- Public Methods
+
+    /**
+     * Create a new {@link org.apache.tomcat.util.http.fileupload.DefaultFileItem}
+     * instance from the supplied parameters and the local factory
+     * configuration.
+     *
+     * @param fieldName   The name of the form field.
+     * @param contentType The content type of the form field.
+     * @param isFormField <code>true</code> if this is a plain form field;
+     *                    <code>false</code> otherwise.
+     * @param fileName    The name of the uploaded file, if any, as supplied
+     *                    by the browser or other client.
+     *
+     * @return The newly created file item.
+     */
+    public FileItem createItem(
+            String fieldName,
+            String contentType,
+            boolean isFormField,
+            String fileName
+            )
+    {
+        return new DefaultFileItem(fieldName, contentType,
+                isFormField, fileName, sizeThreshold, repository);
+    }
+
+}

Propchange: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DefaultFileItemFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DeferredFileOutputStream.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DeferredFileOutputStream.java?rev=412780&view=auto
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DeferredFileOutputStream.java (added)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DeferredFileOutputStream.java Thu Jun  8 08:35:56 2006
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2001-2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.tomcat.util.http.fileupload;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * <p>An output stream which will retain data in memory until a specified
+ * threshold is reached, and only then commit it to disk. If the stream is
+ * closed before the threshold is reached, the data will not be written to
+ * disk at all.</p>
+ *
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ *
+ * @version $Id: DeferredFileOutputStream.java,v 1.2 2003/05/31 22:31:08 martinc Exp $
+ */
+public class DeferredFileOutputStream
+    extends ThresholdingOutputStream
+{
+
+    // ----------------------------------------------------------- Data members
+
+
+    /**
+     * The output stream to which data will be written prior to the theshold
+     * being reached.
+     */
+    private ByteArrayOutputStream memoryOutputStream;
+
+
+    /**
+     * The output stream to which data will be written after the theshold is
+     * reached.
+     */
+    private FileOutputStream diskOutputStream;
+
+
+    /**
+     * The output stream to which data will be written at any given time. This
+     * will always be one of <code>memoryOutputStream</code> or
+     * <code>diskOutputStream</code>.
+     */
+    private OutputStream currentOutputStream;
+
+
+    /**
+     * The file to which output will be directed if the threshold is exceeded.
+     */
+    private File outputFile;
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Constructs an instance of this class which will trigger an event at the
+     * specified threshold, and save data to a file beyond that point.
+     *
+     * @param threshold  The number of bytes at which to trigger an event.
+     * @param outputFile The file to which data is saved beyond the threshold.
+     */
+    public DeferredFileOutputStream(int threshold, File outputFile)
+    {
+        super(threshold);
+        this.outputFile = outputFile;
+
+        memoryOutputStream = new ByteArrayOutputStream(threshold);
+        currentOutputStream = memoryOutputStream;
+    }
+
+
+    // --------------------------------------- ThresholdingOutputStream methods
+
+
+    /**
+     * Returns the current output stream. This may be memory based or disk
+     * based, depending on the current state with respect to the threshold.
+     *
+     * @return The underlying output stream.
+     *
+     * @exception IOException if an error occurs.
+     */
+    protected OutputStream getStream() throws IOException
+    {
+        return currentOutputStream;
+    }
+
+
+    /**
+     * Switches the underlying output stream from a memory based stream to one
+     * that is backed by disk. This is the point at which we realise that too
+     * much data is being written to keep in memory, so we elect to switch to
+     * disk-based storage.
+     *
+     * @exception IOException if an error occurs.
+     */
+    protected void thresholdReached() throws IOException
+    {
+        byte[] data = memoryOutputStream.toByteArray();
+        FileOutputStream fos = new FileOutputStream(outputFile);
+        fos.write(data);
+        diskOutputStream = fos;
+        currentOutputStream = fos;
+        memoryOutputStream = null;
+    }
+
+
+    // --------------------------------------------------------- Public methods
+
+
+    /**
+     * Determines whether or not the data for this output stream has been
+     * retained in memory.
+     *
+     * @return <code>true</code> if the data is available in memory;
+     *         <code>false</code> otherwise.
+     */
+    public boolean isInMemory()
+    {
+        return (!isThresholdExceeded());
+    }
+
+
+    /**
+     * Returns the data for this output stream as an array of bytes, assuming
+     * that the data has been retained in memory. If the data was written to
+     * disk, this method returns <code>null</code>.
+     *
+     * @return The data for this output stream, or <code>null</code> if no such
+     *         data is available.
+     */
+    public byte[] getData()
+    {
+        if (memoryOutputStream != null)
+        {
+            return memoryOutputStream.toByteArray();
+        }
+        return null;
+    }
+
+
+    /**
+     * Returns the data for this output stream as a <code>File</code>, assuming
+     * that the data was written to disk. If the data was retained in memory,
+     * this method returns <code>null</code>.
+     *
+     * @return The file for this output stream, or <code>null</code> if no such
+     *         file exists.
+     */
+    public File getFile()
+    {
+        return outputFile;
+    }
+}

Propchange: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DeferredFileOutputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DiskFileUpload.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DiskFileUpload.java?rev=412780&view=auto
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DiskFileUpload.java (added)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DiskFileUpload.java Thu Jun  8 08:35:56 2006
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2001-2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.tomcat.util.http.fileupload;
+
+
+import java.io.File;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+
+
+/**
+ * <p>High level API for processing file uploads.</p>
+ *
+ * <p>This class handles multiple files per single HTML widget, sent using
+ * <code>multipart/mixed</code> encoding type, as specified by
+ * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>.  Use {@link
+ * #parseRequest(HttpServletRequest)} to acquire a list of {@link
+ * org.apache.tomcat.util.http.fileupload.FileItem}s associated with a given HTML
+ * widget.</p>
+ *
+ * <p>Individual parts will be stored in temporary disk storage or in memory,
+ * depending on their size, and will be available as {@link
+ * org.apache.tomcat.util.http.fileupload.FileItem}s.</p>
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ * @author Sean C. Sullivan
+ *
+ * @version $Id: DiskFileUpload.java,v 1.3 2003/06/01 00:18:13 martinc Exp $
+ */
+public class DiskFileUpload
+    extends FileUploadBase
+ {
+
+    // ----------------------------------------------------------- Data members
+
+
+    /**
+     * The factory to use to create new form items.
+     */
+    private DefaultFileItemFactory fileItemFactory;
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Constructs an instance of this class which uses the default factory to
+     * create <code>FileItem</code> instances.
+     *
+     * @see #DiskFileUpload(DefaultFileItemFactory fileItemFactory)
+     */
+    public DiskFileUpload()
+    {
+        super();
+        this.fileItemFactory = new DefaultFileItemFactory();
+    }
+
+
+    /**
+     * Constructs an instance of this class which uses the supplied factory to
+     * create <code>FileItem</code> instances.
+     *
+     * @see #DiskFileUpload()
+     */
+    public DiskFileUpload(DefaultFileItemFactory fileItemFactory)
+    {
+        super();
+        this.fileItemFactory = fileItemFactory;
+    }
+
+
+    // ----------------------------------------------------- Property accessors
+
+
+    /**
+     * Returns the factory class used when creating file items.
+     *
+     * @return The factory class for new file items.
+     */
+    public FileItemFactory getFileItemFactory()
+    {
+        return fileItemFactory;
+    }
+
+
+    /**
+     * Sets the factory class to use when creating file items. The factory must
+     * be an instance of <code>DefaultFileItemFactory</code> or a subclass
+     * thereof, or else a <code>ClassCastException</code> will be thrown.
+     *
+     * @param factory The factory class for new file items.
+     */
+    public void setFileItemFactory(FileItemFactory factory)
+    {
+        this.fileItemFactory = (DefaultFileItemFactory) factory;
+    }
+
+
+    /**
+     * Returns the size threshold beyond which files are written directly to
+     * disk.
+     *
+     * @return The size threshold, in bytes.
+     *
+     * @see #setSizeThreshold(int)
+     */
+    public int getSizeThreshold()
+    {
+        return fileItemFactory.getSizeThreshold();
+    }
+
+
+    /**
+     * Sets the size threshold beyond which files are written directly to disk.
+     *
+     * @param sizeThreshold The size threshold, in bytes.
+     *
+     * @see #getSizeThreshold()
+     */
+    public void setSizeThreshold(int sizeThreshold)
+    {
+        fileItemFactory.setSizeThreshold(sizeThreshold);
+    }
+
+
+    /**
+     * Returns the location used to temporarily store files that are larger
+     * than the configured size threshold.
+     *
+     * @return The path to the temporary file location.
+     *
+     * @see #setRepositoryPath(String)
+     */
+    public String getRepositoryPath()
+    {
+        return fileItemFactory.getRepository().getPath();
+    }
+
+
+    /**
+     * Sets the location used to temporarily store files that are larger
+     * than the configured size threshold.
+     *
+     * @param repositoryPath The path to the temporary file location.
+     *
+     * @see #getRepositoryPath()
+     */
+    public void setRepositoryPath(String repositoryPath)
+    {
+        fileItemFactory.setRepository(new File(repositoryPath));
+    }
+
+
+    // --------------------------------------------------------- Public methods
+
+
+    /**
+     * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
+     * compliant <code>multipart/form-data</code> stream. If files are stored
+     * on disk, the path is given by <code>getRepository()</code>.
+     *
+     * @param req           The servlet request to be parsed. Must be non-null.
+     * @param sizeThreshold The max size in bytes to be stored in memory.
+     * @param sizeMax       The maximum allowed upload size, in bytes.
+     * @param path          The location where the files should be stored.
+     *
+     * @return A list of <code>FileItem</code> instances parsed from the
+     *         request, in the order that they were transmitted.
+     *
+     * @exception FileUploadException if there are problems reading/parsing
+     *                                the request or storing files.
+     */
+    public List /* FileItem */ parseRequest(HttpServletRequest req,
+                                            int sizeThreshold,
+                                            long sizeMax, String path)
+        throws FileUploadException
+    {
+        setSizeThreshold(sizeThreshold);
+        setSizeMax(sizeMax);
+        setRepositoryPath(path);
+        return parseRequest(req);
+    }
+
+}

Propchange: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/DiskFileUpload.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileItem.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileItem.java?rev=412780&view=auto
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileItem.java (added)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileItem.java Thu Jun  8 08:35:56 2006
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2001-2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.tomcat.util.http.fileupload;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+
+
+/**
+ * <p> This class represents a file or form item that was received within a
+ * <code>multipart/form-data</code> POST request.
+ *
+ * <p> After retrieving an instance of this class from a {@link
+ * org.apache.tomcat.util.http.fileupload.FileUpload FileUpload} instance (see
+ * {@link org.apache.tomcat.util.http.fileupload.FileUpload
+ * #parseRequest(javax.servlet.http.HttpServletRequest)}), you may
+ * either request all contents of the file at once using {@link #get()} or
+ * request an {@link java.io.InputStream InputStream} with
+ * {@link #getInputStream()} and process the file without attempting to load
+ * it into memory, which may come handy with large files.
+ *
+ * <p> While this interface does not extend
+ * <code>javax.activation.DataSource</code> per se (to avoid a seldom used
+ * dependency), several of the defined methods are specifically defined with
+ * the same signatures as methods in that interface. This allows an
+ * implementation of this interface to also implement
+ * <code>javax.activation.DataSource</code> with minimal additional work.
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:sean@informage.net">Sean Legassick</a>
+ * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ *
+ * @version $Id: FileItem.java,v 1.15 2003/06/01 17:33:24 martinc Exp $
+ */
+public interface FileItem
+    extends Serializable
+{
+
+
+    // ------------------------------- Methods from javax.activation.DataSource
+
+
+    /**
+     * Returns an {@link java.io.InputStream InputStream} that can be
+     * used to retrieve the contents of the file.
+     *
+     * @return An {@link java.io.InputStream InputStream} that can be
+     *         used to retrieve the contents of the file.
+     *
+     * @exception IOException if an error occurs.
+     */
+    InputStream getInputStream()
+        throws IOException;
+
+
+    /**
+     * Returns the content type passed by the browser or <code>null</code> if
+     * not defined.
+     *
+     * @return The content type passed by the browser or <code>null</code> if
+     *         not defined.
+     */
+    String getContentType();
+
+
+    /**
+     * Returns the original filename in the client's filesystem, as provided by
+     * the browser (or other client software). In most cases, this will be the
+     * base file name, without path information. However, some clients, such as
+     * the Opera browser, do include path information.
+     *
+     * @return The original filename in the client's filesystem.
+     */
+    String getName();
+
+
+    // ------------------------------------------------------- FileItem methods
+
+
+    /**
+     * Provides a hint as to whether or not the file contents will be read
+     * from memory.
+     *
+     * @return <code>true</code> if the file contents will be read from memory;
+     *         <code>false</code> otherwise.
+     */
+    boolean isInMemory();
+
+
+    /**
+     * Returns the size of the file item.
+     *
+     * @return The size of the file item, in bytes.
+     */
+    long getSize();
+
+
+    /**
+     * Returns the contents of the file item as an array of bytes.
+     *
+     * @return The contents of the file item as an array of bytes.
+     */
+    byte[] get();
+
+
+    /**
+     * Returns the contents of the file item as a String, using the specified
+     * encoding.  This method uses {@link #get()} to retrieve the
+     * contents of the item.
+     *
+     * @param encoding The character encoding to use.
+     *
+     * @return The contents of the item, as a string.
+     *
+     * @exception UnsupportedEncodingException if the requested character
+     *                                         encoding is not available.
+     */
+    String getString(String encoding)
+        throws UnsupportedEncodingException;
+
+
+    /**
+     * Returns the contents of the file item as a String, using the default
+     * character encoding.  This method uses {@link #get()} to retrieve the
+     * contents of the item.
+     *
+     * @return The contents of the item, as a string.
+     */
+    String getString();
+
+
+    /**
+     * A convenience method to write an uploaded item to disk. The client code
+     * is not concerned with whether or not the item is stored in memory, or on
+     * disk in a temporary location. They just want to write the uploaded item
+     * to a file.
+     * <p>
+     * This method is not guaranteed to succeed if called more than once for
+     * the same item. This allows a particular implementation to use, for
+     * example, file renaming, where possible, rather than copying all of the
+     * underlying data, thus gaining a significant performance benefit.
+     *
+     * @param file The <code>File</code> into which the uploaded item should
+     *             be stored.
+     *
+     * @exception Exception if an error occurs.
+     */
+    void write(File file) throws Exception;
+
+
+    /**
+     * Deletes the underlying storage for a file item, including deleting any
+     * associated temporary disk file. Although this storage will be deleted
+     * automatically when the <code>FileItem</code> instance is garbage
+     * collected, this method can be used to ensure that this is done at an
+     * earlier time, thus preserving system resources.
+     */
+    void delete();
+
+
+    /**
+     * Returns the name of the field in the multipart form corresponding to
+     * this file item.
+     *
+     * @return The name of the form field.
+     */
+    String getFieldName();
+
+
+    /**
+     * Sets the field name used to reference this file item.
+     *
+     * @param name The name of the form field.
+     */
+    void setFieldName(String name);
+
+
+    /**
+     * Determines whether or not a <code>FileItem</code> instance represents
+     * a simple form field.
+     *
+     * @return <code>true</code> if the instance represents a simple form
+     *         field; <code>false</code> if it represents an uploaded file.
+     */
+    boolean isFormField();
+
+
+    /**
+     * Specifies whether or not a <code>FileItem</code> instance represents
+     * a simple form field.
+     *
+     * @param state <code>true</code> if the instance represents a simple form
+     *              field; <code>false</code> if it represents an uploaded file.
+     */
+    void setFormField(boolean state);
+
+
+    /**
+     * Returns an {@link java.io.OutputStream OutputStream} that can
+     * be used for storing the contents of the file.
+     *
+     * @return An {@link java.io.OutputStream OutputStream} that can be used
+     *         for storing the contensts of the file.
+     *
+     * @exception IOException if an error occurs.
+     */
+    OutputStream getOutputStream() throws IOException;
+
+}

Propchange: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileItem.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileItemFactory.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileItemFactory.java?rev=412780&view=auto
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileItemFactory.java (added)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileItemFactory.java Thu Jun  8 08:35:56 2006
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2001-2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.tomcat.util.http.fileupload;
+
+
+/**
+ * <p>A factory interface for creating {@link FileItem} instances. Factories
+ * can provide their own custom configuration, over and above that provided
+ * by the default file upload implementation.</p>
+ *
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ * 
+ * @version $Id: FileItemFactory.java,v 1.1 2003/04/27 17:30:06 martinc Exp $
+ */
+public interface FileItemFactory
+{
+
+    /**
+     * Create a new {@link FileItem} instance from the supplied parameters and
+     * any local factory configuration.
+     *
+     * @param fieldName   The name of the form field.
+     * @param contentType The content type of the form field.
+     * @param isFormField <code>true</code> if this is a plain form field;
+     *                    <code>false</code> otherwise.
+     * @param fileName    The name of the uploaded file, if any, as supplied
+     *                    by the browser or other client.
+     *
+     * @return The newly created file item.
+     */
+    FileItem createItem(
+            String fieldName,
+            String contentType,
+            boolean isFormField,
+            String fileName
+            );
+}

Propchange: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileItemFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUpload.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUpload.java?rev=412780&view=auto
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUpload.java (added)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUpload.java Thu Jun  8 08:35:56 2006
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2001-2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.tomcat.util.http.fileupload;
+
+
+/**
+ * <p>High level API for processing file uploads.</p>
+ *
+ * <p>This class handles multiple files per single HTML widget, sent using
+ * <code>multipart/mixed</code> encoding type, as specified by
+ * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>.  Use {@link
+ * #parseRequest(HttpServletRequest)} to acquire a list of {@link
+ * org.apache.tomcat.util.http.fileupload.FileItem}s associated with a given HTML
+ * widget.</p>
+ *
+ * <p>How the data for individual parts is stored is determined by the factory
+ * used to create them; a given part may be in memory, on disk, or somewhere
+ * else.</p>
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ * @author Sean C. Sullivan
+ *
+ * @version $Id: FileUpload.java,v 1.23 2003/06/24 05:45:43 martinc Exp $
+ */
+public class FileUpload
+    extends FileUploadBase
+ {
+
+    // ----------------------------------------------------------- Data members
+
+
+    /**
+     * The factory to use to create new form items.
+     */
+    private FileItemFactory fileItemFactory;
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Constructs an instance of this class which uses the default factory to
+     * create <code>FileItem</code> instances.
+     *
+     * @see #FileUpload(FileItemFactory)
+     */
+    public FileUpload()
+    {
+        super();
+    }
+
+
+    /**
+     * Constructs an instance of this class which uses the supplied factory to
+     * create <code>FileItem</code> instances.
+     *
+     * @see #FileUpload()
+     */
+    public FileUpload(FileItemFactory fileItemFactory)
+    {
+        super();
+        this.fileItemFactory = fileItemFactory;
+    }
+
+
+    // ----------------------------------------------------- Property accessors
+
+
+    /**
+     * Returns the factory class used when creating file items.
+     *
+     * @return The factory class for new file items.
+     */
+    public FileItemFactory getFileItemFactory()
+    {
+        return fileItemFactory;
+    }
+
+
+    /**
+     * Sets the factory class to use when creating file items.
+     *
+     * @param factory The factory class for new file items.
+     */
+    public void setFileItemFactory(FileItemFactory factory)
+    {
+        this.fileItemFactory = factory;
+    }
+
+
+}

Propchange: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUpload.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java?rev=412780&view=auto
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java (added)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java Thu Jun  8 08:35:56 2006
@@ -0,0 +1,640 @@
+/*
+ * Copyright 2001-2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.tomcat.util.http.fileupload;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+
+
+/**
+ * <p>High level API for processing file uploads.</p>
+ *
+ * <p>This class handles multiple files per single HTML widget, sent using
+ * <code>multipart/mixed</code> encoding type, as specified by
+ * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>.  Use {@link
+ * #parseRequest(HttpServletRequest)} to acquire a list of {@link
+ * org.apache.tomcat.util.http.fileupload.FileItem}s associated with a given HTML
+ * widget.</p>
+ *
+ * <p>How the data for individual parts is stored is determined by the factory
+ * used to create them; a given part may be in memory, on disk, or somewhere
+ * else.</p>
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ * @author Sean C. Sullivan
+ *
+ * @version $Id: FileUploadBase.java,v 1.3 2003/06/01 00:18:13 martinc Exp $
+ */
+public abstract class FileUploadBase
+{
+
+    // ---------------------------------------------------------- Class methods
+
+
+    /**
+     * Utility method that determines whether the request contains multipart
+     * content.
+     *
+     * @param req The servlet request to be evaluated. Must be non-null.
+     *
+     * @return <code>true</code> if the request is multipart;
+     *         <code>false</code> otherwise.
+     */
+    public static final boolean isMultipartContent(HttpServletRequest req)
+    {
+        String contentType = req.getHeader(CONTENT_TYPE);
+        if (contentType == null)
+        {
+            return false;
+        }
+        if (contentType.startsWith(MULTIPART))
+        {
+            return true;
+        }
+        return false;
+    }
+
+
+    // ----------------------------------------------------- Manifest constants
+
+
+    /**
+     * HTTP content type header name.
+     */
+    public static final String CONTENT_TYPE = "Content-type";
+
+
+    /**
+     * HTTP content disposition header name.
+     */
+    public static final String CONTENT_DISPOSITION = "Content-disposition";
+
+
+    /**
+     * Content-disposition value for form data.
+     */
+    public static final String FORM_DATA = "form-data";
+
+
+    /**
+     * Content-disposition value for file attachment.
+     */
+    public static final String ATTACHMENT = "attachment";
+
+
+    /**
+     * Part of HTTP content type header.
+     */
+    public static final String MULTIPART = "multipart/";
+
+
+    /**
+     * HTTP content type header for multipart forms.
+     */
+    public static final String MULTIPART_FORM_DATA = "multipart/form-data";
+
+
+    /**
+     * HTTP content type header for multiple uploads.
+     */
+    public static final String MULTIPART_MIXED = "multipart/mixed";
+
+
+    /**
+     * The maximum length of a single header line that will be parsed
+     * (1024 bytes).
+     */
+    public static final int MAX_HEADER_SIZE = 1024;
+
+
+    // ----------------------------------------------------------- Data members
+
+
+    /**
+     * The maximum size permitted for an uploaded file. A value of -1 indicates
+     * no maximum.
+     */
+    private long sizeMax = -1;
+
+
+    /**
+     * The content encoding to use when reading part headers.
+     */
+    private String headerEncoding;
+
+
+    // ----------------------------------------------------- Property accessors
+
+
+    /**
+     * Returns the factory class used when creating file items.
+     *
+     * @return The factory class for new file items.
+     */
+    public abstract FileItemFactory getFileItemFactory();
+
+
+    /**
+     * Sets the factory class to use when creating file items.
+     *
+     * @param factory The factory class for new file items.
+     */
+    public abstract void setFileItemFactory(FileItemFactory factory);
+
+
+    /**
+     * Returns the maximum allowed upload size.
+     *
+     * @return The maximum allowed size, in bytes.
+     *
+     * @see #setSizeMax(long)
+     *
+     */
+    public long getSizeMax()
+    {
+        return sizeMax;
+    }
+
+
+    /**
+     * Sets the maximum allowed upload size. If negative, there is no maximum.
+     *
+     * @param sizeMax The maximum allowed size, in bytes, or -1 for no maximum.
+     *
+     * @see #getSizeMax()
+     *
+     */
+    public void setSizeMax(long sizeMax)
+    {
+        this.sizeMax = sizeMax;
+    }
+
+
+    /**
+     * Retrieves the character encoding used when reading the headers of an
+     * individual part. When not specified, or <code>null</code>, the platform
+     * default encoding is used.
+     *
+     * @return The encoding used to read part headers.
+     */
+    public String getHeaderEncoding()
+    {
+        return headerEncoding;
+    }
+
+
+    /**
+     * Specifies the character encoding to be used when reading the headers of
+     * individual parts. When not specified, or <code>null</code>, the platform
+     * default encoding is used.
+     *
+     * @param encoding The encoding used to read part headers.
+     */
+    public void setHeaderEncoding(String encoding)
+    {
+        headerEncoding = encoding;
+    }
+
+
+    // --------------------------------------------------------- Public methods
+
+
+    /**
+     * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
+     * compliant <code>multipart/form-data</code> stream. If files are stored
+     * on disk, the path is given by <code>getRepository()</code>.
+     *
+     * @param req The servlet request to be parsed.
+     *
+     * @return A list of <code>FileItem</code> instances parsed from the
+     *         request, in the order that they were transmitted.
+     *
+     * @exception FileUploadException if there are problems reading/parsing
+     *                                the request or storing files.
+     */
+    public List /* FileItem */ parseRequest(HttpServletRequest req)
+        throws FileUploadException
+    {
+        if (null == req)
+        {
+            throw new NullPointerException("req parameter");
+        }
+
+        ArrayList items = new ArrayList();
+        String contentType = req.getHeader(CONTENT_TYPE);
+
+        if ((null == contentType) || (!contentType.startsWith(MULTIPART)))
+        {
+            throw new InvalidContentTypeException(
+                "the request doesn't contain a "
+                + MULTIPART_FORM_DATA
+                + " or "
+                + MULTIPART_MIXED
+                + " stream, content type header is "
+                + contentType);
+        }
+        int requestSize = req.getContentLength();
+
+        if (requestSize == -1)
+        {
+            throw new UnknownSizeException(
+                "the request was rejected because it's size is unknown");
+        }
+
+        if (sizeMax >= 0 && requestSize > sizeMax)
+        {
+            throw new SizeLimitExceededException(
+                "the request was rejected because "
+                + "it's size exceeds allowed range");
+        }
+
+        try
+        {
+            int boundaryIndex = contentType.indexOf("boundary=");
+            if (boundaryIndex < 0)
+            {
+                throw new FileUploadException(
+                        "the request was rejected because "
+                        + "no multipart boundary was found");
+            }
+            byte[] boundary = contentType.substring(
+                    boundaryIndex + 9).getBytes();
+
+            InputStream input = req.getInputStream();
+
+            MultipartStream multi = new MultipartStream(input, boundary);
+            multi.setHeaderEncoding(headerEncoding);
+
+            boolean nextPart = multi.skipPreamble();
+            while (nextPart)
+            {
+                Map headers = parseHeaders(multi.readHeaders());
+                String fieldName = getFieldName(headers);
+                if (fieldName != null)
+                {
+                    String subContentType = getHeader(headers, CONTENT_TYPE);
+                    if (subContentType != null && subContentType
+                                                .startsWith(MULTIPART_MIXED))
+                    {
+                        // Multiple files.
+                        byte[] subBoundary =
+                            subContentType.substring(
+                                subContentType
+                                .indexOf("boundary=") + 9).getBytes();
+                        multi.setBoundary(subBoundary);
+                        boolean nextSubPart = multi.skipPreamble();
+                        while (nextSubPart)
+                        {
+                            headers = parseHeaders(multi.readHeaders());
+                            if (getFileName(headers) != null)
+                            {
+                                FileItem item =
+                                        createItem(headers, false);
+                                OutputStream os = item.getOutputStream();
+                                try
+                                {
+                                    multi.readBodyData(os);
+                                }
+                                finally
+                                {
+                                    os.close();
+                                }
+                                items.add(item);
+                            }
+                            else
+                            {
+                                // Ignore anything but files inside
+                                // multipart/mixed.
+                                multi.discardBodyData();
+                            }
+                            nextSubPart = multi.readBoundary();
+                        }
+                        multi.setBoundary(boundary);
+                    }
+                    else
+                    {
+                        if (getFileName(headers) != null)
+                        {
+                            // A single file.
+                            FileItem item = createItem(headers, false);
+                            OutputStream os = item.getOutputStream();
+                            try
+                            {
+                                multi.readBodyData(os);
+                            }
+                            finally
+                            {
+                                os.close();
+                            }
+                            items.add(item);
+                        }
+                        else
+                        {
+                            // A form field.
+                            FileItem item = createItem(headers, true);
+                            OutputStream os = item.getOutputStream();
+                            try
+                            {
+                                multi.readBodyData(os);
+                            }
+                            finally
+                            {
+                                os.close();
+                            }
+                            items.add(item);
+                        }
+                    }
+                }
+                else
+                {
+                    // Skip this part.
+                    multi.discardBodyData();
+                }
+                nextPart = multi.readBoundary();
+            }
+        }
+        catch (IOException e)
+        {
+            throw new FileUploadException(
+                "Processing of " + MULTIPART_FORM_DATA
+                    + " request failed. " + e.getMessage());
+        }
+
+        return items;
+    }
+
+
+    // ------------------------------------------------------ Protected methods
+
+
+    /**
+     * Retrieves the file name from the <code>Content-disposition</code>
+     * header.
+     *
+     * @param headers A <code>Map</code> containing the HTTP request headers.
+     *
+     * @return The file name for the current <code>encapsulation</code>.
+     */
+    protected String getFileName(Map /* String, String */ headers)
+    {
+        String fileName = null;
+        String cd = getHeader(headers, CONTENT_DISPOSITION);
+        if (cd.startsWith(FORM_DATA) || cd.startsWith(ATTACHMENT))
+        {
+            int start = cd.indexOf("filename=\"");
+            int end = cd.indexOf('"', start + 10);
+            if (start != -1 && end != -1)
+            {
+                fileName = cd.substring(start + 10, end).trim();
+            }
+        }
+        return fileName;
+    }
+
+
+    /**
+     * Retrieves the field name from the <code>Content-disposition</code>
+     * header.
+     *
+     * @param headers A <code>Map</code> containing the HTTP request headers.
+     *
+     * @return The field name for the current <code>encapsulation</code>.
+     */
+    protected String getFieldName(Map /* String, String */ headers)
+    {
+        String fieldName = null;
+        String cd = getHeader(headers, CONTENT_DISPOSITION);
+        if (cd != null && cd.startsWith(FORM_DATA))
+        {
+            int start = cd.indexOf("name=\"");
+            int end = cd.indexOf('"', start + 6);
+            if (start != -1 && end != -1)
+            {
+                fieldName = cd.substring(start + 6, end);
+            }
+        }
+        return fieldName;
+    }
+
+
+    /**
+     * Creates a new {@link FileItem} instance.
+     *
+     * @param headers       A <code>Map</code> containing the HTTP request
+     *                      headers.
+     * @param isFormField   Whether or not this item is a form field, as
+     *                      opposed to a file.
+     *
+     * @return A newly created <code>FileItem</code> instance.
+     *
+     * @exception FileUploadException if an error occurs.
+     */
+    protected FileItem createItem(Map /* String, String */ headers,
+                                  boolean isFormField)
+        throws FileUploadException
+    {
+        return getFileItemFactory().createItem(getFieldName(headers),
+                getHeader(headers, CONTENT_TYPE),
+                isFormField,
+                getFileName(headers));
+    }
+
+
+    /**
+     * <p> Parses the <code>header-part</code> and returns as key/value
+     * pairs.
+     *
+     * <p> If there are multiple headers of the same names, the name
+     * will map to a comma-separated list containing the values.
+     *
+     * @param headerPart The <code>header-part</code> of the current
+     *                   <code>encapsulation</code>.
+     *
+     * @return A <code>Map</code> containing the parsed HTTP request headers.
+     */
+    protected Map /* String, String */ parseHeaders(String headerPart)
+    {
+        Map headers = new HashMap();
+        char buffer[] = new char[MAX_HEADER_SIZE];
+        boolean done = false;
+        int j = 0;
+        int i;
+        String header, headerName, headerValue;
+        try
+        {
+            while (!done)
+            {
+                i = 0;
+                // Copy a single line of characters into the buffer,
+                // omitting trailing CRLF.
+                while (i < 2 || buffer[i - 2] != '\r' || buffer[i - 1] != '\n')
+                {
+                    buffer[i++] = headerPart.charAt(j++);
+                }
+                header = new String(buffer, 0, i - 2);
+                if (header.equals(""))
+                {
+                    done = true;
+                }
+                else
+                {
+                    if (header.indexOf(':') == -1)
+                    {
+                        // This header line is malformed, skip it.
+                        continue;
+                    }
+                    headerName = header.substring(0, header.indexOf(':'))
+                        .trim().toLowerCase();
+                    headerValue =
+                        header.substring(header.indexOf(':') + 1).trim();
+                    if (getHeader(headers, headerName) != null)
+                    {
+                        // More that one heder of that name exists,
+                        // append to the list.
+                        headers.put(headerName,
+                                    getHeader(headers, headerName) + ','
+                                        + headerValue);
+                    }
+                    else
+                    {
+                        headers.put(headerName, headerValue);
+                    }
+                }
+            }
+        }
+        catch (IndexOutOfBoundsException e)
+        {
+            // Headers were malformed. continue with all that was
+            // parsed.
+        }
+        return headers;
+    }
+
+
+    /**
+     * Returns the header with the specified name from the supplied map. The
+     * header lookup is case-insensitive.
+     *
+     * @param headers A <code>Map</code> containing the HTTP request headers.
+     * @param name    The name of the header to return.
+     *
+     * @return The value of specified header, or a comma-separated list if
+     *         there were multiple headers of that name.
+     */
+    protected final String getHeader(Map /* String, String */ headers,
+                                     String name)
+    {
+        return (String) headers.get(name.toLowerCase());
+    }
+
+
+    /**
+     * Thrown to indicate that the request is not a multipart request.
+     */
+    public static class InvalidContentTypeException
+        extends FileUploadException
+    {
+        /**
+         * Constructs a <code>InvalidContentTypeException</code> with no
+         * detail message.
+         */
+        public InvalidContentTypeException()
+        {
+            super();
+        }
+
+        /**
+         * Constructs an <code>InvalidContentTypeException</code> with
+         * the specified detail message.
+         *
+         * @param message The detail message.
+         */
+        public InvalidContentTypeException(String message)
+        {
+            super(message);
+        }
+    }
+
+
+    /**
+     * Thrown to indicate that the request size is not specified.
+     */
+    public static class UnknownSizeException
+        extends FileUploadException
+    {
+        /**
+         * Constructs a <code>UnknownSizeException</code> with no
+         * detail message.
+         */
+        public UnknownSizeException()
+        {
+            super();
+        }
+
+        /**
+         * Constructs an <code>UnknownSizeException</code> with
+         * the specified detail message.
+         *
+         * @param message The detail message.
+         */
+        public UnknownSizeException(String message)
+        {
+            super(message);
+        }
+    }
+
+
+    /**
+     * Thrown to indicate that the request size exceeds the configured maximum.
+     */
+    public static class SizeLimitExceededException
+        extends FileUploadException
+    {
+        /**
+         * Constructs a <code>SizeExceededException</code> with no
+         * detail message.
+         */
+        public SizeLimitExceededException()
+        {
+            super();
+        }
+
+        /**
+         * Constructs an <code>SizeExceededException</code> with
+         * the specified detail message.
+         *
+         * @param message The detail message.
+         */
+        public SizeLimitExceededException(String message)
+        {
+            super(message);
+        }
+    }
+
+}

Propchange: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java?rev=412780&view=auto
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java (added)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java Thu Jun  8 08:35:56 2006
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2001-2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.tomcat.util.http.fileupload;
+
+
+/**
+ * Exception for errors encountered while processing the request.
+ *
+ * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
+ * @version $Id: FileUploadException.java,v 1.7 2003/04/27 17:30:06 martinc Exp $
+ */
+public class FileUploadException
+    extends Exception
+{
+
+    /**
+     * Constructs a new <code>FileUploadException</code> without message.
+     */
+    public FileUploadException()
+    {
+    }
+
+    /**
+     * Constructs a new <code>FileUploadException</code> with specified detail
+     * message.
+     *
+     * @param msg the error message.
+     */
+    public FileUploadException(String msg)
+    {
+        super(msg);
+    }
+}

Propchange: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org