You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by jo...@apache.org on 2010/06/06 23:19:57 UTC

svn commit: r951978 [3/5] - in /commons/sandbox/commons-fileupload2: ./ .settings/ src/ src/changes/ src/checkstyle/ src/conf/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/commons/ src/java/org/apache/commons/fileupload2/ src/java/o...

Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/AbstractStoredFileItem.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/AbstractStoredFileItem.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/AbstractStoredFileItem.java (added)
+++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/AbstractStoredFileItem.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,125 @@
+package org.apache.commons.fileupload2.impl;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.commons.fileupload2.FileItem;
+import org.apache.commons.fileupload2.FileUploadException;
+import org.apache.commons.fileupload2.StoredFileItem;
+
+
+/**
+ * Abstract base implementation of {@link StoredFileItem}. Implementation note:
+ * This class is basically identical with {@link AbstractFileItem}. The main
+ * difference is, that it implements the {@link Serializable} interface. It
+ * could be implemented as a subclass of {@link AbstractFileItem}. However,
+ * in that case, its fields wouldn't be persisted automatically.
+ */
+public abstract class AbstractStoredFileItem implements StoredFileItem, Serializable {
+	private static final long serialVersionUID = 8474582370751849854L;
+	private long contentLength;
+    private String contentType, encoding;
+    private String fieldName, fileName;
+    private boolean formField;
+
+    /**
+     * Creates a new instance with default settings.
+     */
+    protected AbstractStoredFileItem() {
+        // Nothing to do.
+    }
+
+    /**
+     * Creates a new instance, which copies its settings from the
+     * given {@link FileItem}.
+     */
+    protected AbstractStoredFileItem(FileItem pFileItem) {
+        setContentLength(pFileItem.getContentLength());
+        setContentType(pFileItem.getContentType());
+        setEncoding(pFileItem.getEncoding());
+        setFieldName(pFileItem.getFieldName());
+        setFileName(pFileItem.getFileName());
+        setFormField(pFileItem.isFormField());
+    }
+
+    public long getContentLength() {
+        return contentLength;
+    }
+
+    /**
+     * Sets the file items content length.
+     */
+    public void setContentLength(long pContentLength) {
+        contentLength = pContentLength;
+    }
+    
+    public String getContentType() {
+        return contentType;
+    }
+
+    /**
+     * Sets the content type.
+     * @see #getContentType()
+     */
+    public void setContentType(String pContentType) {
+        contentType = pContentType;
+    }
+    
+    public String getEncoding() {
+        return encoding;
+    }
+
+    /**
+     * Sets the file items encoding.
+     */
+    public void setEncoding(String pEncoding) {
+        encoding = pEncoding;
+    }
+    
+    public String getFieldName() {
+        return fieldName;
+    }
+
+    /**
+     * Sets the field name.
+     * @see #getFieldName()
+     */
+    public void setFieldName(String pFieldName) {
+        fieldName = pFieldName;
+    }
+    
+    public String getFileName() {
+        return fileName;
+    }
+
+    /**
+     * Sets the file name.
+     * @see #getFileName()
+     */
+    public void setFileName(String pFileName) {
+        fileName = pFileName;
+    }
+
+    public boolean isFormField() {
+        return formField;
+    }
+
+    /**
+     * Sets, whether the file item is in fact a simple form field.
+     * If the file item is no simple form field, then the value
+     * returned by {@link #getFileName()} is valid. Otherwise, the
+     * value returned by {@link #getFileName()} will most likely be
+     * null, and should be ignored.
+     */
+    public void setFormField(boolean pFormField) {
+        formField = pFormField;
+    }
+
+    public Reader getReader(String pEncoding) throws FileUploadException,
+            UnsupportedEncodingException, IOException {
+        return new InputStreamReader(getInputStream(), pEncoding);
+    }
+}

Propchange: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/AbstractStoredFileItem.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/DefaultEventListener.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/DefaultEventListener.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/DefaultEventListener.java (added)
+++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/DefaultEventListener.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,71 @@
+package org.apache.commons.fileupload2.impl;
+
+import java.io.IOException;
+import java.lang.reflect.UndeclaredThrowableException;
+
+import org.apache.commons.fileupload2.EventListener;
+import org.apache.commons.fileupload2.FileItem;
+import org.apache.commons.fileupload2.FileSizeMaxException;
+import org.apache.commons.fileupload2.FileUpload;
+import org.apache.commons.fileupload2.UploadRequest;
+import org.apache.commons.fileupload2.RequestSizeMaxException;
+
+
+/**
+ * Default implementation of {@link EventListener}. Throws exceptions
+ * in case of errors and ignores the other events.
+ */
+public class DefaultEventListener implements EventListener {
+    public void endItem(FileUpload pFileUpload, UploadRequest pRequest, FileItem item, long contentLength)
+            throws IOException {
+        // Does nothing
+    }
+
+    public void endRequest(FileUpload pFileUpload, UploadRequest pRequest) throws IOException {
+        // Does nothing
+    }
+
+    public void error(FileUpload pFileUpload, UploadRequest pRequest, Throwable pError) throws IOException {
+        if (pError instanceof IOException) {
+            throw (IOException) pError;
+        }
+        if (pError instanceof RuntimeException) {
+            throw (RuntimeException) pError;
+        }
+        if (pError instanceof Error) {
+            throw (Error) pError;
+        }
+        throw new UndeclaredThrowableException(pError);
+    }
+
+    public long parsingItem(FileUpload fileUpload, UploadRequest pRequest, FileItem item,
+            long currentLength) throws IOException {
+        return EventListener.NO_PARSING_ITEM_CALLS;
+    }
+
+    public void requestSizeMaxExceeded(FileUpload pFileUpload, UploadRequest pRequest, long pRequestSize)
+            throws IOException {
+        throw new RequestSizeMaxException("Maximum request size of "
+                + pFileUpload.getRequestSizeMax() + " exceeded, actual size is "
+                + pRequestSize + " or more.", pFileUpload.getRequestSizeMax(), pRequestSize);
+    }
+
+    public long startItem(FileUpload fileUpload, UploadRequest pRequest, FileItem item)
+            throws IOException {
+        return EventListener.NO_PARSING_ITEM_CALLS;
+    }
+
+    public void startRequest(FileUpload fileUpload, UploadRequest pRequest) throws IOException {
+        // Does nothing
+    }
+
+    public void fileSizeMaxExceeded(FileUpload pFileUpload, UploadRequest pRequest,
+            FileItem pItem, long pFileSize) throws IOException {
+        throw new FileSizeMaxException("Maximum file size of "
+                + pFileUpload.getFileSizeMax() + " exceeded for field "
+                + pItem.getFieldName() + ", file " + pItem.getFileName()
+                + ", actual size is " + pFileSize + " or more.",
+                pItem.getFieldName(), pItem.getFileName(),
+                pFileUpload.getFileSizeMax(), pFileSize);
+    }
+}

