[prev in list] [next in list] [prev in thread] [next in thread] 

List:       jakarta-commons-dev
Subject:    [commons-fileupload] branch master updated: Refactor into Maven modules
From:       ggregory () apache ! org
Date:       2023-04-30 21:25:42
Message-ID: 168288994275.1307668.15483595823446410896 () gitbox2-he-fi ! apache ! org
[Download RAW message or body]

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


The following commit(s) were added to refs/heads/master by this push:
     new e654cc4  Refactor into Maven modules
e654cc4 is described below

commit e654cc4b1332fbad56836c832a59ee96ff95b626
Author: Gary Gregory <garydgregory@gmail.com>
AuthorDate: Sun Apr 30 17:25:30 2023 -0400

    Refactor into Maven modules
---
 .checkstyle                                        |    7 +-
 .gitignore                                         |   10 +-
 commons-fileupload2-core/.checkstyle               |   15 +
 commons-fileupload2-core/.gitignore                |    1 +
 commons-fileupload2-core/pom.xml                   |   91 ++
 .../commons/fileupload2/AbstractFileUpload.java    |  149 +--
 .../fileupload2/AbstractRequestContext.java        |    1 -
 .../org/apache/commons/fileupload2/FileItem.java   |    4 +-
 .../commons/fileupload2/FileItemFactory.java       |    0
 .../commons/fileupload2/FileItemHeaders.java       |    0
 .../fileupload2/FileItemHeadersSupport.java        |    9 +-
 .../commons/fileupload2/FileItemIterator.java      |   95 ++
 .../apache/commons/fileupload2/FileItemStream.java |   58 +-
 .../org/apache/commons/fileupload2/FileUpload.java |   28 +-
 .../commons/fileupload2/FileUploadException.java   |    0
 .../fileupload2/InvalidFileNameException.java      |   16 +-
 .../commons/fileupload2/MultipartStream.java       |   33 +-
 .../commons/fileupload2/ParameterParser.java       |   95 +-
 .../commons/fileupload2/ProgressListener.java      |    0
 .../apache/commons/fileupload2/RequestContext.java |    1 +
 .../commons/fileupload2/disk/DiskFileItem.java     | 1177 +++++++++-----------
 .../fileupload2/disk/DiskFileItemFactory.java      |  439 ++++----
 .../commons/fileupload2/disk/package-info.java     |   47 +
 .../fileupload2/impl/FileItemIteratorImpl.java     |  663 ++++++-----
 .../fileupload2/impl/FileItemStreamImpl.java       |  411 ++++---
 .../commons/fileupload2/impl/package-info.java     |    0
 .../apache/commons/fileupload2/package-info.java   |   48 +-
 .../pub/FileUploadByteCountLimitException.java     |  144 +--
 .../pub/FileUploadContentTypeException.java        |  122 +-
 .../pub/FileUploadFileCountLimitException.java     |    0
 .../fileupload2/pub/FileUploadSizeException.java   |  144 +--
 .../commons/fileupload2/pub/package-info.java      |    3 +-
 .../fileupload2/util/FileItemHeadersImpl.java      |    0
 .../fileupload2/util/LimitedInputStream.java       |   81 +-
 .../commons/fileupload2/util/mime/MimeUtility.java |   36 +-
 .../fileupload2/util/mime/ParseException.java      |    0
 .../util/mime/QuotedPrintableDecoder.java          |   13 +-
 .../fileupload2/util/mime/RFC2231Utility.java      |   34 +-
 .../fileupload2/util/mime/package-info.java        |    4 +-
 .../commons/fileupload2/util/package-info.java     |    5 +-
 .../fileupload2/AbstractFileUploadTest.java        |  152 ++-
 .../fileupload2/AbstractFileUploadWrapper.java     |   45 +
 .../org/apache/commons/fileupload2/Constants.java  |    3 +-
 .../fileupload2/DiskFileItemSerializeTest.java     |    0
 .../commons/fileupload2/FileItemHeadersTest.java   |    9 +-
 .../commons/fileupload2/MultipartStreamTest.java   |   20 +-
 .../commons/fileupload2/ParameterParserTest.java   |   24 +-
 .../fileupload2/util/mime/MimeUtilityTestCase.java |    9 +-
 .../util/mime/QuotedPrintableDecoderTestCase.java  |    5 +-
 .../util/mime/RFC2231UtilityTestCase.java          |    8 +-
 commons-fileupload2-jakarta/.checkstyle            |   15 +
 commons-fileupload2-jakarta/pom.xml                |   75 ++
 .../jakarta/JakartaServletFileCleaner.java         |   46 +-
 .../jakarta/JakartaServletFileUpload.java          |   79 +-
 .../jakarta/JakartaServletRequestContext.java      |  161 ++-
 .../commons/fileupload2/jakarta/package-info.java  |   45 +-
 .../jakarta/JakartaServletFileUploadTest.java      |   27 +-
 .../jakarta/MockJakartaServletHttpRequest.java     |   49 +-
 commons-fileupload2-javax/.checkstyle              |   15 +
 commons-fileupload2-javax/pom.xml                  |   69 ++
 .../fileupload2/javax}/FileCleanerCleanup.java     |   44 +-
 .../fileupload2/javax}/ServletFileUpload.java      |   59 +-
 .../fileupload2/javax}/ServletRequestContext.java  |  161 ++-
 .../commons/fileupload2/javax/package-info.java    |   40 +
 .../javax}/HttpServletRequestFactory.java          |   21 +-
 .../fileupload2/javax}/MockHttpServletRequest.java |   31 +-
 .../fileupload2/javax}/ProgressListenerTest.java   |   26 +-
 .../fileupload2/javax}/ServletFileUploadTest.java  |   82 +-
 .../commons/fileupload2/javax}/SizesTest.java      |  526 ++++-----
 .../commons/fileupload2/javax}/StreamingTest.java  |   68 +-
 commons-fileupload2-portlet/.checkstyle            |   15 +
 commons-fileupload2-portlet/.gitignore             |    1 +
 commons-fileupload2-portlet/pom.xml                |   81 ++
 .../fileupload2/portlet/PortletFileUpload.java     |   72 +-
 .../fileupload2/portlet/PortletRequestContext.java |  158 +--
 .../commons/fileupload2/portlet/package-info.java  |   40 +
 .../portlet/MockPortletActionRequest.java          |    3 +-
 .../fileupload2/portlet/PortletFileUploadTest.java |   30 +-
 pom.xml                                            |   84 +-
 .../commons/fileupload2/FileItemIterator.java      |  107 --
 .../commons/fileupload2/disk/package-info.java     |   54 -
 .../commons/fileupload2/jaksrvlt/package-info.java |   41 -
 .../commons/fileupload2/portlet/package-info.java  |   45 -
 .../commons/fileupload2/servlet/package-info.java  |   45 -
 .../java/org/apache/commons/fileupload2/Util.java  |   62 --
 85 files changed, 3311 insertions(+), 3425 deletions(-)

diff --git a/.checkstyle b/.checkstyle
index e39f75b..5fbd5a9 100644
--- a/.checkstyle
+++ b/.checkstyle
@@ -1,13 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>

 <fileset-config file-format-version="1.2.0" simple-config="false" \
                sync-formatter="false">
-  <local-check-config name="maven-checkstyle-plugin validate-main" \
location="file:/Users/garydgregory/git/commons-fileupload/src/checkstyle/fileupload_checks.xml" \
                type="remote" description="maven-checkstyle-plugin configuration \
                validate-main">
-    <property name="checkstyle.header.file" \
value="/Users/garydgregory/eclipse-workspace/apache-commons/.metadata/.plugins/org.ecl \
ipse.core.resources/.projects/commons-fileupload2/com.basistech.m2e.code.quality.checkstyleConfigurator/checkstyle-header-validate-main.txt"/>
 +  <local-check-config name="maven-checkstyle-plugin validate-main" \
location="file:/C:/Users/ggregory/git/a/commons-fileupload/src/checkstyle/fileupload_checks.xml" \
type="remote" description="maven-checkstyle-plugin configuration validate-main"> +    \
<property name="checkstyle.header.file" value="C:\Users\ggregory\OneDrive - Rocket \
Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.project \
s\commons-fileupload2\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-header-validate-main.txt"/>
                
     <property name="checkstyle.cache.file" \
                value="${project_loc}/target/checkstyle-cachefile"/>
-    <property name="checkstyle.suppressions.file" \
value="/Users/garydgregory/eclipse-workspace/apache-commons/.metadata/.plugins/org.ecl \
ipse.core.resources/.projects/commons-fileupload2/com.basistech.m2e.code.quality.checkstyleConfigurator/checkstyle-suppressions-validate-main.xml"/>
 +    <property name="checkstyle.suppressions.file" value="C:\Users\ggregory\OneDrive \
- Rocket Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources \
\.projects\commons-fileupload2\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-suppressions-validate-main.xml"/>
  </local-check-config>
   <fileset name="java-sources-validate-main" enabled="true" \
                check-config-name="maven-checkstyle-plugin validate-main" \
                local="true">
-    <file-match-pattern match-pattern="^src/main/java/.*\/.*\.java" \
                include-pattern="true"/>
     <file-match-pattern match-pattern="^src/main/resources.*\.properties" \
                include-pattern="true"/>
     <file-match-pattern match-pattern="^.*\.properties" include-pattern="true"/>
     <file-match-pattern match-pattern="^src/test/resources.*\.properties" \
                include-pattern="true"/>
diff --git a/.gitignore b/.gitignore
index d23eb15..9e8811e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
-/target/
-/.settings/
-/.classpath
-/.project
-site-content/
+**/target/
+**/.settings/
+**/.classpath
+**/.project
+**/site-content/
 /commons-fileupload2.iml
diff --git a/commons-fileupload2-core/.checkstyle \
b/commons-fileupload2-core/.checkstyle new file mode 100644
index 0000000..322b565
--- /dev/null
+++ b/commons-fileupload2-core/.checkstyle
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="false" \
sync-formatter="false"> +  <local-check-config name="maven-checkstyle-plugin \
validate-main" location="file:/C:/Users/ggregory/git/a/commons-fileupload/commons-fileupload2-core/../src/checkstyle/fileupload_checks.xml" \
type="remote" description="maven-checkstyle-plugin configuration validate-main"> +    \
<property name="checkstyle.header.file" value="C:\Users\ggregory\OneDrive - Rocket \
Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.project \
s\commons-fileupload2-core\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-header-validate-main.txt"/>
 +    <property name="checkstyle.cache.file" \
value="${project_loc}/target/checkstyle-cachefile"/> +    <property \
name="checkstyle.suppressions.file" value="C:\Users\ggregory\OneDrive - Rocket \
Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.project \
s\commons-fileupload2-core\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-suppressions-validate-main.xml"/>
 +  </local-check-config>
