You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2023/06/11 15:14:27 UTC
[commons-fileupload] 02/02: Use a file item builder
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-fileupload.git
commit 16f56322539eebcccf16e19faac7cd756b5a7f4b
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Jun 11 11:14:21 2023 -0400
Use a file item builder
---
.../commons/fileupload2/AbstractFileUpload.java | 11 +-
.../commons/fileupload2/FileItemFactory.java | 122 +++++++++++++++++++--
.../commons/fileupload2/FileItemIteratorImpl.java | 10 +-
.../apache/commons/fileupload2/FileItemStream.java | 10 +-
.../commons/fileupload2/disk/DiskFileItem.java | 98 +++++------------
.../fileupload2/disk/DiskFileItemFactory.java | 29 +----
.../disk/DiskFileItemSerializeTest.java | 14 ++-
7 files changed, 179 insertions(+), 115 deletions(-)
diff --git a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/AbstractFileUpload.java b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/AbstractFileUpload.java
index 9909d3f..bd5f566 100644
--- a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/AbstractFileUpload.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/AbstractFileUpload.java
@@ -420,8 +420,15 @@ public abstract class AbstractFileUpload {
final FileItemStream fileItemStream = iter.next();
// Don't use getName() here to prevent an InvalidFileNameException.
final String fileName = fileItemStream.getName();
- final FileItem fileItem = fileItemFactory.createFileItem(fileItemStream.getFieldName(), fileItemStream.getContentType(),
- fileItemStream.isFormField(), fileName, fileItemStream.getHeaders());
+ // @formatter:off
+ final FileItem fileItem = fileItemFactory.fileItemBuilder()
+ .setFieldName(fileItemStream.getFieldName())
+ .setContentType(fileItemStream.getContentType())
+ .setFormField(fileItemStream.isFormField())
+ .setFileName(fileName)
+ .setFileItemHeaders(fileItemStream.getHeaders())
+ .get();
+ // @formatter:on
itemList.add(fileItem);
try (InputStream inputStream = fileItemStream.getInputStream();
OutputStream outputStream = fileItem.getOutputStream()) {
diff --git a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemFactory.java b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemFactory.java
index 43d8775..ebb130d 100644
--- a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemFactory.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemFactory.java
@@ -16,6 +16,12 @@
*/
package org.apache.commons.fileupload2;
+import org.apache.commons.fileupload2.disk.DiskFileItem;
+import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
+import org.apache.commons.io.FileCleaningTracker;
+import org.apache.commons.io.build.AbstractStreamBuilder;
+import org.apache.commons.io.file.PathUtils;
+
/**
* Creates {@link FileItem} instances.
* <p>
@@ -25,15 +31,115 @@ package org.apache.commons.fileupload2;
public interface FileItemFactory {
/**
- * Creates a new {@link FileItem} instance from the supplied parameters and any local factory configuration.
+ * Builds a new {@link DiskFileItem} instance.
+ * <p>
+ * For example:
+ * </p>
+ *
+ * <pre>{@code
+ * DiskFileItem diskFileItem = DiskFileItem.builder().get();
+ * }
+ * </pre>
*
- * @param fieldName The name of the form field.
- * @param contentType The content type of the form field.
- * @param isFormField {@code true} if this is a plain form field; {@code false} otherwise.
- * @param fileName The name of the uploaded file, if any, as supplied by the browser or other client.
- * @param fileItemHeaders The file item headers.
- * @return The newly created file item.
+ * @param <T> the type of instances to build.
+ * @param <B> the type of builder subclass.
*/
- FileItem createFileItem(String fieldName, String contentType, boolean isFormField, String fileName, FileItemHeaders fileItemHeaders);
+ abstract class FileItemBuilder<T extends FileItem, B extends FileItemBuilder<T, B>> extends AbstractStreamBuilder<T, B> {
+
+ /**
+ * Field name.
+ */
+ private String fieldName;
+
+ /**
+ * Content type.
+ */
+ private String contentType;
+
+ /**
+ * Is this a form field.
+ */
+ private boolean isFormField;
+
+ /**
+ * File name.
+ */
+ private String fileName;
+
+ /**
+ * File item headers.
+ */
+ private FileItemHeaders fileItemHeaders;
+
+ /**
+ * The instance of {@link FileCleaningTracker}, which is responsible for deleting temporary files.
+ * <p>
+ * May be null, if tracking files is not required.
+ * </p>
+ */
+ private FileCleaningTracker fileCleaningTracker;
+
+ public FileItemBuilder() {
+ setBufferSize(DiskFileItemFactory.DEFAULT_THRESHOLD);
+ setPath(PathUtils.getTempDirectory());
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ public FileCleaningTracker getFileCleaningTracker() {
+ return fileCleaningTracker;
+ }
+
+ public FileItemHeaders getFileItemHeaders() {
+ return fileItemHeaders;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public boolean isFormField() {
+ return isFormField;
+ }
+
+ public B setContentType(final String contentType) {
+ this.contentType = contentType;
+ return asThis();
+ }
+
+ public B setFieldName(final String fieldName) {
+ this.fieldName = fieldName;
+ return asThis();
+ }
+
+ public B setFileCleaningTracker(final FileCleaningTracker fileCleaningTracker) {
+ this.fileCleaningTracker = fileCleaningTracker;
+ return asThis();
+ }
+
+ public B setFileItemHeaders(final FileItemHeaders fileItemHeaders) {
+ this.fileItemHeaders = fileItemHeaders;
+ return asThis();
+ }
+
+ public B setFileName(final String fileName) {
+ this.fileName = fileName;
+ return asThis();
+ }
+
+ public B setFormField(final boolean isFormField) {
+ this.isFormField = isFormField;
+ return asThis();
+ }
+
+ }
+
+ <T extends FileItem, B extends FileItemBuilder<T, B>> FileItemBuilder<T, B> fileItemBuilder();
}
diff --git a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemIteratorImpl.java b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemIteratorImpl.java
index 25d987e..503c56d 100644
--- a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemIteratorImpl.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemIteratorImpl.java
@@ -196,7 +196,15 @@ class FileItemIteratorImpl implements FileItemIterator {
final List<FileItem> items = new ArrayList<>();
while (hasNext()) {
final FileItemStream fis = next();
- items.add(fileUploadBase.getFileItemFactory().createFileItem(fis.getFieldName(), fis.getContentType(), fis.isFormField(), fis.getName(), null));
+ // @formatter:off
+ final FileItem fileItem = fileUploadBase.getFileItemFactory().fileItemBuilder()
+ .setFieldName(fis.getFieldName())
+ .setContentType(fis.getContentType())
+ .setFormField(fis.isFormField())
+ .setFileName(fis.getName())
+ .get();
+ // @formatter:on
+ items.add(fileItem);
}
return items;
}
diff --git a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemStream.java b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemStream.java
index 9f460a9..62b3442 100644
--- a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemStream.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemStream.java
@@ -41,6 +41,11 @@ public interface FileItemStream extends FileItemHeadersSupport {
*/
class ItemSkippedException extends FileUploadException {
+ /**
+ * The exceptions serial version UID, which is being used when serializing an exception instance.
+ */
+ private static final long serialVersionUID = 2;
+
/**
* Constructs an instance with a given detail message.
*
@@ -50,11 +55,6 @@ public interface FileItemStream extends FileItemHeadersSupport {
super(message);
}
- /**
- * The exceptions serial version UID, which is being used when serializing an exception instance.
- */
- private static final long serialVersionUID = 2;
-
}
/**
diff --git a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItem.java b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItem.java
index 4443541..6600877 100644
--- a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItem.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItem.java
@@ -36,12 +36,13 @@ import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.fileupload2.FileItem;
+import org.apache.commons.fileupload2.FileItemFactory.FileItemBuilder;
import org.apache.commons.fileupload2.FileItemHeaders;
import org.apache.commons.fileupload2.FileUploadException;
import org.apache.commons.fileupload2.ParameterParser;
import org.apache.commons.io.Charsets;
+import org.apache.commons.io.FileCleaningTracker;
import org.apache.commons.io.build.AbstractOrigin;
-import org.apache.commons.io.build.AbstractStreamBuilder;
import org.apache.commons.io.file.PathUtils;
import org.apache.commons.io.function.Uncheck;
import org.apache.commons.io.output.DeferredFileOutputStream;
@@ -73,37 +74,11 @@ public final class DiskFileItem implements FileItem {
* </p>
*
* <pre>{@code
- * DiskFileItem diskFileItem = DiskFileItem.builder()
- * .get();
+ * DiskFileItem diskFileItem = DiskFileItem.builder().get();
* }
* </pre>
*/
- public static class Builder extends AbstractStreamBuilder<DiskFileItem, Builder> {
-
- /**
- * Field name.
- */
- private String fieldName;
-
- /**
- * Content type.
- */
- private String contentType;
-
- /**
- * Is this a form field.
- */
- private boolean isFormField;
-
- /**
- * File name.
- */
- private String fileName;
-
- /**
- * File item headers.
- */
- private FileItemHeaders fileItemHeaders;
+ public static class Builder extends FileItemBuilder<DiskFileItem, Builder> {
public Builder() {
setBufferSize(DiskFileItemFactory.DEFAULT_THRESHOLD);
@@ -128,32 +103,13 @@ public final class DiskFileItem implements FileItem {
*/
@Override
public DiskFileItem get() {
- return new DiskFileItem(fieldName, contentType, isFormField, fileName, getBufferSize(), getPath(), fileItemHeaders, getCharset());
- }
-
- public Builder setContentType(final String contentType) {
- this.contentType = contentType;
- return this;
- }
-
- public Builder setFieldName(final String fieldName) {
- this.fieldName = fieldName;
- return this;
- }
-
- public Builder setFileItemHeaders(final FileItemHeaders fileItemHeaders) {
- this.fileItemHeaders = fileItemHeaders;
- return this;
- }
-
- public Builder setFileName(final String fileName) {
- this.fileName = fileName;
- return this;
- }
-
- public Builder setFormField(final boolean isFormField) {
- this.isFormField = isFormField;
- return this;
+ final DiskFileItem diskFileItem = new DiskFileItem(getFieldName(), getContentType(), isFormField(), getFileName(), getBufferSize(), getPath(),
+ getFileItemHeaders(), getCharset());
+ final FileCleaningTracker tracker = getFileCleaningTracker();
+ if (tracker != null) {
+ tracker.track(diskFileItem.getTempFile().toFile(), diskFileItem);
+ }
+ return diskFileItem;
}
}
@@ -297,14 +253,14 @@ public final class DiskFileItem implements FileItem {
/**
* Constructs a new {@code DiskFileItem} instance.
*
- * @param fieldName The name of the form field.
- * @param contentType The content type passed by the browser or {@code null} if not specified.
- * @param isFormField Whether or not this item is a plain form field, as opposed to a file upload.
- * @param fileName The original file name in the user's file system, or {@code null} if not specified.
- * @param threshold The threshold, in bytes, below which items will be retained in memory and above which they will be stored as a file.
- * @param repository The data repository, which is the directory in which files will be created, should the item size exceed the threshold.
+ * @param fieldName The name of the form field.
+ * @param contentType The content type passed by the browser or {@code null} if not specified.
+ * @param isFormField Whether or not this item is a plain form field, as opposed to a file upload.
+ * @param fileName The original file name in the user's file system, or {@code null} if not specified.
+ * @param threshold The threshold, in bytes, below which items will be retained in memory and above which they will be stored as a file.
+ * @param repository The data repository, which is the directory in which files will be created, should the item size exceed the threshold.
* @param fileItemHeaders The file item headers.
- * @param defaultCharset The default Charset.
+ * @param defaultCharset The default Charset.
*/
private DiskFileItem(final String fieldName, final String contentType, final boolean isFormField, final String fileName, final int threshold,
final Path repository, final FileItemHeaders fileItemHeaders, final Charset defaultCharset) {
@@ -369,22 +325,22 @@ public final class DiskFileItem implements FileItem {
}
/**
- * Gets the content type passed by the agent or {@code null} if not defined.
+ * Gets the default charset for use when no explicit charset parameter is provided by the sender.
*
- * @return The content type passed by the agent or {@code null} if not defined.
+ * @return the default charset
*/
- @Override
- public String getContentType() {
- return contentType;
+ public Charset getCharsetDefault() {
+ return charsetDefault;
}
/**
- * Gets the default charset for use when no explicit charset parameter is provided by the sender.
+ * Gets the content type passed by the agent or {@code null} if not defined.
*
- * @return the default charset
+ * @return The content type passed by the agent or {@code null} if not defined.
*/
- public Charset getCharsetDefault() {
- return charsetDefault;
+ @Override
+ public String getContentType() {
+ return contentType;
}
/**
diff --git a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItemFactory.java b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItemFactory.java
index a7ce5df..19f1fc1 100644
--- a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItemFactory.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItemFactory.java
@@ -21,7 +21,6 @@ import java.nio.file.Path;
import org.apache.commons.fileupload2.FileItem;
import org.apache.commons.fileupload2.FileItemFactory;
-import org.apache.commons.fileupload2.FileItemHeaders;
import org.apache.commons.io.FileCleaningTracker;
import org.apache.commons.io.build.AbstractOrigin;
import org.apache.commons.io.build.AbstractStreamBuilder;
@@ -172,35 +171,15 @@ public final class DiskFileItemFactory implements FileItemFactory {
this.fileCleaningTracker = fileCleaningTracker;
}
- /**
- * Creates a new {@link DiskFileItem} instance from the supplied parameters and the local factory configuration.
- *
- * @param fieldName The name of the form field.
- * @param contentType The content type of the form field.
- * @param isFormField {@code true} if this is a plain form field; {@code false} otherwise.
- * @param fileName The name of the uploaded file, if any, as supplied by the browser or other client.
- * @return The newly created file item.
- */
@Override
- public FileItem createFileItem(final String fieldName, final String contentType, final boolean isFormField, final String fileName,
- final FileItemHeaders fileItemHeaders) {
+ public DiskFileItem.Builder fileItemBuilder() {
// @formatter:off
- final DiskFileItem result = DiskFileItem.builder()
+ return DiskFileItem.builder()
.setBufferSize(threshold)
- .setContentType(contentType)
.setCharset(charsetDefault)
- .setFieldName(fieldName)
- .setFileItemHeaders(fileItemHeaders)
- .setFileName(fileName)
- .setFormField(isFormField)
- .setPath(repository)
- .get();
+ .setFileCleaningTracker(fileCleaningTracker)
+ .setPath(repository);
// @formatter:on
- final FileCleaningTracker tracker = getFileCleaningTracker();
- if (tracker != null) {
- tracker.track(result.getTempFile().toFile(), result);
- }
- return result;
}
/**
diff --git a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/disk/DiskFileItemSerializeTest.java b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/disk/DiskFileItemSerializeTest.java
index 0ccf5e2..19b8bff 100644
--- a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/disk/DiskFileItemSerializeTest.java
+++ b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/disk/DiskFileItemSerializeTest.java
@@ -103,7 +103,15 @@ public class DiskFileItemSerializeTest {
final FileItemFactory factory = DiskFileItemFactory.builder().setBufferSize(THRESHOLD).setPath(repository).get();
final String textFieldName = "textField";
- final FileItem item = factory.createFileItem(textFieldName, TEXT_CONTENT_TYPE, true, "My File Name", null);
+ // @formatter:off
+ final FileItem item = factory.fileItemBuilder()
+ .setFieldName(textFieldName)
+ .setContentType(TEXT_CONTENT_TYPE)
+ .setFormField(true)
+ .setFileName("My File Name")
+ .get();
+ // @formatter:on
+
try (OutputStream os = item.getOutputStream()) {
os.write(contentBytes);
}
@@ -111,14 +119,14 @@ public class DiskFileItemSerializeTest {
}
/**
- * Do deserialization.
+ * Deserializes.
*/
private Object deserialize(final ByteArrayOutputStream baos) {
return SerializationUtils.deserialize(baos.toByteArray());
}
/**
- * Do serialization.
+ * Serializes.
*/
private ByteArrayOutputStream serialize(final Object target) throws IOException {
try (final ByteArrayOutputStream baos = new ByteArrayOutputStream();