Propchange: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/DefaultEventListener.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java (added)
+++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,237 @@
+package org.apache.commons.fileupload2.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.NoSuchElementException;
+
+import org.apache.commons.fileupload2.EventListener;
+import org.apache.commons.fileupload2.FileItem;
+import org.apache.commons.fileupload2.FileItemIterator;
+import org.apache.commons.fileupload2.FileUpload;
+import org.apache.commons.fileupload2.FileUploadException;
+import org.apache.commons.fileupload2.InvalidContentTypeException;
+import org.apache.commons.fileupload2.UploadRequest;
+import org.apache.commons.fileupload2.util.LimitedInputStream;
+import org.apache.james.mime4j.MimeException;
+import org.apache.james.mime4j.descriptor.BodyDescriptor;
+import org.apache.james.mime4j.descriptor.MaximalBodyDescriptor;
+import org.apache.james.mime4j.parser.EntityStates;
+import org.apache.james.mime4j.parser.MimeEntityConfig;
+import org.apache.james.mime4j.parser.MimeTokenStream;
+
+
+/**
+ * An instance of this class is returned by
+ * {@link FileUpload#parse(org.apache.commons.fileupload2.UploadRequest)}.
+ */
+public class FileItemIteratorImpl<FI extends FileItem> implements FileItemIterator<FI> {
+    private static final EventListener DEFAULT_LISTENER = new DefaultEventListener();
+    private final FileUpload fileUpload;
+    private final UploadRequest request;
+    private EventListener listener;
+    private final MimeTokenStream mts;
+    private String currentFieldName;
+    private FileItem currentItem, previousFileItem;
+    private LimitedInputStream itemStream;
+    private int level;
+
+    /**
+     * Creates a new instance.
+     */
+    public FileItemIteratorImpl(FileUpload pFileUpload, UploadRequest pRequest,
+            EventListener pListener)
+            throws FileUploadException, IOException {
+        if (pFileUpload == null) {
+            throw new IllegalArgumentException("The FileUpload must not be null.");
+        }
+        fileUpload = pFileUpload;
+        if (pRequest == null) {
+            throw new IllegalArgumentException("The UploadRequest must not be null.");
+        }
+        request = pRequest;
+        final String contentType = pRequest.getContentType();
+        if (contentType == null  ||  !contentType.startsWith("multipart/")) {
+            throw new InvalidContentTypeException("Invalid content type: " + contentType);
+        }
+        listener = pListener;
+        if (listener != null) {
+            listener.startRequest(pFileUpload, pRequest);
+        }
+		MimeEntityConfig config = new MimeEntityConfig();
+		config.setMaximalBodyDescriptor(true);
+		config.setStrictParsing(true);
+        mts = new MimeTokenStream(config){
+        	// No additional methods, or fields, just to make the constructor accessible.
+        };
+        final InputStream is;
+        final long requestSizeMax = pFileUpload.getRequestSizeMax();
+        if (requestSizeMax == FileUpload.NO_REQUEST_SIZE_MAX) {
+            is = pRequest.getInputStream();
+        } else {
+            final long contentLength = request.getContentLength();
+            if (contentLength != UploadRequest.UNKNOWN_CONTENT_LENGTH  &&  contentLength > requestSizeMax) {
+                noteRequestSizeMaxExceeded(contentLength);
+            }
+            is = new LimitedInputStream(pRequest.getInputStream(), requestSizeMax){
+                @Override
+                protected void raiseError(long pSizeMax, long pCount)
+                        throws IOException {
+                    noteRequestSizeMaxExceeded(pCount);
+                }
+            };
+        }
+        mts.parseHeadless(is, contentType);
+    }
+
+    public boolean hasNext() throws FileUploadException, IOException {
+        try {
+            if (currentItem != null) {
+                return true;
+            }
+            int state;
+            if (previousFileItem != null) {
+                if (listener != null) {
+                    skip(itemStream);
+                    listener.endItem(fileUpload, request, previousFileItem, itemStream.getCount());
+                }
+            }
+            state = mts.next();
+            for (;;) {
+                switch (state) {
+                    case EntityStates.T_END_OF_STREAM:
+                        if (listener != null) {
+                            listener.endRequest(fileUpload, request);
+                            listener = null;
+                        }
+                        return false;
+                    case EntityStates.T_START_MULTIPART:
+                        if (level++ == 1) {
+                            final MaximalBodyDescriptor bodyDescriptor = (MaximalBodyDescriptor) mts.getBodyDescriptor();
+                            final String fldName = getFieldName(bodyDescriptor);
+                            if (fldName != null) {
+                                final String subContentType = getContentType(bodyDescriptor);
+                                if (subContentType != null
+                                    &&  subContentType.toLowerCase().startsWith("multipart/mixed")) {
+                                    currentFieldName = fldName;
+                                }
+                            }
+                        }
+                        break;
+                    case EntityStates.T_END_MULTIPART:
+                        if (--level == 1) {
+                            currentFieldName = null;
+                        }
+                        break;
+                    case EntityStates.T_BODY:
+                        final MaximalBodyDescriptor bodyDescriptor = (MaximalBodyDescriptor) mts.getBodyDescriptor();
+                        if (currentFieldName == null) {
+                            final String fldName = getFieldName(bodyDescriptor);
+                            if (fldName != null) {
+                                String fileName = getFileName(bodyDescriptor);
+                                currentItem = newFileItem(fldName, fileName, bodyDescriptor);
+                                return true;
+                            }
+                        } else {
+                            String fileName = getFileName(bodyDescriptor);
+                            if (fileName != null) {
+                                currentItem = newFileItem(currentFieldName, fileName, bodyDescriptor);
+                                return true;
+                            }
+                        }
+                        break;
+                }
+                state = mts.next();
+            }
+        } catch (MimeException e) {
+            throw new FileUploadException(e.getMessage(), e);
+        }
+    }
+
+    private void noteFileSizeMaxExceeded(FileItem pItem, long pFileSize)
+            throws FileUploadException, IOException {
+        if (listener == null) {
+            DEFAULT_LISTENER.fileSizeMaxExceeded(fileUpload, request, pItem, pFileSize);
+        } else {
+            listener.fileSizeMaxExceeded(fileUpload, request, pItem, pFileSize);
+        }
+    }
+
+    private void noteRequestSizeMaxExceeded(long pFileSize) throws FileUploadException, IOException {
+        if (listener == null) {
+            DEFAULT_LISTENER.requestSizeMaxExceeded(fileUpload, request, pFileSize);
+        } else {
+            listener.requestSizeMaxExceeded(fileUpload, request, pFileSize);
+        }
+    }
+
+    /**
+     * Creates a new instance of {@link FileItem}.
+     */
+    protected FileItem newFileItem(String pFieldName, String pFileName, MaximalBodyDescriptor pBodyDescriptor)
+            throws FileUploadException, IOException {
+        final long fileSizeMax = fileUpload.getFileSizeMax();
+        final AbstractFileItem fileItem = new AbstractFileItem(){
+            public InputStream getInputStream() throws FileUploadException,
+                    IOException {
+                if (fileSizeMax == FileUpload.NO_FILE_SIZE_MAX  &&  listener == null) {
+                    return mts.getDecodedInputStream();
+                }
+                final FileItem fi = this;
+                itemStream = new LimitedInputStream(mts.getDecodedInputStream(), fileSizeMax == FileUpload.NO_FILE_SIZE_MAX ? 0 : fileSizeMax) {
+                    @Override
+                    protected void raiseError(long pSizeMax, long pCount)
+                            throws IOException {
+                    	noteFileSizeMaxExceeded(fi, pCount);
+                    }
+                };
+                return itemStream;
+            }
+        };
+        final long contentLength = pBodyDescriptor.getContentLength();
+        fileItem.setContentLength(contentLength);
+        fileItem.setContentType(pBodyDescriptor.getMimeType());
+        fileItem.setEncoding(pBodyDescriptor.getCharset());
+        fileItem.setFieldName(pFieldName);
+        fileItem.setFileName(pFileName);
+        fileItem.setFormField(pFileName == null);
+        if (fileSizeMax != FileUpload.NO_FILE_SIZE_MAX
+                &&  contentLength != UploadRequest.UNKNOWN_CONTENT_LENGTH
+                &&  contentLength > fileSizeMax) {
+            noteFileSizeMaxExceeded(fileItem, contentLength);
+        }
+        return fileItem;
+    }
+
+    private String getFieldName(MaximalBodyDescriptor pBodyDescriptor) {
+        return pBodyDescriptor.getContentDispositionParameters().get("name");
+    }
+
+    private String getContentType(BodyDescriptor pBodyDescriptor) {
+        return pBodyDescriptor.getMimeType();
+    }
+
+    private String getFileName(MaximalBodyDescriptor pBodyDescriptor) {
+        return pBodyDescriptor.getContentDispositionFilename();
+    }
+
+    @SuppressWarnings("unchecked")
+    public FI next() throws FileUploadException, IOException {
+        if (currentItem == null) {
+            throw new NoSuchElementException("No current file item available; did you invoke hasNext()?");
+        }
+        previousFileItem = currentItem;
+        currentItem = null;
+        if (listener != null) {
+            listener.startItem(fileUpload, request, previousFileItem);
+        }
+        return (FI) previousFileItem;
+    }
+
+    private void skip(LimitedInputStream pStream) throws IOException {
+        while (!pStream.isClosed()) {
+            if (pStream.skip(Integer.MAX_VALUE) == -1) {
+                pStream.close();
+            }
+        }
+    }
+}