+  <fileset name="java-sources-validate-main" enabled="true" \
check-config-name="maven-checkstyle-plugin validate-main" local="true"> +    \
<file-match-pattern match-pattern="^src/main/java/.*\.java" include-pattern="true"/> \
+    <file-match-pattern match-pattern="^src/main/resources.*\.properties" \
include-pattern="true"/> +    <file-match-pattern match-pattern="^.*\.properties" \
include-pattern="true"/> +    <file-match-pattern \
match-pattern="^src/test/resources.*\.properties" include-pattern="true"/> +  \
</fileset> +</fileset-config>
diff --git a/commons-fileupload2-core/.gitignore \
b/commons-fileupload2-core/.gitignore new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/commons-fileupload2-core/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/commons-fileupload2-core/pom.xml b/commons-fileupload2-core/pom.xml
new file mode 100644
index 0000000..21d8b0c
--- /dev/null
+++ b/commons-fileupload2-core/pom.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" \
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 \
http://maven.apache.org/maven-v4_0_0.xsd"> +  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.commons</groupId>
+    <artifactId>commons-fileupload2</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>commons-fileupload2-core</artifactId>
+
+  <name>Apache Commons FileUpload Core</name>
+  <description>
+    The Apache Commons FileUpload component provides a simple yet flexible means of \
adding support for multipart +    file upload functionality to servlets and web \
applications. +  </description>
+
+  <properties>
+	<commons.parent.dir>${basedir}/..</commons.parent.dir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>${commons.io.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+      <version>${commons.lang3.version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.moditect</groupId>
+        <artifactId>moditect-maven-plugin</artifactId>
+        <version>${moditect-maven-plugin.version}</version>
+        <executions>
+          <execution>
+            <id>add-module-infos</id>
+            <phase>package</phase>
+            <goals>
+              <goal>add-module-info</goal>
+            </goals>
+            <configuration>
+              <jvmVersion>9</jvmVersion>
+              <outputDirectory>${project.build.directory}</outputDirectory>
+              <overwriteExistingFiles>true</overwriteExistingFiles>
+              <module>
+                <moduleInfo>
+                  <name>org.apache.commons.fileupload2</name>
+                  <exports>
+                    !org.apache.commons.fileupload2.impl;
+                    *;
+                  </exports>
+                </moduleInfo>
+              </module>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/src/main/java/org/apache/commons/fileupload2/AbstractFileUpload.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/AbstractFileUpload.java
 similarity index 80%
rename from src/main/java/org/apache/commons/fileupload2/AbstractFileUpload.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/AbstractFileUpload.java
 index 4340bae..a7d6ab4 100644
--- a/src/main/java/org/apache/commons/fileupload2/AbstractFileUpload.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/AbstractFileUpload.java
 @@ -16,7 +16,6 @@
  */
 package org.apache.commons.fileupload2;

-
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -36,17 +35,12 @@ 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
- * org.apache.commons.fileupload2.FileItem}s associated with a given HTML
- * widget.
+ * 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 \
                org.apache.commons.fileupload2.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.
+ * 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>
  */
 public abstract class AbstractFileUpload {
@@ -92,17 +86,14 @@ public abstract class AbstractFileUpload {
     public static final String MULTIPART_MIXED = "multipart/mixed";

     /**
-     * Utility method that determines whether the request contains multipart
-     * content.
+     * Utility method that determines whether the request contains multipart \
                content.
      * <p>
-     * <strong>NOTE:</strong> This method will be moved to the
-     * {@code ServletFileUpload} class after the FileUpload 1.1 release.
-     * Unfortunately, since this method is static, it is not possible to
-     * provide its replacement until this method is removed.
+     * <strong>NOTE:</strong> This method will be moved to the {@code \
ServletFileUpload} class after the FileUpload 1.1 release. Unfortunately, since this \
+     * method is static, it is not possible to provide its replacement until this \
                method is removed.
      * </p>
+     *
      * @param ctx The request context to be evaluated. Must be non-null.
-     * @return {@code true} if the request is multipart;
-     *         {@code false} otherwise.
+     * @return {@code true} if the request is multipart; {@code false} otherwise.
      */
     public static final boolean isMultipartContent(final RequestContext ctx) {
         final String contentType = ctx.getContentType();
@@ -113,20 +104,17 @@ public abstract class AbstractFileUpload {
     }

     /**
-     * The maximum size permitted for the complete request, as opposed to
-     * {@link #fileSizeMax}. A value of -1 indicates no maximum.
+     * The maximum size permitted for the complete request, as opposed to {@link \
                #fileSizeMax}. A value of -1 indicates no maximum.
      */
     private long sizeMax = -1;

     /**
-     * The maximum size permitted for a single uploaded file, as opposed
-     * to {@link #sizeMax}. A value of -1 indicates no maximum.
+     * The maximum size permitted for a single uploaded file, as opposed to {@link \
                #sizeMax}. A value of -1 indicates no maximum.
      */
     private long fileSizeMax = -1;

     /**
-     * The maximum permitted number of files that may be uploaded in a single
-     * request. A value of -1 indicates no maximum.
+     * The maximum permitted number of files that may be uploaded in a single \
                request. A value of -1 indicates no maximum.
      */
     private long fileCountMax = -1;

@@ -143,15 +131,14 @@ public abstract class AbstractFileUpload {
     /**
      * Gets the boundary from the {@code Content-type} header.
      *
-     * @param contentType The value of the content type header from which to
-     *                    extract the boundary value.
+     * @param contentType The value of the content type header from which to extract \
                the boundary value.
      * @return The boundary, as a byte array.
      */
     public byte[] getBoundary(final String contentType) {
         final ParameterParser parser = new ParameterParser();
         parser.setLowerCaseNames(true);
         // Parameter parser can handle null input
-        final Map<String, String> params = parser.parse(contentType, new char[] \
{';', ','}); +        final Map<String, String> params = parser.parse(contentType, \
new char[] { ';', ',' });  final String boundaryStr = params.get("boundary");

         if (boundaryStr == null) {
@@ -163,8 +150,7 @@ public abstract class AbstractFileUpload {
     }

     /**
-     * Gets the field name from the {@code Content-disposition}
-     * header.
+     * Gets the field name from the {@code Content-disposition} header.
      *
      * @param headers A {@code Map} containing the HTTP request headers.
      * @return The field name for the current {@code encapsulation}.
@@ -174,16 +160,14 @@ public abstract class AbstractFileUpload {
     }

     /**
-     * Gets the field name, which is given by the content-disposition
-     * header.
+     * Gets the field name, which is given by the content-disposition header.
      *
      * @param contentDisposition The content-dispositions header value.
      * @return The field jake
      */
     private String getFieldName(final String contentDisposition) {
         String fieldName = null;
-        if (contentDisposition != null
-                && contentDisposition.toLowerCase(Locale.ENGLISH).startsWith(FORM_DATA)) \
{ +        if (contentDisposition != null && \
contentDisposition.toLowerCase(Locale.ENGLISH).startsWith(FORM_DATA)) {  final \
ParameterParser parser = new ParameterParser();  parser.setLowerCaseNames(true);
             // Parameter parser can handle null input
@@ -213,8 +197,7 @@ public abstract class AbstractFileUpload {
     public abstract FileItemFactory getFileItemFactory();

     /**
-     * Gets the file name from the {@code Content-disposition}
-     * header.
+     * Gets the file name from the {@code Content-disposition} header.
      *
      * @param headers The HTTP headers object.
      *
@@ -226,6 +209,7 @@ public abstract class AbstractFileUpload {

     /**
      * Gets the given content-disposition headers file name.
+     *
      * @param contentDisposition The content-disposition headers value.
      * @return The file name
      */
@@ -255,8 +239,7 @@ public abstract class AbstractFileUpload {
     }

     /**
-     * Gets the maximum allowed size of a single uploaded file,
-     * as opposed to {@link #getSizeMax()}.
+     * Gets the maximum allowed size of a single uploaded file, as opposed to {@link \
                #getSizeMax()}.
      *
      * @see #setFileSizeMax(long)
      * @return Maximum size of a single uploaded file.
@@ -266,10 +249,8 @@ public abstract class AbstractFileUpload {
     }

     /**
-     * Gets the character encoding used when reading the headers of an
-     * individual part. When not specified, or {@code null}, the request
-     * encoding is used. If that is also not specified, or {@code null},
-     * the platform default encoding is used.
+     * Gets the character encoding used when reading the headers of an individual \
part. When not specified, or {@code null}, the request encoding is used. If +     * \
                that is also not specified, or {@code null}, the platform default \
                encoding is used.
      *
      * @return The encoding used to read part headers.
      */
@@ -278,32 +259,25 @@ public abstract class AbstractFileUpload {
     }

     /**
-     * Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
-     * compliant {@code multipart/form-data} stream.
+     * Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant \
                {@code multipart/form-data} stream.
      *
      * @param ctx The context for the request to be parsed.
-     * @return An iterator to instances of {@code FileItemStream}
-     *         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.
+     * @return An iterator to instances of {@code FileItemStream} 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 FileItemIterator getItemIterator(final RequestContext ctx) throws \
FileUploadException, IOException {  return new FileItemIteratorImpl(this, ctx);
     }

     /**
-     * Parses the {@code header-part} and returns as key/value
-     * pairs.
+     * Parses the {@code header-part} and returns as key/value pairs.
      * <p>
-     * If there are multiple headers of the same names, the name
-     * will map to a comma-separated list containing the values.
+     * If there are multiple headers of the same names, the name will map to a \
                comma-separated list containing the values.
      * </p>
-     * @param headerPart The {@code header-part} of the current
-     *                   {@code encapsulation}.
+     *
+     * @param headerPart The {@code header-part} of the current {@code \
                encapsulation}.
      * @return A {@code Map} containing the parsed HTTP request headers.
      */
     public FileItemHeaders getParsedHeaders(final String headerPart) {
@@ -321,7 +295,7 @@ public abstract class AbstractFileUpload {
                 int nonWs = start;
                 while (nonWs < len) {
                     final char c = headerPart.charAt(nonWs);
-                    if (c != ' '  &&  c != '\t') {
+                    if (c != ' ' && c != '\t') {
                         break;
                     }
                     ++nonWs;
@@ -349,11 +323,9 @@ public abstract class AbstractFileUpload {
     }

     /**
-     * Gets the maximum allowed size of a complete request, as opposed
-     * to {@link #getFileSizeMax()}.
+     * Gets the maximum allowed size of a complete request, as opposed to {@link \
                #getFileSizeMax()}.
      *
-     * @return The maximum allowed size, in bytes. The default value of
-     *   -1 indicates, that there is no limit.
+     * @return The maximum allowed size, in bytes. The default value of -1 \
                indicates, that there is no limit.
      * @see #setSizeMax(long)
      *
      */
@@ -363,6 +335,7 @@ public abstract class AbstractFileUpload {

     /**
      * Creates a new instance of {@link FileItemHeaders}.
+     *
      * @return The new instance.
      */
     protected FileItemHeadersImpl newFileItemHeaders() {
@@ -373,18 +346,15 @@ public abstract class AbstractFileUpload {
      * Skips bytes until the end of the current line.
      *
      * @param headerPart The headers, which are being parsed.
-     * @param end Index of the last byte, which has yet been
-     *   processed.
-     * @return Index of the \r\n sequence, which indicates
-     *   end of line.
+     * @param end        Index of the last byte, which has yet been processed.
+     * @return Index of the \r\n sequence, which indicates end of line.
      */
     private int parseEndOfLine(final String headerPart, final int end) {
         int index = end;
         for (;;) {
             final int offset = headerPart.indexOf('\r', index);
-            if (offset == -1  ||  offset + 1 >= headerPart.length()) {
-                throw new IllegalStateException(
-                    "Expected headers to be terminated by an empty line.");
+            if (offset == -1 || offset + 1 >= headerPart.length()) {
+                throw new IllegalStateException("Expected headers to be terminated \
by an empty line.");  }
             if (headerPart.charAt(offset + 1) == '\n') {
                 return offset;
@@ -397,7 +367,7 @@ public abstract class AbstractFileUpload {
      * Parses the next header line.
      *
      * @param headers String with all headers.
-     * @param header Map where to store the current header.
+     * @param header  Map where to store the current header.
      */
     private void parseHeaderLine(final FileItemHeadersImpl headers, final String \
header) {  final int colonOffset = header.indexOf(':');
@@ -406,23 +376,19 @@ public abstract class AbstractFileUpload {
             return;
         }
         final String headerName = header.substring(0, colonOffset).trim();
-        final String headerValue -            header.substring(colonOffset + \
1).trim(); +        final String headerValue = header.substring(colonOffset + \
1).trim();  headers.addHeader(headerName, headerValue);
     }

     /**
-     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
-     * compliant {@code multipart/form-data} stream.
+     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> \
                compliant {@code multipart/form-data} stream.
      *
      * @param ctx The context for the 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.
+     * @throws FileUploadException if there are problems reading/parsing the request \
                or storing files.
      * @since 1.3
      */
-    public Map<String, List<FileItem>> parseParameterMap(final RequestContext ctx)
-            throws FileUploadException {
+    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());

@@ -437,17 +403,13 @@ public abstract class AbstractFileUpload {
     }

     /**
-     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
-     * compliant {@code multipart/form-data} stream.
+     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> \
                compliant {@code multipart/form-data} stream.
      *
      * @param ctx The context for the 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.
+     * @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 ctx)
-            throws FileUploadException {
+    public List<FileItem> parseRequest(final RequestContext ctx) throws \
FileUploadException {  final List<FileItem> items = new ArrayList<>();
         boolean successful = false;
         try {
@@ -510,8 +472,7 @@ public abstract class AbstractFileUpload {
     public abstract void setFileItemFactory(FileItemFactory factory);

     /**
-     * Sets the maximum allowed size of a single uploaded file,
-     * as opposed to {@link #getSizeMax()}.
+     * Sets the maximum allowed size of a single uploaded file, as opposed to {@link \
                #getSizeMax()}.
      *
      * @see #getFileSizeMax()
      * @param fileSizeMax Maximum size of a single uploaded file.
@@ -521,10 +482,8 @@ public abstract class AbstractFileUpload {
     }

     /**
-     * Specifies the character encoding to be used when reading the headers of
-     * individual part. When not specified, or {@code null}, the request
-     * encoding is used. If that is also not specified, or {@code null},
-     * the platform default encoding is used.
+     * Specifies the character encoding to be used when reading the headers of \
individual part. When not specified, or {@code null}, the request encoding is +     * \
used. If that is also not specified, or {@code null}, the platform default encoding \
                is used.
      *
      * @param encoding The encoding used to read part headers.
      */
@@ -542,11 +501,9 @@ public abstract class AbstractFileUpload {
     }

     /**
-     * Sets the maximum allowed size of a complete request, as opposed
-     * to {@link #setFileSizeMax(long)}.
+     * Sets the maximum allowed size of a complete request, as opposed to {@link \
                #setFileSizeMax(long)}.
      *
-     * @param sizeMax The maximum allowed size, in bytes. The default value of
-     *   -1 indicates, that there is no limit.
+     * @param sizeMax The maximum allowed size, in bytes. The default value of -1 \
                indicates, that there is no limit.
      * @see #getSizeMax()
      */
     public void setSizeMax(final long sizeMax) {
diff --git a/src/main/java/org/apache/commons/fileupload2/AbstractRequestContext.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/AbstractRequestContext.java
 similarity index 99%
rename from src/main/java/org/apache/commons/fileupload2/AbstractRequestContext.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/AbstractRequestContext.java
 index bb1422e..61ab217 100644
--- a/src/main/java/org/apache/commons/fileupload2/AbstractRequestContext.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/AbstractRequestContext.java
 @@ -39,7 +39,6 @@ public abstract class AbstractRequestContext implements \
                RequestContext {
      * @param contentLengthDefault How to get the content length default.
      */
     protected AbstractRequestContext(final Function<String, String> \
                contentLengthString, final LongSupplier contentLengthDefault) {
-        super();
         this.contentLengthString = contentLengthString;
         this.contentLengthDefault = contentLengthDefault;
     }
diff --git a/src/main/java/org/apache/commons/fileupload2/FileItem.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItem.java \
similarity index 98% rename from \
src/main/java/org/apache/commons/fileupload2/FileItem.java rename to \
commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItem.java \
                index ad8d28d..0477cfc 100644
--- a/src/main/java/org/apache/commons/fileupload2/FileItem.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItem.java
 @@ -29,7 +29,7 @@ import java.io.UnsupportedEncodingException;
  * </p>
  * <p>
  * After retrieving an instance of this class from a {@link \
                org.apache.commons.fileupload2.FileUpload FileUpload} instance (see
- * {@link org.apache.commons.fileupload2.servlet.ServletFileUpload \
#parseRequest(javax.servlet.http.HttpServletRequest)}), you may either request all \
contents + * {@code org.apache.commons.fileupload2.servlet.ServletFileUpload \
#parseRequest(javax.servlet.http.HttpServletRequest)}), you may either request all \
                contents
  * of the file at once using {@link #get()} or request an {@link java.io.InputStream \
                InputStream} with {@link #getInputStream()} and process the file \
                without
  * attempting to load it into memory, which may come handy with large files.
  * </p>
@@ -38,6 +38,7 @@ import java.io.UnsupportedEncodingException;
  * specifically 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>
+ *
  * @since 1.3 additionally implements FileItemHeadersSupport
  */
 public interface FileItem extends FileItemHeadersSupport {
@@ -165,6 +166,7 @@ public interface FileItem extends FileItemHeadersSupport {
      * This method is not guaranteed to succeed if called more than once for the \
                same item. This allows a particular implementation to use, for \
                example, file
      * renaming, where possible, rather than copying all of the underlying data, \
                thus gaining a significant performance benefit.
      * </p>
+     *
      * @param file The {@code File} into which the uploaded item should be stored.
      * @throws IOException if an error occurs.
      */
diff --git a/src/main/java/org/apache/commons/fileupload2/FileItemFactory.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemFactory.java
 similarity index 100%
rename from src/main/java/org/apache/commons/fileupload2/FileItemFactory.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemFactory.java
                
diff --git a/src/main/java/org/apache/commons/fileupload2/FileItemHeaders.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemHeaders.java
 similarity index 100%
rename from src/main/java/org/apache/commons/fileupload2/FileItemHeaders.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemHeaders.java
                
diff --git a/src/main/java/org/apache/commons/fileupload2/FileItemHeadersSupport.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemHeadersSupport.java
 similarity index 79%
copy from src/main/java/org/apache/commons/fileupload2/FileItemHeadersSupport.java
copy to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemHeadersSupport.java
 index a71553a..54b14f5 100644
--- a/src/main/java/org/apache/commons/fileupload2/FileItemHeadersSupport.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemHeadersSupport.java
 @@ -33,13 +33,10 @@ public interface FileItemHeadersSupport {
     FileItemHeaders getHeaders();

     /**
-     * Sets the headers read from within an item.  Implementations of
-     * {@link FileItem} or {@link FileItemStream} should implement this
-     * interface to be able to get the raw headers found within the item
-     * header block.
+     * Sets the headers read from within an item. Implementations of {@link \
FileItem} or {@link FileItemStream} should implement this interface to be able to +   \
                * get the raw headers found within the item header block.
      *
-     * @param headers the instance that holds onto the headers
-     *         for this instance.
+     * @param headers the instance that holds onto the headers for this instance.
      */
     void setHeaders(FileItemHeaders headers);

diff --git a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemIterator.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemIterator.java
 new file mode 100644
index 0000000..d8338fd
--- /dev/null
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemIterator.java
 @@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.naming.SizeLimitExceededException;
+
+import org.apache.commons.fileupload2.pub.FileUploadByteCountLimitException;
+
+/**
+ * An iterator, as returned by {@link \
AbstractFileUpload#getItemIterator(RequestContext)}. + */
+public interface FileItemIterator {
+
+    List<FileItem> getFileItems() throws FileUploadException, IOException;
+
+    /**
+     * Gets the maximum size of a single file. An {@link \
FileUploadByteCountLimitException} will be thrown, if there is an uploaded file, \
which is exceeding +     * this value. By default, this value will be copied from the \
{@link AbstractFileUpload#getFileSizeMax() FileUploadBase} object, however, the user \
may +     * replace the default value with a request specific value by invoking \
{@link #setFileSizeMax(long)} on this object. +     *
+     * @return The maximum size of a single, uploaded file. The value -1 indicates \
"unlimited". +     */
+    long getFileSizeMax();
+
+    /**
+     * Gets the maximum size of the complete HTTP request. A {@link \
SizeLimitExceededException} will be thrown, if the HTTP request will exceed this \
value. By +     * default, this value will be copied from the {@link \
AbstractFileUpload#getSizeMax() FileUploadBase} object, however, the user may replace \
the default +     * value with a request specific value by invoking {@link \
#setSizeMax(long)} on this object. +     *
+     * @return The maximum size of the complete HTTP request. The value -1 indicates \
"unlimited". +     */
+    long getSizeMax();
+
+    /**
+     * Tests whether another instance of {@link FileItemStream} is available.
+     *
+     * @throws FileUploadException Parsing or processing the file item failed.
+     * @throws IOException         Reading the file item failed.
+     * @return True, if one or more additional file items are available, otherwise \
false. +     */
+    boolean hasNext() throws FileUploadException, IOException;
+
+    /**
+     * Returns the next available {@link FileItemStream}.
+     *
+     * @throws java.util.NoSuchElementException No more items are available. Use \
{@link #hasNext()} to prevent this exception. +     * @throws FileUploadException     \
Parsing or processing the file item failed. +     * @throws IOException               \
Reading the file item failed. +     * @return FileItemStream instance, which provides \
access to the next file item. +     */
+    FileItemStream next() throws FileUploadException, IOException;
+
+    /**
+     * Sets the maximum size of a single file. An {@link \
FileUploadByteCountLimitException} will be thrown, if there is an uploaded file, \
which is exceeding +     * this value. By default, this value will be copied from the \
{@link AbstractFileUpload#getFileSizeMax() FileUploadBase} object, however, the user \
may +     * replace the default value with a request specific value by invoking \
{@link #setFileSizeMax(long)} on this object, so there is no need to configure it +   \
* here. +     * <p>
+     * <em>Note:</em> Changing this value doesn't affect files, that have already \
been uploaded. +     * </p>
+     *
+     * @param fileSizeMax The maximum size of a single, uploaded file. The value -1 \
indicates "unlimited". +     */
+    void setFileSizeMax(long fileSizeMax);
+
+    /**
+     * Sets the maximum size of the complete HTTP request. A {@link \
SizeLimitExceededException} will be thrown, if the HTTP request will exceed this \
value. By +     * default, this value will be copied from the {@link \
AbstractFileUpload#getSizeMax() FileUploadBase} object, however, the user may replace \
the default +     * value with a request specific value by invoking {@link \
#setSizeMax(long)} on this object. +     * <p>
+     * <em>Note:</em> Setting the maximum size on this object will work only, if the \
iterator is not yet initialized. In other words: If the methods +     * {@link \
#hasNext()}, {@link #next()} have not yet been invoked. +     * </p>
+     *
+     * @param sizeMax The maximum size of the complete HTTP request. The value -1 \
indicates "unlimited". +     */
+    void setSizeMax(long sizeMax);
+}
diff --git a/src/main/java/org/apache/commons/fileupload2/FileItemStream.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemStream.java
 similarity index 59%
rename from src/main/java/org/apache/commons/fileupload2/FileItemStream.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemStream.java
 index cef170f..e3ec176 100644
--- a/src/main/java/org/apache/commons/fileupload2/FileItemStream.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileItemStream.java
 @@ -20,85 +20,69 @@ import java.io.IOException;
 import java.io.InputStream;

 /**
- * Provides access to a file or form item that was
- * received within a {@code multipart/form-data} POST request.
+ * Provides access to a file or form item that was received within a {@code \
                multipart/form-data} POST request.
  * <p>
  * The items contents are retrieved by calling {@link #openStream()}.
  * </p>
- * <p>Instances of this class are created by accessing the
- * iterator, returned by
- * {@link AbstractFileUpload#getItemIterator(RequestContext)}.
+ * <p>
+ * Instances of this class are created by accessing the iterator, returned by {@link \
                AbstractFileUpload#getItemIterator(RequestContext)}.
  * </p>
- * <p><em>Note</em>: There is an interaction between the iterator and
- * its associated instances of {@link FileItemStream}: By invoking
- * {@link java.util.Iterator#hasNext()} on the iterator, you discard all data,
- * which hasn't been read so far from the previous data.
+ * <p>
+ * <em>Note</em>: There is an interaction between the iterator and its associated \
instances of {@link FileItemStream}: By invoking + * {@link \
java.util.Iterator#hasNext()} on the iterator, you discard all data, which hasn't \
                been read so far from the previous data.
  * </p>
  */
 public interface FileItemStream extends FileItemHeadersSupport {

     /**
-     * This exception is thrown, if an attempt is made to read
-     * data from the {@link InputStream}, which has been returned
-     * by {@link FileItemStream#openStream()}, after
-     * {@link java.util.Iterator#hasNext()} has been invoked on the
-     * iterator, which created the {@link FileItemStream}.
+     * This exception is thrown, if an attempt is made to read data from the {@link \
InputStream}, which has been returned by +     * {@link FileItemStream#openStream()}, \
after {@link java.util.Iterator#hasNext()} has been invoked on the iterator, which \
created the +     * {@link FileItemStream}.
      */
     class ItemSkippedException extends IOException {

         /**
-         * The exceptions serial version UID, which is being used
-         * when serializing an exception instance.
+         * The exceptions serial version UID, which is being used when serializing \
                an exception instance.
          */
         private static final long serialVersionUID = 2;

     }

     /**
-     * Gets the content type passed by the browser or {@code null} if
-     * not defined.
+     * Gets the content type passed by the browser or {@code null} if not defined.
      *
-     * @return The content type passed by the browser or {@code null} if
-     *         not defined.
+     * @return The content type passed by the browser or {@code null} if not \
                defined.
      */
     String getContentType();

     /**
-     * Gets the name of the field in the multipart form corresponding to
-     * this file item.
+     * Gets the name of the field in the multipart form corresponding to this file \
                item.
      *
      * @return The name of the form field.
      */
     String getFieldName();

     /**
-     * Gets the original file name in the client's file system, as provided by
-     * the browser (or other client software). In most cases, this will be the
-     * base file name, without path information. However, some clients, such as
-     * the Opera browser, do include path information.
+     * Gets the original file name in the client's file system, as provided by the \
browser (or other client software). In most cases, this will be the base file +     * \
name, without path information. However, some clients, such as the Opera browser, do \
                include path information.
      *
      * @return The original file name in the client's file system.
      */
     String getName();

     /**
-     * Tests whether or not a {@code FileItem} instance represents
-     * a simple form field.
+     * Tests whether or not a {@code FileItem} instance represents a simple form \
                field.
      *
-     * @return {@code true} if the instance represents a simple form
-     *         field; {@code false} if it represents an uploaded file.
+     * @return {@code true} if the instance represents a simple form field; {@code \
                false} if it represents an uploaded file.
      */
     boolean isFormField();

     /**
-     * Opens an {@link InputStream}, which allows to read the
-     * items contents.
+     * Opens an {@link InputStream}, which allows to read the items contents.
      *
-     * @return The input stream, from which the items data may
-     *   be read.
-     * @throws IllegalStateException The method was already invoked on
-     * this item. It is not possible to recreate the data stream.
-     * @throws IOException An I/O error occurred.
+     * @return The input stream, from which the items data may be read.
+     * @throws IllegalStateException The method was already invoked on this item. It \
is not possible to recreate the data stream. +     * @throws IOException           An \
                I/O error occurred.
      * @see ItemSkippedException
      */
     InputStream openStream() throws IOException;
diff --git a/src/main/java/org/apache/commons/fileupload2/FileUpload.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileUpload.java
 similarity index 72%
rename from src/main/java/org/apache/commons/fileupload2/FileUpload.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileUpload.java
 index 6a8e05a..c177765 100644
--- a/src/main/java/org/apache/commons/fileupload2/FileUpload.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileUpload.java
 @@ -17,18 +17,19 @@
 package org.apache.commons.fileupload2;

 /**
- * <p>High level API for processing file uploads.</p>
+ * <p>
+ * High level API for processing file uploads.
+ * </p>
  *
- * <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 org.apache.commons.fileupload2.FileItem FileItems} associated
- * with a given HTML widget.</p>
+ * <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 \
org.apache.commons.fileupload2.FileItem FileItems} 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>
+ * <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>
  */
 public class FileUpload extends AbstractFileUpload {

@@ -40,9 +41,7 @@ public class FileUpload extends AbstractFileUpload {
     /**
      * Constructs an uninitialized instance of this class.
      *
-     * A factory must be
-     * configured, using {@code setFileItemFactory()}, before attempting
-     * to parse requests.
+     * A factory must be configured, using {@code setFileItemFactory()}, before \
                attempting to parse requests.
      *
      * @see #FileUpload(FileItemFactory)
      */
@@ -50,8 +49,7 @@ public class FileUpload extends AbstractFileUpload {
     }

     /**
-     * Constructs an instance of this class which uses the supplied factory to
-     * create {@code FileItem} instances.
+     * Constructs an instance of this class which uses the supplied factory to \
                create {@code FileItem} instances.
      *
      * @see #FileUpload()
      * @param fileItemFactory The factory to use for creating file items.
diff --git a/src/main/java/org/apache/commons/fileupload2/FileUploadException.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileUploadException.java
 similarity index 100%
rename from src/main/java/org/apache/commons/fileupload2/FileUploadException.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/FileUploadException.java
                
diff --git a/src/main/java/org/apache/commons/fileupload2/InvalidFileNameException.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/InvalidFileNameException.java
 similarity index 71%
rename from src/main/java/org/apache/commons/fileupload2/InvalidFileNameException.java
 rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/InvalidFileNameException.java
 index 3937ab6..064238c 100644
--- a/src/main/java/org/apache/commons/fileupload2/InvalidFileNameException.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/InvalidFileNameException.java
 @@ -17,20 +17,14 @@
 package org.apache.commons.fileupload2;

 /**
- * Signals an invalid file name.
- * A file name is invalid, if it contains a NUL character.
- * Attackers might use this to circumvent security checks:
- * For example, a malicious user might upload a file with the name
- * "foo.exe\0.png". This file name might pass security checks (i.e.
- * checks for the extension ".png"), while, depending on the underlying
- * C library, it might create a file named "foo.exe", as the NUL
- * character is the string terminator in C.
+ * Signals an invalid file name. A file name is invalid, if it contains a NUL \
character. Attackers might use this to circumvent security checks: For example, a + * \
malicious user might upload a file with the name "foo.exe\0.png". This file name \
might pass security checks (i.e. checks for the extension ".png"), while, + * \
depending on the underlying C library, it might create a file named "foo.exe", as the \
                NUL character is the string terminator in C.
  */
 public class InvalidFileNameException extends RuntimeException {

     /**
-     * Serial version UID, being used, if the exception
-     * is serialized.
+     * Serial version UID, being used, if the exception is serialized.
      */
     private static final long serialVersionUID = 2;

@@ -42,7 +36,7 @@ public class InvalidFileNameException extends RuntimeException {
     /**
      * Constructs a new instance.
      *
-     * @param name The file name causing the exception.
+     * @param name    The file name causing the exception.
      * @param message A human readable error message.
      */
     public InvalidFileNameException(final String name, final String message) {
diff --git a/src/main/java/org/apache/commons/fileupload2/MultipartStream.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/MultipartStream.java
 similarity index 97%
rename from src/main/java/org/apache/commons/fileupload2/MultipartStream.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/MultipartStream.java
 index 9d9613a..da7b078 100644
--- a/src/main/java/org/apache/commons/fileupload2/MultipartStream.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/MultipartStream.java
 @@ -16,7 +16,6 @@
  */
 package org.apache.commons.fileupload2;

-
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -59,6 +58,7 @@ import org.apache.commons.io.output.NullOutputStream;
  * <p>
  * Here is an example of usage of this class:
  * </p>
+ *
  * <pre>
  * try {
  *     MultipartStream multipartStream = new MultipartStream(input, boundary);
@@ -398,8 +398,8 @@ public class MultipartStream {
         /**
          * Creates a new instance with the given listener and content length.
          *
-         * @param progressListener      The listener to invoke.
-         * @param contentLength The expected content length.
+         * @param progressListener The listener to invoke.
+         * @param contentLength    The expected content length.
          */
         public ProgressNotifier(final ProgressListener progressListener, final long \
contentLength) {  this.progressListener = progressListener;
@@ -557,18 +557,17 @@ public class MultipartStream {
      */
     private final ProgressNotifier notifier;

-
-
     /**
      * Constructs a {@code MultipartStream} with a custom size buffer.
      * <p>
      * Note that the buffer must be at least big enough to contain the boundary \
                string, plus 4 characters for CR/LF and double dash, plus at least \
                one byte of
      * data. Too small a buffer size setting will degrade performance.
      * </p>
-     * @param input     The {@code InputStream} to serve as a data source.
-     * @param boundary  The token used for dividing the stream into {@code \
                encapsulations}.
-     * @param bufferSize   The size of the buffer to be used, in bytes.
-     * @param notifier The notifier, which is used for calling the progress \
listener, if any. +     *
+     * @param input      The {@code InputStream} to serve as a data source.
+     * @param boundary   The token used for dividing the stream into {@code \
encapsulations}. +     * @param bufferSize The size of the buffer to be used, in \
bytes. +     * @param notifier   The notifier, which is used for calling the progress \
                listener, if any.
      * @throws IllegalArgumentException If the buffer size is too small.
      * @since 1.3.1
      */
@@ -604,8 +603,8 @@ public class MultipartStream {
     /**
      * Constructs a {@code MultipartStream} with a default size buffer.
      *
-     * @param input     The {@code InputStream} to serve as a data source.
-     * @param boundary  The token used for dividing the stream into {@code \
encapsulations}. +     * @param input            The {@code InputStream} to serve as \
a data source. +     * @param boundary         The token used for dividing the stream \
                into {@code encapsulations}.
      * @param progressNotifier An object for calling the progress listener, if any.
      * @see #MultipartStream(InputStream, byte[], int, ProgressNotifier)
      */
@@ -642,6 +641,7 @@ public class MultipartStream {
      * <p>
      * Use this method to skip encapsulations you don't need or don't understand.
      * </p>
+     *
      * @return The amount of data discarded.
      * @throws MalformedStreamException if the stream ends unexpectedly.
      * @throws IOException              if an i/o error occurs.
@@ -692,8 +692,8 @@ public class MultipartStream {
     }

     /**
-     * Gets the character encoding used when reading the headers of an individual \
                part. When not specified, or {@code null}, the platform default \
                encoding
-     * is used.
+     * Gets the character encoding used when reading the headers of an individual \
part. When not specified, or {@code null}, the platform default encoding is +     * \
                used.
      *
      * @return The encoding used to read part headers.
      */
@@ -716,6 +716,7 @@ public class MultipartStream {
      * Arbitrary large amounts of data can be processed by this method using a \
                constant size buffer. (see
      * {@link #MultipartStream(InputStream,byte[],int, \
                MultipartStream.ProgressNotifier) constructor}).
      * </p>
+     *
      * @param output The {@code Stream} to write data into. May be null, in which \
                case this method is equivalent to {@link #discardBodyData()}.
      * @return the amount of data written.
      * @throws MalformedStreamException if the stream ends unexpectedly.
@@ -798,6 +799,7 @@ public class MultipartStream {
      * <p>
      * <strong>TODO</strong> allow limiting maximum header size to protect against \
                abuse.
      * </p>
+     *
      * @return The {@code header-part} of the current encapsulation.
      * @throws FileUploadSizeException  if the bytes read from the stream exceeded \
                the size limits.
      * @throws MalformedStreamException if the stream ends unexpectedly.
@@ -856,6 +858,7 @@ public class MultipartStream {
      * <p>
      * Restoring the parent stream boundary token after processing of a nested \
                stream is left to the application.
      * </p>
+     *
      * @param boundary The boundary to be used for parsing of the nested stream.
      * @throws FileUploadBoundaryException if the {@code boundary} has a different \
                length than the one being currently parsed.
      */
@@ -868,8 +871,8 @@ public class MultipartStream {
     }

     /**
-     * Sets the character encoding to be used when reading the headers of individual \
                parts. When not specified, or {@code null}, the platform default
-     * encoding is used.
+     * Sets the character encoding to be used when reading the headers of individual \
parts. When not specified, or {@code null}, the platform default encoding +     * is \
                used.
      *
      * @param encoding The encoding used to read part headers.
      */
diff --git a/src/main/java/org/apache/commons/fileupload2/ParameterParser.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/ParameterParser.java
 similarity index 76%
rename from src/main/java/org/apache/commons/fileupload2/ParameterParser.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/ParameterParser.java
 index cf7e848..64770ef 100644
--- a/src/main/java/org/apache/commons/fileupload2/ParameterParser.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/ParameterParser.java
 @@ -27,9 +27,8 @@ import org.apache.commons.fileupload2.util.mime.RFC2231Utility;
 /**
  * A simple parser intended to parse sequences of name/value pairs.
  * <p>
- * Parameter values are expected to be enclosed in quotes if they
- * contain unsafe characters, such as '=' characters or separators.
- * Parameter values are optional and can be omitted.
+ * Parameter values are expected to be enclosed in quotes if they contain unsafe \
characters, such as '=' characters or separators. Parameter values are optional + * \
                and can be omitted.
  * </p>
  * <p>
  * {@code param1 = value; param2 = "anything goes; really"; param3}
@@ -74,12 +73,9 @@ public class ParameterParser {
     }

     /**
-     * A helper method to process the parsed token. This method removes
-     * leading and trailing blanks as well as enclosing quotation marks,
-     * when necessary.
+     * A helper method to process the parsed token. This method removes leading and \
                trailing blanks as well as enclosing quotation marks, when necessary.
      *
-     * @param quoted {@code true} if quotation marks are expected,
-     *               {@code false} otherwise.
+     * @param quoted {@code true} if quotation marks are expected, {@code false} \
                otherwise.
      * @return the token
      */
     private String getToken(final boolean quoted) {
@@ -92,10 +88,7 @@ public class ParameterParser {
             i2--;
         }
         // Strip away quotation marks if necessary
-        if (quoted
-            && ((i2 - i1) >= 2)
-            && (chars[i1] == '"')
-            && (chars[i2 - 1] == '"')) {
+        if (quoted && ((i2 - i1) >= 2) && (chars[i1] == '"') && (chars[i2 - 1] == \
'"')) {  i1++;
             i2--;
         }
@@ -109,20 +102,16 @@ public class ParameterParser {
     /**
      * Tests if there any characters left to parse.
      *
-     * @return {@code true} if there are unparsed characters,
-     *         {@code false} otherwise.
+     * @return {@code true} if there are unparsed characters, {@code false} \
                otherwise.
      */
     private boolean hasChar() {
         return this.pos < this.len;
     }

     /**
-     * Tests {@code true} if parameter names are to be converted to lower
-     * case when name/value pairs are parsed.
+     * Tests {@code true} if parameter names are to be converted to lower case when \
                name/value pairs are parsed.
      *
-     * @return {@code true} if parameter names are to be
-     * converted to lower case when name/value pairs are parsed.
-     * Otherwise returns {@code false}
+     * @return {@code true} if parameter names are to be converted to lower case \
                when name/value pairs are parsed. Otherwise returns {@code false}
      */
     public boolean isLowerCaseNames() {
         return this.lowerCaseNames;
@@ -131,10 +120,9 @@ public class ParameterParser {
     /**
      * Tests if the given character is present in the array of characters.
      *
-     * @param ch the character to test for presence in the array of characters
+     * @param ch      the character to test for presence in the array of characters
      * @param charray the array of characters to test against
-     * @return {@code true} if the character is present in the array of
-     *   characters, {@code false} otherwise.
+     * @return {@code true} if the character is present in the array of characters, \
                {@code false} otherwise.
      */
     private boolean isOneOf(final char ch, final char[] charray) {
         boolean result = false;
@@ -148,11 +136,9 @@ public class ParameterParser {
     }

     /**
-     * Extracts a map of name/value pairs from the given array of
-     * characters. Names are expected to be unique.
+     * Extracts a map of name/value pairs from the given array of characters. Names \
                are expected to be unique.
      *
-     * @param charArray the array of characters that contains a sequence of
-     * name/value pairs
+     * @param charArray the array of characters that contains a sequence of \
                name/value pairs
      * @param separator the name/value pairs separator
      * @return a map of name/value pairs
      */
@@ -164,21 +150,15 @@ public class ParameterParser {
     }

     /**
-     * Extracts a map of name/value pairs from the given array of
-     * characters. Names are expected to be unique.
+     * Extracts a map of name/value pairs from the given array of characters. Names \
                are expected to be unique.
      *
-     * @param charArray the array of characters that contains a sequence of
-     * name/value pairs
-     * @param offset - the initial offset.
-     * @param length - the length.
+     * @param charArray the array of characters that contains a sequence of \
name/value pairs +     * @param offset    - the initial offset.
+     * @param length    - the length.
      * @param separator the name/value pairs separator
      * @return a map of name/value pairs
      */
-    public Map<String, String> parse(
-        final char[] charArray,
-        final int offset,
-        final int length,
-        final char separator) {
+    public Map<String, String> parse(final char[] charArray, final int offset, final \
int length, final char separator) {

         if (charArray == null) {
             return new HashMap<>();
@@ -191,18 +171,15 @@ public class ParameterParser {
         String paramName;
         String paramValue;
         while (hasChar()) {
-            paramName = parseToken(new char[] {
-                    '=', separator });
+            paramName = parseToken(new char[] { '=', separator });
             paramValue = null;
             if (hasChar() && (charArray[pos] == '=')) {
                 pos++; // skip '='
-                paramValue = parseQuotedToken(new char[] {
-                        separator });
+                paramValue = parseQuotedToken(new char[] { separator });

                 if (paramValue != null) {
                     try {
-                        paramValue = RFC2231Utility.hasEncodedValue(paramName) ? \
                RFC2231Utility.decodeText(paramValue)
-                                : MimeUtility.decodeText(paramValue);
+                        paramValue = RFC2231Utility.hasEncodedValue(paramName) ? \
RFC2231Utility.decodeText(paramValue) : MimeUtility.decodeText(paramValue);  } catch \
(final UnsupportedEncodingException e) {  // let's keep the original value in this \
case  }
@@ -223,10 +200,9 @@ public class ParameterParser {
     }

     /**
-     * Extracts a map of name/value pairs from the given string. Names are
-     * expected to be unique.
+     * Extracts a map of name/value pairs from the given string. Names are expected \
                to be unique.
      *
-     * @param str the string that contains a sequence of name/value pairs
+     * @param str       the string that contains a sequence of name/value pairs
      * @param separator the name/value pairs separator
      * @return a map of name/value pairs
      */
@@ -238,11 +214,10 @@ public class ParameterParser {
     }

     /**
-     * Extracts a map of name/value pairs from the given string. Names are
-     * expected to be unique. Multiple separators may be specified and
-     * the earliest found in the input string is used.
+     * Extracts a map of name/value pairs from the given string. Names are expected \
to be unique. Multiple separators may be specified and the earliest found in +     * \
                the input string is used.
      *
-     * @param str the string that contains a sequence of name/value pairs
+     * @param str        the string that contains a sequence of name/value pairs
      * @param separators the name/value pairs separators
      * @return a map of name/value pairs
      */
@@ -265,12 +240,9 @@ public class ParameterParser {
     }

     /**
-     * Parses out a token until any of the given terminators
-     * is encountered outside the quotation marks.
+     * Parses out a token until any of the given terminators is encountered outside \
                the quotation marks.
      *
-     * @param terminators the array of terminating characters. Any of these
-     * characters when encountered outside the quotation marks signify the end
-     * of the token
+     * @param terminators the array of terminating characters. Any of these \
                characters when encountered outside the quotation marks signify the \
                end of the token
      * @return the token
      */
     private String parseQuotedToken(final char[] terminators) {
@@ -296,11 +268,9 @@ public class ParameterParser {
     }

     /**
-     * Parses out a token until any of the given terminators
-     * is encountered.
+     * Parses out a token until any of the given terminators is encountered.
      *
-     * @param terminators the array of terminating characters. Any of these
-     * characters when encountered signify the end of the token
+     * @param terminators the array of terminating characters. Any of these \
                characters when encountered signify the end of the token
      * @return the token
      */
     private String parseToken(final char[] terminators) {
@@ -319,12 +289,9 @@ public class ParameterParser {
     }

     /**
-     * Sets the flag if parameter names are to be converted to lower case when
-     * name/value pairs are parsed.
+     * Sets the flag if parameter names are to be converted to lower case when \
                name/value pairs are parsed.
      *
-     * @param b {@code true} if parameter names are to be
-     * converted to lower case when name/value pairs are parsed.
-     * {@code false} otherwise.
+     * @param b {@code true} if parameter names are to be converted to lower case \
                when name/value pairs are parsed. {@code false} otherwise.
      */
     public void setLowerCaseNames(final boolean b) {
         this.lowerCaseNames = b;
diff --git a/src/main/java/org/apache/commons/fileupload2/ProgressListener.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/ProgressListener.java
 similarity index 100%
rename from src/main/java/org/apache/commons/fileupload2/ProgressListener.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/ProgressListener.java
                
diff --git a/src/main/java/org/apache/commons/fileupload2/RequestContext.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/RequestContext.java
 similarity index 99%
rename from src/main/java/org/apache/commons/fileupload2/RequestContext.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/RequestContext.java
 index 99f9070..66c44bb 100644
--- a/src/main/java/org/apache/commons/fileupload2/RequestContext.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/RequestContext.java
 @@ -24,6 +24,7 @@ import java.io.InputStream;
  * <p>
  * This interface should be implemented for each type of request that may be handled \
                by FileUpload, such as servlets and portlets.
  * </p>
+ *
  * @since 1.1
  */
 public interface RequestContext {
diff --git a/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItem.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItem.java
 similarity index 70%
rename from src/main/java/org/apache/commons/fileupload2/disk/DiskFileItem.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItem.java
 index 9974e02..088bef5 100644
--- a/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItem.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItem.java
 @@ -1,620 +1,557 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2.disk;
-
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UncheckedIOException;
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.commons.fileupload2.FileItem;
-import org.apache.commons.fileupload2.FileItemHeaders;
-import org.apache.commons.fileupload2.FileUploadException;
-import org.apache.commons.fileupload2.InvalidFileNameException;
-import org.apache.commons.fileupload2.ParameterParser;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.output.DeferredFileOutputStream;
-
-/**
- * The default implementation of the
- * {@link org.apache.commons.fileupload2.FileItem FileItem} interface.
- *
- * <p>
- * After retrieving an instance of this class from a {@link
- * DiskFileItemFactory} instance (see
- * {@link org.apache.commons.fileupload2.servlet.ServletFileUpload
- * #parseRequest(javax.servlet.http.HttpServletRequest)}), you may
- * either request all contents of file at once using {@link #get()} or
- * request an {@link java.io.InputStream InputStream} with
- * {@link #getInputStream()} and process the file without attempting to load
- * it into memory, which may come handy with large files.
- * </p>
- * <p>
- * Temporary files, which are created for file items, should be
- * deleted later on. The best way to do this is using a
- * {@link org.apache.commons.io.FileCleaningTracker}, which you can set on the
- * {@link DiskFileItemFactory}. However, if you do use such a tracker,
- * then you must consider the following: Temporary files are automatically
- * deleted as soon as they are no longer needed. (More precisely, when the
- * corresponding instance of {@link java.io.File} is garbage collected.)
- * This is done by the so-called reaper thread, which is started and stopped
- * automatically by the {@link org.apache.commons.io.FileCleaningTracker} when
- * there are files to be tracked.
- * It might make sense to terminate that thread, for example, if
- * your web application ends. See the section on "Resource cleanup"
- * in the users guide of commons-fileupload.
- * </p>
- *
- * @since 1.1
- */
-public class DiskFileItem implements FileItem {
-
-    /**
-     * Default content charset to be used when no explicit charset
-     * parameter is provided by the sender. Media subtypes of the
-     * "text" type are defined to have a default charset value of
-     * "ISO-8859-1" when received via HTTP.
-     */
-    public static final String DEFAULT_CHARSET = StandardCharsets.ISO_8859_1.name();
-
-    /**
-     * UID used in unique file name generation.
-     */
-    private static final String UID = UUID.randomUUID().toString().replace('-', \
                '_');
-
-    /**
-     * Counter used in unique identifier generation.
-     */
-    private static final AtomicInteger COUNTER = new AtomicInteger(0);
-
-    /**
-     * Returns an identifier that is unique within the class loader used to
-     * load this class, but does not have random-like appearance.
-     *
-     * @return A String with the non-random looking instance identifier.
-     */
-    private static String getUniqueId() {
-        final int limit = 100000000;
-        final int current = COUNTER.getAndIncrement();
-        String id = Integer.toString(current);
-
-        // If you manage to get more than 100 million of ids, you'll
-        // start getting ids longer than 8 characters.
-        if (current < limit) {
-            id = ("00000000" + id).substring(id.length());
-        }
-        return id;
-    }
-
-    /**
-     * The name of the form field as provided by the browser.
-     */
-    private String fieldName;
-
-    /**
-     * The content type passed by the browser, or {@code null} if
-     * not defined.
-     */
-    private final String contentType;
-
-    /**
-     * Whether or not this item is a simple form field.
-     */
-    private boolean isFormField;
-
-    /**
-     * The original file name in the user's file system.
-     */
-    private final String fileName;
-
-    /**
-     * The size of the item, in bytes. This is used to cache the size when a
-     * file item is moved from its original location.
-     */
-    private long size = -1;
-
-    /**
-     * The threshold above which uploads will be stored on disk.
-     */
-    private final int sizeThreshold;
-
-    /**
-     * The directory in which uploaded files will be stored, if stored on disk.
-     */
-    private final File repository;
-
-    /**
-     * Cached contents of the file.
-     */
-    private byte[] cachedContent;
-
-    /**
-     * Output stream for this item.
-     */
-    private transient DeferredFileOutputStream dfos;
-
-    /**
-     * The temporary file to use.
-     */
-    private transient File tempFile;
-
-    /**
-     * The file items headers.
-     */
-    private FileItemHeaders headers;
-
-    /**
-     * Default content charset to be used when no explicit charset
-     * parameter is provided by the sender.
-     */
-    private String defaultCharset = DEFAULT_CHARSET;
-
-    /**
-     * Constructs a new {@code DiskFileItem} instance.
-     *
-     * @param fieldName     The name of the form field.
-     * @param contentType   The content type passed by the browser or
-     *                      {@code null} if not specified.
-     * @param isFormField   Whether or not this item is a plain form field, as
-     *                      opposed to a file upload.
-     * @param fileName      The original file name in the user's file system, or
-     *                      {@code null} if not specified.
-     * @param sizeThreshold The threshold, in bytes, below which items will be
-     *                      retained in memory and above which they will be
-     *                      stored as a file.
-     * @param repository    The data repository, which is the directory in
-     *                      which files will be created, should the item size
-     *                      exceed the threshold.
-     */
-    public DiskFileItem(final String fieldName,
-            final String contentType, final boolean isFormField, final String \
                fileName,
-            final int sizeThreshold, final File repository) {
-        this.fieldName = fieldName;
-        this.contentType = contentType;
-        this.isFormField = isFormField;
-        this.fileName = fileName;
-        this.sizeThreshold = sizeThreshold;
-        this.repository = repository;
-    }
-
-    /**
-     * Deletes the underlying storage for a file item, including deleting any \
                associated temporary disk file.
-     * This method can be used to ensure that this is done at an earlier time, thus \
                preserving system resources.
-     */
-    @Override
-    public void delete() {
-        cachedContent = null;
-        final File outputFile = getStoreLocation();
-        if (outputFile != null && !isInMemory() && outputFile.exists()) {
-            if (!outputFile.delete()) {
-                final String desc = "Cannot delete " + outputFile.toString();
-                throw new UncheckedIOException(desc, new IOException(desc));
-            }
-        }
-    }
-
-    /**
-     * Gets the contents of the file as an array of bytes.  If the
-     * contents of the file were not yet cached in memory, they will be
-     * loaded from the disk storage and cached.
-     *
-     * @return The contents of the file as an array of bytes
-     * or {@code null} if the data cannot be read
-     * @throws UncheckedIOException if an I/O error occurs
-     */
-    @Override
-    public byte[] get() throws UncheckedIOException {
-        if (isInMemory()) {
-            if (cachedContent == null && dfos != null) {
-                cachedContent = dfos.getData();
-            }
-            return cachedContent != null ? cachedContent.clone() : new byte[0];
-        }
-
-        final byte[] fileData = new byte[(int) getSize()];
-
-        try (InputStream fis = Files.newInputStream(dfos.getFile().toPath())) {
-            IOUtils.readFully(fis, fileData);
-        } catch (final IOException e) {
-            throw new UncheckedIOException(e);
-        }
-        return fileData;
-    }
-
-    /**
-     * Gets the content charset passed by the agent or {@code null} if
-     * not defined.
-     *
-     * @return The content charset passed by the agent or {@code null} if
-     *         not defined.
-     */
-    public String getCharSet() {
-        final ParameterParser parser = new ParameterParser();
-        parser.setLowerCaseNames(true);
-        // Parameter parser can handle null input
-        final Map<String, String> params = parser.parse(getContentType(), ';');
-        return params.get("charset");
-    }
-
-    /**
-     * Gets the content type passed by the agent or {@code null} if
-     * not defined.
-     *
-     * @return The content type passed by the agent or {@code null} if
-     *         not defined.
-     */
-    @Override
-    public String getContentType() {
-        return contentType;
-    }
-
-    /**
-     * Gets the default charset for use when no explicit charset
-     * parameter is provided by the sender.
-     *
-     * @return the default charset
-     */
-    public String getDefaultCharset() {
-        return defaultCharset;
-    }
-
-    /**
-     * Gets the name of the field in the multipart form corresponding to
-     * this file item.
-     *
-     * @return The name of the form field.
-     * @see #setFieldName(String)
-     */
-    @Override
-    public String getFieldName() {
-        return fieldName;
-    }
-
-    /**
-     * Gets the file item headers.
-     *
-     * @return The file items headers.
-     */
-    @Override
-    public FileItemHeaders getHeaders() {
-        return headers;
-    }
-
-    /**
-     * Gets an {@link java.io.InputStream InputStream} that can be
-     * used to retrieve the contents of the file.
-     *
-     * @return An {@link java.io.InputStream InputStream} that can be
-     *         used to retrieve the contents of the file.
-     * @throws IOException if an error occurs.
-     */
-    @Override
-    public InputStream getInputStream()
-        throws IOException {
-        if (!isInMemory()) {
-            return Files.newInputStream(dfos.getFile().toPath());
-        }
-
-        if (cachedContent == null) {
-            cachedContent = dfos.getData();
-        }
-        return new ByteArrayInputStream(cachedContent);
-    }
-
-    /**
-     * Gets the original file name in the client's file system.
-     *
-     * @return The original file name in the client's file system.
-     * @throws org.apache.commons.fileupload2.InvalidFileNameException The file name \
                contains a NUL character,
-     *   which might be an indicator of a security attack. If you intend to
-     *   use the file name anyways, catch the exception and use
-     *   {@link org.apache.commons.fileupload2.InvalidFileNameException#getName()}.
-     */
-    @Override
-    public String getName() {
-        return DiskFileItem.checkFileName(fileName);
-    }
-
-    /**
-     * Gets an {@link java.io.OutputStream OutputStream} that can
-     * be used for storing the contents of the file.
-     *
-     * @return An {@link java.io.OutputStream OutputStream} that can be used
-     *         for storing the contents of the file.
-     */
-    @Override
-    public OutputStream getOutputStream() {
-        if (dfos == null) {
-            final File outputFile = getTempFile();
-            dfos = new DeferredFileOutputStream(sizeThreshold, outputFile);
-        }
-        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 java.io.File} object 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 java.io.File#renameTo(java.io.File)} to
-     * move the file to new location without copying the data, if the
-     * source and destination locations reside within the same logical
-     * volume.
-     *
-     * @return The data file, or {@code null} if the data is stored in
-     *         memory.
-     */
-    public File getStoreLocation() {
-        if (dfos == null) {
-            return null;
-        }
-        if (isInMemory()) {
-            return null;
-        }
-        return dfos.getFile();
-    }
-
-    /**
-     * 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>
-     * <b>TODO</b> Consider making this method throw UnsupportedEncodingException.
-     * </p>
-     * @return The contents of the file, as a string.
-     */
-    @Override
-    public String getString() {
-        try {
-            final byte[] rawData = get();
-            String charset = getCharSet();
-            if (charset == null) {
-                charset = defaultCharset;
-            }
-            return new String(rawData, charset);
-        } catch (final IOException e) {
-            return "";
-        }
-    }
-
-    /**
-     * Gets the contents of the file as a String, using the specified
-     * encoding.  This method uses {@link #get()} to retrieve the
-     * contents of the file.
-     *
-     * @param charset The charset to use.
-     * @return The contents of the file, as a string.
-     * @throws UnsupportedEncodingException if the requested character
-     *                                      encoding is not available.
-     */
-    @Override
-    public String getString(final String charset)
-        throws UnsupportedEncodingException, IOException {
-        return new String(get(), charset);
-    }
-
-    /**
-     * Creates and returns a {@link java.io.File File} representing a uniquely
-     * named temporary file in the configured repository path. The lifetime of
-     * the file is tied to the lifetime of the {@code FileItem} instance;
-     * the file will be deleted when the instance is garbage collected.
-     * <p>
-     * <b>Note: Subclasses that override this method must ensure that they return \
                the
-     * same File each time.</b>
-     * </p>
-     * @return The {@link java.io.File File} to be used for temporary storage.
-     */
-    protected File getTempFile() {
-        if (tempFile == null) {
-            File tempDir = repository;
-            if (tempDir == null) {
-                tempDir = FileUtils.getTempDirectory();
-            }
-            final String tempFileName = String.format("upload_%s_%s.tmp", UID, \
                getUniqueId());
-            tempFile = new File(tempDir, tempFileName);
-        }
-        return tempFile;
-    }
-
-    /**
-     * Tests whether or not a {@code FileItem} instance represents
-     * a simple form field.
-     *
-     * @return {@code true} if the instance represents a simple form
-     *         field; {@code false} if it represents an uploaded file.
-     * @see #setFormField(boolean)
-     */
-    @Override
-    public boolean isFormField() {
-        return isFormField;
-    }
-
-    /**
-     * Provides a hint as to whether or not the file contents will be read
-     * from memory.
-     *
-     * @return {@code true} if the file contents will be read
-     *         from memory; {@code false} otherwise.
-     */
-    @Override
-    public boolean isInMemory() {
-        if (cachedContent != null) {
-            return true;
-        }
-        return dfos.isInMemory();
-    }
-
-    /**
-     * Sets the default charset for use when no explicit charset
-     * parameter is provided by the sender.
-     *
-     * @param charset the default charset
-     */
-    public void setDefaultCharset(final String charset) {
-        defaultCharset = charset;
-    }
-
-    /**
-     * Sets the field name used to reference this file item.
-     *
-     * @param fieldName The name of the form field.
-     * @see #getFieldName()
-     */
-    @Override
-    public void setFieldName(final String fieldName) {
-        this.fieldName = fieldName;
-    }
-
-    /**
-     * Specifies 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.
-     * @see #isFormField()
-     */
-    @Override
-    public void setFormField(final boolean state) {
-        isFormField = state;
-    }
-
-    /**
-     * Sets the file item headers.
-     *
-     * @param headers The file items headers.
-     */
-    @Override
-    public void setHeaders(final FileItemHeaders headers) {
-        this.headers = headers;
-    }
-
-    /**
-     * Returns a string representation of this object.
-     *
-     * @return a string representation of this object.
-     */
-    @Override
-    public String toString() {
-        return String.format("name=%s, StoreLocation=%s, size=%s bytes, \
isFormField=%s, FieldName=%s", getName(), getStoreLocation(), getSize(), \
                isFormField(),
-                getFieldName());
-    }
-
-    /**
-     * Writes an uploaded item to disk.
-     * <p>
-     * The client code is not concerned with whether or not the item is stored in \
                memory, or on disk in a temporary location. They just want to write \
                the
-     * uploaded item to a file.
-     * </p>
-     * <p>
-     * This implementation first attempts to rename the uploaded item to the \
                specified destination file, if the item was originally written to \
                disk. Otherwise,
-     * the data will be copied to the specified file.
-     * </p>
-     * <p>
-     * This method is only guaranteed to work <em>once</em>, the first time it is \
                invoked for a particular item. This is because, in the event that the \
                method
-     * renames a temporary file, that file will no longer be available to copy or \
                rename again at a later time.
-     * </p>
-     * @param file The {@code File} into which the uploaded item should be stored.
-     * @throws IOException if an error occurs.
-     */
-    @Override
-    public void write(final File file) throws IOException {
-        if (isInMemory()) {
-            try (OutputStream fout = Files.newOutputStream(file.toPath())) {
-                fout.write(get());
-            } catch (final IOException e) {
-                throw new IOException("Unexpected output data", e);
-            }
-        } else {
-            final File outputFile = getStoreLocation();
-            if (outputFile == null) {
-                /*
-                 * For whatever reason we cannot write the file to disk.
-                 */
-                throw new FileUploadException("Cannot write uploaded file to \
                disk.");
-            }
-            // Save the length of the file
-            size = outputFile.length();
-            /*
-             * The uploaded file is being stored on disk in a temporary location so \
                move it to the desired file.
-             */
-            if (file.exists() && !file.delete()) {
-                throw new FileUploadException("Cannot write uploaded file to \
                disk.");
-            }
-            FileUtils.moveFile(outputFile, file);
-        }
-    }
-
-    /**
-     * Checks, whether the given file name is valid in the sense,
-     * that it doesn't contain any NUL characters. If the file name
-     * is valid, it will be returned without any modifications. Otherwise,
-     * an {@link InvalidFileNameException} is raised.
-     *
-     * @param fileName The file name to check
-     * @return Unmodified file name, if valid.
-     * @throws InvalidFileNameException The file name was found to be invalid.
-     */
-    public static String checkFileName(final String fileName) {
-        if (fileName != null  &&  fileName.indexOf('\u0000') != -1) {
-            // fileName.replace("\u0000", "\\0")
-            final StringBuilder sb = new StringBuilder();
-            for (int i = 0;  i < fileName.length();  i++) {
-                final char c = fileName.charAt(i);
-                switch (c) {
-                    case 0:
-                        sb.append("\\0");
-                        break;
-                    default:
-                        sb.append(c);
-                        break;
-                }
-            }
-            throw new InvalidFileNameException(fileName,
-                    "Invalid file name: " + sb);
-        }
-        return fileName;
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2.disk;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.commons.fileupload2.FileItem;
+import org.apache.commons.fileupload2.FileItemHeaders;
+import org.apache.commons.fileupload2.FileUploadException;
+import org.apache.commons.fileupload2.InvalidFileNameException;
+import org.apache.commons.fileupload2.ParameterParser;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.DeferredFileOutputStream;
+
+/**
+ * The default implementation of the {@link org.apache.commons.fileupload2.FileItem \
FileItem} interface. + *
+ * <p>
+ * After retrieving an instance of this class from a {@link DiskFileItemFactory} \
instance (see {@code org.apache.commons.fileupload2.servlet.ServletFileUpload + * \
#parseRequest(javax.servlet.http.HttpServletRequest)}), you may either request all \
contents of file at once using {@link #get()} or request an + * {@link \
java.io.InputStream InputStream} with {@link #getInputStream()} and process the file \
without attempting to load it into memory, which may come handy + * with large files.
+ * </p>
+ * <p>
+ * Temporary files, which are created for file items, should be deleted later on. \
The best way to do this is using a + * {@link \
org.apache.commons.io.FileCleaningTracker}, which you can set on the {@link \
DiskFileItemFactory}. However, if you do use such a tracker, then you must + * \
consider the following: Temporary files are automatically deleted as soon as they are \
no longer needed. (More precisely, when the corresponding instance of + * {@link \
java.io.File} is garbage collected.) This is done by the so-called reaper thread, \
which is started and stopped automatically by the + * {@link \
org.apache.commons.io.FileCleaningTracker} when there are files to be tracked. It \
might make sense to terminate that thread, for example, if your web + * application \
ends. See the section on "Resource cleanup" in the users guide of Commons FileUpload. \
+ * </p> + *
+ * @since 1.1
+ */
+public class DiskFileItem implements FileItem {
+
+    /**
+     * Default content charset to be used when no explicit charset parameter is \
provided by the sender. Media subtypes of the "text" type are defined to have a +     \
* default charset value of "ISO-8859-1" when received via HTTP. +     */
+    public static final String DEFAULT_CHARSET = StandardCharsets.ISO_8859_1.name();
+
+    /**
+     * UID used in unique file name generation.
+     */
+    private static final String UID = UUID.randomUUID().toString().replace('-', \
'_'); +
+    /**
+     * Counter used in unique identifier generation.
+     */
+    private static final AtomicInteger COUNTER = new AtomicInteger(0);
+
+    /**
+     * Checks, whether the given file name is valid in the sense, that it doesn't \
contain any NUL characters. If the file name is valid, it will be returned +     * \
without any modifications. Otherwise, an {@link InvalidFileNameException} is raised. \
+     * +     * @param fileName The file name to check
+     * @return Unmodified file name, if valid.
+     * @throws InvalidFileNameException The file name was found to be invalid.
+     */
+    public static String checkFileName(final String fileName) {
+        if (fileName != null && fileName.indexOf('\u0000') != -1) {
+            // fileName.replace("\u0000", "\\0")
+            final StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < fileName.length(); i++) {
+                final char c = fileName.charAt(i);
+                switch (c) {
+                case 0:
+                    sb.append("\\0");
+                    break;
+                default:
+                    sb.append(c);
+                    break;
+                }
+            }
+            throw new InvalidFileNameException(fileName, "Invalid file name: " + \
sb); +        }
+        return fileName;
+    }
+
+    /**
+     * Returns an identifier that is unique within the class loader used to load \
this class, but does not have random-like appearance. +     *
+     * @return A String with the non-random looking instance identifier.
+     */
+    private static String getUniqueId() {
+        final int limit = 100000000;
+        final int current = COUNTER.getAndIncrement();
+        String id = Integer.toString(current);
+
+        // If you manage to get more than 100 million of ids, you'll
+        // start getting ids longer than 8 characters.
+        if (current < limit) {
+            id = ("00000000" + id).substring(id.length());
+        }
+        return id;
+    }
+
+    /**
+     * The name of the form field as provided by the browser.
+     */
+    private String fieldName;
+
+    /**
+     * The content type passed by the browser, or {@code null} if not defined.
+     */
+    private final String contentType;
+
+    /**
+     * Whether or not this item is a simple form field.
+     */
+    private boolean isFormField;
+
+    /**
+     * The original file name in the user's file system.
+     */
+    private final String fileName;
+
+    /**
+     * The size of the item, in bytes. This is used to cache the size when a file \
item is moved from its original location. +     */
+    private long size = -1;
+
+    /**
+     * The threshold above which uploads will be stored on disk.
+     */
+    private final int sizeThreshold;
+
+    /**
+     * The directory in which uploaded files will be stored, if stored on disk.
+     */
+    private final File repository;
+
+    /**
+     * Cached contents of the file.
+     */
+    private byte[] cachedContent;
+
+    /**
+     * Output stream for this item.
+     */
+    private transient DeferredFileOutputStream dfos;
+
+    /**
+     * The temporary file to use.
+     */
+    private transient File tempFile;
+
+    /**
+     * The file items headers.
+     */
+    private FileItemHeaders headers;
+
+    /**
+     * Default content charset to be used when no explicit charset parameter is \
provided by the sender. +     */
+    private String defaultCharset = DEFAULT_CHARSET;
+
+    /**
+     * Constructs a new {@code DiskFileItem} instance.
+     *
+     * @param fieldName     The name of the form field.
+     * @param contentType   The content type passed by the browser or {@code null} \
if not specified. +     * @param isFormField   Whether or not this item is a plain \
form field, as opposed to a file upload. +     * @param fileName      The original \
file name in the user's file system, or {@code null} if not specified. +     * @param \
sizeThreshold The threshold, in bytes, below which items will be retained in memory \
and above which they will be stored as a file. +     * @param repository    The data \
repository, which is the directory in which files will be created, should the item \
size exceed the threshold. +     */
+    public DiskFileItem(final String fieldName, final String contentType, final \
boolean isFormField, final String fileName, final int sizeThreshold, +            \
final File repository) { +        this.fieldName = fieldName;
+        this.contentType = contentType;
+        this.isFormField = isFormField;
+        this.fileName = fileName;
+        this.sizeThreshold = sizeThreshold;
+        this.repository = repository;
+    }
+
+    /**
+     * Deletes the underlying storage for a file item, including deleting any \
associated temporary disk file. This method can be used to ensure that this is +     \
* done at an earlier time, thus preserving system resources. +     */
+    @Override
+    public void delete() {
+        cachedContent = null;
+        final File outputFile = getStoreLocation();
+        if (outputFile != null && !isInMemory() && outputFile.exists()) {
+            if (!outputFile.delete()) {
+                final String desc = "Cannot delete " + outputFile.toString();
+                throw new UncheckedIOException(desc, new IOException(desc));
+            }
+        }
+    }
+
+    /**
+     * Gets the contents of the file as an array of bytes. If the contents of the \
file were not yet cached in memory, they will be loaded from the disk storage +     * \
and cached. +     *
+     * @return The contents of the file as an array of bytes or {@code null} if the \
data cannot be read +     * @throws UncheckedIOException if an I/O error occurs
+     */
+    @Override
+    public byte[] get() throws UncheckedIOException {
+        if (isInMemory()) {
+            if (cachedContent == null && dfos != null) {
+                cachedContent = dfos.getData();
+            }
+            return cachedContent != null ? cachedContent.clone() : new byte[0];
+        }
+
+        final byte[] fileData = new byte[(int) getSize()];
+
+        try (InputStream fis = Files.newInputStream(dfos.getFile().toPath())) {
+            IOUtils.readFully(fis, fileData);
+        } catch (final IOException e) {
+            throw new UncheckedIOException(e);
+        }
+        return fileData;
+    }
+
+    /**
+     * Gets the content charset passed by the agent or {@code null} if not defined.
+     *
+     * @return The content charset passed by the agent or {@code null} if not \
defined. +     */
+    public String getCharSet() {
+        final ParameterParser parser = new ParameterParser();
+        parser.setLowerCaseNames(true);
+        // Parameter parser can handle null input
+        final Map<String, String> params = parser.parse(getContentType(), ';');
+        return params.get("charset");
+    }
+
+    /**
+     * Gets the content type passed by the agent or {@code null} if not defined.
+     *
+     * @return The content type passed by the agent or {@code null} if not defined.
+     */
+    @Override
+    public String getContentType() {
+        return contentType;
+    }
+
+    /**
+     * Gets the default charset for use when no explicit charset parameter is \
provided by the sender. +     *
+     * @return the default charset
+     */
+    public String getDefaultCharset() {
+        return defaultCharset;
+    }
+
+    /**
+     * Gets the name of the field in the multipart form corresponding to this file \
item. +     *
+     * @return The name of the form field.
+     * @see #setFieldName(String)
+     */
+    @Override
+    public String getFieldName() {
+        return fieldName;
+    }
+
+    /**
+     * Gets the file item headers.
+     *
+     * @return The file items headers.
+     */
+    @Override
+    public FileItemHeaders getHeaders() {
+        return headers;
+    }
+
+    /**
+     * Gets an {@link java.io.InputStream InputStream} that can be used to retrieve \
the contents of the file. +     *
+     * @return An {@link java.io.InputStream InputStream} that can be used to \
retrieve the contents of the file. +     * @throws IOException if an error occurs.
+     */
+    @Override
+    public InputStream getInputStream() throws IOException {
+        if (!isInMemory()) {
+            return Files.newInputStream(dfos.getFile().toPath());
+        }
+
+        if (cachedContent == null) {
+            cachedContent = dfos.getData();
+        }
+        return new ByteArrayInputStream(cachedContent);
+    }
+
+    /**
+     * Gets the original file name in the client's file system.
+     *
+     * @return The original file name in the client's file system.
+     * @throws org.apache.commons.fileupload2.InvalidFileNameException The file name \
contains a NUL character, which might be an indicator of a security attack. +     *   \
If you intend to use the file name anyways, catch the exception and use +     *       \
{@link org.apache.commons.fileupload2.InvalidFileNameException#getName()}. +     */
+    @Override
+    public String getName() {
+        return DiskFileItem.checkFileName(fileName);
+    }
+
+    /**
+     * Gets an {@link java.io.OutputStream OutputStream} that can be used for \
storing the contents of the file. +     *
+     * @return An {@link java.io.OutputStream OutputStream} that can be used for \
storing the contents of the file. +     */
+    @Override
+    public OutputStream getOutputStream() {
+        if (dfos == null) {
+            final File outputFile = getTempFile();
+            dfos = new DeferredFileOutputStream(sizeThreshold, outputFile);
+        }
+        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 java.io.File} object 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 java.io.File#renameTo(java.io.File)} to move +     * the \
file to new location without copying the data, if the source and destination \
locations reside within the same logical volume. +     *
+     * @return The data file, or {@code null} if the data is stored in memory.
+     */
+    public File getStoreLocation() {
+        if (dfos == null) {
+            return null;
+        }
+        if (isInMemory()) {
+            return null;
+        }
+        return dfos.getFile();
+    }
+
+    /**
+     * 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> +     * <b>TODO</b> Consider making this method throw \
UnsupportedEncodingException. +     * </p>
+     *
+     * @return The contents of the file, as a string.
+     */
+    @Override
+    public String getString() {
+        try {
+            final byte[] rawData = get();
+            String charset = getCharSet();
+            if (charset == null) {
+                charset = defaultCharset;
+            }
+            return new String(rawData, charset);
+        } catch (final IOException e) {
+            return "";
+        }
+    }
+
+    /**
+     * Gets the contents of the file as a String, using the specified encoding. This \
method uses {@link #get()} to retrieve the contents of the file. +     *
+     * @param charset The charset to use.
+     * @return The contents of the file, as a string.
+     * @throws UnsupportedEncodingException if the requested character encoding is \
not available. +     */
+    @Override
+    public String getString(final String charset) throws \
UnsupportedEncodingException, IOException { +        return new String(get(), \
charset); +    }
+
+    /**
+     * Creates and returns a {@link java.io.File File} representing a uniquely named \
temporary file in the configured repository path. The lifetime of the file +     * is \
tied to the lifetime of the {@code FileItem} instance; the file will be deleted when \
the instance is garbage collected. +     * <p>
+     * <b>Note: Subclasses that override this method must ensure that they return \
the same File each time.</b> +     * </p>
+     *
+     * @return The {@link java.io.File File} to be used for temporary storage.
+     */
+    protected File getTempFile() {
+        if (tempFile == null) {
+            File tempDir = repository;
+            if (tempDir == null) {
+                tempDir = FileUtils.getTempDirectory();
+            }
+            final String tempFileName = String.format("upload_%s_%s.tmp", UID, \
getUniqueId()); +            tempFile = new File(tempDir, tempFileName);
+        }
+        return tempFile;
+    }
+
+    /**
+     * Tests whether or not a {@code FileItem} instance represents a simple form \
field. +     *
+     * @return {@code true} if the instance represents a simple form field; {@code \
false} if it represents an uploaded file. +     * @see #setFormField(boolean)
+     */
+    @Override
+    public boolean isFormField() {
+        return isFormField;
+    }
+
+    /**
+     * Provides a hint as to whether or not the file contents will be read from \
memory. +     *
+     * @return {@code true} if the file contents will be read from memory; {@code \
false} otherwise. +     */
+    @Override
+    public boolean isInMemory() {
+        if (cachedContent != null) {
+            return true;
+        }
+        return dfos.isInMemory();
+    }
+
+    /**
+     * Sets the default charset for use when no explicit charset parameter is \
provided by the sender. +     *
+     * @param charset the default charset
+     */
+    public void setDefaultCharset(final String charset) {
+        defaultCharset = charset;
+    }
+
+    /**
+     * Sets the field name used to reference this file item.
+     *
+     * @param fieldName The name of the form field.
+     * @see #getFieldName()
+     */
+    @Override
+    public void setFieldName(final String fieldName) {
+        this.fieldName = fieldName;
+    }
+
+    /**
+     * Specifies 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. +     * @see #isFormField()
+     */
+    @Override
+    public void setFormField(final boolean state) {
+        isFormField = state;
+    }
+
+    /**
+     * Sets the file item headers.
+     *
+     * @param headers The file items headers.
+     */
+    @Override
+    public void setHeaders(final FileItemHeaders headers) {
+        this.headers = headers;
+    }
+
+    /**
+     * Returns a string representation of this object.
+     *
+     * @return a string representation of this object.
+     */
+    @Override
+    public String toString() {
+        return String.format("name=%s, StoreLocation=%s, size=%s bytes, \
isFormField=%s, FieldName=%s", getName(), getStoreLocation(), getSize(), \
isFormField(), +                getFieldName());
+    }
+
+    /**
+     * Writes an uploaded item to disk.
+     * <p>
+     * The client code is not concerned with whether or not the item is stored in \
memory, or on disk in a temporary location. They just want to write the +     * \
uploaded item to a file. +     * </p>
+     * <p>
+     * This implementation first attempts to rename the uploaded item to the \
specified destination file, if the item was originally written to disk. Otherwise, +  \
* the data will be copied to the specified file. +     * </p>
+     * <p>
+     * This method is only guaranteed to work <em>once</em>, the first time it is \
invoked for a particular item. This is because, in the event that the method +     * \
renames a temporary file, that file will no longer be available to copy or rename \
again at a later time. +     * </p>
+     *
+     * @param file The {@code File} into which the uploaded item should be stored.
+     * @throws IOException if an error occurs.
+     */
+    @Override
+    public void write(final File file) throws IOException {
+        if (isInMemory()) {
+            try (OutputStream fout = Files.newOutputStream(file.toPath())) {
+                fout.write(get());
+            } catch (final IOException e) {
+                throw new IOException("Unexpected output data", e);
+            }
+        } else {
+            final File outputFile = getStoreLocation();
+            if (outputFile == null) {
+                /*
+                 * For whatever reason we cannot write the file to disk.
+                 */
+                throw new FileUploadException("Cannot write uploaded file to \
disk."); +            }
+            // Save the length of the file
+            size = outputFile.length();
+            /*
+             * The uploaded file is being stored on disk in a temporary location so \
move it to the desired file. +             */
+            if (file.exists() && !file.delete()) {
+                throw new FileUploadException("Cannot write uploaded file to \
disk."); +            }
+            FileUtils.moveFile(outputFile, file);
+        }
+    }
+}
diff --git a/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItemFactory.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItemFactory.java
 similarity index 62%
rename from src/main/java/org/apache/commons/fileupload2/disk/DiskFileItemFactory.java
 rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItemFactory.java
 index d139a1b..a397569 100644
--- a/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItemFactory.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/DiskFileItemFactory.java
 @@ -1,240 +1,199 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2.disk;
-
-import java.io.File;
-
-import org.apache.commons.fileupload2.FileItem;
-import org.apache.commons.fileupload2.FileItemFactory;
-import org.apache.commons.io.FileCleaningTracker;
-
-/**
- * The default {@link org.apache.commons.fileupload2.FileItemFactory}
- * implementation.
- * <p>
- * This implementation creates
- * {@link org.apache.commons.fileupload2.FileItem} instances which keep their
- * content either in memory, for smaller items, or in a temporary file on disk,
- * for larger items. The size threshold, above which content will be stored on
- * disk, is configurable, as is the directory in which temporary files will be
- * created.
- * </p>
- * <p>
- * If not otherwise configured, the default configuration values are as
- * follows:
- * </p>
- * <ul>
- *   <li>Size threshold is 10KB.</li>
- *   <li>Repository is the system default temp directory, as returned by
- *       {@code System.getProperty("java.io.tmpdir")}.</li>
- * </ul>
- * <p>
- * <b>NOTE</b>: Files are created in the system default temp directory with
- * predictable names. This means that a local attacker with write access to that
- * directory can perform a TOUTOC attack to replace any uploaded file with a
- * file of the attackers choice. The implications of this will depend on how the
- * uploaded file is used but could be significant. When using this
- * implementation in an environment with local, untrusted users,
- * {@link #setRepository(File)} MUST be used to configure a repository location
- * that is not publicly writable. In a Servlet container the location identified
- * by the ServletContext attribute {@code javax.servlet.context.tempdir}
- * may be used.
- * </p>
- * <p>
- * Temporary files, which are created for file items, should be
- * deleted later on. The best way to do this is using a
- * {@link FileCleaningTracker}, which you can set on the
- * {@link DiskFileItemFactory}. However, if you do use such a tracker,
- * then you must consider the following: Temporary files are automatically
- * deleted as soon as they are no longer needed. (More precisely, when the
- * corresponding instance of {@link java.io.File} is garbage collected.)
- * This is done by the so-called reaper thread, which is started and stopped
- * automatically by the {@link FileCleaningTracker} when there are files to be
- * tracked.
- * It might make sense to terminate that thread, for example, if
- * your web application ends. See the section on "Resource cleanup"
- * in the users guide of commons-fileupload.
- * </p>
- *
- * @since 1.1
- */
-public class DiskFileItemFactory implements FileItemFactory {
-
-    /**
-     * The default threshold above which uploads will be stored on disk.
-     */
-    public static final int DEFAULT_SIZE_THRESHOLD = 10240;
-
-    /**
-     * The directory in which uploaded files will be stored, if stored on disk.
-     */
-    private File repository;
-
-    /**
-     * The threshold above which uploads will be stored on disk.
-     */
-    private int sizeThreshold = DEFAULT_SIZE_THRESHOLD;
-
-    /**
-     * The instance of {@link FileCleaningTracker}, which is responsible
-     * for deleting temporary files.
-     * <p>
-     * May be null, if tracking files is not required.
-     * </p>
-     */
-    private FileCleaningTracker fileCleaningTracker;
-
-    /**
-     * Default content charset to be used when no explicit charset
-     * parameter is provided by the sender.
-     */
-    private String defaultCharset = DiskFileItem.DEFAULT_CHARSET;
-
-    /**
-     * Constructs an unconfigured instance of this class. The resulting factory
-     * may be configured by calling the appropriate setter methods.
-     */
-    public DiskFileItemFactory() {
-        this(DEFAULT_SIZE_THRESHOLD, null);
-    }
-
-    /**
-     * Constructs a preconfigured instance of this class.
-     *
-     * @param sizeThreshold The threshold, in bytes, below which items will be
-     *                      retained in memory and above which they will be
-     *                      stored as a file.
-     * @param repository    The data repository, which is the directory in
-     *                      which files will be created, should the item size
-     *                      exceed the threshold.
-     */
-    public DiskFileItemFactory(final int sizeThreshold, final File repository) {
-        this.sizeThreshold = sizeThreshold;
-        this.repository = repository;
-    }
-
-    /**
-     * Creates a new {@link org.apache.commons.fileupload2.disk.DiskFileItem}
-     * instance from the supplied parameters and the local factory
-     * configuration.
-     *
-     * @param fieldName   The name of the form field.
-     * @param contentType The content type of the form field.
-     * @param isFormField {@code true} if this is a plain form field;
-     *                    {@code false} otherwise.
-     * @param fileName    The name of the uploaded file, if any, as supplied
-     *                    by the browser or other client.
-     * @return The newly created file item.
-     */
-    @Override
-    public FileItem createItem(final String fieldName, final String contentType,
-                final boolean isFormField, final String fileName) {
-        final DiskFileItem result = new DiskFileItem(fieldName, contentType,
-                isFormField, fileName, sizeThreshold, repository);
-        result.setDefaultCharset(defaultCharset);
-        final FileCleaningTracker tracker = getFileCleaningTracker();
-        if (tracker != null) {
-            tracker.track(result.getTempFile(), result);
-        }
-        return result;
-    }
-
-    /**
-     * Gets the default charset for use when no explicit charset
-     * parameter is provided by the sender.
-     *
-     * @return the default charset
-     */
-    public String getDefaultCharset() {
-        return defaultCharset;
-    }
-
-    /**
-     * Gets the tracker, which is responsible for deleting temporary
-     * files.
-     *
-     * @return An instance of {@link FileCleaningTracker}, or null
-     *   (default), if temporary files aren't tracked.
-     */
-    public FileCleaningTracker getFileCleaningTracker() {
-        return fileCleaningTracker;
-    }
-
-    /**
-     * Gets the directory used to temporarily store files that are larger
-     * than the configured size threshold.
-     *
-     * @return The directory in which temporary files will be located.
-     * @see #setRepository(java.io.File)
-     */
-    public File getRepository() {
-        return repository;
-    }
-
-    /**
-     * Gets the size threshold beyond which files are written directly to
-     * disk. The default value is 10240 bytes.
-     *
-     * @return The size threshold, in bytes.
-     * @see #setSizeThreshold(int)
-     */
-    public int getSizeThreshold() {
-        return sizeThreshold;
-    }
-
-    /**
-     * Sets the default charset for use when no explicit charset
-     * parameter is provided by the sender.
-     * @param charset the default charset
-     */
-    public void setDefaultCharset(final String charset) {
-        defaultCharset = charset;
-    }
-
-    /**
-     * Sets the tracker, which is responsible for deleting temporary
-     * files.
-     *
-     * @param tracker An instance of {@link FileCleaningTracker},
-     *   which will from now on track the created files, or null
-     *   (default), to disable tracking.
-     */
-    public void setFileCleaningTracker(final FileCleaningTracker tracker) {
-        fileCleaningTracker = tracker;
-    }
-
-    /**
-     * Sets the directory used to temporarily store files that are larger
-     * than the configured size threshold.
-     *
-     * @param repository The directory in which temporary files will be located.
-     * @see #getRepository()
-     */
-    public void setRepository(final File repository) {
-        this.repository = repository;
-    }
-
-    /**
-     * Sets the size threshold beyond which files are written directly to disk.
-     *
-     * @param sizeThreshold The size threshold, in bytes.
-     * @see #getSizeThreshold()
-     */
-    public void setSizeThreshold(final int sizeThreshold) {
-        this.sizeThreshold = sizeThreshold;
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2.disk;
+
+import java.io.File;
+
+import org.apache.commons.fileupload2.FileItem;
+import org.apache.commons.fileupload2.FileItemFactory;
+import org.apache.commons.io.FileCleaningTracker;
+
+/**
+ * The default {@link org.apache.commons.fileupload2.FileItemFactory} \
implementation. + * <p>
+ * This implementation creates {@link org.apache.commons.fileupload2.FileItem} \
instances which keep their content either in memory, for smaller items, or in a + * \
temporary file on disk, for larger items. The size threshold, above which content \
will be stored on disk, is configurable, as is the directory in which + * temporary \
files will be created. + * </p>
+ * <p>
+ * If not otherwise configured, the default configuration values are as follows:
+ * </p>
+ * <ul>
+ * <li>Size threshold is 10KB.</li>
+ * <li>Repository is the system default temp directory, as returned by {@code \
System.getProperty("java.io.tmpdir")}.</li> + * </ul>
+ * <p>
+ * <b>NOTE</b>: Files are created in the system default temp directory with \
predictable names. This means that a local attacker with write access to that + * \
directory can perform a TOUTOC attack to replace any uploaded file with a file of the \
attackers choice. The implications of this will depend on how the + * uploaded file \
is used but could be significant. When using this implementation in an environment \
with local, untrusted users, {@link #setRepository(File)} + * MUST be used to \
configure a repository location that is not publicly writable. In a Servlet container \
the location identified by the ServletContext attribute + * {@code \
javax.servlet.context.tempdir} may be used. + * </p>
+ * <p>
+ * Temporary files, which are created for file items, should be deleted later on. \
The best way to do this is using a {@link FileCleaningTracker}, which you can + * set \
on the {@link DiskFileItemFactory}. However, if you do use such a tracker, then you \
must consider the following: Temporary files are automatically + * deleted as soon as \
they are no longer needed. (More precisely, when the corresponding instance of {@link \
java.io.File} is garbage collected.) This is done by + * the so-called reaper thread, \
which is started and stopped automatically by the {@link FileCleaningTracker} when \
there are files to be tracked. It might make + * sense to terminate that thread, for \
example, if your web application ends. See the section on "Resource cleanup" in the \
users guide of commons-fileupload. + * </p>
+ *
+ * @since 1.1
+ */
+public class DiskFileItemFactory implements FileItemFactory {
+
+    /**
+     * The default threshold above which uploads will be stored on disk.
+     */
+    public static final int DEFAULT_SIZE_THRESHOLD = 10240;
+
+    /**
+     * The directory in which uploaded files will be stored, if stored on disk.
+     */
+    private File repository;
+
+    /**
+     * The threshold above which uploads will be stored on disk.
+     */
+    private int sizeThreshold = DEFAULT_SIZE_THRESHOLD;
+
+    /**
+     * The instance of {@link FileCleaningTracker}, which is responsible for \
deleting temporary files. +     * <p>
+     * May be null, if tracking files is not required.
+     * </p>
+     */
+    private FileCleaningTracker fileCleaningTracker;
+
+    /**
+     * Default content charset to be used when no explicit charset parameter is \
provided by the sender. +     */
+    private String defaultCharset = DiskFileItem.DEFAULT_CHARSET;
+
+    /**
+     * Constructs an unconfigured instance of this class. The resulting factory may \
be configured by calling the appropriate setter methods. +     */
+    public DiskFileItemFactory() {
+        this(DEFAULT_SIZE_THRESHOLD, null);
+    }
+
+    /**
+     * Constructs a preconfigured instance of this class.
+     *
+     * @param sizeThreshold The threshold, in bytes, below which items will be \
retained in memory and above which they will be stored as a file. +     * @param \
repository    The data repository, which is the directory in which files will be \
created, should the item size exceed the threshold. +     */
+    public DiskFileItemFactory(final int sizeThreshold, final File repository) {
+        this.sizeThreshold = sizeThreshold;
+        this.repository = repository;
+    }
+
+    /**
+     * Creates a new {@link org.apache.commons.fileupload2.disk.DiskFileItem} \
instance from the supplied parameters and the local factory configuration. +     *
+     * @param fieldName   The name of the form field.
+     * @param contentType The content type of the form field.
+     * @param isFormField {@code true} if this is a plain form field; {@code false} \
otherwise. +     * @param fileName    The name of the uploaded file, if any, as \
supplied by the browser or other client. +     * @return The newly created file item.
+     */
+    @Override
+    public FileItem createItem(final String fieldName, final String contentType, \
final boolean isFormField, final String fileName) { +        final DiskFileItem \
result = new DiskFileItem(fieldName, contentType, isFormField, fileName, \
sizeThreshold, repository); +        result.setDefaultCharset(defaultCharset);
+        final FileCleaningTracker tracker = getFileCleaningTracker();
+        if (tracker != null) {
+            tracker.track(result.getTempFile(), result);
+        }
+        return result;
+    }
+
+    /**
+     * Gets the default charset for use when no explicit charset parameter is \
provided by the sender. +     *
+     * @return the default charset
+     */
+    public String getDefaultCharset() {
+        return defaultCharset;
+    }
+
+    /**
+     * Gets the tracker, which is responsible for deleting temporary files.
+     *
+     * @return An instance of {@link FileCleaningTracker}, or null (default), if \
temporary files aren't tracked. +     */
+    public FileCleaningTracker getFileCleaningTracker() {
+        return fileCleaningTracker;
+    }
+
+    /**
+     * Gets the directory used to temporarily store files that are larger than the \
configured size threshold. +     *
+     * @return The directory in which temporary files will be located.
+     * @see #setRepository(java.io.File)
+     */
+    public File getRepository() {
+        return repository;
+    }
+
+    /**
+     * Gets the size threshold beyond which files are written directly to disk. The \
default value is 10240 bytes. +     *
+     * @return The size threshold, in bytes.
+     * @see #setSizeThreshold(int)
+     */
+    public int getSizeThreshold() {
+        return sizeThreshold;
+    }
+
+    /**
+     * Sets the default charset for use when no explicit charset parameter is \
provided by the sender. +     *
+     * @param charset the default charset
+     */
+    public void setDefaultCharset(final String charset) {
+        defaultCharset = charset;
+    }
+
+    /**
+     * Sets the tracker, which is responsible for deleting temporary files.
+     *
+     * @param tracker An instance of {@link FileCleaningTracker}, which will from \
now on track the created files, or null (default), to disable tracking. +     */
+    public void setFileCleaningTracker(final FileCleaningTracker tracker) {
+        fileCleaningTracker = tracker;
+    }
+
+    /**
+     * Sets the directory used to temporarily store files that are larger than the \
configured size threshold. +     *
+     * @param repository The directory in which temporary files will be located.
+     * @see #getRepository()
+     */
+    public void setRepository(final File repository) {
+        this.repository = repository;
+    }
+
+    /**
+     * Sets the size threshold beyond which files are written directly to disk.
+     *
+     * @param sizeThreshold The size threshold, in bytes.
+     * @see #getSizeThreshold()
+     */
+    public void setSizeThreshold(final int sizeThreshold) {
+        this.sizeThreshold = sizeThreshold;
+    }
+}
diff --git a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/package-info.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/package-info.java
 new file mode 100644
index 0000000..1bc8e86
--- /dev/null
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/disk/package-info.java
 @@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * <p>
+ * A disk-based implementation of the {@link org.apache.commons.fileupload2.FileItem \
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.disk.DiskFileItemFactory DiskFileItemFactory} would be \
created, configured, and then + * passed to a {@link \
org.apache.commons.fileupload2.FileUpload FileUpload} implementation such as + * \
{@code org.apache.commons.fileupload2.servlet.ServletFileUpload ServletFileUpload} or \
+ * {@code org.apache.commons.fileupload2.portlet.PortletFileUpload \
PortletFileUpload}. + * </p>
+ * <p>
+ * The following code fragment demonstrates this usage.
+ * </p>
+ *
+ * <pre>
+ * DiskFileItemFactory factory = new DiskFileItemFactory();
+ * // maximum size that will be stored in memory
+ * factory.setSizeThreshold(4096);
+ * // the location for saving data that is larger than getSizeThreshold()
+ * factory.setRepository(new File("/tmp"));
+ *
+ * ServletFileUpload upload = new ServletFileUpload(factory);
+ * </pre>
+ * <p>
+ * Please see the FileUpload <a \
href="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a> \
for further details and examples of how to + * use this package.
+ * </p>
+ */
+package org.apache.commons.fileupload2.disk;
diff --git a/src/main/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java
 similarity index 97%
rename from src/main/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java
 rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java
 index 6aff516..17db6ac 100644
--- a/src/main/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/impl/FileItemIteratorImpl.java
 @@ -1,332 +1,331 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2.impl;
-
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.NoSuchElementException;
-import java.util.Objects;
-
-import org.apache.commons.fileupload2.AbstractFileUpload;
-import org.apache.commons.fileupload2.FileItem;
-import org.apache.commons.fileupload2.FileItemHeaders;
-import org.apache.commons.fileupload2.FileItemIterator;
-import org.apache.commons.fileupload2.FileItemStream;
-import org.apache.commons.fileupload2.FileUploadException;
-import org.apache.commons.fileupload2.MultipartStream;
-import org.apache.commons.fileupload2.ProgressListener;
-import org.apache.commons.fileupload2.RequestContext;
-import org.apache.commons.fileupload2.pub.FileUploadContentTypeException;
-import org.apache.commons.fileupload2.pub.FileUploadSizeException;
-import org.apache.commons.fileupload2.util.LimitedInputStream;
-import org.apache.commons.io.IOUtils;
-
-/**
- * The iterator, which is returned by {@link \
                AbstractFileUpload#getItemIterator(RequestContext)}.
- */
-public class FileItemIteratorImpl implements FileItemIterator {
-
-    /**
-     * The file uploads processing utility.
-     *
-     * @see AbstractFileUpload
-     */
-    private final AbstractFileUpload fileUploadBase;
-
-    /**
-     * The request context.
-     *
-     * @see RequestContext
-     */
-    private final RequestContext ctx;
-
-    /**
-     * The maximum allowed size of a complete request.
-     */
-    private long sizeMax;
-
-    /**
-     * The maximum allowed size of a single uploaded file.
-     */
-    private long fileSizeMax;
-
-    /**
-     * The multi part stream to process.
-     */
-    private MultipartStream multiPartStream;
-
-    /**
-     * The notifier, which used for triggering the {@link ProgressListener}.
-     */
-    private MultipartStream.ProgressNotifier progressNotifier;
-
-    /**
-     * The boundary, which separates the various parts.
-     */
-    private byte[] multiPartBoundary;
-
-    /**
-     * The item, which we currently process.
-     */
-    private FileItemStreamImpl currentItem;
-
-    /**
-     * The current items field name.
-     */
-    private String currentFieldName;
-
-    /**
-     * Whether we are currently skipping the preamble.
-     */
-    private boolean skipPreamble;
-
-    /**
-     * Whether the current item may still be read.
-     */
-    private boolean itemValid;
-
-    /**
-     * Whether we have seen the end of the file.
-     */
-    private boolean eof;
-
-    /**
-     * Constructs a new instance.
-     *
-     * @param fileUploadBase Main processor.
-     * @param requestContext The request context.
-     * @throws FileUploadException An error occurred while parsing the request.
-     * @throws IOException         An I/O error occurred.
-     */
-    public FileItemIteratorImpl(final AbstractFileUpload fileUploadBase, final \
                RequestContext requestContext) throws FileUploadException, \
                IOException {
-        this.fileUploadBase = fileUploadBase;
-        this.sizeMax = fileUploadBase.getSizeMax();
-        this.fileSizeMax = fileUploadBase.getFileSizeMax();
-        this.ctx = Objects.requireNonNull(requestContext, "requestContext");
-        this.skipPreamble = true;
-        findNextItem();
-    }
-
-    /**
-     * Finds the next item, if any.
-     *
-     * @return True, if an next item was found, otherwise false.
-     * @throws IOException An I/O error occurred.
-     */
-    private boolean findNextItem() throws FileUploadException, IOException {
-        if (eof) {
-            return false;
-        }
-        if (currentItem != null) {
-            currentItem.close();
-            currentItem = null;
-        }
-        final MultipartStream multi = getMultiPartStream();
-        for (;;) {
-            final boolean nextPart;
-            if (skipPreamble) {
-                nextPart = multi.skipPreamble();
-            } else {
-                nextPart = multi.readBoundary();
-            }
-            if (!nextPart) {
-                if (currentFieldName == null) {
-                    // Outer multipart terminated -> No more data
-                    eof = true;
-                    return false;
-                }
-                // Inner multipart terminated -> Return to parsing the outer
-                multi.setBoundary(multiPartBoundary);
-                currentFieldName = null;
-                continue;
-            }
-            final FileItemHeaders headers = \
                fileUploadBase.getParsedHeaders(multi.readHeaders());
-            if (currentFieldName == null) {
-                // We're parsing the outer multipart
-                final String fieldName = fileUploadBase.getFieldName(headers);
-                if (fieldName != null) {
-                    final String subContentType = \
                headers.getHeader(AbstractFileUpload.CONTENT_TYPE);
-                    if (subContentType != null && \
subContentType.toLowerCase(Locale.ENGLISH).startsWith(AbstractFileUpload.MULTIPART_MIXED)) \
                {
-                        currentFieldName = fieldName;
-                        // Multiple files associated with this field name
-                        final byte[] subBoundary = \
                fileUploadBase.getBoundary(subContentType);
-                        multi.setBoundary(subBoundary);
-                        skipPreamble = true;
-                        continue;
-                    }
-                    final String fileName = fileUploadBase.getFileName(headers);
-                    currentItem = new FileItemStreamImpl(this, fileName, fieldName, \
                headers.getHeader(AbstractFileUpload.CONTENT_TYPE), fileName == null,
-                            getContentLength(headers));
-                    currentItem.setHeaders(headers);
-                    progressNotifier.noteItem();
-                    itemValid = true;
-                    return true;
-                }
-            } else {
-                final String fileName = fileUploadBase.getFileName(headers);
-                if (fileName != null) {
-                    currentItem = new FileItemStreamImpl(this, fileName, \
                currentFieldName, headers.getHeader(AbstractFileUpload.CONTENT_TYPE), \
                false,
-                            getContentLength(headers));
-                    currentItem.setHeaders(headers);
-                    progressNotifier.noteItem();
-                    itemValid = true;
-                    return true;
-                }
-            }
-            multi.discardBodyData();
-        }
-    }
-
-    private long getContentLength(final FileItemHeaders headers) {
-        try {
-            return Long.parseLong(headers.getHeader(AbstractFileUpload.CONTENT_LENGTH));
                
-        } catch (final Exception e) {
-            return -1;
-        }
-    }
-
-    @Override
-    public List<FileItem> getFileItems() throws FileUploadException, IOException {
-        final List<FileItem> items = new ArrayList<>();
-        while (hasNext()) {
-            final FileItemStream fis = next();
-            items.add(fileUploadBase.getFileItemFactory().createItem(fis.getFieldName(), \
                fis.getContentType(), fis.isFormField(), fis.getName()));
-        }
-        return items;
-    }
-
-    @Override
-    public long getFileSizeMax() {
-        return fileSizeMax;
-    }
-
-    public MultipartStream getMultiPartStream() throws FileUploadException, \
                IOException {
-        if (multiPartStream == null) {
-            init(fileUploadBase, ctx);
-        }
-        return multiPartStream;
-    }
-
-    @Override
-    public long getSizeMax() {
-        return sizeMax;
-    }
-
-    /**
-     * Tests whether another instance of {@link FileItemStream} is available.
-     *
-     * @throws FileUploadException Parsing or processing the file item failed.
-     * @throws IOException         Reading the file item failed.
-     * @return True, if one or more additional file items are available, otherwise \
                false.
-     */
-    @Override
-    public boolean hasNext() throws FileUploadException, IOException {
-        if (eof) {
-            return false;
-        }
-        if (itemValid) {
-            return true;
-        }
-        return findNextItem();
-    }
-
-    protected void init(final AbstractFileUpload fileUploadBase, final \
                RequestContext requestContext) throws FileUploadException, \
                IOException {
-        final String contentType = ctx.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",
-                    AbstractFileUpload.MULTIPART_FORM_DATA, \
                AbstractFileUpload.MULTIPART_MIXED, contentType), contentType);
-        }
-        final long contentLengthInt = ctx.getContentLength();
-        // @formatter:off
-        final long requestSize = \
                RequestContext.class.isAssignableFrom(ctx.getClass())
-                                 // Inline conditional is OK here CHECKSTYLE:OFF
-                                 ? ctx.getContentLength()
-                                 : contentLengthInt;
-                                 // CHECKSTYLE:ON
-        // @formatter:on
-        final InputStream input; // N.B. this is eventually closed in \
                MultipartStream processing
-        if (sizeMax >= 0) {
-            if (requestSize != -1 && requestSize > sizeMax) {
-                throw new FileUploadSizeException(
-                        String.format("the request was rejected because its size \
                (%s) exceeds the configured maximum (%s)", requestSize, sizeMax), \
                sizeMax,
-                        requestSize);
-            }
-            // N.B. this is eventually closed in MultipartStream processing
-            input = new LimitedInputStream(ctx.getInputStream(), sizeMax) {
-                @Override
-                protected void raiseError(final long maxLen, final long count) \
                throws IOException {
-                    throw new FileUploadSizeException(
-                            String.format("The request was rejected because its size \
                (%s) exceeds the configured maximum (%s)", count, maxLen), maxLen, \
                count);
-                }
-            };
-        } else {
-            input = ctx.getInputStream();
-        }
-
-        String charEncoding = fileUploadBase.getHeaderEncoding();
-        if (charEncoding == null) {
-            charEncoding = ctx.getCharacterEncoding();
-        }
-
-        multiPartBoundary = fileUploadBase.getBoundary(contentType);
-        if (multiPartBoundary == null) {
-            IOUtils.closeQuietly(input); // avoid possible resource leak
-            throw new FileUploadException("the request was rejected because no \
                multipart boundary was found");
-        }
-
-        progressNotifier = new \
                MultipartStream.ProgressNotifier(fileUploadBase.getProgressListener(), \
                requestSize);
-        try {
-            multiPartStream = new MultipartStream(input, multiPartBoundary, \
                progressNotifier);
-        } catch (final IllegalArgumentException e) {
-            IOUtils.closeQuietly(input); // avoid possible resource leak
-            throw new FileUploadContentTypeException(String.format("The boundary \
                specified in the %s header is too long", \
                AbstractFileUpload.CONTENT_TYPE), e);
-        }
-        multiPartStream.setHeaderEncoding(charEncoding);
-    }
-
-    /**
-     * Returns the next available {@link FileItemStream}.
-     *
-     * @throws java.util.NoSuchElementException No more items are available. Use \
                {@link #hasNext()} to prevent this exception.
-     * @throws FileUploadException              Parsing or processing the file item \
                failed.
-     * @throws IOException                      Reading the file item failed.
-     * @return FileItemStream instance, which provides access to the next file item.
-     */
-    @Override
-    public FileItemStream next() throws FileUploadException, IOException {
-        if (eof || (!itemValid && !hasNext())) {
-            throw new NoSuchElementException();
-        }
-        itemValid = false;
-        return currentItem;
-    }
-
-    @Override
-    public void setFileSizeMax(final long fileSizeMax) {
-        this.fileSizeMax = fileSizeMax;
-    }
-
-    @Override
-    public void setSizeMax(final long sizeMax) {
-        this.sizeMax = sizeMax;
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+
+import org.apache.commons.fileupload2.AbstractFileUpload;
+import org.apache.commons.fileupload2.FileItem;
+import org.apache.commons.fileupload2.FileItemHeaders;
+import org.apache.commons.fileupload2.FileItemIterator;
+import org.apache.commons.fileupload2.FileItemStream;
+import org.apache.commons.fileupload2.FileUploadException;
+import org.apache.commons.fileupload2.MultipartStream;
+import org.apache.commons.fileupload2.ProgressListener;
+import org.apache.commons.fileupload2.RequestContext;
+import org.apache.commons.fileupload2.pub.FileUploadContentTypeException;
+import org.apache.commons.fileupload2.pub.FileUploadSizeException;
+import org.apache.commons.fileupload2.util.LimitedInputStream;
+import org.apache.commons.io.IOUtils;
+
+/**
+ * The iterator, which is returned by {@link \
AbstractFileUpload#getItemIterator(RequestContext)}. + */
+public class FileItemIteratorImpl implements FileItemIterator {
+
+    /**
+     * The file uploads processing utility.
+     *
+     * @see AbstractFileUpload
+     */
+    private final AbstractFileUpload fileUploadBase;
+
+    /**
+     * The request context.
+     *
+     * @see RequestContext
+     */
+    private final RequestContext ctx;
+
+    /**
+     * The maximum allowed size of a complete request.
+     */
+    private long sizeMax;
+
+    /**
+     * The maximum allowed size of a single uploaded file.
+     */
+    private long fileSizeMax;
+
+    /**
+     * The multi part stream to process.
+     */
+    private MultipartStream multiPartStream;
+
+    /**
+     * The notifier, which used for triggering the {@link ProgressListener}.
+     */
+    private MultipartStream.ProgressNotifier progressNotifier;
+
+    /**
+     * The boundary, which separates the various parts.
+     */
+    private byte[] multiPartBoundary;
+
+    /**
+     * The item, which we currently process.
+     */
+    private FileItemStreamImpl currentItem;
+
+    /**
+     * The current items field name.
+     */
+    private String currentFieldName;
+
+    /**
+     * Whether we are currently skipping the preamble.
+     */
+    private boolean skipPreamble;
+
+    /**
+     * Whether the current item may still be read.
+     */
+    private boolean itemValid;
+
+    /**
+     * Whether we have seen the end of the file.
+     */
+    private boolean eof;
+
+    /**
+     * Constructs a new instance.
+     *
+     * @param fileUploadBase Main processor.
+     * @param requestContext The request context.
+     * @throws FileUploadException An error occurred while parsing the request.
+     * @throws IOException         An I/O error occurred.
+     */
+    public FileItemIteratorImpl(final AbstractFileUpload fileUploadBase, final \
RequestContext requestContext) throws FileUploadException, IOException { +        \
this.fileUploadBase = fileUploadBase; +        this.sizeMax = \
fileUploadBase.getSizeMax(); +        this.fileSizeMax = \
fileUploadBase.getFileSizeMax(); +        this.ctx = \
Objects.requireNonNull(requestContext, "requestContext"); +        this.skipPreamble \
= true; +        findNextItem();
+    }
+
+    /**
+     * Finds the next item, if any.
+     *
+     * @return True, if an next item was found, otherwise false.
+     * @throws IOException An I/O error occurred.
+     */
+    private boolean findNextItem() throws FileUploadException, IOException {
+        if (eof) {
+            return false;
+        }
+        if (currentItem != null) {
+            currentItem.close();
+            currentItem = null;
+        }
+        final MultipartStream multi = getMultiPartStream();
+        for (;;) {
+            final boolean nextPart;
+            if (skipPreamble) {
+                nextPart = multi.skipPreamble();
+            } else {
+                nextPart = multi.readBoundary();
+            }
+            if (!nextPart) {
+                if (currentFieldName == null) {
+                    // Outer multipart terminated -> No more data
+                    eof = true;
+                    return false;
+                }
+                // Inner multipart terminated -> Return to parsing the outer
+                multi.setBoundary(multiPartBoundary);
+                currentFieldName = null;
+                continue;
+            }
+            final FileItemHeaders headers = \
fileUploadBase.getParsedHeaders(multi.readHeaders()); +            if \
(currentFieldName == null) { +                // We're parsing the outer multipart
+                final String fieldName = fileUploadBase.getFieldName(headers);
+                if (fieldName != null) {
+                    final String subContentType = \
headers.getHeader(AbstractFileUpload.CONTENT_TYPE); +                    if \
(subContentType != null && \
subContentType.toLowerCase(Locale.ENGLISH).startsWith(AbstractFileUpload.MULTIPART_MIXED)) \
{ +                        currentFieldName = fieldName;
+                        // Multiple files associated with this field name
+                        final byte[] subBoundary = \
fileUploadBase.getBoundary(subContentType); +                        \
multi.setBoundary(subBoundary); +                        skipPreamble = true;
+                        continue;
+                    }
+                    final String fileName = fileUploadBase.getFileName(headers);
+                    currentItem = new FileItemStreamImpl(this, fileName, fieldName, \
headers.getHeader(AbstractFileUpload.CONTENT_TYPE), fileName == null, +               \
getContentLength(headers)); +                    currentItem.setHeaders(headers);
+                    progressNotifier.noteItem();
+                    itemValid = true;
+                    return true;
+                }
+            } else {
+                final String fileName = fileUploadBase.getFileName(headers);
+                if (fileName != null) {
+                    currentItem = new FileItemStreamImpl(this, fileName, \
currentFieldName, headers.getHeader(AbstractFileUpload.CONTENT_TYPE), false, +        \
getContentLength(headers)); +                    currentItem.setHeaders(headers);
+                    progressNotifier.noteItem();
+                    itemValid = true;
+                    return true;
+                }
+            }
+            multi.discardBodyData();
+        }
+    }
+
+    private long getContentLength(final FileItemHeaders headers) {
+        try {
+            return Long.parseLong(headers.getHeader(AbstractFileUpload.CONTENT_LENGTH));
 +        } catch (final Exception e) {
+            return -1;
+        }
+    }
+
+    @Override
+    public List<FileItem> getFileItems() throws FileUploadException, IOException {
+        final List<FileItem> items = new ArrayList<>();
+        while (hasNext()) {
+            final FileItemStream fis = next();
+            items.add(fileUploadBase.getFileItemFactory().createItem(fis.getFieldName(), \
fis.getContentType(), fis.isFormField(), fis.getName())); +        }
+        return items;
+    }
+
+    @Override
+    public long getFileSizeMax() {
+        return fileSizeMax;
+    }
+
+    public MultipartStream getMultiPartStream() throws FileUploadException, \
IOException { +        if (multiPartStream == null) {
+            init(fileUploadBase, ctx);
+        }
+        return multiPartStream;
+    }
+
+    @Override
+    public long getSizeMax() {
+        return sizeMax;
+    }
+
+    /**
+     * Tests whether another instance of {@link FileItemStream} is available.
+     *
+     * @throws FileUploadException Parsing or processing the file item failed.
+     * @throws IOException         Reading the file item failed.
+     * @return True, if one or more additional file items are available, otherwise \
false. +     */
+    @Override
+    public boolean hasNext() throws FileUploadException, IOException {
+        if (eof) {
+            return false;
+        }
+        if (itemValid) {
+            return true;
+        }
+        return findNextItem();
+    }
+
+    protected void init(final AbstractFileUpload fileUploadBase, final \
RequestContext requestContext) throws FileUploadException, IOException { +        \
final String contentType = ctx.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", +                    \
AbstractFileUpload.MULTIPART_FORM_DATA, AbstractFileUpload.MULTIPART_MIXED, \
contentType), contentType); +        }
+        final long contentLengthInt = ctx.getContentLength();
+        // @formatter:off
+        final long requestSize = \
RequestContext.class.isAssignableFrom(ctx.getClass()) +                               \
// Inline conditional is OK here CHECKSTYLE:OFF +                                 ? \
ctx.getContentLength() +                                 : contentLengthInt;
+                                 // CHECKSTYLE:ON
+        // @formatter:on
+        final InputStream input; // N.B. this is eventually closed in \
MultipartStream processing +        if (sizeMax >= 0) {
+            if (requestSize != -1 && requestSize > sizeMax) {
+                throw new FileUploadSizeException(
+                        String.format("the request was rejected because its size \
(%s) exceeds the configured maximum (%s)", requestSize, sizeMax), sizeMax, +          \
requestSize); +            }
+            // N.B. this is eventually closed in MultipartStream processing
+            input = new LimitedInputStream(ctx.getInputStream(), sizeMax) {
+                @Override
+                protected void raiseError(final long maxLen, final long count) \
throws IOException { +                    throw new FileUploadSizeException(
+                            String.format("The request was rejected because its size \
(%s) exceeds the configured maximum (%s)", count, maxLen), maxLen, count); +          \
} +            };
+        } else {
+            input = ctx.getInputStream();
+        }
+
+        String charEncoding = fileUploadBase.getHeaderEncoding();
+        if (charEncoding == null) {
+            charEncoding = ctx.getCharacterEncoding();
+        }
+
+        multiPartBoundary = fileUploadBase.getBoundary(contentType);
+        if (multiPartBoundary == null) {
+            IOUtils.closeQuietly(input); // avoid possible resource leak
+            throw new FileUploadException("the request was rejected because no \
multipart boundary was found"); +        }
+
+        progressNotifier = new \
MultipartStream.ProgressNotifier(fileUploadBase.getProgressListener(), requestSize); \
+        try { +            multiPartStream = new MultipartStream(input, \
multiPartBoundary, progressNotifier); +        } catch (final \
IllegalArgumentException e) { +            IOUtils.closeQuietly(input); // avoid \
possible resource leak +            throw new \
FileUploadContentTypeException(String.format("The boundary specified in the %s header \
is too long", AbstractFileUpload.CONTENT_TYPE), e); +        }
+        multiPartStream.setHeaderEncoding(charEncoding);
+    }
+
+    /**
+     * Returns the next available {@link FileItemStream}.
+     *
+     * @throws java.util.NoSuchElementException No more items are available. Use \
{@link #hasNext()} to prevent this exception. +     * @throws FileUploadException     \
Parsing or processing the file item failed. +     * @throws IOException               \
Reading the file item failed. +     * @return FileItemStream instance, which provides \
access to the next file item. +     */
+    @Override
+    public FileItemStream next() throws FileUploadException, IOException {
+        if (eof || (!itemValid && !hasNext())) {
+            throw new NoSuchElementException();
+        }
+        itemValid = false;
+        return currentItem;
+    }
+
+    @Override
+    public void setFileSizeMax(final long fileSizeMax) {
+        this.fileSizeMax = fileSizeMax;
+    }
+
+    @Override
+    public void setSizeMax(final long sizeMax) {
+        this.sizeMax = sizeMax;
+    }
+
+}
diff --git a/src/main/java/org/apache/commons/fileupload2/impl/FileItemStreamImpl.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/impl/FileItemStreamImpl.java
 similarity index 96%
rename from src/main/java/org/apache/commons/fileupload2/impl/FileItemStreamImpl.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/impl/FileItemStreamImpl.java
 index e89bc01..1c59aef 100644
--- a/src/main/java/org/apache/commons/fileupload2/impl/FileItemStreamImpl.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/impl/FileItemStreamImpl.java
 @@ -1,206 +1,205 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2.impl;
-
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.commons.fileupload2.FileItemHeaders;
-import org.apache.commons.fileupload2.FileItemStream;
-import org.apache.commons.fileupload2.FileUploadException;
-import org.apache.commons.fileupload2.InvalidFileNameException;
-import org.apache.commons.fileupload2.MultipartStream.ItemInputStream;
-import org.apache.commons.fileupload2.disk.DiskFileItem;
-import org.apache.commons.fileupload2.pub.FileUploadByteCountLimitException;
-import org.apache.commons.fileupload2.util.LimitedInputStream;
-
-/**
- * Default implementation of {@link FileItemStream}.
- */
-public class FileItemStreamImpl implements FileItemStream {
-
-    /**
-     * The File Item iterator implementation.
-     *
-     * @see FileItemIteratorImpl
-     */
-    private final FileItemIteratorImpl fileItemIteratorImpl;
-
-    /**
-     * The file items content type.
-     */
-    private final String contentType;
-
-    /**
-     * The file items field name.
-     */
-    private final String fieldName;
-
-    /**
-     * The file items file name.
-     */
-    private final String fileName;
-
-    /**
-     * Whether the file item is a form field.
-     */
-    private final boolean formField;
-
-    /**
-     * The file items input stream.
-     */
-    private final InputStream inputStream;
-
-    /**
-     * The file items input stream closed flag.
-     */
-    private boolean inputStreamClosed;
-
-    /**
-     * The headers, if any.
-     */
-    private FileItemHeaders headers;
-
-    /**
-     * Creates a new instance.
-     *
-     * @param fileItemIterator The {@link FileItemIteratorImpl iterator}, which \
                returned this file item.
-     * @param fileName             The items file name, or null.
-     * @param fieldName        The items field name.
-     * @param contentType      The items content type, or null.
-     * @param formField        Whether the item is a form field.
-     * @param contentLength    The items content length, if known, or -1
-     * @throws IOException         Creating the file item failed.
-     * @throws FileUploadException Parsing the incoming data stream failed.
-     */
-    public FileItemStreamImpl(final FileItemIteratorImpl fileItemIterator, final \
                String fileName, final String fieldName, final String contentType,
-            final boolean formField, final long contentLength) throws \
                FileUploadException, IOException {
-        this.fileItemIteratorImpl = fileItemIterator;
-        this.fileName = fileName;
-        this.fieldName = fieldName;
-        this.contentType = contentType;
-        this.formField = formField;
-        final long fileSizeMax = fileItemIteratorImpl.getFileSizeMax();
-        if (fileSizeMax != -1 && contentLength != -1 && contentLength > fileSizeMax) \
                {
-            throw new FileUploadByteCountLimitException(String.format("The field %s \
                exceeds its maximum permitted size of %s bytes.", fieldName, \
                fileSizeMax),
-                    contentLength, fileSizeMax, fileName, fieldName);
-        }
-        // OK to construct stream now
-        final ItemInputStream itemInputStream = \
                fileItemIteratorImpl.getMultiPartStream().newInputStream();
-        InputStream istream = itemInputStream;
-        if (fileSizeMax != -1) {
-            istream = new LimitedInputStream(istream, fileSizeMax) {
-                @Override
-                protected void raiseError(final long sizeMax, final long count) \
                throws IOException {
-                    itemInputStream.close(true);
-                    throw new FileUploadByteCountLimitException(
-                            String.format("The field %s exceeds its maximum \
                permitted size of %s bytes.", fieldName, sizeMax), count, sizeMax, \
                fileName,
-                            fieldName);
-                }
-            };
-        }
-        this.inputStream = istream;
-    }
-
-    /**
-     * Closes the file item.
-     *
-     * @throws IOException An I/O error occurred.
-     */
-    public void close() throws IOException {
-        inputStream.close();
-        inputStreamClosed = true;
-    }
-
-    /**
-     * Gets the items content type, or null.
-     *
-     * @return Content type, if known, or null.
-     */
-    @Override
-    public String getContentType() {
-        return contentType;
-    }
-
-    /**
-     * Gets the items field name.
-     *
-     * @return Field name.
-     */
-    @Override
-    public String getFieldName() {
-        return fieldName;
-    }
-
-    /**
-     * Gets the file item headers.
-     *
-     * @return The items header object
-     */
-    @Override
-    public FileItemHeaders getHeaders() {
-        return headers;
-    }
-
-    /**
-     * Gets the items file name.
-     *
-     * @return File name, if known, or null.
-     * @throws InvalidFileNameException The file name contains a NUL character, \
                which might be an indicator of a security attack. If you intend to \
                use the file
-     *                                  name anyways, catch the exception and use \
                InvalidFileNameException#getName().
-     */
-    @Override
-    public String getName() {
-        return DiskFileItem.checkFileName(fileName);
-    }
-
-    /**
-     * Tests whether this is a form field.
-     *
-     * @return True, if the item is a form field, otherwise false.
-     */
-    @Override
-    public boolean isFormField() {
-        return formField;
-    }
-
-    /**
-     * Gets the input stream, which may be used to read the items contents.
-     *
-     * @return Opened input stream.
-     * @throws IOException An I/O error occurred.
-     */
-    @Override
-    public InputStream openStream() throws IOException {
-        if (inputStreamClosed) {
-            throw new FileItemStream.ItemSkippedException();
-        }
-        return inputStream;
-    }
-
-    /**
-     * Sets the file item headers.
-     *
-     * @param headers The items header object
-     */
-    @Override
-    public void setHeaders(final FileItemHeaders headers) {
-        this.headers = headers;
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.fileupload2.FileItemHeaders;
+import org.apache.commons.fileupload2.FileItemStream;
+import org.apache.commons.fileupload2.FileUploadException;
+import org.apache.commons.fileupload2.InvalidFileNameException;
+import org.apache.commons.fileupload2.MultipartStream.ItemInputStream;
+import org.apache.commons.fileupload2.disk.DiskFileItem;
+import org.apache.commons.fileupload2.pub.FileUploadByteCountLimitException;
+import org.apache.commons.fileupload2.util.LimitedInputStream;
+
+/**
+ * Default implementation of {@link FileItemStream}.
+ */
+public class FileItemStreamImpl implements FileItemStream {
+
+    /**
+     * The File Item iterator implementation.
+     *
+     * @see FileItemIteratorImpl
+     */
+    private final FileItemIteratorImpl fileItemIteratorImpl;
+
+    /**
+     * The file items content type.
+     */
+    private final String contentType;
+
+    /**
+     * The file items field name.
+     */
+    private final String fieldName;
+
+    /**
+     * The file items file name.
+     */
+    private final String fileName;
+
+    /**
+     * Whether the file item is a form field.
+     */
+    private final boolean formField;
+
+    /**
+     * The file items input stream.
+     */
+    private final InputStream inputStream;
+
+    /**
+     * The file items input stream closed flag.
+     */
+    private boolean inputStreamClosed;
+
+    /**
+     * The headers, if any.
+     */
+    private FileItemHeaders headers;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param fileItemIterator The {@link FileItemIteratorImpl iterator}, which \
returned this file item. +     * @param fileName         The items file name, or \
null. +     * @param fieldName        The items field name.
+     * @param contentType      The items content type, or null.
+     * @param formField        Whether the item is a form field.
+     * @param contentLength    The items content length, if known, or -1
+     * @throws IOException         Creating the file item failed.
+     * @throws FileUploadException Parsing the incoming data stream failed.
+     */
+    public FileItemStreamImpl(final FileItemIteratorImpl fileItemIterator, final \
String fileName, final String fieldName, final String contentType, +            final \
boolean formField, final long contentLength) throws FileUploadException, IOException \
{ +        this.fileItemIteratorImpl = fileItemIterator;
+        this.fileName = fileName;
+        this.fieldName = fieldName;
+        this.contentType = contentType;
+        this.formField = formField;
+        final long fileSizeMax = fileItemIteratorImpl.getFileSizeMax();
+        if (fileSizeMax != -1 && contentLength != -1 && contentLength > fileSizeMax) \
{ +            throw new FileUploadByteCountLimitException(String.format("The field \
%s exceeds its maximum permitted size of %s bytes.", fieldName, fileSizeMax), +       \
contentLength, fileSizeMax, fileName, fieldName); +        }
+        // OK to construct stream now
+        final ItemInputStream itemInputStream = \
fileItemIteratorImpl.getMultiPartStream().newInputStream(); +        InputStream \
istream = itemInputStream; +        if (fileSizeMax != -1) {
+            istream = new LimitedInputStream(istream, fileSizeMax) {
+                @Override
+                protected void raiseError(final long sizeMax, final long count) \
throws IOException { +                    itemInputStream.close(true);
+                    throw new FileUploadByteCountLimitException(
+                            String.format("The field %s exceeds its maximum \
permitted size of %s bytes.", fieldName, sizeMax), count, sizeMax, fileName, +        \
fieldName); +                }
+            };
+        }
+        this.inputStream = istream;
+    }
+
+    /**
+     * Closes the file item.
+     *
+     * @throws IOException An I/O error occurred.
+     */
+    public void close() throws IOException {
+        inputStream.close();
+        inputStreamClosed = true;
+    }
+
+    /**
+     * Gets the items content type, or null.
+     *
+     * @return Content type, if known, or null.
+     */
+    @Override
+    public String getContentType() {
+        return contentType;
+    }
+
+    /**
+     * Gets the items field name.
+     *
+     * @return Field name.
+     */
+    @Override
+    public String getFieldName() {
+        return fieldName;
+    }
+
+    /**
+     * Gets the file item headers.
+     *
+     * @return The items header object
+     */
+    @Override
+    public FileItemHeaders getHeaders() {
+        return headers;
+    }
+
+    /**
+     * Gets the items file name.
+     *
+     * @return File name, if known, or null.
+     * @throws InvalidFileNameException The file name contains a NUL character, \
which might be an indicator of a security attack. If you intend to use the file +     \
*                                  name anyways, catch the exception and use \
InvalidFileNameException#getName(). +     */
+    @Override
+    public String getName() {
+        return DiskFileItem.checkFileName(fileName);
+    }
+
+    /**
+     * Tests whether this is a form field.
+     *
+     * @return True, if the item is a form field, otherwise false.
+     */
+    @Override
+    public boolean isFormField() {
+        return formField;
+    }
+
+    /**
+     * Gets the input stream, which may be used to read the items contents.
+     *
+     * @return Opened input stream.
+     * @throws IOException An I/O error occurred.
+     */
+    @Override
+    public InputStream openStream() throws IOException {
+        if (inputStreamClosed) {
+            throw new FileItemStream.ItemSkippedException();
+        }
+        return inputStream;
+    }
+
+    /**
+     * Sets the file item headers.
+     *
+     * @param headers The items header object
+     */
+    @Override
+    public void setHeaders(final FileItemHeaders headers) {
+        this.headers = headers;
+    }
+
+}
diff --git a/src/main/java/org/apache/commons/fileupload2/impl/package-info.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/impl/package-info.java
 similarity index 100%
rename from src/main/java/org/apache/commons/fileupload2/impl/package-info.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/impl/package-info.java
                
diff --git a/src/main/java/org/apache/commons/fileupload2/package-info.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/package-info.java
 similarity index 57%
rename from src/main/java/org/apache/commons/fileupload2/package-info.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/package-info.java
 index e91d991..de11820 100644
--- a/src/main/java/org/apache/commons/fileupload2/package-info.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/package-info.java
 @@ -17,29 +17,23 @@

 /**
  * <p>
- * A component for handling HTML file uploads as specified by
- * <a href="http://www.ietf.org/rfc/rfc1867.txt" target="_top">RFC&nbsp;1867</a>.
- * This component provides support for uploads within both servlets (JSR 53)
- * and portlets (JSR 168).
+ * A component for handling HTML file uploads as specified by <a \
href="http://www.ietf.org/rfc/rfc1867.txt" target="_top">RFC&nbsp;1867</a>. This \
component + * provides support for uploads within both servlets (JSR 53) and portlets \
                (JSR 168).
  * </p>
  * <p>
- * While this package provides the generic functionality for file uploads,
- * these classes are not typically used directly. Instead, normal usage
- * involves one of the provided extensions of
- * {@link org.apache.commons.fileupload2.FileUpload FileUpload} such as
- * {@link org.apache.commons.fileupload2.servlet.ServletFileUpload \
                ServletFileUpload}
- * or
- * {@link org.apache.commons.fileupload2.portlet.PortletFileUpload \
                PortletFileUpload},
- * together with a factory for
- * {@link org.apache.commons.fileupload2.FileItem FileItem} instances,
- * such as
- * {@link org.apache.commons.fileupload2.disk.DiskFileItemFactory \
DiskFileItemFactory}. + * While this package provides the generic functionality for \
file uploads, these classes are not typically used directly. Instead, normal usage \
involves one of + * the provided extensions of {@link \
org.apache.commons.fileupload2.FileUpload FileUpload} such as + * {@code \
org.apache.commons.fileupload2.servlet.ServletFileUpload ServletFileUpload} or + * \
{@code org.apache.commons.fileupload2.portlet.PortletFileUpload PortletFileUpload}, \
together with a factory for + * {@link org.apache.commons.fileupload2.FileItem \
FileItem} instances, such as {@link \
org.apache.commons.fileupload2.disk.DiskFileItemFactory + * DiskFileItemFactory}.
  * </p>
  * <p>
- * The following is a brief example of typical usage in a servlet, storing
- * the uploaded files on disk.
+ * The following is a brief example of typical usage in a servlet, storing the \
                uploaded files on disk.
  * </p>
- * <pre>public void doPost(HttpServletRequest req, HttpServletResponse res) {
+ *
+ * <pre>
+ * public void doPost(HttpServletRequest req, HttpServletResponse res) {
  *   DiskFileItemFactory factory = new DiskFileItemFactory();
  *   // maximum size that will be stored in memory
  *   factory.setSizeThreshold(4096);
@@ -66,20 +60,14 @@
  * }
  * </pre>
  * <p>
- * In the example above, the first file is loaded into memory as a
- * {@code String}. Before calling the {@code getString} method,
- * the data may have been in memory or on disk depending on its size. The
- * second file we assume it will be large and therefore never explicitly
- * load it into memory, though if it is less than 4096 bytes it will be
- * in memory before it is written to its final location. When writing to
- * the final location, if the data is larger than the threshold, an attempt
- * is made to rename the temporary file to the given location.  If it cannot
- * be renamed, it is streamed to the new location.
+ * In the example above, the first file is loaded into memory as a {@code String}. \
Before calling the {@code getString} method, the data may have been in memory + * or \
on disk depending on its size. The second file we assume it will be large and \
therefore never explicitly load it into memory, though if it is less than + * 4096 \
bytes it will be in memory before it is written to its final location. When writing \
to the final location, if the data is larger than the threshold, an + * attempt is \
made to rename the temporary file to the given location. If it cannot be renamed, it \
                is streamed to the new location.
  * </p>
  * <p>
- * Please see the FileUpload
- * <a href="https://commons.apache.org/fileupload/using.html" target="_top">User \
                Guide</a>
- * for further details and examples of how to use this package.
+ * Please see the FileUpload <a \
href="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a> \
for further details and examples of how to + * use this package.
  * </p>
  */
 package org.apache.commons.fileupload2;
diff --git a/src/main/java/org/apache/commons/fileupload2/pub/FileUploadByteCountLimitException.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/FileUploadByteCountLimitException.java
 similarity index 97%
rename from src/main/java/org/apache/commons/fileupload2/pub/FileUploadByteCountLimitException.java
 rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/FileUploadByteCountLimitException.java
 index 9bc015f..612f1b2 100644
--- a/src/main/java/org/apache/commons/fileupload2/pub/FileUploadByteCountLimitException.java
                
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/FileUploadByteCountLimitException.java
 @@ -1,72 +1,72 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2.pub;
-
-/**
- * Signals that a file size exceeds the configured maximum.
- */
-public class FileUploadByteCountLimitException extends FileUploadSizeException {
-
-    /**
-     * The exceptions UID, for serializing an instance.
-     */
-    private static final long serialVersionUID = 2;
-
-    /**
-     * File name of the item, which caused the exception.
-     */
-    private final String fileName;
-
-    /**
-     * Field name of the item, which caused the exception.
-     */
-    private final String fieldName;
-
-    /**
-     * Constructs an instance with the specified detail message, and actual and \
                permitted sizes.
-     *
-     * @param message   The detail message (which is saved for later retrieval by \
                the {@link #getMessage()} method)
-     * @param actual    The actual request size.
-     * @param permitted The maximum permitted request size.
-     * @param fileName  File name of the item, which caused the exception.
-     * @param fieldName Field name of the item, which caused the exception.
-     */
-    public FileUploadByteCountLimitException(final String message, final long \
                actual, final long permitted, final String fileName, final String \
                fieldName) {
-        super(message, permitted, actual);
-        this.fileName = fileName;
-        this.fieldName = fieldName;
-    }
-
-    /**
-     * Gets the field name of the item, which caused the exception.
-     *
-     * @return Field name, if known, or null.
-     */
-    public String getFieldName() {
-        return fieldName;
-    }
-
-    /**
-     * Gets the file name of the item, which caused the exception.
-     *
-     * @return File name, if known, or null.
-     */
-    public String getFileName() {
-        return fileName;
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2.pub;
+
+/**
+ * Signals that a file size exceeds the configured maximum.
+ */
+public class FileUploadByteCountLimitException extends FileUploadSizeException {
+
+    /**
+     * The exceptions UID, for serializing an instance.
+     */
+    private static final long serialVersionUID = 2;
+
+    /**
+     * File name of the item, which caused the exception.
+     */
+    private final String fileName;
+
+    /**
+     * Field name of the item, which caused the exception.
+     */
+    private final String fieldName;
+
+    /**
+     * Constructs an instance with the specified detail message, and actual and \
permitted sizes. +     *
+     * @param message   The detail message (which is saved for later retrieval by \
the {@link #getMessage()} method) +     * @param actual    The actual request size.
+     * @param permitted The maximum permitted request size.
+     * @param fileName  File name of the item, which caused the exception.
+     * @param fieldName Field name of the item, which caused the exception.
+     */
+    public FileUploadByteCountLimitException(final String message, final long \
actual, final long permitted, final String fileName, final String fieldName) { +      \
super(message, permitted, actual); +        this.fileName = fileName;
+        this.fieldName = fieldName;
+    }
+
+    /**
+     * Gets the field name of the item, which caused the exception.
+     *
+     * @return Field name, if known, or null.
+     */
+    public String getFieldName() {
+        return fieldName;
+    }
+
+    /**
+     * Gets the file name of the item, which caused the exception.
+     *
+     * @return File name, if known, or null.
+     */
+    public String getFileName() {
+        return fileName;
+    }
+
+}
diff --git a/src/main/java/org/apache/commons/fileupload2/pub/FileUploadContentTypeException.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/FileUploadContentTypeException.java
 similarity index 88%
rename from src/main/java/org/apache/commons/fileupload2/pub/FileUploadContentTypeException.java
 rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/FileUploadContentTypeException.java
 index 5c4b221..2d0f18d 100644
--- a/src/main/java/org/apache/commons/fileupload2/pub/FileUploadContentTypeException.java
                
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/FileUploadContentTypeException.java
 @@ -1,62 +1,60 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2.pub;
-
-import org.apache.commons.fileupload2.FileUploadException;
-
-/**
- * Signals that a request is not a multipart request.
- */
-public class FileUploadContentTypeException extends FileUploadException {
-
-    /**
-     * The exceptions UID, for serializing an instance.
-     */
-    private static final long serialVersionUID = 2;
-
-    /**
-     * The guilty content type.
-     */
-    private String contentType;
-
-    /**
-     * Constructs an instance with the specified detail message.
-     *
-     * @param message The detail message (which is saved for later retrieval by the \
                {@link #getMessage()} method)
-     * @param contentType The guilty content type.
-     */
-    public FileUploadContentTypeException(final String message, final String \
                contentType) {
-        super(message);
-        this.contentType = contentType;
-    }
-
-    /**
-     * Constructs an instance with the specified detail message and cause.
-     *
-     * @param message
-     *        The detail message (which is saved for later retrieval
-     *        by the {@link #getMessage()} method)
-     * @param cause the original cause
-     */
-    public FileUploadContentTypeException(final String message, final Throwable \
                cause) {
-        super(message, cause);
-    }
-
-    public String getContentType() {
-        return contentType;
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2.pub;
+
+import org.apache.commons.fileupload2.FileUploadException;
+
+/**
+ * Signals that a request is not a multipart request.
+ */
+public class FileUploadContentTypeException extends FileUploadException {
+
+    /**
+     * The exceptions UID, for serializing an instance.
+     */
+    private static final long serialVersionUID = 2;
+
+    /**
+     * The guilty content type.
+     */
+    private String contentType;
+
+    /**
+     * Constructs an instance with the specified detail message.
+     *
+     * @param message     The detail message (which is saved for later retrieval by \
the {@link #getMessage()} method) +     * @param contentType The guilty content type.
+     */
+    public FileUploadContentTypeException(final String message, final String \
contentType) { +        super(message);
+        this.contentType = contentType;
+    }
+
+    /**
+     * Constructs an instance with the specified detail message and cause.
+     *
+     * @param message The detail message (which is saved for later retrieval by the \
{@link #getMessage()} method) +     * @param cause   the original cause
+     */
+    public FileUploadContentTypeException(final String message, final Throwable \
cause) { +        super(message, cause);
+    }
+
+    public String getContentType() {
+        return contentType;
+    }
+}
diff --git a/src/main/java/org/apache/commons/fileupload2/pub/FileUploadFileCountLimitException.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/FileUploadFileCountLimitException.java
 similarity index 100%
rename from src/main/java/org/apache/commons/fileupload2/pub/FileUploadFileCountLimitException.java
 rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/FileUploadFileCountLimitException.java
                
diff --git a/src/main/java/org/apache/commons/fileupload2/pub/FileUploadSizeException.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/FileUploadSizeException.java
 similarity index 96%
rename from src/main/java/org/apache/commons/fileupload2/pub/FileUploadSizeException.java
 rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/FileUploadSizeException.java
 index b33fa56..9efa8b7 100644
--- a/src/main/java/org/apache/commons/fileupload2/pub/FileUploadSizeException.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/FileUploadSizeException.java
 @@ -1,72 +1,72 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2.pub;
-
-import org.apache.commons.fileupload2.FileUploadException;
-
-/**
- * Signals that a requests permitted size is exceeded.
- */
-public class FileUploadSizeException extends FileUploadException {
-
-    /**
-     * Serial version UID, being used, if serialized.
-     */
-    private static final long serialVersionUID = 2;
-
-    /**
-     * The actual size of the request.
-     */
-    private final long actual;
-
-    /**
-     * The maximum permitted size of the request.
-     */
-    private final long permitted;
-
-    /**
-     * Constructs an instance.
-     *
-     * @param message   The detail message (which is saved for later retrieval by \
                the {@link #getMessage()} method)
-     * @param permitted The requests size limit.
-     * @param actual    The actual values for the request.
-     */
-    public FileUploadSizeException(final String message, final long permitted, final \
                long actual) {
-        super(message);
-        this.permitted = permitted;
-        this.actual = actual;
-    }
-
-    /**
-     * Gets the actual size of the request.
-     *
-     * @return The actual size of the request.
-     */
-    public long getActualSize() {
-        return actual;
-    }
-
-    /**
-     * Gets the limit size of the request.
-     *
-     * @return The limit size of the request.
-     */
-    public long getPermitted() {
-        return permitted;
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2.pub;
+
+import org.apache.commons.fileupload2.FileUploadException;
+
+/**
+ * Signals that a requests permitted size is exceeded.
+ */
+public class FileUploadSizeException extends FileUploadException {
+
+    /**
+     * Serial version UID, being used, if serialized.
+     */
+    private static final long serialVersionUID = 2;
+
+    /**
+     * The actual size of the request.
+     */
+    private final long actual;
+
+    /**
+     * The maximum permitted size of the request.
+     */
+    private final long permitted;
+
+    /**
+     * Constructs an instance.
+     *
+     * @param message   The detail message (which is saved for later retrieval by \
the {@link #getMessage()} method) +     * @param permitted The requests size limit.
+     * @param actual    The actual values for the request.
+     */
+    public FileUploadSizeException(final String message, final long permitted, final \
long actual) { +        super(message);
+        this.permitted = permitted;
+        this.actual = actual;
+    }
+
+    /**
+     * Gets the actual size of the request.
+     *
+     * @return The actual size of the request.
+     */
+    public long getActualSize() {
+        return actual;
+    }
+
+    /**
+     * Gets the limit size of the request.
+     *
+     * @return The limit size of the request.
+     */
+    public long getPermitted() {
+        return permitted;
+    }
+
+}
diff --git a/src/main/java/org/apache/commons/fileupload2/pub/package-info.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/package-info.java
 similarity index 97%
rename from src/main/java/org/apache/commons/fileupload2/pub/package-info.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/package-info.java
 index 1b8698b..6ffca2a 100644
--- a/src/main/java/org/apache/commons/fileupload2/pub/package-info.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/pub/package-info.java
 @@ -16,7 +16,6 @@
  */

 /**
- * Exceptions, and other classes, that are known to be used outside
- * of FileUpload.
+ * Exceptions, and other classes, that are known to be used outside of FileUpload.
  */
 package org.apache.commons.fileupload2.pub;
diff --git a/src/main/java/org/apache/commons/fileupload2/util/FileItemHeadersImpl.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/FileItemHeadersImpl.java
 similarity index 100%
rename from src/main/java/org/apache/commons/fileupload2/util/FileItemHeadersImpl.java
 rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/FileItemHeadersImpl.java
                
diff --git a/src/main/java/org/apache/commons/fileupload2/util/LimitedInputStream.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/LimitedInputStream.java
 similarity index 52%
rename from src/main/java/org/apache/commons/fileupload2/util/LimitedInputStream.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/LimitedInputStream.java
 index b4b678c..32553b5 100644
--- a/src/main/java/org/apache/commons/fileupload2/util/LimitedInputStream.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/LimitedInputStream.java
 @@ -21,8 +21,7 @@ import java.io.IOException;
 import java.io.InputStream;

 /**
- * An input stream, which limits its data size. This stream is
- * used, if the content length is unknown.
+ * An input stream, which limits its data size. This stream is used, if the content \
                length is unknown.
  */
 public abstract class LimitedInputStream extends FilterInputStream {

@@ -40,8 +39,7 @@ public abstract class LimitedInputStream extends FilterInputStream \
                {
      * Creates a new instance.
      *
      * @param inputStream The input stream, which shall be limited.
-     * @param sizeMax The limit; no more than this number of bytes
-     *   shall be returned by the source stream.
+     * @param sizeMax     The limit; no more than this number of bytes shall be \
                returned by the source stream.
      */
     public LimitedInputStream(final InputStream inputStream, final long sizeMax) {
         super(inputStream);
@@ -49,8 +47,7 @@ public abstract class LimitedInputStream extends FilterInputStream \
{  }

     /**
-     * Called to check, whether the input streams
-     * limit is reached.
+     * Called to check, whether the input streams limit is reached.
      *
      * @throws IOException The given limit is exceeded.
      */
@@ -61,13 +58,10 @@ public abstract class LimitedInputStream extends \
FilterInputStream {  }

     /**
-     * Closes this input stream and releases any system resources
-     * associated with the stream.
-     * This
-     * method simply performs {@code in.close()}.
+     * Closes this input stream and releases any system resources associated with \
                the stream. This method simply performs {@code in.close()}.
      *
-     * @throws  IOException  if an I/O error occurs.
-     * @see        java.io.FilterInputStream#in
+     * @throws IOException if an I/O error occurs.
+     * @see java.io.FilterInputStream#in
      */
     @Override
     public void close() throws IOException {
@@ -75,33 +69,25 @@ public abstract class LimitedInputStream extends \
FilterInputStream {  }

     /**
-     * Called to indicate, that the input streams limit has
-     * been exceeded.
+     * Called to indicate, that the input streams limit has been exceeded.
      *
      * @param sizeMax The input streams limit, in bytes.
-     * @param count The actual number of bytes.
-     * @throws IOException The called method is expected
-     *   to raise an IOException.
+     * @param count   The actual number of bytes.
+     * @throws IOException The called method is expected to raise an IOException.
      */
-    protected abstract void raiseError(long sizeMax, long count)
-            throws IOException;
+    protected abstract void raiseError(long sizeMax, long count) throws IOException;

     /**
-     * Reads the next byte of data from this input stream. The value
-     * byte is returned as an {@code int} in the range
-     * {@code 0} to {@code 255}. If no byte is available
-     * because the end of the stream has been reached, the value
-     * {@code -1} is returned. This method blocks until input data
-     * is available, the end of the stream is detected, or an exception
-     * is thrown.
+     * Reads the next byte of data from this input stream. The value byte is \
returned as an {@code int} in the range {@code 0} to {@code 255}. If no byte is +     \
* available because the end of the stream has been reached, the value {@code -1} is \
returned. This method blocks until input data is available, the end of +     * the \
                stream is detected, or an exception is thrown.
      * <p>
-     * This method
-     * simply performs {@code in.read()} and returns the result.
+     * This method simply performs {@code in.read()} and returns the result.
      * </p>
-     * @return     the next byte of data, or {@code -1} if the end of the
-     *             stream is reached.
-     * @throws  IOException  if an I/O error occurs.
-     * @see        java.io.FilterInputStream#in
+     *
+     * @return the next byte of data, or {@code -1} if the end of the stream is \
reached. +     * @throws IOException if an I/O error occurs.
+     * @see java.io.FilterInputStream#in
      */
     @Override
     public int read() throws IOException {
@@ -114,27 +100,20 @@ public abstract class LimitedInputStream extends \
FilterInputStream {  }

     /**
-     * Reads up to {@code len} bytes of data from this input stream
-     * into an array of bytes. If {@code len} is not zero, the method
-     * blocks until some input is available; otherwise, no
-     * bytes are read and {@code 0} is returned.
+     * Reads up to {@code len} bytes of data from this input stream into an array of \
bytes. If {@code len} is not zero, the method blocks until some input is +     * \
                available; otherwise, no bytes are read and {@code 0} is returned.
      * <p>
-     * This method simply performs {@code in.read(b, off, len)}
-     * and returns the result.
+     * This method simply performs {@code in.read(b, off, len)} and returns the \
                result.
      * </p>
-     * @param      b     the buffer into which the data is read.
-     * @param      off   The start offset in the destination array
-     *                   {@code b}.
-     * @param      len   the maximum number of bytes read.
-     * @return     the total number of bytes read into the buffer, or
-     *             {@code -1} if there is no more data because the end of
-     *             the stream has been reached.
-     * @throws  NullPointerException If {@code b} is {@code null}.
-     * @throws  IndexOutOfBoundsException If {@code off} is negative,
-     * {@code len} is negative, or {@code len} is greater than
-     * {@code b.length - off}
-     * @throws  IOException  if an I/O error occurs.
-     * @see        java.io.FilterInputStream#in
+     *
+     * @param b   the buffer into which the data is read.
+     * @param off The start offset in the destination array {@code b}.
+     * @param len the maximum number of bytes read.
+     * @return the total number of bytes read into the buffer, or {@code -1} if \
there is no more data because the end of the stream has been reached. +     * @throws \
NullPointerException      If {@code b} is {@code null}. +     * @throws \
IndexOutOfBoundsException If {@code off} is negative, {@code len} is negative, or \
{@code len} is greater than {@code b.length - off} +     * @throws IOException        \
if an I/O error occurs. +     * @see java.io.FilterInputStream#in
      */
     @Override
     public int read(final byte[] b, final int off, final int len) throws IOException \
                {
diff --git a/src/main/java/org/apache/commons/fileupload2/util/mime/MimeUtility.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/MimeUtility.java
 similarity index 91%
rename from src/main/java/org/apache/commons/fileupload2/util/mime/MimeUtility.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/MimeUtility.java
 index c2fc47a..63a80c7 100644
--- a/src/main/java/org/apache/commons/fileupload2/util/mime/MimeUtility.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/MimeUtility.java
 @@ -76,18 +76,16 @@ public final class MimeUtility {
     }

     /**
-     * Decodes a string of text obtained from a mail header into
-     * its proper form.  The text generally will consist of a
-     * string of tokens, some of which may be encoded using
-     * base64 encoding.
+     * Decodes a string of text obtained from a mail header into its proper form. \
The text generally will consist of a string of tokens, some of which may be +     * \
                encoded using base64 encoding.
      *
-     * @param text   The text to decode.
+     * @param text The text to decode.
      *
      * @return The decoded text string.
      * @throws UnsupportedEncodingException if the detected encoding in the input \
                text is not supported.
      */
     public static String decodeText(final String text) throws \
                UnsupportedEncodingException {
-        // if the text contains any encoded tokens, those tokens will be marked with \
"=?".  If the +        // if the text contains any encoded tokens, those tokens will \
                be marked with "=?". If the
         // source string doesn't contain that sequent, no decoding is required.
         if (!text.contains(ENCODED_TOKEN_MARKER)) {
             return text;
@@ -121,7 +119,7 @@ public final class MimeUtility {
                     offset++;
                 }
             } else {
-                // we have a word token.  We need to scan over the word and then try \
to parse it. +                // we have a word token. We need to scan over the word \
and then try to parse it.  final int wordStart = offset;

                 while (offset < endOffset) {
@@ -132,17 +130,17 @@ public final class MimeUtility {
                     }
                     offset++;

-                    //NB:  Trailing whitespace on these header strings will just be \
discarded. +                    // NB: Trailing whitespace on these header strings \
will just be discarded.  }
                 // pull out the word token.
                 final String word = text.substring(wordStart, offset);
-                // is the token encoded?  decode the word
+                // is the token encoded? decode the word
                 if (word.startsWith(ENCODED_TOKEN_MARKER)) {
                     try {
                         // if this gives a parsing failure, treat it like a \
non-encoded word.  final String decodedWord = decodeWord(word);

-                        // are any whitespace characters significant?  Append 'em if \
we've got 'em. +                        // are any whitespace characters significant? \
                Append 'em if we've got 'em.
                         if (!previousTokenEncoded && startWhiteSpace != -1) {
                             decodedText.append(text, startWhiteSpace, \
endWhiteSpace);  startWhiteSpace = -1;
@@ -159,7 +157,7 @@ public final class MimeUtility {
                         // just ignore it, skip to next word
                     }
                 }
-                // this is a normal token, so it doesn't matter what the previous \
token was.  Add the white space +                // this is a normal token, so it \
doesn't matter what the previous token was. Add the white space  // if we have it.
                 if (startWhiteSpace != -1) {
                     decodedText.append(text, startWhiteSpace, endWhiteSpace);
@@ -175,19 +173,18 @@ public final class MimeUtility {
     }

     /**
-     * Decodes a string using the RFC 2047 rules for an "encoded-word"
-     * type.  This encoding has the syntax:
+     * Decodes a string using the RFC 2047 rules for an "encoded-word" type. This \
                encoding has the syntax:
      *
      * encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
      *
-     * @param word   The possibly encoded word value.
+     * @param word The possibly encoded word value.
      *
      * @return The decoded word.
-     * @throws ParseException in case of a parse error of the RFC 2047
+     * @throws ParseException               in case of a parse error of the RFC 2047
      * @throws UnsupportedEncodingException Thrown when Invalid RFC 2047 encoding \
                was found
      */
     private static String decodeWord(final String word) throws ParseException, \
                UnsupportedEncodingException {
-        // encoded words start with the characters "=?".  If this not an encoded \
word, we throw a +        // encoded words start with the characters "=?". If this \
not an encoded word, we throw a  // ParseException for the caller.

         if (!word.startsWith(ENCODED_TOKEN_MARKER)) {
@@ -246,8 +243,7 @@ public final class MimeUtility {
     }

     /**
-     * Translate a MIME standard character set name into the Java
-     * equivalent.
+     * Translate a MIME standard character set name into the Java equivalent.
      *
      * @param charset The MIME standard name.
      *
@@ -260,8 +256,8 @@ public final class MimeUtility {
         }

         final String mappedCharset = \
                MIME2JAVA.get(charset.toLowerCase(Locale.ENGLISH));
-        // if there is no mapping, then the original name is used.  Many of the MIME \
                character set
-        // names map directly back into Java.  The reverse isn't necessarily true.
+        // if there is no mapping, then the original name is used. Many of the MIME \
character set +        // names map directly back into Java. The reverse isn't \
necessarily true.  if (mappedCharset == null) {
             return charset;
         }
diff --git a/src/main/java/org/apache/commons/fileupload2/util/mime/ParseException.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/ParseException.java
 similarity index 100%
rename from src/main/java/org/apache/commons/fileupload2/util/mime/ParseException.java
 rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/ParseException.java
                
diff --git a/src/main/java/org/apache/commons/fileupload2/util/mime/QuotedPrintableDecoder.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/QuotedPrintableDecoder.java
 similarity index 88%
rename from src/main/java/org/apache/commons/fileupload2/util/mime/QuotedPrintableDecoder.java
 rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/QuotedPrintableDecoder.java
 index 1eb0b7b..1aa4ca2 100644
--- a/src/main/java/org/apache/commons/fileupload2/util/mime/QuotedPrintableDecoder.java
                
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/QuotedPrintableDecoder.java
 @@ -25,16 +25,15 @@ import java.io.OutputStream;
 final class QuotedPrintableDecoder {

     /**
-     * The shift value required to create the upper nibble
-     * from the first of 2 byte values converted from ascii hex.
+     * The shift value required to create the upper nibble from the first of 2 byte \
                values converted from ascii hex.
      */
     private static final int UPPER_NIBBLE_SHIFT = Byte.SIZE / 2;

     /**
      * Decodes the encoded byte data writing it to the given output stream.
      *
-     * @param data   The array of byte data to decode.
-     * @param out    The output stream used to return the decoded data.
+     * @param data The array of byte data to decode.
+     * @param out  The output stream used to return the decoded data.
      *
      * @return the number of bytes produced.
      * @throws IOException if an IO error occurs
@@ -52,7 +51,7 @@ final class QuotedPrintableDecoder {
             if (ch == '_') {
                 out.write(' ');
             } else if (ch == '=') {
-                // we found an encoded character.  Reduce the 3 char sequence to \
one. +                // we found an encoded character. Reduce the 3 char sequence to \
                one.
                 // but first, make sure we have two characters to work with.
                 if (off + 1 >= endOffset) {
                     throw new IOException("Invalid quoted printable encoding; \
truncated escape sequence"); @@ -61,12 +60,12 @@ final class QuotedPrintableDecoder {
                 final byte b1 = data[off++];
                 final byte b2 = data[off++];

-                // we've found an encoded carriage return.  The next char needs to \
be a newline +                // we've found an encoded carriage return. The next \
char needs to be a newline  if (b1 == '\r') {
                     if (b2 != '\n') {
                         throw new IOException("Invalid quoted printable encoding; CR \
must be followed by LF");  }
-                    // this was a soft linebreak inserted by the encoding.  We just \
toss this away +                    // this was a soft linebreak inserted by the \
encoding. We just toss this away  // on decode.
                 } else {
                     // this is a hex pair we need to convert back to a single byte.
diff --git a/src/main/java/org/apache/commons/fileupload2/util/mime/RFC2231Utility.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/RFC2231Utility.java
 similarity index 86%
rename from src/main/java/org/apache/commons/fileupload2/util/mime/RFC2231Utility.java
 rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/RFC2231Utility.java
 index 5dd6cfd..4295ac7 100644
--- a/src/main/java/org/apache/commons/fileupload2/util/mime/RFC2231Utility.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/RFC2231Utility.java
 @@ -18,14 +18,15 @@ package org.apache.commons.fileupload2.util.mime;

 import java.io.ByteArrayOutputStream;
 import java.io.UnsupportedEncodingException;
+
 /**
- * Utility class to decode/encode character set on HTTP Header fields based on RFC \
                2231.
- * This implementation adheres to RFC 5987 in particular, which was defined for HTTP \
headers + * Utility class to decode/encode character set on HTTP Header fields based \
on RFC 2231. This implementation adheres to RFC 5987 in particular, which was + * \
                defined for HTTP headers
  * <p>
- * RFC 5987 builds on RFC 2231, but has lesser scope like
- * <a href="https://tools.ietf.org/html/rfc5987#section-3.2">mandatory charset \
                definition</a>
- * and <a href="https://tools.ietf.org/html/rfc5987#section-4">no parameter \
continuation</a> + * RFC 5987 builds on RFC 2231, but has lesser scope like <a \
href="https://tools.ietf.org/html/rfc5987#section-3.2">mandatory charset \
definition</a> and + * <a href="https://tools.ietf.org/html/rfc5987#section-4">no \
                parameter continuation</a>
  * </p>
+ *
  * @see <a href="https://tools.ietf.org/html/rfc2231">RFC 2231</a>
  * @see <a href="https://tools.ietf.org/html/rfc5987">RFC 5987</a>
  */
@@ -59,17 +60,13 @@ public final class RFC2231Utility {
     /**
      * Decodes a string of text obtained from a HTTP header as per RFC 2231
      *
-     * <b>Eg 1.</b> {@code us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A}
-     * will be decoded to {@code This is ***fun***}
+     * <b>Eg 1.</b> {@code us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A} will be \
                decoded to {@code This is ***fun***}
      *
-     * <b>Eg 2.</b> {@code iso-8859-1'en'%A3%20rate}
-     * will be decoded to {@code  £ rate}.
+     * <b>Eg 2.</b> {@code iso-8859-1'en'%A3%20rate} will be decoded to {@code  £ \
                rate}.
      *
-     * <b>Eg 3.</b> {@code UTF-8''%c2%a3%20and%20%e2%82%ac%20rates}
-     * will be decoded to {@code  £ and € rates}.
+     * <b>Eg 3.</b> {@code UTF-8''%c2%a3%20and%20%e2%82%ac%20rates} will be decoded \
                to {@code  £ and € rates}.
      *
-     * @param encodedText - Text to be decoded has a format of {@code \
                <charset>'<language>'<encoded_value>}
-     * and ASCII only
+     * @param encodedText - Text to be decoded has a format of {@code \
                <charset>'<language>'<encoded_value>} and ASCII only
      * @return Decoded text based on charset encoding
      * @throws UnsupportedEncodingException The requested character set wasn't \
                found.
      */
@@ -120,8 +117,8 @@ public final class RFC2231Utility {
     }

     /**
-     * Tests if asterisk (*) at the end of parameter name to indicate,
-     * if it has charset and language information to decode the value.
+     * Tests if asterisk (*) at the end of parameter name to indicate, if it has \
charset and language information to decode the value. +     *
      * @param paramName The parameter, which is being checked.
      * @return {@code true}, if encoded as per RFC 2231, {@code false} otherwise
      */
@@ -133,8 +130,8 @@ public final class RFC2231Utility {
     }

     /**
-     * If {@code paramName} has Asterisk (*) at the end, it will be stripped off,
-     * else the passed value will be returned.
+     * If {@code paramName} has Asterisk (*) at the end, it will be stripped off, \
else the passed value will be returned. +     *
      * @param paramName The parameter, which is being inspected.
      * @return stripped {@code paramName} of Asterisk (*), if RFC2231 encoded
      */
@@ -148,8 +145,7 @@ public final class RFC2231Utility {
     }

     /**
-     * Private constructor so that no instances can be created. This class
-     * contains only static utility methods.
+     * Private constructor so that no instances can be created. This class contains \
                only static utility methods.
      */
     private RFC2231Utility() {
     }
diff --git a/src/main/java/org/apache/commons/fileupload2/util/mime/package-info.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/package-info.java
 similarity index 82%
rename from src/main/java/org/apache/commons/fileupload2/util/mime/package-info.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/package-info.java
 index 6b9c410..8fffd8e 100644
--- a/src/main/java/org/apache/commons/fileupload2/util/mime/package-info.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/mime/package-info.java
 @@ -16,7 +16,7 @@
  */

 /**
- * MIME decoder implementation, imported and retailed from
- * <a href="http://svn.apache.org/repos/asf/geronimo/specs/tags/geronimo-javamail_1.4_spec-1.4/">Apache \
Geronimo</a>. + * MIME decoder implementation, imported and retailed from <a \
href="http://svn.apache.org/repos/asf/geronimo/specs/tags/geronimo-javamail_1.4_spec-1.4/">Apache
 + * Geronimo</a>.
  */
 package org.apache.commons.fileupload2.util.mime;
diff --git a/src/main/java/org/apache/commons/fileupload2/util/package-info.java \
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/package-info.java
 similarity index 83%
rename from src/main/java/org/apache/commons/fileupload2/util/package-info.java
rename to commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/package-info.java
 index 95817a1..b988928 100644
--- a/src/main/java/org/apache/commons/fileupload2/util/package-info.java
+++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/util/package-info.java
 @@ -16,8 +16,7 @@
  */

 /**
- * This package contains various IO related utility classes
- * or methods, which are basically reusable and not necessarily
- * restricted to the scope of a file upload.
+ * This package contains various IO related utility classes or methods, which are \
basically reusable and not necessarily restricted to the scope of a file + * upload.
  */
 package org.apache.commons.fileupload2.util;
diff --git a/src/test/java/org/apache/commons/fileupload2/FileUploadTest.java \
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/AbstractFileUploadTest.java
 similarity index 77%
rename from src/test/java/org/apache/commons/fileupload2/FileUploadTest.java
rename to commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/AbstractFileUploadTest.java
 index 4e837bf..19fe3d7 100644
--- a/src/test/java/org/apache/commons/fileupload2/FileUploadTest.java
+++ b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/AbstractFileUploadTest.java
 @@ -24,33 +24,22 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
-import java.util.stream.Stream;

-import org.apache.commons.fileupload2.portlet.PortletFileUploadTest;
-import org.apache.commons.fileupload2.servlet.ServletFileUploadTest;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.jupiter.api.Test;

 /**
- * Common tests for implementations of {@link FileUpload}. 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 FileUpload}. This is a parameterized \
test. Tests must be valid and common to all implementations of FileUpload + * added \
                as parameter in this class.
  *
- * @see ServletFileUploadTest
- * @see PortletFileUploadTest
  * @since 1.4
  */
-public class FileUploadTest {
+public abstract class AbstractFileUploadTest extends AbstractFileUploadWrapper {

-    /**
-     * @return {@link FileUpload} classes under test.
-     */
-    public static Stream<FileUpload> data() {
-        return Util.fileUploadImplementations().stream();
+    protected AbstractFileUploadTest(final FileUpload 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 FileItem fileItems, final int index) {  for (int i = 0; i < \
                headerNames.length; i++) {
             final String value = fileItems.getHeaders().getHeader(headerNames[i]);
             if (i == index) {
@@ -64,11 +53,10 @@ public class FileUploadTest {
     /**
      * Test for <a href="https://issues.apache.org/jira/browse/FILEUPLOAD-239">FILEUPLOAD-239</a>
                
      */
-    @ParameterizedTest
-    @MethodSource("data")
-    public void testContentTypeAttachment(final FileUpload upload)
-            throws IOException, FileUploadException {
-        final List<FileItem> fileItems = Util.parseUpload(upload,
+    @Test
+    public void testContentTypeAttachment() throws IOException, FileUploadException \
{ +        // @formatter:off
+        final List<FileItem> fileItems = parseUpload(upload,
                 "-----1234\r\n" +
                 "content-disposition: form-data; name=\"field1\"\r\n" +
                 "\r\n" +
@@ -84,6 +72,7 @@ public class FileUploadTest {
                 "... contents of file1.txt ...\r\n" +
                 "-----9876--\r\n" +
                 "-----1234--\r\n");
+        // @formatter:on
         assertEquals(2, fileItems.size());

         final FileItem field = fileItems.get(0);
@@ -102,16 +91,16 @@ public class FileUploadTest {
     /**
      * This is what the browser does if you submit the form without choosing a file.
      */
-    @ParameterizedTest
-    @MethodSource("data")
-    public void testEmptyFile(final FileUpload upload)
-            throws FileUploadException {
-        final List<FileItem> fileItems = Util.parseUpload (upload,
+    @Test
+    public void testEmptyFile() throws FileUploadException {
+        // @formatter:off
+        final List<FileItem> fileItems = parseUpload (upload,
                                                 "-----1234\r\n" +
                                                 "Content-Disposition: form-data; \
name=\"file\"; filename=\"\"\r\n" +  "\r\n" +
                                                 "\r\n" +
                                                 "-----1234--\r\n");
+        // @formatter:on
         assertEquals(1, fileItems.size());

         final FileItem file = fileItems.get(0);
@@ -120,11 +109,10 @@ public class FileUploadTest {
         assertEquals("", file.getName());
     }

-    @ParameterizedTest
-    @MethodSource("data")
-    public void testFilenameCaseSensitivity(final FileUpload upload)
-            throws IOException, FileUploadException {
-        final List<FileItem> fileItems = Util.parseUpload(upload,
+    @Test
+    public void testFilenameCaseSensitivity() throws IOException, \
FileUploadException { +        // @formatter:off
+        final List<FileItem> fileItems = parseUpload(upload,
                                                "-----1234\r\n" +
                                                "Content-Disposition: form-data; "
                                              + "name=\"FiLe\"; \
filename=\"FOO.tab\"\r\n" + @@ -133,6 +121,7 @@ public class FileUploadTest {
                                                "This is the content of the file\n" +
                                                "\r\n" +
                                                "-----1234--\r\n");
+        // @formatter:on
         assertEquals(1, fileItems.size());

         final FileItem file = fileItems.get(0);
@@ -140,11 +129,10 @@ public class FileUploadTest {
         assertEquals("FOO.tab", file.getName());
     }

-    @ParameterizedTest
-    @MethodSource("data")
-    public void testFileUpload(final FileUpload upload)
-            throws IOException, FileUploadException {
-        final List<FileItem> fileItems = Util.parseUpload(upload,
+    @Test
+    public void testFileUpload() throws IOException, FileUploadException {
+        // @formatter:off
+        final List<FileItem> fileItems = parseUpload(upload,
                                                "-----1234\r\n" +
                                                "Content-Disposition: "
                                                + "form-data; name=\"file\"; \
filename=\"foo.tab\"\r\n" + @@ -165,6 +153,7 @@ public class FileUploadTest {
                                                "\r\n" +
                                                "value2\r\n" +
                                                "-----1234--\r\n");
+        // @formatter:on
         assertEquals(4, fileItems.size());

         final FileItem file = fileItems.get(0);
@@ -193,17 +182,12 @@ public class FileUploadTest {
     /**
      * Test case for <a href="https://issues.apache.org/jira/browse/FILEUPLOAD-130">
      */
-    @ParameterizedTest
-    @MethodSource("data")
-    public void testFileUpload130(final FileUpload upload)
-            throws Exception {
-        final String[] headerNames = {
-            "SomeHeader", "OtherHeader", "YetAnotherHeader", "WhatAHeader"
-        };
-        final String[] headerValues = {
-            "present", "Is there", "Here", "Is That"
-        };
-        final List<FileItem> fileItems = Util.parseUpload(upload,
+    @Test
+    public void testFileUpload130() throws Exception {
+        final String[] headerNames = { "SomeHeader", "OtherHeader", \
"YetAnotherHeader", "WhatAHeader" }; +        final String[] headerValues = { \
"present", "Is there", "Here", "Is That" }; +        // @formatter:off
+        final List<FileItem> fileItems = parseUpload(upload,
                                                "-----1234\r\n" +
                                                "Content-Disposition: form-data; \
                name=\"file\"; "
                                              + "filename=\"foo.tab\"\r\n" +
@@ -230,6 +214,7 @@ public class FileUploadTest {
                                                "\r\n" +
                                                "value2\r\n" +
                                                "-----1234--\r\n");
+        // @formatter:on
         assertEquals(4, fileItems.size());

         final FileItem file = fileItems.get(0);
@@ -248,9 +233,9 @@ public class FileUploadTest {
     /**
      * Test for <a href="https://issues.apache.org/jira/browse/FILEUPLOAD-62">FILEUPLOAD-62</a>
                
      */
-    @ParameterizedTest
-    @MethodSource("data")
-    public void testFILEUPLOAD62(final FileUpload upload) throws Exception {
+    @Test
+    public void testFILEUPLOAD62() throws Exception {
+        // @formatter:off
         final String contentType = "multipart/form-data; boundaryªB03x";
         final String request              "--AaB03x\r\n" +
@@ -274,8 +259,8 @@ public class FileUploadTest {
             "...contents of file2.gif...\r\n" +
             "--BbC04y--\r\n" +
             "--AaB03x--";
-        final List<FileItem> fileItems = Util.parseUpload(upload, \
                request.getBytes(StandardCharsets.US_ASCII),
-                contentType);
+        // @formatter:on
+        final List<FileItem> fileItems = parseUpload(upload, \
request.getBytes(StandardCharsets.US_ASCII), contentType);  assertEquals(3, \
fileItems.size());  final FileItem item0 = fileItems.get(0);
         assertEquals("field1", item0.getFieldName());
@@ -294,11 +279,10 @@ public class FileUploadTest {
     /**
      * Test for <a href="https://issues.apache.org/jira/browse/FILEUPLOAD-111">FILEUPLOAD-111</a>
                
      */
-    @ParameterizedTest
-    @MethodSource("data")
-    public void testFoldedHeaders(final FileUpload upload)
-            throws IOException, FileUploadException {
-        final List<FileItem> fileItems = Util.parseUpload(upload, "-----1234\r\n" +
+    @Test
+    public void testFoldedHeaders() throws IOException, FileUploadException {
+        // @formatter:off
+        final List<FileItem> 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" +
@@ -319,6 +303,7 @@ public class FileUploadTest {
                 "\r\n" +
                 "value2\r\n" +
                 "-----1234--\r\n");
+        // @formatter:on
         assertEquals(4, fileItems.size());

         final FileItem file = fileItems.get(0);
@@ -345,32 +330,31 @@ public class FileUploadTest {
     }

     /**
-     * Internet Explorer 5 for the Mac has a bug where the carriage
-     * return is missing on any boundary line immediately preceding
-     * an input with type=image. (type=submit does not have the bug.)
+     * Internet Explorer 5 for the Mac has a bug where the carriage return is \
missing on any boundary line immediately preceding an input with type=image. +     * \
                (type=submit does not have the bug.)
      */
-    @ParameterizedTest
-    @MethodSource("data")
-    public void testIE5MacBug(final FileUpload upload)
-            throws FileUploadException {
-        final List<FileItem> fileItems = Util.parseUpload(upload,
-                                               "-----1234\r\n" +
-                                               "Content-Disposition: form-data; \
                name=\"field1\"\r\n" +
-                                               "\r\n" +
-                                               "fieldValue\r\n" +
-                                               "-----1234\n" + // NOTE \r missing
-                                               "Content-Disposition: form-data; \
                name=\"submitName.x\"\r\n" +
-                                               "\r\n" +
-                                               "42\r\n" +
-                                               "-----1234\n" + // NOTE \r missing
-                                               "Content-Disposition: form-data; \
                name=\"submitName.y\"\r\n" +
-                                               "\r\n" +
-                                               "21\r\n" +
-                                               "-----1234\r\n" +
-                                               "Content-Disposition: form-data; \
                name=\"field2\"\r\n" +
-                                               "\r\n" +
-                                               "fieldValue2\r\n" +
-                                               "-----1234--\r\n");
+    @Test
+    public void testIE5MacBug() throws FileUploadException {
+        final List<FileItem> fileItems = parseUpload(upload,
+        // @formatter:off
+                "-----1234\r\n" +
+                "Content-Disposition: form-data; name=\"field1\"\r\n" +
+                "\r\n" +
+                "fieldValue\r\n" +
+                "-----1234\n" + // NOTE \r missing
+                "Content-Disposition: form-data; name=\"submitName.x\"\r\n" +
+                "\r\n" +
+                "42\r\n" +
+                "-----1234\n" + // NOTE \r missing
+                "Content-Disposition: form-data; name=\"submitName.y\"\r\n" +
+                "\r\n" +
+                "21\r\n" +
+                "-----1234\r\n" +
+                "Content-Disposition: form-data; name=\"field2\"\r\n" +
+                "\r\n" +
+                "fieldValue2\r\n" +
+                "-----1234--\r\n");
+        //@formatter:on

         assertEquals(4, fileItems.size());

diff --git a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/AbstractFileUploadWrapper.java \
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/AbstractFileUploadWrapper.java
 new file mode 100644
index 0000000..10d9215
--- /dev/null
+++ b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/AbstractFileUploadWrapper.java
 @@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+/**
+ * Common tests for implementations of {@link FileUpload}. This is a parameterized \
test. Tests must be valid and common to all implementations of FileUpload + * added \
as parameter in this class. + */
+public abstract class AbstractFileUploadWrapper {
+
+    protected final FileUpload upload;
+
+    protected AbstractFileUploadWrapper(final FileUpload fileUpload) {
+        this.upload = fileUpload;
+    }
+
+    public List<FileItem> parseUpload(final FileUpload upload, final byte[] bytes) \
throws FileUploadException { +        return parseUpload(upload, bytes, \
Constants.CONTENT_TYPE); +    }
+
+    public abstract List<FileItem> parseUpload(final FileUpload upload, final byte[] \
bytes, final String contentType) throws FileUploadException; +
+    public List<FileItem> parseUpload(final FileUpload upload, final String content) \
throws FileUploadException { +        final byte[] bytes = \
content.getBytes(StandardCharsets.US_ASCII); +        return parseUpload(upload, \
bytes, Constants.CONTENT_TYPE); +    }
+
+}
diff --git a/src/test/java/org/apache/commons/fileupload2/Constants.java \
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/Constants.java
 similarity index 97%
rename from src/test/java/org/apache/commons/fileupload2/Constants.java
rename to commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/Constants.java
 index 7389018..72c2b4a 100644
--- a/src/test/java/org/apache/commons/fileupload2/Constants.java
+++ b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/Constants.java
 @@ -28,5 +28,6 @@ public final class Constants {
      */
     public static final String CONTENT_TYPE = "multipart/form-data; \
boundary=---1234";

-    private Constants() { }
+    private Constants() {
+    }
 }
diff --git a/src/test/java/org/apache/commons/fileupload2/DiskFileItemSerializeTest.java \
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/DiskFileItemSerializeTest.java
 similarity index 100%
rename from src/test/java/org/apache/commons/fileupload2/DiskFileItemSerializeTest.java
 rename to commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/DiskFileItemSerializeTest.java
                
diff --git a/src/test/java/org/apache/commons/fileupload2/FileItemHeadersTest.java \
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/FileItemHeadersTest.java
 similarity index 94%
rename from src/test/java/org/apache/commons/fileupload2/FileItemHeadersTest.java
rename to commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/FileItemHeadersTest.java
 index 7832cd2..bf02ce9 100644
--- a/src/test/java/org/apache/commons/fileupload2/FileItemHeadersTest.java
+++ b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/FileItemHeadersTest.java
 @@ -27,8 +27,7 @@ import org.apache.commons.fileupload2.util.FileItemHeadersImpl;
 import org.junit.jupiter.api.Test;

 /**
- * Unit tests {@link FileItemHeaders} and
- * {@link FileItemHeadersImpl}.
+ * Unit tests {@link FileItemHeaders} and {@link FileItemHeadersImpl}.
  */
 public class FileItemHeadersTest {

@@ -38,8 +37,7 @@ public class FileItemHeadersTest {
     @Test
     public void testFileItemHeaders() throws Exception {
         final FileItemHeadersImpl aMutableFileItemHeaders = new \
                FileItemHeadersImpl();
-        aMutableFileItemHeaders.addHeader("Content-Disposition",
-                "form-data; name=\"FileItem\"; filename=\"file1.txt\"");
+        aMutableFileItemHeaders.addHeader("Content-Disposition", "form-data; \
name=\"FileItem\"; filename=\"file1.txt\"");  \
aMutableFileItemHeaders.addHeader("Content-Type", "text/plain");

         aMutableFileItemHeaders.addHeader("TestHeader", "headerValue1");
@@ -53,8 +51,7 @@ public class FileItemHeadersTest {
         assertEquals("testheader", headerNameEnumeration.next());
         assertFalse(headerNameEnumeration.hasNext());

-        assertEquals(aMutableFileItemHeaders.getHeader("Content-Disposition"),
-                "form-data; name=\"FileItem\"; filename=\"file1.txt\"");
+        assertEquals(aMutableFileItemHeaders.getHeader("Content-Disposition"), \
                "form-data; name=\"FileItem\"; filename=\"file1.txt\"");
         assertEquals(aMutableFileItemHeaders.getHeader("Content-Type"), \
                "text/plain");
         assertEquals(aMutableFileItemHeaders.getHeader("content-type"), \
                "text/plain");
         assertEquals(aMutableFileItemHeaders.getHeader("TestHeader"), \
                "headerValue1");
diff --git a/src/test/java/org/apache/commons/fileupload2/MultipartStreamTest.java \
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/MultipartStreamTest.java
 similarity index 75%
rename from src/test/java/org/apache/commons/fileupload2/MultipartStreamTest.java
rename to commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/MultipartStreamTest.java
 index 5b354cc..a77560b 100644
--- a/src/test/java/org/apache/commons/fileupload2/MultipartStreamTest.java
+++ b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/MultipartStreamTest.java
 @@ -39,11 +39,7 @@ public class MultipartStreamTest {
         final byte[] boundary = BOUNDARY_TEXT.getBytes();
         final int iBufSize = 1;
         assertThrows(IllegalArgumentException.class,
-                () -> new MultipartStream(
-                        input,
-                        boundary,
-                        iBufSize,
-                        new MultipartStream.ProgressNotifier(null, \
contents.length))); +                () -> new MultipartStream(input, boundary, \
iBufSize, new MultipartStream.ProgressNotifier(null, contents.length)));  }

     @Test
@@ -52,13 +48,8 @@ public class MultipartStreamTest {
         final byte[] contents = strData.getBytes();
         final InputStream input = new ByteArrayInputStream(contents);
         final byte[] boundary = BOUNDARY_TEXT.getBytes();
-        final int iBufSize -                boundary.length + \
                MultipartStream.BOUNDARY_PREFIX.length + 1;
-        final MultipartStream ms = new MultipartStream(
-                input,
-                boundary,
-                iBufSize,
-                new MultipartStream.ProgressNotifier(null, contents.length));
+        final int iBufSize = boundary.length + \
MultipartStream.BOUNDARY_PREFIX.length + 1; +        final MultipartStream ms = new \
MultipartStream(input, boundary, iBufSize, new MultipartStream.ProgressNotifier(null, \
contents.length));  assertNotNull(ms);
     }

@@ -68,10 +59,7 @@ public class MultipartStreamTest {
         final byte[] contents = strData.getBytes();
         final InputStream input = new ByteArrayInputStream(contents);
         final byte[] boundary = BOUNDARY_TEXT.getBytes();
-        final MultipartStream ms = new MultipartStream(
-                input,
-                boundary,
-                new MultipartStream.ProgressNotifier(null, contents.length));
+        final MultipartStream ms = new MultipartStream(input, boundary, new \
MultipartStream.ProgressNotifier(null, contents.length));  assertNotNull(ms);
     }

diff --git a/src/test/java/org/apache/commons/fileupload2/ParameterParserTest.java \
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/ParameterParserTest.java
 similarity index 88%
rename from src/test/java/org/apache/commons/fileupload2/ParameterParserTest.java
rename to commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/ParameterParserTest.java
 index d59286d..c7ab480 100644
--- a/src/test/java/org/apache/commons/fileupload2/ParameterParserTest.java
+++ b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/ParameterParserTest.java
 @@ -42,15 +42,15 @@ public class ParameterParserTest {
     public void testFileUpload139() {
         final ParameterParser parser = new ParameterParser();
         String s = "Content-type: multipart/form-data , boundaryªB03x";
-        Map<String, String> params = parser.parse(s, new char[] {',', ';' });
+        Map<String, String> params = parser.parse(s, new char[] { ',', ';' });
         assertEquals("AaB03x", params.get("boundary"));

         s = "Content-type: multipart/form-data, boundaryªB03x";
-        params = parser.parse(s, new char[] {';', ',' });
+        params = parser.parse(s, new char[] { ';', ',' });
         assertEquals("AaB03x", params.get("boundary"));

         s = "Content-type: multipart/mixed, boundary»C04y";
-        params = parser.parse(s, new char[] {',', ';' });
+        params = parser.parse(s, new char[] { ',', ';' });
         assertEquals("BbC04y", params.get("boundary"));
     }

@@ -74,36 +74,34 @@ public class ParameterParserTest {
         final ParameterParser parser = new ParameterParser();

         // Should parse a UTF-8 charset
-        String s = "Content-Disposition: form-data; "
-                + "name=\"file\"; \
filename*=UTF-8''%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF\r\n"; +        String \
s = "Content-Disposition: form-data; " + "name=\"file\"; \
                filename*=UTF-8''%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF\r\n";
         Map<String, String> params = parser.parse(s, new char[] { ',', ';' });
-        assertEquals("\u3053\u3093\u306B\u3061\u306F", params.get("filename")); \
//filename = "ã“ã‚“ã«ã¡ã¯" in japanese +        \
assertEquals("\u3053\u3093\u306B\u3061\u306F", params.get("filename")); // filename = \
"ã“ã‚“ã«ã¡ã¯" in japanese

         // Should parse ISO-8859-1 charset
         s = "Content-Disposition: form-data; name=\"file\"; \
filename*=UTF-8''%70%C3%A2%74%C3%A9\r\n";  params = parser.parse(s, new char[] { ',', \
                ';' });
-        assertEquals("\u0070\u00e2\u0074\u00e9", params.get("filename")); //filename \
= "pâté" in french +        assertEquals("\u0070\u00e2\u0074\u00e9", \
params.get("filename")); // filename = "pâté" in french

         // Should not decode if '*' is not at the end of param-name
         s = "Content-Disposition: form-data; name=\"file\"; \
                file*name=UTF-8''%61%62%63\r\n";
-        params = parser.parse(s, new char[] {',', ';' });
+        params = parser.parse(s, new char[] { ',', ';' });
         assertEquals("UTF-8''%61%62%63", params.get("file*name"));

         // Should not decode if param-value does not follow \
                <charset>'<lang>'<encoded>
         s = "Content-Disposition: form-data; name=\"file\"; filename*=a'bc\r\n";
-        params = parser.parse(s, new char[] {',', ';' });
+        params = parser.parse(s, new char[] { ',', ';' });
         assertEquals("a'bc", params.get("filename"));

         // Should not decode if param-name doesn't have '*' at end
         s = "Content-Disposition: form-data; name=\"file\"; filename=a'b'c\r\n";
-        params = parser.parse(s, new char[] {',', ';' });
+        params = parser.parse(s, new char[] { ',', ';' });
         assertEquals("a'b'c", params.get("filename"));
     }

     @Test
     public void testParsing() {
-        String s -            "test; test1 =  stuff   ; test2 =  \"stuff; stuff\"; \
test3=\"stuff"; +        String s = "test; test1 =  stuff   ; test2 =  \"stuff; \
stuff\"; test3=\"stuff";  final ParameterParser parser = new ParameterParser();
         Map<String, String> params = parser.parse(s, ';');
         assertNull(params.get("test"));
@@ -111,7 +109,7 @@ public class ParameterParserTest {
         assertEquals("stuff; stuff", params.get("test2"));
         assertEquals("\"stuff", params.get("test3"));

-        params = parser.parse(s, new char[] {',', ';' });
+        params = parser.parse(s, new char[] { ',', ';' });
         assertNull(params.get("test"));
         assertEquals("stuff", params.get("test1"));
         assertEquals("stuff; stuff", params.get("test2"));
diff --git a/src/test/java/org/apache/commons/fileupload2/util/mime/MimeUtilityTestCase.java \
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/util/mime/MimeUtilityTestCase.java
 similarity index 87%
rename from src/test/java/org/apache/commons/fileupload2/util/mime/MimeUtilityTestCase.java
 rename to commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/util/mime/MimeUtilityTestCase.java
 index c5f9d2b..dcedae6 100644
--- a/src/test/java/org/apache/commons/fileupload2/util/mime/MimeUtilityTestCase.java
+++ b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/util/mime/MimeUtilityTestCase.java
 @@ -24,8 +24,7 @@ import java.io.UnsupportedEncodingException;
 import org.junit.jupiter.api.Test;

 /**
- * Use the online <a \
                href="http://dogmamix.com/MimeHeadersDecoder/">MimeHeadersDecoder</a>
- * to validate expected values.
+ * Use the online <a \
href="http://dogmamix.com/MimeHeadersDecoder/">MimeHeadersDecoder</a> to validate \
                expected values.
  *
  * @since 1.3
  */
@@ -43,15 +42,13 @@ public final class MimeUtilityTestCase {
     @Test
     public void decodeIso88591Base64Encoded() throws Exception {
         assertEncoded("If you can read this you understand the example.",
-                      "=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= "
-                            + \
"=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=\"\r\n"); +                \
"=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= " + \
"=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=\"\r\n");  }

     @Test
     public void decodeIso88591Base64EncodedWithWhiteSpace() throws Exception {
         assertEncoded("If you can read this you understand the example.",
-                "=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=\t  \r\n   \
                =?ISO-8859-"
-                      + "2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=\"\r\n");
+                "=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=\t  \r\n   \
=?ISO-8859-" + "2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=\"\r\n");  }

     @Test
diff --git a/src/test/java/org/apache/commons/fileupload2/util/mime/QuotedPrintableDecoderTestCase.java \
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/util/mime/QuotedPrintableDecoderTestCase.java
 similarity index 94%
rename from src/test/java/org/apache/commons/fileupload2/util/mime/QuotedPrintableDecoderTestCase.java
 rename to commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/util/mime/QuotedPrintableDecoderTestCase.java
 index c8831f6..646140f 100644
--- a/src/test/java/org/apache/commons/fileupload2/util/mime/QuotedPrintableDecoderTestCase.java
                
+++ b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/util/mime/QuotedPrintableDecoderTestCase.java
 @@ -100,9 +100,8 @@ public final class QuotedPrintableDecoderTestCase {
      */
     @Test
     public void softLineBreakDecode() throws Exception {
-        assertEncoded("If you believe that truth¾auty, then surely mathematics is \
                the most "
-                        +  "beautiful branch of philosophy.", "If you believe that \
                truth=beauty, then "
-                        + "surely =\r\nmathematics is the most beautiful branch of \
philosophy."); +        assertEncoded("If you believe that truth¾auty, then surely \
mathematics is the most " + "beautiful branch of philosophy.", +                "If \
you believe that truth=beauty, then " + "surely =\r\nmathematics is the most \
beautiful branch of philosophy.");  }

     @Test
diff --git a/src/test/java/org/apache/commons/fileupload2/util/mime/RFC2231UtilityTestCase.java \
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/util/mime/RFC2231UtilityTestCase.java
 similarity index 94%
rename from src/test/java/org/apache/commons/fileupload2/util/mime/RFC2231UtilityTestCase.java
 rename to commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/util/mime/RFC2231UtilityTestCase.java
 index 409373d..bc999cc 100644
--- a/src/test/java/org/apache/commons/fileupload2/util/mime/RFC2231UtilityTestCase.java
                
+++ b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/util/mime/RFC2231UtilityTestCase.java
 @@ -28,8 +28,7 @@ import org.junit.jupiter.api.Test;
 /**
  * The expected characters are encoded in UTF16, while the actual characters may be \
                encoded in UTF-8/ISO-8859-1
  *
- * RFC 5987 recommends to support both UTF-8 & ISO 8859-1. Test values are taken
- * from https://tools.ietf.org/html/rfc5987#section-3.2.2
+ * RFC 5987 recommends to support both UTF-8 & ISO 8859-1. Test values are taken \
                from https://tools.ietf.org/html/rfc5987#section-3.2.2
  */
 public final class RFC2231UtilityTestCase {

@@ -44,13 +43,12 @@ public final class RFC2231UtilityTestCase {

     @Test
     public void decodeIso88591() throws Exception {
-        assertEncoded("\u00A3 rate", "iso-8859-1'en'%A3%20rate"); //" £ rate"
+        assertEncoded("\u00A3 rate", "iso-8859-1'en'%A3%20rate"); // " £ rate"
     }

     @Test
     public void decodeUtf8() throws Exception {
-        assertEncoded("\u00a3 \u0061\u006e\u0064 \u20ac \
                \u0072\u0061\u0074\u0065\u0073",
-                "UTF-8''%c2%a3%20and%20%e2%82%ac%20rates"); //" £ and € rates"
+        assertEncoded("\u00a3 \u0061\u006e\u0064 \u20ac \
\u0072\u0061\u0074\u0065\u0073", "UTF-8''%c2%a3%20and%20%e2%82%ac%20rates"); // " £ \
and € rates"  }

     @Test
diff --git a/commons-fileupload2-jakarta/.checkstyle \
b/commons-fileupload2-jakarta/.checkstyle new file mode 100644
index 0000000..e0d8bb7
--- /dev/null
+++ b/commons-fileupload2-jakarta/.checkstyle
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="false" \
sync-formatter="false"> +  <local-check-config name="maven-checkstyle-plugin \
validate-main" location="file:/C:/Users/ggregory/git/a/commons-fileupload/commons-fileupload2-jakarta/../src/checkstyle/fileupload_checks.xml" \
type="remote" description="maven-checkstyle-plugin configuration validate-main"> +    \
<property name="checkstyle.header.file" value="C:\Users\ggregory\OneDrive - Rocket \
Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.project \
s\commons-fileupload2-jakarta\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-header-validate-main.txt"/>
 +    <property name="checkstyle.cache.file" \
value="${project_loc}/target/checkstyle-cachefile"/> +    <property \
name="checkstyle.suppressions.file" value="C:\Users\ggregory\OneDrive - Rocket \
Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.project \
s\commons-fileupload2-jakarta\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-suppressions-validate-main.xml"/>
 +  </local-check-config>
+  <fileset name="java-sources-validate-main" enabled="true" \
check-config-name="maven-checkstyle-plugin validate-main" local="true"> +    \
<file-match-pattern match-pattern="^src/main/java/.*\.java" include-pattern="true"/> \
+    <file-match-pattern match-pattern="^src/main/resources.*\.properties" \
include-pattern="true"/> +    <file-match-pattern match-pattern="^.*\.properties" \
include-pattern="true"/> +    <file-match-pattern \
match-pattern="^src/test/resources.*\.properties" include-pattern="true"/> +  \
</fileset> +</fileset-config>
diff --git a/commons-fileupload2-jakarta/pom.xml \
b/commons-fileupload2-jakarta/pom.xml new file mode 100644
index 0000000..3f62577
--- /dev/null
+++ b/commons-fileupload2-jakarta/pom.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" \
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 \
http://maven.apache.org/maven-v4_0_0.xsd"> +  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.commons</groupId>
+    <artifactId>commons-fileupload2</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>commons-fileupload2-jakarta</artifactId>
+
+  <name>Apache Commons FileUpload Jakarta Servlet</name>
+  <description>
+    The Apache Commons FileUpload component provides a simple yet flexible means of \
adding support for multipart +    file upload functionality to servlets and web \
applications. +  </description>
+
+  <properties>
+	<commons.parent.dir>${basedir}/..</commons.parent.dir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-fileupload2-core</artifactId>
+      <version>2.0.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-fileupload2-core</artifactId>
+      <version>2.0.0-SNAPSHOT</version>
+      <classifier>tests</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>${commons.io.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>jakarta.servlet</groupId>
+      <artifactId>jakarta.servlet-api</artifactId>
+      <!-- Version 6.0.0 requires Java 11 -->
+      <version>5.0.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+      <version>${commons.lang3.version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/src/main/java/org/apache/commons/fileupload2/jaksrvlt/JakSrvltFileCleaner.java \
b/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileCleaner.java
 similarity index 53%
rename from src/main/java/org/apache/commons/fileupload2/jaksrvlt/JakSrvltFileCleaner.java
 rename to commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileCleaner.java
 index d22caac..6ad1a3f 100644
--- a/src/main/java/org/apache/commons/fileupload2/jaksrvlt/JakSrvltFileCleaner.java
+++ b/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileCleaner.java
 @@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.fileupload2.jaksrvlt;
+package org.apache.commons.fileupload2.jakarta;

 import org.apache.commons.io.FileCleaningTracker;

@@ -23,50 +23,39 @@ import jakarta.servlet.ServletContextEvent;
 import jakarta.servlet.ServletContextListener;

 /**
- * A servlet context listener, which ensures that the
- * {@link FileCleaningTracker}'s reaper thread is terminated,
- * when the web application is destroyed.
+ * A servlet context listener, which ensures that the {@link FileCleaningTracker}'s \
                reaper thread is terminated, when the web application is destroyed.
  */
-public class JakSrvltFileCleaner implements ServletContextListener {
+public class JakartaServletFileCleaner implements ServletContextListener {

     /**
-     * Attribute name, which is used for storing an instance of
-     * {@link FileCleaningTracker} in the web application.
+     * Attribute name, which is used for storing an instance of {@link \
                FileCleaningTracker} in the web application.
      */
-    public static final String FILE_CLEANING_TRACKER_ATTRIBUTE
-        = JakSrvltFileCleaner.class.getName() + ".FileCleaningTracker";
+    public static final String FILE_CLEANING_TRACKER_ATTRIBUTE = \
JakartaServletFileCleaner.class.getName() + ".FileCleaningTracker";

     /**
-     * Gets the instance of {@link FileCleaningTracker}, which is
-     * associated with the given {@link ServletContext}.
+     * Gets the instance of {@link FileCleaningTracker}, which is associated with \
                the given {@link ServletContext}.
      *
      * @param servletContext The servlet context to query
      * @return The contexts tracker
      */
-    public static FileCleaningTracker
-            getFileCleaningTracker(final ServletContext servletContext) {
-        return (FileCleaningTracker)
-            servletContext.getAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE);
+    public static FileCleaningTracker getFileCleaningTracker(final ServletContext \
servletContext) { +        return (FileCleaningTracker) \
servletContext.getAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE);  }

     /**
-     * Sets the instance of {@link FileCleaningTracker}, which is
-     * associated with the given {@link ServletContext}.
+     * Sets the instance of {@link FileCleaningTracker}, which is associated with \
                the given {@link ServletContext}.
      *
      * @param servletContext The servlet context to modify
-     * @param tracker The tracker to set
+     * @param tracker        The tracker to set
      */
-    public static void setFileCleaningTracker(final ServletContext servletContext,
-            final FileCleaningTracker tracker) {
+    public static void setFileCleaningTracker(final ServletContext servletContext, \
                final FileCleaningTracker tracker) {
         servletContext.setAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE, tracker);
     }

     /**
-     * Called when the web application is being destroyed.
-     * Calls {@link FileCleaningTracker#exitWhenFinished()}.
+     * Called when the web application is being destroyed. Calls {@link \
                FileCleaningTracker#exitWhenFinished()}.
      *
-     * @param sce The servlet context, used for calling
-     *     {@link #getFileCleaningTracker(ServletContext)}.
+     * @param sce The servlet context, used for calling {@link \
                #getFileCleaningTracker(ServletContext)}.
      */
     @Override
     public void contextDestroyed(final ServletContextEvent sce) {
@@ -74,15 +63,12 @@ public class JakSrvltFileCleaner implements \
ServletContextListener {  }

     /**
-     * Called when the web application is initialized. Does
-     * nothing.
+     * Called when the web application is initialized. Does nothing.
      *
-     * @param sce The servlet context, used for calling
-     *   {@link #setFileCleaningTracker(ServletContext, FileCleaningTracker)}.
+     * @param sce The servlet context, used for calling {@link \
                #setFileCleaningTracker(ServletContext, FileCleaningTracker)}.
      */
     @Override
     public void contextInitialized(final ServletContextEvent sce) {
-        setFileCleaningTracker(sce.getServletContext(),
-                new FileCleaningTracker());
+        setFileCleaningTracker(sce.getServletContext(), new FileCleaningTracker());
     }
 }
diff --git a/src/main/java/org/apache/commons/fileupload2/jaksrvlt/JakSrvltFileUpload.java \
b/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUpload.java
 similarity index 61%
rename from src/main/java/org/apache/commons/fileupload2/jaksrvlt/JakSrvltFileUpload.java
 rename to commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUpload.java
 index d012da1..33d5130 100644
--- a/src/main/java/org/apache/commons/fileupload2/jaksrvlt/JakSrvltFileUpload.java
+++ b/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUpload.java
 @@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.fileupload2.jaksrvlt;
+package org.apache.commons.fileupload2.jakarta;

 import java.io.IOException;
 import java.util.List;
@@ -32,20 +32,15 @@ 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
- * org.apache.commons.fileupload2.FileItem}s associated with a given HTML
- * widget.
+ * 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 \
                org.apache.commons.fileupload2.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.
+ * 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>
  */
-public class JakSrvltFileUpload extends FileUpload {
+public class JakartaServletFileUpload extends FileUpload {

     /**
      * Constant for HTTP POST method.
@@ -53,86 +48,70 @@ public class JakSrvltFileUpload extends FileUpload {
     private static final String POST_METHOD = "POST";

     /**
-     * Utility method that determines whether the request contains multipart
-     * content.
+     * Utility method that determines whether the request contains multipart \
                content.
      *
      * @param request The servlet request to be evaluated. Must be non-null.
      *
-     * @return {@code true} if the request is multipart;
-     *         {@code false} otherwise.
+     * @return {@code true} if the request is multipart; {@code false} otherwise.
      */
     public static final boolean isMultipartContent(final HttpServletRequest request) \
                {
-        return POST_METHOD.equalsIgnoreCase(request.getMethod()) && \
AbstractFileUpload.isMultipartContent(new JakSrvltRequestContext(request)); +        \
return POST_METHOD.equalsIgnoreCase(request.getMethod()) && \
AbstractFileUpload.isMultipartContent(new JakartaServletRequestContext(request));  }

     /**
-     * Constructs an uninitialized instance of this class. A factory must be
-     * configured, using {@code setFileItemFactory()}, before attempting
-     * to parse requests.
+     * Constructs an uninitialized instance of this class. A factory must be \
configured, using {@code setFileItemFactory()}, before attempting to parse +     * \
                requests.
      *
      * @see FileUpload#FileUpload(FileItemFactory)
      */
-    public JakSrvltFileUpload() {
+    public JakartaServletFileUpload() {
     }

     /**
-     * Constructs an instance of this class which uses the supplied factory to
-     * create {@code FileItem} instances.
+     * Constructs an instance of this class which uses the supplied factory to \
                create {@code FileItem} instances.
      *
      * @see FileUpload#FileUpload()
      * @param fileItemFactory The factory to use for creating file items.
      */
-    public JakSrvltFileUpload(final FileItemFactory fileItemFactory) {
+    public JakartaServletFileUpload(final FileItemFactory fileItemFactory) {
         super(fileItemFactory);
     }

     /**
-     * Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
-     * compliant {@code multipart/form-data} file item iterator.
+     * Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant \
                {@code multipart/form-data} file item iterator.
      *
      * @param request The servlet request to be parsed.
-     * @return An iterator to instances of {@code FileItemStream}
-     *         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.
+     * @return An iterator to instances of {@code FileItemStream} 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 FileItemIterator getItemIterator(final HttpServletRequest request)
-    throws FileUploadException, IOException {
-        return super.getItemIterator(new JakSrvltRequestContext(request));
+    public FileItemIterator getItemIterator(final HttpServletRequest request) throws \
FileUploadException, IOException { +        return super.getItemIterator(new \
JakartaServletRequestContext(request));  }

     /**
-     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
-     * compliant {@code multipart/form-data} stream.
+     * 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.
+     * @throws FileUploadException if there are problems reading/parsing the request \
                or storing files.
      *
      * @since 1.3
      */
-    public Map<String, List<FileItem>> parseParameterMap(final HttpServletRequest \
                request)
-            throws FileUploadException {
-        return parseParameterMap(new JakSrvltRequestContext(request));
+    public Map<String, List<FileItem>> parseParameterMap(final HttpServletRequest \
request) throws FileUploadException { +        return parseParameterMap(new \
JakartaServletRequestContext(request));  }

     /**
-     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
-     * compliant {@code multipart/form-data} stream.
+     * 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.
+     * @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 HttpServletRequest request) throws \
                FileUploadException {
-        return parseRequest(new JakSrvltRequestContext(request));
+        return parseRequest(new JakartaServletRequestContext(request));
     }

 }
diff --git a/src/main/java/org/apache/commons/fileupload2/jaksrvlt/JakSrvltRequestContext.java \
b/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/JakartaServletRequestContext.java
 similarity index 87%
rename from src/main/java/org/apache/commons/fileupload2/jaksrvlt/JakSrvltRequestContext.java
 rename to commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/JakartaServletRequestContext.java
 index e182807..0023e30 100644
--- a/src/main/java/org/apache/commons/fileupload2/jaksrvlt/JakSrvltRequestContext.java
                
+++ b/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/JakartaServletRequestContext.java
 @@ -1,81 +1,80 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2.jaksrvlt;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.commons.fileupload2.AbstractRequestContext;
-
-import jakarta.servlet.http.HttpServletRequest;
-
-/**
- * Provides access to the request information needed for a request made to
- * an HTTP servlet.
- *
- * @since 1.1
- */
-public class JakSrvltRequestContext extends AbstractRequestContext {
-
-    /**
-     * The request for which the context is being provided.
-     */
-    private final HttpServletRequest request;
-
-    /**
-     * Construct a context for this request.
-     *
-     * @param request The request to which this context applies.
-     */
-    public JakSrvltRequestContext(final HttpServletRequest request) {
-        super(request::getHeader, request::getContentLength);
-        this.request = request;
-    }
-
-    /**
-     * Gets the character encoding for the request.
-     *
-     * @return The character encoding for the request.
-     */
-    @Override
-    public String getCharacterEncoding() {
-        return request.getCharacterEncoding();
-    }
-
-    /**
-     * Gets the content type of the request.
-     *
-     * @return The content type of the request.
-     */
-    @Override
-    public String getContentType() {
-        return request.getContentType();
-    }
-
-    /**
-     * Gets the input stream for the request.
-     *
-     * @return The input stream for the request.
-     *
-     * @throws IOException if a problem occurs.
-     */
-    @Override
-    public InputStream getInputStream() throws IOException {
-        return request.getInputStream();
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2.jakarta;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.fileupload2.AbstractRequestContext;
+
+import jakarta.servlet.http.HttpServletRequest;
+
+/**
+ * Provides access to the request information needed for a request made to an HTTP \
servlet. + *
+ * @since 1.1
+ */
+public class JakartaServletRequestContext extends AbstractRequestContext {
+
+    /**
+     * The request for which the context is being provided.
+     */
+    private final HttpServletRequest request;
+
+    /**
+     * Construct a context for this request.
+     *
+     * @param request The request to which this context applies.
+     */
+    public JakartaServletRequestContext(final HttpServletRequest request) {
+        super(request::getHeader, request::getContentLength);
+        this.request = request;
+    }
+
+    /**
+     * Gets the character encoding for the request.
+     *
+     * @return The character encoding for the request.
+     */
+    @Override
+    public String getCharacterEncoding() {
+        return request.getCharacterEncoding();
+    }
+
+    /**
+     * Gets the content type of the request.
+     *
+     * @return The content type of the request.
+     */
+    @Override
+    public String getContentType() {
+        return request.getContentType();
+    }
+
+    /**
+     * Gets the input stream for the request.
+     *
+     * @return The input stream for the request.
+     *
+     * @throws IOException if a problem occurs.
+     */
+    @Override
+    public InputStream getInputStream() throws IOException {
+        return request.getInputStream();
+    }
+
+}
diff --git a/src/main/java/org/apache/commons/fileupload2/FileItemHeadersSupport.java \
b/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/package-info.java
 similarity index 51%
rename from src/main/java/org/apache/commons/fileupload2/FileItemHeadersSupport.java
rename to commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/package-info.java
 index a71553a..2aa1fdf 100644
--- a/src/main/java/org/apache/commons/fileupload2/FileItemHeadersSupport.java
+++ b/commons-fileupload2-jakarta/src/main/java/org/apache/commons/fileupload2/jakarta/package-info.java
 @@ -14,33 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.fileupload2;

 /**
- * Accepts headers for an item type.
+ * <p>
+ * An implementation of {@link org.apache.commons.fileupload2.FileUpload FileUpload} \
                for use in servlets conforming to the namespace {@code \
                jakarta.servlet}.
  *
- * @see FileItem
- * @see FileItemStream
- * @since 1.2.1
+ * </p>
+ * <p>
+ * The following code fragment demonstrates typical usage.
+ * </p>
+ *
+ * <pre>
+ * DiskFileItemFactory factory = new DiskFileItemFactory();
+ * // Configure the factory here, if desired.
+ * JakSrvltFileUpload upload = new JakSrvltFileUpload(factory);
+ * // Configure the uploader here, if desired.
+ * List fileItems = upload.parseRequest(request);
+ * </pre>
+ * <p>
+ * Please see the FileUpload <a \
href="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a> \
for further details and examples of how to + * use this package.
+ * </p>
  */
-public interface FileItemHeadersSupport {
-
-    /**
-     * Gets the collection of headers defined locally within this item.
-     *
-     * @return the {@link FileItemHeaders} present for this item.
-     */
-    FileItemHeaders getHeaders();
-
-    /**
-     * Sets the headers read from within an item.  Implementations of
-     * {@link FileItem} or {@link FileItemStream} should implement this
-     * interface to be able to get the raw headers found within the item
-     * header block.
-     *
-     * @param headers the instance that holds onto the headers
-     *         for this instance.
-     */
-    void setHeaders(FileItemHeaders headers);
-
-}
+package org.apache.commons.fileupload2.jakarta;
diff --git a/src/test/java/org/apache/commons/fileupload2/jaksrvlt/JakSrvltFileUploadTest.java \
b/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUploadTest.java
 similarity index 81%
rename from src/test/java/org/apache/commons/fileupload2/jaksrvlt/JakSrvltFileUploadTest.java
 rename to commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUploadTest.java
 index 0fe2339..7ff29af 100644
--- a/src/test/java/org/apache/commons/fileupload2/jaksrvlt/JakSrvltFileUploadTest.java
                
+++ b/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/JakartaServletFileUploadTest.java
 @@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.fileupload2.jaksrvlt;
+package org.apache.commons.fileupload2.jakarta;

 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -23,9 +23,9 @@ import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.Map;

+import org.apache.commons.fileupload2.AbstractFileUploadTest;
 import org.apache.commons.fileupload2.Constants;
 import org.apache.commons.fileupload2.FileItem;
-import org.apache.commons.fileupload2.FileUploadTest;
 import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
 import org.junit.jupiter.api.Test;

@@ -34,40 +34,40 @@ import jakarta.servlet.http.HttpServletRequest;
 /**
  * Test for {@link org.apache.commons.fileupload2.servlet.ServletFileUpload}.
  *
- * @see FileUploadTest
+ * @see AbstractFileUploadTest
  * @since 1.4
  */
-public class JakSrvltFileUploadTest {
+public class JakartaServletFileUploadTest {

     @Test
-    public void parseImpliedUtf8()
-        throws Exception {
+    public void parseImpliedUtf8() throws Exception {
         // utf8 encoded form-data without explicit content-type encoding
+        // @formatter:off
         final String text = "-----1234\r\n" +
                 "Content-Disposition: form-data; name=\"utf8Html\"\r\n" +
                 "\r\n" +
                 "Thís ís the coñteñt of the fíle\n" +
                 "\r\n" +
                 "-----1234--\r\n";
+        // @formatter:on

         final byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
-        final HttpServletRequest request = new MockJakSrvltHttpRequest(bytes, \
Constants.CONTENT_TYPE); +        final HttpServletRequest request = new \
MockJakartaServletHttpRequest(bytes, Constants.CONTENT_TYPE);

         final DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
         fileItemFactory.setDefaultCharset("UTF-8");
-        final JakSrvltFileUpload upload = new JakSrvltFileUpload(fileItemFactory);
+        final JakartaServletFileUpload upload = new \
JakartaServletFileUpload(fileItemFactory);  final List<FileItem> fileItems = \
upload.parseRequest(request);  final FileItem fileItem = fileItems.get(0);
         assertTrue(fileItem.getString().contains("coñteñt"), \
fileItem.getString());  }

-
     /**
      * Test case for <a href="https://issues.apache.org/jira/browse/FILEUPLOAD-210">
      */
     @Test
-    public void parseParameterMap()
-            throws Exception {
+    public void parseParameterMap() throws Exception {
+        // @formatter:off
         final String text = "-----1234\r\n" +
                       "Content-Disposition: form-data; name=\"file\"; \
filename=\"foo.tab\"\r\n" +  "Content-Type: text/whatever\r\n" +
@@ -87,10 +87,11 @@ public class JakSrvltFileUploadTest {
                       "\r\n" +
                       "value2\r\n" +
                       "-----1234--\r\n";
+        // @formatter:on
         final byte[] bytes = text.getBytes(StandardCharsets.US_ASCII);
-        final HttpServletRequest request = new MockJakSrvltHttpRequest(bytes, \
Constants.CONTENT_TYPE); +        final HttpServletRequest request = new \
MockJakartaServletHttpRequest(bytes, Constants.CONTENT_TYPE);

-        final JakSrvltFileUpload upload = new JakSrvltFileUpload(new \
DiskFileItemFactory()); +        final JakartaServletFileUpload upload = new \
                JakartaServletFileUpload(new DiskFileItemFactory());
         final Map<String, List<FileItem>> mappedParameters = \
upload.parseParameterMap(request);  assertTrue(mappedParameters.containsKey("file"));
         assertEquals(1, mappedParameters.get("file").size());
diff --git a/src/test/java/org/apache/commons/fileupload2/jaksrvlt/MockJakSrvltHttpRequest.java \
b/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/MockJakartaServletHttpRequest.java
 similarity index 91%
rename from src/test/java/org/apache/commons/fileupload2/jaksrvlt/MockJakSrvltHttpRequest.java
 rename to commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/MockJakartaServletHttpRequest.java
 index 440c2a3..9fa19fa 100644
--- a/src/test/java/org/apache/commons/fileupload2/jaksrvlt/MockJakSrvltHttpRequest.java
                
+++ b/commons-fileupload2-jakarta/src/test/java/org/apache/commons/fileupload2/jakarta/MockJakartaServletHttpRequest.java
 @@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.fileupload2.jaksrvlt;
+package org.apache.commons.fileupload2.jakarta;

 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
@@ -45,17 +45,15 @@ import jakarta.servlet.http.HttpSession;
 import jakarta.servlet.http.HttpUpgradeHandler;
 import jakarta.servlet.http.Part;

-public class MockJakSrvltHttpRequest implements HttpServletRequest {
+public class MockJakartaServletHttpRequest implements HttpServletRequest {

-    private static class MyServletInputStream
-        extends jakarta.servlet.ServletInputStream {
+    private static class MyServletInputStream extends \
jakarta.servlet.ServletInputStream {

         private final InputStream inputStream;
         private final int readLimit;

         /**
-         * Creates a new instance, which returns the given
-         * streams data.
+         * Creates a new instance, which returns the given streams data.
          */
         public MyServletInputStream(final InputStream inputStream, final int \
readLimit) {  this.inputStream = inputStream;
@@ -103,24 +101,16 @@ public class MockJakSrvltHttpRequest implements \
                HttpServletRequest {
     private final Map<String, String> mHeaders = new java.util.HashMap<>();

     /**
-     * Creates a new instance with the given request data
-     * and content type.
+     * Creates a new instance with the given request data and content type.
      */
-    public MockJakSrvltHttpRequest(
-            final byte[] requestData,
-            final String strContentType) {
-        this(new ByteArrayInputStream(requestData),
-                requestData.length, strContentType);
+    public MockJakartaServletHttpRequest(final byte[] requestData, final String \
strContentType) { +        this(new ByteArrayInputStream(requestData), \
requestData.length, strContentType);  }

     /**
-     * Creates a new instance with the given request data
-     * and content type.
+     * Creates a new instance with the given request data and content type.
      */
-    public MockJakSrvltHttpRequest(
-            final InputStream requestData,
-            final long requestLength,
-            final String strContentType) {
+    public MockJakartaServletHttpRequest(final InputStream requestData, final long \
requestLength, final String strContentType) {  mRequestData = requestData;
         length = requestLength;
         mStrContentType = strContentType;
@@ -393,6 +383,10 @@ public class MockJakSrvltHttpRequest implements \
HttpServletRequest {  return null;
     }

+    public String getProtocolRequestId() {
+        throw new IllegalStateException("Not implemented 6.0.0");
+    }
+
     /**
      * @see javax.servlet.http.HttpServletRequest#getQueryString()
      */
@@ -463,6 +457,10 @@ public class MockJakSrvltHttpRequest implements \
HttpServletRequest {  return null;
     }

+    public String getRequestId() {
+        throw new IllegalStateException("Not implemented 6.0.0");
+    }
+
     /**
      * @see javax.servlet.http.HttpServletRequest#getRequestURI()
      */
@@ -509,7 +507,7 @@ public class MockJakSrvltHttpRequest implements \
HttpServletRequest {  if (session == null) {
             return null;
         }
-      return session.getServletContext();
+        return session.getServletContext();
     }

     /**
@@ -632,8 +630,7 @@ public class MockJakSrvltHttpRequest implements \
                HttpServletRequest {
      * @see javax.servlet.ServletRequest#setCharacterEncoding(String)
      */
     @Override
-    public void setCharacterEncoding(final String arg0)
-        throws UnsupportedEncodingException {
+    public void setCharacterEncoding(final String arg0) throws \
UnsupportedEncodingException {  }

     /**
@@ -658,8 +655,7 @@ public class MockJakSrvltHttpRequest implements \
HttpServletRequest {  }

     @Override
-    public AsyncContext startAsync(final ServletRequest servletRequest, final \
                ServletResponse servletResponse)
-            throws IllegalStateException {
+    public AsyncContext startAsync(final ServletRequest servletRequest, final \
ServletResponse servletResponse) throws IllegalStateException {  throw new \
IllegalStateException("Not implemented");  }

@@ -667,4 +663,9 @@ public class MockJakSrvltHttpRequest implements \
                HttpServletRequest {
     public <T extends HttpUpgradeHandler> T upgrade(final Class<T> handlerClass) \
throws IOException, ServletException {  throw new IllegalStateException("Not \
implemented");  }
+
+//    @Override
+//    public ServletConnection getServletConnection() {
+//        throw new IllegalStateException("Not implemented 6.0.0");
+//    }
 }
diff --git a/commons-fileupload2-javax/.checkstyle \
b/commons-fileupload2-javax/.checkstyle new file mode 100644
index 0000000..192ffcc
--- /dev/null
+++ b/commons-fileupload2-javax/.checkstyle
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="false" \
sync-formatter="false"> +  <local-check-config name="maven-checkstyle-plugin \
validate-main" location="file:/C:/Users/ggregory/git/a/commons-fileupload/commons-fileupload2-javax/../src/checkstyle/fileupload_checks.xml" \
type="remote" description="maven-checkstyle-plugin configuration validate-main"> +    \
<property name="checkstyle.header.file" value="C:\Users\ggregory\OneDrive - Rocket \
Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.project \
s\commons-fileupload2-javax\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-header-validate-main.txt"/>
 +    <property name="checkstyle.cache.file" \
value="${project_loc}/target/checkstyle-cachefile"/> +    <property \
name="checkstyle.suppressions.file" value="C:\Users\ggregory\OneDrive - Rocket \
Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.project \
s\commons-fileupload2-javax\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-suppressions-validate-main.xml"/>
 +  </local-check-config>
+  <fileset name="java-sources-validate-main" enabled="true" \
check-config-name="maven-checkstyle-plugin validate-main" local="true"> +    \
<file-match-pattern match-pattern="^src/main/java/.*\.java" include-pattern="true"/> \
+    <file-match-pattern match-pattern="^src/main/resources.*\.properties" \
include-pattern="true"/> +    <file-match-pattern match-pattern="^.*\.properties" \
include-pattern="true"/> +    <file-match-pattern \
match-pattern="^src/test/resources.*\.properties" include-pattern="true"/> +  \
</fileset> +</fileset-config>
diff --git a/commons-fileupload2-javax/pom.xml b/commons-fileupload2-javax/pom.xml
new file mode 100644
index 0000000..ba44e85
--- /dev/null
+++ b/commons-fileupload2-javax/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" \
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 \
http://maven.apache.org/maven-v4_0_0.xsd"> +  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.commons</groupId>
+    <artifactId>commons-fileupload2</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>commons-fileupload2-javax</artifactId>
+
+  <name>Apache Commons FileUpload Javax Servlet</name>
+  <description>
+    The Apache Commons FileUpload component provides a simple yet flexible means of \
adding support for multipart +    file upload functionality to servlets and web \
applications. +  </description>
+
+  <properties>
+	<commons.parent.dir>${basedir}/..</commons.parent.dir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-fileupload2-core</artifactId>
+      <version>2.0.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-fileupload2-core</artifactId>
+      <version>2.0.0-SNAPSHOT</version>
+      <classifier>tests</classifier>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>${commons.servlet-api.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>${commons.io.version}</version>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/src/main/java/org/apache/commons/fileupload2/servlet/FileCleanerCleanup.java \
b/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/FileCleanerCleanup.java
 similarity index 55%
rename from src/main/java/org/apache/commons/fileupload2/servlet/FileCleanerCleanup.java
 rename to commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/FileCleanerCleanup.java
 index fcc302e..4f12a7d 100644
--- a/src/main/java/org/apache/commons/fileupload2/servlet/FileCleanerCleanup.java
+++ b/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/FileCleanerCleanup.java
 @@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.fileupload2.servlet;
+package org.apache.commons.fileupload2.javax;

 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
@@ -23,50 +23,39 @@ import javax.servlet.ServletContextListener;
 import org.apache.commons.io.FileCleaningTracker;

 /**
- * A servlet context listener, which ensures that the
- * {@link FileCleaningTracker}'s reaper thread is terminated,
- * when the web application is destroyed.
+ * A servlet context listener, which ensures that the {@link FileCleaningTracker}'s \
                reaper thread is terminated, when the web application is destroyed.
  */
 public class FileCleanerCleanup implements ServletContextListener {

     /**
-     * Attribute name, which is used for storing an instance of
-     * {@link FileCleaningTracker} in the web application.
+     * Attribute name, which is used for storing an instance of {@link \
                FileCleaningTracker} in the web application.
      */
-    public static final String FILE_CLEANING_TRACKER_ATTRIBUTE
-        = FileCleanerCleanup.class.getName() + ".FileCleaningTracker";
+    public static final String FILE_CLEANING_TRACKER_ATTRIBUTE = \
FileCleanerCleanup.class.getName() + ".FileCleaningTracker";

     /**
-     * Gets the instance of {@link FileCleaningTracker}, which is
-     * associated with the given {@link ServletContext}.
+     * Gets the instance of {@link FileCleaningTracker}, which is associated with \
                the given {@link ServletContext}.
      *
      * @param servletContext The servlet context to query
      * @return The contexts tracker
      */
-    public static FileCleaningTracker
-            getFileCleaningTracker(final ServletContext servletContext) {
-        return (FileCleaningTracker)
-            servletContext.getAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE);
+    public static FileCleaningTracker getFileCleaningTracker(final ServletContext \
servletContext) { +        return (FileCleaningTracker) \
servletContext.getAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE);  }

     /**
-     * Sets the instance of {@link FileCleaningTracker}, which is
-     * associated with the given {@link ServletContext}.
+     * Sets the instance of {@link FileCleaningTracker}, which is associated with \
                the given {@link ServletContext}.
      *
      * @param servletContext The servlet context to modify
-     * @param tracker The tracker to set
+     * @param tracker        The tracker to set
      */
-    public static void setFileCleaningTracker(final ServletContext servletContext,
-            final FileCleaningTracker tracker) {
+    public static void setFileCleaningTracker(final ServletContext servletContext, \
                final FileCleaningTracker tracker) {
         servletContext.setAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE, tracker);
     }

     /**
-     * Called when the web application is being destroyed.
-     * Calls {@link FileCleaningTracker#exitWhenFinished()}.
+     * Called when the web application is being destroyed. Calls {@link \
                FileCleaningTracker#exitWhenFinished()}.
      *
-     * @param sce The servlet context, used for calling
-     *     {@link #getFileCleaningTracker(ServletContext)}.
+     * @param sce The servlet context, used for calling {@link \
                #getFileCleaningTracker(ServletContext)}.
      */
     @Override
     public void contextDestroyed(final ServletContextEvent sce) {
@@ -74,16 +63,13 @@ public class FileCleanerCleanup implements ServletContextListener \
{  }

     /**
-     * Called when the web application is initialized. Does
-     * nothing.
+     * Called when the web application is initialized. Does nothing.
      *
-     * @param sce The servlet context, used for calling
-     *   {@link #setFileCleaningTracker(ServletContext, FileCleaningTracker)}.
+     * @param sce The servlet context, used for calling {@link \
                #setFileCleaningTracker(ServletContext, FileCleaningTracker)}.
      */
     @Override
     public void contextInitialized(final ServletContextEvent sce) {
-        setFileCleaningTracker(sce.getServletContext(),
-                new FileCleaningTracker());
+        setFileCleaningTracker(sce.getServletContext(), new FileCleaningTracker());
     }

 }
diff --git a/src/main/java/org/apache/commons/fileupload2/servlet/ServletFileUpload.java \
b/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/ServletFileUpload.java
 similarity index 71%
rename from src/main/java/org/apache/commons/fileupload2/servlet/ServletFileUpload.java
 rename to commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/ServletFileUpload.java
 index d514fae..9287593 100644
--- a/src/main/java/org/apache/commons/fileupload2/servlet/ServletFileUpload.java
+++ b/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/ServletFileUpload.java
 @@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.fileupload2.servlet;
+package org.apache.commons.fileupload2.javax;

 import java.io.IOException;
 import java.util.List;
@@ -32,17 +32,12 @@ import org.apache.commons.fileupload2.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
- * org.apache.commons.fileupload2.FileItem}s associated with a given HTML
- * widget.
+ * 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 \
                org.apache.commons.fileupload2.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.
+ * 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>
  */
 public class ServletFileUpload extends FileUpload {
@@ -53,22 +48,19 @@ public class ServletFileUpload extends FileUpload {
     private static final String POST_METHOD = "POST";

     /**
-     * Tests whether the request contains multipart
-     * content.
+     * Tests whether the request contains multipart content.
      *
      * @param request The servlet request to be evaluated. Must be non-null.
      *
-     * @return {@code true} if the request is multipart;
-     *         {@code false} otherwise.
+     * @return {@code true} if the request is multipart; {@code false} otherwise.
      */
     public static final boolean isMultipartContent(final HttpServletRequest request) \
                {
         return POST_METHOD.equalsIgnoreCase(request.getMethod()) && \
AbstractFileUpload.isMultipartContent(new ServletRequestContext(request));  }

     /**
-     * Constructs an uninitialized instance of this class. A factory must be
-     * configured, using {@code setFileItemFactory()}, before attempting
-     * to parse requests.
+     * Constructs an uninitialized instance of this class. A factory must be \
configured, using {@code setFileItemFactory()}, before attempting to parse +     * \
                requests.
      *
      * @see FileUpload#FileUpload(FileItemFactory)
      */
@@ -76,8 +68,7 @@ public class ServletFileUpload extends FileUpload {
     }

     /**
-     * Constructs an instance of this class which uses the supplied factory to
-     * create {@code FileItem} instances.
+     * Constructs an instance of this class which uses the supplied factory to \
                create {@code FileItem} instances.
      *
      * @see FileUpload#FileUpload()
      * @param fileItemFactory The factory to use for creating file items.
@@ -87,31 +78,24 @@ public class ServletFileUpload extends FileUpload {
     }

     /**
-     * Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
-     * compliant {@code multipart/form-data} file item iterator.
+     * Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant \
                {@code multipart/form-data} file item iterator.
      *
      * @param request The servlet request to be parsed.
-     * @return An iterator to instances of {@code FileItemStream}
-     *         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.
+     * @return An iterator to instances of {@code FileItemStream} 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 FileItemIterator getItemIterator(final HttpServletRequest request) throws \
FileUploadException, IOException {  return super.getItemIterator(new \
ServletRequestContext(request));  }

     /**
-     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
-     * compliant {@code multipart/form-data} stream.
+     * 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.
+     * @throws FileUploadException if there are problems reading/parsing the request \
                or storing files.
      * @since 1.3
      */
     public Map<String, List<FileItem>> parseParameterMap(final HttpServletRequest \
request) throws FileUploadException { @@ -119,14 +103,11 @@ public class \
ServletFileUpload extends FileUpload {  }

     /**
-     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
-     * compliant {@code multipart/form-data} stream.
+     * 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.
+     * @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 HttpServletRequest request) throws \
FileUploadException {  return parseRequest(new ServletRequestContext(request));
diff --git a/src/main/java/org/apache/commons/fileupload2/servlet/ServletRequestContext.java \
b/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/ServletRequestContext.java
 similarity index 93%
rename from src/main/java/org/apache/commons/fileupload2/servlet/ServletRequestContext.java
 rename to commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/ServletRequestContext.java
 index 73a0a15..49c7a16 100644
--- a/src/main/java/org/apache/commons/fileupload2/servlet/ServletRequestContext.java
+++ b/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/ServletRequestContext.java
 @@ -1,81 +1,80 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2.servlet;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.fileupload2.AbstractRequestContext;
-
-/**
- * Provides access to the request information needed for a request made to
- * an HTTP servlet.
- *
- * @since 1.1
- */
-public class ServletRequestContext extends AbstractRequestContext {
-
-    /**
-     * The request for which the context is being provided.
-     */
-    private final HttpServletRequest request;
-
-    /**
-     * Constructs a context for this request.
-     *
-     * @param request The request to which this context applies.
-     */
-    public ServletRequestContext(final HttpServletRequest request) {
-        super(request::getHeader, request::getContentLength);
-        this.request = request;
-    }
-
-    /**
-     * Gets the character encoding for the request.
-     *
-     * @return The character encoding for the request.
-     */
-    @Override
-    public String getCharacterEncoding() {
-        return request.getCharacterEncoding();
-    }
-
-    /**
-     * Gets the content type of the request.
-     *
-     * @return The content type of the request.
-     */
-    @Override
-    public String getContentType() {
-        return request.getContentType();
-    }
-
-    /**
-     * Gets the input stream for the request.
-     *
-     * @return The input stream for the request.
-     *
-     * @throws IOException if a problem occurs.
-     */
-    @Override
-    public InputStream getInputStream() throws IOException {
-        return request.getInputStream();
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2.javax;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload2.AbstractRequestContext;
+
+/**
+ * Provides access to the request information needed for a request made to an HTTP \
servlet. + *
+ * @since 1.1
+ */
+public class ServletRequestContext extends AbstractRequestContext {
+
+    /**
+     * The request for which the context is being provided.
+     */
+    private final HttpServletRequest request;
+
+    /**
+     * Constructs a context for this request.
+     *
+     * @param request The request to which this context applies.
+     */
+    public ServletRequestContext(final HttpServletRequest request) {
+        super(request::getHeader, request::getContentLength);
+        this.request = request;
+    }
+
+    /**
+     * Gets the character encoding for the request.
+     *
+     * @return The character encoding for the request.
+     */
+    @Override
+    public String getCharacterEncoding() {
+        return request.getCharacterEncoding();
+    }
+
+    /**
+     * Gets the content type of the request.
+     *
+     * @return The content type of the request.
+     */
+    @Override
+    public String getContentType() {
+        return request.getContentType();
+    }
+
+    /**
+     * Gets the input stream for the request.
+     *
+     * @return The input stream for the request.
+     *
+     * @throws IOException if a problem occurs.
+     */
+    @Override
+    public InputStream getInputStream() throws IOException {
+        return request.getInputStream();
+    }
+
+}
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
 new file mode 100644
index 0000000..c79ebae
--- /dev/null
+++ b/commons-fileupload2-javax/src/main/java/org/apache/commons/fileupload2/javax/package-info.java
 @@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * <p>
+ * An implementation of {@link org.apache.commons.fileupload2.FileUpload FileUpload} \
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.FileItemFactory FileItemFactory} + * \
implementation, such as {@link \
org.apache.commons.fileupload2.disk.DiskFileItemFactory DiskFileItemFactory}. + * \
</p> + * <p>
+ * The following code fragment demonstrates typical usage.
+ * </p>
+ *
+ * <pre>
+ * DiskFileItemFactory factory = new DiskFileItemFactory();
+ * // Configure the factory here, if desired.
+ * ServletFileUpload upload = new ServletFileUpload(factory);
+ * // Configure the uploader here, if desired.
+ * List fileItems = upload.parseRequest(request);
+ * </pre>
+ * <p>
+ * Please see the FileUpload <a \
href="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a> \
for further details and examples of how to + * use this package.
+ * </p>
+ */
+package org.apache.commons.fileupload2.javax;
diff --git a/src/test/java/org/apache/commons/fileupload2/HttpServletRequestFactory.java \
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/HttpServletRequestFactory.java
 similarity index 72%
rename from src/test/java/org/apache/commons/fileupload2/HttpServletRequestFactory.java
 rename to commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/HttpServletRequestFactory.java
 index e4ee1c9..a01199d 100644
--- a/src/test/java/org/apache/commons/fileupload2/HttpServletRequestFactory.java
+++ b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/HttpServletRequestFactory.java
 @@ -14,29 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.fileupload2;
+package org.apache.commons.fileupload2.javax;

 import javax.servlet.http.HttpServletRequest;

+import org.apache.commons.fileupload2.AbstractFileUpload;
+
 final class HttpServletRequestFactory {

     public static HttpServletRequest createHttpServletRequestWithNullContentType() {
         final byte[] requestData = "foobar".getBytes();
-        return new MockHttpServletRequest(
-                            requestData,
-                            null);
+        return new MockHttpServletRequest(requestData, null);
     }

     static public HttpServletRequest createInvalidHttpServletRequest() {
         final byte[] requestData = "foobar".getBytes();
-        return new MockHttpServletRequest(
-                            requestData,
-                            AbstractFileUpload.MULTIPART_FORM_DATA);
+        return new MockHttpServletRequest(requestData, \
AbstractFileUpload.MULTIPART_FORM_DATA);  }

-    public static HttpServletRequest createValidHttpServletRequest(
-            final String[] strFileNames) {
-        // todo - provide a real implementation
+    public static HttpServletRequest createValidHttpServletRequest(final String[] \
strFileNames) { +        // TODO Provide a real implementation.

         final StringBuilder sbRequestData = new StringBuilder();

@@ -46,9 +43,7 @@ final class HttpServletRequestFactory {

         final byte[] requestData = sbRequestData.toString().getBytes();

-        return new MockHttpServletRequest(
-                            requestData,
-                            AbstractFileUpload.MULTIPART_FORM_DATA);
+        return new MockHttpServletRequest(requestData, \
AbstractFileUpload.MULTIPART_FORM_DATA);  }

 }
diff --git a/src/test/java/org/apache/commons/fileupload2/MockHttpServletRequest.java \
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/MockHttpServletRequest.java
 similarity index 93%
rename from src/test/java/org/apache/commons/fileupload2/MockHttpServletRequest.java
rename to commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/MockHttpServletRequest.java
 index 45a4ec7..32fe8a1 100644
--- a/src/test/java/org/apache/commons/fileupload2/MockHttpServletRequest.java
+++ b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/MockHttpServletRequest.java
 @@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.fileupload2;
+package org.apache.commons.fileupload2.javax;

 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
@@ -32,17 +32,17 @@ import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;

+import org.apache.commons.fileupload2.AbstractFileUpload;
+
 public class MockHttpServletRequest implements HttpServletRequest {

-    private static class MyServletInputStream
-        extends javax.servlet.ServletInputStream {
+    private static class MyServletInputStream extends \
javax.servlet.ServletInputStream {

         private final InputStream inputStream;
         private final int readLimit;

         /**
-         * Creates a new instance, which returns the given
-         * streams data.
+         * Creates a new instance, which returns the given streams data.
          */
         public MyServletInputStream(final InputStream inputStream, final int \
readLimit) {  this.inputStream = inputStream;
@@ -75,24 +75,16 @@ public class MockHttpServletRequest implements HttpServletRequest \
                {
     private final Map<String, String> mHeaders = new java.util.HashMap<>();

     /**
-     * Creates a new instance with the given request data
-     * and content type.
+     * Creates a new instance with the given request data and content type.
      */
-    public MockHttpServletRequest(
-            final byte[] requestData,
-            final String strContentType) {
-        this(new ByteArrayInputStream(requestData),
-                requestData.length, strContentType);
+    public MockHttpServletRequest(final byte[] requestData, final String \
strContentType) { +        this(new ByteArrayInputStream(requestData), \
requestData.length, strContentType);  }

     /**
-     * Creates a new instance with the given request data
-     * and content type.
+     * Creates a new instance with the given request data and content type.
      */
-    public MockHttpServletRequest(
-            final InputStream requestData,
-            final long requestLength,
-            final String strContentType) {
+    public MockHttpServletRequest(final InputStream requestData, final long \
requestLength, final String strContentType) {  mmRequestData = requestData;
         length = requestLength;
         mStrContentType = strContentType;
@@ -545,8 +537,7 @@ public class MockHttpServletRequest implements HttpServletRequest \
                {
      * @see javax.servlet.ServletRequest#setCharacterEncoding(String)
      */
     @Override
-    public void setCharacterEncoding(final String arg0)
-        throws UnsupportedEncodingException {
+    public void setCharacterEncoding(final String arg0) throws \
UnsupportedEncodingException {  }

     /**
diff --git a/src/test/java/org/apache/commons/fileupload2/ProgressListenerTest.java \
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/ProgressListenerTest.java
 similarity index 81%
rename from src/test/java/org/apache/commons/fileupload2/ProgressListenerTest.java
rename to commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/ProgressListenerTest.java
 index dcfae16..9896343 100644
--- a/src/test/java/org/apache/commons/fileupload2/ProgressListenerTest.java
+++ b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/ProgressListenerTest.java
 @@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.fileupload2;
+package org.apache.commons.fileupload2.javax;

 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -25,7 +25,11 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;

-import org.apache.commons.fileupload2.servlet.ServletFileUpload;
+import org.apache.commons.fileupload2.Constants;
+import org.apache.commons.fileupload2.FileItemIterator;
+import org.apache.commons.fileupload2.FileItemStream;
+import org.apache.commons.fileupload2.FileUploadException;
+import org.apache.commons.fileupload2.ProgressListener;
 import org.junit.jupiter.api.Test;

 /**
@@ -55,13 +59,13 @@ public class ProgressListenerTest {

         @Override
         public void update(final long actualBytesRead, final long \
                actualContentLength, final int actualItems) {
-            assertTrue(actualBytesRead >= 0  &&  actualBytesRead <= \
                expectedContentLength);
-            assertTrue(actualContentLength == -1  ||  actualContentLength == \
                expectedContentLength);
-            assertTrue(actualItems >= 0  &&  actualItems <= expectedItems);
+            assertTrue(actualBytesRead >= 0 && actualBytesRead <= \
expectedContentLength); +            assertTrue(actualContentLength == -1 || \
actualContentLength == expectedContentLength); +            assertTrue(actualItems >= \
0 && actualItems <= expectedItems);

-            assertTrue(bytesRead == null  ||  actualBytesRead >= \
bytesRead.longValue()); +            assertTrue(bytesRead == null || actualBytesRead \
>= bytesRead.longValue());  bytesRead = Long.valueOf(actualBytesRead);
-            assertTrue(items == null  ||  actualItems >= items.intValue());
+            assertTrue(items == null || actualItems >= items.intValue());
             items = Integer.valueOf(actualItems);
         }

@@ -100,12 +104,10 @@ public class ProgressListenerTest {
     public void testProgressListener() throws Exception {
         final int NUM_ITEMS = 512;
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        for (int i = 0;  i < NUM_ITEMS;  i++) {
-            final String header = "-----1234\r\n"
-                + "Content-Disposition: form-data; name=\"field" + (i + 1) + \
                "\"\r\n"
-                + "\r\n";
+        for (int i = 0; i < NUM_ITEMS; i++) {
+            final String header = "-----1234\r\n" + "Content-Disposition: form-data; \
name=\"field" + (i + 1) + "\"\r\n" + "\r\n";  \
                baos.write(header.getBytes(StandardCharsets.US_ASCII));
-            for (int j = 0;  j < 16384 + i;  j++) {
+            for (int j = 0; j < 16384 + i; j++) {
                 baos.write((byte) j);
             }
             baos.write("\r\n".getBytes(StandardCharsets.US_ASCII));
diff --git a/src/test/java/org/apache/commons/fileupload2/servlet/ServletFileUploadTest.java \
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/ServletFileUploadTest.java
 similarity index 60%
rename from src/test/java/org/apache/commons/fileupload2/servlet/ServletFileUploadTest.java
 rename to commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/ServletFileUploadTest.java
 index f683a1b..9a245f4 100644
--- a/src/test/java/org/apache/commons/fileupload2/servlet/ServletFileUploadTest.java
+++ b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/ServletFileUploadTest.java
 @@ -14,42 +14,46 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.fileupload2.servlet;
+
+package org.apache.commons.fileupload2.javax;

 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;

+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.nio.charset.StandardCharsets;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;

 import javax.servlet.http.HttpServletRequest;

+import org.apache.commons.fileupload2.AbstractFileUploadTest;
 import org.apache.commons.fileupload2.Constants;
 import org.apache.commons.fileupload2.FileItem;
-import org.apache.commons.fileupload2.FileUploadTest;
-import org.apache.commons.fileupload2.MockHttpServletRequest;
+import org.apache.commons.fileupload2.FileUpload;
+import org.apache.commons.fileupload2.FileUploadException;
 import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
 import org.junit.jupiter.api.Test;

-/**
- * Test for {@link ServletFileUpload}.
- *
- * @see FileUploadTest
- * @since 1.4
- */
-public class ServletFileUploadTest {
+public class ServletFileUploadTest extends AbstractFileUploadTest {
+
+    public ServletFileUploadTest() {
+        super(new ServletFileUpload(new DiskFileItemFactory()));
+    }

     @Test
-    public void parseImpliedUtf8()
-        throws Exception {
+    public void parseImpliedUtf8() throws Exception {
         // utf8 encoded form-data without explicit content-type encoding
+        // @formatter:off
         final String text = "-----1234\r\n" +
                 "Content-Disposition: form-data; name=\"utf8Html\"\r\n" +
                 "\r\n" +
                 "Thís ís the coñteñt of the fíle\n" +
                 "\r\n" +
                 "-----1234--\r\n";
+        // @formatter:on

         final byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
         final HttpServletRequest request = new MockHttpServletRequest(bytes, \
Constants.CONTENT_TYPE); @@ -62,13 +66,12 @@ public class ServletFileUploadTest {
         assertTrue(fileItem.getString().contains("coñteñt"), \
fileItem.getString());  }

-
     /**
      * Test case for <a href="https://issues.apache.org/jira/browse/FILEUPLOAD-210">
      */
     @Test
-    public void parseParameterMap()
-            throws Exception {
+    public void parseParameterMap() throws Exception {
+        // @formatter:off
         final String text = "-----1234\r\n" +
                       "Content-Disposition: form-data; name=\"file\"; \
filename=\"foo.tab\"\r\n" +  "Content-Type: text/whatever\r\n" +
@@ -88,6 +91,7 @@ public class ServletFileUploadTest {
                       "\r\n" +
                       "value2\r\n" +
                       "-----1234--\r\n";
+        // @formatter:on
         final byte[] bytes = text.getBytes(StandardCharsets.US_ASCII);
         final HttpServletRequest request = new MockHttpServletRequest(bytes, \
Constants.CONTENT_TYPE);

@@ -102,4 +106,52 @@ public class ServletFileUploadTest {
         assertTrue(mappedParameters.containsKey("multi"));
         assertEquals(2, mappedParameters.get("multi").size());
     }
+
+    @Override
+    public List<FileItem> parseUpload(final FileUpload upload, final byte[] bytes, \
final String contentType) throws FileUploadException { +        final \
HttpServletRequest request = new MockHttpServletRequest(bytes, contentType); +        \
return upload.parseRequest(new ServletRequestContext(request)); +    }
+
+    /**
+     * Runs a test with varying file sizes.
+     */
+    @Override
+    @Test
+    public void testFileUpload() throws IOException, FileUploadException {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        int add = 16;
+        int num = 0;
+        for (int i = 0; i < 16384; i += add) {
+            if (++add == 32) {
+                add = 16;
+            }
+            final String header = "-----1234\r\n" + "Content-Disposition: form-data; \
name=\"field" + (num++) + "\"\r\n" + "\r\n"; +            \
baos.write(header.getBytes(StandardCharsets.US_ASCII)); +            for (int j = 0; \
j < i; j++) { +                baos.write((byte) j);
+            }
+            baos.write("\r\n".getBytes(StandardCharsets.US_ASCII));
+        }
+        baos.write("-----1234--\r\n".getBytes(StandardCharsets.US_ASCII));
+
+        final List<FileItem> fileItems = parseUpload(new ServletFileUpload(new \
DiskFileItemFactory()), baos.toByteArray()); +        final Iterator<FileItem> \
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();
+            assertEquals("field" + (num++), item.getFieldName());
+            final byte[] bytes = item.get();
+            assertEquals(i, bytes.length);
+            for (int j = 0; j < i; j++) {
+                assertEquals((byte) j, bytes[j]);
+            }
+        }
+        assertTrue(!fileIter.hasNext());
+    }
+
 }
diff --git a/src/test/java/org/apache/commons/fileupload2/SizesTest.java \
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/SizesTest.java
 similarity index 73%
rename from src/test/java/org/apache/commons/fileupload2/SizesTest.java
rename to commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/SizesTest.java
 index c14afda..7d14d16 100644
--- a/src/test/java/org/apache/commons/fileupload2/SizesTest.java
+++ b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/SizesTest.java
 @@ -1,282 +1,244 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload2.pub.FileUploadByteCountLimitException;
-import org.apache.commons.fileupload2.pub.FileUploadSizeException;
-import org.apache.commons.fileupload2.servlet.ServletFileUpload;
-import org.apache.commons.io.IOUtils;
-import org.junit.jupiter.api.Test;
-
-/**
- * Unit test for items with varying sizes.
- */
-public class SizesTest {
-
-    /** Checks, whether limiting the file size works.
-     */
-    @Test
-    public void testFileSizeLimit()
-            throws IOException, FileUploadException {
-        final String request -            "-----1234\r\n" +
-            "Content-Disposition: form-data; name=\"file\"; \
                filename=\"foo.tab\"\r\n" +
-            "Content-Type: text/whatever\r\n" +
-            "\r\n" +
-            "This is the content of the file\n" +
-            "\r\n" +
-            "-----1234--\r\n";
-
-        ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
-        upload.setFileSizeMax(-1);
-        HttpServletRequest req = new MockHttpServletRequest(
-                request.getBytes(StandardCharsets.US_ASCII), \
                Constants.CONTENT_TYPE);
-        List<FileItem> fileItems = upload.parseRequest(req);
-        assertEquals(1, fileItems.size());
-        FileItem item = fileItems.get(0);
-        assertEquals("This is the content of the file\n", new String(item.get()));
-
-        upload = new ServletFileUpload(new DiskFileItemFactory());
-        upload.setFileSizeMax(40);
-        req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
                Constants.CONTENT_TYPE);
-        fileItems = upload.parseRequest(req);
-        assertEquals(1, fileItems.size());
-        item = fileItems.get(0);
-        assertEquals("This is the content of the file\n", new String(item.get()));
-
-        upload = new ServletFileUpload(new DiskFileItemFactory());
-        upload.setFileSizeMax(30);
-        req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
                Constants.CONTENT_TYPE);
-        try {
-            upload.parseRequest(req);
-            fail("Expected exception.");
-        } catch (final FileUploadByteCountLimitException e) {
-            assertEquals(30, e.getPermitted());
-        }
-    }
-
-    /** Checks, whether a faked Content-Length header is detected.
-     */
-    @Test
-    public void testFileSizeLimitWithFakedContentLength()
-            throws IOException, FileUploadException {
-        final String request -            "-----1234\r\n" +
-            "Content-Disposition: form-data; name=\"file\"; \
                filename=\"foo.tab\"\r\n" +
-            "Content-Type: text/whatever\r\n" +
-            "Content-Length: 10\r\n" +
-            "\r\n" +
-            "This is the content of the file\n" +
-            "\r\n" +
-            "-----1234--\r\n";
-
-        ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
-        upload.setFileSizeMax(-1);
-        HttpServletRequest req = new MockHttpServletRequest(
-                request.getBytes(StandardCharsets.US_ASCII), \
                Constants.CONTENT_TYPE);
-        List<FileItem> fileItems = upload.parseRequest(req);
-        assertEquals(1, fileItems.size());
-        FileItem item = fileItems.get(0);
-        assertEquals("This is the content of the file\n", new String(item.get()));
-
-        upload = new ServletFileUpload(new DiskFileItemFactory());
-        upload.setFileSizeMax(40);
-        req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
                Constants.CONTENT_TYPE);
-        fileItems = upload.parseRequest(req);
-        assertEquals(1, fileItems.size());
-        item = fileItems.get(0);
-        assertEquals("This is the content of the file\n", new String(item.get()));
-
-        // provided Content-Length is larger than the FileSizeMax -> handled by ctor
-        upload = new ServletFileUpload(new DiskFileItemFactory());
-        upload.setFileSizeMax(5);
-        req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
                Constants.CONTENT_TYPE);
-        try {
-            upload.parseRequest(req);
-            fail("Expected exception.");
-        } catch (final FileUploadByteCountLimitException e) {
-            assertEquals(5, e.getPermitted());
-        }
-
-        // provided Content-Length is wrong, actual content is larger -> handled by \
                LimitedInputStream
-        upload = new ServletFileUpload(new DiskFileItemFactory());
-        upload.setFileSizeMax(15);
-        req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
                Constants.CONTENT_TYPE);
-        try {
-            upload.parseRequest(req);
-            fail("Expected exception.");
-        } catch (final FileUploadByteCountLimitException e) {
-            assertEquals(15, e.getPermitted());
-        }
-    }
-
-    /**
-     * Runs a test with varying file sizes.
-     */
-    @Test
-    public void testFileUpload()
-            throws IOException, FileUploadException {
-        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        int add = 16;
-        int num = 0;
-        for (int i = 0;  i < 16384;  i += add) {
-            if (++add == 32) {
-                add = 16;
-            }
-            final String header = "-----1234\r\n"
-                + "Content-Disposition: form-data; name=\"field" + (num++) + \
                "\"\r\n"
-                + "\r\n";
-            baos.write(header.getBytes(StandardCharsets.US_ASCII));
-            for (int j = 0;  j < i;  j++) {
-                baos.write((byte) j);
-            }
-            baos.write("\r\n".getBytes(StandardCharsets.US_ASCII));
-        }
-        baos.write("-----1234--\r\n".getBytes(StandardCharsets.US_ASCII));
-
-        final List<FileItem> fileItems -                Util.parseUpload(new \
                ServletFileUpload(new DiskFileItemFactory()), baos.toByteArray());
-        final Iterator<FileItem> 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();
-            assertEquals("field" + (num++), item.getFieldName());
-            final byte[] bytes = item.get();
-            assertEquals(i, bytes.length);
-            for (int j = 0;  j < i;  j++) {
-                assertEquals((byte) j, bytes[j]);
-            }
-        }
-        assertTrue(!fileIter.hasNext());
-    }
-
-    /** Checks, whether the maxSize works.
-     */
-    @Test
-    public void testMaxSizeLimit()
-            throws IOException, FileUploadException {
-        final String request -            "-----1234\r\n" +
-            "Content-Disposition: form-data; name=\"file1\"; \
                filename=\"foo1.tab\"\r\n" +
-            "Content-Type: text/whatever\r\n" +
-            "Content-Length: 10\r\n" +
-            "\r\n" +
-            "This is the content of the file\n" +
-            "\r\n" +
-            "-----1234\r\n" +
-            "Content-Disposition: form-data; name=\"file2\"; \
                filename=\"foo2.tab\"\r\n" +
-            "Content-Type: text/whatever\r\n" +
-            "\r\n" +
-            "This is the content of the file\n" +
-            "\r\n" +
-            "-----1234--\r\n";
-
-        final ServletFileUpload upload = new ServletFileUpload(new \
                DiskFileItemFactory());
-        upload.setFileSizeMax(-1);
-        upload.setSizeMax(200);
-
-        final MockHttpServletRequest req = new MockHttpServletRequest(
-                request.getBytes(StandardCharsets.US_ASCII), \
                Constants.CONTENT_TYPE);
-        try {
-            upload.parseRequest(req);
-            fail("Expected exception.");
-        } catch (final FileUploadSizeException e) {
-            assertEquals(200, e.getPermitted());
-        }
-    }
-
-    @Test
-    public void testMaxSizeLimitUnknownContentLength()
-            throws IOException, FileUploadException {
-        final String request -            "-----1234\r\n" +
-            "Content-Disposition: form-data; name=\"file1\"; \
                filename=\"foo1.tab\"\r\n" +
-            "Content-Type: text/whatever\r\n" +
-            "Content-Length: 10\r\n" +
-            "\r\n" +
-            "This is the content of the file\n" +
-            "\r\n" +
-            "-----1234\r\n" +
-            "Content-Disposition: form-data; name=\"file2\"; \
                filename=\"foo2.tab\"\r\n" +
-            "Content-Type: text/whatever\r\n" +
-            "\r\n" +
-            "This is the content of the file\n" +
-            "\r\n" +
-            "-----1234--\r\n";
-
-        final ServletFileUpload upload = new ServletFileUpload(new \
                DiskFileItemFactory());
-        upload.setFileSizeMax(-1);
-        upload.setSizeMax(300);
-
-        // the first item should be within the max size limit
-        // set the read limit to 10 to simulate a "real" stream
-        // otherwise the buffer would be immediately filled
-
-        final MockHttpServletRequest req = new MockHttpServletRequest(
-                request.getBytes(StandardCharsets.US_ASCII), \
                Constants.CONTENT_TYPE);
-        req.setContentLength(-1);
-        req.setReadLimit(10);
-
-        final FileItemIterator it = upload.getItemIterator(req);
-        assertTrue(it.hasNext());
-
-        final FileItemStream item = it.next();
-        assertFalse(item.isFormField());
-        assertEquals("file1", item.getFieldName());
-        assertEquals("foo1.tab", item.getName());
-
-        {
-            try (final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                    final InputStream stream = item.openStream()) {
-                IOUtils.copy(stream, baos);
-            }
-
-        }
-
-        // the second item is over the size max, thus we expect an error
-        // the header is still within size max -> this shall still succeed
-        assertTrue(it.hasNext());
-
-        assertThrows(FileUploadException.class, () -> {
-            final FileItemStream item2 = it.next();
-            try (final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                    final InputStream stream = item2.openStream()) {
-                IOUtils.copy(stream, baos);
-            }
-        });
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2.javax;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload2.Constants;
+import org.apache.commons.fileupload2.FileItem;
+import org.apache.commons.fileupload2.FileItemIterator;
+import org.apache.commons.fileupload2.FileItemStream;
+import org.apache.commons.fileupload2.FileUploadException;
+import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload2.pub.FileUploadByteCountLimitException;
+import org.apache.commons.fileupload2.pub.FileUploadSizeException;
+import org.apache.commons.io.IOUtils;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Unit test for items with varying sizes.
+ */
+public class SizesTest {
+
+    /**
+     * Checks, whether limiting the file size works.
+     */
+    @Test
+    public void testFileSizeLimit() throws IOException, FileUploadException {
+        // @formatter:off
+        final String request +            "-----1234\r\n" +
+            "Content-Disposition: form-data; name=\"file\"; \
filename=\"foo.tab\"\r\n" + +            "Content-Type: text/whatever\r\n" +
+            "\r\n" +
+            "This is the content of the file\n" +
+            "\r\n" +
+            "-----1234--\r\n";
+        // @formatter:on
+
+        ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
+        upload.setFileSizeMax(-1);
+        HttpServletRequest req = new \
MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
Constants.CONTENT_TYPE); +        List<FileItem> fileItems = \
upload.parseRequest(req); +        assertEquals(1, fileItems.size());
+        FileItem item = fileItems.get(0);
+        assertEquals("This is the content of the file\n", new String(item.get()));
+
+        upload = new ServletFileUpload(new DiskFileItemFactory());
+        upload.setFileSizeMax(40);
+        req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
Constants.CONTENT_TYPE); +        fileItems = upload.parseRequest(req);
+        assertEquals(1, fileItems.size());
+        item = fileItems.get(0);
+        assertEquals("This is the content of the file\n", new String(item.get()));
+
+        upload = new ServletFileUpload(new DiskFileItemFactory());
+        upload.setFileSizeMax(30);
+        req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
Constants.CONTENT_TYPE); +        try {
+            upload.parseRequest(req);
+            fail("Expected exception.");
+        } catch (final FileUploadByteCountLimitException e) {
+            assertEquals(30, e.getPermitted());
+        }
+    }
+
+    /**
+     * Checks, whether a faked Content-Length header is detected.
+     */
+    @Test
+    public void testFileSizeLimitWithFakedContentLength() throws IOException, \
FileUploadException { +        // @formatter:off
+        final String request +            "-----1234\r\n" +
+            "Content-Disposition: form-data; name=\"file\"; \
filename=\"foo.tab\"\r\n" + +            "Content-Type: text/whatever\r\n" +
+            "Content-Length: 10\r\n" +
+            "\r\n" +
+            "This is the content of the file\n" +
+            "\r\n" +
+            "-----1234--\r\n";
+        // @formatter:on
+
+        ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
+        upload.setFileSizeMax(-1);
+        HttpServletRequest req = new \
MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
Constants.CONTENT_TYPE); +        List<FileItem> fileItems = \
upload.parseRequest(req); +        assertEquals(1, fileItems.size());
+        FileItem item = fileItems.get(0);
+        assertEquals("This is the content of the file\n", new String(item.get()));
+
+        upload = new ServletFileUpload(new DiskFileItemFactory());
+        upload.setFileSizeMax(40);
+        req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
Constants.CONTENT_TYPE); +        fileItems = upload.parseRequest(req);
+        assertEquals(1, fileItems.size());
+        item = fileItems.get(0);
+        assertEquals("This is the content of the file\n", new String(item.get()));
+
+        // provided Content-Length is larger than the FileSizeMax -> handled by ctor
+        upload = new ServletFileUpload(new DiskFileItemFactory());
+        upload.setFileSizeMax(5);
+        req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
Constants.CONTENT_TYPE); +        try {
+            upload.parseRequest(req);
+            fail("Expected exception.");
+        } catch (final FileUploadByteCountLimitException e) {
+            assertEquals(5, e.getPermitted());
+        }
+
+        // provided Content-Length is wrong, actual content is larger -> handled by \
LimitedInputStream +        upload = new ServletFileUpload(new \
DiskFileItemFactory()); +        upload.setFileSizeMax(15);
+        req = new MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
Constants.CONTENT_TYPE); +        try {
+            upload.parseRequest(req);
+            fail("Expected exception.");
+        } catch (final FileUploadByteCountLimitException e) {
+            assertEquals(15, e.getPermitted());
+        }
+    }
+
+    /**
+     * Checks whether maxSize works.
+     */
+    @Test
+    public void testMaxSizeLimit() throws IOException, FileUploadException {
+        // @formatter:off
+        final String request +            "-----1234\r\n" +
+            "Content-Disposition: form-data; name=\"file1\"; \
filename=\"foo1.tab\"\r\n" + +            "Content-Type: text/whatever\r\n" +
+            "Content-Length: 10\r\n" +
+            "\r\n" +
+            "This is the content of the file\n" +
+            "\r\n" +
+            "-----1234\r\n" +
+            "Content-Disposition: form-data; name=\"file2\"; \
filename=\"foo2.tab\"\r\n" + +            "Content-Type: text/whatever\r\n" +
+            "\r\n" +
+            "This is the content of the file\n" +
+            "\r\n" +
+            "-----1234--\r\n";
+        // @formatter:on
+
+        final ServletFileUpload upload = new ServletFileUpload(new \
DiskFileItemFactory()); +        upload.setFileSizeMax(-1);
+        upload.setSizeMax(200);
+
+        final MockHttpServletRequest req = new \
MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
Constants.CONTENT_TYPE); +        try {
+            upload.parseRequest(req);
+            fail("Expected exception.");
+        } catch (final FileUploadSizeException e) {
+            assertEquals(200, e.getPermitted());
+        }
+    }
+
+    @Test
+    public void testMaxSizeLimitUnknownContentLength() throws IOException, \
FileUploadException { +        // @formatter:off
+        final String request +            "-----1234\r\n" +
+            "Content-Disposition: form-data; name=\"file1\"; \
filename=\"foo1.tab\"\r\n" + +            "Content-Type: text/whatever\r\n" +
+            "Content-Length: 10\r\n" +
+            "\r\n" +
+            "This is the content of the file\n" +
+            "\r\n" +
+            "-----1234\r\n" +
+            "Content-Disposition: form-data; name=\"file2\"; \
filename=\"foo2.tab\"\r\n" + +            "Content-Type: text/whatever\r\n" +
+            "\r\n" +
+            "This is the content of the file\n" +
+            "\r\n" +
+            "-----1234--\r\n";
+        // @formatter:on
+
+        final ServletFileUpload upload = new ServletFileUpload(new \
DiskFileItemFactory()); +        upload.setFileSizeMax(-1);
+        upload.setSizeMax(300);
+
+        // the first item should be within the max size limit
+        // set the read limit to 10 to simulate a "real" stream
+        // otherwise the buffer would be immediately filled
+
+        final MockHttpServletRequest req = new \
MockHttpServletRequest(request.getBytes(StandardCharsets.US_ASCII), \
Constants.CONTENT_TYPE); +        req.setContentLength(-1);
+        req.setReadLimit(10);
+
+        final FileItemIterator it = upload.getItemIterator(req);
+        assertTrue(it.hasNext());
+
+        final FileItemStream item = it.next();
+        assertFalse(item.isFormField());
+        assertEquals("file1", item.getFieldName());
+        assertEquals("foo1.tab", item.getName());
+
+        {
+            try (final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    final InputStream stream = item.openStream()) {
+                IOUtils.copy(stream, baos);
+            }
+
+        }
+
+        // the second item is over the size max, thus we expect an error
+        // the header is still within size max -> this shall still succeed
+        assertTrue(it.hasNext());
+
+        assertThrows(FileUploadException.class, () -> {
+            final FileItemStream item2 = it.next();
+            try (final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    final InputStream stream = item2.openStream()) {
+                IOUtils.copy(stream, baos);
+            }
+        });
+    }
+}
diff --git a/src/test/java/org/apache/commons/fileupload2/StreamingTest.java \
b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/StreamingTest.java
 similarity index 85%
rename from src/test/java/org/apache/commons/fileupload2/StreamingTest.java
rename to commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/StreamingTest.java
 index 4e331ad..0a85d7d 100644
--- a/src/test/java/org/apache/commons/fileupload2/StreamingTest.java
+++ b/commons-fileupload2-javax/src/test/java/org/apache/commons/fileupload2/javax/StreamingTest.java
 @@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.fileupload2;
+package org.apache.commons.fileupload2.javax;

 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -32,9 +32,14 @@ import java.util.List;

 import javax.servlet.http.HttpServletRequest;

+import org.apache.commons.fileupload2.AbstractFileUpload;
+import org.apache.commons.fileupload2.FileItem;
+import org.apache.commons.fileupload2.FileItemIterator;
+import org.apache.commons.fileupload2.FileItemStream;
+import org.apache.commons.fileupload2.FileUploadException;
+import org.apache.commons.fileupload2.InvalidFileNameException;
+import org.apache.commons.fileupload2.MultipartStream;
 import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload2.servlet.ServletFileUpload;
-import org.apache.commons.fileupload2.servlet.ServletRequestContext;
 import org.junit.jupiter.api.Test;

 /**
@@ -47,10 +52,11 @@ public class StreamingTest {
     }

     private String getHeader(final String value) {
+        // @formatter:off
         return "-----1234\r\n"
             + "Content-Disposition: form-data; name=\"" + value + "\"\r\n"
             + "\r\n";
-
+        // @formatter:on
     }

     private byte[] newRequest() throws IOException {
@@ -89,26 +95,22 @@ public class StreamingTest {
         return parseUpload(new ByteArrayInputStream(bytes), bytes.length);
     }

-    private List<FileItem> parseUpload(final InputStream inputStream, final int \
                length)
-            throws FileUploadException {
+    private List<FileItem> parseUpload(final InputStream inputStream, final int \
                length) throws FileUploadException {
         final String contentType = "multipart/form-data; boundary=---1234";

         final AbstractFileUpload upload = new ServletFileUpload();
         upload.setFileItemFactory(new DiskFileItemFactory());
-        final HttpServletRequest request = new MockHttpServletRequest(inputStream,
-                length, contentType);
+        final HttpServletRequest request = new MockHttpServletRequest(inputStream, \
length, contentType);

         return upload.parseRequest(new ServletRequestContext(request));
     }

-    private FileItemIterator parseUpload(final int length, final InputStream \
                inputStream)
-            throws FileUploadException, IOException {
+    private FileItemIterator parseUpload(final int length, final InputStream \
                inputStream) throws FileUploadException, IOException {
         final String contentType = "multipart/form-data; boundary=---1234";

         final AbstractFileUpload upload = new ServletFileUpload();
         upload.setFileItemFactory(new DiskFileItemFactory());
-        final HttpServletRequest request = new MockHttpServletRequest(inputStream,
-                length, contentType);
+        final HttpServletRequest request = new MockHttpServletRequest(inputStream, \
length, contentType);

         return upload.getItemIterator(new ServletRequestContext(request));
     }
@@ -117,14 +119,13 @@ public class StreamingTest {
      * Tests a file upload with varying file sizes.
      */
     @Test
-    public void testFileUpload()
-            throws IOException, FileUploadException {
+    public void testFileUpload() throws IOException, FileUploadException {
         final byte[] request = newRequest();
         final List<FileItem> fileItems = parseUpload(request);
         final Iterator<FileItem> fileIter = fileItems.iterator();
         int add = 16;
         int num = 0;
-        for (int i = 0;  i < 16384;  i += add) {
+        for (int i = 0; i < 16384; i += add) {
             if (++add == 32) {
                 add = 16;
             }
@@ -132,7 +133,7 @@ public class StreamingTest {
             assertEquals("field" + (num++), item.getFieldName());
             final byte[] bytes = item.get();
             assertEquals(i, bytes.length);
-            for (int j = 0;  j < i;  j++) {
+            for (int j = 0; j < i; j++) {
                 assertEquals((byte) j, bytes[j]);
             }
         }
@@ -143,20 +144,17 @@ public class StreamingTest {
      * Test for FILEUPLOAD-135
      */
     @Test
-    public void testFILEUPLOAD135()
-            throws IOException, FileUploadException {
+    public void testFILEUPLOAD135() throws IOException, FileUploadException {
         final byte[] request = newShortRequest();
         final ByteArrayInputStream bais = new ByteArrayInputStream(request);
         final List<FileItem> fileItems = parseUpload(new InputStream() {
             @Override
-            public int read()
-            throws IOException
-            {
+            public int read() throws IOException {
                 return bais.read();
             }
+
             @Override
-            public int read(final byte[] b, final int off, final int len) throws \
                IOException
-            {
+            public int read(final byte[] b, final int off, final int len) throws \
IOException {  return bais.read(b, off, Math.min(len, 3));
             }

@@ -167,19 +165,17 @@ public class StreamingTest {
         assertEquals("field", item.getFieldName());
         final byte[] bytes = item.get();
         assertEquals(3, bytes.length);
-        assertEquals((byte)'1', bytes[0]);
-        assertEquals((byte)'2', bytes[1]);
-        assertEquals((byte)'3', bytes[2]);
+        assertEquals((byte) '1', bytes[0]);
+        assertEquals((byte) '2', bytes[1]);
+        assertEquals((byte) '3', bytes[2]);
         assertTrue(!fileIter.hasNext());
     }

     /**
-     * Tests, whether an invalid request throws a proper
-     * exception.
+     * Tests, whether an invalid request throws a proper exception.
      */
     @Test
-    public void testFileUploadException()
-            throws IOException, FileUploadException {
+    public void testFileUploadException() throws IOException, FileUploadException {
         final byte[] request = newRequest();
         final byte[] invalidRequest = new byte[request.length - 11];
         System.arraycopy(request, 0, invalidRequest, 0, request.length - 11);
@@ -197,6 +193,7 @@ public class StreamingTest {
     @Test
     public void testInvalidFileNameException() throws Exception {
         final String fileName = "foo.exe\u0000.png";
+        // @formatter:off
         final String request              "-----1234\r\n" +
             "Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName \
+ "\"\r\n" + @@ -217,6 +214,7 @@ public class StreamingTest {
             "\r\n" +
             "value2\r\n" +
             "-----1234--\r\n";
+        // @formatter:on
         final byte[] reqBytes = request.getBytes(StandardCharsets.US_ASCII);

         final FileItemIterator fileItemIter = parseUpload(reqBytes.length, new \
ByteArrayInputStream(reqBytes)); @@ -244,11 +242,11 @@ public class StreamingTest {
      * Tests, whether an IOException is properly delegated.
      */
     @Test
-    public void testIOException()
-            throws IOException {
+    public void testIOException() throws IOException {
         final byte[] request = newRequest();
         final InputStream stream = new FilterInputStream(new \
ByteArrayInputStream(request)) {  private int num;
+
             @Override
             public int read() throws IOException {
                 if (++num > 123) {
@@ -256,10 +254,10 @@ public class StreamingTest {
                 }
                 return super.read();
             }
+
             @Override
-            public int read(final byte[] buffer, final int offset, final int length)
-                    throws IOException {
-                for (int i = 0;  i < length;  i++) {
+            public int read(final byte[] buffer, final int offset, final int length) \
throws IOException { +                for (int i = 0; i < length; i++) {
                     final int res = read();
                     if (res == -1) {
                         return i == 0 ? -1 : i;
diff --git a/commons-fileupload2-portlet/.checkstyle \
b/commons-fileupload2-portlet/.checkstyle new file mode 100644
index 0000000..b97f1a3
--- /dev/null
+++ b/commons-fileupload2-portlet/.checkstyle
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="false" \
sync-formatter="false"> +  <local-check-config name="maven-checkstyle-plugin \
validate-main" location="file:/C:/Users/ggregory/git/a/commons-fileupload/commons-fileupload2-portlet/../src/checkstyle/fileupload_checks.xml" \
type="remote" description="maven-checkstyle-plugin configuration validate-main"> +    \
<property name="checkstyle.header.file" value="C:\Users\ggregory\OneDrive - Rocket \
Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.project \
s\commons-fileupload2-portlet\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-header-validate-main.txt"/>
 +    <property name="checkstyle.cache.file" \
value="${project_loc}/target/checkstyle-cachefile"/> +    <property \
name="checkstyle.suppressions.file" value="C:\Users\ggregory\OneDrive - Rocket \
Software, Inc\ew\apache-commons\.metadata\.plugins\org.eclipse.core.resources\.project \
s\commons-fileupload2-portlet\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-suppressions-validate-main.xml"/>
 +  </local-check-config>
+  <fileset name="java-sources-validate-main" enabled="true" \
check-config-name="maven-checkstyle-plugin validate-main" local="true"> +    \
<file-match-pattern match-pattern="^src/main/java/.*\.java" include-pattern="true"/> \
+    <file-match-pattern match-pattern="^src/main/resources.*\.properties" \
include-pattern="true"/> +    <file-match-pattern match-pattern="^.*\.properties" \
include-pattern="true"/> +    <file-match-pattern \
match-pattern="^src/test/resources.*\.properties" include-pattern="true"/> +  \
</fileset> +</fileset-config>
diff --git a/commons-fileupload2-portlet/.gitignore \
b/commons-fileupload2-portlet/.gitignore new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/commons-fileupload2-portlet/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/commons-fileupload2-portlet/pom.xml \
b/commons-fileupload2-portlet/pom.xml new file mode 100644
index 0000000..f30af2e
--- /dev/null
+++ b/commons-fileupload2-portlet/pom.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" \
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 \
http://maven.apache.org/maven-v4_0_0.xsd"> +  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.commons</groupId>
+    <artifactId>commons-fileupload2</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>commons-fileupload2-portlet</artifactId>
+
+  <name>Apache Commons FileUpload Portlet</name>
+  <description>
+    The Apache Commons FileUpload component provides a simple yet flexible means of \
adding support for multipart +    file upload functionality to servlets and web \
applications. +  </description>
+
+  <properties>
+	<commons.parent.dir>${basedir}/..</commons.parent.dir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-fileupload2-core</artifactId>
+      <version>2.0.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-fileupload2-core</artifactId>
+      <version>2.0.0-SNAPSHOT</version>
+      <classifier>tests</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-fileupload2-javax</artifactId>
+      <version>2.0.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-fileupload2-javax</artifactId>
+      <version>2.0.0-SNAPSHOT</version>
+      <classifier>tests</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>${commons.servlet-api.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>portlet-api</groupId>
+      <artifactId>portlet-api</artifactId>
+      <version>1.0</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/src/main/java/org/apache/commons/fileupload2/portlet/PortletFileUpload.java \
b/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/PortletFileUpload.java
 similarity index 66%
rename from src/main/java/org/apache/commons/fileupload2/portlet/PortletFileUpload.java
 rename to commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/PortletFileUpload.java
 index 2224018..2384792 100644
--- a/src/main/java/org/apache/commons/fileupload2/portlet/PortletFileUpload.java
+++ b/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/PortletFileUpload.java
 @@ -32,40 +32,32 @@ import org.apache.commons.fileupload2.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 org.apache.commons.fileupload2.servlet.ServletFileUpload
- * #parseRequest(javax.servlet.http.HttpServletRequest)} to acquire a list
- * of {@link org.apache.commons.fileupload2.FileItem FileItems} associated
- * with a given HTML widget.
+ * 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 \
org.apache.commons.fileupload2.javax.ServletFileUpload + * \
#parseRequest(javax.servlet.http.HttpServletRequest)} to acquire a list of {@link \
org.apache.commons.fileupload2.FileItem FileItems} 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.
+ * 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>
+ *
  * @since 1.1
  */
 public class PortletFileUpload extends FileUpload {

     /**
-     * Tests whether the request contains multipart
-     * content.
+     * Tests whether the request contains multipart content.
      *
      * @param request The portlet request to be evaluated. Must be non-null.
-     * @return {@code true} if the request is multipart;
-     *         {@code false} otherwise.
+     * @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 \
PortletRequestContext(request));  }

     /**
-     * Constructs an uninitialized instance of this class. A factory must be
-     * configured, using {@code setFileItemFactory()}, before attempting
-     * to parse requests.
+     * Constructs an uninitialized instance of this class. A factory must be \
configured, using {@code setFileItemFactory()}, before attempting to parse +     * \
                requests.
      *
      * @see FileUpload#FileUpload(FileItemFactory)
      */
@@ -73,8 +65,7 @@ public class PortletFileUpload extends FileUpload {
     }

     /**
-     * Constructs an instance of this class which uses the supplied factory to
-     * create {@code FileItem} instances.
+     * Constructs an instance of this class which uses the supplied factory to \
                create {@code FileItem} instances.
      *
      * @see FileUpload#FileUpload()
      * @param fileItemFactory The factory to use for creating file items.
@@ -84,51 +75,38 @@ public class PortletFileUpload extends FileUpload {
     }

     /**
-     * Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
-     * compliant {@code multipart/form-data} file item iterator.
+     * Gets an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant \
                {@code multipart/form-data} file item iterator.
      *
      * @param request The portlet request to be parsed.
-     * @return An iterator to instances of {@code FileItemStream}
-     *         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.
+     * @return An iterator to instances of {@code FileItemStream} 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 FileItemIterator getItemIterator(final ActionRequest request)
-            throws FileUploadException, IOException {
+    public FileItemIterator getItemIterator(final ActionRequest request) throws \
FileUploadException, IOException {  return super.getItemIterator(new \
PortletRequestContext(request));  }

     /**
-     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
-     * compliant {@code multipart/form-data} stream.
+     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> \
                compliant {@code multipart/form-data} stream.
      *
      * @param request The portlet 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.
+     * @throws FileUploadException if there are problems reading/parsing the request \
                or storing files.
      * @since 1.3
      */
-    public Map<String, List<FileItem>> parseParameterMap(final ActionRequest \
                request)
-            throws FileUploadException {
+    public Map<String, List<FileItem>> parseParameterMap(final ActionRequest \
request) throws FileUploadException {  return parseParameterMap(new \
PortletRequestContext(request));  }

     /**
-     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
-     * compliant {@code multipart/form-data} stream.
+     * Parses an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> \
                compliant {@code multipart/form-data} stream.
      *
      * @param request The portlet 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.
+     * @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 ActionRequest request)
-            throws FileUploadException {
+    public List<FileItem> parseRequest(final ActionRequest request) throws \
FileUploadException {  return parseRequest(new PortletRequestContext(request));
     }

diff --git a/src/main/java/org/apache/commons/fileupload2/portlet/PortletRequestContext.java \
b/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/PortletRequestContext.java
 similarity index 96%
rename from src/main/java/org/apache/commons/fileupload2/portlet/PortletRequestContext.java
 rename to commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/PortletRequestContext.java
 index c1b4077..665d0b7 100644
--- a/src/main/java/org/apache/commons/fileupload2/portlet/PortletRequestContext.java
+++ b/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/PortletRequestContext.java
 @@ -1,79 +1,79 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2.portlet;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.portlet.ActionRequest;
-
-import org.apache.commons.fileupload2.AbstractRequestContext;
-
-/**
- * Provides access to the request information needed for a request made to a \
                portlet.
- *
- * @since 1.1
- */
-public class PortletRequestContext extends AbstractRequestContext {
-
-    /**
-     * The request for which the context is being provided.
-     */
-    private final ActionRequest request;
-
-    /**
-     * Construct a context for this request.
-     *
-     * @param request The request to which this context applies.
-     */
-    public PortletRequestContext(final ActionRequest request) {
-        super(request::getProperty, request::getContentLength);
-        this.request = request;
-    }
-
-    /**
-     * Gets the character encoding for the request.
-     *
-     * @return The character encoding for the request.
-     */
-    @Override
-    public String getCharacterEncoding() {
-        return request.getCharacterEncoding();
-    }
-
-    /**
-     * Gets the content type of the request.
-     *
-     * @return The content type of the request.
-     */
-    @Override
-    public String getContentType() {
-        return request.getContentType();
-    }
-
-    /**
-     * Gets the input stream for the request.
-     *
-     * @return The input stream for the request.
-     * @throws IOException if a problem occurs.
-     */
-    @Override
-    public InputStream getInputStream() throws IOException {
-        return request.getPortletInputStream();
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.fileupload2.portlet;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.portlet.ActionRequest;
+
+import org.apache.commons.fileupload2.AbstractRequestContext;
+
+/**
+ * Provides access to the request information needed for a request made to a \
portlet. + *
+ * @since 1.1
+ */
+public class PortletRequestContext extends AbstractRequestContext {
+
+    /**
+     * The request for which the context is being provided.
+     */
+    private final ActionRequest request;
+
+    /**
+     * Construct a context for this request.
+     *
+     * @param request The request to which this context applies.
+     */
+    public PortletRequestContext(final ActionRequest request) {
+        super(request::getProperty, request::getContentLength);
+        this.request = request;
+    }
+
+    /**
+     * Gets the character encoding for the request.
+     *
+     * @return The character encoding for the request.
+     */
+    @Override
+    public String getCharacterEncoding() {
+        return request.getCharacterEncoding();
+    }
+
+    /**
+     * Gets the content type of the request.
+     *
+     * @return The content type of the request.
+     */
+    @Override
+    public String getContentType() {
+        return request.getContentType();
+    }
+
+    /**
+     * Gets the input stream for the request.
+     *
+     * @return The input stream for the request.
+     * @throws IOException if a problem occurs.
+     */
+    @Override
+    public InputStream getInputStream() throws IOException {
+        return request.getPortletInputStream();
+    }
+
+}
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
 new file mode 100644
index 0000000..0d24735
--- /dev/null
+++ b/commons-fileupload2-portlet/src/main/java/org/apache/commons/fileupload2/portlet/package-info.java
 @@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * <p>
+ * An implementation of {@link org.apache.commons.fileupload2.FileUpload FileUpload} \
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.FileItemFactory FileItemFactory} + * implementation, \
such as {@link org.apache.commons.fileupload2.disk.DiskFileItemFactory \
DiskFileItemFactory}. + * </p>
+ * <p>
+ * The following code fragment demonstrates typical usage.
+ * </p>
+ *
+ * <pre>
+ * DiskFileItemFactory factory = new DiskFileItemFactory();
+ * // Configure the factory here, if desired.
+ * PortletFileUpload upload = new PortletFileUpload(factory);
+ * // Configure the uploader here, if desired.
+ * List fileItems = upload.parseRequest(request);
+ * </pre>
+ * <p>
+ * Please see the FileUpload <a \
href="https://commons.apache.org/fileupload/using.html" target="_top">User Guide</a> \
for further details and examples of how to + * use this package.
+ * </p>
+ */
+package org.apache.commons.fileupload2.portlet;
diff --git a/src/test/java/org/apache/commons/fileupload2/portlet/MockPortletActionRequest.java \
b/commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/MockPortletActionRequest.java
 similarity index 98%
rename from src/test/java/org/apache/commons/fileupload2/portlet/MockPortletActionRequest.java
 rename to commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/MockPortletActionRequest.java
 index ce28b54..4fdda3a 100644
--- a/src/test/java/org/apache/commons/fileupload2/portlet/MockPortletActionRequest.java
                
+++ b/commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/MockPortletActionRequest.java
 @@ -61,8 +61,7 @@ public class MockPortletActionRequest implements ActionRequest {
         this(new ByteArrayInputStream(requestData), requestData.length, \
contentType);  }

-    public MockPortletActionRequest(final ByteArrayInputStream byteArrayInputStream,
-                                    final int requestLength, final String \
contentType) { +    public MockPortletActionRequest(final ByteArrayInputStream \
byteArrayInputStream, final int requestLength, final String contentType) {  \
this.requestData = byteArrayInputStream;  length = requestLength;
         this.contentType = contentType;
diff --git a/src/test/java/org/apache/commons/fileupload2/portlet/PortletFileUploadTest.java \
b/commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/PortletFileUploadTest.java
 similarity index 72%
rename from src/test/java/org/apache/commons/fileupload2/portlet/PortletFileUploadTest.java
 rename to commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/PortletFileUploadTest.java
 index 311c737..1053a9a 100644
--- a/src/test/java/org/apache/commons/fileupload2/portlet/PortletFileUploadTest.java
+++ b/commons-fileupload2-portlet/src/test/java/org/apache/commons/fileupload2/portlet/PortletFileUploadTest.java
 @@ -24,27 +24,33 @@ import java.util.List;
 import java.util.Map;

 import javax.portlet.ActionRequest;
+import javax.servlet.http.HttpServletRequest;

+import org.apache.commons.fileupload2.AbstractFileUploadTest;
 import org.apache.commons.fileupload2.Constants;
 import org.apache.commons.fileupload2.FileItem;
-import org.apache.commons.fileupload2.FileUploadTest;
+import org.apache.commons.fileupload2.FileUpload;
+import org.apache.commons.fileupload2.FileUploadException;
 import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
-import org.junit.jupiter.api.BeforeEach;
+import org.apache.commons.fileupload2.javax.MockHttpServletRequest;
+import org.apache.commons.fileupload2.javax.ServletRequestContext;
 import org.junit.jupiter.api.Test;

 /**
  * Test for {@link PortletFileUpload}.
  *
- * @see FileUploadTest
+ * @see AbstractFileUploadTest
  * @since 1.4
  */
-public class PortletFileUploadTest {
+public class PortletFileUploadTest extends AbstractFileUploadTest {

-    private PortletFileUpload upload;
+    public PortletFileUploadTest() {
+        super(new PortletFileUpload(new DiskFileItemFactory()));
+    }

     @Test
-    public void parseParameterMap()
-            throws Exception {
+    public void parseParameterMap() throws Exception {
+        // @formatter:off
         final String text = "-----1234\r\n" +
                       "Content-Disposition: form-data; name=\"file\"; \
filename=\"foo.tab\"\r\n" +  "Content-Type: text/whatever\r\n" +
@@ -64,10 +70,11 @@ public class PortletFileUploadTest {
                       "\r\n" +
                       "value2\r\n" +
                       "-----1234--\r\n";
+        // @formatter:on
         final byte[] bytes = text.getBytes(StandardCharsets.US_ASCII);
         final ActionRequest request = new MockPortletActionRequest(bytes, \
Constants.CONTENT_TYPE);

-        final Map<String, List<FileItem>> mappedParameters = \
upload.parseParameterMap(request); +        final Map<String, List<FileItem>> \
mappedParameters = ((PortletFileUpload) upload).parseParameterMap(request);  \
assertTrue(mappedParameters.containsKey("file"));  assertEquals(1, \
mappedParameters.get("file").size());

@@ -78,9 +85,10 @@ public class PortletFileUploadTest {
         assertEquals(2, mappedParameters.get("multi").size());
     }

-    @BeforeEach
-    public void setUp() {
-        upload = new PortletFileUpload(new DiskFileItemFactory());
+    @Override
+    public List<FileItem> parseUpload(final FileUpload upload, final byte[] bytes, \
final String contentType) throws FileUploadException { +        final \
HttpServletRequest request = new MockHttpServletRequest(bytes, contentType); +        \
return upload.parseRequest(new ServletRequestContext(request));  }

 }
diff --git a/pom.xml b/pom.xml
index 68f5e5c..e0436b4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,9 +25,10 @@
   </parent>

   <artifactId>commons-fileupload2</artifactId>
-  <version>2.0-SNAPSHOT</version>
+  <version>2.0.0-SNAPSHOT</version>
+  <packaging>pom</packaging>

-  <name>Apache Commons FileUpload</name>
+  <name>Apache Commons FileUpload Parent</name>
   <description>
     The Apache Commons FileUpload component provides a simple yet flexible means of \
adding support for multipart  file upload functionality to servlets and web \
applications. @@ -223,6 +224,7 @@
   <properties>
     <maven.compiler.source>1.8</maven.compiler.source>
     <maven.compiler.target>1.8</maven.compiler.target>
+	<commons.parent.dir>${basedir}</commons.parent.dir>
     <commons.componentid>fileupload</commons.componentid>
     <commons.module.name>org.apache.commons.fileupload</commons.module.name>
     <commons.release.version>2.0</commons.release.version>
@@ -235,6 +237,9 @@
     <commons.osgi.export>!org.apache.commons.fileupload.util.mime,org.apache.commons.*;version=${project.version};-noimport:=true</commons.osgi.export>
  <commons.osgi.import>!javax.portlet,*</commons.osgi.import>
     <commons.osgi.dynamicImport>javax.portlet</commons.osgi.dynamicImport>
+    <commons.servlet-api.version>2.5</commons.servlet-api.version>
+    <commons.io.version>2.11.0</commons.io.version>
+    <commons.lang3.version>3.12.0</commons.lang3.version>
     <japicmp.skip>true</japicmp.skip>
     <clirr.skip>true</clirr.skip>
     <moditect-maven-plugin.version>1.0.0.RC2</moditect-maven-plugin.version>
@@ -249,43 +254,6 @@
     <commons.releaseManagerKey>B6E73D84EA4FCC47166087253FAAD2CD5ECBB314</commons.releaseManagerKey>
  </properties>

-  <dependencies>
-    <dependency>
-      <groupId>org.junit.jupiter</groupId>
-      <artifactId>junit-jupiter</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>servlet-api</artifactId>
-      <version>2.4</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>portlet-api</groupId>
-      <artifactId>portlet-api</artifactId>
-      <version>1.0</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>commons-io</groupId>
-      <artifactId>commons-io</artifactId>
-      <version>2.11.0</version>
-    </dependency>
-    <dependency>
-      <groupId>jakarta.servlet</groupId>
-      <artifactId>jakarta.servlet-api</artifactId>
-      <version>5.0.0</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-lang3</artifactId>
-      <version>3.12.0</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-
   <build>
     <plugins>
       <plugin>
@@ -296,8 +264,8 @@
             <id>validate-main</id>
             <phase>validate</phase>
             <configuration>
-              <configLocation>${basedir}/src/checkstyle/fileupload_checks.xml</configLocation>
                
-              <suppressionsLocation>${basedir}/src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
 +              <configLocation>${commons.parent.dir}/src/checkstyle/fileupload_checks.xml</configLocation>
 +              <suppressionsLocation>${commons.parent.dir}/src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
                
               <includeTestSourceDirectory>false</includeTestSourceDirectory>
               <enableRulesSummary>false</enableRulesSummary>
               <consoleOutput>true</consoleOutput>
@@ -314,8 +282,8 @@
         <artifactId>maven-assembly-plugin</artifactId>
         <configuration>
           <descriptors>
-            <descriptor>${basedir}/src/main/assembly/bin.xml</descriptor>
-            <descriptor>${basedir}/src/main/assembly/src.xml</descriptor>
+            <descriptor>${commons.parent.dir}/src/main/assembly/bin.xml</descriptor>
+            <descriptor>${commons.parent.dir}/src/main/assembly/src.xml</descriptor>
           </descriptors>
           <tarLongFileMode>gnu</tarLongFileMode>
         </configuration>
@@ -429,12 +397,19 @@
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-checkstyle-plugin</artifactId>
           <configuration>
-            <configLocation>${basedir}/src/checkstyle/fileupload_checks.xml</configLocation>
                
-            <suppressionsLocation>${basedir}/src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
 +            <configLocation>${commons.parent.dir}/src/checkstyle/fileupload_checks.xml</configLocation>
 +            <suppressionsLocation>${commons.parent.dir}/src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
                
             <includeTestSourceDirectory>false</includeTestSourceDirectory>
             <enableRulesSummary>false</enableRulesSummary>
           </configuration>
         </plugin>
+        <plugin>
+          <groupId>com.github.spotbugs</groupId>
+          <artifactId>spotbugs-maven-plugin</artifactId>
+          <configuration>
+            <excludeFilterFile>${commons.parent.dir}/spotbugs-exclude-filter.xml</excludeFilterFile>
 +          </configuration>
+        </plugin>
       </plugins>
     </pluginManagement>
     <defaultGoal>clean verify apache-rat:check checkstyle:check javadoc:javadoc \
spotbugs:check</defaultGoal> @@ -462,8 +437,8 @@
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
         <configuration>
-          <configLocation>${basedir}/src/checkstyle/fileupload_checks.xml</configLocation>
                
-          <suppressionsLocation>${basedir}/src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
 +          <configLocation>${commons.parent.dir}/src/checkstyle/fileupload_checks.xml</configLocation>
 +          <suppressionsLocation>${commons.parent.dir}/src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
  <includeTestSourceDirectory>false</includeTestSourceDirectory>
           <enableRulesSummary>false</enableRulesSummary>
         </configuration>
@@ -474,7 +449,7 @@
         <configuration>
           <targetJdk>${maven.compiler.target}</targetJdk>
           <rulesets>
-            <ruleset>${basedir}/src/checkstyle/fileupload_basic.xml</ruleset>
+            <ruleset>${commons.parent.dir}/src/checkstyle/fileupload_basic.xml</ruleset>
  </rulesets>
         </configuration>
       </plugin>
@@ -567,13 +542,6 @@
               </execution>
             </executions>
           </plugin>
-          <plugin>
-            <groupId>com.github.spotbugs</groupId>
-            <artifactId>spotbugs-maven-plugin</artifactId>
-            <configuration>
-              <excludeFilterFile>${basedir}/spotbugs-exclude-filter.xml</excludeFilterFile>
                
-            </configuration>
-          </plugin>
         </plugins>
       </build>
     </profile>
@@ -595,4 +563,10 @@
       </properties>
     </profile>
   </profiles>
+  <modules>
+	<module>commons-fileupload2-core</module>
+	<module>commons-fileupload2-jakarta</module>
+	<module>commons-fileupload2-javax</module>
+	<module>commons-fileupload2-portlet</module>
+  </modules>
 </project>
diff --git a/src/main/java/org/apache/commons/fileupload2/FileItemIterator.java \
b/src/main/java/org/apache/commons/fileupload2/FileItemIterator.java deleted file \
mode 100644 index 160f983..0000000
--- a/src/main/java/org/apache/commons/fileupload2/FileItemIterator.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2;
-
-import java.io.IOException;
-import java.util.List;
-
-import javax.naming.SizeLimitExceededException;
-
-import org.apache.commons.fileupload2.pub.FileUploadByteCountLimitException;
-
-/**
- * An iterator, as returned by
- * {@link AbstractFileUpload#getItemIterator(RequestContext)}.
- */
-public interface FileItemIterator {
-
-    List<FileItem> getFileItems() throws FileUploadException, IOException;
-
-    /**
-     * Gets the maximum size of a single file. An {@link \
                FileUploadByteCountLimitException}
-     * will be thrown, if there is an uploaded file, which is exceeding this value.
-     * By default, this value will be copied from the {@link \
                AbstractFileUpload#getFileSizeMax()
-     * FileUploadBase} object, however, the user may replace the default value with \
                a
-     * request specific value by invoking {@link #setFileSizeMax(long)} on this \
                object.
-     * @return The maximum size of a single, uploaded file. The value -1 indicates \
                "unlimited".
-     */
-    long getFileSizeMax();
-
-    /**
-     * Gets the maximum size of the complete HTTP request. A {@link \
                SizeLimitExceededException}
-     * will be thrown, if the HTTP request will exceed this value.
-     * By default, this value will be copied from the {@link \
                AbstractFileUpload#getSizeMax()
-     * FileUploadBase} object, however, the user may replace the default value with \
                a
-     * request specific value by invoking {@link #setSizeMax(long)} on this object.
-     * @return The maximum size of the complete HTTP request. The value -1 indicates \
                "unlimited".
-     */
-    long getSizeMax();
-
-    /**
-     * Tests whether another instance of {@link FileItemStream}
-     * is available.
-     *
-     * @throws FileUploadException Parsing or processing the
-     *   file item failed.
-     * @throws IOException Reading the file item failed.
-     * @return True, if one or more additional file items
-     *   are available, otherwise false.
-     */
-    boolean hasNext() throws FileUploadException, IOException;
-
-    /**
-     * Returns the next available {@link FileItemStream}.
-     *
-     * @throws java.util.NoSuchElementException No more items are available. Use
-     * {@link #hasNext()} to prevent this exception.
-     * @throws FileUploadException Parsing or processing the
-     *   file item failed.
-     * @throws IOException Reading the file item failed.
-     * @return FileItemStream instance, which provides
-     *   access to the next file item.
-     */
-    FileItemStream next() throws FileUploadException, IOException;
-
-    /**
-     * Sets the maximum size of a single file. An {@link \
                FileUploadByteCountLimitException}
-     * will be thrown, if there is an uploaded file, which is exceeding this value.
-     * By default, this value will be copied from the {@link \
                AbstractFileUpload#getFileSizeMax()
-     * FileUploadBase} object, however, the user may replace the default value with \
                a
-     * request specific value by invoking {@link #setFileSizeMax(long)} on this \
                object, so
-     * there is no need to configure it here.
-     * <p>
-     * <em>Note:</em> Changing this value doesn't affect files, that have already \
                been uploaded.
-     * </p>
-     * @param fileSizeMax The maximum size of a single, uploaded file. The value -1 \
                indicates "unlimited".
-     */
-    void setFileSizeMax(long fileSizeMax);
-
-    /**
-     * Sets the maximum size of the complete HTTP request. A {@link \
                SizeLimitExceededException}
-     * will be thrown, if the HTTP request will exceed this value.
-     * By default, this value will be copied from the {@link \
                AbstractFileUpload#getSizeMax()
-     * FileUploadBase} object, however, the user may replace the default value with \
                a
-     * request specific value by invoking {@link #setSizeMax(long)} on this object.
-     * <p>
-     * <em>Note:</em> Setting the maximum size on this object will work only, if the \
                iterator is not
-     * yet initialized. In other words: If the methods {@link #hasNext()}, {@link \
                #next()} have not
-     * yet been invoked.
-     * </p>
-     * @param sizeMax The maximum size of the complete HTTP request. The value -1 \
                indicates "unlimited".
-     */
-    void setSizeMax(long sizeMax);
-}
diff --git a/src/main/java/org/apache/commons/fileupload2/disk/package-info.java \
b/src/main/java/org/apache/commons/fileupload2/disk/package-info.java deleted file \
mode 100644 index f4b5cff..0000000
--- a/src/main/java/org/apache/commons/fileupload2/disk/package-info.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- *    <p>
- *      A disk-based implementation of the
- *      {@link org.apache.commons.fileupload2.FileItem 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.disk.DiskFileItemFactory \
                DiskFileItemFactory}
- *      would be created, configured, and then passed to a
- *      {@link org.apache.commons.fileupload2.FileUpload FileUpload}
- *      implementation such as
- *      {@link org.apache.commons.fileupload2.servlet.ServletFileUpload \
                ServletFileUpload}
- *      or
- *      {@link org.apache.commons.fileupload2.portlet.PortletFileUpload \
                PortletFileUpload}.
- *    </p>
- *    <p>
- *      The following code fragment demonstrates this usage.
- *    </p>
- * <pre>
- *        DiskFileItemFactory factory = new DiskFileItemFactory();
- *        // maximum size that will be stored in memory
- *        factory.setSizeThreshold(4096);
- *        // the location for saving data that is larger than getSizeThreshold()
- *        factory.setRepository(new File("/tmp"));
- *
- *        ServletFileUpload upload = new ServletFileUpload(factory);
- * </pre>
- *    <p>
- *      Please see the FileUpload
- *      <a href="https://commons.apache.org/fileupload/using.html" \
                target="_top">User Guide</a>
- *      for further details and examples of how to use this package.
- *    </p>
- */
-package org.apache.commons.fileupload2.disk;
diff --git a/src/main/java/org/apache/commons/fileupload2/jaksrvlt/package-info.java \
b/src/main/java/org/apache/commons/fileupload2/jaksrvlt/package-info.java deleted \
file mode 100644 index 1c19bf2..0000000
--- a/src/main/java/org/apache/commons/fileupload2/jaksrvlt/package-info.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- *    <p>
- *      An implementation of
- *      {@link org.apache.commons.fileupload2.FileUpload FileUpload}
- *      for use in servlets conforming to the namespace {@code jakarta.servlet}.
- *
- *    </p>
- *    <p>
- *      The following code fragment demonstrates typical usage.
- *    </p>
- * <pre>
- *        DiskFileItemFactory factory = new DiskFileItemFactory();
- *        // Configure the factory here, if desired.
- *        JakSrvltFileUpload upload = new JakSrvltFileUpload(factory);
- *        // Configure the uploader here, if desired.
- *        List fileItems = upload.parseRequest(request);
- * </pre>
- *    <p>
- *      Please see the FileUpload
- *      <a href="https://commons.apache.org/fileupload/using.html" \
                target="_top">User Guide</a>
- *      for further details and examples of how to use this package.
- *    </p>
- */
-package org.apache.commons.fileupload2.jaksrvlt;
diff --git a/src/main/java/org/apache/commons/fileupload2/portlet/package-info.java \
b/src/main/java/org/apache/commons/fileupload2/portlet/package-info.java deleted file \
mode 100644 index bb1b281..0000000
--- a/src/main/java/org/apache/commons/fileupload2/portlet/package-info.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- *    <p>
- *      An implementation of
- *      {@link org.apache.commons.fileupload2.FileUpload FileUpload}
- *      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.FileItemFactory FileItemFactory}
- *      implementation, such as
- *      {@link org.apache.commons.fileupload2.disk.DiskFileItemFactory \
                DiskFileItemFactory}.
- *    </p>
- *    <p>
- *      The following code fragment demonstrates typical usage.
- *    </p>
- * <pre>
- *        DiskFileItemFactory factory = new DiskFileItemFactory();
- *        // Configure the factory here, if desired.
- *        PortletFileUpload upload = new PortletFileUpload(factory);
- *        // Configure the uploader here, if desired.
- *        List fileItems = upload.parseRequest(request);
- * </pre>
- *    <p>
- *      Please see the FileUpload
- *      <a href="https://commons.apache.org/fileupload/using.html" \
                target="_top">User Guide</a>
- *      for further details and examples of how to use this package.
- *    </p>
- */
-package org.apache.commons.fileupload2.portlet;
diff --git a/src/main/java/org/apache/commons/fileupload2/servlet/package-info.java \
b/src/main/java/org/apache/commons/fileupload2/servlet/package-info.java deleted file \
mode 100644 index d1050fa..0000000
--- a/src/main/java/org/apache/commons/fileupload2/servlet/package-info.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- *    <p>
- *      An implementation of
- *      {@link org.apache.commons.fileupload2.FileUpload FileUpload}
- *      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.FileItemFactory FileItemFactory}
- *      implementation, such as
- *      {@link org.apache.commons.fileupload2.disk.DiskFileItemFactory \
                DiskFileItemFactory}.
- *    </p>
- *    <p>
- *      The following code fragment demonstrates typical usage.
- *    </p>
- * <pre>
- *        DiskFileItemFactory factory = new DiskFileItemFactory();
- *        // Configure the factory here, if desired.
- *        ServletFileUpload upload = new ServletFileUpload(factory);
- *        // Configure the uploader here, if desired.
- *        List fileItems = upload.parseRequest(request);
- * </pre>
- *    <p>
- *      Please see the FileUpload
- *      <a href="https://commons.apache.org/fileupload/using.html" \
                target="_top">User Guide</a>
- *      for further details and examples of how to use this package.
- *    </p>
- */
-package org.apache.commons.fileupload2.servlet;
diff --git a/src/test/java/org/apache/commons/fileupload2/Util.java \
b/src/test/java/org/apache/commons/fileupload2/Util.java deleted file mode 100644
index b35a517..0000000
--- a/src/test/java/org/apache/commons/fileupload2/Util.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.fileupload2;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.fileupload2.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload2.portlet.PortletFileUpload;
-import org.apache.commons.fileupload2.servlet.ServletFileUpload;
-import org.apache.commons.fileupload2.servlet.ServletRequestContext;
-
-/**
- * Test utility methods.
- *
- * @since 1.4
- */
-public class Util {
-
-    /**
-     * Return a list of {@link FileUpload} implementations for parameterized tests.
-     * @return a list of {@link FileUpload} implementations
-     */
-    public static List<FileUpload> fileUploadImplementations() {
-        return Arrays.asList(
-                new ServletFileUpload(new DiskFileItemFactory()),
-                new PortletFileUpload(new DiskFileItemFactory()));
-    }
-
-    public static List<FileItem> parseUpload(final FileUpload upload, final byte[] \
                bytes) throws FileUploadException {
-        return parseUpload(upload, bytes, Constants.CONTENT_TYPE);
-    }
-
-    public static List<FileItem> parseUpload(final FileUpload upload, final byte[] \
                bytes, final String contentType)
-            throws FileUploadException {
-        final HttpServletRequest request = new MockHttpServletRequest(bytes, \
                contentType);
-        return upload.parseRequest(new ServletRequestContext(request));
-    }
-
-    public static List<FileItem> parseUpload(final FileUpload upload, final String \
                content)
-        throws FileUploadException {
-        final byte[] bytes = content.getBytes(StandardCharsets.US_ASCII);
-        return parseUpload(upload, bytes, Constants.CONTENT_TYPE);
-    }
-}


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic