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 0332c98cb428976e9a7e37e783d827c5b382f063
Author: Gary Gregory <garydgreg...@gmail.com>
AuthorDate: Sun Jul 9 17:41:10 2023 -0400

    Generics
---
 .../fileupload2/core/AbstractFileUpload.java       | 75 +++++++++++-----------
 .../apache/commons/fileupload2/core/FileItem.java  | 27 ++++----
 .../commons/fileupload2/core/FileItemFactory.java  | 16 +++--
 .../fileupload2/core/FileItemHeadersProvider.java  |  6 +-
 .../commons/fileupload2/core/FileItemInput.java    |  2 +-
 .../fileupload2/core/FileItemInputImpl.java        |  3 +-
 .../core/FileItemInputIteratorImpl.java            |  6 +-
 .../commons/fileupload2/core/MultipartInput.java   | 10 +--
 .../fileupload2/core/disk/DiskFileItem.java        | 65 ++++++++++---------
 .../fileupload2/core/disk/DiskFileItemFactory.java |  9 ++-
 .../fileupload2/core/disk/package-info.java        |  8 +--
 .../fileupload2/core/AbstractFileUploadTest.java   | 74 +++++++++++----------
 .../core/AbstractFileUploadWrapper.java            | 21 +++---
 .../core/AbstractProgressListenerTest.java         | 11 ++--
 .../fileupload2/core/AbstractSizesTest.java        | 25 ++++----
 .../fileupload2/core/AbstractStreamingTest.java    | 38 ++++++-----
 .../commons/fileupload2/core/AbstractTest.java     | 10 +--
 .../core/disk/DiskFileItemSerializeTest.java       | 17 +++--
 .../jakarta/JakartaServletFileUpload.java          | 15 +++--
 .../commons/fileupload2/jakarta/package-info.java  |  3 +-
 .../jakarta/JakartaProgressListenerTest.java       |  9 ++-
 .../jakarta/JakartaServletFileUploadTest.java      | 20 +++---
 .../fileupload2/jakarta/JakartaSizesTest.java      | 11 ++--
 .../fileupload2/jakarta/JakartaStreamingTest.java  | 14 +++-
 .../fileupload2/javax/JavaxServletFileUpload.java  | 15 +++--
 .../commons/fileupload2/javax/package-info.java    |  7 +-
 .../javax/JavaxProgressListenerTest.java           |  9 ++-
 .../javax/JavaxServletFileUploadTest.java          | 26 ++++----
 .../commons/fileupload2/javax/JavaxSizesTest.java  | 11 ++--
 .../fileupload2/javax/JavaxStreamingTest.java      | 14 +++-
 .../portlet/JavaxPortletFileUpload.java            | 19 +++---
 ...ontext.java => JavaxPortletRequestContext.java} |  4 +-
 .../commons/fileupload2/portlet/package-info.java  |  4 +-
 ...adTest.java => JavaxPortletFileUploadTest.java} | 23 ++++---
 ...est.java => JavaxPortletMockActionRequest.java} |  8 +--
 35 files changed, 354 insertions(+), 281 deletions(-)

diff --git 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/AbstractFileUpload.java
 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/AbstractFileUpload.java