Propchange: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryCapableFileItemStore.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryCapableFileItemStore.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryCapableFileItemStore.java (added)
+++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryCapableFileItemStore.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,112 @@
+package org.apache.commons.fileupload2.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.commons.fileupload2.FileItem;
+import org.apache.commons.fileupload2.FileItemStore;
+import org.apache.commons.fileupload2.FileUploadException;
+import org.apache.commons.fileupload2.StoredFileItem;
+import org.apache.commons.fileupload2.util.Streams;
+
+
+/**
+ * Abstract base class for deriving implementations of
+ * {@link FileItemStore}, which keep file items in memory, if
+ * their size doesn't exceed the file item stores {@link #getThreshold()
+ * threshold}.
+ */
+public abstract class MemoryCapableFileItemStore extends FileItemStore {
+    private final byte[] buffer = new byte[8192];
+
+    /**
+     * Default value for the file item stores {@link #getThreshold() threshold}.
+     */
+    private int threshold;
+
+    /**
+     * Returns the file items threshold. If the file items content length
+     * doesn't exceed the threshold, then it will be converted into an
+     * instance of {@link MemoryFileItem}.
+     */
+    public int getThreshold() {
+        return threshold;
+    }
+
+    /**
+     * Sets the file items threshold. If the file items content length
+     * doesn't exceed the threshold, then it will be converted into an
+     * instance of {@link MemoryFileItem}.
+     */
+    public void setThreshold(int pThreshold) {
+        threshold = pThreshold;
+    }
+
+    /**
+     * Creates a new instance of {@link StoredFileItem}. This method
+     * will only be called, if the file items size exceeds the
+     * threshold.
+     *
+     * @param pFileItem An instance of {@link FileItem}, from which
+     *   to copy the properties like {@link FileItem#getFieldName()
+     *   field name}, {@link FileItem#getContentType()}, and so on.
+     * @return An instance of {@link StoredFileItem}, 
+     * @throws FileUploadException
+     * @throws IOException
+     */
+    protected abstract WritableFileItem newWritableFileItem(FileItem pFileItem)
+        throws FileUploadException, IOException;
+
+    /**
+     * Creates a new instance of {@link MemoryFileItem}, if the
+     * file items size doesn't exceed the threshold.
+     * @throws FileUploadException Creating the memory file item failed.
+     * @throws IOException An I/O error occurred.
+     */
+    protected StoredFileItem newMemoryFileItem(FileItem pFileItem, byte[] pBuffer)
+            throws FileUploadException, IOException {
+        final MemoryFileItem mfi = new MemoryFileItem(pFileItem, pBuffer);
+        mfi.setContentLength(pBuffer.length);
+        return mfi;
+    }
+
+    @Override
+    public StoredFileItem store(FileItem pFileItem) throws FileUploadException, IOException {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        InputStream is = pFileItem.getInputStream();
+        OutputStream os = null;
+        try {
+            long length = 0;
+            final int t = getThreshold();
+            for (;;) {
+                int res = is.read(buffer);
+                if (res == -1) {
+                    is.close();
+                    is = null;
+                    return newMemoryFileItem(pFileItem, baos.toByteArray());
+                }
+                if (res > 0) {
+                    length += res;
+                    if (baos.size() + res > t) {
+                        final WritableFileItem asfi = newWritableFileItem(pFileItem);
+                        os = asfi.newOutputStream();
+                        baos.writeTo(os);
+                        os.write(buffer, 0, res);
+                        length += Streams.copy(is, os, true);
+                        asfi.setContentLength(length);
+                        os = null;
+                        is.close();
+                        is = null;
+                        return asfi;
+                    }
+                    baos.write(buffer, 0, res);
+                }
+            }
+        } finally {
+            Streams.close(os);
+            Streams.close(is);
+        }
+    }
+}

Propchange: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryCapableFileItemStore.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryFileItem.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryFileItem.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryFileItem.java (added)
+++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryFileItem.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,76 @@
+package org.apache.commons.fileupload2.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+
+import org.apache.commons.fileupload2.FileItem;
+import org.apache.commons.fileupload2.FileUploadException;
+import org.apache.commons.fileupload2.StoredFileItem;
+
+
+/**
+ * Implementation of a {@link StoredFileItem}, which is completely held
+ * in memory.
+ */
+public class MemoryFileItem extends AbstractStoredFileItem {
+    private static final long serialVersionUID = -5290091310206015619L;
+    private byte[] buffer;
+    private String s, encoding;
+
+    /**
+     * Creates a new instance with default settings.
+     */
+    @SuppressWarnings("unused")
+	private MemoryFileItem() {
+    	// Nothing to do
+    }
+
+    /**
+     * Creates a new instance with the given buffer.
+     */
+    public MemoryFileItem(FileItem pFileItem, byte[] pBuffer) {
+        super(pFileItem);
+        buffer = pBuffer;
+    }
+    
+    public InputStream getInputStream() throws FileUploadException, IOException {
+        if (buffer == null) {
+            throw new FileUploadException("The internal memory buffer has already been deleted.");
+        }
+        return new ByteArrayInputStream(buffer);
+    }
+
+    /**
+     * Converts the memory buffer into a string.
+     */
+    public String getString(String pEncoding) throws FileUploadException, IOException {
+        if (buffer == null) {
+            throw new FileUploadException("The internal memory buffer has already been deleted.");
+        }
+        if (s != null) {
+            if (encoding.equals(pEncoding)) {
+                return s;
+            }
+        }
+        encoding = pEncoding == null ? "UTF-8" : pEncoding;
+        s = new String(buffer, pEncoding);
+        return s;
+    }
+
+    @Override
+    public Reader getReader(String pEncoding) throws FileUploadException, IOException {
+        return new StringReader(getString(pEncoding));
+    }
+
+    public void delete() throws FileUploadException, IOException {
+        buffer = null;
+    }
+
+	@Override
+	public long getContentLength() {
+		return buffer.length;
+	}
+}

Propchange: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/MemoryFileItem.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/WritableFileItem.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/WritableFileItem.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/WritableFileItem.java (added)
+++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/WritableFileItem.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,31 @@
+package org.apache.commons.fileupload2.impl;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.commons.fileupload2.FileUploadException;
+import org.apache.commons.fileupload2.StoredFileItem;
+
+
+/**
+ * Abstract base class for deriving instances of {@link StoredFileItem},
+ * 
+ * @author jwi
+ *
+ */
+public interface WritableFileItem extends StoredFileItem {
+    /**
+     * Creates an output stream, to which the file items contents may
+     * be written.
+     * @return The output stream, to which the file items contents will
+     *   be written.
+     * @throws IOException Creating the output stream failed.
+     */
+    OutputStream newOutputStream() throws FileUploadException, IOException;
+
+    /**
+     * Called to set the file items content length.
+     * @param pContentLength The file items content length.
+     */
+    void setContentLength(long pContentLength);
+}

