Author: mgrigorov Date: Sun Dec 5 13:08:00 2010 New Revision: 1042345 URL: http://svn.apache.org/viewvc?rev=1042345&view=rev Log: Merge r942052 from 1.4.x: author: jcompagner commit message: latest code from FileUpload and patched for generating more random files date: Fri May 7 11:29:36 2010 UTC
Added: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/Closeable.java - copied, changed from r1042295, wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/RequestContext.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeaders.java (with props) wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeadersImpl.java (with props) wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeadersSupport.java - copied, changed from r1042295, wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/RequestContext.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemIterator.java (with props) wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemStream.java (with props) wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/LimitedInputStream.java (with props) wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/ProgressListener.java - copied, changed from r1042295, wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/RequestContext.java Modified: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/DeferredFileOutputStream.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/Streams.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItem.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItemFactory.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItem.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileUpload.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileUploadBase.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileUploadException.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/MultipartFormInputStream.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/ParameterParser.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/RequestContext.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/ServletFileUpload.java wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/ServletRequestContext.java Modified: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/DeferredFileOutputStream.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/DeferredFileOutputStream.java?rev=1042345&r1=1042344&r2=1042345&view=diff ============================================================================== --- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/DeferredFileOutputStream.java (original) +++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/DeferredFileOutputStream.java Sun Dec 5 13:08:00 2010 @@ -21,6 +21,7 @@ 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 @@ -34,7 +35,6 @@ import java.io.OutputStream; * </p> * * @author <a href="mailto:mart...@apache.org">Martin Cooper</a> - * @version $Id$ */ public class DeferredFileOutputStream extends ThresholdingOutputStream { @@ -58,7 +58,10 @@ public class DeferredFileOutputStream ex /** * The file to which output will be directed if the threshold is exceeded. */ - private final File outputFile; + private File outputFile; + + + private final FileFactory fileFactory; // ----------------------------------------------------------- Constructors @@ -76,7 +79,30 @@ public class DeferredFileOutputStream ex public DeferredFileOutputStream(final int threshold, final File outputFile) { super(threshold); + if (outputFile == null) + throw new IllegalArgumentException("output file must be specified"); this.outputFile = outputFile; + fileFactory = null; + + memoryOutputStream = new ByteArrayOutputStream(); + currentOutputStream = memoryOutputStream; + } + + /** + * 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 fileFactory + * The FileFactory to create the file. + */ + public DeferredFileOutputStream(int threshold, FileFactory fileFactory) + { + super(threshold); + if (fileFactory == null) + throw new IllegalArgumentException("FileFactory must be specified"); + this.fileFactory = fileFactory; memoryOutputStream = new ByteArrayOutputStream(); currentOutputStream = memoryOutputStream; @@ -155,9 +181,26 @@ public class DeferredFileOutputStream ex protected void thresholdReached() throws IOException { byte[] data = memoryOutputStream.toByteArray(); + if (outputFile == null) + { + outputFile = fileFactory.createFile(); + } FileOutputStream fos = new FileOutputStream(outputFile); fos.write(data); currentOutputStream = fos; memoryOutputStream = null; } + + /** + * The file factory for this deferred file output stream. + * + * @author jcompagner + */ + public interface FileFactory + { + /** + * @return the file to use for disk cache + */ + File createFile(); +} } Modified: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/Streams.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/Streams.java?rev=1042345&r1=1042344&r2=1042345&view=diff ============================================================================== --- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/Streams.java (original) +++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/Streams.java Sun Dec 5 13:08:00 2010 @@ -49,6 +49,30 @@ public final class Streams /** * Writes the input stream to the output stream. Input is done without a Reader object, meaning + * that the input is copied in its raw form. After it is copied it will close the streams. + * + * @param in + * The input stream + * @param out + * The output stream + * @return Number of bytes copied from one stream to the other + * @throws IOException + */ + public static long copyAndClose(InputStream in, OutputStream out) throws IOException + { + try + { + return copy(in, out); + } + finally + { + IOUtils.closeQuietly(in); + IOUtils.closeQuietly(out); + } + } + + /** + * Writes the input stream to the output stream. Input is done without a Reader object, meaning * that the input is copied in its raw form. * * @param in Copied: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/Closeable.java (from r1042295, wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/RequestContext.java) URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/Closeable.java?p2=wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/Closeable.java&p1=wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/RequestContext.java&r1=1042295&r2=1042345&rev=1042345&view=diff ============================================================================== --- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/RequestContext.java (original) +++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/Closeable.java Sun Dec 5 13:08:00 2010 @@ -17,41 +17,27 @@ package org.apache.wicket.util.upload; import java.io.IOException; -import java.io.InputStream; + /** - * <p> - * Abstracts access to the request information needed for file uploads. This interface should be - * implemented for each type of request that may be handled by FileUpload, such as servlets and - * portlets. - * </p> - * - * @author <a href="mailto:mart...@apache.org">Martin Cooper</a> + * Interface of an object, which may be closed. */ -public interface RequestContext +public interface Closeable { - - /** - * Retrieve the content type of the request. - * - * @return The content type of the request. - */ - String getContentType(); - /** - * Retrieve the content length of the request. + * Closes the object. * - * @return The content length of the request. + * @throws IOException + * An I/O error occurred. */ - int getContentLength(); + void close() throws IOException; /** - * Retrieve the input stream for the request. - * - * @return The input stream for the request. + * Returns, whether the object is already closed. * + * @return True, if the object is closed, otherwise false. * @throws IOException - * if a problem occurs. + * An I/O error occurred. */ - InputStream getInputStream() throws IOException; + boolean isClosed() throws IOException; } Modified: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItem.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItem.java?rev=1042345&r1=1042344&r2=1042345&view=diff ============================================================================== --- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItem.java (original) +++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItem.java Sun Dec 5 13:08:00 2010 @@ -16,19 +16,27 @@ */ package org.apache.wicket.util.upload; +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.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.Map; +import java.util.Random; +import java.util.UUID; import org.apache.wicket.util.file.FileCleaner; import org.apache.wicket.util.file.Files; import org.apache.wicket.util.io.DeferredFileOutputStream; +import org.apache.wicket.util.io.IOUtils; +import org.apache.wicket.util.io.Streams; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,10 +46,22 @@ import org.slf4j.LoggerFactory; * interface. * * <p> - * After retrieving an instance of this class, 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. + * After retrieving an instance of this class from a + * {...@link org.apache.wicket.util.upload.DiskFileUpload DiskFileUpload} instance (see + * {...@link org.apache.wicket.util.upload.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. + * + * <p> + * When using the <code>DiskFileItemFactory</code>, then you should consider the following: + * Temporary files are automatically deleted as soon as they are no longer needed. (More precisely, + * when the corresponding instance of {...@link java.io.File} is garbage collected.) This is done by + * the so-called reaper thread, which is started automatically when the class + * {...@link org.apache.commons.io.FileCleaner} is loaded. It might make sense to terminate that + * thread, for example, if your web application ends. See the section on "Resource cleanup" in the + * users guide of commons-fileupload. + * </p> * * @author <a href="mailto:rafal.krzew...@e-point.pl">Rafal Krzewski</a> * @author <a href="mailto:s...@informage.net">Sean Legassick</a> @@ -50,13 +70,16 @@ import org.slf4j.LoggerFactory; * @author <a href="mailto:mart...@apache.org">Martin Cooper</a> * @author Sean C. Sullivan */ -public class DiskFileItem implements FileItem +public class DiskFileItem implements FileItem, FileItemHeadersSupport { private static final Logger log = LoggerFactory.getLogger(DiskFileItem.class); - private static final long serialVersionUID = 1L; - // ----------------------------------------------------- Manifest constants + /** + * The UID to use when serializing this instance. + */ + private static final long serialVersionUID = 2237570099615271025L; + /** * Default content charset to be used when no explicit charset parameter is provided by the @@ -67,12 +90,18 @@ public class DiskFileItem implements Fil // ----------------------------------------------------------- Data members - /** - * Counter used in unique identifier generation. + * UID used in unique file name generation. */ - private static int counter = 0; + private static final String UID = UUID.randomUUID() + .toString() + .replace(':', '_') + .replace('-', '_'); + /** + * Random counter used in unique identifier generation. + */ + private static final Random counter = new Random(); /** * The name of the form field as provided by the browser. @@ -99,6 +128,13 @@ public class DiskFileItem implements Fil /** + * The size of the item, in bytes. This is used to cache the size when a file item is moved from + * its original location. + */ + private long size = -1; + + + /** * The threshold above which uploads will be stored on disk. */ private final int sizeThreshold; @@ -121,6 +157,20 @@ public class DiskFileItem implements Fil */ private transient DeferredFileOutputStream dfos; + /** + * The temporary file to use. + */ + private transient File tempFile; + + /** + * File to allow for serialization of the content of this item. + */ + private File dfosFile; + + /** + * The file items headers. + */ + private FileItemHeaders headers; // ----------------------------------------------------------- Constructors @@ -167,12 +217,12 @@ public class DiskFileItem implements Fil * @return An {...@link java.io.InputStream InputStream} that can be used to retrieve the contents * of the file. * - * @exception IOException - * if an error occurs. + * @throws IOException + * if an error occurs. */ public InputStream getInputStream() throws IOException { - if (!dfos.isInMemory()) + if (!isInMemory()) { return new FileInputStream(dfos.getFile()); } @@ -233,7 +283,11 @@ public class DiskFileItem implements Fil */ public boolean isInMemory() { - return (dfos.isInMemory()); + if (cachedContent != null) + { + return true; + } + return dfos.isInMemory(); } @@ -244,7 +298,11 @@ public class DiskFileItem implements Fil */ public long getSize() { - if (cachedContent != null) + if (size >= 0) + { + return size; + } + else if (cachedContent != null) { return cachedContent.length; } @@ -267,7 +325,7 @@ public class DiskFileItem implements Fil */ public byte[] get() { - if (dfos.isInMemory()) + if (isInMemory()) { if (cachedContent == null) { @@ -299,8 +357,8 @@ public class DiskFileItem implements Fil * * @return The contents of the file, as a string. * - * @exception UnsupportedEncodingException - * if the requested character encoding is not available. + * @throws UnsupportedEncodingException + * if the requested character encoding is not available. */ public String getString(final String charset) throws UnsupportedEncodingException { @@ -351,8 +409,8 @@ public class DiskFileItem implements Fil * @param file * The <code>File</code> into which the uploaded item should be stored. * - * @exception Exception - * if an error occurs. + * @throws Exception + * if an error occurs. */ public void write(final File file) throws IOException { @@ -379,11 +437,27 @@ public class DiskFileItem implements Fil "for a non-memory upload the file location must not be empty"); } - // The uploaded file is being stored on disk in a temporary location so move it to - // the desired file. - if (outputFile.renameTo(file) == false) + // Save the length of the file + size = outputFile.length(); + /* + * The uploaded file is being stored on disk in a temporary location so move it to the + * desired file. + */ + if (!outputFile.renameTo(file)) { - Files.copy(outputFile, file); + BufferedInputStream in = null; + BufferedOutputStream out = null; + try + { + in = new BufferedInputStream(new FileInputStream(outputFile)); + out = new BufferedOutputStream(new FileOutputStream(file)); + Streams.copy(in, out); + } + finally + { + IOUtils.closeQuietly(in); + IOUtils.closeQuietly(out); + } } } } @@ -476,15 +550,21 @@ public class DiskFileItem implements Fil * @return An {...@link java.io.OutputStream OutputStream} that can be used for storing the * contensts of the file. * - * @exception IOException - * if an error occurs. + * @throws IOException + * if an error occurs. */ public OutputStream getOutputStream() throws IOException { if (dfos == null) { - File outputFile = getTempFile(); - dfos = new DeferredFileOutputStream(sizeThreshold, outputFile); + dfos = new DeferredFileOutputStream(sizeThreshold, + new DeferredFileOutputStream.FileFactory() + { + public File createFile() + { + return getTempFile(); + } + }); } return dfos; } @@ -504,7 +584,7 @@ public class DiskFileItem implements Fil */ public File getStoreLocation() { - return dfos.getFile(); + return dfos == null ? null : dfos.getFile(); } @@ -541,57 +621,74 @@ public class DiskFileItem implements Fil */ protected File getTempFile() { - File tempDir = repository; - - if (tempDir == null) + if (tempFile == null) { + File tempDir = repository; + if (tempDir == null) + { + String systemTmp = null; + try + { + systemTmp = System.getProperty("java.io.tmpdir"); + } + catch (SecurityException e) + { + throw new RuntimeException( + "Reading property java.io.tmpdir is not allowed" + + " for the current security settings. The repository location needs to be" + + " set manually, or upgrade permissions to allow reading the tmpdir property."); + } + tempDir = new File(systemTmp); + } + try { - tempDir = new File(System.getProperty("java.io.tmpdir")); + do + { + String tempFileName = "upload_" + UID + "_" + getUniqueId() + ".tmp"; + tempFile = new File(tempDir, tempFileName); + } + while (!tempFile.createNewFile()); } - catch (SecurityException e) + catch (IOException e) { - throw new RuntimeException("Reading property java.io.tmpdir is not allowed" - + " for the current security settings. The repository location needs to be" - + " set manually, or upgrade permissions to allow reading the tmpdir property."); + throw new RuntimeException("Could not create the temp file for upload", e); } - } - - String fileName = "upload_" + getUniqueId() + ".tmp"; - File f = new File(tempDir, fileName); - FileCleaner.track(f, this); - return f; + FileCleaner.track(tempFile, this); + } + return tempFile; } - // -------------------------------------------------------- Private methods /** * Returns an identifier that is unique within the class loader used to load this class, but - * does not have random-like apearance. + * does not have random-like appearance. * * @return A String with the non-random looking instance identifier. */ private static String getUniqueId() { + final int limit = 100000000; int current; synchronized (DiskFileItem.class) { - current = counter++; + current = counter.nextInt(); } 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) + if (current < limit) { id = ("00000000" + id).substring(id.length()); } return id; } + /** * @see java.lang.Object#toString() */ @@ -602,4 +699,88 @@ public class DiskFileItem implements Fil ", size=" + getSize() + "bytes, " + "isFormField=" + isFormField() + ", FieldName=" + getFieldName(); } -} \ No newline at end of file + + + // -------------------------------------------------- Serialization methods + + + /** + * Writes the state of this object during serialization. + * + * @param out + * The stream to which the state should be written. + * + * @throws IOException + * if an error occurs. + */ + private void writeObject(ObjectOutputStream out) throws IOException + { + // Read the data + if (dfos.isInMemory()) + { + cachedContent = get(); + } + else + { + cachedContent = null; + dfosFile = dfos.getFile(); + } + + // write out values + out.defaultWriteObject(); + } + + /** + * Reads the state of this object during deserialization. + * + * @param in + * The stream from which the state should be read. + * + * @throws IOException + * if an error occurs. + * @throws ClassNotFoundException + * if class cannot be found. + */ + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException + { + // read values + in.defaultReadObject(); + + OutputStream output = getOutputStream(); + if (cachedContent != null) + { + output.write(cachedContent); + } + else + { + FileInputStream input = new FileInputStream(dfosFile); + Streams.copy(input, output); + dfosFile.delete(); + dfosFile = null; + } + output.close(); + + cachedContent = null; + } + + /** + * Returns the file item headers. + * + * @return The file items headers. + */ + public FileItemHeaders getHeaders() + { + return headers; + } + + /** + * Sets the file item headers. + * + * @param pHeaders + * The file items headers. + */ + public void setHeaders(FileItemHeaders pHeaders) + { + headers = pHeaders; + } +} Modified: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItemFactory.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItemFactory.java?rev=1042345&r1=1042344&r2=1042345&view=diff ============================================================================== --- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItemFactory.java (original) +++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItemFactory.java Sun Dec 5 13:08:00 2010 @@ -18,6 +18,7 @@ package org.apache.wicket.util.upload; import java.io.File; + /** * <p> * The default {...@link org.apache.wicket.util.upload.FileItemFactory} implementation. This @@ -36,6 +37,16 @@ import java.io.File; * </ul> * </p> * + * <p> + * When using the <code>DiskFileItemFactory</code>, then you should consider the following: + * Temporary files are automatically deleted as soon as they are no longer needed. (More precisely, + * when the corresponding instance of {...@link java.io.File} is garbage collected.) Cleaning up those + * files is done by an instance of {...@link FileCleaningTracker}, and an associated thread. In a + * complex environment, for example in a web application, you should consider terminating this + * thread, for example, when your web application ends. See the section on "Resource cleanup" in the + * users guide of commons-fileupload. + * </p> + * * @author <a href="mailto:mart...@apache.org">Martin Cooper</a> */ public class DiskFileItemFactory implements FileItemFactory @@ -74,6 +85,7 @@ public class DiskFileItemFactory impleme */ public DiskFileItemFactory() { + this(DEFAULT_SIZE_THRESHOLD, null); } @@ -93,7 +105,6 @@ public class DiskFileItemFactory impleme this.repository = repository; } - // ------------------------------------------------------------- Properties @@ -130,7 +141,7 @@ public class DiskFileItemFactory impleme /** * Returns the size threshold beyond which files are written directly to disk. The default value - * is 1024 bytes. + * is 10240 bytes. * * @return The size threshold, in bytes. * @@ -160,8 +171,8 @@ public class DiskFileItemFactory impleme // --------------------------------------------------------- Public Methods /** - * Create a new {...@link org.apache.wicket.util.upload.DiskFileItem} instance from the supplied - * parameters and the local factory configuration. + * Create a new {...@link org.apache.wicket.util.upload.DiskFileItem} instance from the + * supplied parameters and the local factory configuration. * * @param fieldName * The name of the form field. @@ -180,4 +191,5 @@ public class DiskFileItemFactory impleme return new DiskFileItem(fieldName, contentType, isFormField, fileName, sizeThreshold, repository); } -} \ No newline at end of file + +} Modified: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItem.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItem.java?rev=1042345&r1=1042344&r2=1042345&view=diff ============================================================================== --- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItem.java (original) +++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItem.java Sun Dec 5 13:08:00 2010 @@ -24,7 +24,6 @@ import java.io.UnsupportedEncodingExcept import org.apache.wicket.IClusterable; - /** * <p> * This class represents a file or form item that was received within a @@ -32,10 +31,11 @@ import org.apache.wicket.IClusterable; * * <p> * After retrieving an instance of this class from a - * {...@link org.apache.wicket.util.upload.FileUpload FileUpload} instance, 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. + * {...@link org.apache.wicket.util.upload.FileUpload FileUpload} instance (see + * {...@link org.apache.wicket.util.upload.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 @@ -62,8 +62,8 @@ public interface FileItem extends IClust * @return An {...@link java.io.InputStream InputStream} that can be used to retrieve the contents * of the file. * - * @exception IOException - * if an error occurs. + * @throws IOException + * if an error occurs. */ InputStream getInputStream() throws IOException; @@ -123,8 +123,8 @@ public interface FileItem extends IClust * * @return The contents of the item, as a string. * - * @exception UnsupportedEncodingException - * if the requested character encoding is not available. + * @throws UnsupportedEncodingException + * if the requested character encoding is not available. */ String getString(String encoding) throws UnsupportedEncodingException; @@ -150,8 +150,8 @@ public interface FileItem extends IClust * @param file * The <code>File</code> into which the uploaded item should be stored. * - * @exception Exception - * if an error occurs. + * @throws Exception + * if an error occurs. */ void write(File file) throws IOException; @@ -206,10 +206,10 @@ public interface FileItem extends IClust * contents of the file. * * @return An {...@link java.io.OutputStream OutputStream} that can be used for storing the - * contents of the file. + * contensts of the file. * - * @exception IOException - * if an error occurs. + * @throws IOException + * if an error occurs. */ OutputStream getOutputStream() throws IOException; Added: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeaders.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeaders.java?rev=1042345&view=auto ============================================================================== --- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeaders.java (added) +++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeaders.java Sun Dec 5 13:08:00 2010 @@ -0,0 +1,74 @@ +/* + * 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.wicket.util.upload; + +import java.util.Iterator; + +/** + * <p> + * This class provides support for accessing the headers for a file or form item that was received + * within a <code>multipart/form-data</code> POST request. + * </p> + * + * @author Michael C. Macaluso + */ +public interface FileItemHeaders +{ + /** + * Returns the value of the specified part header as a <code>String</code>. If the part did not + * include a header of the specified name, this method return <code>null</code>. If there are + * multiple headers with the same name, this method returns the first header in the item. The + * header name is case insensitive. + * + * @param name + * a <code>String</code> specifying the header name + * @return a <code>String</code> containing the value of the requested header, or + * <code>null</code> if the item does not have a header of that name + */ + String getHeader(String name); + + /** + * <p> + * Returns all the values of the specified item header as an <code>Enumeration</code> of + * <code>String</code> objects. + * </p> + * <p> + * If the item did not include any headers of the specified name, this method returns an empty + * <code>Enumeration</code>. The header name is case insensitive. + * </p> + * + * @param name + * a <code>String</code> specifying the header name + * @return an <code>Enumeration</code> containing the values of the requested header. If the + * item does not have any headers of that name, return an empty <code>Enumeration</code> + */ + Iterator getHeaders(String name); + + /** + * <p> + * Returns an <code>Enumeration</code> of all the header names. + * </p> + * <p> + * If the item did not include any headers of the specified name, this method returns an empty + * <code>Enumeration</code>. The header name is case insensitive. + * </p> + * + * @return an <code>Enumeration</code> containing the values of the requested header. If the + * item does not have any headers of that name return an empty <code>Enumeration</code> + */ + Iterator getHeaderNames(); +} Propchange: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeaders.java ------------------------------------------------------------------------------ svn:eol-style = native Added: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeadersImpl.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeadersImpl.java?rev=1042345&view=auto ============================================================================== --- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeadersImpl.java (added) +++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeadersImpl.java Sun Dec 5 13:08:00 2010 @@ -0,0 +1,95 @@ +/* + * 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.wicket.util.upload; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Default implementation of the {...@link FileItemHeaders} interface. + * + * @author Michael C. Macaluso + * @since 1.3 + */ +public class FileItemHeadersImpl implements FileItemHeaders, Serializable +{ + private static final long serialVersionUID = -4455695752627032559L; + + /** + * Map of <code>String</code> keys to a <code>List</code> of <code>String</code> instances. + */ + private final Map headerNameToValueListMap = new HashMap(); + + /** + * List to preserve order of headers as added. This would not be needed if a + * <code>LinkedHashMap</code> could be used, but don't want to depend on 1.4. + */ + private final List headerNameList = new ArrayList(); + + public String getHeader(String name) + { + String nameLower = name.toLowerCase(); + List headerValueList = (List)headerNameToValueListMap.get(nameLower); + if (null == headerValueList) + { + return null; + } + return (String)headerValueList.get(0); + } + + public Iterator getHeaderNames() + { + return headerNameList.iterator(); + } + + public Iterator getHeaders(String name) + { + String nameLower = name.toLowerCase(); + List headerValueList = (List)headerNameToValueListMap.get(nameLower); + if (null == headerValueList) + { + return Collections.EMPTY_LIST.iterator(); + } + return headerValueList.iterator(); + } + + /** + * Method to add header values to this instance. + * + * @param name + * name of this header + * @param value + * value of this header + */ + public synchronized void addHeader(String name, String value) + { + String nameLower = name.toLowerCase(); + List headerValueList = (List)headerNameToValueListMap.get(nameLower); + if (null == headerValueList) + { + headerValueList = new ArrayList(); + headerNameToValueListMap.put(nameLower, headerValueList); + headerNameList.add(nameLower); + } + headerValueList.add(value); + } +} Propchange: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeadersImpl.java ------------------------------------------------------------------------------ svn:eol-style = native Copied: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeadersSupport.java (from r1042295, wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/RequestContext.java) URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeadersSupport.java?p2=wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeadersSupport.java&p1=wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/RequestContext.java&r1=1042295&r2=1042345&rev=1042345&view=diff ============================================================================== --- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/RequestContext.java (original) +++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemHeadersSupport.java Sun Dec 5 13:08:00 2010 @@ -16,42 +16,31 @@ */ package org.apache.wicket.util.upload; -import java.io.IOException; -import java.io.InputStream; - /** - * <p> - * Abstracts access to the request information needed for file uploads. This interface should be - * implemented for each type of request that may be handled by FileUpload, such as servlets and - * portlets. - * </p> + * Interface that will indicate that {...@link FileItem} or {...@link FileItemStream} implementations will + * accept the headers read for the item. + * + * @author Michael C. Macaluso * - * @author <a href="mailto:mart...@apache.org">Martin Cooper</a> + * @see FileItem + * @see FileItemStream */ -public interface RequestContext +public interface FileItemHeadersSupport { - - /** - * Retrieve the content type of the request. - * - * @return The content type of the request. - */ - String getContentType(); - /** - * Retrieve the content length of the request. + * Returns the collection of headers defined locally within this item. * - * @return The content length of the request. + * @return the {...@link FileItemHeaders} present for this item. */ - int getContentLength(); + FileItemHeaders getHeaders(); /** - * Retrieve the input stream for the request. - * - * @return The input stream for the request. + * Sets the headers read from within an item. Implementations of {...@link FileItem} or + * {...@link FileItemStream} should implement this interface to be able to get the raw headers + * found within the item header block. * - * @throws IOException - * if a problem occurs. + * @param headers + * the instance that holds onto the headers for this instance. */ - InputStream getInputStream() throws IOException; + void setHeaders(FileItemHeaders headers); } Added: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemIterator.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemIterator.java?rev=1042345&view=auto ============================================================================== --- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemIterator.java (added) +++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemIterator.java Sun Dec 5 13:08:00 2010 @@ -0,0 +1,50 @@ +/* + * 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.wicket.util.upload; + +import java.io.IOException; + + +/** + * An iterator, as returned by {...@link FileUploadBase#getItemIterator(RequestContext)}. + */ +public interface FileItemIterator +{ + /** + * Returns, whether another instance of {...@link FileItemStream} is available. + * + * @throws FileUploadException + * Parsing or processing the file item failed. + * @throws IOException + * Reading the file item failed. + * @return True, if one or more additional file items are available, otherwise false. + */ + boolean hasNext() throws FileUploadException, IOException; + + /** + * Returns the next available {...@link FileItemStream}. + * + * @throws java.util.NoSuchElementException + * No more items are available. Use {...@link #hasNext()} to prevent this exception. + * @throws FileUploadException + * Parsing or processing the file item failed. + * @throws IOException + * Reading the file item failed. + * @return FileItemStream instance, which provides access to the next file item. + */ + FileItemStream next() throws FileUploadException, IOException; +} Propchange: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemIterator.java ------------------------------------------------------------------------------ svn:eol-style = native Added: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemStream.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemStream.java?rev=1042345&view=auto ============================================================================== --- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemStream.java (added) +++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemStream.java Sun Dec 5 13:08:00 2010 @@ -0,0 +1,99 @@ +/* + * 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.wicket.util.upload; + +import java.io.IOException; +import java.io.InputStream; + + +/** + * <p> + * This interface provides access to a file or form item that was received within a + * <code>multipart/form-data</code> POST request. The items contents are retrieved by calling + * {...@link #openStream()}. + * </p> + * <p> + * Instances of this class are created by accessing the iterator, returned by + * {...@link FileUploadBase#getItemIterator(RequestContext)}. + * </p> + * <p> + * <em>Note</em>: There is an interaction between the iterator and its associated instances of + * {...@link FileItemStream}: By invoking {...@link java.util.Iterator#hasNext()} on the iterator, you + * discard all data, which hasn't been read so far from the previous data. + * </p> + */ +public interface FileItemStream extends FileItemHeadersSupport +{ + /** + * This exception is thrown, if an attempt is made to read data from the {...@link InputStream}, + * which has been returned by {...@link FileItemStream#openStream()}, after + * {...@link java.util.Iterator#hasNext()} has been invoked on the iterator, which created the + * {...@link FileItemStream}. + */ + public static class ItemSkippedException extends IOException + { + /** + * The exceptions serial version UID, which is being used when serializing an exception + * instance. + */ + private static final long serialVersionUID = -7280778431581963740L; + } + + /** + * Creates an {...@link InputStream}, which allows to read the items contents. + * + * @return The input stream, from which the items data may be read. + * @throws IllegalStateException + * The method was already invoked on this item. It is not possible to recreate the + * data stream. + * @throws IOException + * An I/O error occurred. + * @see ItemSkippedException + */ + InputStream openStream() 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(); + + /** + * Returns the name of the field in the multipart form corresponding to this file item. + * + * @return The name of the form field. + */ + String getFieldName(); + + /** + * 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(); +} Propchange: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileItemStream.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileUpload.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileUpload.java?rev=1042345&r1=1042344&r2=1042345&view=diff ============================================================================== --- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileUpload.java (original) +++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/FileUpload.java Sun Dec 5 13:08:00 2010 @@ -24,7 +24,9 @@ package org.apache.wicket.util.upload; * * <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>. + * encoding type, as specified by <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use + * {...@link #parseRequest(javax.servlet.http.HttpServletRequest)} to acquire a list of + * {...@link org.apache.wicket.util.upload.FileItem FileItems} associated with a given HTML widget. * </p> * * <p> @@ -42,13 +44,20 @@ package org.apache.wicket.util.upload; public class FileUpload extends FileUploadBase { + // ----------------------------------------------------------- Data members + + /** * The factory to use to create new form items. */ private FileItemFactory fileItemFactory; + + // ----------------------------------------------------------- Constructors + + /** - * Constructs an uninitialized instance of this class. A factory must be configured, using + * Constructs an uninitialised instance of this class. A factory must be configured, using * <code>setFileItemFactory()</code>, before attempting to parse requests. * * @see #FileUpload(FileItemFactory) @@ -63,9 +72,9 @@ public class FileUpload extends FileUplo * Constructs an instance of this class which uses the supplied factory to create * <code>FileItem</code> instances. * - * @param fileItemFactory - * * @see #FileUpload() + * @param fileItemFactory + * The factory to use for creating file items. */ public FileUpload(final FileItemFactory fileItemFactory) { @@ -73,6 +82,10 @@ public class FileUpload extends FileUplo this.fileItemFactory = fileItemFactory; } + + // ----------------------------------------------------- Property accessors + + /** * Returns the factory class used when creating file items. * @@ -96,4 +109,6 @@ public class FileUpload extends FileUplo { fileItemFactory = factory; } + + }