You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by jo...@apache.org on 2019/09/23 13:30:17 UTC
[commons-fileupload] 01/02: PR: FILEUPLOAD-300
This is an automated email from the ASF dual-hosted git repository.
jochen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-fileupload.git
commit de1a19730600bd295a9f2c5c3bf83b0d0c20dc32
Author: Jochen Wiedmann <jo...@gmail.com>
AuthorDate: Mon Sep 23 15:15:17 2019 +0200
PR: FILEUPLOAD-300
Making FileItemIteratorImpl, and FileItemStreamImpl static, as a
preparation for moving them out.
---
.../commons/fileupload2/FileItemIterator.java | 148 +++++++++++++--------
.../apache/commons/fileupload2/FileUploadBase.java | 116 +++++++++++-----
2 files changed, 181 insertions(+), 83 deletions(-)
diff --git a/src/main/java/org/apache/commons/fileupload2/FileItemIterator.java b/src/main/java/org/apache/commons/fileupload2/FileItemIterator.java
index ac630df..b56706d 100644
--- a/src/main/java/org/apache/commons/fileupload2/FileItemIterator.java
+++ b/src/main/java/org/apache/commons/fileupload2/FileItemIterator.java
@@ -1,52 +1,96 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2;
-
-import java.io.IOException;
-
-/**
- * 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;
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.fileupload2.FileUploadBase.FileSizeLimitExceededException;
+
+/**
+ * An iterator, as returned by
+ * {@link FileUploadBase#getItemIterator(RequestContext)}.
+ */
+public interface FileItemIterator {
+ /** Returns the maximum size of a single file. An {@link FileSizeLimitExceededException}
+ * will be thrown, if there is an uploaded file, which is exceeding this value.
+ * By default, this value will be copied from the {@link FileUploadBase#getFileSizeMax()
+ * FileUploadBase} object, however, the user may replace the default value with a
+ * request specific value by invoking {@link #setFileSizeMax(long)} on this object.
+ * @return The maximum size of a single, uploaded file. The value -1 indicates "unlimited".
+ */
+ public long getFileSizeMax();
+
+ /** Sets the maximum size of a single file. An {@link FileSizeLimitExceededException}
+ * will be thrown, if there is an uploaded file, which is exceeding this value.
+ * By default, this value will be copied from the {@link FileUploadBase#getFileSizeMax()
+ * FileUploadBase} object, however, the user may replace the default value with a
+ * request specific value by invoking {@link #setFileSizeMax(long)} on this object, so
+ * there is no need to configure it here.
+ * <em>Note:</em>Changing this value doesn't affect files, that have already been uploaded.
+ * @param pFileSizeMax The maximum size of a single, uploaded file. The value -1 indicates "unlimited".
+ */
+ public void setFileSizeMax(long pFileSizeMax);
+
+ /** Returns the maximum size of the complete HTTP request. A {@link SizeLimitExceededException}
+ * will be thrown, if the HTTP request will exceed this value.
+ * By default, this value will be copied from the {@link FileUploadBase#getSizeMax()
+ * FileUploadBase} object, however, the user may replace the default value with a
+ * request specific value by invoking {@link #setSizeMax(long)} on this object.
+ * @return The maximum size of the complete HTTP requqest. The value -1 indicates "unlimited".
+ */
+ public long getSizeMax();
+
+ /** Returns the maximum size of the complete HTTP request. A {@link SizeLimitExceededException}
+ * will be thrown, if the HTTP request will exceed this value.
+ * By default, this value will be copied from the {@link FileUploadBase#getSizeMax()
+ * FileUploadBase} object, however, the user may replace the default value with a
+ * request specific value by invoking {@link #setSizeMax(long)} on this object.
+ * <em>Note:</em> Setting the maximum size on this object will work only, if the iterator is not
+ * yet initialized. In other words: If the methods {@link #hasNext()}, {@link #next()} have not
+ * yet been invoked.
+ * @param pSizeMax The maximum size of the complete HTTP request. The value -1 indicates "unlimited".
+ */
+ public void setSizeMax(long pSizeMax);
+
+ /**
+ * 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.
+ */
+ public 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.
+ */
+ public FileItemStream next() throws FileUploadException, IOException;
+
+ public List<FileItem> getFileItems() throws FileUploadException, IOException;
+}
diff --git a/src/main/java/org/apache/commons/fileupload2/FileUploadBase.java b/src/main/java/org/apache/commons/fileupload2/FileUploadBase.java
index 777f34d..c15b0f9 100644
--- a/src/main/java/org/apache/commons/fileupload2/FileUploadBase.java
+++ b/src/main/java/org/apache/commons/fileupload2/FileUploadBase.java
@@ -306,7 +306,7 @@ public abstract class FileUploadBase {
public FileItemIterator getItemIterator(RequestContext ctx)
throws FileUploadException, IOException {
try {
- return new FileItemIteratorImpl(ctx);
+ return new FileItemIteratorImpl(this, ctx);
} catch (FileUploadIOException e) {
// unwrap encapsulated SizeException
throw (FileUploadException) e.getCause();
@@ -706,12 +706,37 @@ public abstract class FileUploadBase {
* The iterator, which is returned by
* {@link FileUploadBase#getItemIterator(RequestContext)}.
*/
- private class FileItemIteratorImpl implements FileItemIterator {
+ private static class FileItemIteratorImpl implements FileItemIterator {
+ private final FileUploadBase fileUploadBase;
+ private final RequestContext ctx;
+ private long sizeMax, fileSizeMax;
- /**
+
+ @Override
+ public long getSizeMax() {
+ return sizeMax;
+ }
+
+ @Override
+ public void setSizeMax(long sizeMax) {
+ this.sizeMax = sizeMax;
+ }
+
+ @Override
+ public long getFileSizeMax() {
+ return fileSizeMax;
+ }
+
+ @Override
+ public void setFileSizeMax(long fileSizeMax) {
+ this.fileSizeMax = fileSizeMax;
+ }
+
+ /**
* Default implementation of {@link FileItemStream}.
*/
- class FileItemStreamImpl implements FileItemStream {
+ public static class FileItemStreamImpl implements FileItemStream {
+ private final FileItemIteratorImpl fileItemIteratorImpl;
/**
* The file items content type.
@@ -758,13 +783,15 @@ public abstract class FileUploadBase {
* @param pContentLength The items content length, if known, or -1
* @throws IOException Creating the file item failed.
*/
- FileItemStreamImpl(String pName, String pFieldName,
+ FileItemStreamImpl(FileItemIteratorImpl pFileItemIterator, String pName, String pFieldName,
String pContentType, boolean pFormField,
- long pContentLength) throws IOException {
+ long pContentLength) throws FileUploadException, IOException {
+ fileItemIteratorImpl = pFileItemIterator;
name = pName;
fieldName = pFieldName;
contentType = pContentType;
formField = pFormField;
+ final long fileSizeMax = fileItemIteratorImpl.getFileSizeMax();
if (fileSizeMax != -1) { // Check if limit is already exceeded
if (pContentLength != -1
&& pContentLength > fileSizeMax) {
@@ -779,7 +806,7 @@ public abstract class FileUploadBase {
}
}
// OK to construct stream now
- final ItemInputStream itemStream = multi.newInputStream();
+ final ItemInputStream itemStream = fileItemIteratorImpl.getMultiPartStream().newInputStream();
InputStream istream = itemStream;
if (fileSizeMax != -1) {
istream = new LimitedInputStream(istream, fileSizeMax) {
@@ -899,18 +926,18 @@ public abstract class FileUploadBase {
/**
* The multi part stream to process.
*/
- private final MultipartStream multi;
+ private MultipartStream multiPartStream;
/**
* The notifier, which used for triggering the
* {@link ProgressListener}.
*/
- private final MultipartStream.ProgressNotifier notifier;
+ private MultipartStream.ProgressNotifier progressNotifier;
/**
* The boundary, which separates the various parts.
*/
- private final byte[] boundary;
+ private byte[] multiPartBoundary;
/**
* The item, which we currently process.
@@ -945,12 +972,23 @@ public abstract class FileUploadBase {
* parsing the request.
* @throws IOException An I/O error occurred.
*/
- FileItemIteratorImpl(RequestContext ctx)
+ FileItemIteratorImpl(FileUploadBase pFileUploadBase, RequestContext pRequestContext)
throws FileUploadException, IOException {
+ fileUploadBase = pFileUploadBase;
+ sizeMax = fileUploadBase.getSizeMax();
+ fileSizeMax = fileUploadBase.getFileSizeMax();
+ ctx = pRequestContext;
if (ctx == null) {
throw new NullPointerException("ctx parameter");
}
+
+ skipPreamble = true;
+ findNextItem();
+ }
+
+ protected void init(FileUploadBase fileUploadBase, RequestContext pRequestContext)
+ throws FileUploadException, IOException {
String contentType = ctx.getContentType();
if ((null == contentType)
|| (!contentType.toLowerCase(Locale.ENGLISH).startsWith(MULTIPART))) {
@@ -993,38 +1031,42 @@ public abstract class FileUploadBase {
input = ctx.getInputStream();
}
- String charEncoding = headerEncoding;
+ String charEncoding = fileUploadBase.getHeaderEncoding();
if (charEncoding == null) {
charEncoding = ctx.getCharacterEncoding();
}
- boundary = getBoundary(contentType);
- if (boundary == null) {
+ multiPartBoundary = fileUploadBase.getBoundary(contentType);
+ if (multiPartBoundary == null) {
IOUtils.closeQuietly(input); // avoid possible resource leak
throw new FileUploadException("the request was rejected because no multipart boundary was found");
}
- notifier = new MultipartStream.ProgressNotifier(listener, requestSize);
+ progressNotifier = new MultipartStream.ProgressNotifier(fileUploadBase.getProgressListener(), requestSize);
try {
- multi = new MultipartStream(input, boundary, notifier);
+ multiPartStream = new MultipartStream(input, multiPartBoundary, progressNotifier);
} 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);
}
- multi.setHeaderEncoding(charEncoding);
-
- skipPreamble = true;
- findNextItem();
+ multiPartStream.setHeaderEncoding(charEncoding);
}
+ public MultipartStream getMultiPartStream() throws FileUploadException, IOException {
+ if (multiPartStream == null) {
+ init(fileUploadBase, ctx);
+ }
+ return multiPartStream;
+ }
+
/**
* Called for finding the next item, if any.
*
* @return True, if an next item was found, otherwise false.
* @throws IOException An I/O error occurred.
*/
- private boolean findNextItem() throws IOException {
+ private boolean findNextItem() throws FileUploadException, IOException {
if (eof) {
return false;
}
@@ -1032,6 +1074,7 @@ public abstract class FileUploadBase {
currentItem.close();
currentItem = null;
}
+ final MultipartStream multi = getMultiPartStream();
for (;;) {
boolean nextPart;
if (skipPreamble) {
@@ -1046,14 +1089,14 @@ public abstract class FileUploadBase {
return false;
}
// Inner multipart terminated -> Return to parsing the outer
- multi.setBoundary(boundary);
+ multi.setBoundary(multiPartBoundary);
currentFieldName = null;
continue;
}
- FileItemHeaders headers = getParsedHeaders(multi.readHeaders());
+ FileItemHeaders headers = fileUploadBase.getParsedHeaders(multi.readHeaders());
if (currentFieldName == null) {
// We're parsing the outer multipart
- String fieldName = getFieldName(headers);
+ String fieldName = fileUploadBase.getFieldName(headers);
if (fieldName != null) {
String subContentType = headers.getHeader(CONTENT_TYPE);
if (subContentType != null
@@ -1061,29 +1104,29 @@ public abstract class FileUploadBase {
.startsWith(MULTIPART_MIXED)) {
currentFieldName = fieldName;
// Multiple files associated with this field name
- byte[] subBoundary = getBoundary(subContentType);
+ byte[] subBoundary = fileUploadBase.getBoundary(subContentType);
multi.setBoundary(subBoundary);
skipPreamble = true;
continue;
}
- String fileName = getFileName(headers);
- currentItem = new FileItemStreamImpl(fileName,
+ String fileName = fileUploadBase.getFileName(headers);
+ currentItem = new FileItemStreamImpl(this, fileName,
fieldName, headers.getHeader(CONTENT_TYPE),
fileName == null, getContentLength(headers));
currentItem.setHeaders(headers);
- notifier.noteItem();
+ progressNotifier.noteItem();
itemValid = true;
return true;
}
} else {
- String fileName = getFileName(headers);
+ String fileName = fileUploadBase.getFileName(headers);
if (fileName != null) {
- currentItem = new FileItemStreamImpl(fileName,
+ currentItem = new FileItemStreamImpl(this, fileName,
currentFieldName,
headers.getHeader(CONTENT_TYPE),
false, getContentLength(headers));
currentItem.setHeaders(headers);
- notifier.noteItem();
+ progressNotifier.noteItem();
itemValid = true;
return true;
}
@@ -1146,6 +1189,17 @@ public abstract class FileUploadBase {
return currentItem;
}
+ @Override
+ public List<FileItem> getFileItems() throws FileUploadException, IOException {
+ final List<FileItem> items = new ArrayList<FileItem>();
+ while (hasNext()) {
+ final FileItemStream fis = next();
+ final FileItem fi = fileUploadBase.getFileItemFactory().createItem(fis.getFieldName(), fis.getContentType(), fis.isFormField(), fis.getName());
+ items.add(fi);
+ }
+ return items;
+ }
+
}
/**