Propchange: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/impl/WritableFileItem.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/portlet/PortletUploadRequest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/portlet/PortletUploadRequest.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/portlet/PortletUploadRequest.java (added)
+++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/portlet/PortletUploadRequest.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,61 @@
+package org.apache.commons.fileupload2.portlet;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.portlet.ActionRequest;
+
+import org.apache.commons.fileupload2.UploadRequest;
+import org.apache.commons.fileupload2.servlet.HttpServletUploadRequest;
+
+
+/**
+ * Implementation of {@link UploadRequest}, which allows to process
+ * a portlets {@link ActionRequest}.
+ */
+public class PortletUploadRequest implements UploadRequest {
+    private final ActionRequest request;
+
+    /**
+     * Creates a new instance for processing the given {@link ActionRequest}.
+     */
+    public PortletUploadRequest(ActionRequest pRequest) {
+        request = pRequest;
+    }
+
+    public String getCharacterEncoding() {
+        return request.getCharacterEncoding();
+    }
+
+    public long getContentLength() {
+        return request.getContentLength();
+    }
+
+    public String getContentType() {
+        return request.getContentType();
+    }
+
+    public InputStream getInputStream() throws IOException {
+        return request.getPortletInputStream();
+    }
+
+    /**
+     * Utility method that determines whether the request contains multipart
+     * content.
+     *
+     * @param pRequest The portlet 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(ActionRequest pRequest) {
+        String contentType = pRequest.getContentType();
+        if (contentType == null) {
+            return false;
+        }
+        if (contentType.toLowerCase().startsWith(HttpServletUploadRequest.MULTIPART)) {
+            return true;
+        }
+        return false;
+    }
+}

Propchange: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/portlet/PortletUploadRequest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/servlet/HttpServletUploadRequest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/servlet/HttpServletUploadRequest.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/servlet/HttpServletUploadRequest.java (added)
+++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/servlet/HttpServletUploadRequest.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,69 @@
+package org.apache.commons.fileupload2.servlet;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload2.UploadRequest;
+
+
+/**
+ * Implementation of {@link HttpServletUploadRequest} for
+ * servlets, and JSP pages.
+ */
+public class HttpServletUploadRequest implements UploadRequest {
+    /**
+     * Part of HTTP content type header; the method {@link #isMultipartContent(HttpServletRequest)}
+     * returns true, if the content type starts with this string.
+     */
+    public static final String MULTIPART = "multipart/";
+
+    private final HttpServletRequest request;
+
+    /**
+     * Creates a new instance as a wrapper for the given {@link HttpServletRequest}.
+     */
+    public HttpServletUploadRequest(HttpServletRequest pRequest) {
+        request = pRequest;
+    }
+    
+    public String getCharacterEncoding() {
+        return request.getCharacterEncoding();
+    }
+
+    public long getContentLength() {
+        return request.getContentLength();
+    }
+
+    public String getContentType() {
+        return request.getContentType();
+    }
+
+    public InputStream getInputStream() throws IOException {
+        return request.getInputStream();
+    }
+
+    /**
+     * Utility method that determines whether the request contains multipart
+     * content.
+     *
+     * @param pRequest 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 pRequest) {
+        if (!"post".equals(pRequest.getMethod().toLowerCase())) {
+            return false;
+        }
+        String contentType = pRequest.getContentType();
+        if (contentType == null) {
+            return false;
+        }
+        if (contentType.toLowerCase().startsWith(MULTIPART)) {
+            return true;
+        }
+        return false;
+    }
+}

Propchange: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/servlet/HttpServletUploadRequest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/FileUploadUtils.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/FileUploadUtils.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/FileUploadUtils.java (added)
+++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/FileUploadUtils.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,51 @@
+package org.apache.commons.fileupload2.util;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.fileupload2.FileItem;
+import org.apache.commons.fileupload2.FileItemIterator;
+import org.apache.commons.fileupload2.FileUploadException;
+import org.apache.commons.fileupload2.StoredFileItem;
+
+
+/**
+ * Utility class for working with FileUpload.
+ */
+public class FileUploadUtils {
+    /**
+     * Converts the given iterator into a list of items.
+     */
+    public static List<StoredFileItem> asList(FileItemIterator<StoredFileItem> pIterator)
+            throws FileUploadException, IOException {
+        final List<StoredFileItem> list = new ArrayList<StoredFileItem>();
+        while (pIterator.hasNext()) {
+            list.add(pIterator.next());
+        }
+        return list;
+    }
+
+    /**
+     * Converts the given file items contents into a string, using the
+     * encoding UTF-8.
+     */
+    public static String asString(FileItem pFileItem) throws FileUploadException, IOException {
+        return asString(pFileItem, "UTF-8");
+    }
+
+    /**
+     * Converts the given file items contents into a string, using the
+     * given encoding.
+     */
+    public static String asString(FileItem pFileItem, String pEncoding) throws FileUploadException, IOException {
+        return Streams.asString(pFileItem.getInputStream(), pEncoding);
+    }
+
+    /**
+     * Converts the given file items contents into a byte array.
+     */
+    public static byte[] asByteArray(FileItem pItem) throws FileUploadException, IOException {
+        return Streams.asByteArray(pItem.getInputStream());
+    }
+}

Propchange: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/FileUploadUtils.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/LimitedInputStream.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/LimitedInputStream.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/LimitedInputStream.java (added)
+++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/LimitedInputStream.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2.util;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+
+/**
+ * An input stream, which limits its data size. This stream is
+ * used, if the content length is unknown.
+ */
+public abstract class LimitedInputStream extends FilterInputStream {
+    /**
+     * Whether the stream is closed.
+     */
+    private boolean closed;
+    /**
+     * The maximum size of an item, in bytes.
+     */
+    private long sizeMax;
+    /**
+     * The current number of bytes.
+     */
+    private long count;
+
+    /**
+     * Creates a new instance.
+     * @param pIn The input stream, which shall be limited.
+     * @param pSizeMax The limit; no more than this number of bytes
+     *   shall be returned by the source stream.
+     */
+    public LimitedInputStream(InputStream pIn, long pSizeMax) {
+        super(pIn);
+        sizeMax = pSizeMax;
+    }
+
+    /**
+     * Called to indicate, that the input streams limit has
+     * been exceeded.
+     * @param pSizeMax The input streams limit, in bytes.
+     * @param pCount The actual number of bytes.
+     * @throws IOException The called method is expected
+     *   to raise an IOException.
+     */
+    protected abstract void raiseError(long pSizeMax, long pCount)
+            throws IOException;
+
+    /** Called to check, whether the input streams
+     * limit is reached.
+     * @throws IOException The given limit is exceeded.
+     */
+    private void checkLimit() throws IOException {
+        if (sizeMax != 0  &&  count > sizeMax) {
+            raiseError(sizeMax, count);
+            sizeMax = 0;  // Prevent multiple raiseError calls.
+        }
+    }
+
+    /**
+     * Reads the next byte of data from this input stream. The value
+     * byte is returned as an <code>int</code> in the range
+     * <code>0</code> to <code>255</code>. If no byte is available
+     * because the end of the stream has been reached, the value
+     * <code>-1</code> is returned. This method blocks until input data
+     * is available, the end of the stream is detected, or an exception
+     * is thrown.
+     * <p>
+     * This method
+     * simply performs <code>in.read()</code> and returns the result.
+     *
+     * @return     the next byte of data, or <code>-1</code> if the end of the
+     *             stream is reached.
+     * @exception  IOException  if an I/O error occurs.
+     * @see        java.io.FilterInputStream#in
+     */
+    @Override
+    public int read() throws IOException {
+        int res = super.read();
+        if (res != -1) {
+            count++;
+            checkLimit();
+        }
+        return res;
+    }
+
+    /**
+     * Reads up to <code>len</code> bytes of data from this input stream
+     * into an array of bytes. If <code>len</code> is not zero, the method
+     * blocks until some input is available; otherwise, no
+     * bytes are read and <code>0</code> is returned.
+     * <p>
+     * This method simply performs <code>in.read(b, off, len)</code>
+     * and returns the result.
+     *
+     * @param      b     the buffer into which the data is read.
+     * @param      off   The start offset in the destination array
+     *                   <code>b</code>.
+     * @param      len   the maximum number of bytes read.
+     * @return     the total number of bytes read into the buffer, or
+     *             <code>-1</code> if there is no more data because the end of
+     *             the stream has been reached.
+     * @exception  NullPointerException If <code>b</code> is <code>null</code>.
+     * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
+     * <code>len</code> is negative, or <code>len</code> is greater than
+     * <code>b.length - off</code>
+     * @exception  IOException  if an I/O error occurs.
+     * @see        java.io.FilterInputStream#in
+     */
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+        int res = super.read(b, off, len);
+        if (res > 0) {
+            count += res;
+            checkLimit();
+        }
+        return res;
+    }
+
+    /**
+     * Returns the number of items returned by this stream.
+     */
+    public long getCount() {
+        return count;
+    }
+
+    /**
+     * Closes the stream.
+     */
+    @Override
+    public void close() throws IOException {
+        closed = true;
+        super.close();
+    }
+
+    /**
+     * Returns, whether the stream is closed.
+     */
+    public boolean isClosed() {
+        return closed;
+    }
+
+    @Override
+    public long skip(long pCount) throws IOException {
+        long res = super.skip(pCount);
+        if (res > 0) {
+            count += res;
+            checkLimit();
+        }
+        return res;
+    }
+}

Propchange: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/LimitedInputStream.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/Streams.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/Streams.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/Streams.java (added)
+++ commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/Streams.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.commons.fileupload2.FileItem;
+
+
+/** Utility class for working with streams.
+ */
+public final class Streams {
+    /**
+     * Private constructor, to prevent instantiation.
+     * This class has only static methods.
+     */
+    private Streams() {
+        // Does nothing
+    }
+
+    /**
+     * Default buffer size for use in
+     * {@link #copy(InputStream, OutputStream, boolean)}.
+     */
+    private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+    /**
+     * Copies the contents of the given {@link InputStream}
+     * to the given {@link OutputStream}. Shortcut for
+     * <pre>
+     *   copy(pInputStream, pOutputStream, new byte[8192]);
+     * </pre>
+     * @param pInputStream The input stream, which is being read.
+     * It is guaranteed, that {@link InputStream#close()} is called
+     * on the stream.
+     * @param pOutputStream The output stream, to which data should
+     * be written. May be null, in which case the input streams
+     * contents are simply discarded.
+     * @param pClose True guarantees, that {@link OutputStream#close()}
+     * is called on the stream. False indicates, that only
+     * {@link OutputStream#flush()} should be called finally.
+     *
+     * @return Number of bytes, which have been copied.
+     * @throws IOException An I/O error occurred.
+     */
+    public static long copy(InputStream pInputStream,
+            OutputStream pOutputStream, boolean pClose)
+            throws IOException {
+        return copy(pInputStream, pOutputStream, pClose,
+                new byte[DEFAULT_BUFFER_SIZE]);
+    }
+
+    /**
+     * Copies the contents of the given {@link InputStream}
+     * to the given {@link OutputStream}.
+     * @param pIn The input stream, which is being read.
+     *   It is guaranteed, that {@link InputStream#close()} is called
+     *   on the stream.
+     * @param pOut The output stream, to which data should
+     *   be written. May be null, in which case the input streams
+     *   contents are simply discarded.
+     * @param pClose True guarantees, that {@link OutputStream#close()}
+     *   is called on the stream. False indicates, that only
+     *   {@link OutputStream#flush()} should be called finally.
+     * @param pBuffer Temporary buffer, which is to be used for
+     *   copying data.
+     * @return Number of bytes, which have been copied.
+     * @throws IOException An I/O error occurred.
+     */
+    public static long copy(InputStream pIn,
+            OutputStream pOut, boolean pClose,
+            byte[] pBuffer)
+    throws IOException {
+        OutputStream out = pOut;
+        InputStream in = pIn;
+        try {
+            long total = 0;
+            for (;;) {
+                int res = in.read(pBuffer);
+                if (res == -1) {
+                    break;
+                }
+                if (res > 0) {
+                    total += res;
+                    if (out != null) {
+                        out.write(pBuffer, 0, res);
+                    }
+                }
+            }
+            if (out != null) {
+                if (pClose) {
+                    out.close();
+                } else {
+                    out.flush();
+                }
+                out = null;
+            }
+            in.close();
+            in = null;
+            return total;
+        } finally {
+            if (in != null) {
+                try {
+                    in.close();
+                } catch (Throwable t) {
+                    /* Ignore me */
+                }
+            }
+            if (pClose  &&  out != null) {
+                try {
+                    out.close();
+                } catch (Throwable t) {
+                    /* Ignore me */
+                }
+            }
+        }
+    }
+
+    /**
+     * This convenience method allows to read a
+     * {@link FileItem file items}
+     * content into a string. The platform's default character encoding
+     * is used for converting bytes into characters.
+     * @param pStream The input stream to read.
+     * @see #asString(InputStream, String)
+     * @return The streams contents, as a string.
+     * @throws IOException An I/O error occurred.
+     */
+    public static String asString(InputStream pStream) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        copy(pStream, baos, true);
+        return baos.toString();
+    }
+
+    /**
+     * This convenience method allows to read a
+     * {@link FileItem file items} content into a string,
+     * using the given character encoding.
+     * @param pStream The input stream to read.
+     * @param pEncoding The character encoding, typically "UTF-8".
+     * @see #asString(InputStream)
+     * @return The streams contents, as a string.
+     * @throws IOException An I/O error occurred.
+     */
+    public static String asString(InputStream pStream, String pEncoding)
+            throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        copy(pStream, baos, true);
+        return baos.toString(pEncoding);
+    }
+
+    /**
+     * Closes the given output stream safely. Exceptions will be
+     * trapped.
+     */
+    public static void close(OutputStream pOs) {
+        if (pOs != null) {
+            try {
+                pOs.close();
+            } catch (RuntimeException e) {
+                // Do nothing
+            } catch (IOException e) {
+                // Do nothing.
+            }
+        }
+    }
+
+    /**
+     * Closes the given input stream safely. Exceptions will be
+     * trapped.
+     */
+    public static void close(InputStream pIs) {
+        if (pIs != null) {
+            try {
+                pIs.close();
+            } catch (RuntimeException e) {
+                // Do nothing
+            } catch (IOException e) {
+                // Do nothing.
+            }
+        }
+    }
+
+    /**
+     * This convenience method allows to read a {@link FileItem file items}
+     * content into a byte array.
+     * @param pStream The input stream to read.
+     * @return The streams contents, as a byte array.
+     * @throws IOException An I/O error occurred.
+     */
+    public static byte[] asByteArray(InputStream pStream) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        copy(pStream, baos, true);
+        return baos.toByteArray();
+    }
+}