index b927e38..aeb1ec7 100644
--- 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/AbstractFileUpload.java
+++ 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/AbstractFileUpload.java
@@ -35,15 +35,18 @@ import org.apache.commons.io.IOUtils;
  * High level API for processing file uploads.
  * <p>
  * This class handles multiple files per single HTML widget, sent using {@code 
multipart/mixed} encoding type, as specified by
- * <a href="http://www.ietf.org/rfc/rfc1867.txt";>RFC 1867</a>. Use {@link 
#parseRequest(RequestContext)} to acquire a list of
- * {@link FileItem}s associated with a given HTML widget.
+ * <a href="http://www.ietf.org/rfc/rfc1867.txt";>RFC 1867</a>. Use {@link 
#parseRequest(RequestContext)} to acquire a list of {@link FileItem}s 
associated with
+ * a given HTML widget.
  * </p>
  * <p>
  * 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.
  * </p>
- * @param <T> the context type
+ *
+ * @param <R> The request context type.
+ * @param <I> The FileItem type.
+ * @param <F> the FileItemFactory type.
  */
-public abstract class AbstractFileUpload<T> {
+public abstract class AbstractFileUpload<R, I extends FileItem<I>, F extends 
FileItemFactory<I>> {
 
     /**
      * Boundary parameter key.
@@ -146,7 +149,7 @@ public abstract class AbstractFileUpload<T> {
     /**
      * The factory to use to create new form items.
      */
-    private FileItemFactory fileItemFactory;
+    private F fileItemFactory;
 
     /**
      * Gets the boundary from the {@code Content-type} header.
@@ -208,7 +211,7 @@ public abstract class AbstractFileUpload<T> {
      *
      * @return The factory class for new file items.
      */
-    public FileItemFactory getFileItemFactory() {
+    public F getFileItemFactory() {
         return fileItemFactory;
     }
 
@@ -275,28 +278,28 @@ public abstract class AbstractFileUpload<T> {
     }
 
     /**
-     * Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt";>RFC 1867</a> 
compliant {@code multipart/form-data} stream.
+     * Gets a file item iterator.
      *
-     * @param requestContext The context for the request to be parsed.
+     * @param request The servlet request to be parsed.
      * @return An iterator to instances of {@code FileItemInput} parsed from 
the request, in the order that they were transmitted.
      * @throws FileUploadException if there are problems reading/parsing the 
request or storing files.
      * @throws IOException         An I/O error occurred. This may be a 
network error while communicating with the client or a problem while storing the
      *                             uploaded content.
      */
-    public FileItemInputIterator getItemIterator(final RequestContext 
requestContext) throws FileUploadException, IOException {
-        return new FileItemInputIteratorImpl(this, requestContext);
-    }
+    public abstract FileItemInputIterator getItemIterator(R request) throws 
FileUploadException, IOException;
 
     /**
-     * Gets a file item iterator.
+     * Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt";>RFC 1867</a> 
compliant {@code multipart/form-data} stream.
      *
-     * @param request The servlet request to be parsed.
+     * @param requestContext The context for the request to be parsed.
      * @return An iterator to instances of {@code FileItemInput} parsed from 
the request, in the order that they were transmitted.
      * @throws FileUploadException if there are problems reading/parsing the 
request or storing files.
      * @throws IOException         An I/O error occurred. This may be a 
network error while communicating with the client or a problem while storing the
      *                             uploaded content.
      */
-    public abstract FileItemInputIterator getItemIterator(T request) throws 
FileUploadException, IOException;
+    public FileItemInputIterator getItemIterator(final RequestContext 
requestContext) throws FileUploadException, IOException {
+        return new FileItemInputIteratorImpl(this, requestContext);
+    }
 
     /**
      * Parses the {@code header-part} and returns as key/value pairs.
@@ -407,6 +410,15 @@ public abstract class AbstractFileUpload<T> {
         headers.addHeader(headerName, headerValue);
     }
 
+    /**
+     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt";>RFC 1867</a> 
compliant {@code multipart/form-data} stream.
+     *
+     * @param request The servlet request to be parsed.
+     * @return A map of {@code FileItem} instances parsed from the request.
+     * @throws FileUploadException if there are problems reading/parsing the 
request or storing files.
+     */
+    public abstract Map<String, List<I>> parseParameterMap(R request) throws 
FileUploadException;
+
     /**
      * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt";>RFC 1867</a> 
compliant {@code multipart/form-data} stream.
      *
@@ -414,13 +426,13 @@ public abstract class AbstractFileUpload<T> {
      * @return A map of {@code FileItem} instances parsed from the request.
      * @throws FileUploadException if there are problems reading/parsing the 
request or storing files.
      */
-    public Map<String, List<FileItem>> parseParameterMap(final RequestContext 
ctx) throws FileUploadException {
-        final List<FileItem> items = parseRequest(ctx);
-        final Map<String, List<FileItem>> itemsMap = new 
HashMap<>(items.size());
+    public Map<String, List<I>> parseParameterMap(final RequestContext ctx) 
throws FileUploadException {
+        final List<I> items = parseRequest(ctx);
+        final Map<String, List<I>> itemsMap = new HashMap<>(items.size());
 
-        for (final FileItem fileItem : items) {
+        for (final I fileItem : items) {
             final String fieldName = fileItem.getFieldName();
-            final List<FileItem> mappedItems = 
itemsMap.computeIfAbsent(fieldName, k -> new ArrayList<>());
+            final List<I> mappedItems = itemsMap.computeIfAbsent(fieldName, k 
-> new ArrayList<>());
             mappedItems.add(fileItem);
         }
 
@@ -431,10 +443,10 @@ public abstract class AbstractFileUpload<T> {
      * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt";>RFC 1867</a> 
compliant {@code multipart/form-data} stream.
      *
      * @param request The servlet request to be parsed.
-     * @return A map of {@code FileItem} instances parsed from the request.
+     * @return A list of {@code FileItem} instances parsed from the request, 
in the order that they were transmitted.
      * @throws FileUploadException if there are problems reading/parsing the 
request or storing files.
      */
-    public abstract Map<String, List<FileItem>> parseParameterMap(T request) 
throws FileUploadException;
+    public abstract List<I> parseRequest(R request) throws FileUploadException;
 
     /**
      * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt";>RFC 1867</a> 
compliant {@code multipart/form-data} stream.
@@ -443,11 +455,11 @@ public abstract class AbstractFileUpload<T> {
      * @return A list of {@code FileItem} instances parsed from the request, 
in the order that they were transmitted.
      * @throws FileUploadException if there are problems reading/parsing the 
request or storing files.
      */
-    public List<FileItem> parseRequest(final RequestContext requestContext) 
throws FileUploadException {
-        final List<FileItem> itemList = new ArrayList<>();
+    public List<I> parseRequest(final RequestContext requestContext) throws 
FileUploadException {
+        final List<I> itemList = new ArrayList<>();
         boolean successful = false;
         try {
-            final FileItemFactory fileItemFactory = 
Objects.requireNonNull(getFileItemFactory(), "No FileItemFactory has been 
set.");
+            final F fileItemFactory = 
Objects.requireNonNull(getFileItemFactory(), "No FileItemFactory has been 
set.");
             final byte[] buffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE];
             getItemIterator(requestContext).forEachRemaining(fileItemInput -> {
                 if (itemList.size() == fileCountMax) {
@@ -456,7 +468,7 @@ public abstract class AbstractFileUpload<T> {
                 }
                 // Don't use getName() here to prevent an 
InvalidFileNameException.
                 // @formatter:off
-                final FileItem fileItem = fileItemFactory.fileItemBuilder()
+                final I fileItem = fileItemFactory.fileItemBuilder()
                     .setFieldName(fileItemInput.getFieldName())
                     .setContentType(fileItemInput.getContentType())
                     .setFormField(fileItemInput.isFormField())
@@ -482,7 +494,7 @@ public abstract class AbstractFileUpload<T> {
             throw new FileUploadException(e.getMessage(), e);
         } finally {
             if (!successful) {
-                for (final FileItem fileItem : itemList) {
+                for (final I fileItem : itemList) {
                     try {
                         fileItem.delete();
                     } catch (final Exception ignored) {
@@ -493,15 +505,6 @@ public abstract class AbstractFileUpload<T> {
         }
     }
 
-    /**
-     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt";>RFC 1867</a> 
compliant {@code multipart/form-data} stream.
-     *
-     * @param request The servlet request to be parsed.
-     * @return A list of {@code FileItem} instances parsed from the request, 
in the order that they were transmitted.
-     * @throws FileUploadException if there are problems reading/parsing the 
request or storing files.
-     */
-    public abstract List<FileItem> parseRequest(T request) throws 
FileUploadException;
-
     /**
      * Sets the maximum number of files allowed per request.
      *
@@ -516,7 +519,7 @@ public abstract class AbstractFileUpload<T> {
      *
      * @param factory The factory class for new file items.
      */
-    public void setFileItemFactory(final FileItemFactory factory) {
+    public void setFileItemFactory(final F factory) {
         this.fileItemFactory = factory;
     }
 
diff --git 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItem.java
 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItem.java
index f064d9c..18f8c79 100644
--- 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItem.java
+++ 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItem.java
@@ -39,17 +39,19 @@ import java.nio.file.Path;
  * defined with the same signatures as methods in that interface. This allows 
an implementation of this interface to also implement
  * {@code javax.activation.DataSource} with minimal additional work.
  * </p>
+ *
+ * @param <F> The FileItem type.
  */
-public interface FileItem extends FileItemHeadersProvider {
+public interface FileItem<F extends FileItem<F>> extends 
FileItemHeadersProvider<F> {
 
     /**
-     * Deletes the underlying storage for a file item, including deleting any 
associated temporary disk file. Although this storage will be deleted
-     * automatically when the {@code FileItem} instance is garbage collected, 
this method can be used to ensure that this is done at an earlier time, thus
-     * preserving system resources.
+     * Deletes the underlying storage for a file item, including deleting any 
associated temporary disk file. Use this method to ensure that this is done at 
an
+     * earlier time, to preserve resources.
      *
+     * @return this
      * @throws IOException if an error occurs.
      */
-    void delete() throws IOException;
+    F delete() throws IOException;
 
     /**
      * Gets the contents of the file item as a byte array.
@@ -88,8 +90,8 @@ public interface FileItem extends FileItemHeadersProvider {
      * name, without path information. However, some clients, such as the 
Opera browser, do include path information.
      *
      * @return The original file name in the client's file system.
-     * @throws InvalidPathException 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 InvalidFileNameException#getName().
+     * @throws InvalidPathException 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 
InvalidFileNameException#getName().
      */
     String getName();
 
@@ -124,7 +126,7 @@ public interface FileItem extends FileItemHeadersProvider {
      *
      * @return The contents of the item, as a string.
      *
-     * @throws IOException                  if an I/O error occurs
+     * @throws IOException if an I/O error occurs
      */
     String getString(Charset toCharset) throws IOException;
 
@@ -146,15 +148,17 @@ public interface FileItem extends FileItemHeadersProvider 
{
      * Sets the field name used to reference this file item.
      *
      * @param name The name of the form field.
+     * @return this
      */
-    void setFieldName(String name);
+    F setFieldName(String name);
 
     /**
      * Sets whether or not a {@code FileItem} instance represents a simple 
form field.
      *
      * @param state {@code true} if the instance represents a simple form 
field; {@code false} if it represents an uploaded file.
+     * @return this
      */
-    void setFormField(boolean state);
+    F setFormField(boolean state);
 
     /**
      * Writes an uploaded item to disk.
@@ -169,7 +173,8 @@ public interface FileItem extends FileItemHeadersProvider {
      *
      * @param file The {@code File} into which the uploaded item should be 
stored.
      * @throws IOException if an error occurs.
+     * @return this
      */
-    void write(Path file) throws IOException;
+    F write(Path file) throws IOException;
 
 }
diff --git 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemFactory.java
 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemFactory.java
index ad442e0..e09f6ea 100644
--- 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemFactory.java
+++ 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemFactory.java
@@ -26,16 +26,18 @@ import org.apache.commons.io.file.PathUtils;
  * <p>
  * Factories can provide their own custom configuration, over and above that 
provided by the default file upload implementation.
  * </p>
+ *
+ * @param <I> The {@link FileItem} type this factory creates.
  */
-public interface FileItemFactory {
+public interface FileItemFactory<I extends FileItem<I>> {
 
     /**
      * Abstracts building for subclasses.
      *
-     * @param <T> the type of instances to build.
+     * @param <I> the type of {@link FileItem} to build.
      * @param <B> the type of builder subclass.
      */
-    abstract class FileItemBuilder<T extends FileItem, B extends 
FileItemBuilder<T, B>> extends AbstractStreamBuilder<T, B> {
+    abstract class FileItemBuilder<I extends FileItem<I>, B extends 
FileItemBuilder<I, B>> extends AbstractStreamBuilder<I, B> {
 
         public static FileItemHeaders newFileItemHeaders() {
             return new FileItemHeadersImpl();
@@ -135,6 +137,12 @@ public interface FileItemFactory {
 
     }
 
-    <T extends FileItem, B extends FileItemBuilder<T, B>> FileItemBuilder<T, 
B> fileItemBuilder();
+    /**
+     * Creates a new FileItemBuilder.
+     *
+     * @param <B> The type of FileItemBuilder.
+     * @return a new FileItemBuilder.
+     */
+    <B extends FileItemBuilder<I, B>> FileItemBuilder<I, B> fileItemBuilder();
 
 }
diff --git 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemHeadersProvider.java
 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemHeadersProvider.java
index 74d2c46..55d2f55 100644
--- 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemHeadersProvider.java
+++ 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemHeadersProvider.java
@@ -19,10 +19,11 @@ package org.apache.commons.fileupload2.core;
 /**
  * Provides access to headers.
  *
+ * @param <T> The FileItemHeadersProvider type.
  * @see FileItem
  * @see FileItemInput
  */
-public interface FileItemHeadersProvider {
+public interface FileItemHeadersProvider<T extends FileItemHeadersProvider<T>> 
{
 
     /**
      * Gets the collection of headers defined locally within this item.
@@ -36,7 +37,8 @@ public interface FileItemHeadersProvider {
      * the raw headers found within the item header block.
      *
      * @param headers the instance that holds onto the headers for this 
instance.
+     * @return this
      */
-    void setHeaders(FileItemHeaders headers);
+    T setHeaders(FileItemHeaders headers);
 
 }
diff --git 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemInput.java
 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemInput.java
index 86dfc8a..e18e8d4 100644
--- 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemInput.java
+++ 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemInput.java
@@ -32,7 +32,7 @@ import java.io.InputStream;
  * {@link java.util.Iterator#hasNext()} on the iterator, you discard all data, 
which hasn't been read so far from the previous data.
  * </p>
  */
-public interface FileItemInput extends FileItemHeadersProvider {
+public interface FileItemInput extends FileItemHeadersProvider<FileItemInput> {
 
     /**
      * This exception is thrown, if an attempt is made to read data from the 
{@link InputStream}, which has been returned by
diff --git 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemInputImpl.java
 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemInputImpl.java
index 27c2a48..ffd1fd5 100644
--- 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemInputImpl.java
+++ 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemInputImpl.java
@@ -194,8 +194,9 @@ class FileItemInputImpl implements FileItemInput {
      * @param headers The items header object
      */
     @Override
-    public void setHeaders(final FileItemHeaders headers) {
+    public FileItemInputImpl setHeaders(final FileItemHeaders headers) {
         this.headers = headers;
+        return this;
     }
 
 }
diff --git 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemInputIteratorImpl.java
 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemInputIteratorImpl.java
index e4e2de0..09a8db3 100644
--- 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemInputIteratorImpl.java
+++ 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/FileItemInputIteratorImpl.java
@@ -38,7 +38,7 @@ class FileItemInputIteratorImpl implements 
FileItemInputIterator {
      *
      * @see AbstractFileUpload
      */
-    private final AbstractFileUpload<?> fileUpload;
+    private final AbstractFileUpload<?, ?, ?> fileUpload;
 
     /**
      * The request context.
@@ -105,7 +105,7 @@ class FileItemInputIteratorImpl implements 
FileItemInputIterator {
      * @throws FileUploadException An error occurred while parsing the request.
      * @throws IOException         An I/O error occurred.
      */
-    FileItemInputIteratorImpl(final AbstractFileUpload<?> fileUploadBase, 
final RequestContext requestContext) throws FileUploadException, IOException {
+    FileItemInputIteratorImpl(final AbstractFileUpload<?, ?, ?> 
fileUploadBase, final RequestContext requestContext) throws 
FileUploadException, IOException {
         this.fileUpload = fileUploadBase;
         this.sizeMax = fileUploadBase.getSizeMax();
         this.fileSizeMax = fileUploadBase.getFileSizeMax();
@@ -227,7 +227,7 @@ class FileItemInputIteratorImpl implements 
FileItemInputIterator {
         return findNextItem();
     }
 
-    protected void init(final AbstractFileUpload<?> fileUploadBase, final 
RequestContext initContext) throws FileUploadException, IOException {
+    protected void init(final AbstractFileUpload<?, ?, ?> fileUploadBase, 
final RequestContext initContext) throws FileUploadException, IOException {
         final String contentType = requestContext.getContentType();
         if (null == contentType || 
!contentType.toLowerCase(Locale.ENGLISH).startsWith(AbstractFileUpload.MULTIPART))
 {
             throw new FileUploadContentTypeException(String.format("the 
request doesn't contain a %s or %s stream, content type header is %s",
diff --git 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/MultipartInput.java
 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/MultipartInput.java
index 4c52e9d..e004c86 100644
--- 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/MultipartInput.java
+++ 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/MultipartInput.java
@@ -91,10 +91,7 @@ public final class MultipartInput {
      * </p>
      *
      * <pre>{@code
-     * MultipartInput factory = MultipartInput.builder()
-     *    .setPath(path)
-     *    .setBufferSize(DEFAULT_THRESHOLD)
-     *    .get();
+     * MultipartInput factory = 
MultipartInput.builder().setPath(path).setBufferSize(DEFAULT_THRESHOLD).get();
      * }
      * </pre>
      */
@@ -125,7 +122,7 @@ public final class MultipartInput {
          * </p>
          *
          * @return a new instance.
-         * @throws IOException if an I/O error occurs.
+         * @throws IOException                   if an I/O error occurs.
          * @throws UnsupportedOperationException if the origin cannot provide 
a Path.
          * @see AbstractOrigin#getReader(Charset)
          */
@@ -782,8 +779,7 @@ public final class MultipartInput {
     /**
      * Reads {@code body-data} from the current {@code encapsulation} and 
writes its contents into the output {@code Stream}.
      * <p>
-     * Arbitrary large amounts of data can be processed by this method using a 
constant size buffer. (see
-     * {@link MultipartInput#builder()}).
+     * Arbitrary large amounts of data can be processed by this method using a 
constant size buffer. (see {@link MultipartInput#builder()}).
      * </p>
      *
      * @param output The {@code Stream} to write data into. May be null, in 
which case this method is equivalent to {@link #discardBodyData()}.
diff --git 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/disk/DiskFileItem.java
 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/disk/DiskFileItem.java
index a380e8d..2787f68 100644
--- 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/disk/DiskFileItem.java
+++ 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/disk/DiskFileItem.java
@@ -47,7 +47,6 @@ import org.apache.commons.io.output.DeferredFileOutputStream;
 
 /**
  * The default implementation of the {@link FileItem FileItem} interface.
- *
  * <p>
  * After retrieving an instance of this class from a {@link 
DiskFileItemFactory} instance (see
  * {@code org.apache.commons.fileupload2.core.servlet.ServletFileUpload
@@ -64,7 +63,7 @@ import org.apache.commons.io.output.DeferredFileOutputStream;
  * application ends. See the section on "Resource cleanup" in the users guide 
of Commons FileUpload.
  * </p>
  */
-public final class DiskFileItem implements FileItem {
+public final class DiskFileItem implements FileItem<DiskFileItem> {
 
     /**
      * Builds a new {@link DiskFileItem} instance.
@@ -284,12 +283,13 @@ public final class DiskFileItem implements FileItem {
      * @throws IOException if an error occurs.
      */
     @Override
-    public void delete() throws IOException {
+    public DiskFileItem delete() throws IOException {
         cachedContent = null;
-        final Path outputFile = getStoreLocation();
+        final Path outputFile = getPath();
         if (outputFile != null && !isInMemory() && Files.exists(outputFile)) {
             Files.delete(outputFile);
         }
+        return this;
     }
 
     /**
@@ -408,25 +408,6 @@ public final class DiskFileItem implements FileItem {
         return dfos;
     }
 
-    /**
-     * Gets the size of the file.
-     *
-     * @return The size of the file, in bytes.
-     */
-    @Override
-    public long getSize() {
-        if (size >= 0) {
-            return size;
-        }
-        if (cachedContent != null) {
-            return cachedContent.length;
-        }
-        if (dfos.isInMemory()) {
-            return dfos.getData().length;
-        }
-        return dfos.getFile().length();
-    }
-
     /**
      * Gets the {@link Path} for the {@code FileItem}'s data's temporary 
location on the disk. Note that for {@code FileItem}s that have their data 
stored in
      * memory, this method will return {@code null}. When handling large 
files, you can use {@link Files#move(Path,Path,CopyOption...)} to move the file 
to new
@@ -434,7 +415,7 @@ public final class DiskFileItem implements FileItem {
      *
      * @return The data file, or {@code null} if the data is stored in memory.
      */
-    public Path getStoreLocation() {
+    public Path getPath() {
         if (dfos == null) {
             return null;
         }
@@ -444,6 +425,22 @@ public final class DiskFileItem implements FileItem {
         return dfos.getFile().toPath();
     }
 
+    /**
+     * Gets the size of the file.
+     *
+     * @return The size of the file, in bytes.
+     */
+    @Override
+    public long getSize() {
+        if (size >= 0) {
+            return size;
+        }
+        if (cachedContent != null) {
+            return cachedContent.length;
+        }
+        return dfos.getByteCount();
+    }
+
     /**
      * Gets the contents of the file as a String, using the default character 
encoding. This method uses {@link #get()} to retrieve the contents of the file.
      * <p>
@@ -509,9 +506,11 @@ public final class DiskFileItem implements FileItem {
      * Sets the default charset for use when no explicit charset parameter is 
provided by the sender.
      *
      * @param charset the default charset
+     * @return this
      */
-    public void setCharsetDefault(final Charset charset) {
+    public DiskFileItem setCharsetDefault(final Charset charset) {
         charsetDefault = charset;
+        return this;
     }
 
     /**
@@ -521,8 +520,9 @@ public final class DiskFileItem implements FileItem {
      * @see #getFieldName()
      */
     @Override
-    public void setFieldName(final String fieldName) {
+    public DiskFileItem setFieldName(final String fieldName) {
         this.fieldName = fieldName;
+        return this;
     }
 
     /**
@@ -532,8 +532,9 @@ public final class DiskFileItem implements FileItem {
      * @see #isFormField()
      */
     @Override
-    public void setFormField(final boolean state) {
+    public DiskFileItem setFormField(final boolean state) {
         isFormField = state;
+        return this;
     }
 
     /**
@@ -542,8 +543,9 @@ public final class DiskFileItem implements FileItem {
      * @param headers The file items headers.
      */
     @Override
-    public void setHeaders(final FileItemHeaders headers) {
+    public DiskFileItem setHeaders(final FileItemHeaders headers) {
         this.fileItemHeaders = headers;
+        return this;
     }
 
     /**
@@ -553,7 +555,7 @@ public final class DiskFileItem implements FileItem {
      */
     @Override
     public String toString() {
-        return String.format("name=%s, StoreLocation=%s, size=%s bytes, 
isFormField=%s, FieldName=%s", getName(), getStoreLocation(), getSize(), 
isFormField(),
+        return String.format("name=%s, StoreLocation=%s, size=%s bytes, 
isFormField=%s, FieldName=%s", getName(), getPath(), getSize(), isFormField(),
                 getFieldName());
     }
 
@@ -576,7 +578,7 @@ public final class DiskFileItem implements FileItem {
      * @throws IOException if an error occurs.
      */
     @Override
-    public void write(final Path file) throws IOException {
+    public DiskFileItem write(final Path file) throws IOException {
         if (isInMemory()) {
             try (OutputStream fout = Files.newOutputStream(file)) {
                 fout.write(get());
@@ -584,7 +586,7 @@ public final class DiskFileItem implements FileItem {
                 throw new IOException("Unexpected output data", e);
             }
         } else {
-            final Path outputFile = getStoreLocation();
+            final Path outputFile = getPath();
             if (outputFile == null) {
                 /*
                  * For whatever reason we cannot write the file to disk.
@@ -598,5 +600,6 @@ public final class DiskFileItem implements FileItem {
             //
             Files.move(outputFile, file, StandardCopyOption.REPLACE_EXISTING);
         }
+        return this;
     }
 }
diff --git 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/disk/DiskFileItemFactory.java
 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/disk/DiskFileItemFactory.java
index 287f8de..c4b28b3 100644
--- 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/disk/DiskFileItemFactory.java
+++ 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/disk/DiskFileItemFactory.java
@@ -57,18 +57,16 @@ import org.apache.commons.io.file.PathUtils;
  * @see Builder
  * @see Builder#get()
  */
-public final class DiskFileItemFactory implements FileItemFactory {
+public final class DiskFileItemFactory implements 
FileItemFactory<DiskFileItem> {
 
     /**
      * Builds a new {@link DiskFileItemFactory} instance.
      * <p>
      * For example:
      * </p>
+     *
      * <pre>{@code
-     * DiskFileItemFactory factory = DiskFileItemFactory.builder()
-     *   .setPath(path)
-     *   .setBufferSize(DEFAULT_THRESHOLD)
-     *   .get();
+     * DiskFileItemFactory factory = 
DiskFileItemFactory.builder().setPath(path).setBufferSize(DEFAULT_THRESHOLD).get();
      * }
      * </pre>
      */
@@ -173,6 +171,7 @@ public final class DiskFileItemFactory implements 
FileItemFactory {
         this.fileCleaningTracker = fileCleaningTracker;
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public DiskFileItem.Builder fileItemBuilder() {
         // @formatter:off
diff --git 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/disk/package-info.java
 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/disk/package-info.java
index 2224b16..d862a1a 100644
--- 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/disk/package-info.java
+++ 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/disk/package-info.java
@@ -17,12 +17,12 @@
 
 /**
  * <p>
- * A disk-based implementation of the {@link 
org.apache.commons.fileupload2.core.FileItem} interface. This implementation 
retains smaller items in memory,
- * while writing larger ones to disk. The threshold between these two is 
configurable, as is the location of files that are written to disk.
+ * A disk-based implementation of the {@link 
org.apache.commons.fileupload2.core.FileItem} interface. This implementation 
retains smaller items in memory, while
+ * writing larger ones to disk. The threshold between these two is 
configurable, as is the location of files that are written to disk.
  * </p>
  * <p>
- * In typical usage, an instance of {@link 
org.apache.commons.fileupload2.core.disk.DiskFileItemFactory} would be created, 
configured, and then
- * passed to a {@link org.apache.commons.fileupload2.core.AbstractFileUpload} 
implementation such as
+ * In typical usage, an instance of {@link 
org.apache.commons.fileupload2.core.disk.DiskFileItemFactory} would be created, 
configured, and then passed to a
+ * {@link org.apache.commons.fileupload2.core.AbstractFileUpload} 
implementation such as
  * {@code org.apache.commons.fileupload2.core.servlet.ServletFileUpload 
ServletFileUpload} or
  * {@code org.apache.commons.fileupload2.core.portlet.PortletFileUpload 
PortletFileUpload}.
  * </p>
diff --git 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractFileUploadTest.java
 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractFileUploadTest.java
index c0103ad..35112c2 100644
--- 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractFileUploadTest.java
+++ 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractFileUploadTest.java
@@ -31,15 +31,19 @@ import org.junit.jupiter.api.Test;
  * Common tests for implementations of {@link AbstractFileUpload}. This is a 
parameterized test. Tests must be valid and common to all implementations of
  * FileUpload added as parameter in this class.
  *
- * @param <T> The type for {@link AbstractFileUpload}.
+ * @param <AFU> The {@link AbstractFileUpload} type.
+ * @param <R>   The FileUpload request type.
+ * @param <I>   The FileItem type.
+ * @param <F>   The FileItemFactory type.
  */
-public abstract class AbstractFileUploadTest<T extends AbstractFileUpload<?>> 
extends AbstractFileUploadWrapper<T> {
+public abstract class AbstractFileUploadTest<AFU extends AbstractFileUpload<R, 
I, F>, R, I extends FileItem<I>, F extends FileItemFactory<I>>
+        extends AbstractFileUploadWrapper<AFU, R, I, F> {
 
-    protected AbstractFileUploadTest(final T fileUpload) {
+    protected AbstractFileUploadTest(final AFU fileUpload) {
         super(fileUpload);
     }
 
-    private void assertHeaders(final String[] headerNames, final String[] 
headerValues, final FileItem fileItems, final int index) {
+    private void assertHeaders(final String[] headerNames, final String[] 
headerValues, final I fileItems, final int index) {
         for (int i = 0; i < headerNames.length; i++) {
             final String value = 
fileItems.getHeaders().getHeader(headerNames[i]);
             if (i == index) {
@@ -58,7 +62,7 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
     @Test
     public void testContentTypeAttachment() throws IOException {
         // @formatter:off
-        final List<FileItem> fileItems = parseUpload(upload,
+        final List<I> fileItems = parseUpload(upload,
                 "-----1234\r\n" +
                 "content-disposition: form-data; name=\"field1\"\r\n" +
                 "\r\n" +
@@ -77,12 +81,12 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
         // @formatter:on
         assertEquals(2, fileItems.size());
 
-        final FileItem field = fileItems.get(0);
+        final I field = fileItems.get(0);
         assertEquals("field1", field.getFieldName());
         assertTrue(field.isFormField());
         assertEquals("Joe Blow", field.getString());
 
-        final FileItem fileItem = fileItems.get(1);
+        final I fileItem = fileItems.get(1);
         assertEquals("pics", fileItem.getFieldName());
         assertFalse(fileItem.isFormField());
         assertEquals("... contents of file1.txt ...", fileItem.getString());
@@ -98,7 +102,7 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
     @Test
     public void testEmptyFile() throws FileUploadException {
         // @formatter:off
-        final List<FileItem> fileItems = parseUpload (upload,
+        final List<I> fileItems = parseUpload (upload,
                                                 "-----1234\r\n" +
                                                 "Content-Disposition: 
form-data; name=\"file\"; filename=\"\"\r\n" +
                                                 "\r\n" +
@@ -107,7 +111,7 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
         // @formatter:on
         assertEquals(1, fileItems.size());
 
-        final FileItem file = fileItems.get(0);
+        final I file = fileItems.get(0);
         assertFalse(file.isFormField());
         assertEquals("", file.getString());
         assertEquals("", file.getName());
@@ -116,7 +120,7 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
     @Test
     public void testFilenameCaseSensitivity() throws IOException {
         // @formatter:off
-        final List<FileItem> fileItems = parseUpload(upload,
+        final List<I> fileItems = parseUpload(upload,
                                                "-----1234\r\n" +
                                                "Content-Disposition: 
form-data; "
                                              + "name=\"FiLe\"; 
filename=\"FOO.tab\"\r\n" +
@@ -128,7 +132,7 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
         // @formatter:on
         assertEquals(1, fileItems.size());
 
-        final FileItem file = fileItems.get(0);
+        final I file = fileItems.get(0);
         assertEquals("FiLe", file.getFieldName());
         assertEquals("FOO.tab", file.getName());
     }
@@ -136,7 +140,7 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
     @Test
     public void testFileUpload() throws IOException {
         // @formatter:off
-        final List<FileItem> fileItems = parseUpload(upload,
+        final List<I> fileItems = parseUpload(upload,
                                                "-----1234\r\n" +
                                                "Content-Disposition: "
                                                + "form-data; name=\"file\"; 
filename=\"foo.tab\"\r\n" +
@@ -160,24 +164,24 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
         // @formatter:on
         assertEquals(4, fileItems.size());
 
-        final FileItem file = fileItems.get(0);
+        final I file = fileItems.get(0);
         assertEquals("file", file.getFieldName());
         assertFalse(file.isFormField());
         assertEquals("This is the content of the file\n", file.getString());
         assertEquals("text/whatever", file.getContentType());
         assertEquals("foo.tab", file.getName());
 
-        final FileItem field = fileItems.get(1);
+        final I field = fileItems.get(1);
         assertEquals("field", field.getFieldName());
         assertTrue(field.isFormField());
         assertEquals("fieldValue", field.getString());
 
-        final FileItem multi0 = fileItems.get(2);
+        final I multi0 = fileItems.get(2);
         assertEquals("multi", multi0.getFieldName());
         assertTrue(multi0.isFormField());
         assertEquals("value1", multi0.getString());
 
-        final FileItem multi1 = fileItems.get(3);
+        final I multi1 = fileItems.get(3);
         assertEquals("multi", multi1.getFieldName());
         assertTrue(multi1.isFormField());
         assertEquals("value2", multi1.getString());
@@ -193,7 +197,7 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
         final String[] headerNames = { "SomeHeader", "OtherHeader", 
"YetAnotherHeader", "WhatAHeader" };
         final String[] headerValues = { "present", "Is there", "Here", "Is 
That" };
         // @formatter:off
-        final List<FileItem> fileItems = parseUpload(upload,
+        final List<I> fileItems = parseUpload(upload,
                                                "-----1234\r\n" +
                                                "Content-Disposition: 
form-data; name=\"file\"; "
                                              + "filename=\"foo.tab\"\r\n" +
@@ -223,16 +227,16 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
         // @formatter:on
         assertEquals(4, fileItems.size());
 
-        final FileItem file = fileItems.get(0);
+        final I file = fileItems.get(0);
         assertHeaders(headerNames, headerValues, file, 0);
 
-        final FileItem field = fileItems.get(1);
+        final I field = fileItems.get(1);
         assertHeaders(headerNames, headerValues, field, 1);
 
-        final FileItem multi0 = fileItems.get(2);
+        final I multi0 = fileItems.get(2);
         assertHeaders(headerNames, headerValues, multi0, 2);
 
-        final FileItem multi1 = fileItems.get(3);
+        final I multi1 = fileItems.get(3);
         assertHeaders(headerNames, headerValues, multi1, 3);
     }
 
@@ -268,17 +272,17 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
             "--BbC04y--\r\n" +
             "--AaB03x--";
         // @formatter:on
-        final List<FileItem> fileItems = parseUpload(upload, 
request.getBytes(StandardCharsets.US_ASCII), contentType);
+        final List<I> fileItems = parseUpload(upload, 
request.getBytes(StandardCharsets.US_ASCII), contentType);
         assertEquals(3, fileItems.size());
-        final FileItem item0 = fileItems.get(0);
+        final I item0 = fileItems.get(0);
         assertEquals("field1", item0.getFieldName());
         assertNull(item0.getName());
         assertEquals("Joe Blow", new String(item0.get()));
-        final FileItem item1 = fileItems.get(1);
+        final I item1 = fileItems.get(1);
         assertEquals("pics", item1.getFieldName());
         assertEquals("file1.txt", item1.getName());
         assertEquals("... contents of file1.txt ...", new String(item1.get()));
-        final FileItem item2 = fileItems.get(2);
+        final I item2 = fileItems.get(2);
         assertEquals("pics", item2.getFieldName());
         assertEquals("file2.gif", item2.getName());
         assertEquals("...contents of file2.gif...", new String(item2.get()));
@@ -292,7 +296,7 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
     @Test
     public void testFoldedHeaders() throws IOException {
         // @formatter:off
-        final List<FileItem> fileItems = parseUpload(upload, "-----1234\r\n" +
+        final List<I> fileItems = parseUpload(upload, "-----1234\r\n" +
                 "Content-Disposition: form-data; name=\"file\"; 
filename=\"foo.tab\"\r\n" +
                 "Content-Type: text/whatever\r\n" +
                 "\r\n" +
@@ -316,24 +320,24 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
         // @formatter:on
         assertEquals(4, fileItems.size());
 
-        final FileItem file = fileItems.get(0);
+        final I file = fileItems.get(0);
         assertEquals("file", file.getFieldName());
         assertFalse(file.isFormField());
         assertEquals("This is the content of the file\n", file.getString());
         assertEquals("text/whatever", file.getContentType());
         assertEquals("foo.tab", file.getName());
 
-        final FileItem field = fileItems.get(1);
+        final I field = fileItems.get(1);
         assertEquals("field", field.getFieldName());
         assertTrue(field.isFormField());
         assertEquals("fieldValue", field.getString());
 
-        final FileItem multi0 = fileItems.get(2);
+        final I multi0 = fileItems.get(2);
         assertEquals("multi", multi0.getFieldName());
         assertTrue(multi0.isFormField());
         assertEquals("value1", multi0.getString());
 
-        final FileItem multi1 = fileItems.get(3);
+        final I multi1 = fileItems.get(3);
         assertEquals("multi", multi1.getFieldName());
         assertTrue(multi1.isFormField());
         assertEquals("value2", multi1.getString());
@@ -347,7 +351,7 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
      */
     @Test
     public void testIE5MacBug() throws FileUploadException {
-        final List<FileItem> fileItems = parseUpload(upload,
+        final List<I> fileItems = parseUpload(upload,
         // @formatter:off
                 "-----1234\r\n" +
                 "Content-Disposition: form-data; name=\"field1\"\r\n" +
@@ -370,22 +374,22 @@ public abstract class AbstractFileUploadTest<T extends 
AbstractFileUpload<?>> ex
 
         assertEquals(4, fileItems.size());
 
-        final FileItem field1 = fileItems.get(0);
+        final I field1 = fileItems.get(0);
         assertEquals("field1", field1.getFieldName());
         assertTrue(field1.isFormField());
         assertEquals("fieldValue", field1.getString());
 
-        final FileItem submitX = fileItems.get(1);
+        final I submitX = fileItems.get(1);
         assertEquals("submitName.x", submitX.getFieldName());
         assertTrue(submitX.isFormField());
         assertEquals("42", submitX.getString());
 
-        final FileItem submitY = fileItems.get(2);
+        final I submitY = fileItems.get(2);
         assertEquals("submitName.y", submitY.getFieldName());
         assertTrue(submitY.isFormField());
         assertEquals("21", submitY.getString());
 
-        final FileItem field2 = fileItems.get(3);
+        final I field2 = fileItems.get(3);
         assertEquals("field2", field2.getFieldName());
         assertTrue(field2.isFormField());
         assertEquals("fieldValue2", field2.getString());
diff --git 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractFileUploadWrapper.java
 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractFileUploadWrapper.java
index e48456a..a39bbf0 100644
--- 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractFileUploadWrapper.java
+++ 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractFileUploadWrapper.java
@@ -20,26 +20,29 @@ import java.nio.charset.StandardCharsets;
 import java.util.List;
 
 /**
- * Common tests for implementations of {@link AbstractFileUpload}. This is a 
parameterized test. Tests must be valid and common to all implementations of 
FileUpload
- * added as parameter in this class.
+ * Common tests for implementations of {@link AbstractFileUpload}. This is a 
parameterized test. Tests must be valid and common to all implementations of
+ * FileUpload added as parameter in this class.
  *
- * @param <T> The type for {@link AbstractFileUpload}.
+ * @param <AFU> The type for {@link AbstractFileUpload}.
+ * @param <R>   The FileUpload request type.
+ * @param <I>   The FileItem type.
+ * @param <F>   The FileItemFactory type.
  */
-public abstract class AbstractFileUploadWrapper<T extends 
AbstractFileUpload<?>> {
+public abstract class AbstractFileUploadWrapper<AFU extends 
AbstractFileUpload<R, I, F>, R, I extends FileItem<I>, F extends 
FileItemFactory<I>> {
 
-    protected final T upload;
+    protected final AFU upload;
 
-    protected AbstractFileUploadWrapper(final T fileUpload) {
+    protected AbstractFileUploadWrapper(final AFU fileUpload) {
         this.upload = fileUpload;
     }
 
-    public List<FileItem> parseUpload(final T upload, final byte[] bytes) 
throws FileUploadException {
+    public List<I> parseUpload(final AFU upload, final byte[] bytes) throws 
FileUploadException {
         return parseUpload(upload, bytes, Constants.CONTENT_TYPE);
     }
 
-    public abstract List<FileItem> parseUpload(final T upload, final byte[] 
bytes, final String contentType) throws FileUploadException;
+    public abstract List<I> parseUpload(final AFU upload, final byte[] bytes, 
final String contentType) throws FileUploadException;
 
-    public List<FileItem> parseUpload(final T upload, final String content) 
throws FileUploadException {
+    public List<I> parseUpload(final AFU upload, final String content) throws 
FileUploadException {
         final byte[] bytes = content.getBytes(StandardCharsets.US_ASCII);
         return parseUpload(upload, bytes, Constants.CONTENT_TYPE);
     }
diff --git 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractProgressListenerTest.java
 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractProgressListenerTest.java
index 91ae359..801fa6c 100644
--- 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractProgressListenerTest.java
+++ 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractProgressListenerTest.java
@@ -29,10 +29,13 @@ import org.junit.jupiter.api.Test;
 /**
  * Tests the {@link ProgressListener}.
  *
- * @param <F> The subclass of FileUpload.
- * @param <R> The type of FileUpload request.
+ * @param <AFU> The subclass of FileUpload.
+ * @param <R>   The FileUpload request type.
+ * @param <I>   The FileItem type.
+ * @param <F>   The FileItemFactory type.
  */
-public abstract class AbstractProgressListenerTest<F extends 
AbstractFileUpload<R>, R> extends AbstractTest<F, R> {
+public abstract class AbstractProgressListenerTest<AFU extends 
AbstractFileUpload<R, I, F>, R, I extends FileItem<I>, F extends 
FileItemFactory<I>>
+        extends AbstractTest<AFU, R, I, F> {
 
     protected static class ProgressListenerImpl implements ProgressListener {
 
@@ -69,7 +72,7 @@ public abstract class AbstractProgressListenerTest<F extends 
AbstractFileUpload<
     }
 
     protected void runTest(final int itemCount, final long contentLength, 
final R request) throws FileUploadException, IOException {
-        final F upload = newFileUpload();
+        final AFU upload = newFileUpload();
         final ProgressListenerImpl listener = new 
ProgressListenerImpl(contentLength, itemCount);
         upload.setProgressListener(listener);
         final FileItemInputIterator iter = upload.getItemIterator(request);
diff --git 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractSizesTest.java
 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractSizesTest.java
index 9a75a56..7ddfef7 100644
--- 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractSizesTest.java
+++ 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractSizesTest.java
@@ -33,10 +33,13 @@ import org.junit.jupiter.api.Test;
 /**
  * Unit test for items with varying sizes.
  *
- * @param <F> The subclass of FileUpload.
- * @param <R> The type of FileUpload request.
+ * @param <AFU> The FileUpload type.
+ * @param <R>   The FileUpload request type.
+ * @param <I>   The FileItem type.
+ * @param <F>   The FileItemFactory type.
  */
-public abstract class AbstractSizesTest<F extends AbstractFileUpload<R>, R> 
extends AbstractTest<F, R> {
+public abstract class AbstractSizesTest<AFU extends AbstractFileUpload<R, I, 
F>, R, I extends FileItem<I>, F extends FileItemFactory<I>>
+        extends AbstractTest<AFU, R, I, F> {
 
     /**
      * Checks, whether limiting the file size works.
@@ -56,12 +59,12 @@ public abstract class AbstractSizesTest<F extends 
AbstractFileUpload<R>, R> exte
             "-----1234--\r\n";
         // @formatter:on
 
-        F upload = newFileUpload();
+        AFU upload = newFileUpload();
         upload.setFileSizeMax(-1);
         R req = newMockHttpServletRequest(request, null, null);
-        List<FileItem> fileItems = upload.parseRequest(req);
+        List<I> fileItems = upload.parseRequest(req);
         assertEquals(1, fileItems.size());
-        FileItem item = fileItems.get(0);
+        I item = fileItems.get(0);
         assertEquals("This is the content of the file\n", new 
String(item.get()));
 
         upload = newFileUpload();
@@ -102,12 +105,12 @@ public abstract class AbstractSizesTest<F extends 
AbstractFileUpload<R>, R> exte
             "-----1234--\r\n";
         // @formatter:on
 
-        F upload = newFileUpload();
+        AFU upload = newFileUpload();
         upload.setFileSizeMax(-1);
         R req = newMockHttpServletRequest(request, null, null);
-        List<FileItem> fileItems = upload.parseRequest(req);
+        List<I> fileItems = upload.parseRequest(req);
         assertEquals(1, fileItems.size());
-        FileItem item = fileItems.get(0);
+        I item = fileItems.get(0);
         assertEquals("This is the content of the file\n", new 
String(item.get()));
 
         upload = newFileUpload();
@@ -166,7 +169,7 @@ public abstract class AbstractSizesTest<F extends 
AbstractFileUpload<R>, R> exte
             "-----1234--\r\n";
         // @formatter:on
 
-        final F upload = newFileUpload();
+        final AFU upload = newFileUpload();
         upload.setFileSizeMax(-1);
         upload.setSizeMax(200);
 
@@ -199,7 +202,7 @@ public abstract class AbstractSizesTest<F extends 
AbstractFileUpload<R>, R> exte
             "-----1234--\r\n";
         // @formatter:on
 
-        final F upload = newFileUpload();
+        final AFU upload = newFileUpload();
         upload.setFileSizeMax(-1);
         upload.setSizeMax(300);
 
diff --git 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractStreamingTest.java
 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractStreamingTest.java
index 57b7ae5..b02edeb 100644
--- 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractStreamingTest.java
+++ 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractStreamingTest.java
@@ -31,17 +31,19 @@ import java.nio.file.InvalidPathException;
 import java.util.Iterator;
 import java.util.List;
 
-import org.apache.commons.fileupload2.core.disk.DiskFileItemFactory;
 import org.junit.jupiter.api.Test;
 
 /**
  * Unit test for items with varying sizes.
  *
- * @param <F> The subclass of FileUpload.
- * @param <R> The type of FileUpload request.
- * @param <C> The request context type.
+ * @param <AFU> The subclass of FileUpload.
+ * @param <R>   The type of FileUpload request.
+ * @param <C>   The request context type.
+ * @param <I>   The FileItem type.
+ * @param <F>   The FileItemFactory type.
  */
-public abstract class AbstractStreamingTest<F extends AbstractFileUpload<R>, 
R, C extends AbstractRequestContext<?>> extends AbstractTest<F, R> {
+public abstract class AbstractStreamingTest<AFU extends AbstractFileUpload<R, 
I, F>, R, C extends AbstractRequestContext<?>, I extends FileItem<I>, F extends 
FileItemFactory<I>>
+        extends AbstractTest<AFU, R, I, F> {
 
     protected String getFooter() {
         return "-----1234--\r\n";
@@ -55,6 +57,8 @@ public abstract class AbstractStreamingTest<F extends 
AbstractFileUpload<R>, R,
         // @formatter:on
     }
 
+    protected abstract F newDiskFileItemFactory();
+
     protected byte[] newRequest() throws IOException {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         try (final OutputStreamWriter osw = new OutputStreamWriter(baos, 
StandardCharsets.US_ASCII)) {
@@ -89,15 +93,15 @@ public abstract class AbstractStreamingTest<F extends 
AbstractFileUpload<R>, R,
         return baos.toByteArray();
     }
 
-    protected List<FileItem> parseUpload(final byte[] bytes) throws 
FileUploadException {
+    protected List<I> parseUpload(final byte[] bytes) throws 
FileUploadException {
         return parseUpload(new ByteArrayInputStream(bytes), bytes.length);
     }
 
-    protected List<FileItem> parseUpload(final InputStream inputStream, final 
int length) throws FileUploadException {
+    protected List<I> parseUpload(final InputStream inputStream, final int 
length) throws FileUploadException {
         final String contentType = "multipart/form-data; boundary=---1234";
 
-        final AbstractFileUpload<?> upload = newFileUpload();
-        upload.setFileItemFactory(DiskFileItemFactory.builder().get());
+        final AFU upload = newFileUpload();
+        upload.setFileItemFactory(newDiskFileItemFactory());
         final R request = newMockHttpServletRequest(inputStream, length, 
contentType, -1);
 
         return upload.parseRequest(newServletRequestContext(request));
@@ -106,8 +110,8 @@ public abstract class AbstractStreamingTest<F extends 
AbstractFileUpload<R>, R,
     protected FileItemInputIterator parseUpload(final int length, final 
InputStream inputStream) throws FileUploadException, IOException {
         final String contentType = "multipart/form-data; boundary=---1234";
 
-        final AbstractFileUpload<?> upload = newFileUpload();
-        upload.setFileItemFactory(DiskFileItemFactory.builder().get());
+        final AFU upload = newFileUpload();
+        upload.setFileItemFactory(newDiskFileItemFactory());
         final R request = newMockHttpServletRequest(inputStream, length, 
contentType, -1);
 
         return upload.getItemIterator(newServletRequestContext(request));
@@ -121,15 +125,15 @@ public abstract class AbstractStreamingTest<F extends 
AbstractFileUpload<R>, R,
     @Test
     public void testFileUpload() throws IOException {
         final byte[] request = newRequest();
-        final List<FileItem> fileItems = parseUpload(request);
-        final Iterator<FileItem> fileIter = fileItems.iterator();
+        final List<I> fileItems = parseUpload(request);
+        final Iterator<I> fileIter = fileItems.iterator();
         int add = 16;
         int num = 0;
         for (int i = 0; i < 16384; i += add) {
             if (++add == 32) {
                 add = 16;
             }
-            final FileItem item = fileIter.next();
+            final I item = fileIter.next();
             assertEquals("field" + (num++), item.getFieldName());
             final byte[] bytes = item.get();
             assertEquals(i, bytes.length);
@@ -149,7 +153,7 @@ public abstract class AbstractStreamingTest<F extends 
AbstractFileUpload<R>, R,
     public void testFILEUPLOAD135() throws IOException {
         final byte[] request = newShortRequest();
         final ByteArrayInputStream bais = new ByteArrayInputStream(request);
-        final List<FileItem> fileItems = parseUpload(new InputStream() {
+        final List<I> fileItems = parseUpload(new InputStream() {
             @Override
             public int read() throws IOException {
                 return bais.read();
@@ -161,9 +165,9 @@ public abstract class AbstractStreamingTest<F extends 
AbstractFileUpload<R>, R,
             }
 
         }, request.length);
-        final Iterator<FileItem> fileIter = fileItems.iterator();
+        final Iterator<I> fileIter = fileItems.iterator();
         assertTrue(fileIter.hasNext());
-        final FileItem item = fileIter.next();
+        final I item = fileIter.next();
         assertEquals("field", item.getFieldName());
         final byte[] bytes = item.get();
         assertEquals(3, bytes.length);
diff --git 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractTest.java
 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractTest.java
index 13351e0..3d9a106 100644
--- 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractTest.java
+++ 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractTest.java
@@ -23,12 +23,14 @@ import java.nio.charset.StandardCharsets;
 /**
  * Abstract test.
  *
- * @param <F> The subclass of FileUpload.
- * @param <R> The type of FileUpload request.
+ * @param <AFU> The AbstractFileUpload type.
+ * @param <R>   The FileUpload request type.
+ * @param <I>   The FileItem type.
+ * @param <F>   The FileItemFactory type.
  */
-public abstract class AbstractTest<F extends AbstractFileUpload<R>, R> {
+public abstract class AbstractTest<AFU extends AbstractFileUpload<R, I, F>, R, 
I extends FileItem<I>, F extends FileItemFactory<I>> {
 
-    protected abstract F newFileUpload();
+    protected abstract AFU newFileUpload();
 
     protected R newMockHttpServletRequest(final byte[] request, final Long 
overrideContenLength, final String contentType, final Integer 
overrideReadLimit) {
         return newMockHttpServletRequest(new ByteArrayInputStream(request), 
overrideContenLength != null ? overrideContenLength : request.length, 
contentType,
diff --git 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/disk/DiskFileItemSerializeTest.java
 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/disk/DiskFileItemSerializeTest.java
index 1a90f41..9e267c6 100644
--- 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/disk/DiskFileItemSerializeTest.java
+++ 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/disk/DiskFileItemSerializeTest.java
@@ -32,7 +32,6 @@ import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
 import java.nio.file.attribute.BasicFileAttributes;
 
-import org.apache.commons.fileupload2.core.FileItem;
 import org.apache.commons.fileupload2.core.FileItemFactory;
 import org.apache.commons.io.file.PathUtils;
 import org.apache.commons.io.file.SimplePathVisitor;
@@ -92,22 +91,22 @@ public class DiskFileItemSerializeTest {
     /**
      * Create a FileItem with the specfied content bytes.
      */
-    private FileItem createFileItem(final byte[] contentBytes) throws 
IOException {
+    private DiskFileItem createFileItem(final byte[] contentBytes) throws 
IOException {
         return createFileItem(contentBytes, REPOSITORY);
     }
 
     /**
      * Create a FileItem with the specfied content bytes and repository.
      */
-    private FileItem createFileItem(final byte[] contentBytes, final Path 
repository) throws IOException {
+    private DiskFileItem createFileItem(final byte[] contentBytes, final Path 
repository) throws IOException {
         // @formatter:off
-        final FileItemFactory factory = DiskFileItemFactory.builder()
+        final FileItemFactory<DiskFileItem> factory = 
DiskFileItemFactory.builder()
                 .setBufferSize(THRESHOLD)
                 .setPath(repository)
                 .get();
         // @formatter:on
         // @formatter:off
-        final FileItem item = factory.fileItemBuilder()
+        final DiskFileItem item = factory.fileItemBuilder()
                 .setFieldName("textField")
                 .setContentType(TEXT_CONTENT_TYPE)
                 .setFormField(true)
@@ -173,7 +172,7 @@ public class DiskFileItemSerializeTest {
     public void testAboveThreshold() throws IOException {
         // Create the FileItem
         final byte[] testFieldValueBytes = createContentBytes(THRESHOLD + 1);
-        final FileItem item = createFileItem(testFieldValueBytes);
+        final DiskFileItem item = createFileItem(testFieldValueBytes);
 
         // Check state is as expected
         assertFalse(item.isInMemory(), "Initial: in memory");
@@ -212,7 +211,7 @@ public class DiskFileItemSerializeTest {
      * Helper method to test creation of a field when a repository is used.
      */
     private void testInMemoryObject(final byte[] testFieldValueBytes, final 
Path repository) throws IOException {
-        final FileItem item = createFileItem(testFieldValueBytes, repository);
+        final DiskFileItem item = createFileItem(testFieldValueBytes, 
repository);
 
         // Check state is as expected
         assertTrue(item.isInMemory(), "Initial: in memory");
@@ -232,7 +231,7 @@ public class DiskFileItemSerializeTest {
         // Create the FileItem
         final byte[] testFieldValueBytes = createContentBytes(THRESHOLD);
         final Path repository = PathUtils.getTempDirectory().resolve("file");
-        final FileItem item = createFileItem(testFieldValueBytes, repository);
+        final DiskFileItem item = createFileItem(testFieldValueBytes, 
repository);
         assertThrows(IOException.class, () -> deserialize(serialize(item)));
     }
 
@@ -263,7 +262,7 @@ public class DiskFileItemSerializeTest {
     /**
      * Helper method to test writing item contents to a file.
      */
-    private void testWritingToFile(final FileItem item, final byte[] 
testFieldValueBytes) throws IOException {
+    private void testWritingToFile(final DiskFileItem item, final byte[] 
testFieldValueBytes) throws IOException {
         final Path temp = Files.createTempFile("fileupload", null);
         // Note that the file exists and is initially empty;
         // write() must be able to handle that.
diff --git 
a/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUpload.java
 
b/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUpload.java
index bbb00ac..8621906 100644
--- 
a/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUpload.java
+++ 
b/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUpload.java
@@ -32,14 +32,17 @@ import jakarta.servlet.http.HttpServletRequest;
  * High level API for processing file uploads.
  * <p>
  * This class handles multiple files per single HTML widget, sent using {@code 
multipart/mixed} encoding type, as specified by
- * <a href="http://www.ietf.org/rfc/rfc1867.txt";>RFC 1867</a>. Use {@link 
#parseRequest(HttpServletRequest)} to acquire a list of
- * {@link FileItem}s associated with a given HTML widget.
+ * <a href="http://www.ietf.org/rfc/rfc1867.txt";>RFC 1867</a>. Use {@link 
#parseRequest(HttpServletRequest)} to acquire a list of {@link FileItem}s 
associated
+ * with a given HTML widget.
  * </p>
  * <p>
  * 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.
  * </p>
+ *
+ * @param <I> The FileItem type.
+ * @param <F> the FileItemFactory type.
  */
-public class JakartaServletFileUpload extends 
AbstractFileUpload<HttpServletRequest> {
+public class JakartaServletFileUpload<I extends FileItem<I>, F extends 
FileItemFactory<I>> extends AbstractFileUpload<HttpServletRequest, I, F> {
 
     /**
      * Constant for HTTP POST method.
@@ -72,7 +75,7 @@ public class JakartaServletFileUpload extends 
AbstractFileUpload<HttpServletRequ
      * @see AbstractFileUpload#AbstractFileUpload()
      * @param fileItemFactory The factory to use for creating file items.
      */
-    public JakartaServletFileUpload(final FileItemFactory fileItemFactory) {
+    public JakartaServletFileUpload(final F fileItemFactory) {
         setFileItemFactory(fileItemFactory);
     }
 
@@ -98,7 +101,7 @@ public class JakartaServletFileUpload extends 
AbstractFileUpload<HttpServletRequ
      * @throws FileUploadException if there are problems reading/parsing the 
request or storing files.
      */
     @Override
-    public Map<String, List<FileItem>> parseParameterMap(final 
HttpServletRequest request) throws FileUploadException {
+    public Map<String, List<I>> parseParameterMap(final HttpServletRequest 
request) throws FileUploadException {
         return parseParameterMap(new JakartaServletRequestContext(request));
     }
 
@@ -110,7 +113,7 @@ public class JakartaServletFileUpload extends 
AbstractFileUpload<HttpServletRequ
      * @throws FileUploadException if there are problems reading/parsing the 
request or storing files.
      */
     @Override
-    public List<FileItem> parseRequest(final HttpServletRequest request) 
throws FileUploadException {
+    public List<I> parseRequest(final HttpServletRequest request) throws 
FileUploadException {
         return parseRequest(new JakartaServletRequestContext(request));
     }
 
diff --git 
a/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/package-info.java
 
b/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/package-info.java
index b603860..70a7b79 100644
--- 
a/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/package-info.java
+++ 
b/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/package-info.java
@@ -17,8 +17,7 @@
 
 /**
  * <p>
- * An implementation of {@link 
org.apache.commons.fileupload2.core.AbstractFileUpload} for use in servlets 
conforming to the namespace
- * {@code jakarta.servlet}.
+ * An implementation of {@link 
org.apache.commons.fileupload2.core.AbstractFileUpload} for use in servlets 
conforming to the namespace {@code jakarta.servlet}.
  *
  * </p>
  * <p>
diff --git 
a/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaProgressListenerTest.java
 
b/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaProgressListenerTest.java
index 53cd61b..c194b79 100644
--- 
a/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaProgressListenerTest.java
+++ 
b/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaProgressListenerTest.java
@@ -20,17 +20,20 @@ import java.io.InputStream;
 
 import org.apache.commons.fileupload2.core.AbstractProgressListenerTest;
 import org.apache.commons.fileupload2.core.ProgressListener;
+import org.apache.commons.fileupload2.core.disk.DiskFileItem;
+import org.apache.commons.fileupload2.core.disk.DiskFileItemFactory;
 
 import jakarta.servlet.http.HttpServletRequest;
 
 /**
  * Tests the {@link ProgressListener}.
  */
-public class JakartaProgressListenerTest extends 
AbstractProgressListenerTest<JakartaServletFileUpload, HttpServletRequest> {
+public class JakartaProgressListenerTest extends
+        AbstractProgressListenerTest<JakartaServletFileUpload<DiskFileItem, 
DiskFileItemFactory>, HttpServletRequest, DiskFileItem, DiskFileItemFactory> {
 
     @Override
-    protected JakartaServletFileUpload newFileUpload() {
-        return new JakartaServletFileUpload();
+    protected JakartaServletFileUpload<DiskFileItem, DiskFileItemFactory> 
newFileUpload() {
+        return new JakartaServletFileUpload<>();
     }
 
     @Override
diff --git 
a/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUploadTest.java
 
b/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUploadTest.java
index ec66afa..1924fa5 100644
--- 
a/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUploadTest.java
+++ 
b/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUploadTest.java
@@ -25,8 +25,8 @@ import java.util.Map;
 
 import org.apache.commons.fileupload2.core.AbstractFileUploadTest;
 import org.apache.commons.fileupload2.core.Constants;
-import org.apache.commons.fileupload2.core.FileItem;
 import org.apache.commons.fileupload2.core.FileUploadException;
+import org.apache.commons.fileupload2.core.disk.DiskFileItem;
 import org.apache.commons.fileupload2.core.disk.DiskFileItemFactory;
 import org.junit.jupiter.api.Test;
 
@@ -37,10 +37,11 @@ import jakarta.servlet.http.HttpServletRequest;
  *
  * @see AbstractFileUploadTest
  */
-public class JakartaServletFileUploadTest extends 
AbstractFileUploadTest<JakartaServletFileUpload> {
+public class JakartaServletFileUploadTest
+        extends AbstractFileUploadTest<JakartaServletFileUpload<DiskFileItem, 
DiskFileItemFactory>, HttpServletRequest, DiskFileItem, DiskFileItemFactory> {
 
     public JakartaServletFileUploadTest() {
-        super(new 
JakartaServletFileUpload(DiskFileItemFactory.builder().get()));
+        super(new 
JakartaServletFileUpload<>(DiskFileItemFactory.builder().get()));
     }
 
     @Test
@@ -62,9 +63,9 @@ public class JakartaServletFileUploadTest extends 
AbstractFileUploadTest<Jakarta
                 .setCharset(StandardCharsets.UTF_8)
                 .get();
         // @formatter:on
-        final JakartaServletFileUpload upload = new 
JakartaServletFileUpload(fileItemFactory);
-        final List<FileItem> fileItems = upload.parseRequest(request);
-        final FileItem fileItem = fileItems.get(0);
+        final JakartaServletFileUpload<DiskFileItem, DiskFileItemFactory> 
upload = new JakartaServletFileUpload<>(fileItemFactory);
+        final List<DiskFileItem> fileItems = upload.parseRequest(request);
+        final DiskFileItem fileItem = fileItems.get(0);
         assertTrue(fileItem.getString().contains("coñteñt"), 
fileItem.getString());
     }
 
@@ -97,8 +98,8 @@ public class JakartaServletFileUploadTest extends 
AbstractFileUploadTest<Jakarta
         final byte[] bytes = text.getBytes(StandardCharsets.US_ASCII);
         final HttpServletRequest request = new 
JakartaMockServletHttpRequest(bytes, Constants.CONTENT_TYPE);
 
-        final JakartaServletFileUpload upload = new 
JakartaServletFileUpload(DiskFileItemFactory.builder().get());
-        final Map<String, List<FileItem>> mappedParameters = 
upload.parseParameterMap(request);
+        final JakartaServletFileUpload<DiskFileItem, DiskFileItemFactory> 
upload = new JakartaServletFileUpload<>(DiskFileItemFactory.builder().get());
+        final Map<String, List<DiskFileItem>> mappedParameters = 
upload.parseParameterMap(request);
         assertTrue(mappedParameters.containsKey("file"));
         assertEquals(1, mappedParameters.get("file").size());
 
@@ -110,7 +111,8 @@ public class JakartaServletFileUploadTest extends 
AbstractFileUploadTest<Jakarta
     }
 
     @Override
-    public List<FileItem> parseUpload(final JakartaServletFileUpload upload, 
final byte[] bytes, final String contentType) throws FileUploadException {
+    public List<DiskFileItem> parseUpload(final 
JakartaServletFileUpload<DiskFileItem, DiskFileItemFactory> upload, final 
byte[] bytes,
+            final String contentType) throws FileUploadException {
         final HttpServletRequest request = new 
JakartaMockHttpServletRequest(bytes, contentType);
         return upload.parseRequest(new JakartaServletRequestContext(request));
     }
diff --git 
a/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaSizesTest.java
 
b/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaSizesTest.java
index 234a047..b97e672 100644
--- 
a/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaSizesTest.java
+++ 
b/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaSizesTest.java
@@ -19,6 +19,7 @@ package org.apache.commons.fileupload2.jakarta;
 import java.io.InputStream;
 
 import org.apache.commons.fileupload2.core.AbstractSizesTest;
+import org.apache.commons.fileupload2.core.disk.DiskFileItem;
 import org.apache.commons.fileupload2.core.disk.DiskFileItemFactory;
 
 import jakarta.servlet.http.HttpServletRequest;
@@ -26,15 +27,17 @@ import jakarta.servlet.http.HttpServletRequest;
 /**
  * Unit test for items with varying sizes.
  */
-public class JakartaSizesTest extends 
AbstractSizesTest<JakartaServletFileUpload, HttpServletRequest> {
+public class JakartaSizesTest
+        extends AbstractSizesTest<JakartaServletFileUpload<DiskFileItem, 
DiskFileItemFactory>, HttpServletRequest, DiskFileItem, DiskFileItemFactory> {
 
     @Override
-    protected JakartaServletFileUpload newFileUpload() {
-        return new 
JakartaServletFileUpload(DiskFileItemFactory.builder().get());
+    protected JakartaServletFileUpload<DiskFileItem, DiskFileItemFactory> 
newFileUpload() {
+        return new 
JakartaServletFileUpload<>(DiskFileItemFactory.builder().get());
     }
 
     @Override
-    protected JakartaMockHttpServletRequest newMockHttpServletRequest(final 
InputStream request, final long requestLength, final String contentType, final 
int readLimit) {
+    protected JakartaMockHttpServletRequest newMockHttpServletRequest(final 
InputStream request, final long requestLength, final String contentType,
+            final int readLimit) {
         return new JakartaMockHttpServletRequest(request, requestLength, 
contentType, readLimit);
     }
 
diff --git 
a/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaStreamingTest.java
 
b/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaStreamingTest.java
index 3d6e4d5..0257992 100644
--- 
a/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaStreamingTest.java
+++ 
b/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaStreamingTest.java
@@ -19,17 +19,25 @@ package org.apache.commons.fileupload2.jakarta;
 import java.io.InputStream;
 
 import org.apache.commons.fileupload2.core.AbstractStreamingTest;
+import org.apache.commons.fileupload2.core.disk.DiskFileItem;
+import org.apache.commons.fileupload2.core.disk.DiskFileItemFactory;
 
 import jakarta.servlet.http.HttpServletRequest;
 
 /**
  * Unit test for items with varying sizes.
  */
-public class JakartaStreamingTest extends 
AbstractStreamingTest<JakartaServletFileUpload, HttpServletRequest, 
JakartaServletRequestContext> {
+public class JakartaStreamingTest extends
+        AbstractStreamingTest<JakartaServletFileUpload<DiskFileItem, 
DiskFileItemFactory>, HttpServletRequest, JakartaServletRequestContext, 
DiskFileItem, DiskFileItemFactory> {
 
     @Override
-    protected JakartaServletFileUpload newFileUpload() {
-        return new JakartaServletFileUpload();
+    protected DiskFileItemFactory newDiskFileItemFactory() {
+        return DiskFileItemFactory.builder().get();
+    }
+
+    @Override
+    protected JakartaServletFileUpload<DiskFileItem, DiskFileItemFactory> 
newFileUpload() {
+        return new JakartaServletFileUpload<>();
     }
 
     @Override
diff --git 
a/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/JavaxServletFileUpload.java
 
b/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/JavaxServletFileUpload.java
index 6a5943d..30b04b3 100644
--- 
a/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/JavaxServletFileUpload.java
+++ 
b/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/JavaxServletFileUpload.java
@@ -32,14 +32,17 @@ import 
org.apache.commons.fileupload2.core.FileUploadException;
  * High level API for processing file uploads.
  * <p>
  * This class handles multiple files per single HTML widget, sent using {@code 
multipart/mixed} encoding type, as specified by
- * <a href="http://www.ietf.org/rfc/rfc1867.txt";>RFC 1867</a>. Use {@link 
#parseRequest(HttpServletRequest)} to acquire a list of
- * {@link FileItem}s associated with a given HTML widget.
+ * <a href="http://www.ietf.org/rfc/rfc1867.txt";>RFC 1867</a>. Use {@link 
#parseRequest(HttpServletRequest)} to acquire a list of {@link FileItem}s 
associated
+ * with a given HTML widget.
  * </p>
  * <p>
  * 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.
  * </p>
+ *
+ * @param <I> The FileItem type.
+ * @param <F> the FileItemFactory type.
  */
-public class JavaxServletFileUpload extends 
AbstractFileUpload<HttpServletRequest> {
+public class JavaxServletFileUpload<I extends FileItem<I>, F extends 
FileItemFactory<I>> extends AbstractFileUpload<HttpServletRequest, I, F> {
 
     /**
      * Constant for HTTP POST method.
@@ -72,7 +75,7 @@ public class JavaxServletFileUpload extends 
AbstractFileUpload<HttpServletReques
      * @see AbstractFileUpload#AbstractFileUpload()
      * @param fileItemFactory The factory to use for creating file items.
      */
-    public JavaxServletFileUpload(final FileItemFactory fileItemFactory) {
+    public JavaxServletFileUpload(final F fileItemFactory) {
         setFileItemFactory(fileItemFactory);
     }
 
@@ -98,7 +101,7 @@ public class JavaxServletFileUpload extends 
AbstractFileUpload<HttpServletReques
      * @throws FileUploadException if there are problems reading/parsing the 
request or storing files.
      */
     @Override
-    public Map<String, List<FileItem>> parseParameterMap(final 
HttpServletRequest request) throws FileUploadException {
+    public Map<String, List<I>> parseParameterMap(final HttpServletRequest 
request) throws FileUploadException {
         return parseParameterMap(new JavaxServletRequestContext(request));
     }
 
@@ -110,7 +113,7 @@ public class JavaxServletFileUpload extends 
AbstractFileUpload<HttpServletReques
      * @throws FileUploadException if there are problems reading/parsing the 
request or storing files.
      */
     @Override
-    public List<FileItem> parseRequest(final HttpServletRequest request) 
throws FileUploadException {
+    public List<I> parseRequest(final HttpServletRequest request) throws 
FileUploadException {
         return parseRequest(new JavaxServletRequestContext(request));
     }
 
diff --git 
a/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/package-info.java
 
b/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/package-info.java
index 27d504e..b1c27b7 100644
--- 
a/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/package-info.java
+++ 
b/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/package-info.java
@@ -17,10 +17,9 @@
 
 /**
  * <p>
- * An implementation of {@link 
org.apache.commons.fileupload2.core.AbstractFileUpload} for use in servlets 
conforming to JSR 53. This implementation
- * requires only access to the servlet's current {@code HttpServletRequest} 
instance, and a suitable
- * {@link org.apache.commons.fileupload2.core.FileItemFactory} implementation, 
such as
- * {@link org.apache.commons.fileupload2.core.disk.DiskFileItemFactory}.
+ * An implementation of {@link 
org.apache.commons.fileupload2.core.AbstractFileUpload} for use in servlets 
conforming to JSR 53. This implementation requires
+ * only access to the servlet's current {@code HttpServletRequest} instance, 
and a suitable {@link org.apache.commons.fileupload2.core.FileItemFactory}
+ * implementation, such as {@link 
org.apache.commons.fileupload2.core.disk.DiskFileItemFactory}.
  * </p>
  * <p>
  * The following code fragment demonstrates typical usage.
diff --git 
a/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxProgressListenerTest.java
 
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxProgressListenerTest.java
index 69e9435..5ce9387 100644
--- 
a/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxProgressListenerTest.java
+++ 
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxProgressListenerTest.java
@@ -22,15 +22,18 @@ import javax.servlet.http.HttpServletRequest;
 
 import org.apache.commons.fileupload2.core.AbstractProgressListenerTest;
 import org.apache.commons.fileupload2.core.ProgressListener;
+import org.apache.commons.fileupload2.core.disk.DiskFileItem;
+import org.apache.commons.fileupload2.core.disk.DiskFileItemFactory;
 
 /**
  * Tests the {@link ProgressListener}.
  */
-public class JavaxProgressListenerTest extends 
AbstractProgressListenerTest<JavaxServletFileUpload, HttpServletRequest> {
+public class JavaxProgressListenerTest
+        extends 
AbstractProgressListenerTest<JavaxServletFileUpload<DiskFileItem, 
DiskFileItemFactory>, HttpServletRequest, DiskFileItem, DiskFileItemFactory> {
 
     @Override
-    protected JavaxServletFileUpload newFileUpload() {
-        return new JavaxServletFileUpload();
+    protected JavaxServletFileUpload<DiskFileItem, DiskFileItemFactory> 
newFileUpload() {
+        return new JavaxServletFileUpload<>();
     }
 
     @Override
diff --git 
a/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxServletFileUploadTest.java
 
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxServletFileUploadTest.java
index a0c72d5..c5cbf05 100644
--- 
a/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxServletFileUploadTest.java
+++ 
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxServletFileUploadTest.java
@@ -31,8 +31,8 @@ import javax.servlet.http.HttpServletRequest;
 
 import org.apache.commons.fileupload2.core.AbstractFileUploadTest;
 import org.apache.commons.fileupload2.core.Constants;
-import org.apache.commons.fileupload2.core.FileItem;
 import org.apache.commons.fileupload2.core.FileUploadException;
+import org.apache.commons.fileupload2.core.disk.DiskFileItem;
 import org.apache.commons.fileupload2.core.disk.DiskFileItemFactory;
 import org.junit.jupiter.api.Test;
 
@@ -41,10 +41,11 @@ import org.junit.jupiter.api.Test;
  *
  * @see AbstractFileUploadTest
  */
-public class JavaxServletFileUploadTest extends 
AbstractFileUploadTest<JavaxServletFileUpload> {
+public class JavaxServletFileUploadTest
+        extends AbstractFileUploadTest<JavaxServletFileUpload<DiskFileItem, 
DiskFileItemFactory>, HttpServletRequest, DiskFileItem, DiskFileItemFactory> {
 
     public JavaxServletFileUploadTest() {
-        super(new JavaxServletFileUpload(DiskFileItemFactory.builder().get()));
+        super(new 
JavaxServletFileUpload<>(DiskFileItemFactory.builder().get()));
     }
 
     @Test
@@ -66,9 +67,9 @@ public class JavaxServletFileUploadTest extends 
AbstractFileUploadTest<JavaxServ
                 .setCharset(StandardCharsets.UTF_8)
                 .get();
         // @formatter:on
-        final JavaxServletFileUpload upload = new 
JavaxServletFileUpload(fileItemFactory);
-        final List<FileItem> fileItems = upload.parseRequest(request);
-        final FileItem fileItem = fileItems.get(0);
+        final JavaxServletFileUpload<DiskFileItem, DiskFileItemFactory> upload 
= new JavaxServletFileUpload<>(fileItemFactory);
+        final List<DiskFileItem> fileItems = upload.parseRequest(request);
+        final DiskFileItem fileItem = fileItems.get(0);
         assertTrue(fileItem.getString().contains("coñteñt"), 
fileItem.getString());
     }
 
@@ -101,8 +102,8 @@ public class JavaxServletFileUploadTest extends 
AbstractFileUploadTest<JavaxServ
         final byte[] bytes = text.getBytes(StandardCharsets.US_ASCII);
         final HttpServletRequest request = new 
JavaxMockHttpServletRequest(bytes, Constants.CONTENT_TYPE);
 
-        final JavaxServletFileUpload upload = new 
JavaxServletFileUpload(DiskFileItemFactory.builder().get());
-        final Map<String, List<FileItem>> mappedParameters = 
upload.parseParameterMap(request);
+        final JavaxServletFileUpload<DiskFileItem, DiskFileItemFactory> upload 
= new JavaxServletFileUpload<>(DiskFileItemFactory.builder().get());
+        final Map<String, List<DiskFileItem>> mappedParameters = 
upload.parseParameterMap(request);
         assertTrue(mappedParameters.containsKey("file"));
         assertEquals(1, mappedParameters.get("file").size());
 
@@ -114,7 +115,8 @@ public class JavaxServletFileUploadTest extends 
AbstractFileUploadTest<JavaxServ
     }
 
     @Override
-    public List<FileItem> parseUpload(final JavaxServletFileUpload upload, 
final byte[] bytes, final String contentType) throws FileUploadException {
+    public List<DiskFileItem> parseUpload(final 
JavaxServletFileUpload<DiskFileItem, DiskFileItemFactory> upload, final byte[] 
bytes, final String contentType)
+            throws FileUploadException {
         final HttpServletRequest request = new 
JavaxMockHttpServletRequest(bytes, contentType);
         return upload.parseRequest(new JavaxServletRequestContext(request));
     }
@@ -141,15 +143,15 @@ public class JavaxServletFileUploadTest extends 
AbstractFileUploadTest<JavaxServ
         }
         baos.write("-----1234--\r\n".getBytes(StandardCharsets.US_ASCII));
 
-        final List<FileItem> fileItems = parseUpload(new 
JavaxServletFileUpload(DiskFileItemFactory.builder().get()), 
baos.toByteArray());
-        final Iterator<FileItem> fileIter = fileItems.iterator();
+        final List<DiskFileItem> fileItems = parseUpload(new 
JavaxServletFileUpload<>(DiskFileItemFactory.builder().get()), 
baos.toByteArray());
+        final Iterator<DiskFileItem> fileIter = fileItems.iterator();
         add = 16;
         num = 0;
         for (int i = 0; i < 16384; i += add) {
             if (++add == 32) {
                 add = 16;
             }
-            final FileItem item = fileIter.next();
+            final DiskFileItem item = fileIter.next();
             assertEquals("field" + (num++), item.getFieldName());
             final byte[] bytes = item.get();
             assertEquals(i, bytes.length);
diff --git 
a/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxSizesTest.java
 
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxSizesTest.java
index d42ef8e..aa230b6 100644
--- 
a/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxSizesTest.java
+++ 
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxSizesTest.java
@@ -21,20 +21,23 @@ import java.io.InputStream;
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.commons.fileupload2.core.AbstractSizesTest;
+import org.apache.commons.fileupload2.core.disk.DiskFileItem;
 import org.apache.commons.fileupload2.core.disk.DiskFileItemFactory;
 
 /**
  * Unit test for items with varying sizes.
  */
-public class JavaxSizesTest extends AbstractSizesTest<JavaxServletFileUpload, 
HttpServletRequest> {
+public class JavaxSizesTest
+        extends AbstractSizesTest<JavaxServletFileUpload<DiskFileItem, 
DiskFileItemFactory>, HttpServletRequest, DiskFileItem, DiskFileItemFactory> {
 
     @Override
-    protected JavaxServletFileUpload newFileUpload() {
-        return new JavaxServletFileUpload(DiskFileItemFactory.builder().get());
+    protected JavaxServletFileUpload<DiskFileItem, DiskFileItemFactory> 
newFileUpload() {
+        return new 
JavaxServletFileUpload<>(DiskFileItemFactory.builder().get());
     }
 
     @Override
-    protected JavaxMockHttpServletRequest newMockHttpServletRequest(final 
InputStream request, final long requestLength, final String contentType, final 
int readLimit) {
+    protected JavaxMockHttpServletRequest newMockHttpServletRequest(final 
InputStream request, final long requestLength, final String contentType,
+            final int readLimit) {
         return new JavaxMockHttpServletRequest(request, requestLength, 
contentType, readLimit);
     }
 
diff --git 
a/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxStreamingTest.java
 
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxStreamingTest.java
index 8e365c4..954de92 100644
--- 
a/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxStreamingTest.java
+++ 
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/JavaxStreamingTest.java
@@ -21,15 +21,23 @@ import java.io.InputStream;
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.commons.fileupload2.core.AbstractStreamingTest;
+import org.apache.commons.fileupload2.core.disk.DiskFileItem;
+import org.apache.commons.fileupload2.core.disk.DiskFileItemFactory;
 
 /**
  * Unit test for items with varying sizes.
  */
-public class JavaxStreamingTest extends 
AbstractStreamingTest<JavaxServletFileUpload, HttpServletRequest, 
JavaxServletRequestContext> {
+public class JavaxStreamingTest extends
+        AbstractStreamingTest<JavaxServletFileUpload<DiskFileItem, 
DiskFileItemFactory>, HttpServletRequest, JavaxServletRequestContext, 
DiskFileItem, DiskFileItemFactory> {
 
     @Override
-    protected JavaxServletFileUpload newFileUpload() {
-        return new JavaxServletFileUpload();
+    protected DiskFileItemFactory newDiskFileItemFactory() {
+        return DiskFileItemFactory.builder().get();
+    }
+
+    @Override
+    protected JavaxServletFileUpload<DiskFileItem, DiskFileItemFactory> 
newFileUpload() {
+        return new JavaxServletFileUpload<>();
     }
 
     @Override
diff --git 
a/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/JavaxPortletFileUpload.java
 
b/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/JavaxPortletFileUpload.java
index 314d77b..afb5664 100644
--- 
a/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/JavaxPortletFileUpload.java
+++ 
b/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/JavaxPortletFileUpload.java
@@ -39,8 +39,11 @@ import 
org.apache.commons.fileupload2.javax.JavaxServletFileUpload;
  * <p>
  * 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.
  * </p>
+ *
+ * @param <I> The FileItem type.
+ * @param <F> the FileItemFactory type.
  */
-public class JavaxPortletFileUpload extends AbstractFileUpload<ActionRequest> {
+public class JavaxPortletFileUpload<I extends FileItem<I>, F extends 
FileItemFactory<I>> extends AbstractFileUpload<ActionRequest, I, F> {
 
     /**
      * Tests whether the request contains multipart content.
@@ -49,7 +52,7 @@ public class JavaxPortletFileUpload extends 
AbstractFileUpload<ActionRequest> {
      * @return {@code true} if the request is multipart; {@code false} 
otherwise.
      */
     public static final boolean isMultipartContent(final ActionRequest 
request) {
-        return AbstractFileUpload.isMultipartContent(new 
PortletRequestContext(request));
+        return AbstractFileUpload.isMultipartContent(new 
JavaxPortletRequestContext(request));
     }
 
     /**
@@ -67,7 +70,7 @@ public class JavaxPortletFileUpload extends 
AbstractFileUpload<ActionRequest> {
      * @see AbstractFileUpload#AbstractFileUpload()
      * @param fileItemFactory The factory to use for creating file items.
      */
-    public JavaxPortletFileUpload(final FileItemFactory fileItemFactory) {
+    public JavaxPortletFileUpload(final F fileItemFactory) {
         setFileItemFactory(fileItemFactory);
     }
 
@@ -82,7 +85,7 @@ public class JavaxPortletFileUpload extends 
AbstractFileUpload<ActionRequest> {
      */
     @Override
     public FileItemInputIterator getItemIterator(final ActionRequest request) 
throws FileUploadException, IOException {
-        return super.getItemIterator(new PortletRequestContext(request));
+        return super.getItemIterator(new JavaxPortletRequestContext(request));
     }
 
     /**
@@ -93,8 +96,8 @@ public class JavaxPortletFileUpload extends 
AbstractFileUpload<ActionRequest> {
      * @throws FileUploadException if there are problems reading/parsing the 
request or storing files.
      */
     @Override
-    public Map<String, List<FileItem>> parseParameterMap(final ActionRequest 
request) throws FileUploadException {
-        return parseParameterMap(new PortletRequestContext(request));
+    public Map<String, List<I>> parseParameterMap(final ActionRequest request) 
throws FileUploadException {
+        return parseParameterMap(new JavaxPortletRequestContext(request));
     }
 
     /**
@@ -105,8 +108,8 @@ public class JavaxPortletFileUpload extends 
AbstractFileUpload<ActionRequest> {
      * @throws FileUploadException if there are problems reading/parsing the 
request or storing files.
      */
     @Override
-    public List<FileItem> parseRequest(final ActionRequest request) throws 
FileUploadException {
-        return parseRequest(new PortletRequestContext(request));
+    public List<I> parseRequest(final ActionRequest request) throws 
FileUploadException {
+        return parseRequest(new JavaxPortletRequestContext(request));
     }
 
 }
diff --git 
a/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/PortletRequestContext.java
 
b/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/JavaxPortletRequestContext.java
similarity index 93%
rename from 
commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/PortletRequestContext.java
rename to 
commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/JavaxPortletRequestContext.java
index 28565c2..460a55e 100644
--- 
a/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/PortletRequestContext.java
+++ 
b/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/JavaxPortletRequestContext.java
@@ -26,14 +26,14 @@ import 
org.apache.commons.fileupload2.core.AbstractRequestContext;
 /**
  * Provides access to the request information needed for a request made to a 
portlet.
  */
-public class PortletRequestContext extends 
AbstractRequestContext<ActionRequest> {
+public class JavaxPortletRequestContext extends 
AbstractRequestContext<ActionRequest> {
 
     /**
      * Constructs a context for this request.
      *
      * @param request The request to which this context applies.
      */
-    public PortletRequestContext(final ActionRequest request) {
+    public JavaxPortletRequestContext(final ActionRequest request) {
         super(request::getProperty, request::getContentLength, request);
     }
 
diff --git 
a/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/package-info.java
 
b/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/package-info.java
index 803b43c..5462c97 100644
--- 
a/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/package-info.java
+++ 
b/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/package-info.java
@@ -17,8 +17,8 @@
 
 /**
  * <p>
- * An implementation of {@link 
org.apache.commons.fileupload2.core.AbstractFileUpload} for use in portlets 
conforming to JSR 168. This implementation
- * requires only access to the portlet's current {@code ActionRequest} 
instance, and a suitable {@link 
org.apache.commons.fileupload2.core.FileItemFactory}
+ * An implementation of {@link 
org.apache.commons.fileupload2.core.AbstractFileUpload} for use in portlets 
conforming to JSR 168. This implementation requires
+ * only access to the portlet's current {@code ActionRequest} instance, and a 
suitable {@link org.apache.commons.fileupload2.core.FileItemFactory}
  * implementation, such as {@link 
org.apache.commons.fileupload2.core.disk.DiskFileItemFactory}.
  * </p>
  * <p>
diff --git 
a/commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/PortletFileUploadTest.java
 
b/commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/JavaxPortletFileUploadTest.java
similarity index 75%
rename from 
commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/PortletFileUploadTest.java
rename to 
commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/JavaxPortletFileUploadTest.java
index f1060ee..f511a20 100644
--- 
a/commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/PortletFileUploadTest.java
+++ 
b/commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/JavaxPortletFileUploadTest.java
@@ -24,15 +24,12 @@ import java.util.List;
 import java.util.Map;
 
 import javax.portlet.ActionRequest;
-import javax.servlet.http.HttpServletRequest;
 
 import org.apache.commons.fileupload2.core.AbstractFileUploadTest;
 import org.apache.commons.fileupload2.core.Constants;
-import org.apache.commons.fileupload2.core.FileItem;
 import org.apache.commons.fileupload2.core.FileUploadException;
+import org.apache.commons.fileupload2.core.disk.DiskFileItem;
 import org.apache.commons.fileupload2.core.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload2.javax.JavaxMockHttpServletRequest;
-import org.apache.commons.fileupload2.javax.JavaxServletRequestContext;
 import org.junit.jupiter.api.Test;
 
 /**
@@ -40,10 +37,11 @@ import org.junit.jupiter.api.Test;
  *
  * @see AbstractFileUploadTest
  */
-public class PortletFileUploadTest extends 
AbstractFileUploadTest<JavaxPortletFileUpload> {
+public class JavaxPortletFileUploadTest
+        extends AbstractFileUploadTest<JavaxPortletFileUpload<DiskFileItem, 
DiskFileItemFactory>, ActionRequest, DiskFileItem, DiskFileItemFactory> {
 
-    public PortletFileUploadTest() {
-        super(new JavaxPortletFileUpload(DiskFileItemFactory.builder().get()));
+    public JavaxPortletFileUploadTest() {
+        super(new 
JavaxPortletFileUpload<>(DiskFileItemFactory.builder().get()));
     }
 
     @Test
@@ -70,9 +68,9 @@ public class PortletFileUploadTest extends 
AbstractFileUploadTest<JavaxPortletFi
                       "-----1234--\r\n";
         // @formatter:on
         final byte[] bytes = text.getBytes(StandardCharsets.US_ASCII);
-        final ActionRequest request = new MockPortletActionRequest(bytes, 
Constants.CONTENT_TYPE);
+        final ActionRequest request = new JavaxPortletMockActionRequest(bytes, 
Constants.CONTENT_TYPE);
 
-        final Map<String, List<FileItem>> mappedParameters = 
upload.parseParameterMap(request);
+        final Map<String, List<DiskFileItem>> mappedParameters = 
upload.parseParameterMap(request);
         assertTrue(mappedParameters.containsKey("file"));
         assertEquals(1, mappedParameters.get("file").size());
 
@@ -84,9 +82,10 @@ public class PortletFileUploadTest extends 
AbstractFileUploadTest<JavaxPortletFi
     }
 
     @Override
-    public List<FileItem> parseUpload(final JavaxPortletFileUpload upload, 
final byte[] bytes, final String contentType) throws FileUploadException {
-        final HttpServletRequest request = new 
JavaxMockHttpServletRequest(bytes, contentType);
-        return upload.parseRequest(new JavaxServletRequestContext(request));
+    public List<DiskFileItem> parseUpload(final 
JavaxPortletFileUpload<DiskFileItem, DiskFileItemFactory> upload, final byte[] 
bytes, final String contentType)
+            throws FileUploadException {
+        final ActionRequest request = new JavaxPortletMockActionRequest(bytes, 
contentType);
+        return upload.parseRequest(new JavaxPortletRequestContext(request));
     }
 
 }
diff --git 
a/commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/MockPortletActionRequest.java
 
b/commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/JavaxPortletMockActionRequest.java
similarity index 94%
rename from 
commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/MockPortletActionRequest.java
rename to 
commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/JavaxPortletMockActionRequest.java
index 55b74ff..616ae02 100644
--- 
a/commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/MockPortletActionRequest.java
+++ 
b/commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/JavaxPortletMockActionRequest.java
@@ -42,10 +42,10 @@ import 
org.apache.commons.fileupload2.core.AbstractFileUpload;
 /**
  * Mock class for tests. Implements an {@link ActionRequest}.
  *
- * @see PortletFileUploadTest
+ * @see JavaxPortletFileUploadTest
  */
 @SuppressWarnings("rawtypes") // because of the portlet ActionRequest API does 
not use generics
-public class MockPortletActionRequest implements ActionRequest {
+public class JavaxPortletMockActionRequest implements ActionRequest {
 
     private final Hashtable<String, Object> attributes = new Hashtable<>();
 
@@ -56,11 +56,11 @@ public class MockPortletActionRequest implements 
ActionRequest {
     private final String contentType;
     private final InputStream requestData;
 
-    public MockPortletActionRequest(final byte[] requestData, final String 
contentType) {
+    public JavaxPortletMockActionRequest(final byte[] requestData, final 
String contentType) {
         this(new ByteArrayInputStream(requestData), requestData.length, 
contentType);
     }
 
-    public MockPortletActionRequest(final ByteArrayInputStream requestData, 
final int length, final String contentType) {
+    public JavaxPortletMockActionRequest(final ByteArrayInputStream 
requestData, final int length, final String contentType) {
         this.requestData = requestData;
         this.length = length;
         this.contentType = contentType;

Reply via email to