diff --git a/fine-commons-fileupload/README.md b/fine-commons-fileupload/README.md index 590c7eac8..c3966b6df 100644 --- a/fine-commons-fileupload/README.md +++ b/fine-commons-fileupload/README.md @@ -1,2 +1,2 @@ apache commons fileupload https://archive.apache.org/dist/commons/fileupload/source/ -1.3.3 \ No newline at end of file +1.5 \ No newline at end of file diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DefaultFileItem.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DefaultFileItem.java index d24587a58..e65c3f611 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DefaultFileItem.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DefaultFileItem.java @@ -16,9 +16,10 @@ */ package com.fr.third.org.apache.commons.fileupload; -import java.io.File; import com.fr.third.org.apache.commons.fileupload.disk.DiskFileItem; +import java.io.File; + /** *

The default implementation of the * {@link FileItem FileItem} interface. @@ -32,8 +33,6 @@ import com.fr.third.org.apache.commons.fileupload.disk.DiskFileItem; * {@link #getInputStream()} and process the file without attempting to load * it into memory, which may come handy with large files. * - * @version $Id$ - * * @deprecated 1.1 Use DiskFileItem instead. */ @Deprecated @@ -42,11 +41,6 @@ public class DefaultFileItem // ----------------------------------------------------------- Constructors - /** - * The UID to use when serializing this instance. - */ - private static final long serialVersionUID = 4088572813833518255L; - /** * Constructs a new DefaultFileItem instance. * diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DefaultFileItemFactory.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DefaultFileItemFactory.java index edf0e8967..516d64e42 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DefaultFileItemFactory.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DefaultFileItemFactory.java @@ -16,9 +16,10 @@ */ package com.fr.third.org.apache.commons.fileupload; -import java.io.File; import com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory; +import java.io.File; + /** *

The default {@link FileItemFactory} * implementation. This implementation creates @@ -28,7 +29,7 @@ import com.fr.third.org.apache.commons.fileupload.disk.DiskFileItemFactory; * disk, is configurable, as is the directory in which temporary files will be * created.

* - * If not otherwise configured, the default configuration values are as + *

If not otherwise configured, the default configuration values are as * follows: *

* - * @version $Id$ - * * @deprecated 1.1 Use DiskFileItemFactory instead. */ @Deprecated diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DiskFileUpload.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DiskFileUpload.java index 44ce5e556..bc12aa4fc 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DiskFileUpload.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/DiskFileUpload.java @@ -16,9 +16,9 @@ */ package com.fr.third.org.apache.commons.fileupload; +import javax.servlet.http.HttpServletRequest; import java.io.File; import java.util.List; -import javax.servlet.http.HttpServletRequest; /** *

High level API for processing file uploads.

@@ -34,8 +34,6 @@ import javax.servlet.http.HttpServletRequest; * depending on their size, and will be available as {@link * FileItem}s.

* - * @version $Id$ - * * @deprecated 1.1 Use ServletFileUpload together with * DiskFileItemFactory instead. */ diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileCountLimitExceededException.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileCountLimitExceededException.java new file mode 100644 index 000000000..bc644635f --- /dev/null +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileCountLimitExceededException.java @@ -0,0 +1,51 @@ +/* + * 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 com.fr.third.org.apache.commons.fileupload; + +/** + * This exception is thrown if a request contains more files than the specified + * limit. + */ +public class FileCountLimitExceededException extends FileUploadException { + + private static final long serialVersionUID = 6904179610227521789L; + + /** + * The limit that was exceeded. + */ + private final long limit; + + /** + * Creates a new instance. + * + * @param message The detail message + * @param limit The limit that was exceeded + */ + public FileCountLimitExceededException(final String message, final long limit) { + super(message); + this.limit = limit; + } + + /** + * Retrieves the limit that was exceeded. + * + * @return The limit that was exceeded by the request + */ + public long getLimit() { + return limit; + } +} diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItem.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItem.java index d7772b2f2..0d83a043d 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItem.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItem.java @@ -22,7 +22,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.Serializable; import java.io.UnsupportedEncodingException; /** @@ -34,7 +33,7 @@ import java.io.UnsupportedEncodingException; * {@link ServletFileUpload * #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 + * request an {@link InputStream InputStream} with * {@link #getInputStream()} and process the file without attempting to load * it into memory, which may come handy with large files. * @@ -45,18 +44,17 @@ import java.io.UnsupportedEncodingException; * implementation of this interface to also implement * javax.activation.DataSource with minimal additional work. * - * @version $Id$ * @since 1.3 additionally implements FileItemHeadersSupport */ -public interface FileItem extends Serializable, FileItemHeadersSupport { +public interface FileItem extends FileItemHeadersSupport { // ------------------------------- Methods from javax.activation.DataSource /** - * Returns an {@link java.io.InputStream InputStream} that can be + * Returns an {@link InputStream InputStream} that can be * used to retrieve the contents of the file. * - * @return An {@link java.io.InputStream InputStream} that can be + * @return An {@link InputStream InputStream} that can be * used to retrieve the contents of the file. * * @throws IOException if an error occurs. @@ -195,10 +193,10 @@ public interface FileItem extends Serializable, FileItemHeadersSupport { void setFormField(boolean state); /** - * Returns an {@link java.io.OutputStream OutputStream} that can + * Returns an {@link OutputStream OutputStream} that can * be used for storing the contents of the file. * - * @return An {@link java.io.OutputStream OutputStream} that can be used + * @return An {@link OutputStream OutputStream} that can be used * for storing the contensts of the file. * * @throws IOException if an error occurs. diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemFactory.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemFactory.java index da5782cad..90af20469 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemFactory.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemFactory.java @@ -20,8 +20,6 @@ package com.fr.third.org.apache.commons.fileupload; *

A factory interface for creating {@link FileItem} instances. Factories * can provide their own custom configuration, over and above that provided * by the default file upload implementation.

- * - * @version $Id$ */ public interface FileItemFactory { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemHeaders.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemHeaders.java index 19d7d901f..b41da70af 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemHeaders.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemHeaders.java @@ -24,8 +24,6 @@ import java.util.Iterator; * request.

* * @since 1.2.1 - * - * @version $Id$ */ public interface FileItemHeaders { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemHeadersSupport.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemHeadersSupport.java index 5e22af909..58a6f0845 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemHeadersSupport.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemHeadersSupport.java @@ -24,8 +24,6 @@ package com.fr.third.org.apache.commons.fileupload; * * @see FileItem * @see FileItemStream - * - * @version $Id$ */ public interface FileItemHeadersSupport { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemIterator.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemIterator.java index d03715740..11fc6b0b7 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemIterator.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemIterator.java @@ -21,8 +21,6 @@ import java.io.IOException; /** * An iterator, as returned by * {@link FileUploadBase#getItemIterator(RequestContext)}. - * - * @version $Id$ */ public interface FileItemIterator { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemStream.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemStream.java index 41433990b..e177e0984 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemStream.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileItemStream.java @@ -30,8 +30,6 @@ import java.io.InputStream; * 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.

- * - * @version $Id$ */ public interface FileItemStream extends FileItemHeadersSupport { @@ -42,7 +40,7 @@ public interface FileItemStream extends FileItemHeadersSupport { * {@link java.util.Iterator#hasNext()} has been invoked on the * iterator, which created the {@link FileItemStream}. */ - public static class ItemSkippedException extends IOException { + class ItemSkippedException extends IOException { /** * The exceptions serial version UID, which is being used diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUpload.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUpload.java index f90fa9e18..affea4309 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUpload.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUpload.java @@ -29,8 +29,6 @@ package com.fr.third.org.apache.commons.fileupload; *

How the data for individual parts is stored is determined by the factory * used to create them; a given part may be in memory, on disk, or somewhere * else.

- * - * @version $Id$ */ public class FileUpload extends FileUploadBase { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUploadBase.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUploadBase.java index 44a8f3e32..3921ab267 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUploadBase.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUploadBase.java @@ -16,8 +16,15 @@ */ package com.fr.third.org.apache.commons.fileupload; -import static java.lang.String.format; +import com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload; +import com.fr.third.org.apache.commons.fileupload.servlet.ServletRequestContext; +import com.fr.third.org.apache.commons.fileupload.util.Closeable; +import com.fr.third.org.apache.commons.fileupload.util.FileItemHeadersImpl; +import com.fr.third.org.apache.commons.fileupload.util.LimitedInputStream; +import com.fr.third.org.apache.commons.fileupload.util.Streams; +import com.fr.third.org.apache.commons.io.IOUtils; +import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; @@ -29,15 +36,7 @@ import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; -import javax.servlet.http.HttpServletRequest; - -import com.fr.third.org.apache.commons.fileupload.MultipartStream.ItemInputStream; -import com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload; -import com.fr.third.org.apache.commons.fileupload.servlet.ServletRequestContext; -import com.fr.third.org.apache.commons.fileupload.util.Closeable; -import com.fr.third.org.apache.commons.fileupload.util.FileItemHeadersImpl; -import com.fr.third.org.apache.commons.fileupload.util.LimitedInputStream; -import com.fr.third.org.apache.commons.fileupload.util.Streams; +import static java.lang.String.format; /** *

High level API for processing file uploads.

@@ -52,8 +51,6 @@ import com.fr.third.org.apache.commons.fileupload.util.Streams; *

How the data for individual parts is stored is determined by the factory * used to create them; a given part may be in memory, on disk, or somewhere * else.

- * - * @version $Id$ */ public abstract class FileUploadBase { @@ -166,6 +163,12 @@ public abstract class FileUploadBase { */ private long fileSizeMax = -1; + /** + * The maximum permitted number of files that may be uploaded in a single + * request. A value of -1 indicates no maximum. + */ + private long fileCountMax = -1; + /** * The content encoding to use when reading part headers. */ @@ -242,6 +245,25 @@ public abstract class FileUploadBase { this.fileSizeMax = fileSizeMax; } + /** + * Returns the maximum number of files allowed in a single request. + * + * @return The maximum number of files allowed in a single request. + */ + public long getFileCountMax() { + return fileCountMax; + } + + /** + * Sets the maximum number of files allowed per request. + * + * @param fileCountMax The new limit. {@code -1} means no limit. + */ + public void setFileCountMax(final long fileCountMax) { + this.fileCountMax = fileCountMax; + } + + /** * Retrieves the character encoding used when reading the headers of an * individual part. When not specified, or null, the request @@ -333,10 +355,15 @@ public abstract class FileUploadBase { try { FileItemIterator iter = getItemIterator(ctx); FileItemFactory fac = getFileItemFactory(); + final byte[] buffer = new byte[Streams.DEFAULT_BUFFER_SIZE]; if (fac == null) { throw new NullPointerException("No FileItemFactory has been set."); } while (iter.hasNext()) { + if (items.size() == fileCountMax) { + // The next item will exceed the limit. + throw new FileCountLimitExceededException(ATTACHMENT, getFileCountMax()); + } final FileItemStream item = iter.next(); // Don't use getName() here to prevent an InvalidFileNameException. final String fileName = ((FileItemIteratorImpl.FileItemStreamImpl) item).name; @@ -344,7 +371,7 @@ public abstract class FileUploadBase { item.isFormField(), fileName); items.add(fileItem); try { - Streams.copy(item.openStream(), fileItem.getOutputStream(), true); + Streams.copy(item.openStream(), fileItem.getOutputStream(), true, buffer); } catch (FileUploadIOException e) { throw (FileUploadException) e.getCause(); } catch (IOException e) { @@ -365,8 +392,8 @@ public abstract class FileUploadBase { for (FileItem fileItem : items) { try { fileItem.delete(); - } catch (Throwable e) { - // ignore it + } catch (Exception ignored) { + // ignored TODO perhaps add to tracker delete failure list somehow? } } } @@ -765,20 +792,23 @@ public abstract class FileUploadBase { fieldName = pFieldName; contentType = pContentType; formField = pFormField; - final ItemInputStream itemStream = multi.newInputStream(); - InputStream istream = itemStream; - if (fileSizeMax != -1) { + if (fileSizeMax != -1) { // Check if limit is already exceeded if (pContentLength != -1 - && pContentLength > fileSizeMax) { + && pContentLength > fileSizeMax) { FileSizeLimitExceededException e = - new FileSizeLimitExceededException( - format("The field %s exceeds its maximum permitted size of %s bytes.", - fieldName, Long.valueOf(fileSizeMax)), - pContentLength, fileSizeMax); + new FileSizeLimitExceededException( + format("The field %s exceeds its maximum permitted size of %s bytes.", + fieldName, Long.valueOf(fileSizeMax)), + pContentLength, fileSizeMax); e.setFileName(pName); e.setFieldName(pFieldName); throw new FileUploadIOException(e); } + } + // OK to construct stream now + final MultipartStream.ItemInputStream itemStream = multi.newInputStream(); + InputStream istream = itemStream; + if (fileSizeMax != -1) { istream = new LimitedInputStream(istream, fileSizeMax) { @Override protected void raiseError(long pSizeMax, long pCount) @@ -803,6 +833,7 @@ public abstract class FileUploadBase { * * @return Content type, if known, or null. */ + @Override public String getContentType() { return contentType; } @@ -812,6 +843,7 @@ public abstract class FileUploadBase { * * @return Field name. */ + @Override public String getFieldName() { return fieldName; } @@ -825,6 +857,7 @@ public abstract class FileUploadBase { * use the file name anyways, catch the exception and use * InvalidFileNameException#getName(). */ + @Override public String getName() { return Streams.checkFileName(name); } @@ -835,6 +868,7 @@ public abstract class FileUploadBase { * @return True, if the item is a form field, * otherwise false. */ + @Override public boolean isFormField() { return formField; } @@ -846,13 +880,14 @@ public abstract class FileUploadBase { * @return Opened input stream. * @throws IOException An I/O error occurred. */ + @Override public InputStream openStream() throws IOException { if (opened) { throw new IllegalStateException( "The stream was already opened."); } if (((Closeable) stream).isClosed()) { - throw new FileItemStream.ItemSkippedException(); + throw new ItemSkippedException(); } return stream; } @@ -871,6 +906,7 @@ public abstract class FileUploadBase { * * @return The items header object */ + @Override public FileItemHeaders getHeaders() { return headers; } @@ -880,6 +916,7 @@ public abstract class FileUploadBase { * * @param pHeaders The items header object */ + @Override public void setHeaders(FileItemHeaders pHeaders) { headers = pHeaders; } @@ -949,7 +986,6 @@ public abstract class FileUploadBase { MULTIPART_FORM_DATA, MULTIPART_MIXED, contentType)); } - InputStream input = ctx.getInputStream(); @SuppressWarnings("deprecation") // still has to be backward compatible final int contentLengthInt = ctx.getContentLength(); @@ -960,6 +996,7 @@ public abstract class FileUploadBase { : contentLengthInt; // CHECKSTYLE:ON + InputStream input; // N.B. this is eventually closed in MultipartStream processing if (sizeMax >= 0) { if (requestSize != -1 && requestSize > sizeMax) { throw new SizeLimitExceededException( @@ -967,7 +1004,8 @@ public abstract class FileUploadBase { Long.valueOf(requestSize), Long.valueOf(sizeMax)), requestSize, sizeMax); } - input = new LimitedInputStream(input, sizeMax) { + // N.B. this is eventually closed in MultipartStream processing + input = new LimitedInputStream(ctx.getInputStream(), sizeMax) { @Override protected void raiseError(long pSizeMax, long pCount) throws IOException { @@ -978,6 +1016,8 @@ public abstract class FileUploadBase { throw new FileUploadIOException(ex); } }; + } else { + input = ctx.getInputStream(); } String charEncoding = headerEncoding; @@ -987,6 +1027,7 @@ public abstract class FileUploadBase { boundary = getBoundary(contentType); if (boundary == null) { + IOUtils.closeQuietly(input); // avoid possible resource leak throw new FileUploadException("the request was rejected because no multipart boundary was found"); } @@ -994,6 +1035,7 @@ public abstract class FileUploadBase { try { multi = new MultipartStream(input, boundary, notifier); } catch (IllegalArgumentException iae) { + IOUtils.closeQuietly(input); // avoid possible resource leak throw new InvalidContentTypeException( format("The boundary specified in the %s header is too long", CONTENT_TYPE), iae); } @@ -1095,6 +1137,7 @@ public abstract class FileUploadBase { * @return True, if one or more additional file items * are available, otherwise false. */ + @Override public boolean hasNext() throws FileUploadException, IOException { if (eof) { return false; @@ -1113,7 +1156,7 @@ public abstract class FileUploadBase { /** * Returns the next available {@link FileItemStream}. * - * @throws java.util.NoSuchElementException No more items are + * @throws NoSuchElementException No more items are * available. Use {@link #hasNext()} to prevent this exception. * @throws FileUploadException Parsing or processing the * file item failed. @@ -1121,6 +1164,7 @@ public abstract class FileUploadBase { * @return FileItemStream instance, which provides * access to the next file item. */ + @Override public FileItemStream next() throws FileUploadException, IOException { if (eof || (!itemValid && !hasNext())) { throw new NoSuchElementException(); @@ -1361,7 +1405,7 @@ public abstract class FileUploadBase { /** * @deprecated 1.2 Replaced by - * {@code SizeLimitExceededException(String, long, long)} + * {@link #SizeLimitExceededException(String, long, long)} */ @Deprecated public SizeLimitExceededException() { @@ -1370,7 +1414,7 @@ public abstract class FileUploadBase { /** * @deprecated 1.2 Replaced by - * {@code #SizeLimitExceededException(String, long, long)} + * {@link #SizeLimitExceededException(String, long, long)} * @param message The exceptions detail message. */ @Deprecated diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUploadException.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUploadException.java index 29ec77534..d7025dbf3 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUploadException.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/FileUploadException.java @@ -21,8 +21,6 @@ import java.io.PrintWriter; /** * Exception for errors encountered while processing the request. - * - * @version $Id$ */ public class FileUploadException extends Exception { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/InvalidFileNameException.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/InvalidFileNameException.java index e604d90f3..fd17f563e 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/InvalidFileNameException.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/InvalidFileNameException.java @@ -25,8 +25,6 @@ package com.fr.third.org.apache.commons.fileupload; * checks for the extension ".png"), while, depending on the underlying * C library, it might create a file named "foo.exe", as the NUL * character is the string terminator in C. - * - * @version $Id$ */ public class InvalidFileNameException extends RuntimeException { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/MultipartStream.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/MultipartStream.java index 5d1802fa0..d4716d49a 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/MultipartStream.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/MultipartStream.java @@ -16,7 +16,9 @@ */ package com.fr.third.org.apache.commons.fileupload; -import static java.lang.String.format; +import com.fr.third.org.apache.commons.fileupload.FileUploadBase.FileUploadIOException; +import com.fr.third.org.apache.commons.fileupload.util.Closeable; +import com.fr.third.org.apache.commons.fileupload.util.Streams; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -24,9 +26,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; -import com.fr.third.org.apache.commons.fileupload.FileUploadBase.FileUploadIOException; -import com.fr.third.org.apache.commons.fileupload.util.Closeable; -import com.fr.third.org.apache.commons.fileupload.util.Streams; +import static java.lang.String.format; /** *

Low level API for processing file uploads. @@ -80,8 +80,6 @@ import com.fr.third.org.apache.commons.fileupload.util.Streams; * // a read or write error occurred * } * - * - * @version $Id$ */ public class MultipartStream { @@ -222,12 +220,17 @@ public class MultipartStream { * The amount of data, in bytes, that must be kept in the buffer in order * to detect delimiters reliably. */ - private int keepRegion; + private final int keepRegion; /** * The byte sequence that partitions the stream. */ - private byte[] boundary; + private final byte[] boundary; + + /** + * The table for Knuth-Morris-Pratt search algorithm. + */ + private final int[] boundaryTable; /** * The length of the buffer used for processing the request. @@ -339,12 +342,14 @@ public class MultipartStream { this.notifier = pNotifier; this.boundary = new byte[this.boundaryLength]; + this.boundaryTable = new int[this.boundaryLength + 1]; this.keepRegion = this.boundary.length; System.arraycopy(BOUNDARY_PREFIX, 0, this.boundary, 0, BOUNDARY_PREFIX.length); System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, boundary.length); + computeBoundaryTable(); head = 0; tail = 0; @@ -502,10 +507,35 @@ public class MultipartStream { throws IllegalBoundaryException { if (boundary.length != boundaryLength - BOUNDARY_PREFIX.length) { throw new IllegalBoundaryException( - "The length of a boundary token can not be changed"); + "The length of a boundary token cannot be changed"); } System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, boundary.length); + computeBoundaryTable(); + } + + /** + * Compute the table used for Knuth-Morris-Pratt search algorithm. + */ + private void computeBoundaryTable() { + int position = 2; + int candidate = 0; + + boundaryTable[0] = -1; + boundaryTable[1] = 0; + + while (position <= boundaryLength) { + if (boundary[position - 1] == boundary[candidate]) { + boundaryTable[position] = candidate + 1; + candidate++; + position++; + } else if (candidate > 0) { + candidate = boundaryTable[candidate]; + } else { + boundaryTable[position] = 0; + position++; + } + } } /** @@ -576,7 +606,7 @@ public class MultipartStream { *

Arbitrary large amounts of data can be processed by this * method using a constant size buffer. (see {@link * #MultipartStream(InputStream,byte[],int, - * MultipartStream.ProgressNotifier) constructor}). + * ProgressNotifier) constructor}). * * @param output The Stream to write data into. May * be null, in which case this method is equivalent @@ -589,8 +619,7 @@ public class MultipartStream { */ public int readBodyData(OutputStream output) throws MalformedStreamException, IOException { - final InputStream istream = newInputStream(); - return (int) Streams.copy(istream, output, false); + return (int) Streams.copy(newInputStream(), output, false); // N.B. Streams.copy closes the input stream } /** @@ -629,6 +658,7 @@ public class MultipartStream { // First delimiter may be not preceeded with a CRLF. System.arraycopy(boundary, 2, boundary, 0, boundary.length - 2); boundaryLength = boundary.length - 2; + computeBoundaryTable(); try { // Discard all data up to the delimiter. discardBodyData(); @@ -644,6 +674,7 @@ public class MultipartStream { boundaryLength = boundary.length; boundary[0] = CR; boundary[1] = LF; + computeBoundaryTable(); } } @@ -699,23 +730,20 @@ public class MultipartStream { * not found. */ protected int findSeparator() { - int first; - int match = 0; - int maxpos = tail - boundaryLength; - for (first = head; first <= maxpos && match != boundaryLength; first++) { - first = findByte(boundary[0], first); - if (first == -1 || first > maxpos) { - return -1; + + int bufferPos = this.head; + int tablePos = 0; + + while (bufferPos < this.tail) { + while (tablePos >= 0 && buffer[bufferPos] != boundary[tablePos]) { + tablePos = boundaryTable[tablePos]; } - for (match = 1; match < boundaryLength; match++) { - if (buffer[first + match] != boundary[match]) { - break; - } + bufferPos++; + tablePos++; + if (tablePos == boundaryLength) { + return bufferPos - boundaryLength; } } - if (match == boundaryLength) { - return first - 1; - } return -1; } @@ -1023,6 +1051,7 @@ public class MultipartStream { * * @return True, if the stream is closed, otherwise false. */ + @Override public boolean isClosed() { return closed; } diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/ParameterParser.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/ParameterParser.java index 34fa21832..5a79b7d5d 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/ParameterParser.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/ParameterParser.java @@ -16,13 +16,13 @@ */ package com.fr.third.org.apache.commons.fileupload; +import com.fr.third.org.apache.commons.fileupload.util.mime.MimeUtility; + import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Locale; import java.util.Map; -import com.fr.third.org.apache.commons.fileupload.util.mime.MimeUtility; - /** * A simple parser intended to parse sequences of name/value pairs. * @@ -33,8 +33,6 @@ import com.fr.third.org.apache.commons.fileupload.util.mime.MimeUtility; *

* param1 = value; param2 = "anything goes; really"; param3 *

- * - * @version $Id$ */ public class ParameterParser { @@ -78,8 +76,8 @@ public class ParameterParser { /** * Are there any characters left to parse? * - * @return true if there are unparsed characters, - * false otherwise. + * @return {@code true} if there are unparsed characters, + * {@code false} otherwise. */ private boolean hasChar() { return this.pos < this.len; @@ -90,8 +88,8 @@ public class ParameterParser { * leading and trailing blanks as well as enclosing quotation marks, * when necessary. * - * @param quoted true if quotation marks are expected, - * false otherwise. + * @param quoted {@code true} if quotation marks are expected, + * {@code false} otherwise. * @return the token */ private String getToken(boolean quoted) { @@ -124,8 +122,8 @@ public class ParameterParser { * @param ch the character to test for presense in the array of characters * @param charray the array of characters to test against * - * @return true if the character is present in the array of - * characters, false otherwise. + * @return {@code true} if the character is present in the array of + * characters, {@code false} otherwise. */ private boolean isOneOf(char ch, final char[] charray) { boolean result = false; @@ -195,12 +193,12 @@ public class ParameterParser { } /** - * Returns true if parameter names are to be converted to lower + * Returns {@code true} if parameter names are to be converted to lower * case when name/value pairs are parsed. * - * @return true if parameter names are to be + * @return {@code true} if parameter names are to be * converted to lower case when name/value pairs are parsed. - * Otherwise returns false + * Otherwise returns {@code false} */ public boolean isLowerCaseNames() { return this.lowerCaseNames; @@ -210,9 +208,9 @@ public class ParameterParser { * Sets the flag if parameter names are to be converted to lower case when * name/value pairs are parsed. * - * @param b true if parameter names are to be + * @param b {@code true} if parameter names are to be * converted to lower case when name/value pairs are parsed. - * false otherwise. + * {@code false} otherwise. */ public void setLowerCaseNames(boolean b) { this.lowerCaseNames = b; diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/ProgressListener.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/ProgressListener.java index 5f39a2f80..4d9993daf 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/ProgressListener.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/ProgressListener.java @@ -19,8 +19,6 @@ package com.fr.third.org.apache.commons.fileupload; /** * The {@link ProgressListener} may be used to display a progress bar * or do stuff like that. - * - * @version $Id$ */ public interface ProgressListener { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/RequestContext.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/RequestContext.java index d8965a1a5..959d06900 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/RequestContext.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/RequestContext.java @@ -16,8 +16,8 @@ */ package com.fr.third.org.apache.commons.fileupload; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; /** *

Abstracts access to the request information needed for file uploads. This @@ -25,8 +25,6 @@ import java.io.IOException; * handled by FileUpload, such as servlets and portlets.

* * @since FileUpload 1.1 - * - * @version $Id$ */ public interface RequestContext { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/DiskFileItem.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/DiskFileItem.java index 033b88258..d8e887d5e 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/DiskFileItem.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/DiskFileItem.java @@ -16,33 +16,28 @@ */ package com.fr.third.org.apache.commons.fileupload.disk; -import static java.lang.String.format; +import com.fr.third.org.apache.commons.fileupload.FileItem; +import com.fr.third.org.apache.commons.fileupload.FileItemHeaders; +import com.fr.third.org.apache.commons.fileupload.FileUploadException; +import com.fr.third.org.apache.commons.fileupload.ParameterParser; +import com.fr.third.org.apache.commons.fileupload.util.Streams; +import com.fr.third.org.apache.commons.io.FileUtils; +import com.fr.third.org.apache.commons.io.IOUtils; +import com.fr.third.org.apache.commons.io.output.DeferredFileOutputStream; -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.UUID; import java.util.concurrent.atomic.AtomicInteger; -import com.fr.third.org.apache.commons.fileupload.FileItem; -import com.fr.third.org.apache.commons.fileupload.FileItemHeaders; -import com.fr.third.org.apache.commons.fileupload.FileUploadException; -import com.fr.third.org.apache.commons.fileupload.InvalidFileNameException; -import com.fr.third.org.apache.commons.fileupload.ParameterParser; -import com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload; -import com.fr.third.org.apache.commons.fileupload.util.Streams; -import com.fr.third.org.apache.commons.io.IOUtils; -import com.fr.third.org.apache.commons.io.output.DeferredFileOutputStream; +import static java.lang.String.format; /** *

The default implementation of the @@ -50,47 +45,34 @@ import com.fr.third.org.apache.commons.io.output.DeferredFileOutputStream; * *

After retrieving an instance of this class from a {@link * DiskFileItemFactory} instance (see - * {@link ServletFileUpload + * {@link com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload * #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 + * request an {@link InputStream InputStream} with * {@link #getInputStream()} and process the file without attempting to load * it into memory, which may come handy with large files. * *

Temporary files, which are created for file items, should be * deleted later on. The best way to do this is using a - * {@link org.apache.commons.io.FileCleaningTracker}, which you can set on the + * {@link com.fr.third.org.apache.commons.io.FileCleaningTracker}, which you can set on the * {@link DiskFileItemFactory}. However, if you do use such a tracker, * then you must 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.) + * corresponding instance of {@link File} is garbage collected.) * This is done by the so-called reaper thread, which is started and stopped - * automatically by the {@link org.apache.commons.io.FileCleaningTracker} when + * automatically by the {@link com.fr.third.org.apache.commons.io.FileCleaningTracker} when * there are files to be tracked. * 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.

* * @since FileUpload 1.1 - * - * @version $Id$ */ public class DiskFileItem implements FileItem { - /** - * Although it implements {@link java.io.Serializable}, a DiskFileItem can actually only be deserialized, - * if this System property is true. - */ - public static final String SERIALIZABLE_PROPERTY = DiskFileItem.class.getName() + ".serializable"; - // ----------------------------------------------------- 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 sender. Media subtypes of the @@ -166,14 +148,15 @@ public class DiskFileItem private transient File tempFile; /** - * File to allow for serialization of the content of this item. + * The file items headers. */ - private File dfosFile; + private FileItemHeaders headers; /** - * The file items headers. + * Default content charset to be used when no explicit charset + * parameter is provided by the sender. */ - private FileItemHeaders headers; + private String defaultCharset = DEFAULT_CHARSET; // ----------------------------------------------------------- Constructors @@ -208,14 +191,15 @@ public class DiskFileItem // ------------------------------- Methods from javax.activation.DataSource /** - * Returns an {@link java.io.InputStream InputStream} that can be + * Returns an {@link InputStream InputStream} that can be * used to retrieve the contents of the file. * - * @return An {@link java.io.InputStream InputStream} that can be + * @return An {@link InputStream InputStream} that can be * used to retrieve the contents of the file. * * @throws IOException if an error occurs. */ + @Override public InputStream getInputStream() throws IOException { if (!isInMemory()) { @@ -235,6 +219,7 @@ public class DiskFileItem * @return The content type passed by the agent or null if * not defined. */ + @Override public String getContentType() { return contentType; } @@ -258,11 +243,12 @@ public class DiskFileItem * Returns the original filename in the client's filesystem. * * @return The original filename in the client's filesystem. - * @throws InvalidFileNameException The file name contains a NUL character, + * @throws com.fr.third.org.apache.commons.fileupload.InvalidFileNameException The file name contains a NUL character, * which might be an indicator of a security attack. If you intend to * use the file name anyways, catch the exception and use - * {@link InvalidFileNameException#getName()}. + * {@link com.fr.third.org.apache.commons.fileupload.InvalidFileNameException#getName()}. */ + @Override public String getName() { return Streams.checkFileName(fileName); } @@ -276,6 +262,7 @@ public class DiskFileItem * @return true if the file contents will be read * from memory; false otherwise. */ + @Override public boolean isInMemory() { if (cachedContent != null) { return true; @@ -288,6 +275,7 @@ public class DiskFileItem * * @return The size of the file, in bytes. */ + @Override public long getSize() { if (size >= 0) { return size; @@ -305,11 +293,13 @@ public class DiskFileItem * contents of the file were not yet cached in memory, they will be * loaded from the disk storage and cached. * - * @return The contents of the file as an array of bytes. + * @return The contents of the file as an array of bytes + * or {@code null} if the data cannot be read */ + @Override public byte[] get() { if (isInMemory()) { - if (cachedContent == null) { + if (cachedContent == null && dfos != null) { cachedContent = dfos.getData(); } return cachedContent; @@ -319,18 +309,12 @@ public class DiskFileItem InputStream fis = null; try { - fis = new BufferedInputStream(new FileInputStream(dfos.getFile())); - fis.read(fileData); + fis = new FileInputStream(dfos.getFile()); + IOUtils.readFully(fis, fileData); } catch (IOException e) { fileData = null; } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException e) { - // ignore - } - } + IOUtils.closeQuietly(fis); } return fileData; @@ -348,6 +332,7 @@ public class DiskFileItem * @throws UnsupportedEncodingException if the requested character * encoding is not available. */ + @Override public String getString(final String charset) throws UnsupportedEncodingException { return new String(get(), charset); @@ -362,11 +347,12 @@ public class DiskFileItem * * @return The contents of the file, as a string. */ + @Override public String getString() { byte[] rawdata = get(); String charset = getCharSet(); if (charset == null) { - charset = DEFAULT_CHARSET; + charset = defaultCharset; } try { return new String(rawdata, charset); @@ -395,16 +381,16 @@ public class DiskFileItem * * @throws Exception if an error occurs. */ + @Override public void write(File file) throws Exception { if (isInMemory()) { FileOutputStream fout = null; try { fout = new FileOutputStream(file); fout.write(get()); + fout.close(); } finally { - if (fout != null) { - fout.close(); - } + IOUtils.closeQuietly(fout); } } else { File outputFile = getStoreLocation(); @@ -416,32 +402,10 @@ public class DiskFileItem * in a temporary location so move it to the * desired file. */ - if (!outputFile.renameTo(file)) { - BufferedInputStream in = null; - BufferedOutputStream out = null; - try { - in = new BufferedInputStream( - new FileInputStream(outputFile)); - out = new BufferedOutputStream( - new FileOutputStream(file)); - IOUtils.copy(in, out); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - // ignore - } - } - if (out != null) { - try { - out.close(); - } catch (IOException e) { - // ignore - } - } - } + if (file.exists()) { + file.delete(); } + FileUtils.moveFile(outputFile, file); } else { /* * For whatever reason we cannot write the @@ -460,10 +424,11 @@ public class DiskFileItem * collected, this method can be used to ensure that this is done at an * earlier time, thus preserving system resources. */ + @Override public void delete() { cachedContent = null; File outputFile = getStoreLocation(); - if (outputFile != null && outputFile.exists()) { + if (outputFile != null && !isInMemory() && outputFile.exists()) { outputFile.delete(); } } @@ -474,9 +439,10 @@ public class DiskFileItem * * @return The name of the form field. * - * @see #setFieldName(java.lang.String) + * @see #setFieldName(String) * */ + @Override public String getFieldName() { return fieldName; } @@ -489,6 +455,7 @@ public class DiskFileItem * @see #getFieldName() * */ + @Override public void setFieldName(String fieldName) { this.fieldName = fieldName; } @@ -503,6 +470,7 @@ public class DiskFileItem * @see #setFormField(boolean) * */ + @Override public boolean isFormField() { return isFormField; } @@ -517,19 +485,21 @@ public class DiskFileItem * @see #isFormField() * */ + @Override public void setFormField(boolean state) { isFormField = state; } /** - * Returns an {@link java.io.OutputStream OutputStream} that can + * Returns an {@link OutputStream OutputStream} that can * be used for storing the contents of the file. * - * @return An {@link java.io.OutputStream OutputStream} that can be used - * for storing the contensts of the file. + * @return An {@link OutputStream OutputStream} that can be used + * for storing the contents of the file. * * @throws IOException if an error occurs. */ + @Override public OutputStream getOutputStream() throws IOException { if (dfos == null) { @@ -542,11 +512,11 @@ public class DiskFileItem // --------------------------------------------------------- Public methods /** - * Returns the {@link java.io.File} object for the FileItem's + * Returns the {@link File} object for the FileItem's * data's temporary location on the disk. Note that for * FileItems that have their data stored in memory, * this method will return null. When handling large - * files, you can use {@link java.io.File#renameTo(java.io.File)} to + * files, you can use {@link File#renameTo(File)} to * move the file to new location without copying the data, if the * source and destination locations reside within the same logical * volume. @@ -558,6 +528,9 @@ public class DiskFileItem if (dfos == null) { return null; } + if (isInMemory()) { + return null; + } return dfos.getFile(); } @@ -568,6 +541,9 @@ public class DiskFileItem */ @Override protected void finalize() { + if (dfos == null || dfos.isInMemory()) { + return; + } File outputFile = dfos.getFile(); if (outputFile != null && outputFile.exists()) { @@ -576,12 +552,15 @@ public class DiskFileItem } /** - * Creates and returns a {@link java.io.File File} representing a uniquely + * Creates and returns a {@link File File} representing a uniquely * named temporary file in the configured repository path. The lifetime of * the file is tied to the lifetime of the FileItem instance; * the file will be deleted when the instance is garbage collected. + *

+ * Note: Subclasses that override this method must ensure that they return the + * same File each time. * - * @return The {@link java.io.File File} to be used for temporary storage. + * @return The {@link File File} to be used for temporary storage. */ protected File getTempFile() { if (tempFile == null) { @@ -601,7 +580,7 @@ public class DiskFileItem /** * Returns an identifier that is unique within the class loader used to - * load this class, but does not have random-like apearance. + * load this class, but does not have random-like appearance. * * @return A String with the non-random looking instance identifier. */ @@ -630,83 +609,11 @@ public class DiskFileItem Boolean.valueOf(isFormField()), getFieldName()); } - // -------------------------------------------------- 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 { - if (!Boolean.getBoolean(SERIALIZABLE_PROPERTY)) { - throw new IllegalStateException("Property " + SERIALIZABLE_PROPERTY - + " is not true, rejecting to deserialize a DiskFileItem."); - } - // read values - in.defaultReadObject(); - - /* One expected use of serialization is to migrate HTTP sessions - * containing a DiskFileItem between JVMs. Particularly if the JVMs are - * on different machines It is possible that the repository location is - * not valid so validate it. - */ - if (repository != null) { - if (repository.isDirectory()) { - // Check path for nulls - if (repository.getPath().contains("\0")) { - throw new IOException(format( - "The repository [%s] contains a null character", - repository.getPath())); - } - } else { - throw new IOException(format( - "The repository [%s] is not a directory", - repository.getAbsolutePath())); - } - } - - OutputStream output = getOutputStream(); - if (cachedContent != null) { - output.write(cachedContent); - } else { - FileInputStream input = new FileInputStream(dfosFile); - IOUtils.copy(input, output); - dfosFile.delete(); - dfosFile = null; - } - output.close(); - - cachedContent = null; - } - /** * Returns the file item headers. * @return The file items headers. */ + @Override public FileItemHeaders getHeaders() { return headers; } @@ -715,8 +622,26 @@ public class DiskFileItem * Sets the file item headers. * @param pHeaders The file items headers. */ + @Override public void setHeaders(FileItemHeaders pHeaders) { headers = pHeaders; } + /** + * Returns the default charset for use when no explicit charset + * parameter is provided by the sender. + * @return the default charset + */ + public String getDefaultCharset() { + return defaultCharset; + } + + /** + * Sets the default charset for use when no explicit charset + * parameter is provided by the sender. + * @param charset the default charset + */ + public void setDefaultCharset(String charset) { + defaultCharset = charset; + } } diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/DiskFileItemFactory.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/DiskFileItemFactory.java index 8415a79a5..f2d787a39 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/DiskFileItemFactory.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/disk/DiskFileItemFactory.java @@ -16,12 +16,12 @@ */ package com.fr.third.org.apache.commons.fileupload.disk; -import java.io.File; - -import com.fr.third.org.apache.commons.fileupload.FileItem; import com.fr.third.org.apache.commons.fileupload.FileItemFactory; +import com.fr.third.org.apache.commons.fileupload.FileItem; import com.fr.third.org.apache.commons.io.FileCleaningTracker; +import java.io.File; + /** *

The default {@link FileItemFactory} * implementation. This implementation creates @@ -57,7 +57,7 @@ import com.fr.third.org.apache.commons.io.FileCleaningTracker; * {@link DiskFileItemFactory}. However, if you do use such a tracker, * then you must 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.) + * corresponding instance of {@link File} is garbage collected.) * This is done by the so-called reaper thread, which is started and stopped * automatically by the {@link FileCleaningTracker} when there are files to be * tracked. @@ -66,8 +66,6 @@ import com.fr.third.org.apache.commons.io.FileCleaningTracker; * in the users guide of commons-fileupload.

* * @since FileUpload 1.1 - * - * @version $Id$ */ public class DiskFileItemFactory implements FileItemFactory { @@ -97,6 +95,12 @@ public class DiskFileItemFactory implements FileItemFactory { */ private FileCleaningTracker fileCleaningTracker; + /** + * Default content charset to be used when no explicit charset + * parameter is provided by the sender. + */ + private String defaultCharset = DiskFileItem.DEFAULT_CHARSET; + // ----------------------------------------------------------- Constructors /** @@ -130,7 +134,7 @@ public class DiskFileItemFactory implements FileItemFactory { * * @return The directory in which temporary files will be located. * - * @see #setRepository(java.io.File) + * @see #setRepository(File) * */ public File getRepository() { @@ -190,10 +194,12 @@ public class DiskFileItemFactory implements FileItemFactory { * * @return The newly created file item. */ + @Override public FileItem createItem(String fieldName, String contentType, boolean isFormField, String fileName) { DiskFileItem result = new DiskFileItem(fieldName, contentType, isFormField, fileName, sizeThreshold, repository); + result.setDefaultCharset(defaultCharset); FileCleaningTracker tracker = getFileCleaningTracker(); if (tracker != null) { tracker.track(result.getTempFile(), result); @@ -224,4 +230,21 @@ public class DiskFileItemFactory implements FileItemFactory { fileCleaningTracker = pTracker; } + /** + * Returns the default charset for use when no explicit charset + * parameter is provided by the sender. + * @return the default charset + */ + public String getDefaultCharset() { + return defaultCharset; + } + + /** + * Sets the default charset for use when no explicit charset + * parameter is provided by the sender. + * @param pCharset the default charset + */ + public void setDefaultCharset(String pCharset) { + defaultCharset = pCharset; + } } diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/PortletFileUpload.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/PortletFileUpload.java index d970a040c..5fd1d7180 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/PortletFileUpload.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/PortletFileUpload.java @@ -16,19 +16,18 @@ */ package com.fr.third.org.apache.commons.fileupload.portlet; -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import javax.portlet.ActionRequest; - -import com.fr.third.org.apache.commons.fileupload.FileItem; import com.fr.third.org.apache.commons.fileupload.FileItemFactory; -import com.fr.third.org.apache.commons.fileupload.FileItemIterator; import com.fr.third.org.apache.commons.fileupload.FileUpload; -import com.fr.third.org.apache.commons.fileupload.FileUploadBase; import com.fr.third.org.apache.commons.fileupload.FileUploadException; import com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload; +import com.fr.third.org.apache.commons.fileupload.FileItem; +import com.fr.third.org.apache.commons.fileupload.FileItemIterator; +import com.fr.third.org.apache.commons.fileupload.FileUploadBase; + +import javax.portlet.ActionRequest; +import java.io.IOException; +import java.util.List; +import java.util.Map; /** *

High level API for processing file uploads.

@@ -46,8 +45,6 @@ import com.fr.third.org.apache.commons.fileupload.servlet.ServletFileUpload; * else.

* * @since FileUpload 1.1 - * - * @version $Id$ */ public class PortletFileUpload extends FileUpload { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/PortletRequestContext.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/PortletRequestContext.java index d55305598..3963a2ede 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/PortletRequestContext.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/portlet/PortletRequestContext.java @@ -16,23 +16,20 @@ */ package com.fr.third.org.apache.commons.fileupload.portlet; -import static java.lang.String.format; +import com.fr.third.org.apache.commons.fileupload.FileUploadBase; +import com.fr.third.org.apache.commons.fileupload.UploadContext; +import javax.portlet.ActionRequest; import java.io.IOException; import java.io.InputStream; -import javax.portlet.ActionRequest; - -import com.fr.third.org.apache.commons.fileupload.FileUploadBase; -import com.fr.third.org.apache.commons.fileupload.UploadContext; +import static java.lang.String.format; /** *

Provides access to the request information needed for a request made to * a portlet.

* * @since FileUpload 1.1 - * - * @version $Id$ */ public class PortletRequestContext implements UploadContext { @@ -63,6 +60,7 @@ public class PortletRequestContext implements UploadContext { * * @return The character encoding for the request. */ + @Override public String getCharacterEncoding() { return request.getCharacterEncoding(); } @@ -72,6 +70,7 @@ public class PortletRequestContext implements UploadContext { * * @return The content type of the request. */ + @Override public String getContentType() { return request.getContentType(); } @@ -82,6 +81,7 @@ public class PortletRequestContext implements UploadContext { * @return The content length of the request. * @deprecated 1.3 Use {@link #contentLength()} instead */ + @Override @Deprecated public int getContentLength() { return request.getContentLength(); @@ -93,6 +93,7 @@ public class PortletRequestContext implements UploadContext { * @return The content length of the request. * @since 1.3 */ + @Override public long contentLength() { long size; try { @@ -110,6 +111,7 @@ public class PortletRequestContext implements UploadContext { * * @throws IOException if a problem occurs. */ + @Override public InputStream getInputStream() throws IOException { return request.getPortletInputStream(); } diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/FileCleanerCleanup.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/FileCleanerCleanup.java index 58f75c8a1..ba91464b9 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/FileCleanerCleanup.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/FileCleanerCleanup.java @@ -16,18 +16,16 @@ */ package com.fr.third.org.apache.commons.fileupload.servlet; +import com.fr.third.org.apache.commons.io.FileCleaningTracker; + import javax.servlet.ServletContext; -import javax.servlet.ServletContextListener; import javax.servlet.ServletContextEvent; - -import com.fr.third.org.apache.commons.io.FileCleaningTracker; +import javax.servlet.ServletContextListener; /** * A servlet context listener, which ensures that the * {@link FileCleaningTracker}'s reaper thread is terminated, * when the web application is destroyed. - * - * @version $Id$ */ public class FileCleanerCleanup implements ServletContextListener { @@ -70,6 +68,7 @@ public class FileCleanerCleanup implements ServletContextListener { * @param sce The servlet context, used for calling * {@link #setFileCleaningTracker(ServletContext, FileCleaningTracker)}. */ + @Override public void contextInitialized(ServletContextEvent sce) { setFileCleaningTracker(sce.getServletContext(), new FileCleaningTracker()); @@ -82,6 +81,7 @@ public class FileCleanerCleanup implements ServletContextListener { * @param sce The servlet context, used for calling * {@link #getFileCleaningTracker(ServletContext)}. */ + @Override public void contextDestroyed(ServletContextEvent sce) { getFileCleaningTracker(sce.getServletContext()).exitWhenFinished(); } diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/ServletFileUpload.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/ServletFileUpload.java index 94abdbec5..29dd04b59 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/ServletFileUpload.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/ServletFileUpload.java @@ -16,18 +16,17 @@ */ package com.fr.third.org.apache.commons.fileupload.servlet; -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; - -import com.fr.third.org.apache.commons.fileupload.FileItem; import com.fr.third.org.apache.commons.fileupload.FileItemFactory; -import com.fr.third.org.apache.commons.fileupload.FileItemIterator; import com.fr.third.org.apache.commons.fileupload.FileUpload; -import com.fr.third.org.apache.commons.fileupload.FileUploadBase; import com.fr.third.org.apache.commons.fileupload.FileUploadException; +import com.fr.third.org.apache.commons.fileupload.FileItem; +import com.fr.third.org.apache.commons.fileupload.FileItemIterator; +import com.fr.third.org.apache.commons.fileupload.FileUploadBase; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.List; +import java.util.Map; /** *

High level API for processing file uploads.

@@ -42,8 +41,6 @@ import com.fr.third.org.apache.commons.fileupload.FileUploadException; *

How the data for individual parts is stored is determined by the factory * used to create them; a given part may be in memory, on disk, or somewhere * else.

- * - * @version $Id$ */ public class ServletFileUpload extends FileUpload { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/ServletRequestContext.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/ServletRequestContext.java index ae4fed385..6997e0e3f 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/ServletRequestContext.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/servlet/ServletRequestContext.java @@ -16,23 +16,20 @@ */ package com.fr.third.org.apache.commons.fileupload.servlet; -import static java.lang.String.format; +import com.fr.third.org.apache.commons.fileupload.UploadContext; +import com.fr.third.org.apache.commons.fileupload.FileUploadBase; +import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.InputStream; -import javax.servlet.http.HttpServletRequest; - -import com.fr.third.org.apache.commons.fileupload.FileUploadBase; -import com.fr.third.org.apache.commons.fileupload.UploadContext; +import static java.lang.String.format; /** *

Provides access to the request information needed for a request made to * an HTTP servlet.

* * @since FileUpload 1.1 - * - * @version $Id$ */ public class ServletRequestContext implements UploadContext { @@ -61,6 +58,7 @@ public class ServletRequestContext implements UploadContext { * * @return The character encoding for the request. */ + @Override public String getCharacterEncoding() { return request.getCharacterEncoding(); } @@ -70,6 +68,7 @@ public class ServletRequestContext implements UploadContext { * * @return The content type of the request. */ + @Override public String getContentType() { return request.getContentType(); } @@ -80,6 +79,7 @@ public class ServletRequestContext implements UploadContext { * @return The content length of the request. * @deprecated 1.3 Use {@link #contentLength()} instead */ + @Override @Deprecated public int getContentLength() { return request.getContentLength(); @@ -91,6 +91,7 @@ public class ServletRequestContext implements UploadContext { * @return The content length of the request. * @since 1.3 */ + @Override public long contentLength() { long size; try { @@ -108,6 +109,7 @@ public class ServletRequestContext implements UploadContext { * * @throws IOException if a problem occurs. */ + @Override public InputStream getInputStream() throws IOException { return request.getInputStream(); } diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/Closeable.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/Closeable.java index 3128ca2c3..354f89914 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/Closeable.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/Closeable.java @@ -20,8 +20,6 @@ import java.io.IOException; /** * Interface of an object, which may be closed. - * - * @version $Id$ */ public interface Closeable { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/FileItemHeadersImpl.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/FileItemHeadersImpl.java index 6632cef95..a2ad50e26 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/FileItemHeadersImpl.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/FileItemHeadersImpl.java @@ -16,6 +16,8 @@ */ package com.fr.third.org.apache.commons.fileupload.util; +import com.fr.third.org.apache.commons.fileupload.FileItemHeaders; + import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; @@ -25,14 +27,10 @@ import java.util.List; import java.util.Locale; import java.util.Map; -import com.fr.third.org.apache.commons.fileupload.FileItemHeaders; - /** * Default implementation of the {@link FileItemHeaders} interface. * * @since 1.2.1 - * - * @version $Id$ */ public class FileItemHeadersImpl implements FileItemHeaders, Serializable { @@ -50,6 +48,7 @@ public class FileItemHeadersImpl implements FileItemHeaders, Serializable { /** * {@inheritDoc} */ + @Override public String getHeader(String name) { String nameLower = name.toLowerCase(Locale.ENGLISH); List headerValueList = headerNameToValueListMap.get(nameLower); @@ -62,6 +61,7 @@ public class FileItemHeadersImpl implements FileItemHeaders, Serializable { /** * {@inheritDoc} */ + @Override public Iterator getHeaderNames() { return headerNameToValueListMap.keySet().iterator(); } @@ -69,6 +69,7 @@ public class FileItemHeadersImpl implements FileItemHeaders, Serializable { /** * {@inheritDoc} */ + @Override public Iterator getHeaders(String name) { String nameLower = name.toLowerCase(Locale.ENGLISH); List headerValueList = headerNameToValueListMap.get(nameLower); diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/LimitedInputStream.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/LimitedInputStream.java index ddee3f142..97e275481 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/LimitedInputStream.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/LimitedInputStream.java @@ -23,8 +23,6 @@ import java.io.InputStream; /** * An input stream, which limits its data size. This stream is * used, if the content length is unknown. - * - * @version $Id$ */ public abstract class LimitedInputStream extends FilterInputStream implements Closeable { @@ -93,8 +91,8 @@ public abstract class LimitedInputStream extends FilterInputStream implements Cl * * @return the next byte of data, or -1 if the end of the * stream is reached. - * @exception IOException if an I/O error occurs. - * @see java.io.FilterInputStream#in + * @throws IOException if an I/O error occurs. + * @see FilterInputStream#in */ @Override public int read() throws IOException { @@ -122,12 +120,12 @@ public abstract class LimitedInputStream extends FilterInputStream implements Cl * @return the total number of bytes read into the buffer, or * -1 if there is no more data because the end of * the stream has been reached. - * @exception NullPointerException If b is null. - * @exception IndexOutOfBoundsException If off is negative, + * @throws NullPointerException If b is null. + * @throws IndexOutOfBoundsException If off is negative, * len is negative, or len is greater than * b.length - off - * @exception IOException if an I/O error occurs. - * @see java.io.FilterInputStream#in + * @throws IOException if an I/O error occurs. + * @see FilterInputStream#in */ @Override public int read(byte[] b, int off, int len) throws IOException { @@ -145,6 +143,7 @@ public abstract class LimitedInputStream extends FilterInputStream implements Cl * @return True, if the stream is closed, otherwise false. * @throws IOException An I/O error occurred. */ + @Override public boolean isClosed() throws IOException { return closed; } @@ -155,8 +154,8 @@ public abstract class LimitedInputStream extends FilterInputStream implements Cl * This * method simply performs in.close(). * - * @exception IOException if an I/O error occurs. - * @see java.io.FilterInputStream#in + * @throws IOException if an I/O error occurs. + * @see FilterInputStream#in */ @Override public void close() throws IOException { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/Streams.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/Streams.java index b6ca1e7bf..47d5c1ea5 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/Streams.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/Streams.java @@ -16,19 +16,16 @@ */ package com.fr.third.org.apache.commons.fileupload.util; +import com.fr.third.org.apache.commons.fileupload.InvalidFileNameException; +import com.fr.third.org.apache.commons.io.IOUtils; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import com.fr.third.org.apache.commons.fileupload.FileItemStream; -import com.fr.third.org.apache.commons.fileupload.InvalidFileNameException; -import com.fr.third.org.apache.commons.io.IOUtils; - /** * Utility class for working with streams. - * - * @version $Id$ */ public final class Streams { @@ -44,7 +41,7 @@ public final class Streams { * Default buffer size for use in * {@link #copy(InputStream, OutputStream, boolean)}. */ - private static final int DEFAULT_BUFFER_SIZE = 8192; + public static final int DEFAULT_BUFFER_SIZE = 8192; /** * Copies the contents of the given {@link InputStream} @@ -130,7 +127,7 @@ public final class Streams { /** * This convenience method allows to read a - * {@link FileItemStream}'s + * {@link com.fr.third.org.apache.commons.fileupload.FileItemStream}'s * content into a string. The platform's default character encoding * is used for converting bytes into characters. * @@ -147,7 +144,7 @@ public final class Streams { /** * This convenience method allows to read a - * {@link FileItemStream}'s + * {@link com.fr.third.org.apache.commons.fileupload.FileItemStream}'s * content into a string, using the given character encoding. * * @param inputStream The input stream to read. diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/Base64Decoder.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/Base64Decoder.java index b3c7b5185..4822ba911 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/Base64Decoder.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/Base64Decoder.java @@ -104,8 +104,8 @@ final class Base64Decoder { * @throws IOException thrown when the padding is incorrect or the input is truncated. */ public static int decode(byte[] data, OutputStream out) throws IOException { - int outLen = 0; - byte [] cache = new byte[INPUT_BYTES_PER_CHUNK]; + int outLen = 0; + byte[] cache = new byte[INPUT_BYTES_PER_CHUNK]; int cachedBytes = 0; for (byte b : data) { diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/MimeUtility.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/MimeUtility.java index 262a6ea51..cf4d92833 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/MimeUtility.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/MimeUtility.java @@ -212,7 +212,7 @@ public final class MimeUtility { } // pull out the character set information (this is the MIME name at this point). - String charset = word.substring(2, charsetPos).toLowerCase(); + String charset = word.substring(2, charsetPos).toLowerCase(Locale.ENGLISH); // now pull out the encoding token the same way. int encodingPos = word.indexOf('?', charsetPos + 1); diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/ParseException.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/ParseException.java index 794a45f1c..6b1ac7c74 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/ParseException.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/ParseException.java @@ -31,7 +31,7 @@ final class ParseException extends Exception { * * @param message the detail message. */ - public ParseException(String message) { + ParseException(String message) { super(message); } diff --git a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/QuotedPrintableDecoder.java b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/QuotedPrintableDecoder.java index 33bd50062..c9754b43d 100644 --- a/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/QuotedPrintableDecoder.java +++ b/fine-commons-fileupload/src/main/java/com/fr/third/org/apache/commons/fileupload/util/mime/QuotedPrintableDecoder.java @@ -44,7 +44,7 @@ final class QuotedPrintableDecoder { * @param out The output stream used to return the decoded data. * * @return the number of bytes produced. - * @exception IOException + * @throws IOException */ public static int decode(byte[] data, OutputStream out) throws IOException { int off = 0; diff --git a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java index 57a874a82..57a755ef9 100644 --- a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java +++ b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java @@ -483,6 +483,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement private Map querySubstitutions; private boolean strictJpaQueryLanguageCompliance; private boolean namedQueryStartupCheckingEnabled; + private boolean conventionalJavaConstants; private final boolean procedureParameterNullPassingEnabled; private final boolean collectionJoinSubqueryRewriteEnabled; @@ -600,6 +601,8 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement this.querySubstitutions = ConfigurationHelper.toMap( QUERY_SUBSTITUTIONS, " ,=;:\n\t\r\f", configurationSettings ); this.strictJpaQueryLanguageCompliance = cfgService.getSetting( JPAQL_STRICT_COMPLIANCE, BOOLEAN, false ); this.namedQueryStartupCheckingEnabled = cfgService.getSetting( QUERY_STARTUP_CHECKING, BOOLEAN, true ); + this.conventionalJavaConstants = cfgService.getSetting( + CONVENTIONAL_JAVA_CONSTANTS, BOOLEAN, true ); this.procedureParameterNullPassingEnabled = cfgService.getSetting( PROCEDURE_NULL_PARAM_PASSING, BOOLEAN, false ); this.collectionJoinSubqueryRewriteEnabled = cfgService.getSetting( COLLECTION_JOIN_SUBQUERY, BOOLEAN, true ); @@ -851,6 +854,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement return namedQueryStartupCheckingEnabled; } + @Override + public boolean isConventionalJavaConstants() { + return conventionalJavaConstants; + } + @Override public boolean isProcedureParameterNullPassingEnabled() { return procedureParameterNullPassingEnabled; @@ -1132,6 +1140,10 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement return options.isNamedQueryStartupCheckingEnabled(); } + @Override + public boolean isConventionalJavaConstants() { + return options.isConventionalJavaConstants(); + } @Override public boolean isProcedureParameterNullPassingEnabled() { return options.isProcedureParameterNullPassingEnabled(); diff --git a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/internal/SessionFactoryOptionsImpl.java b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/internal/SessionFactoryOptionsImpl.java index ffaa7a149..f925b5cba 100644 --- a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/internal/SessionFactoryOptionsImpl.java +++ b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/internal/SessionFactoryOptionsImpl.java @@ -88,6 +88,9 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions { private final Map querySubstitutions; private final boolean strictJpaQueryLanguageCompliance; private final boolean namedQueryStartupCheckingEnabled; + + private final boolean conventionalJavaConstants; + private final boolean procedureParameterNullPassingEnabled; private final boolean collectionJoinSubqueryRewriteEnabled; @@ -160,6 +163,7 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions { this.querySubstitutions = state.getQuerySubstitutions(); this.strictJpaQueryLanguageCompliance = state.isStrictJpaQueryLanguageCompliance(); this.namedQueryStartupCheckingEnabled = state.isNamedQueryStartupCheckingEnabled(); + this.conventionalJavaConstants = state.isConventionalJavaConstants(); this.procedureParameterNullPassingEnabled = state.isProcedureParameterNullPassingEnabled(); this.collectionJoinSubqueryRewriteEnabled = state.isCollectionJoinSubqueryRewriteEnabled(); @@ -339,6 +343,11 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions { return namedQueryStartupCheckingEnabled; } + @Override + public boolean isConventionalJavaConstants() { + return conventionalJavaConstants; + } + @Override public boolean isProcedureParameterNullPassingEnabled() { return procedureParameterNullPassingEnabled; diff --git a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/internal/SessionFactoryOptionsState.java b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/internal/SessionFactoryOptionsState.java index c73f94f8b..8835f3453 100644 --- a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/internal/SessionFactoryOptionsState.java +++ b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/internal/SessionFactoryOptionsState.java @@ -98,6 +98,8 @@ public interface SessionFactoryOptionsState { boolean isNamedQueryStartupCheckingEnabled(); + boolean isConventionalJavaConstants(); + boolean isProcedureParameterNullPassingEnabled(); boolean isCollectionJoinSubqueryRewriteEnabled(); diff --git a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java index 3e8a7f603..97d723488 100644 --- a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java +++ b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java @@ -198,6 +198,11 @@ public abstract class AbstractDelegatingSessionFactoryOptions implements Session return delegate.isNamedQueryStartupCheckingEnabled(); } + @Override + public boolean isConventionalJavaConstants() { + return delegate.isConventionalJavaConstants(); + } + @Override public boolean isProcedureParameterNullPassingEnabled() { return delegate.isProcedureParameterNullPassingEnabled(); diff --git a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/spi/SessionFactoryOptions.java b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/spi/SessionFactoryOptions.java index 7872aacb7..6c8972464 100644 --- a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/spi/SessionFactoryOptions.java +++ b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/boot/spi/SessionFactoryOptions.java @@ -122,6 +122,8 @@ public interface SessionFactoryOptions { boolean isNamedQueryStartupCheckingEnabled(); + boolean isConventionalJavaConstants(); + boolean isSecondLevelCacheEnabled(); boolean isQueryCacheEnabled(); diff --git a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/cfg/AvailableSettings.java b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/cfg/AvailableSettings.java index 0ac6a9122..80541d2f1 100644 --- a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/cfg/AvailableSettings.java +++ b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/cfg/AvailableSettings.java @@ -564,6 +564,17 @@ public interface AvailableSettings { */ String QUERY_STARTUP_CHECKING = "hibernate.query.startup_check"; + /** + * Setting which indicates whether or not Java constant follow the Java Naming conventions. + *

+ * Default is {@code true}. Existing applications may want to disable this (set it {@code false}) if non-conventional Java constants are used. + * However, there is a significant performance overhead for using non-conventional Java constants since Hibernate cannot determine if aliases + * should be treated as Java constants or not. + * + * @since 5.2 + */ + String CONVENTIONAL_JAVA_CONSTANTS = "hibernate.query.conventional_java_constants"; + /** * The {@link com.fr.third.org.hibernate.exception.spi.SQLExceptionConverter} to use for converting SQLExceptions * to Hibernate's JDBCException hierarchy. The default is to use the configured diff --git a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/ast/QueryTranslatorImpl.java b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/ast/QueryTranslatorImpl.java index e7968fcca..ab9c923a8 100644 --- a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/ast/QueryTranslatorImpl.java +++ b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/ast/QueryTranslatorImpl.java @@ -612,7 +612,7 @@ public class QueryTranslatorImpl implements FilterTranslator { } private void handleDotStructure(AST dotStructureRoot) { final String expression = ASTUtil.getPathText( dotStructureRoot ); - final Object constant = ReflectHelper.getConstantValue( expression, factory.getServiceRegistry().getService( ClassLoaderService.class ) ); + final Object constant = ReflectHelper.getConstantValue( expression, factory ); if ( constant != null ) { dotStructureRoot.setFirstChild( null ); dotStructureRoot.setType( HqlTokenTypes.JAVA_CONSTANT ); diff --git a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/ast/tree/JavaConstantNode.java b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/ast/tree/JavaConstantNode.java index 2f77663fd..5a678968e 100644 --- a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/ast/tree/JavaConstantNode.java +++ b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/ast/tree/JavaConstantNode.java @@ -39,7 +39,7 @@ public class JavaConstantNode extends Node implements ExpectedTypeAwareNode, Ses // this method to get called twice. The first time with an empty string if ( StringHelper.isNotEmpty( s ) ) { constantExpression = s; - constantValue = ReflectHelper.getConstantValue( s, factory.getServiceRegistry().getService( ClassLoaderService.class ) ); + constantValue = ReflectHelper.getConstantValue( s, factory ); heuristicType = factory.getTypeResolver().heuristicType( constantValue.getClass().getName() ); super.setText( s ); } diff --git a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/ast/util/LiteralProcessor.java b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/ast/util/LiteralProcessor.java index c414c847f..6fb54838d 100644 --- a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/ast/util/LiteralProcessor.java +++ b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/ast/util/LiteralProcessor.java @@ -107,7 +107,7 @@ public class LiteralProcessor implements HqlSqlTokenTypes { setSQLValue( node, text, discrim ); } else { - Object value = ReflectHelper.getConstantValue( text, walker.getSessionFactoryHelper().getFactory().getServiceRegistry().getService( ClassLoaderService.class ) ); + Object value = ReflectHelper.getConstantValue( text, walker.getSessionFactoryHelper().getFactory() ); if ( value == null ) { throw new InvalidPathException( "Invalid path: '" + text + "'" ); } diff --git a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/classic/WhereParser.java b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/classic/WhereParser.java index 618950829..7f22b82ee 100644 --- a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/classic/WhereParser.java +++ b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/hql/internal/classic/WhereParser.java @@ -419,7 +419,7 @@ public class WhereParser implements Parser { Object constant; if ( token.indexOf( '.' ) > -1 && - ( constant = ReflectHelper.getConstantValue( token, q.getFactory().getServiceRegistry().getService( ClassLoaderService.class ) ) ) != null + ( constant = ReflectHelper.getConstantValue( token, q.getFactory() ) ) != null ) { Type type; try { diff --git a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/internal/util/ReflectHelper.java b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/internal/util/ReflectHelper.java index bb9d5aa3a..819fc0358 100644 --- a/fine-hibernate/src/main/java/com/fr/third/org/hibernate/internal/util/ReflectHelper.java +++ b/fine-hibernate/src/main/java/com/fr/third/org/hibernate/internal/util/ReflectHelper.java @@ -13,12 +13,14 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Locale; +import java.util.regex.Pattern; import com.fr.third.org.hibernate.AssertionFailure; import com.fr.third.org.hibernate.MappingException; import com.fr.third.org.hibernate.PropertyNotFoundException; import com.fr.third.org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import com.fr.third.org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import com.fr.third.org.hibernate.engine.spi.SessionFactoryImplementor; import com.fr.third.org.hibernate.property.access.internal.PropertyAccessStrategyMixedImpl; import com.fr.third.org.hibernate.property.access.spi.Getter; import com.fr.third.org.hibernate.type.PrimitiveType; @@ -32,6 +34,8 @@ import com.fr.third.org.hibernate.type.Type; */ @SuppressWarnings("unchecked") public final class ReflectHelper { + private static final Pattern JAVA_CONSTANT_PATTERN = Pattern.compile( + "[a-z\\d]+\\.([A-Z]+[a-z\\d]+)+\\$?([A-Z]{1}[a-z\\d]+)*\\.[A-Z_\\$]+", Pattern.UNICODE_CHARACTER_CLASS); public static final Class[] NO_PARAM_SIGNATURE = new Class[0]; public static final Object[] NO_PARAMS = new Object[0]; @@ -229,9 +233,15 @@ public final class ReflectHelper { return PropertyAccessStrategyMixedImpl.INSTANCE.buildPropertyAccess( clazz, name ).getGetter(); } - public static Object getConstantValue(String name, ClassLoaderService classLoaderService) { + public static Object getConstantValue(String name, SessionFactoryImplementor factory) { + boolean conventionalJavaConstants = factory.getSessionFactoryOptions().isConventionalJavaConstants(); Class clazz; try { + if ( conventionalJavaConstants && + !JAVA_CONSTANT_PATTERN.matcher( name ).find() ) { + return null; + } + ClassLoaderService classLoaderService = factory.getServiceRegistry().getService( ClassLoaderService.class ); clazz = classLoaderService.classForName( StringHelper.qualifier( name ) ); } catch ( Throwable t ) {