Propchange: commons/sandbox/commons-fileupload2/src/java/org/apache/commons/fileupload2/util/Streams.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/main/assembly/bin.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/main/assembly/bin.xml?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/main/assembly/bin.xml (added)
+++ commons/sandbox/commons-fileupload2/src/main/assembly/bin.xml Sun Jun  6 21:19:54 2010
@@ -0,0 +1,39 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<assembly>
+  <id>bin</id>
+  <formats>
+    <format>tar.gz</format>
+    <format>zip</format>
+  </formats>
+  <includeSiteDirectory>true</includeSiteDirectory>
+  <fileSets>
+    <fileSet>
+      <includes>
+		<include>LICENSE.txt</include>
+        <include>NOTICE.txt</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory>lib</outputDirectory>
+      <includes>
+        <include>*.jar</include>
+      </includes>
+    </fileSet>
+  </fileSets>
+</assembly>

Propchange: commons/sandbox/commons-fileupload2/src/main/assembly/bin.xml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/main/assembly/src.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/main/assembly/src.xml?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/main/assembly/src.xml (added)
+++ commons/sandbox/commons-fileupload2/src/main/assembly/src.xml Sun Jun  6 21:19:54 2010
@@ -0,0 +1,46 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<assembly>
+  <id>src</id>
+  <formats>
+    <format>tar.gz</format>
+    <format>zip</format>
+  </formats>
+  <baseDirectory>${artifactId}-${version}-src</baseDirectory>
+  <fileSets>
+    <fileSet>
+      <includes>
+		<include>build-gump.xml</include>
+		<include>build.xml</include>
+		<include>doap_fileupload.rdf</include>
+		<include>gump.xml</include>
+		<include>LICENSE.txt</include>
+        <include>maven.xml</include>
+        <include>NOTICE.txt</include>
+        <include>pom.xml</include>
+        <include>project.properties</include>
+        <include>project.xml</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>src</directory>
+    </fileSet>
+    <fileSet>
+      <directory>xdocs</directory>
+    </fileSet>
+  </fileSets>
+</assembly>

Propchange: commons/sandbox/commons-fileupload2/src/main/assembly/src.xml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/media/logo.xcf
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/media/logo.xcf?rev=951978&view=auto
==============================================================================
Binary file - no diff available.

Propchange: commons/sandbox/commons-fileupload2/src/media/logo.xcf
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: commons/sandbox/commons-fileupload2/src/site/resources/images/jakarta-logo-blue.gif
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/site/resources/images/jakarta-logo-blue.gif?rev=951978&view=auto
==============================================================================
Binary file - no diff available.

Propchange: commons/sandbox/commons-fileupload2/src/site/resources/images/jakarta-logo-blue.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: commons/sandbox/commons-fileupload2/src/site/resources/images/logo.gif
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/site/resources/images/logo.gif?rev=951978&view=auto
==============================================================================
Binary file - no diff available.

Propchange: commons/sandbox/commons-fileupload2/src/site/resources/images/logo.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: commons/sandbox/commons-fileupload2/src/site/resources/images/logo.png
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/site/resources/images/logo.png?rev=951978&view=auto
==============================================================================
Binary file - no diff available.

Propchange: commons/sandbox/commons-fileupload2/src/site/resources/images/logo.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: commons/sandbox/commons-fileupload2/src/site/site.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/site/site.xml?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/site/site.xml (added)
+++ commons/sandbox/commons-fileupload2/src/site/site.xml Sun Jun  6 21:19:54 2010
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project name="FileUpload">
+
+  <bannerRight>
+    <name>Commons FileUpload</name>
+    <src>/images/logo.png</src>
+    <href>/index.html</href>
+  </bannerRight>
+
+  <body>
+
+    <menu name="Commons FileUpload">
+      <item name="Overview"                 href="/index.html"/>
+      <item name="User guide"               href="/using.html"/>
+      <item name="Streaming API"            href="/streaming.html"/>
+      <item name="FAQ"                      href="/faq.html"/>
+      <item name="Javadoc"                  href="apidocs/index.html"/>
+      <item name="Mailing lists"            href="/mail-lists.html"/>
+      <item name="Issue Tracking"           href="/issue-tracking.html"/>
+      <item name="Team"                     href="/team-list.html"/>
+      <item name="Tasks"                    href="/tasks.html"/>
+      <item name="SVN repository"           href="/source-repository.html"/>
+    </menu>
+
+  </body>
+</project>

Propchange: commons/sandbox/commons-fileupload2/src/site/site.xml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DefaultFileItemTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DefaultFileItemTest.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DefaultFileItemTest.java (added)
+++ commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DefaultFileItemTest.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,310 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+import org.apache.commons.fileupload2.disk.DiskFileItem;
+import org.apache.commons.fileupload2.disk.DiskFileItemStore;
+import org.apache.commons.fileupload2.impl.AbstractFileItem;
+import org.apache.commons.fileupload2.impl.MemoryFileItem;
+import org.apache.commons.fileupload2.util.Streams;
+import org.junit.Test;
+
+
+/**
+ * Unit tests for {@link DiskFileItem}.
+ *
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ */
+public class DefaultFileItemTest {
+
+    /**
+     * Content type for regular form items.
+     */
+    private static final String textContentType = "text/plain";
+
+    /**
+     * Content type for file uploads.
+     */
+    private static final String fileContentType = "application/octet-stream";
+
+    /**
+     * Very low threshold for testing memory versus disk options.
+     */
+    private static final int threshold = 16;
+
+    /**
+     * Test construction of a regular text field.
+     */
+    @Test public void testTextFieldConstruction() throws IOException {
+        final String textFieldName = "textField";
+        final FileItem item = createFileItem(textFieldName, null, textContentType, new byte[0]);
+        assertNotNull(item);
+        assertEquals(item.getFieldName(), textFieldName);
+        assertEquals(item.getContentType(), textContentType);
+        assertTrue(item.isFormField());
+        assertNull(item.getFileName());
+
+        final FileItemStore fileItemStore = createFileItemStore(null);
+        final StoredFileItem storedFileItem = fileItemStore.store(item);
+        assertNotNull(storedFileItem);
+        assertEquals(storedFileItem.getFieldName(), textFieldName);
+        assertEquals(storedFileItem.getContentType(), textContentType);
+        assertTrue(storedFileItem.isFormField());
+        assertNull(storedFileItem.getFileName());
+    }
+
+    /**
+     * Test construction of a file field.
+     */
+    @Test public void testFileFieldConstruction() throws IOException {
+        final String fileFieldName = "fileField";
+        final String fileName = "originalFileName";
+        final FileItem item = createFileItem(fileFieldName, fileName, fileContentType, new byte[0]);
+        assertNotNull(item);
+        assertEquals(item.getFieldName(), fileFieldName);
+        assertEquals(item.getContentType(), fileContentType);
+        assertFalse(item.isFormField());
+        assertEquals(item.getFileName(), fileName);
+
+        final FileItemStore fileItemStore = createFileItemStore(null);
+        final StoredFileItem storedFileItem = fileItemStore.store(item);
+        assertNotNull(storedFileItem);
+        assertEquals(storedFileItem.getFieldName(), fileFieldName);
+        assertEquals(storedFileItem.getContentType(), fileContentType);
+        assertFalse(storedFileItem.isFormField());
+        assertEquals(storedFileItem.getFileName(), fileName);
+    }
+
+    /**
+     * Test creation of a field for which the amount of data falls below the
+     * configured threshold.
+     */
+    @Test public void testBelowThreshold() throws IOException {
+        final String textFieldName = "textField";
+        final String textFieldValue = "0123456789";
+        final byte[] testFieldValueBytes = textFieldValue.getBytes();
+
+        final FileItem item = createFileItem(textFieldName, null, textContentType, testFieldValueBytes);
+        final FileItemStore fileItemStore = createFileItemStore(null);
+        final StoredFileItem storedFileItem = fileItemStore.store(item);
+        assertNotNull(storedFileItem);
+        assertTrue(storedFileItem instanceof MemoryFileItem);
+        assertEquals(testFieldValueBytes.length, storedFileItem.getContentLength());
+        assertTrue(Arrays.equals(Streams.asByteArray(storedFileItem.getInputStream()), testFieldValueBytes));
+        assertEquals(Streams.asString(storedFileItem.getInputStream()), textFieldValue);
+    }
+
+    /**
+     * Test creation of a field for which the amount of data falls above the
+     * configured threshold, where no specific repository is configured.
+     */
+    @Test public void testAboveThresholdDefaultRepository() throws IOException {
+        doTestAboveThreshold(null);
+    }
+
+    /**
+     * Test creation of a field for which the amount of data falls above the
+     * configured threshold, where a specific repository is configured.
+     */
+    @Test public void testAboveThresholdSpecifiedRepository() throws IOException {
+        String tempPath = System.getProperty("java.io.tmpdir");
+        String tempDirName = "testAboveThresholdSpecifiedRepository";
+        File tempDir = new File(tempPath, tempDirName);
+        tempDir.mkdir();
+        doTestAboveThreshold(tempDir);
+        assertTrue(tempDir.delete());
+    }
+
+    /**
+     * Common code for cases where the amount of data is above the configured
+     * threshold, but the ultimate destination of the data has not yet been
+     * determined.
+     *
+     * @param repository The directory within which temporary files will be
+     *                   created.
+     */
+    public void doTestAboveThreshold(File repository) throws IOException
+    {
+        String textFieldName = "textField";
+        String textFieldValue = "01234567890123456789";
+        byte[] testFieldValueBytes = textFieldValue.getBytes();
+
+        final FileItem item = createFileItem(textFieldName, null, textContentType, testFieldValueBytes);
+        assertNotNull(item);
+        FileItemStore factory = createFileItemStore(repository);
+        final StoredFileItem storedFileItem = factory.store(item);
+        assertTrue(storedFileItem instanceof DiskFileItem);
+        assertEquals(testFieldValueBytes.length, storedFileItem.getContentLength());
+        assertTrue(Arrays.equals(Streams.asByteArray(storedFileItem.getInputStream()), testFieldValueBytes));
+        assertEquals(Streams.asString(storedFileItem.getInputStream()), textFieldValue);
+
+        DiskFileItem diskFileItem = (DiskFileItem) storedFileItem;
+        final File file = diskFileItem.getFile();
+        assertNotNull(file);
+        assertTrue(file.isFile());
+        assertEquals(file.length(), testFieldValueBytes.length);
+
+        if (repository != null)
+        {
+            assertEquals(file.getParentFile(), repository);
+        }
+
+        diskFileItem.delete();
+        assertFalse(file.exists());
+    }
+
+    /**
+     * Creates a new instance of {@link FileItem}.
+     * @param pFieldName The file items field name.
+     * @param pFileName The file items file name, if any, or null.
+     * @param pContentType The file items content type.
+     * @param pContent The file items content.
+     */
+    protected FileItem createFileItem(String pFieldName, String pFileName,
+            String pContentType, final byte[] pContent) {
+        final AbstractFileItem item = new AbstractFileItem(){
+            public InputStream getInputStream() throws FileUploadException,
+                    IOException {
+                return new ByteArrayInputStream(pContent);
+            }
+        };
+        item.setFieldName(pFieldName);
+        item.setContentType(pContentType);
+        item.setFormField(pFileName == null);
+        item.setFileName(pFileName);
+        return item;
+    }
+
+    /**
+     * Creates a new <code>FileItemFactory</code> and returns it, obscuring
+     * from the caller the underlying implementation of this interface.
+     *
+     * @param repository The directory within which temporary files will be
+     *                   created.
+     * @return the new <code>FileItemFactory</code> instance.
+     */
+    protected FileItemStore createFileItemStore(File repository)
+    {
+        final DiskFileItemStore store = new DiskFileItemStore();
+        store.setThreshold(threshold);
+        store.setRepository(repository);
+        return store;
+    }
+
+
+    static final String CHARSET_ISO88591 = "ISO-8859-1";
+    static final String CHARSET_ASCII = "US-ASCII";
+    static final String CHARSET_UTF8 = "UTF-8";
+    static final String CHARSET_KOI8_R = "KOI8_R";
+    static final String CHARSET_WIN1251 = "Cp1251";
+
+    static final int SWISS_GERMAN_STUFF_UNICODE [] = 
+    {
+        0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
+    };
+    
+    static final int SWISS_GERMAN_STUFF_ISO8859_1 [] = 
+    {
+        0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
+    };
+    
+    static final int SWISS_GERMAN_STUFF_UTF8 [] = 
+    {
+        0x47, 0x72, 0xC3, 0xBC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xC3, 0xA4,
+        0x6D, 0xC3, 0xA4
+    };
+
+    static final int RUSSIAN_STUFF_UNICODE [] = 
+    {
+        0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438, 
+        0x432, 0x435, 0x442 
+    }; 
+
+    static final int RUSSIAN_STUFF_UTF8 [] = 
+    {
+        0xD0, 0x92, 0xD1, 0x81, 0xD0, 0xB5, 0xD0, 0xBC, 0x5F, 
+        0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 
+        0xB5, 0xD1, 0x82
+    };
+
+    static final int RUSSIAN_STUFF_KOI8R [] = 
+    {
+        0xF7, 0xD3, 0xC5, 0xCD, 0x5F, 0xD0, 0xD2, 0xC9, 0xD7, 
+        0xC5, 0xD4
+    };
+
+    static final int RUSSIAN_STUFF_WIN1251 [] = 
+    {
+        0xC2, 0xF1, 0xE5, 0xEC, 0x5F, 0xEF, 0xF0, 0xE8, 0xE2, 
+        0xE5, 0xF2
+    };
+
+
+    private static String constructString(int[] unicodeChars)
+    {
+        StringBuffer buffer = new StringBuffer();
+        if (unicodeChars != null)
+        {
+            for (int i = 0; i < unicodeChars.length; i++)
+            {
+                buffer.append((char) unicodeChars[i]);
+            }
+        }
+        return buffer.toString();
+    }
+
+    private void testContentCharSet(int[] pUnicodeContent, int[] pCharsetContent, String pCharset) throws IOException {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        for (int i = 0;  i < pCharsetContent.length;  i++) {
+            baos.write(pCharsetContent[i]);
+        }
+        final byte[] contents = baos.toByteArray();
+        String teststr = constructString(pUnicodeContent);
+        final FileItem item = createFileItem("doesnotmatter", null, 
+            "text/plain; charset=" + pCharset,
+            contents);
+        final ByteArrayOutputStream got = new ByteArrayOutputStream();
+        Streams.copy(item.getInputStream(), got, true);
+        assertArrayEquals(contents, got.toByteArray());
+        assertEquals(teststr, teststr, Streams.asString(new ByteArrayInputStream(got.toByteArray()), pCharset));
+    }
+    
+    /**
+     * Test construction of content charset.
+     */
+    @Test public void testContentCharSet() throws Exception {
+        testContentCharSet(SWISS_GERMAN_STUFF_UNICODE, SWISS_GERMAN_STUFF_ISO8859_1, CHARSET_ISO88591);
+        testContentCharSet(SWISS_GERMAN_STUFF_UNICODE, SWISS_GERMAN_STUFF_UTF8, CHARSET_UTF8);
+        testContentCharSet(RUSSIAN_STUFF_UNICODE, RUSSIAN_STUFF_KOI8R, CHARSET_KOI8_R);
+        testContentCharSet(RUSSIAN_STUFF_UNICODE, RUSSIAN_STUFF_WIN1251, CHARSET_WIN1251);
+        testContentCharSet(RUSSIAN_STUFF_UNICODE, RUSSIAN_STUFF_UTF8, CHARSET_UTF8);
+    }
+}

Propchange: commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DefaultFileItemTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DiskFileItemSerializeTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DiskFileItemSerializeTest.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DiskFileItemSerializeTest.java (added)
+++ commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DiskFileItemSerializeTest.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.commons.fileupload2.disk.DiskFileItem;
+import org.apache.commons.fileupload2.disk.DiskFileItemStore;
+import org.apache.commons.fileupload2.impl.MemoryFileItem;
+import org.apache.commons.fileupload2.util.Streams;
+import org.junit.Test;
+
+
+/**
+ * Serialization Unit tests for {@link DiskFileItem}.
+ */
+public class DiskFileItemSerializeTest {
+    /**
+     * Content type for regular form items.
+     */
+    private static final String textContentType = "text/plain";
+
+    /**
+     * Very low threshold for testing memory versus disk options.
+     */
+    private static final int threshold = 16;
+
+    private void checkItem(StoredFileItem pItem, boolean pIsInMemory, byte[] pContents) throws IOException {
+    	if (pIsInMemory) {
+    		assertTrue("Initial: in memory", pItem instanceof MemoryFileItem);
+    	} else {
+    		assertFalse("Initial: in memory", pItem instanceof MemoryFileItem);
+    	}
+        assertEquals("Initial: size", pItem.getContentLength(), pContents.length);
+        compareBytes("Initial", Streams.asByteArray(pItem.getInputStream()), pContents);
+    }
+
+    private void checkItem(StoredFileItem pItem, byte[] pContents, boolean pIsInMemory)
+    		throws IOException, ClassNotFoundException {
+        // Check state is as expected
+    	checkItem(pItem, pIsInMemory, pContents);
+
+        // Serialize & Deserialize
+        StoredFileItem newItem = (StoredFileItem) serializeDeserialize(pItem);
+
+        // Test deserialized content is as expected
+        checkItem(newItem, pIsInMemory, pContents);
+
+        // Compare FileItem's (except byte[])
+        compareFileItems(pItem, newItem);
+    }
+    
+    /**
+     * Test creation of a field for which the amount of data falls below the
+     * configured threshold.
+     */
+    @Test public void testBelowThreshold() throws Exception {
+        runTest(threshold - 1, true);
+    }
+
+	private void runTest(int pSize, boolean pIsInMemory)
+			throws IOException, ClassNotFoundException {
+		// Create the FileItem
+        byte[] testFieldValueBytes = createContentBytes(pSize);
+        StoredFileItem item = createFileItem(testFieldValueBytes);
+        checkItem(item, testFieldValueBytes, pIsInMemory);
+	}
+
+    /**
+     * Test creation of a field for which the amount of data equals the
+     * configured threshold.
+     */
+    @Test public void testThreshold() throws Exception {
+        runTest(threshold, true);
+    }
+
+    /**
+     * Test creation of a field for which the amount of data falls above the
+     * configured threshold.
+     */
+    @Test public void testAboveThreshold() throws Exception {
+        runTest(threshold+1, false);
+    }
+
+    /**
+     * Compare FileItem's (except the byte[] content)
+     */
+    private void compareFileItems(StoredFileItem pOrigItem, StoredFileItem pNewItem) {
+    	if (pOrigItem instanceof MemoryFileItem) {
+    		assertTrue("Compare: is in Memory", pNewItem instanceof MemoryFileItem);
+    	} else {
+    		assertFalse("Compare: is in Memory", pNewItem instanceof MemoryFileItem);
+    	}
+    	if (pOrigItem.isFormField()) {
+    		assertTrue("Compare: is Form Field", pNewItem.isFormField());
+    	} else {
+    		assertFalse("Compare: is Form Field", pNewItem.isFormField());
+    	}
+        assertEquals("Compare: Field Name", pOrigItem.getFieldName(), pNewItem.getFieldName());
+        assertEquals("Compare: Content Type", pOrigItem.getContentType(), pNewItem.getContentType());
+        assertEquals("Compare: File Name", pOrigItem.getFileName(), pNewItem.getFileName());
+    }
+
+    /**
+     * Compare content bytes.
+     */
+    private void compareBytes(String text, byte[] origBytes, byte[] newBytes) {
+    	assertNotNull(text + " origBytes are null", origBytes);
+    	assertNotNull(text + " newBytes are null", newBytes);
+    	assertEquals(text + " byte[] length", origBytes.length, newBytes.length);
+    	for (int i = 0; i < origBytes.length; i++) {
+    		assertEquals(text + " byte[" + i + "]", origBytes[i], newBytes[i]);
+    	}
+    }
+
+    /**
+     * Create content bytes of a specified size.
+     */
+    private byte[] createContentBytes(int size) {
+        StringBuffer buffer = new StringBuffer(size);
+        byte count = 0;
+        for (int i = 0; i < size; i++) {
+            buffer.append(count+"");
+            count++;
+            if (count > 9) {
+                count = 0;
+            }
+        }
+        return buffer.toString().getBytes();
+    }
+
+    /**
+     * Create a FileItem with the specfied content bytes.
+     */
+    private StoredFileItem createFileItem(final byte[] contentBytes) throws IOException {
+    	final DiskFileItemStore store = new DiskFileItemStore();
+    	store.setThreshold(threshold);
+    	final String textFieldName = "textField";
+    	final StoredFileItem storedItem = store.store(new FileItem(){
+			public String getContentType() { return textContentType; }
+			public String getFileName() { return "My File Name"; }
+			public long getContentLength() { return UploadRequest.UNKNOWN_CONTENT_LENGTH; }
+			public String getFieldName() { return textFieldName; }
+			public boolean isFormField() { return true; }
+			public String getEncoding() { return null; }
+			public InputStream getInputStream() throws FileUploadException, IOException {
+				return new ByteArrayInputStream(contentBytes);
+			}
+			public Reader getReader(String pEncoding)
+					throws FileUploadException, UnsupportedEncodingException,
+					IOException {
+				throw new IllegalStateException("Not implemented");
+			}
+    	});
+        return storedItem;
+
+    }
+
+    /**
+     * Do serialization and deserialization.
+     */
+    private Object serializeDeserialize(Object target) throws IOException, ClassNotFoundException {
+
+        // Serialize the test object
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(baos);
+        oos.writeObject(target);
+        oos.flush();
+        oos.close();
+
+        // Deserialize the test object
+        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+        ObjectInputStream ois = new ObjectInputStream(bais);
+        final Object result = ois.readObject();
+        bais.close();
+        return result;
+    }
+
+}

Propchange: commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/DiskFileItemSerializeTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/FileUploadTestCase.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/FileUploadTestCase.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/FileUploadTestCase.java (added)
+++ commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/FileUploadTestCase.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload2.disk.DiskFileItemStore;
+import org.apache.commons.fileupload2.servlet.HttpServletUploadRequest;
+import org.apache.commons.fileupload2.util.FileUploadUtils;
+
+
+/**
+ * Base class for deriving test cases.
+ */
+public abstract class FileUploadTestCase {
+	protected static final String CONTENT_TYPE = "multipart/form-data; boundary=---1234";
+
+	protected List<StoredFileItem> parseUpload(byte[] bytes)
+	        throws FileUploadException, IOException {
+        return parseUpload(bytes, CONTENT_TYPE);
+    }
+
+	protected List<StoredFileItem> parseUpload(byte[] bytes, String contentType)
+	        throws FileUploadException, IOException {
+        final HttpServletRequest request = new MockHttpServletRequest(bytes, contentType);
+	    return parseUpload(request);
+	}
+
+    protected List<StoredFileItem> parseUpload(final HttpServletRequest request)
+            throws FileUploadException, IOException {
+        final FileUpload fileUpload = new FileUpload();
+        final DiskFileItemStore store = new DiskFileItemStore();
+        final FileItemIterator<StoredFileItem> fii = store.parse(fileUpload, new HttpServletUploadRequest(request));
+        return FileUploadUtils.asList(fii);
+    }
+
+	protected List<StoredFileItem> parseUpload(String content)
+    	    throws FileUploadException, IOException {
+		byte[] bytes = content.getBytes("US-ASCII");
+		return parseUpload(bytes, CONTENT_TYPE);
+    }
+}

Propchange: commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/FileUploadTestCase.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/HttpServletRequestFactory.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/HttpServletRequestFactory.java?rev=951978&view=auto
==============================================================================
--- commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/HttpServletRequestFactory.java (added)
+++ commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/HttpServletRequestFactory.java Sun Jun  6 21:19:54 2010
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2;
+
+import javax.servlet.http.HttpServletRequest;
+
+
+/**
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+final class HttpServletRequestFactory
+{
+	static public HttpServletRequest createHttpServletRequestWithNullContentType()
+	{
+		byte[] requestData = "foobar".getBytes();
+		return new MockHttpServletRequest(
+							requestData,
+							null);
+	}
+
+	static public HttpServletRequest createValidHttpServletRequest(
+			final String[] strFileNames)
+	{
+		// todo - provide a real implementation
+
+		StringBuffer sbRequestData = new StringBuffer();
+
+		for (int i = 0; i < strFileNames.length; i++)
+		{
+			sbRequestData.append(strFileNames[i]);
+		}
+
+		byte[] requestData = null;
+		requestData = sbRequestData.toString().getBytes();
+
+		return new MockHttpServletRequest(requestData, "multipart/form-data");
+	}
+
+	static public HttpServletRequest createInvalidHttpServletRequest()
+	{
+		byte[] requestData = "foobar".getBytes();
+		return new MockHttpServletRequest(requestData, "multipart/form-data");
+	}
+}

Propchange: commons/sandbox/commons-fileupload2/src/test/org/apache/commons/fileupload2/HttpServletRequestFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain