git-svn-id: https://svn.apache.org/repos/asf/commons/proper/fileupload/tags/commons-fileupload-1.2.1rc1@607896 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/b_1_2_1/.classpath b/b_1_2_1/.classpath
new file mode 100644
index 0000000..9befb75
--- /dev/null
+++ b/b_1_2_1/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/java"/>
+ <classpathentry kind="src" path="src/test"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/b_1_2_1/.project b/b_1_2_1/.project
new file mode 100644
index 0000000..2f2a2cb
--- /dev/null
+++ b/b_1_2_1/.project
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>commons-fileupload-1.2</name>
+ <comment>The FileUpload component provides a simple yet flexible means of adding support for multipart file upload functionality to servlets and web applications.</comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.maven.ide.eclipse.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.devzuz.q.maven.jdt.core.mavenNature</nature>
+ <nature>org.maven.ide.eclipse.maven2Nature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/b_1_2_1/.settings/org.eclipse.jdt.core.prefs b/b_1_2_1/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..f16412c
--- /dev/null
+++ b/b_1_2_1/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,74 @@
+#Mon Aug 07 02:40:54 CEST 2006
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.1
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.3
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore
+org.eclipse.jdt.core.compiler.problem.autoboxing=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.3
diff --git a/b_1_2_1/.settings/org.eclipse.jdt.ui.prefs b/b_1_2_1/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..c8d0df1
--- /dev/null
+++ b/b_1_2_1/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,3 @@
+#Sun Jun 18 21:36:57 CEST 2006
+eclipse.preferences.version=1
+internal.default.compliance=default
diff --git a/b_1_2_1/LICENSE.txt b/b_1_2_1/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/b_1_2_1/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed 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.
diff --git a/b_1_2_1/NOTICE.txt b/b_1_2_1/NOTICE.txt
new file mode 100644
index 0000000..686894e
--- /dev/null
+++ b/b_1_2_1/NOTICE.txt
@@ -0,0 +1,5 @@
+Apache Commons FileUpload
+Copyright 2002-2007 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/b_1_2_1/build-gump.xml b/b_1_2_1/build-gump.xml
new file mode 100644
index 0000000..b5d7d58
--- /dev/null
+++ b/b_1_2_1/build-gump.xml
@@ -0,0 +1,36 @@
+<!--
+
+ WARNING: This file is generated! Do not edit by hand!
+
+-->
+
+<project name="maven" default="jar" basedir=".">
+
+ <target
+ name="jar">
+
+ <property name="maven.build.dir" value="target"/>
+ <property name="maven.build.dest" value="${maven.build.dir}/classes"/>
+
+ <mkdir dir="${maven.build.dest}"/>
+
+ <javac
+ destdir="${maven.build.dest}"
+ excludes="**/package.html"
+ debug="false"
+ deprecation="false"
+ optimize="false">
+ <src>
+ <pathelement location="src/java"/>
+ </src>
+ </javac>
+
+ <jar
+ jarfile="${maven.build.dir}/${maven.final.name}.jar"
+ basedir="${maven.build.dest}"
+ excludes="**/package.html"
+ />
+
+ </target>
+
+</project>
diff --git a/b_1_2_1/build.xml b/b_1_2_1/build.xml
new file mode 100644
index 0000000..ebb7b6b
--- /dev/null
+++ b/b_1_2_1/build.xml
@@ -0,0 +1,297 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--build.xml generated by maven from project.xml version 1.2.1
+ on date September 5 2007, time 1015-->
+
+<project default="jar" name="commons-fileupload" basedir=".">
+ <!--Load local and user build preferences-->
+
+ <property file="build.properties">
+ </property>
+ <property file="${user.home}/build.properties">
+ </property>
+ <!--Build properties-->
+
+ <property name="defaulttargetdir" value="${basedir}/target">
+ </property>
+ <property name="libdir" value="${user.home}/.maven/repository">
+ </property>
+ <property name="classesdir" value="${basedir}/target/classes">
+ </property>
+ <property name="testclassesdir" value="${basedir}/target/test-classes">
+ </property>
+ <property name="testreportdir" value="${basedir}/target/test-reports">
+ </property>
+ <property name="distdir" value="${basedir}/dist">
+ </property>
+ <property name="javadocdir" value="${basedir}/dist/docs/api">
+ </property>
+ <property name="final.name" value="commons-fileupload-1.2.1">
+ </property>
+ <property name="proxy.host" value="">
+ </property>
+ <property name="proxy.port" value="">
+ </property>
+ <property name="proxy.username" value="">
+ </property>
+ <property name="proxy.password" value="">
+ </property>
+ <path id="build.classpath">
+ <pathelement location="${libdir}/commons-io/jars/commons-io-1.3.2.jar">
+ </pathelement>
+ <pathelement location="${libdir}/javax.servlet/jars/servlet-api-2.4.jar">
+ </pathelement>
+ <pathelement location="${libdir}/javax.portlet/jars/portlet-api-1.0.jar">
+ </pathelement>
+ <pathelement location="${libdir}/junit/jars/junit-3.8.1.jar">
+ </pathelement>
+ <pathelement location="${libdir}/maven/plugins/maven-xdoc-plugin-1.9.2.jar">
+ </pathelement>
+ <pathelement location="${libdir}/maven/plugins/maven-changelog-plugin-1.9.1.jar">
+ </pathelement>
+ </path>
+ <target name="init" description="o Initializes some properties">
+ <mkdir dir="${libdir}">
+ </mkdir>
+ <condition property="noget">
+ <equals arg2="only" arg1="${build.sysclasspath}">
+ </equals>
+ </condition>
+ <!--Test if JUNIT is present in ANT classpath-->
+
+ <available property="Junit.present" classname="junit.framework.Test">
+ </available>
+ <!--Test if user defined a proxy-->
+
+ <condition property="useProxy">
+ <and>
+ <isset property="proxy.host">
+ </isset>
+ <not>
+ <equals trim="true" arg2="" arg1="${proxy.host}">
+ </equals>
+ </not>
+ </and>
+ </condition>
+ </target>
+ <target name="compile" description="o Compile the code" depends="get-deps">
+ <mkdir dir="${classesdir}">
+ </mkdir>
+ <javac destdir="${classesdir}" deprecation="true" debug="true" optimize="false" excludes="**/package.html">
+ <src>
+ <pathelement location="${basedir}/src/java">
+ </pathelement>
+ </src>
+ <classpath refid="build.classpath">
+ </classpath>
+ </javac>
+ <mkdir dir="${classesdir}/META-INF">
+ </mkdir>
+ <copy todir="${classesdir}/META-INF">
+ <fileset dir="${basedir}/.">
+ <include name="NOTICE.txt">
+ </include>
+ </fileset>
+ </copy>
+ </target>
+ <target name="jar" description="o Create the jar" depends="compile,test">
+ <jar jarfile="${defaulttargetdir}/${final.name}.jar" excludes="**/package.html" basedir="${classesdir}">
+ </jar>
+ </target>
+ <target name="clean" description="o Clean up the generated directories">
+ <delete dir="${defaulttargetdir}">
+ </delete>
+ <delete dir="${distdir}">
+ </delete>
+ </target>
+ <target name="dist" description="o Create a distribution" depends="jar, javadoc">
+ <mkdir dir="dist">
+ </mkdir>
+ <copy todir="dist">
+ <fileset dir="${defaulttargetdir}" includes="*.jar">
+ </fileset>
+ <fileset dir="${basedir}" includes="LICENSE*, README*">
+ </fileset>
+ </copy>
+ </target>
+ <target name="test" description="o Run the test cases" if="test.failure" depends="internal-test">
+ <fail message="There were test failures.">
+ </fail>
+ </target>
+ <target name="internal-test" if="Junit.present" depends="junit-present,compile-tests">
+ <mkdir dir="${testreportdir}">
+ </mkdir>
+ <junit dir="${basedir}" failureproperty="test.failure" printSummary="yes" fork="true" haltonerror="true">
+ <sysproperty key="basedir" value=".">
+ </sysproperty>
+ <formatter type="xml">
+ </formatter>
+ <formatter usefile="false" type="plain">
+ </formatter>
+ <classpath>
+ <path refid="build.classpath">
+ </path>
+ <pathelement path="${testclassesdir}">
+ </pathelement>
+ <pathelement path="${classesdir}">
+ </pathelement>
+ </classpath>
+ <batchtest todir="${testreportdir}">
+ <fileset dir="${basedir}/src/test">
+ <include name="**/*Test.java">
+ </include>
+ </fileset>
+ </batchtest>
+ </junit>
+ </target>
+ <target name="junit-present" unless="Junit.present" depends="init">
+ <echo>================================= WARNING ================================</echo>
+ <echo>Junit isn't present in your ${ANT_HOME}/lib directory. Tests not executed.</echo>
+ <echo>==========================================================================</echo>
+ </target>
+ <target name="compile-tests" if="Junit.present" depends="junit-present,compile">
+ <mkdir dir="${testclassesdir}">
+ </mkdir>
+ <javac destdir="${testclassesdir}" deprecation="true" debug="true" optimize="false" excludes="**/package.html">
+ <src>
+ <pathelement location="${basedir}/src/test">
+ </pathelement>
+ </src>
+ <classpath>
+ <path refid="build.classpath">
+ </path>
+ <pathelement path="${classesdir}">
+ </pathelement>
+ </classpath>
+ </javac>
+ <copy todir="${testclassesdir}">
+ <fileset dir="${basedir}/src/test">
+ <include name="**/*.xml">
+ </include>
+ </fileset>
+ </copy>
+ </target>
+ <target name="javadoc" description="o Generate javadoc" depends="get-deps">
+ <mkdir dir="${javadocdir}">
+ </mkdir>
+ <tstamp>
+ <format pattern="2002-yyyy" property="year">
+ </format>
+ </tstamp>
+ <property name="copyright" value="Copyright &copy; The Apache Software Foundation. All Rights Reserved.">
+ </property>
+ <property name="title" value="FileUpload 1.2.1 API">
+ </property>
+ <javadoc use="true" private="true" destdir="${javadocdir}" author="true" version="true" sourcepath="${basedir}/src/java" packagenames="org.apache.commons.fileupload.*">
+ <classpath>
+ <path refid="build.classpath">
+ </path>
+ </classpath>
+ </javadoc>
+ </target>
+ <target name="get-dep-commons-io.jar" description="o Download the dependency : commons-io.jar" unless="commons-io.jar" depends="init,setProxy,noProxy,get-custom-dep-commons-io.jar">
+ <mkdir dir="${libdir}/commons-io/jars/">
+ </mkdir>
+ <get dest="${libdir}/commons-io/jars/commons-io-1.3.2.jar" usetimestamp="true" ignoreerrors="true" src="http://repo1.maven.org/maven/commons-io/jars/commons-io-1.3.2.jar">
+ </get>
+ <get dest="${libdir}/commons-io/jars/commons-io-1.3.2.jar" usetimestamp="true" ignoreerrors="true" src="http://people.apache.org/repo/m1-snapshot-repository/commons-io/jars/commons-io-1.3.2.jar">
+ </get>
+ </target>
+ <target name="get-custom-dep-commons-io.jar" if="commons-io.jar" depends="init,setProxy,noProxy">
+ <mkdir dir="${libdir}/commons-io/jars/">
+ </mkdir>
+ <get dest="${libdir}/commons-io/jars/commons-io-1.3.2.jar" usetimestamp="true" ignoreerrors="true" src="${commons-io.jar}">
+ </get>
+ </target>
+ <target name="get-dep-servlet-api.jar" description="o Download the dependency : servlet-api.jar" unless="servlet-api.jar" depends="init,setProxy,noProxy,get-custom-dep-servlet-api.jar">
+ <mkdir dir="${libdir}/javax.servlet/jars/">
+ </mkdir>
+ <get dest="${libdir}/javax.servlet/jars/servlet-api-2.4.jar" usetimestamp="true" ignoreerrors="true" src="http://repo1.maven.org/maven/javax.servlet/jars/servlet-api-2.4.jar">
+ </get>
+ <get dest="${libdir}/javax.servlet/jars/servlet-api-2.4.jar" usetimestamp="true" ignoreerrors="true" src="http://people.apache.org/repo/m1-snapshot-repository/javax.servlet/jars/servlet-api-2.4.jar">
+ </get>
+ </target>
+ <target name="get-custom-dep-servlet-api.jar" if="servlet-api.jar" depends="init,setProxy,noProxy">
+ <mkdir dir="${libdir}/javax.servlet/jars/">
+ </mkdir>
+ <get dest="${libdir}/javax.servlet/jars/servlet-api-2.4.jar" usetimestamp="true" ignoreerrors="true" src="${servlet-api.jar}">
+ </get>
+ </target>
+ <target name="get-dep-portlet-api.jar" description="o Download the dependency : portlet-api.jar" unless="portlet-api.jar" depends="init,setProxy,noProxy,get-custom-dep-portlet-api.jar">
+ <mkdir dir="${libdir}/javax.portlet/jars/">
+ </mkdir>
+ <get dest="${libdir}/javax.portlet/jars/portlet-api-1.0.jar" usetimestamp="true" ignoreerrors="true" src="http://repo1.maven.org/maven/javax.portlet/jars/portlet-api-1.0.jar">
+ </get>
+ <get dest="${libdir}/javax.portlet/jars/portlet-api-1.0.jar" usetimestamp="true" ignoreerrors="true" src="http://people.apache.org/repo/m1-snapshot-repository/javax.portlet/jars/portlet-api-1.0.jar">
+ </get>
+ </target>
+ <target name="get-custom-dep-portlet-api.jar" if="portlet-api.jar" depends="init,setProxy,noProxy">
+ <mkdir dir="${libdir}/javax.portlet/jars/">
+ </mkdir>
+ <get dest="${libdir}/javax.portlet/jars/portlet-api-1.0.jar" usetimestamp="true" ignoreerrors="true" src="${portlet-api.jar}">
+ </get>
+ </target>
+ <target name="get-dep-junit.jar" description="o Download the dependency : junit.jar" unless="junit.jar" depends="init,setProxy,noProxy,get-custom-dep-junit.jar">
+ <mkdir dir="${libdir}/junit/jars/">
+ </mkdir>
+ <get dest="${libdir}/junit/jars/junit-3.8.1.jar" usetimestamp="true" ignoreerrors="true" src="http://repo1.maven.org/maven/junit/jars/junit-3.8.1.jar">
+ </get>
+ <get dest="${libdir}/junit/jars/junit-3.8.1.jar" usetimestamp="true" ignoreerrors="true" src="http://people.apache.org/repo/m1-snapshot-repository/junit/jars/junit-3.8.1.jar">
+ </get>
+ </target>
+ <target name="get-custom-dep-junit.jar" if="junit.jar" depends="init,setProxy,noProxy">
+ <mkdir dir="${libdir}/junit/jars/">
+ </mkdir>
+ <get dest="${libdir}/junit/jars/junit-3.8.1.jar" usetimestamp="true" ignoreerrors="true" src="${junit.jar}">
+ </get>
+ </target>
+ <target name="get-dep-maven-xdoc-plugin.jar" description="o Download the dependency : maven-xdoc-plugin.jar" unless="maven-xdoc-plugin.jar" depends="init,setProxy,noProxy,get-custom-dep-maven-xdoc-plugin.jar">
+ <mkdir dir="${libdir}/maven/plugins/">
+ </mkdir>
+ <get dest="${libdir}/maven/plugins/maven-xdoc-plugin-1.9.2.jar" usetimestamp="true" ignoreerrors="true" src="http://repo1.maven.org/maven/maven/plugins/maven-xdoc-plugin-1.9.2.jar">
+ </get>
+ <get dest="${libdir}/maven/plugins/maven-xdoc-plugin-1.9.2.jar" usetimestamp="true" ignoreerrors="true" src="http://people.apache.org/repo/m1-snapshot-repository/maven/plugins/maven-xdoc-plugin-1.9.2.jar">
+ </get>
+ </target>
+ <target name="get-custom-dep-maven-xdoc-plugin.jar" if="maven-xdoc-plugin.jar" depends="init,setProxy,noProxy">
+ <mkdir dir="${libdir}/maven/plugins/">
+ </mkdir>
+ <get dest="${libdir}/maven/plugins/maven-xdoc-plugin-1.9.2.jar" usetimestamp="true" ignoreerrors="true" src="${maven-xdoc-plugin.jar}">
+ </get>
+ </target>
+ <target name="get-dep-maven-changelog-plugin.jar" description="o Download the dependency : maven-changelog-plugin.jar" unless="maven-changelog-plugin.jar" depends="init,setProxy,noProxy,get-custom-dep-maven-changelog-plugin.jar">
+ <mkdir dir="${libdir}/maven/plugins/">
+ </mkdir>
+ <get dest="${libdir}/maven/plugins/maven-changelog-plugin-1.9.1.jar" usetimestamp="true" ignoreerrors="true" src="http://repo1.maven.org/maven/maven/plugins/maven-changelog-plugin-1.9.1.jar">
+ </get>
+ <get dest="${libdir}/maven/plugins/maven-changelog-plugin-1.9.1.jar" usetimestamp="true" ignoreerrors="true" src="http://people.apache.org/repo/m1-snapshot-repository/maven/plugins/maven-changelog-plugin-1.9.1.jar">
+ </get>
+ </target>
+ <target name="get-custom-dep-maven-changelog-plugin.jar" if="maven-changelog-plugin.jar" depends="init,setProxy,noProxy">
+ <mkdir dir="${libdir}/maven/plugins/">
+ </mkdir>
+ <get dest="${libdir}/maven/plugins/maven-changelog-plugin-1.9.1.jar" usetimestamp="true" ignoreerrors="true" src="${maven-changelog-plugin.jar}">
+ </get>
+ </target>
+ <target name="get-deps" unless="noget" depends="get-dep-commons-io.jar,get-dep-servlet-api.jar,get-dep-portlet-api.jar,get-dep-junit.jar,get-dep-maven-xdoc-plugin.jar,get-dep-maven-changelog-plugin.jar">
+ </target>
+ <target name="setProxy" if="useProxy" depends="init">
+ <!--Proxy settings works only with a JDK 1.2 and higher.-->
+
+ <echo>Proxy used :</echo>
+ <echo>Proxy host [${proxy.host}]</echo>
+ <echo>Proxy port [${proxy.port}]</echo>
+ <echo>Proxy user [${proxy.username}]</echo>
+ <setproxy proxyuser="${proxy.username}" proxyport="${proxy.port}" proxypassword="${proxy.password}" proxyhost="${proxy.host}">
+ </setproxy>
+ </target>
+ <target name="noProxy" unless="useProxy" depends="init">
+ <echo>Proxy not used.</echo>
+ </target>
+ <target name="install-maven">
+ <get dest="${user.home}/maven-install-latest.jar" usetimestamp="true" src="${repo}/maven/maven-install-latest.jar">
+ </get>
+ <unjar dest="${maven.home}" src="${user.home}/maven-install-latest.jar">
+ </unjar>
+ </target>
+</project>
\ No newline at end of file
diff --git a/b_1_2_1/doap_fileupload.rdf b/b_1_2_1/doap_fileupload.rdf
new file mode 100644
index 0000000..c09bbf1
--- /dev/null
+++ b/b_1_2_1/doap_fileupload.rdf
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<rdf:RDF xmlns="http://usefulinc.com/ns/doap#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:asfext="http://projects.apache.org/ns/asfext#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:doap="http://usefulinc.com/ns/doap#" xml:lang="en">
+ <Project rdf:about="http://commons.apache.org/fileupload/">
+ <name>Apache Commons FileUpload</name>
+ <homepage rdf:resource="http://commons.apache.org/fileupload/"/>
+ <programming-language>Java</programming-language>
+ <category rdf:resource="http://projects.apache.org/category/library"/>
+ <license rdf:resource="http://usefulinc.com/doap/licenses/asl20"/>
+ <bug-database rdf:resource="http://issues.apache.org/jira/browse/FILEUPLOAD"/>
+ <download-page rdf:resource="http://jakarta.apache.org/site/downloads/downloads_commons-fileupload.cgi"/>
+ <asfext:pmc rdf:resource="http://commons.apache.org/"/>
+ <shortdesc xml:lang="en">File upload component for Java servlets</shortdesc>
+ <description xml:lang="en">
+ The FileUpload component provides a simple yet flexible means of adding
+ support for multipart file upload functionality to servlets and web
+ applications.
+ </description>
+ <repository>
+ <SVNRepository>
+ <browse rdf:resource="http://svn.apache.org/repos/asf"/>
+ <location rdf:resource="http://svn.apache.org/repos/asf/commons/proper/fileupload"/>
+ </SVNRepository>
+ </repository>
+ <release>
+ <revision>
+ <name>commons-fileupload</name>
+ <created>2006-06-08</created>
+ <version>1.1.1</version>
+ </revision>
+ <revision>
+ <name>commons-fileupload</name>
+ <created>2005-12-23</created>
+ <version>1.1</version>
+ </revision>
+ </release>
+ <mailing-list rdf:resource="http://commons.apache.org/mail-lists.html"/>
+ </Project>
+</rdf:RDF>
diff --git a/b_1_2_1/gump.xml b/b_1_2_1/gump.xml
new file mode 100644
index 0000000..b99e8f8
--- /dev/null
+++ b/b_1_2_1/gump.xml
@@ -0,0 +1,56 @@
+<!--
+ 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.
+-->
+<module name="commons-fileupload">
+
+
+ <description>File upload component.</description>
+ <url href="http://commons.apache.org/fileupload/"/>
+
+ <cvs repository="jakarta"/>
+
+ <!-- This is really the cvs module. We need to change this but -->
+ <!-- I will leave this for now until everything works. -->
+
+ <project name="commons-fileupload">
+
+ <!-- Standard Maven target to produce Javadocs, source -->
+ <!-- and binary distributions. -->
+ <ant buildfile="build-gump.xml" target="jar">
+ <property name="maven.final.name" value="commons-fileupload-@@DATE@@"/>
+ </ant>
+
+ <package>org.apache.commons.fileupload</package>
+
+ <!-- All Maven projects need Ant and Xerces to build. -->
+ <depend project="jakarta-ant" inherit="runtime"/>
+ <depend project="xml-xerces"/>
+
+ <depend project="jaf"/>
+ <depend project="servletapi"/>
+
+ <work nested="target/classes"/>
+ <home nested="target"/>
+ <jar name="commons-fileupload-@@DATE@@.jar"/>
+ <javadoc nested="docs/apidocs"/>
+
+ <nag from="Maven Developers <turbine-maven-dev@jakarta.apache.org>"
+ to="dev@commons.apache.org"/>
+
+
+ </project>
+
+</module>
diff --git a/b_1_2_1/maven.xml b/b_1_2_1/maven.xml
new file mode 100644
index 0000000..6a5ce88
--- /dev/null
+++ b/b_1_2_1/maven.xml
@@ -0,0 +1,86 @@
+<!--
+ 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 default="jar:jar"
+ xmlns:ant="jelly:ant">
+
+ <!-- ================================================================== -->
+ <!-- Copy into the binary distribution -->
+ <!-- ================================================================== -->
+ <postGoal name="dist:prepare-bin-filesystem">
+
+ <!-- Copy the NOTICE -->
+ <copy todir="${maven.dist.bin.assembly.dir}">
+ <fileset file='${basedir}/NOTICE.txt'/>
+ </copy>
+
+ </postGoal>
+
+ <!-- ================================================================== -->
+ <!-- Copy into the source distribution -->
+ <!-- ================================================================== -->
+ <postGoal name="dist:prepare-src-filesystem">
+
+ <!-- Copy the NOTICE -->
+ <copy todir="${maven.dist.src.assembly.dir}">
+ <fileset file='${basedir}/NOTICE.txt'/>
+ <fileset file="${basedir}/RELEASE-NOTES.txt"/>
+ <fileset file="${basedir}/fileupload_basic.xml"/>
+ <fileset file="${basedir}/fileupload_checks.xml"/>
+ <fileset file="${basedir}/license-header.txt"/>
+ </copy>
+
+ <!-- Copy xdoc files -->
+ <copy todir="${maven.dist.src.assembly.dir}/xdocs">
+ <fileset dir="${basedir}/xdocs"/>
+ </copy>
+
+ </postGoal>
+
+ <!-- ================================================================== -->
+ <!-- Create MD5 Check Sums -->
+ <!-- ================================================================== -->
+ <postGoal name="dist">
+
+ <!-- create checksum for jar -->
+ <ant:checksum file="${maven.build.dir}/${maven.final.name}.jar" property="jar.md5"/>
+ <ant:echo message="${jar.md5} *${maven.final.name}.jar"
+ file="${maven.build.dir}/${maven.final.name}.jar.md5" />
+
+ <!-- create checksum for binary zip -->
+ <ant:checksum file="${maven.dist.dir}/${maven.final.name}.zip" property="zip.md5"/>
+ <ant:echo message="${zip.md5} *${maven.final.name}.zip"
+ file="${maven.dist.dir}/${maven.final.name}.zip.md5" />
+
+ <!-- create checksum for binary tar.gz -->
+ <ant:checksum file="${maven.dist.dir}/${maven.final.name}.tar.gz" property="tar.gz.md5"/>
+ <ant:echo message="${tar.gz.md5} *${maven.final.name}.tar.gz"
+ file="${maven.dist.dir}/${maven.final.name}.tar.gz.md5" />
+
+ <!-- create checksum for source zip -->
+ <ant:checksum file="${maven.dist.dir}/${maven.final.name}-src.zip" property="src.zip.md5"/>
+ <ant:echo message="${src.zip.md5} *${maven.final.name}-src.zip"
+ file="${maven.dist.dir}/${maven.final.name}-src.zip.md5" />
+
+ <!-- create checksum for source tar.gz -->
+ <ant:checksum file="${maven.dist.dir}/${maven.final.name}-src.tar.gz" property="src.tar.gz.md5"/>
+ <ant:echo message="${src.tar.gz.md5} *${maven.final.name}-src.tar.gz"
+ file="${maven.dist.dir}/${maven.final.name}-src.tar.gz.md5" />
+
+ </postGoal>
+
+</project>
diff --git a/b_1_2_1/pom.xml b/b_1_2_1/pom.xml
new file mode 100644
index 0000000..b51d312
--- /dev/null
+++ b/b_1_2_1/pom.xml
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+<!--
+ 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.
+-->
+ <parent>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-parent</artifactId>
+ <version>5</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.commons.fileupload</groupId>
+ <artifactId>commons-fileupload</artifactId>
+ <version>1.2.1</version>
+ <name>Commons FileUpload</name>
+ <description>
+ The FileUpload component provides a simple yet flexible means of adding support for multipart
+ file upload functionality to servlets and web applications.
+ </description>
+ <url>http://commons.apache.org/fileupload/</url>
+ <issueManagement>
+ <system>jira</system>
+ <url>http://issues.apache.org/jira/browse/FILEUPLOAD</url>
+ </issueManagement>
+ <inceptionYear>2002</inceptionYear>
+
+ <developers>
+ <developer>
+ <name>Martin Cooper</name>
+ <id>martinc</id>
+ <email>martinc@apache.org</email>
+ <organization>EMC</organization>
+ </developer>
+ <developer>
+ <name>dIon Gillard</name>
+ <id>dion</id>
+ <email>dion@apache.org</email>
+ <organization>Multitask Consulting</organization>
+ </developer>
+ <developer>
+ <name>John McNally</name>
+ <id>jmcnally</id>
+ <email>jmcnally@collab.net</email>
+ <organization>CollabNet</organization>
+ </developer>
+ <developer>
+ <name>Daniel Rall</name>
+ <id>dlr</id>
+ <email>dlr@finemaltcoding.com</email>
+ <organization>CollabNet</organization>
+ </developer>
+ <developer>
+ <name>Jason van Zyl</name>
+ <id>jvanzyl</id>
+ <email>jason@zenplex.com</email>
+ <organization>Zenplex</organization>
+ </developer>
+ <developer>
+ <name>Robert Burrell Donkin</name>
+ <id>rdonkin</id>
+ <email>rdonkin@apache.org</email>
+ <organization/>
+ </developer>
+ <developer>
+ <name>Sean C. Sullivan</name>
+ <id>sullis</id>
+ <email>sean |at| seansullivan |dot| com</email>
+ <organization/>
+ </developer>
+ <developer>
+ <name>Jochen Wiedmann</name>
+ <id>jochen</id>
+ <email>jochen.wiedmann@gmail.com</email>
+ <organization/>
+ </developer>
+ </developers>
+
+ <contributors>
+ <contributor>
+ <name>Aaron Freeman</name>
+ <email>aaron@sendthisfile.com</email>
+ </contributor>
+ <contributor>
+ <name>Michael Macaluso</name>
+ <email>michael.public@wavecorp.com</email>
+ </contributor>
+ <contributor>
+ <name>Amichai Rothman</name>
+ <email>amichai2@amichais.net</email>
+ </contributor>
+ <contributor>
+ <name>Alexander Sova</name>
+ <email>bird@noir.crocodile.org</email>
+ </contributor>
+ <contributor>
+ <name>Thomas Vandahl</name>
+ <email>tv@apache.org</email>
+ </contributor>
+ <contributor>
+ <name>Henry Yandell</name>
+ <email>bayard@apache.org</email>
+ </contributor>
+ </contributors>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/fileupload/trunk</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/fileupload/trunk</developerConnection>
+ <url>http://svn.apache.org/viewvc/commons/proper/fileupload/trunk</url>
+ </scm>
+ <properties>
+ <maven.compile.source>1.3</maven.compile.source>
+ <maven.compile.target>1.3</maven.compile.target>
+ </properties>
+
+ <build>
+ <sourceDirectory>src/java</sourceDirectory>
+ <testSourceDirectory>src/test</testSourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/bin.xml</descriptor>
+ <descriptor>src/main/assembly/src.xml</descriptor>
+ </descriptors>
+ <tarLongFileMode>gnu</tarLongFileMode>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.2</version>
+ <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>1.3.2</version>
+ <optional>true</optional>
+ </dependency>
+ </dependencies>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-changes-plugin</artifactId>
+ <configuration>
+ <issueLinkTemplate>%URL%/../%ISSUE%</issueLinkTemplate>
+ </configuration>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>changes-report</report>
+ <report>jira-report</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <configuration>
+ <configLocation>src/checkstyle/fileupload_checks.xml</configLocation>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <configuration>
+ <rulesets>
+ <ruleset>src/checkstyle/fileupload_basic.xml</ruleset>
+ </rulesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>clirr-maven-plugin</artifactId>
+ <configuration>
+ <comparisonVersion>1.2</comparisonVersion>
+ <minSeverity>info</minSeverity>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+</project>
diff --git a/b_1_2_1/project.properties b/b_1_2_1/project.properties
new file mode 100644
index 0000000..dae7c4c
--- /dev/null
+++ b/b_1_2_1/project.properties
@@ -0,0 +1,59 @@
+# 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 R O J E C T P R O P E R T I E S
+# -------------------------------------------------------------------
+
+#
+# Remove the ASF snapshot repository when IO 1.3 is released
+#
+maven.repo.remote=http://repo1.maven.org/maven,http://people.apache.org/repo/m1-snapshot-repository
+
+maven.changelog.factory=org.apache.maven.svnlib.SvnChangeLogFactory
+
+maven.changes.issue.template=%URL%/browse/%ISSUE%
+
+compile.debug = on
+compile.optimize = off
+compile.deprecation = off
+
+maven.compile.source=1.3
+maven.compile.target=1.3
+
+# Jar Manifest and Additional Attributes
+maven.jar.manifest=${basedir}/src/conf/MANIFEST.MF
+maven.jar.manifest.attributes.list=Specification-Version,X-Compile-Source-JDK,X-Compile-Target-JDK
+maven.jar.manifest.attribute.Specification-Version=${pom.currentVersion}
+maven.jar.manifest.attribute.X-Compile-Source-JDK=${maven.compile.source}
+maven.jar.manifest.attribute.X-Compile-Target-JDK=${maven.compile.target}
+
+maven.checkstyle.properties = ${basedir}/src/checkstyle/fileupload_checks.xml
+
+maven.pmd.rulesetfiles=src/checkstyle/fileupload_basic.xml,rulesets/unusedcode.xml,rulesets/imports.xml
+
+maven.javadoc.additionalparam=-tag todo:a:"To Do:"
+maven.linkcheck.enable=true
+
+maven.changelog.type=date
+#maven.changelog.date=lastRelease
+maven.changelog.date=2006-06-08
+
+# documentation properties
+maven.xdoc.date=left
+maven.xdoc.version=${pom.currentVersion}
+maven.xdoc.developmentProcessUrl=http://commons.apache.org/charter.html
+maven.xdoc.poweredby.image=maven-feather.png
+
diff --git a/b_1_2_1/project.xml b/b_1_2_1/project.xml
new file mode 100644
index 0000000..f67d337
--- /dev/null
+++ b/b_1_2_1/project.xml
@@ -0,0 +1,297 @@
+<?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>
+ <pomVersion>3</pomVersion>
+
+ <name>FileUpload</name>
+ <groupId>org.apache.commons.fileupload</groupId>
+ <artifactId>commons-fileupload</artifactId>
+ <currentVersion>1.2.1</currentVersion>
+ <inceptionYear>2002</inceptionYear>
+ <shortDescription>File upload component for Java servlets</shortDescription>
+ <description>
+ The FileUpload component provides a simple yet flexible means of adding
+ support for multipart file upload functionality to servlets and web
+ applications.
+ </description>
+ <logo>/images/logo.png</logo>
+
+ <url>http://commons.apache.org/${pom.artifactId.substring(8)}/</url>
+ <package>org.apache.commons.${pom.artifactId.substring(8)}</package>
+
+ <organization>
+ <name>The Apache Software Foundation</name>
+ <url>http://commons.apache.org/</url>
+ <logo>http://commons.apache.org/images/logo.png</logo>
+ </organization>
+
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>/LICENSE.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <gumpRepositoryId>commons</gumpRepositoryId>
+ <issueTrackingUrl>http://issues.apache.org/jira/</issueTrackingUrl>
+ <siteAddress>people.apache.org</siteAddress>
+ <siteDirectory>/www/commons.apache.org/${pom.artifactId.substring(8)}/</siteDirectory>
+ <distributionDirectory>/www/people.apache.org/builds/commons/${pom.artifactId.substring(8)}/</distributionDirectory>
+
+ <repository>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/${pom.artifactId.substring(8)}/trunk</connection>
+ <url>http://svn.apache.org/repos/asf</url>
+ </repository>
+
+ <mailingLists>
+ <mailingList>
+ <name>Commons Dev List</name>
+ <subscribe>dev-subscribe@commons.apache.org</subscribe>
+ <unsubscribe>dev-unsubscribe@commons.apache.org</unsubscribe>
+ <archive>http://mail-archives.apache.org/mod_mbox/commons-dev/</archive>
+ </mailingList>
+ <mailingList>
+ <name>Commons User List</name>
+ <subscribe>user-subscribe@commons.apache.org</subscribe>
+ <unsubscribe>user-unsubscribe@commons.apache.org</unsubscribe>
+ <archive>http://mail-archives.apache.org/mod_mbox/commons-user/</archive>
+ </mailingList>
+ </mailingLists>
+
+
+ <versions>
+ <version>
+ <id>1.2.1</id>
+ <name>1.2.1</name>
+ <tag>commons-fileupload-1.2.1</tag>
+ </version>
+ <version>
+ <id>1.2</id>
+ <name>1.2</name>
+ <tag>commons-fileupload-1.2</tag>
+ </version>
+ <version>
+ <id>1.1.1</id>
+ <name>1.1.1</name>
+ <tag>FILEUPLOAD_1_1_1</tag>
+ </version>
+ <version>
+ <id>1.1</id>
+ <name>1.1</name>
+ <tag>FILEUPLOAD_1_1</tag>
+ </version>
+ <version>
+ <id>1.1-rc2</id>
+ <name>1.1-rc2</name>
+ <tag>FILEUPLOAD_1_1_RC2</tag>
+ </version>
+ <version>
+ <id>1.1-rc1</id>
+ <name>1.1-rc1</name>
+ <tag>FILEUPLOAD_1_1_RC1</tag>
+ </version>
+ <version>
+ <id>1.0</id>
+ <name>1.0</name>
+ <tag>FILEUPLOAD_1_0</tag>
+ </version>
+ <version>
+ <id>1.0-rc1</id>
+ <name>1.0-rc1</name>
+ <tag>FILEUPLOAD_1_0_RC1</tag>
+ </version>
+ <version>
+ <id>1.0-beta-1</id>
+ <name>1.0-beta-1</name>
+ <tag>FILEUPLOAD_1_0_B1</tag>
+ </version>
+ </versions>
+
+ <developers>
+ <developer>
+ <name>Martin Cooper</name>
+ <id>martinc</id>
+ <email>martinc@apache.org</email>
+ <organization>EMC</organization>
+ </developer>
+ <developer>
+ <name>dIon Gillard</name>
+ <id>dion</id>
+ <email>dion@apache.org</email>
+ <organization>Multitask Consulting</organization>
+ </developer>
+ <developer>
+ <name>John McNally</name>
+ <id>jmcnally</id>
+ <email>jmcnally@collab.net</email>
+ <organization>CollabNet</organization>
+ </developer>
+ <developer>
+ <name>Daniel Rall</name>
+ <id>dlr</id>
+ <email>dlr@finemaltcoding.com</email>
+ <organization>CollabNet</organization>
+ </developer>
+ <developer>
+ <name>Jason van Zyl</name>
+ <id>jvanzyl</id>
+ <email>jason@zenplex.com</email>
+ <organization>Zenplex</organization>
+ </developer>
+ <developer>
+ <name>Robert Burrell Donkin</name>
+ <id>rdonkin</id>
+ <email>rdonkin@apache.org</email>
+ <organization/>
+ </developer>
+ <developer>
+ <name>Sean C. Sullivan</name>
+ <id>sullis</id>
+ <email>sean |at| seansullivan |dot| com</email>
+ <organization></organization>
+ </developer>
+ <developer>
+ <name>Jochen Wiedmann</name>
+ <id>jochen</id>
+ <email>jochen.wiedmann@gmail.com</email>
+ <organization/>
+ </developer>
+ </developers>
+
+ <dependencies>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>1.3.2</version>
+ <url>http://commons.apache.org/io/</url>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.4</version>
+ <url>http://java.sun.com/products/servlet/</url>
+ <properties>
+ <scope>provided</scope>
+ </properties>
+ </dependency>
+ <dependency>
+ <groupId>javax.portlet</groupId>
+ <artifactId>portlet-api</artifactId>
+ <version>1.0</version>
+ <url>http://portals.apache.org/pluto</url>
+ <properties>
+ <scope>provided</scope>
+ <comment>
+ Required only when using FileUpload in a portlet environment.
+ </comment>
+ </properties>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <url>http://www.junit.org/</url>
+ <properties>
+ <scope>test</scope>
+ <comment>
+ <strong>Test Only</strong> - required only for
+ running the FileUpload unit tests.
+ </comment>
+ </properties>
+ </dependency>
+
+ <dependency>
+ <groupId>maven</groupId>
+ <artifactId>maven-xdoc-plugin</artifactId>
+ <version>1.9.2</version>
+ <url>http://maven.apache.org/reference/plugins/xdoc/</url>
+ <type>plugin</type>
+ <properties>
+ <comment>
+ <strong>Site Only</strong> - v1.9.2 (minimum)
+ required for building the FileUpload Site documentation.
+ </comment>
+ </properties>
+ </dependency>
+
+ <dependency>
+ <groupId>maven</groupId>
+ <artifactId>maven-changelog-plugin</artifactId>
+ <version>1.9.1</version>
+ <url>http://maven.apache.org/reference/plugins/changelog/</url>
+ <type>plugin</type>
+ <properties>
+ <comment>
+ <strong>Site Only</strong> - v1.9.1 (minimum)
+ required for building the FileUpload Site documentation.
+ </comment>
+ </properties>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <nagEmailAddress>dev@commons.apache.org</nagEmailAddress>
+ <sourceDirectory>src/java</sourceDirectory>
+ <unitTestSourceDirectory>src/test</unitTestSourceDirectory>
+ <unitTest>
+ <includes>
+ <include>**/*Test.java</include>
+ </includes>
+ <resources>
+ <resource>
+ <directory>${pom.build.unitTestSourceDirectory}</directory>
+ <includes>
+ <include>**/*.xml</include>
+ </includes>
+ </resource>
+ </resources>
+ </unitTest>
+
+ <resources>
+ <resource>
+ <directory>${basedir}</directory>
+ <targetPath>META-INF</targetPath>
+ <includes>
+ <include>NOTICE.txt</include>
+ </includes>
+ </resource>
+ </resources>
+ </build>
+
+ <reports>
+ <report>maven-changes-plugin</report>
+ <report>maven-changelog-plugin</report>
+ <report>maven-checkstyle-plugin</report>
+ <!--report>maven-clover-plugin</report-->
+ <report>maven-developer-activity-plugin</report>
+ <report>maven-faq-plugin</report>
+ <report>maven-file-activity-plugin</report>
+ <report>maven-javadoc-plugin</report>
+ <report>maven-jdepend-plugin</report>
+ <report>maven-junit-report-plugin</report>
+ <report>maven-jxr-plugin</report>
+ <report>maven-license-plugin</report>
+ <!--report>maven-linkcheck-plugin</report-->
+ <report>maven-pmd-plugin</report>
+ <report>maven-simian-plugin</report>
+ <report>maven-tasklist-plugin</report>
+ </reports>
+
+</project>
diff --git a/b_1_2_1/src/changes/changes.xml b/b_1_2_1/src/changes/changes.xml
new file mode 100644
index 0000000..e5dae72
--- /dev/null
+++ b/b_1_2_1/src/changes/changes.xml
@@ -0,0 +1,422 @@
+<?xml version="1.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.
+-->
+
+<!--
+This file is used by the maven-changes-plugin to generate the release notes.
+Useful ways of finding items to add to this file are:
+
+1. Add items when you fix a bug or add a feature (this makes the
+release process easy :-).
+
+2. Do a bugzilla search for tickets closed since the previous release.
+
+3. Use the report generated by the maven-changelog-plugin to see all
+CVS commits. Set the project.properties' maven.changelog.range
+property to the number of days since the last release.
+
+
+The <action> type attribute can be add,update,fix,remove.
+-->
+
+<document>
+
+ <properties>
+ <title>Release Notes</title>
+ <author email="martinc@apache.org">Martin Cooper</author>
+ </properties>
+
+ <body>
+ <release version="1.2.1" date="2008-01-01">
+ <action dev="jochen" type="fix">
+ Upgrade to commons-io-1.4-SNAPSHOT, in order to use the new
+ FileCleaningTracker and fix issues with FileCleaner.
+ </action>
+ <action dev="jochen" type="fix" issue="FILEUPLOAD-129">
+ Made the MockHttpServletRequest comply to the servlet 2.4 specification
+ by applying
+ http://www.sourcelabs.com/dashboards/sash-1.2/patches/commons-fileupload-1.1-1/SUP-520.diff
+ </action>
+ <action dev="jochen" type="add" issue="FILEUPLOAD-130"
+ due-to="Michael Macaluso" due-to-email="michael.public@wavecorp.com">
+ Added support for accessing the file item headers.
+ </action>
+ <action dev="jochen" type="fix" issue="FILEUPLOAD-116"
+ due-to="Amichai Rothman" due-to-email="amichai2@amichais.net">
+ A MalformedStreamException is now thrown, if the size of an items
+ headers exceeds HEADER_PART_SIZE_MAX;
+ </action>
+ <action dev="jochen" type="fix" issue="FILEUPLOAD-134"
+ due-to="Thomas Vandahl" due-to-email="tv@apache.org">
+ DiskFileItem.toString() could throw an NPE.
+ </action>
+ <action dev="jochen" type="fix" issue="FILEUPLOAD-135"
+ due-to="Alexander Sova" due-to-email="bird@noir.crocodile.org">
+ Short files could cause an unexpected end of the item stream.
+ </action>
+ <action dev="jochen" type="fix" issue="FILEUPLOAD-145">
+ A FileSizeLimitExceededException was deferred until the complete
+ file has been uploaded. Additionally, the FileSizeLimitException
+ is now thrown immediately, if the attachments headers contain
+ a content-length value, which exceeds the configured limit.
+ </action>
+ </release>
+
+ <release version="1.2" date="2007-02-13">
+ <action dev="jochen" type="fix" due-to="Aaron Freeman"
+ due-to-email="aaron@sendthisfile.com">
+ Made Streams.asString static.
+ </action>
+ <action dev="jochen" type="update" issue="FILEUPLOAD-109">
+ Eliminated duplicate code.
+ </action>
+ <action dev="jochen" type="add" issue="FILEUPLOAD-112">
+ Added a streaming API.
+ </action>
+ <action dev="jochen" type="fix" issue="FILEUPLOAD-93">
+ Eliminated the necessity of a content-length header.
+ </action>
+ <action dev="jochen" type="fix" issue="FILEUPLOAD-108"
+ due-to="Amichai Rothman" due-to-email="amichai2@amichais.net">
+ Eliminated the limitation of a maximum size for a single
+ header line. (The total size of all headers is already
+ limited, so there's no need for another limit.)
+ </action>
+ <action dev="jochen" type="add" issue="FILEUPLOAD-87">
+ Added the ProgressListener, which allows to implement a
+ progress bar.
+ </action>
+ <action dev="jochen" type="add" issue="FILEUPLOAD-111"
+ due-to="Amichai Rothman" due-to-email="amichai2@amichais.net">
+ Added support for header continuation lines.
+ </action>
+ <action dev="jochen" type="add" issue="FILEUPLOAD-88"
+ due-to="Andrey Aristarkhov" due-to-email="aristarkhov@bitechnology.ru">
+ It is now possible to limit the actual file size and not
+ the request size.
+ </action>
+ <action dev="jochen" type="add" issue="FILEUPLOAD-120"
+ due-to="Henry Yandell" due-to-email="bayard@apache.org">
+ Added the FileCleanerCleanup as an example for how to close
+ down the FileCleaner's reaper thread nicely.
+ </action>
+ <action dev="jochen" type="fix" issue="FILEUPLOAD-123">
+ A descriptive NPE is now thrown, if the FileItemFactory
+ has not been set.
+ </action>
+ </release>
+
+ <release version="1.1.1" date="2006-06-08" description="Bugfix release">
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-20">
+ Cache disk file item size when it is moved to a new location.
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-30">
+ File names were being inadvertently converted to lower case.
+ </action>
+
+ </release>
+
+ <release version="1.1" date="2005-12-24" description="Portlet support, substantial refactoring and numerous bug fixes">
+
+ <action dev="martinc" type="update">
+ Updates for FileUpload 1.1-RC1.
+ </action>
+
+ <action dev="martinc" type="add">
+ Added release notes for FileUpload 1.1.
+ </action>
+
+ <action dev="martinc" type="update">
+ Update the User Guide to document the "right" way of using FileUpload
+ 1.1, rather than the older, and thus deprecated, ways that are
+ compatible with FileUpload 1.0.
+ </action>
+
+ <action dev="martinc" type="add">
+ Add this change log, including all changes since the Commons FileUpload
+ 1.0 release.
+ </action>
+
+ <action dev="martinc" type="update">
+ Update Commons IO dependency to version 1.1.
+ </action>
+
+ <action dev="martinc" type="add">
+ Add custom PMD configuration.
+ </action>
+
+ <action dev="martinc" type="update">
+ Make inner exception classes static, which they should have been all
+ along.
+ </action>
+
+ <action dev="martinc" type="fix">
+ Fix Checkstyle warnings.
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-29" due-to="Rahul Akolkar">
+ Remove Javadoc warnings.
+ </action>
+
+ <action dev="martinc" type="update">
+ Build updates:
+ <ul>
+ <li>
+ Include NOTICE.txt in the jar file and distributions.
+ </li>
+ <li>
+ Include xdocs in source distribution.
+ </li>
+ <li>
+ Create MD5 checksums for distributions.
+ </li>
+ </ul>
+ </action>
+
+ <action dev="martinc" type="add">
+ Add custom Checkstyle configuration.
+ </action>
+
+ <action dev="martinc" type="update">
+ Update dependencies in POM, and add comments and scope.
+ </action>
+
+ <action dev="martinc" type="update">
+ Standardise on @throws instead of having a mixture of that and
+ @exception.
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-50" due-to="Niall Pemberton">
+ Make DiskFileItem serializable. Thanks to Niall Pemberton for the
+ suggestion and patch.
+ </action>
+
+ <action dev="martinc" type="update">
+ Make the temporary file names unique across class loaders, not just
+ within them, by including a UID in the file name.
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-77">
+ Include the actual and permitted sizes in both the exception message
+ and the exception itself.
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-13">
+ If an explicit header encoding is not specified, use the one from the
+ appropriate context (i.e. ServletRequest or ActionRequest).
+ </action>
+
+ <action dev="martinc" type="add">
+ Add getCharacterEncoding to the request context.
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-83">
+ Null check and case insensitivity fixes.
+ </action>
+
+ <action dev="martinc" type="update">
+ Web site updates:
+ <ul>
+ <li>
+ Add detail pages for Source Repository and Issue Tracking, based on
+ those for IO and Validator.
+ </li>
+ <li>
+ Improvements to FileUpload home page, based on similar recent
+ changes to IO and Validator home pages.
+ </li>
+ <li>
+ The Bugzilla component name has a space in it. Fix the URLs.
+ </li>
+ <li>
+ Add an FAQ page, using the Maven plugin to generate it.
+ </li>
+ </ul>
+ </action>
+
+ <action dev="dion" type="fix" issue="COMMONSSITE-2">
+ Fixes to POMs
+ </action>
+
+ <action dev="mrdon" type="update">
+ Setting source and target for Java 1.3
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-37">
+ Fix typos in Javadoc code examples.
+ </action>
+
+ <action dev="martinc" type="fix">
+ Fix typos in exception messages.
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-5">
+ Obtain request content type from container instead of headers.
+ </action>
+
+ <action dev="sullis" type="update">
+ New mock objects from Jetspeed-2, and new FileUpload test cases.
+ </action>
+
+ <action dev="sullis" type="add">
+ added toString() methods
+ </action>
+
+ <action dev="martinc" type="add">
+ Fix up the existing package.html file and add new ones for the newly
+ introduced packages. Fairly minimal, but with a link to the user guide.
+ </action>
+
+ <action dev="martinc" type="update">
+ Substantial refactoring and additions:
+ <ul>
+ <li>
+ The core package is now independent of servlet / portlet / other
+ distinctions, as well as persistence schemes, other than deprecated
+ classes and methods retained for backwards compatibility.
+ </li>
+ <li>
+ Servlet specific functionality has been moved to a new 'servlet'
+ package. Existing users should migrate to this as soon as possible,
+ since the servlet specific functionality in the generic package
+ will be removed in the release after FileUpload 1.1.
+ </li>
+ <li>
+ Support for portlets (JSR 168) has been added, in a new 'portlet'
+ package. This is not well tested at this point, and feedback would
+ be very much appreciated. (This also resolves bug #23620.)
+ </li>
+ <li>
+ The disk-based file item implementation has been moved into a 'disk'
+ package, and renamed from Default* to Disk* to reflect what it
+ really is. The Default* classes have been retained in the top level
+ package for backwards compatibility, but are now deprecated, and
+ will be removed in the release after FileUpload 1.1.
+ </li>
+ <li>
+ The isMultipartRequest method is an unfortunate casualty of this
+ refactoring. That method should really be moved to ServletFileUpload,
+ but since the method is static, it can only exist in either
+ FileUploadBase or ServletFileUpload. Backwards compatibility dictates
+ the former for now, but the latter is the desired state, which
+ implies some future breakage. Fair warning...
+ </li>
+ </ul>
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-4">
+ Specify the encoding (ISO-8859-1) when converting the boundary to a
+ byte array.
+ </action>
+
+ <action dev="martinc" type="update">
+ Convert to Sun coding guidelines.
+ </action>
+
+ <action dev="martinc" type="update">
+ DeferredFileOutputStream moved to Commons IO.
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-16" due-to="Justin Sampson">
+ Workaround for Mac IE5 bug. Thanks to Justin Sampson for the patch and
+ tests for this vexing issue.
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-104">
+ Handle unquoted header parameters.
+ </action>
+
+ <action dev="martinc" type="add" issue="FILEUPLOAD-78">
+ Some documentation on interaction with virus scanners.
+ </action>
+
+ <action dev="martinc" type="add" issue="FILEUPLOAD-31" due-to="Justin Sampson">
+ More unit tests from Justin Sampson.
+ </action>
+
+ <action dev="martinc" type="update" issue="FILEUPLOAD-95">
+ Use FileCleaner from Commons IO to clean up temp files, rather than
+ File.deleteOnExit(), which can cause serious problems in long-running
+ processes.
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-53">
+ Check that HTTP method is POST as part of multipart check.
+ </action>
+
+ <action dev="martinc" type="add">
+ Switch to Commons IO version of DeferredFileOutputStream. Adding IO as
+ a dependency will allow us to take advantage of other classes in that
+ component to fix additional FileUpload bugs.
+ </action>
+
+ <action dev="martinc" type="add" issue="FILEUPLOAD-40">
+ handle quoted boundary specification.
+ </action>
+
+ <action dev="martinc" type="add" issue="FILEUPLOAD-18">
+ use case-independent comparisons for encoding types.
+ </action>
+
+ <action dev="martinc" type="fix">
+ Fix comments to avoid break iterator complaints.
+ </action>
+
+ <action dev="martinc" type="fix" due-to="Yuji Yamano">
+ Fix typos in comments.
+ </action>
+
+ <action dev="martinc" type="add" issue="FILEUPLOAD-101" due-to="Oleg Kalnichevski">
+ Add support for character sets specified for individual parts.
+ </action>
+
+ <action dev="scolebourne" type="update">
+ Change to Apache License 2.0
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-22">
+ Correct the comment for the no-args constructor to reflect the fact
+ that a factory needs to be set before parsing uploads.
+ </action>
+
+ <action dev="martinc" type="update">
+ Collapse some all but duplicated code.
+ </action>
+
+ <action dev="jmcnally" type="fix" issue="FILEUPLOAD-72">
+ Fix example showing FileItem.write to use a File object.
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-21" due-to="Peter Chase">
+ Check for null before attempting to close streams in write().
+ </action>
+
+ <action dev="martinc" type="fix" issue="FILEUPLOAD-67" due-to="Paul Dalton">
+ Correction to sample code in the docs.
+ </action>
+
+ </release>
+
+ <release version="1.0" date="2003-06-26" description="Initial release">
+ </release>
+
+
+ </body>
+
+</document>
diff --git a/b_1_2_1/src/checkstyle/fileupload_basic.xml b/b_1_2_1/src/checkstyle/fileupload_basic.xml
new file mode 100644
index 0000000..6338018
--- /dev/null
+++ b/b_1_2_1/src/checkstyle/fileupload_basic.xml
@@ -0,0 +1,25 @@
+<?xml version="1.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.
+-->
+
+<ruleset name="FileUpload Basic Rules">
+ <description>PMD Basic Ruleset minus the EmptyCatchBlock rule.</description>
+
+ <rule ref="rulesets/basic.xml">
+ <exclude name="EmptyCatchBlock"/>
+ </rule>
+</ruleset>
diff --git a/b_1_2_1/src/checkstyle/fileupload_checks.xml b/b_1_2_1/src/checkstyle/fileupload_checks.xml
new file mode 100644
index 0000000..916f052
--- /dev/null
+++ b/b_1_2_1/src/checkstyle/fileupload_checks.xml
@@ -0,0 +1,224 @@
+<?xml version="1.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.
+-->
+
+<!DOCTYPE module PUBLIC
+ "-//Puppy Crawl//DTD Check Configuration 1.1//EN"
+ "http://www.puppycrawl.com/dtds/configuration_1_1.dtd">
+
+<!--
+ Checkstyle configuration for Commons FileUpload. FileUpload uses the Sun
+ coding guidelines, so this file is almost the same as Maven's sun_checks.xml
+ file. The only changes from that file are:
+
+ - Use a RegexpHeader check instead of a regular Header check, since the
+ copyright years can vary per source file.
+
+ - Disable the HiddenField module, since FileUpload has always used the
+ "this.foo = foo" pattern, which is not recognised by this module.
+
+ - Disable the DesignForExtension module, since fixing those complaints
+ would result in backwards incompatible API changes.
+
+ - Disable the FinalParameters module, since fixing those complaints
+ would result in backwards incompatible API changes.
+-->
+<!--
+
+ Checkstyle configuration that checks the sun coding conventions from:
+
+ - the Java Language Specification at
+ http://java.sun.com/docs/books/jls/second_edition/html/index.html
+
+ - the Sun Code Conventions at http://java.sun.com/docs/codeconv/
+
+ - the Javadoc guidelines at
+ http://java.sun.com/j2se/javadoc/writingdoccomments/index.html
+
+ - the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html
+
+ - some best practices
+
+ Checkstyle is very configurable. Be sure to read the documentation at
+ http://checkstyle.sf.net (or in your downloaded distribution).
+
+ Most Checks are configurable, be sure to consult the documentation.
+
+ To completely disable a check, just comment it out or delete it from the file.
+
+ Finally, it is worth reading the documentation.
+
+-->
+
+<module name="Checker">
+
+ <!-- Checks that a package.html file exists for each package. -->
+ <!-- See http://checkstyle.sf.net/config_javadoc.html#PackageHtml -->
+ <module name="PackageHtml"/>
+
+ <!-- Checks whether files end with a new line. -->
+ <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
+ <module name="NewlineAtEndOfFile"/>
+
+ <!-- Checks that property files contain the same keys. -->
+ <!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
+ <module name="Translation"/>
+
+
+ <module name="TreeWalker">
+
+ <property name="cacheFile" value="${checkstyle.cache.file}"/>
+
+ <!-- Checks for Javadoc comments. -->
+ <!-- See http://checkstyle.sf.net/config_javadoc.html -->
+ <module name="JavadocMethod">
+ <property name="scope" value="protected"/>
+ <property name="allowUndeclaredRTE" value="true"/>
+ <property name="allowThrowsTagsForSubclasses" value="true"/>
+ </module>
+ <module name="JavadocType"/>
+ <module name="JavadocVariable"/>
+ <module name="JavadocStyle"/>
+
+
+ <!-- Checks for Naming Conventions. -->
+ <!-- See http://checkstyle.sf.net/config_naming.html -->
+ <module name="ConstantName"/>
+ <module name="LocalFinalVariableName"/>
+ <module name="LocalVariableName"/>
+ <module name="MemberName"/>
+ <module name="MethodName"/>
+ <module name="PackageName"/>
+ <module name="ParameterName"/>
+ <module name="StaticVariableName"/>
+ <module name="TypeName"/>
+
+
+ <!-- Checks for Headers -->
+ <!-- See http://checkstyle.sf.net/config_header.html -->
+ <!-- <module name="Header"> -->
+ <!-- The follow property value demonstrates the ability -->
+ <!-- to have access to ANT properties. In this case it uses -->
+ <!-- the ${basedir} property to allow Checkstyle to be run -->
+ <!-- from any directory within a project. See property -->
+ <!-- expansion, -->
+ <!-- http://checkstyle.sf.net/config.html#properties -->
+ <!-- <property -->
+ <!-- name="headerFile" -->
+ <!-- value="${basedir}/java.header"/> -->
+ <!-- <property name="headerFile" value="${checkstyle.header.file}"/> -->
+ <!-- </module> -->
+
+ <!-- Following interprets the header file as regular expressions. -->
+ <!-- <module name="RegexpHeader"/> -->
+ <module name="RegexpHeader">
+ <property name="headerFile" value="src/checkstyle/license-header.txt"/>
+ </module>
+
+
+ <!-- Checks for imports -->
+ <!-- See http://checkstyle.sf.net/config_import.html -->
+ <module name="AvoidStarImport"/>
+ <module name="IllegalImport"/> <!-- defaults to sun.* packages -->
+ <module name="RedundantImport"/>
+ <module name="UnusedImports"/>
+
+
+ <!-- Checks for Size Violations. -->
+ <!-- See http://checkstyle.sf.net/config_sizes.html -->
+ <module name="FileLength"/>
+ <!-- Begin Custom for FileUpload -->
+ <module name="LineLength">
+ <property name="ignorePattern" value="^ \* @version .*$"/>
+ </module>
+ <!-- End Custom for FileUpload -->
+ <module name="MethodLength"/>
+ <module name="ParameterNumber"/>
+
+
+ <!-- Checks for whitespace -->
+ <!-- See http://checkstyle.sf.net/config_whitespace.html -->
+ <module name="EmptyForIteratorPad"/>
+ <module name="NoWhitespaceAfter"/>
+ <module name="NoWhitespaceBefore"/>
+ <module name="OperatorWrap"/>
+ <module name="ParenPad"/>
+ <module name="TypecastParenPad"/>
+ <module name="TabCharacter"/>
+ <module name="WhitespaceAfter"/>
+ <module name="WhitespaceAround"/>
+
+
+ <!-- Modifier Checks -->
+ <!-- See http://checkstyle.sf.net/config_modifiers.html -->
+ <module name="ModifierOrder"/>
+ <module name="RedundantModifier"/>
+
+
+ <!-- Checks for blocks. You know, those {}'s -->
+ <!-- See http://checkstyle.sf.net/config_blocks.html -->
+ <module name="AvoidNestedBlocks"/>
+ <!-- Begin Custom for FileUpload -->
+ <module name="EmptyBlock">
+ <property name="option" value="text"/>
+ </module>
+ <!-- End Custom for FileUpload -->
+ <module name="LeftCurly"/>
+ <module name="NeedBraces"/>
+ <module name="RightCurly"/>
+
+
+ <!-- Checks for common coding problems -->
+ <!-- See http://checkstyle.sf.net/config_coding.html -->
+ <module name="AvoidInlineConditionals"/>
+ <module name="DoubleCheckedLocking"/> <!-- MY FAVOURITE -->
+ <module name="EmptyStatement"/>
+ <module name="EqualsHashCode"/>
+ <!-- Disabled for FileUpload: module name="HiddenField"/ -->
+ <module name="IllegalInstantiation"/>
+ <module name="InnerAssignment"/>
+ <module name="MagicNumber"/>
+ <module name="MissingSwitchDefault"/>
+ <module name="RedundantThrows">
+ <property name="allowSubclasses" value="true"/>
+ </module>
+ <module name="SimplifyBooleanExpression"/>
+ <module name="SimplifyBooleanReturn"/>
+
+ <!-- Checks for class design -->
+ <!-- See http://checkstyle.sf.net/config_design.html -->
+ <!-- Disabled for FileUpload: module name="DesignForExtension"/ -->
+ <module name="FinalClass"/>
+ <module name="HideUtilityClassConstructor"/>
+ <module name="InterfaceIsType"/>
+ <module name="VisibilityModifier"/>
+
+
+ <!-- Miscellaneous other checks. -->
+ <!-- See http://checkstyle.sf.net/config_misc.html -->
+ <module name="ArrayTypeStyle"/>
+ <!-- Disabled for FileUpload: module name="FinalParameters"/ -->
+ <module name="GenericIllegalRegexp">
+ <property name="format" value="\s+$"/>
+ <property name="message" value="Line has trailing spaces."/>
+ </module>
+ <module name="TodoComment"/>
+ <module name="UpperEll"/>
+
+ </module>
+
+</module>
diff --git a/b_1_2_1/src/checkstyle/license-header.txt b/b_1_2_1/src/checkstyle/license-header.txt
new file mode 100644
index 0000000..290c957
--- /dev/null
+++ b/b_1_2_1/src/checkstyle/license-header.txt
@@ -0,0 +1,16 @@
+/\*\s*
+ \*\s*Licensed to the Apache Software Foundation \(ASF\) under one or more
+ \*\s*contributor license agreements. See the NOTICE file distributed with
+ \*\s*this work for additional information regarding copyright ownership\.
+ \*\s*The ASF licenses this file to You under the Apache License, Version 2\.0
+ \*\s*\(the "License"\); you may not use this file except in compliance with
+ \*\s*the License\. You may obtain a copy of the License at
+ \*\s*
+ \*\s*http://www\.apache\.org/licenses/LICENSE\-2\.0
+ \*\s*
+ \*\s*Unless required by applicable law or agreed to in writing, software
+ \*\s*distributed under the License is distributed on an "AS IS" BASIS,
+ \*\s*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\.
+ \*\s*See the License for the specific language governing permissions and
+ \*\s*limitations under the License\.
+ \*/\s*
diff --git a/b_1_2_1/src/conf/MANIFEST.MF b/b_1_2_1/src/conf/MANIFEST.MF
new file mode 100644
index 0000000..18a2447
--- /dev/null
+++ b/b_1_2_1/src/conf/MANIFEST.MF
@@ -0,0 +1,5 @@
+Specification-Vendor: Apache Software Foundation
+Specification-Title: Commons FileUpload
+Implementation-Vendor: Apache Software Foundation
+Implementation-Vendor-Id: org.apache
+Implementation-Title: Commons FileUpload
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/DefaultFileItem.java b/b_1_2_1/src/java/org/apache/commons/fileupload/DefaultFileItem.java
new file mode 100644
index 0000000..b1791ba
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/DefaultFileItem.java
@@ -0,0 +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.fileupload;
+
+import java.io.File;
+import org.apache.commons.fileupload.disk.DiskFileItem;
+
+
+/**
+ * <p> The default implementation of the
+ * {@link org.apache.commons.fileupload.FileItem FileItem} interface.
+ *
+ * <p> After retrieving an instance of this class from a {@link
+ * org.apache.commons.fileupload.DiskFileUpload DiskFileUpload} instance (see
+ * {@link org.apache.commons.fileupload.DiskFileUpload
+ * #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.
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:sean@informage.net">Sean Legassick</a>
+ * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:jmcnally@apache.org">John McNally</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ * @author Sean C. Sullivan
+ *
+ * @version $Id$
+ *
+ * @deprecated Use <code>DiskFileItem</code> instead.
+ */
+public class DefaultFileItem
+ extends DiskFileItem {
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Constructs a new <code>DefaultFileItem</code> instance.
+ *
+ * @param fieldName The name of the form field.
+ * @param contentType The content type passed by the browser or
+ * <code>null</code> 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 filename in the user's filesystem, or
+ * <code>null</code> 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.
+ *
+ * @deprecated Use <code>DiskFileItem</code> instead.
+ */
+ public DefaultFileItem(String fieldName, String contentType,
+ boolean isFormField, String fileName, int sizeThreshold,
+ File repository) {
+ super(fieldName, contentType, isFormField, fileName, sizeThreshold,
+ repository);
+ }
+
+
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/DefaultFileItemFactory.java b/b_1_2_1/src/java/org/apache/commons/fileupload/DefaultFileItemFactory.java
new file mode 100644
index 0000000..8e4c70a
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/DefaultFileItemFactory.java
@@ -0,0 +1,107 @@
+/*
+ * 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.fileupload;
+
+import java.io.File;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+
+/**
+ * <p>The default {@link org.apache.commons.fileupload.FileItemFactory}
+ * implementation. This implementation creates
+ * {@link org.apache.commons.fileupload.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:
+ * <ul>
+ * <li>Size threshold is 10KB.</li>
+ * <li>Repository is the system default temp directory, as returned by
+ * <code>System.getProperty("java.io.tmpdir")</code>.</li>
+ * </ul>
+ * </p>
+ *
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ *
+ * @version $Id$
+ *
+ * @deprecated Use <code>DiskFileItemFactory</code> instead.
+ */
+public class DefaultFileItemFactory extends DiskFileItemFactory {
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Constructs an unconfigured instance of this class. The resulting factory
+ * may be configured by calling the appropriate setter methods.
+ *
+ * @deprecated Use <code>DiskFileItemFactory</code> instead.
+ */
+ public DefaultFileItemFactory() {
+ super();
+ }
+
+
+ /**
+ * 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.
+ *
+ * @deprecated Use <code>DiskFileItemFactory</code> instead.
+ */
+ public DefaultFileItemFactory(int sizeThreshold, File repository) {
+ super(sizeThreshold, repository);
+ }
+
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * Create a new {@link org.apache.commons.fileupload.DefaultFileItem}
+ * 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</code> if this is a plain form field;
+ * <code>false</code> 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.
+ *
+ * @deprecated Use <code>DiskFileItemFactory</code> instead.
+ */
+ public FileItem createItem(
+ String fieldName,
+ String contentType,
+ boolean isFormField,
+ String fileName
+ ) {
+ return new DefaultFileItem(fieldName, contentType,
+ isFormField, fileName, getSizeThreshold(), getRepository());
+ }
+
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/DiskFileUpload.java b/b_1_2_1/src/java/org/apache/commons/fileupload/DiskFileUpload.java
new file mode 100644
index 0000000..e64c526
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/DiskFileUpload.java
@@ -0,0 +1,212 @@
+/*
+ * 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.fileupload;
+
+import java.io.File;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * <p>High level API for processing file uploads.</p>
+ *
+ * <p>This class handles multiple files per single HTML widget, sent using
+ * <code>multipart/mixed</code> 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.fileupload.FileItem}s associated with a given HTML
+ * widget.</p>
+ *
+ * <p>Individual parts will be stored in temporary disk storage or in memory,
+ * depending on their size, and will be available as {@link
+ * org.apache.commons.fileupload.FileItem}s.</p>
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ * @author Sean C. Sullivan
+ *
+ * @version $Id$
+ *
+ * @deprecated Use <code>ServletFileUpload</code> together with
+ * <code>DiskFileItemFactory</code> instead.
+ */
+public class DiskFileUpload
+ extends FileUploadBase {
+
+ // ----------------------------------------------------------- Data members
+
+
+ /**
+ * The factory to use to create new form items.
+ */
+ private DefaultFileItemFactory fileItemFactory;
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Constructs an instance of this class which uses the default factory to
+ * create <code>FileItem</code> instances.
+ *
+ * @see #DiskFileUpload(DefaultFileItemFactory fileItemFactory)
+ *
+ * @deprecated Use <code>FileUpload</code> instead.
+ */
+ public DiskFileUpload() {
+ super();
+ this.fileItemFactory = new DefaultFileItemFactory();
+ }
+
+
+ /**
+ * Constructs an instance of this class which uses the supplied factory to
+ * create <code>FileItem</code> instances.
+ *
+ * @see #DiskFileUpload()
+ * @param fileItemFactory The file item factory to use.
+ *
+ * @deprecated Use <code>FileUpload</code> instead.
+ */
+ public DiskFileUpload(DefaultFileItemFactory fileItemFactory) {
+ super();
+ this.fileItemFactory = fileItemFactory;
+ }
+
+
+ // ----------------------------------------------------- Property accessors
+
+
+ /**
+ * Returns the factory class used when creating file items.
+ *
+ * @return The factory class for new file items.
+ *
+ * @deprecated Use <code>FileUpload</code> instead.
+ */
+ public FileItemFactory getFileItemFactory() {
+ return fileItemFactory;
+ }
+
+
+ /**
+ * Sets the factory class to use when creating file items. The factory must
+ * be an instance of <code>DefaultFileItemFactory</code> or a subclass
+ * thereof, or else a <code>ClassCastException</code> will be thrown.
+ *
+ * @param factory The factory class for new file items.
+ *
+ * @deprecated Use <code>FileUpload</code> instead.
+ */
+ public void setFileItemFactory(FileItemFactory factory) {
+ this.fileItemFactory = (DefaultFileItemFactory) factory;
+ }
+
+
+ /**
+ * Returns the size threshold beyond which files are written directly to
+ * disk.
+ *
+ * @return The size threshold, in bytes.
+ *
+ * @see #setSizeThreshold(int)
+ *
+ * @deprecated Use <code>DiskFileItemFactory</code> instead.
+ */
+ public int getSizeThreshold() {
+ return fileItemFactory.getSizeThreshold();
+ }
+
+
+ /**
+ * Sets the size threshold beyond which files are written directly to disk.
+ *
+ * @param sizeThreshold The size threshold, in bytes.
+ *
+ * @see #getSizeThreshold()
+ *
+ * @deprecated Use <code>DiskFileItemFactory</code> instead.
+ */
+ public void setSizeThreshold(int sizeThreshold) {
+ fileItemFactory.setSizeThreshold(sizeThreshold);
+ }
+
+
+ /**
+ * Returns the location used to temporarily store files that are larger
+ * than the configured size threshold.
+ *
+ * @return The path to the temporary file location.
+ *
+ * @see #setRepositoryPath(String)
+ *
+ * @deprecated Use <code>DiskFileItemFactory</code> instead.
+ */
+ public String getRepositoryPath() {
+ return fileItemFactory.getRepository().getPath();
+ }
+
+
+ /**
+ * Sets the location used to temporarily store files that are larger
+ * than the configured size threshold.
+ *
+ * @param repositoryPath The path to the temporary file location.
+ *
+ * @see #getRepositoryPath()
+ *
+ * @deprecated Use <code>DiskFileItemFactory</code> instead.
+ */
+ public void setRepositoryPath(String repositoryPath) {
+ fileItemFactory.setRepository(new File(repositoryPath));
+ }
+
+
+ // --------------------------------------------------------- Public methods
+
+
+ /**
+ * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
+ * compliant <code>multipart/form-data</code> stream. If files are stored
+ * on disk, the path is given by <code>getRepository()</code>.
+ *
+ * @param req The servlet request to be parsed. Must be non-null.
+ * @param sizeThreshold The max size in bytes to be stored in memory.
+ * @param sizeMax The maximum allowed upload size, in bytes.
+ * @param path The location where the files should be stored.
+ *
+ * @return A list of <code>FileItem</code> 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.
+ *
+ * @deprecated Use <code>ServletFileUpload</code> instead.
+ */
+ public List /* FileItem */ parseRequest(HttpServletRequest req,
+ int sizeThreshold,
+ long sizeMax, String path)
+ throws FileUploadException {
+ setSizeThreshold(sizeThreshold);
+ setSizeMax(sizeMax);
+ setRepositoryPath(path);
+ return parseRequest(req);
+ }
+
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/FileItem.java b/b_1_2_1/src/java/org/apache/commons/fileupload/FileItem.java
new file mode 100644
index 0000000..4054129
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/FileItem.java
@@ -0,0 +1,223 @@
+/*
+ * 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.fileupload;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * <p> This class represents a file or form item that was received within a
+ * <code>multipart/form-data</code> POST request.
+ *
+ * <p> After retrieving an instance of this class from a {@link
+ * org.apache.commons.fileupload.FileUpload FileUpload} instance (see
+ * {@link org.apache.commons.fileupload.FileUpload
+ * #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> While this interface does not extend
+ * <code>javax.activation.DataSource</code> per se (to avoid a seldom used
+ * dependency), several of the defined methods are 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</code> with minimal additional work.
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:sean@informage.net">Sean Legassick</a>
+ * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ *
+ * @version $Id$
+ */
+public interface FileItem extends Serializable {
+
+
+ // ------------------------------- Methods from javax.activation.DataSource
+
+
+ /**
+ * Returns 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.
+ */
+ InputStream getInputStream() throws IOException;
+
+
+ /**
+ * Returns the content type passed by the browser or <code>null</code> if
+ * not defined.
+ *
+ * @return The content type passed by the browser or <code>null</code> if
+ * not defined.
+ */
+ String getContentType();
+
+
+ /**
+ * Returns the original filename in the client's filesystem, 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 filename in the client's filesystem.
+ */
+ String getName();
+
+
+ // ------------------------------------------------------- FileItem methods
+
+
+ /**
+ * Provides a hint as to whether or not the file contents will be read
+ * from memory.
+ *
+ * @return <code>true</code> if the file contents will be read from memory;
+ * <code>false</code> otherwise.
+ */
+ boolean isInMemory();
+
+
+ /**
+ * Returns the size of the file item.
+ *
+ * @return The size of the file item, in bytes.
+ */
+ long getSize();
+
+
+ /**
+ * Returns the contents of the file item as an array of bytes.
+ *
+ * @return The contents of the file item as an array of bytes.
+ */
+ byte[] get();
+
+
+ /**
+ * Returns the contents of the file item as a String, using the specified
+ * encoding. This method uses {@link #get()} to retrieve the
+ * contents of the item.
+ *
+ * @param encoding The character encoding to use.
+ *
+ * @return The contents of the item, as a string.
+ *
+ * @throws UnsupportedEncodingException if the requested character
+ * encoding is not available.
+ */
+ String getString(String encoding) throws UnsupportedEncodingException;
+
+
+ /**
+ * Returns the contents of the file item as a String, using the default
+ * character encoding. This method uses {@link #get()} to retrieve the
+ * contents of the item.
+ *
+ * @return The contents of the item, as a string.
+ */
+ String getString();
+
+
+ /**
+ * A convenience method to write an uploaded item to disk. 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>
+ * 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.
+ *
+ * @param file The <code>File</code> into which the uploaded item should
+ * be stored.
+ *
+ * @throws Exception if an error occurs.
+ */
+ void write(File file) throws Exception;
+
+
+ /**
+ * Deletes the underlying storage for a file item, including deleting any
+ * associated temporary disk file. Although this storage will be deleted
+ * automatically when the <code>FileItem</code> instance is garbage
+ * collected, this method can be used to ensure that this is done at an
+ * earlier time, thus preserving system resources.
+ */
+ void delete();
+
+
+ /**
+ * Returns the name of the field in the multipart form corresponding to
+ * this file item.
+ *
+ * @return The name of the form field.
+ */
+ String getFieldName();
+
+
+ /**
+ * Sets the field name used to reference this file item.
+ *
+ * @param name The name of the form field.
+ */
+ void setFieldName(String name);
+
+
+ /**
+ * Determines whether or not a <code>FileItem</code> instance represents
+ * a simple form field.
+ *
+ * @return <code>true</code> if the instance represents a simple form
+ * field; <code>false</code> if it represents an uploaded file.
+ */
+ boolean isFormField();
+
+
+ /**
+ * Specifies whether or not a <code>FileItem</code> instance represents
+ * a simple form field.
+ *
+ * @param state <code>true</code> if the instance represents a simple form
+ * field; <code>false</code> if it represents an uploaded file.
+ */
+ void setFormField(boolean state);
+
+
+ /**
+ * Returns 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 contensts of the file.
+ *
+ * @throws IOException if an error occurs.
+ */
+ OutputStream getOutputStream() throws IOException;
+
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemFactory.java b/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemFactory.java
new file mode 100644
index 0000000..c4bd60e
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemFactory.java
@@ -0,0 +1,50 @@
+/*
+ * 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.fileupload;
+
+
+/**
+ * <p>A factory interface for creating {@link FileItem} instances. Factories
+ * can provide their own custom configuration, over and above that provided
+ * by the default file upload implementation.</p>
+ *
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ *
+ * @version $Id$
+ */
+public interface FileItemFactory {
+
+ /**
+ * Create a new {@link FileItem} instance from the supplied parameters and
+ * any local factory configuration.
+ *
+ * @param fieldName The name of the form field.
+ * @param contentType The content type of the form field.
+ * @param isFormField <code>true</code> if this is a plain form field;
+ * <code>false</code> 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.
+ */
+ FileItem createItem(
+ String fieldName,
+ String contentType,
+ boolean isFormField,
+ String fileName
+ );
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemHeaders.java b/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemHeaders.java
new file mode 100644
index 0000000..9b25766
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemHeaders.java
@@ -0,0 +1,77 @@
+/*
+ * 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.fileupload;
+
+import java.util.Iterator;
+
+/**
+ * <p> This class provides support for accessing the headers for a file or form
+ * item that was received within a <code>multipart/form-data</code> POST
+ * request.</p>
+ *
+ * @author Michael C. Macaluso
+ * @since 1.3
+ */
+public interface FileItemHeaders {
+ /**
+ * Returns the value of the specified part header as a <code>String</code>.
+ * If the part did not include a header of the specified name, this method
+ * return <code>null</code>. If there are multiple headers with the same
+ * name, this method returns the first header in the item. The header
+ * name is case insensitive.
+ *
+ * @param name a <code>String</code> specifying the header name
+ * @return a <code>String</code> containing the value of the requested
+ * header, or <code>null</code> if the item does not have a header
+ * of that name
+ */
+ String getHeader(String name);
+
+ /**
+ * <p>
+ * Returns all the values of the specified item header as an
+ * <code>Enumeration</code> of <code>String</code> objects.
+ * </p>
+ * <p>
+ * If the item did not include any headers of the specified name, this
+ * method returns an empty <code>Enumeration</code>. The header name is
+ * case insensitive.
+ * </p>
+ *
+ * @param name a <code>String</code> specifying the header name
+ * @return an <code>Enumeration</code> containing the values of the
+ * requested header. If the item does not have any headers of
+ * that name, return an empty <code>Enumeration</code>
+ */
+ Iterator getHeaders(String name);
+
+ /**
+ * <p>
+ * Returns an <code>Enumeration</code> of all the header names.
+ * </p>
+ * <p>
+ * If the item did not include any headers of the specified name, this
+ * method returns an empty <code>Enumeration</code>. The header name is
+ * case insensitive.
+ * </p>
+ *
+ * @return an <code>Enumeration</code> containing the values of the
+ * requested header. If the item does not have any headers of
+ * that name return an empty <code>Enumeration</code>
+ */
+ Iterator getHeaderNames();
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemHeadersSupport.java b/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemHeadersSupport.java
new file mode 100644
index 0000000..24c9455
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemHeadersSupport.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.
+ */
+package org.apache.commons.fileupload;
+
+/**
+ * Interface that will indicate that {@link FileItem} or {@link FileItemStream}
+ * implementations will accept the headers read for the item.
+ *
+ * @author Michael C. Macaluso
+ * @since 1.3
+ *
+ * @see FileItem
+ * @see FileItemStream
+ */
+public interface FileItemHeadersSupport {
+ /**
+ * Returns 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);
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemIterator.java b/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemIterator.java
new file mode 100644
index 0000000..3bb2a44
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemIterator.java
@@ -0,0 +1,48 @@
+/*
+ * 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.fileupload;
+import java.io.IOException;
+
+
+/**
+ * An iterator, as returned by
+ * {@link FileUploadBase#getItemIterator(RequestContext)}.
+ */
+public interface FileItemIterator {
+ /**
+ * Returns, whether another instance of {@link FileItemStream}
+ * is available.
+ * @throws FileUploadException Parsing or processing the
+ * file item failed.
+ * @throws IOException Reading the file item failed.
+ * @return True, if one or more additional file items
+ * are available, otherwise false.
+ */
+ boolean hasNext() throws FileUploadException, IOException;
+
+ /**
+ * Returns the next available {@link FileItemStream}.
+ * @throws java.util.NoSuchElementException No more items are available. Use
+ * {@link #hasNext()} to prevent this exception.
+ * @throws FileUploadException Parsing or processing the
+ * file item failed.
+ * @throws IOException Reading the file item failed.
+ * @return FileItemStream instance, which provides
+ * access to the next file item.
+ */
+ FileItemStream next() throws FileUploadException, IOException;
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemStream.java b/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemStream.java
new file mode 100644
index 0000000..508658b
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/FileItemStream.java
@@ -0,0 +1,97 @@
+/*
+ * 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.fileupload;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+
+/**
+ * <p> This interface provides access to a file or form item that was
+ * received within a <code>multipart/form-data</code> POST request.
+ * The items contents are retrieved by calling {@link #openStream()}.</p>
+ * <p>Instances of this class are created by accessing the
+ * iterator, returned by
+ * {@link FileUploadBase#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>
+ */
+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}.
+ */
+ public static class ItemSkippedException extends IOException {
+ /**
+ * The exceptions serial version UID, which is being used
+ * when serializing an exception instance.
+ */
+ private static final long serialVersionUID = -7280778431581963740L;
+ }
+
+ /** Creates 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.
+ * @see ItemSkippedException
+ */
+ InputStream openStream() throws IOException;
+
+ /**
+ * Returns the content type passed by the browser or <code>null</code> if
+ * not defined.
+ *
+ * @return The content type passed by the browser or <code>null</code> if
+ * not defined.
+ */
+ String getContentType();
+
+ /**
+ * Returns the original filename in the client's filesystem, 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 filename in the client's filesystem.
+ */
+ String getName();
+
+ /**
+ * Returns the name of the field in the multipart form corresponding to
+ * this file item.
+ *
+ * @return The name of the form field.
+ */
+ String getFieldName();
+
+ /**
+ * Determines whether or not a <code>FileItem</code> instance represents
+ * a simple form field.
+ *
+ * @return <code>true</code> if the instance represents a simple form
+ * field; <code>false</code> if it represents an uploaded file.
+ */
+ boolean isFormField();
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/FileUpload.java b/b_1_2_1/src/java/org/apache/commons/fileupload/FileUpload.java
new file mode 100644
index 0000000..9c6d288
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/FileUpload.java
@@ -0,0 +1,106 @@
+/*
+ * 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.fileupload;
+
+
+/**
+ * <p>High level API for processing file uploads.</p>
+ *
+ * <p>This class handles multiple files per single HTML widget, sent using
+ * <code>multipart/mixed</code> encoding type, as specified by
+ * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link
+ * #parseRequest(javax.servlet.http.HttpServletRequest)} to acquire a list
+ * of {@link org.apache.commons.fileupload.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>
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ * @author Sean C. Sullivan
+ *
+ * @version $Id$
+ */
+public class FileUpload
+ extends FileUploadBase {
+
+ // ----------------------------------------------------------- Data members
+
+
+ /**
+ * The factory to use to create new form items.
+ */
+ private FileItemFactory fileItemFactory;
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Constructs an uninitialised instance of this class. A factory must be
+ * configured, using <code>setFileItemFactory()</code>, before attempting
+ * to parse requests.
+ *
+ * @see #FileUpload(FileItemFactory)
+ */
+ public FileUpload() {
+ super();
+ }
+
+
+ /**
+ * Constructs an instance of this class which uses the supplied factory to
+ * create <code>FileItem</code> instances.
+ *
+ * @see #FileUpload()
+ * @param fileItemFactory The factory to use for creating file items.
+ */
+ public FileUpload(FileItemFactory fileItemFactory) {
+ super();
+ this.fileItemFactory = fileItemFactory;
+ }
+
+
+ // ----------------------------------------------------- Property accessors
+
+
+ /**
+ * Returns the factory class used when creating file items.
+ *
+ * @return The factory class for new file items.
+ */
+ public FileItemFactory getFileItemFactory() {
+ return fileItemFactory;
+ }
+
+
+ /**
+ * Sets the factory class to use when creating file items.
+ *
+ * @param factory The factory class for new file items.
+ */
+ public void setFileItemFactory(FileItemFactory factory) {
+ this.fileItemFactory = factory;
+ }
+
+
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/FileUploadBase.java b/b_1_2_1/src/java/org/apache/commons/fileupload/FileUploadBase.java
new file mode 100644
index 0000000..9e12e76
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/FileUploadBase.java
@@ -0,0 +1,1310 @@
+/*
+ * 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.fileupload;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload.MultipartStream.ItemInputStream;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.fileupload.servlet.ServletRequestContext;
+import org.apache.commons.fileupload.util.Closeable;
+import org.apache.commons.fileupload.util.FileItemHeadersImpl;
+import org.apache.commons.fileupload.util.LimitedInputStream;
+import org.apache.commons.fileupload.util.Streams;
+
+
+/**
+ * <p>High level API for processing file uploads.</p>
+ *
+ * <p>This class handles multiple files per single HTML widget, sent using
+ * <code>multipart/mixed</code> 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.fileupload.FileItem}s associated with a given HTML
+ * widget.</p>
+ *
+ * <p>How the data for individual parts is stored is determined by the factory
+ * used to create them; a given part may be in memory, on disk, or somewhere
+ * else.</p>
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ * @author Sean C. Sullivan
+ *
+ * @version $Id$
+ */
+public abstract class FileUploadBase {
+
+ // ---------------------------------------------------------- Class methods
+
+
+ /**
+ * <p>Utility method that determines whether the request contains multipart
+ * content.</p>
+ *
+ * <p><strong>NOTE:</strong>This method will be moved to the
+ * <code>ServletFileUpload</code> 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</code> if the request is multipart;
+ * <code>false</code> otherwise.
+ */
+ public static final boolean isMultipartContent(RequestContext ctx) {
+ String contentType = ctx.getContentType();
+ if (contentType == null) {
+ return false;
+ }
+ if (contentType.toLowerCase().startsWith(MULTIPART)) {
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * Utility method that determines whether the request contains multipart
+ * content.
+ *
+ * @param req The servlet request to be evaluated. Must be non-null.
+ *
+ * @return <code>true</code> if the request is multipart;
+ * <code>false</code> otherwise.
+ *
+ * @deprecated Use the method on <code>ServletFileUpload</code> instead.
+ */
+ public static boolean isMultipartContent(HttpServletRequest req) {
+ return ServletFileUpload.isMultipartContent(req);
+ }
+
+
+ // ----------------------------------------------------- Manifest constants
+
+
+ /**
+ * HTTP content type header name.
+ */
+ public static final String CONTENT_TYPE = "Content-type";
+
+
+ /**
+ * HTTP content disposition header name.
+ */
+ public static final String CONTENT_DISPOSITION = "Content-disposition";
+
+ /**
+ * HTTP content length header name.
+ */
+ public static final String CONTENT_LENGTH = "Content-length";
+
+
+ /**
+ * Content-disposition value for form data.
+ */
+ public static final String FORM_DATA = "form-data";
+
+
+ /**
+ * Content-disposition value for file attachment.
+ */
+ public static final String ATTACHMENT = "attachment";
+
+
+ /**
+ * Part of HTTP content type header.
+ */
+ public static final String MULTIPART = "multipart/";
+
+
+ /**
+ * HTTP content type header for multipart forms.
+ */
+ public static final String MULTIPART_FORM_DATA = "multipart/form-data";
+
+
+ /**
+ * HTTP content type header for multiple uploads.
+ */
+ public static final String MULTIPART_MIXED = "multipart/mixed";
+
+
+ /**
+ * The maximum length of a single header line that will be parsed
+ * (1024 bytes).
+ * @deprecated This constant is no longer used. As of commons-fileupload
+ * 1.2, the only applicable limit is the total size of a parts headers,
+ * {@link MultipartStream#HEADER_PART_SIZE_MAX}.
+ */
+ public static final int MAX_HEADER_SIZE = 1024;
+
+
+ // ----------------------------------------------------------- Data members
+
+
+ /**
+ * 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.
+ */
+ private long fileSizeMax = -1;
+
+ /**
+ * The content encoding to use when reading part headers.
+ */
+ private String headerEncoding;
+
+ /**
+ * The progress listener.
+ */
+ private ProgressListener listener;
+
+ // ----------------------------------------------------- Property accessors
+
+
+ /**
+ * Returns the factory class used when creating file items.
+ *
+ * @return The factory class for new file items.
+ */
+ public abstract FileItemFactory getFileItemFactory();
+
+
+ /**
+ * Sets the factory class to use when creating file items.
+ *
+ * @param factory The factory class for new file items.
+ */
+ public abstract void setFileItemFactory(FileItemFactory factory);
+
+
+ /**
+ * Returns 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.
+ *
+ * @see #setSizeMax(long)
+ *
+ */
+ public long getSizeMax() {
+ return sizeMax;
+ }
+
+
+ /**
+ * 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.
+ *
+ * @see #getSizeMax()
+ *
+ */
+ public void setSizeMax(long sizeMax) {
+ this.sizeMax = sizeMax;
+ }
+
+ /**
+ * Returns 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.
+ */
+ public long getFileSizeMax() {
+ return fileSizeMax;
+ }
+
+ /**
+ * 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.
+ */
+ public void setFileSizeMax(long fileSizeMax) {
+ this.fileSizeMax = fileSizeMax;
+ }
+
+ /**
+ * Retrieves the character encoding used when reading the headers of an
+ * individual part. When not specified, or <code>null</code>, the request
+ * encoding is used. If that is also not specified, or <code>null</code>,
+ * the platform default encoding is used.
+ *
+ * @return The encoding used to read part headers.
+ */
+ public String getHeaderEncoding() {
+ return headerEncoding;
+ }
+
+
+ /**
+ * Specifies the character encoding to be used when reading the headers of
+ * individual part. When not specified, or <code>null</code>, the request
+ * encoding is used. If that is also not specified, or <code>null</code>,
+ * the platform default encoding is used.
+ *
+ * @param encoding The encoding used to read part headers.
+ */
+ public void setHeaderEncoding(String encoding) {
+ headerEncoding = encoding;
+ }
+
+
+ // --------------------------------------------------------- Public methods
+
+
+ /**
+ * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
+ * compliant <code>multipart/form-data</code> stream.
+ *
+ * @param req The servlet request to be parsed.
+ *
+ * @return A list of <code>FileItem</code> 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.
+ *
+ * @deprecated Use the method in <code>ServletFileUpload</code> instead.
+ */
+ public List /* FileItem */ parseRequest(HttpServletRequest req)
+ throws FileUploadException {
+ return parseRequest(new ServletRequestContext(req));
+ }
+
+ /**
+ * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
+ * compliant <code>multipart/form-data</code> stream.
+ *
+ * @param ctx The context for the request to be parsed.
+ *
+ * @return An iterator to instances of <code>FileItemStream</code>
+ * 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(RequestContext ctx)
+ throws FileUploadException, IOException {
+ return new FileItemIteratorImpl(ctx);
+ }
+
+ /**
+ * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
+ * compliant <code>multipart/form-data</code> stream.
+ *
+ * @param ctx The context for the request to be parsed.
+ *
+ * @return A list of <code>FileItem</code> 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(RequestContext ctx)
+ throws FileUploadException {
+ try {
+ FileItemIterator iter = getItemIterator(ctx);
+ List items = new ArrayList();
+ FileItemFactory fac = getFileItemFactory();
+ if (fac == null) {
+ throw new NullPointerException(
+ "No FileItemFactory has been set.");
+ }
+ while (iter.hasNext()) {
+ FileItemStream item = iter.next();
+ FileItem fileItem = fac.createItem(item.getFieldName(),
+ item.getContentType(), item.isFormField(),
+ item.getName());
+ try {
+ Streams.copy(item.openStream(), fileItem.getOutputStream(),
+ true);
+ } catch (FileUploadIOException e) {
+ throw (FileUploadException) e.getCause();
+ } catch (IOException e) {
+ throw new IOFileUploadException(
+ "Processing of " + MULTIPART_FORM_DATA
+ + " request failed. " + e.getMessage(), e);
+ }
+ if (fileItem instanceof FileItemHeadersSupport) {
+ final FileItemHeaders fih = item.getHeaders();
+ ((FileItemHeadersSupport) fileItem).setHeaders(fih);
+ }
+ items.add(fileItem);
+ }
+ return items;
+ } catch (FileUploadIOException e) {
+ throw (FileUploadException) e.getCause();
+ } catch (IOException e) {
+ throw new FileUploadException(e.getMessage(), e);
+ }
+ }
+
+
+ // ------------------------------------------------------ Protected methods
+
+
+ /**
+ * Retrieves the boundary from the <code>Content-type</code> header.
+ *
+ * @param contentType The value of the content type header from which to
+ * extract the boundary value.
+ *
+ * @return The boundary, as a byte array.
+ */
+ protected byte[] getBoundary(String contentType) {
+ ParameterParser parser = new ParameterParser();
+ parser.setLowerCaseNames(true);
+ // Parameter parser can handle null input
+ Map params = parser.parse(contentType, new char[] {';', ','});
+ String boundaryStr = (String) params.get("boundary");
+
+ if (boundaryStr == null) {
+ return null;
+ }
+ byte[] boundary;
+ try {
+ boundary = boundaryStr.getBytes("ISO-8859-1");
+ } catch (UnsupportedEncodingException e) {
+ boundary = boundaryStr.getBytes();
+ }
+ return boundary;
+ }
+
+
+ /**
+ * Retrieves the file name from the <code>Content-disposition</code>
+ * header.
+ *
+ * @param headers A <code>Map</code> containing the HTTP request headers.
+ *
+ * @return The file name for the current <code>encapsulation</code>.
+ * @deprecated Use {@link #getFileName(FileItemHeaders)}.
+ */
+ protected String getFileName(Map /* String, String */ headers) {
+ return getFileName(getHeader(headers, CONTENT_DISPOSITION));
+ }
+
+ /**
+ * Retrieves the file name from the <code>Content-disposition</code>
+ * header.
+ *
+ * @param headers The HTTP headers object.
+ *
+ * @return The file name for the current <code>encapsulation</code>.
+ */
+ protected String getFileName(FileItemHeaders headers) {
+ return getFileName(headers.getHeader(CONTENT_DISPOSITION));
+ }
+
+ /**
+ * Returns the given content-disposition headers file name.
+ * @param pContentDisposition The content-disposition headers value.
+ * @return The file name
+ */
+ private String getFileName(String pContentDisposition) {
+ String fileName = null;
+ if (pContentDisposition != null) {
+ String cdl = pContentDisposition.toLowerCase();
+ if (cdl.startsWith(FORM_DATA) || cdl.startsWith(ATTACHMENT)) {
+ ParameterParser parser = new ParameterParser();
+ parser.setLowerCaseNames(true);
+ // Parameter parser can handle null input
+ Map params = parser.parse(pContentDisposition, ';');
+ if (params.containsKey("filename")) {
+ fileName = (String) params.get("filename");
+ if (fileName != null) {
+ fileName = fileName.trim();
+ } else {
+ // Even if there is no value, the parameter is present,
+ // so we return an empty file name rather than no file
+ // name.
+ fileName = "";
+ }
+ }
+ }
+ }
+ return fileName;
+ }
+
+
+ /**
+ * Retrieves the field name from the <code>Content-disposition</code>
+ * header.
+ *
+ * @param headers A <code>Map</code> containing the HTTP request headers.
+ *
+ * @return The field name for the current <code>encapsulation</code>.
+ */
+ protected String getFieldName(FileItemHeaders headers) {
+ return getFieldName(headers.getHeader(CONTENT_DISPOSITION));
+ }
+
+ /**
+ * Returns the field name, which is given by the content-disposition
+ * header.
+ * @param pContentDisposition The content-dispositions header value.
+ * @return The field jake
+ */
+ private String getFieldName(String pContentDisposition) {
+ String fieldName = null;
+ if (pContentDisposition != null
+ && pContentDisposition.toLowerCase().startsWith(FORM_DATA)) {
+ ParameterParser parser = new ParameterParser();
+ parser.setLowerCaseNames(true);
+ // Parameter parser can handle null input
+ Map params = parser.parse(pContentDisposition, ';');
+ fieldName = (String) params.get("name");
+ if (fieldName != null) {
+ fieldName = fieldName.trim();
+ }
+ }
+ return fieldName;
+ }
+
+ /**
+ * Retrieves the field name from the <code>Content-disposition</code>
+ * header.
+ *
+ * @param headers A <code>Map</code> containing the HTTP request headers.
+ *
+ * @return The field name for the current <code>encapsulation</code>.
+ * @deprecated Use {@link #getFieldName(FileItemHeaders)}.
+ */
+ protected String getFieldName(Map /* String, String */ headers) {
+ return getFieldName(getHeader(headers, CONTENT_DISPOSITION));
+ }
+
+
+ /**
+ * Creates a new {@link FileItem} instance.
+ *
+ * @param headers A <code>Map</code> containing the HTTP request
+ * headers.
+ * @param isFormField Whether or not this item is a form field, as
+ * opposed to a file.
+ *
+ * @return A newly created <code>FileItem</code> instance.
+ *
+ * @throws FileUploadException if an error occurs.
+ * @deprecated This method is no longer used in favour of
+ * internally created instances of {@link FileItem}.
+ */
+ protected FileItem createItem(Map /* String, String */ headers,
+ boolean isFormField)
+ throws FileUploadException {
+ return getFileItemFactory().createItem(getFieldName(headers),
+ getHeader(headers, CONTENT_TYPE),
+ isFormField,
+ getFileName(headers));
+ }
+
+ /**
+ * <p> Parses the <code>header-part</code> 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.
+ *
+ * @param headerPart The <code>header-part</code> of the current
+ * <code>encapsulation</code>.
+ *
+ * @return A <code>Map</code> containing the parsed HTTP request headers.
+ */
+ protected FileItemHeaders getParsedHeaders(String headerPart) {
+ final int len = headerPart.length();
+ FileItemHeadersImpl headers = newFileItemHeaders();
+ int start = 0;
+ for (;;) {
+ int end = parseEndOfLine(headerPart, start);
+ if (start == end) {
+ break;
+ }
+ String header = headerPart.substring(start, end);
+ start = end + 2;
+ while (start < len) {
+ int nonWs = start;
+ while (nonWs < len) {
+ char c = headerPart.charAt(nonWs);
+ if (c != ' ' && c != '\t') {
+ break;
+ }
+ ++nonWs;
+ }
+ if (nonWs == start) {
+ break;
+ }
+ // Continuation line found
+ end = parseEndOfLine(headerPart, nonWs);
+ header += " " + headerPart.substring(nonWs, end);
+ start = end + 2;
+ }
+ parseHeaderLine(headers, header);
+ }
+ return headers;
+ }
+
+ /**
+ * Creates a new instance of {@link FileItemHeaders}.
+ * @return The new instance.
+ */
+ protected FileItemHeadersImpl newFileItemHeaders() {
+ return new FileItemHeadersImpl();
+ }
+
+ /**
+ * <p> Parses the <code>header-part</code> 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.
+ *
+ * @param headerPart The <code>header-part</code> of the current
+ * <code>encapsulation</code>.
+ *
+ * @return A <code>Map</code> containing the parsed HTTP request headers.
+ * @deprecated Use {@link #getParsedHeaders(String)}
+ */
+ protected Map /* String, String */ parseHeaders(String headerPart) {
+ FileItemHeaders headers = getParsedHeaders(headerPart);
+ Map result = new HashMap();
+ for (Iterator iter = headers.getHeaderNames(); iter.hasNext();) {
+ String headerName = (String) iter.next();
+ Iterator iter2 = headers.getHeaders(headerName);
+ String headerValue = (String) iter2.next();
+ while (iter2.hasNext()) {
+ headerValue += "," + iter2.next();
+ }
+ result.put(headerName, headerValue);
+ }
+ return result;
+ }
+
+ /**
+ * 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.
+ */
+ private int parseEndOfLine(String headerPart, int end) {
+ int index = end;
+ for (;;) {
+ 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 (headerPart.charAt(offset + 1) == '\n') {
+ return offset;
+ }
+ index = offset + 1;
+ }
+ }
+
+ /**
+ * Reads the next header line.
+ * @param headers String with all headers.
+ * @param header Map where to store the current header.
+ */
+ private void parseHeaderLine(FileItemHeadersImpl headers, String header) {
+ final int colonOffset = header.indexOf(':');
+ if (colonOffset == -1) {
+ // This header line is malformed, skip it.
+ return;
+ }
+ String headerName = header.substring(0, colonOffset).trim();
+ String headerValue =
+ header.substring(header.indexOf(':') + 1).trim();
+ headers.addHeader(headerName, headerValue);
+ }
+
+ /**
+ * Returns the header with the specified name from the supplied map. The
+ * header lookup is case-insensitive.
+ *
+ * @param headers A <code>Map</code> containing the HTTP request headers.
+ * @param name The name of the header to return.
+ *
+ * @return The value of specified header, or a comma-separated list if
+ * there were multiple headers of that name.
+ * @deprecated Use {@link FileItemHeaders#getHeader(String)}.
+ */
+ protected final String getHeader(Map /* String, String */ headers,
+ String name) {
+ return (String) headers.get(name.toLowerCase());
+ }
+
+ /**
+ * The iterator, which is returned by
+ * {@link FileUploadBase#getItemIterator(RequestContext)}.
+ */
+ private class FileItemIteratorImpl implements FileItemIterator {
+ /**
+ * Default implementation of {@link FileItemStream}.
+ */
+ private class FileItemStreamImpl implements FileItemStream {
+ /** 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 name;
+ /** Whether the file item is a form field.
+ */
+ private final boolean formField;
+ /** The file items input stream.
+ */
+ private final InputStream stream;
+ /** Whether the file item was already opened.
+ */
+ private boolean opened;
+ /** The headers, if any.
+ */
+ private FileItemHeaders headers;
+
+ /**
+ * Creates a new instance.
+ * @param pName The items file name, or null.
+ * @param pFieldName The items field name.
+ * @param pContentType The items content type, or null.
+ * @param pFormField Whether the item is a form field.
+ * @param pContentLength The items content length, if known, or -1
+ * @throws IOException Creating the file item failed.
+ */
+ FileItemStreamImpl(String pName, String pFieldName,
+ String pContentType, boolean pFormField,
+ long pContentLength) throws IOException {
+ name = pName;
+ fieldName = pFieldName;
+ contentType = pContentType;
+ formField = pFormField;
+ final ItemInputStream itemStream = multi.newInputStream();
+ InputStream istream = itemStream;
+ if (fileSizeMax != -1) {
+ if (pContentLength != -1
+ && pContentLength > fileSizeMax) {
+ FileUploadException e =
+ new FileSizeLimitExceededException(
+ "The field " + fieldName
+ + " exceeds its maximum permitted "
+ + " size of " + fileSizeMax
+ + " characters.",
+ pContentLength, fileSizeMax);
+ throw new FileUploadIOException(e);
+ }
+ istream = new LimitedInputStream(istream, fileSizeMax) {
+ protected void raiseError(long pSizeMax, long pCount)
+ throws IOException {
+ itemStream.close(true);
+ FileUploadException e =
+ new FileSizeLimitExceededException(
+ "The field " + fieldName
+ + " exceeds its maximum permitted "
+ + " size of " + pSizeMax
+ + " characters.",
+ pCount, pSizeMax);
+ throw new FileUploadIOException(e);
+ }
+ };
+ }
+ stream = istream;
+ }
+
+ /**
+ * Returns the items content type, or null.
+ * @return Content type, if known, or null.
+ */
+ public String getContentType() {
+ return contentType;
+ }
+
+ /**
+ * Returns the items field name.
+ * @return Field name.
+ */
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ /**
+ * Returns the items file name.
+ * @return File name, if known, or null.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns, whether this is a form field.
+ * @return True, if the item is a form field,
+ * otherwise false.
+ */
+ public boolean isFormField() {
+ return formField;
+ }
+
+ /**
+ * Returns an input stream, which may be used to
+ * read the items contents.
+ * @return Opened input stream.
+ * @throws IOException An I/O error occurred.
+ */
+ public InputStream openStream() throws IOException {
+ if (opened) {
+ throw new IllegalStateException(
+ "The stream was already opened.");
+ }
+ if (((Closeable) stream).isClosed()) {
+ throw new FileItemStream.ItemSkippedException();
+ }
+ return stream;
+ }
+
+ /**
+ * Closes the file item.
+ * @throws IOException An I/O error occurred.
+ */
+ void close() throws IOException {
+ stream.close();
+ }
+
+ /**
+ * Returns the file item headers.
+ * @return The items header object
+ */
+ public FileItemHeaders getHeaders() {
+ return headers;
+ }
+
+ /**
+ * Sets the file item headers.
+ * @param pHeaders The items header object
+ */
+ public void setHeaders(FileItemHeaders pHeaders) {
+ headers = pHeaders;
+ }
+ }
+
+ /**
+ * The multi part stream to process.
+ */
+ private final MultipartStream multi;
+ /**
+ * The notifier, which used for triggering the
+ * {@link ProgressListener}.
+ */
+ private final MultipartStream.ProgressNotifier notifier;
+ /**
+ * The boundary, which separates the various parts.
+ */
+ private final byte[] boundary;
+ /**
+ * 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;
+
+ /**
+ * Creates a new instance.
+ * @param ctx The request context.
+ * @throws FileUploadException An error occurred while
+ * parsing the request.
+ * @throws IOException An I/O error occurred.
+ */
+ FileItemIteratorImpl(RequestContext ctx)
+ throws FileUploadException, IOException {
+ if (ctx == null) {
+ throw new NullPointerException("ctx parameter");
+ }
+
+ String contentType = ctx.getContentType();
+ if ((null == contentType)
+ || (!contentType.toLowerCase().startsWith(MULTIPART))) {
+ throw new InvalidContentTypeException(
+ "the request doesn't contain a "
+ + MULTIPART_FORM_DATA
+ + " or "
+ + MULTIPART_MIXED
+ + " stream, content type header is "
+ + contentType);
+ }
+
+ InputStream input = ctx.getInputStream();
+
+ if (sizeMax >= 0) {
+ int requestSize = ctx.getContentLength();
+ if (requestSize == -1) {
+ input = new LimitedInputStream(input, sizeMax) {
+ protected void raiseError(long pSizeMax, long pCount)
+ throws IOException {
+ FileUploadException ex =
+ new SizeLimitExceededException(
+ "the request was rejected because"
+ + " its size (" + pCount
+ + ") exceeds the configured maximum"
+ + " (" + pSizeMax + ")",
+ pCount, pSizeMax);
+ throw new FileUploadIOException(ex);
+ }
+ };
+ } else {
+ if (sizeMax >= 0 && requestSize > sizeMax) {
+ throw new SizeLimitExceededException(
+ "the request was rejected because its size ("
+ + requestSize
+ + ") exceeds the configured maximum ("
+ + sizeMax + ")",
+ requestSize, sizeMax);
+ }
+ }
+ }
+
+ String charEncoding = headerEncoding;
+ if (charEncoding == null) {
+ charEncoding = ctx.getCharacterEncoding();
+ }
+
+ boundary = getBoundary(contentType);
+ if (boundary == null) {
+ throw new FileUploadException(
+ "the request was rejected because "
+ + "no multipart boundary was found");
+ }
+
+ notifier = new MultipartStream.ProgressNotifier(listener,
+ ctx.getContentLength());
+ multi = new MultipartStream(input, boundary, notifier);
+ multi.setHeaderEncoding(charEncoding);
+
+ skipPreamble = true;
+ findNextItem();
+ }
+
+ /**
+ * Called for finding the nex item, if any.
+ * @return True, if an next item was found, otherwise false.
+ * @throws IOException An I/O error occurred.
+ */
+ private boolean findNextItem() throws IOException {
+ if (eof) {
+ return false;
+ }
+ if (currentItem != null) {
+ currentItem.close();
+ currentItem = null;
+ }
+ for (;;) {
+ 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(boundary);
+ currentFieldName = null;
+ continue;
+ }
+ FileItemHeaders headers = getParsedHeaders(multi.readHeaders());
+ if (currentFieldName == null) {
+ // We're parsing the outer multipart
+ String fieldName = getFieldName(headers);
+ if (fieldName != null) {
+ String subContentType = headers.getHeader(CONTENT_TYPE);
+ if (subContentType != null
+ && subContentType.toLowerCase()
+ .startsWith(MULTIPART_MIXED)) {
+ currentFieldName = fieldName;
+ // Multiple files associated with this field name
+ byte[] subBoundary = getBoundary(subContentType);
+ multi.setBoundary(subBoundary);
+ skipPreamble = true;
+ continue;
+ }
+ String fileName = getFileName(headers);
+ currentItem = new FileItemStreamImpl(fileName,
+ fieldName, headers.getHeader(CONTENT_TYPE),
+ fileName == null, getContentLength(headers));
+ notifier.noteItem();
+ itemValid = true;
+ return true;
+ }
+ } else {
+ String fileName = getFileName(headers);
+ if (fileName != null) {
+ currentItem = new FileItemStreamImpl(fileName,
+ currentFieldName,
+ headers.getHeader(CONTENT_TYPE),
+ false, getContentLength(headers));
+ notifier.noteItem();
+ itemValid = true;
+ return true;
+ }
+ }
+ multi.discardBodyData();
+ }
+ }
+
+ private long getContentLength(FileItemHeaders pHeaders) {
+ try {
+ return Long.parseLong(pHeaders.getHeader(CONTENT_LENGTH));
+ } catch (Exception e) {
+ return -1;
+ }
+ }
+
+ /**
+ * Returns, whether another instance of {@link FileItemStream}
+ * is available.
+ * @throws FileUploadException Parsing or processing the
+ * file item failed.
+ * @throws IOException Reading the file item failed.
+ * @return True, if one or more additional file items
+ * are available, otherwise false.
+ */
+ public boolean hasNext() throws FileUploadException, IOException {
+ if (eof) {
+ return false;
+ }
+ if (itemValid) {
+ return true;
+ }
+ return findNextItem();
+ }
+
+ /**
+ * Returns the next available {@link FileItemStream}.
+ * @throws java.util.NoSuchElementException No more items are
+ * available. Use {@link #hasNext()} to prevent this exception.
+ * @throws FileUploadException Parsing or processing the
+ * file item failed.
+ * @throws IOException Reading the file item failed.
+ * @return FileItemStream instance, which provides
+ * access to the next file item.
+ */
+ public FileItemStream next() throws FileUploadException, IOException {
+ if (eof || (!itemValid && !hasNext())) {
+ throw new NoSuchElementException();
+ }
+ itemValid = false;
+ return currentItem;
+ }
+ }
+
+ /**
+ * This exception is thrown for hiding an inner
+ * {@link FileUploadException} in an {@link IOException}.
+ */
+ public static class FileUploadIOException extends IOException {
+ /** The exceptions UID, for serializing an instance.
+ */
+ private static final long serialVersionUID = -7047616958165584154L;
+ /** The exceptions cause; we overwrite the parent
+ * classes field, which is available since Java
+ * 1.4 only.
+ */
+ private final FileUploadException cause;
+
+ /**
+ * Creates a <code>FileUploadIOException</code> with the
+ * given cause.
+ * @param pCause The exceptions cause, if any, or null.
+ */
+ public FileUploadIOException(FileUploadException pCause) {
+ // We're not doing super(pCause) cause of 1.3 compatibility.
+ cause = pCause;
+ }
+
+ /**
+ * Returns the exceptions cause.
+ * @return The exceptions cause, if any, or null.
+ */
+ public Throwable getCause() {
+ return cause;
+ }
+ }
+
+ /**
+ * Thrown to indicate that the request is not a multipart request.
+ */
+ public static class InvalidContentTypeException
+ extends FileUploadException {
+ /** The exceptions UID, for serializing an instance.
+ */
+ private static final long serialVersionUID = -9073026332015646668L;
+
+ /**
+ * Constructs a <code>InvalidContentTypeException</code> with no
+ * detail message.
+ */
+ public InvalidContentTypeException() {
+ // Nothing to do.
+ }
+
+ /**
+ * Constructs an <code>InvalidContentTypeException</code> with
+ * the specified detail message.
+ *
+ * @param message The detail message.
+ */
+ public InvalidContentTypeException(String message) {
+ super(message);
+ }
+ }
+
+ /**
+ * Thrown to indicate an IOException.
+ */
+ public static class IOFileUploadException extends FileUploadException {
+ /** The exceptions UID, for serializing an instance.
+ */
+ private static final long serialVersionUID = 1749796615868477269L;
+ /** The exceptions cause; we overwrite the parent
+ * classes field, which is available since Java
+ * 1.4 only.
+ */
+ private final IOException cause;
+
+ /**
+ * Creates a new instance with the given cause.
+ * @param pMsg The detail message.
+ * @param pException The exceptions cause.
+ */
+ public IOFileUploadException(String pMsg, IOException pException) {
+ super(pMsg);
+ cause = pException;
+ }
+
+ /**
+ * Returns the exceptions cause.
+ * @return The exceptions cause, if any, or null.
+ */
+ public Throwable getCause() {
+ return cause;
+ }
+ }
+
+ /** This exception is thrown, if a requests permitted size
+ * is exceeded.
+ */
+ protected abstract static class SizeException extends FileUploadException {
+ /**
+ * The actual size of the request.
+ */
+ private final long actual;
+
+ /**
+ * The maximum permitted size of the request.
+ */
+ private final long permitted;
+
+ /**
+ * Creates a new instance.
+ * @param message The detail message.
+ * @param actual The actual number of bytes in the request.
+ * @param permitted The requests size limit, in bytes.
+ */
+ protected SizeException(String message, long actual, long permitted) {
+ super(message);
+ this.actual = actual;
+ this.permitted = permitted;
+ }
+
+ /**
+ * Retrieves the actual size of the request.
+ *
+ * @return The actual size of the request.
+ */
+ public long getActualSize() {
+ return actual;
+ }
+
+ /**
+ * Retrieves the permitted size of the request.
+ *
+ * @return The permitted size of the request.
+ */
+ public long getPermittedSize() {
+ return permitted;
+ }
+ }
+
+ /**
+ * Thrown to indicate that the request size is not specified. In other
+ * words, it is thrown, if the content-length header is missing or
+ * contains the value -1.
+ * @deprecated As of commons-fileupload 1.2, the presence of a
+ * content-length header is no longer required.
+ */
+ public static class UnknownSizeException
+ extends FileUploadException {
+ /** The exceptions UID, for serializing an instance.
+ */
+ private static final long serialVersionUID = 7062279004812015273L;
+
+ /**
+ * Constructs a <code>UnknownSizeException</code> with no
+ * detail message.
+ */
+ public UnknownSizeException() {
+ super();
+ }
+
+ /**
+ * Constructs an <code>UnknownSizeException</code> with
+ * the specified detail message.
+ *
+ * @param message The detail message.
+ */
+ public UnknownSizeException(String message) {
+ super(message);
+ }
+ }
+
+ /**
+ * Thrown to indicate that the request size exceeds the configured maximum.
+ */
+ public static class SizeLimitExceededException
+ extends SizeException {
+ /** The exceptions UID, for serializing an instance.
+ */
+ private static final long serialVersionUID = -2474893167098052828L;
+
+ /**
+ * @deprecated Replaced by
+ * {@link #SizeLimitExceededException(String, long, long)}
+ */
+ public SizeLimitExceededException() {
+ this(null, 0, 0);
+ }
+
+ /**
+ * @deprecated Replaced by
+ * {@link #SizeLimitExceededException(String, long, long)}
+ * @param message The exceptions detail message.
+ */
+ public SizeLimitExceededException(String message) {
+ this(message, 0, 0);
+ }
+
+ /**
+ * Constructs a <code>SizeExceededException</code> with
+ * the specified detail message, and actual and permitted sizes.
+ *
+ * @param message The detail message.
+ * @param actual The actual request size.
+ * @param permitted The maximum permitted request size.
+ */
+ public SizeLimitExceededException(String message, long actual,
+ long permitted) {
+ super(message, actual, permitted);
+ }
+ }
+
+ /**
+ * Thrown to indicate that A files size exceeds the configured maximum.
+ */
+ public static class FileSizeLimitExceededException
+ extends SizeException {
+ /** The exceptions UID, for serializing an instance.
+ */
+ private static final long serialVersionUID = 8150776562029630058L;
+
+ /**
+ * Constructs a <code>SizeExceededException</code> with
+ * the specified detail message, and actual and permitted sizes.
+ *
+ * @param message The detail message.
+ * @param actual The actual request size.
+ * @param permitted The maximum permitted request size.
+ */
+ public FileSizeLimitExceededException(String message, long actual,
+ long permitted) {
+ super(message, actual, permitted);
+ }
+ }
+
+ /**
+ * Returns the progress listener.
+ * @return The progress listener, if any, or null.
+ */
+ public ProgressListener getProgressListener() {
+ return listener;
+ }
+
+ /**
+ * Sets the progress listener.
+ * @param pListener The progress listener, if any. Defaults to null.
+ */
+ public void setProgressListener(ProgressListener pListener) {
+ listener = pListener;
+ }
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/FileUploadException.java b/b_1_2_1/src/java/org/apache/commons/fileupload/FileUploadException.java
new file mode 100644
index 0000000..3f2863b
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/FileUploadException.java
@@ -0,0 +1,99 @@
+/*
+ * 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.fileupload;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+
+/**
+ * Exception for errors encountered while processing the request.
+ *
+ * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
+ * @version $Id$
+ */
+public class FileUploadException extends Exception {
+ /**
+ * Serial version UID, being used, if the exception
+ * is serialized.
+ */
+ private static final long serialVersionUID = 8881893724388807504L;
+ /**
+ * The exceptions cause. We overwrite the cause of
+ * the super class, which isn't available in Java 1.3.
+ */
+ private final Throwable cause;
+
+ /**
+ * Constructs a new <code>FileUploadException</code> without message.
+ */
+ public FileUploadException() {
+ this(null, null);
+ }
+
+ /**
+ * Constructs a new <code>FileUploadException</code> with specified detail
+ * message.
+ *
+ * @param msg the error message.
+ */
+ public FileUploadException(final String msg) {
+ this(msg, null);
+ }
+
+ /**
+ * Creates a new <code>FileUploadException</code> with the given
+ * detail message and cause.
+ * @param msg The exceptions detail message.
+ * @param cause The exceptions cause.
+ */
+ public FileUploadException(String msg, Throwable cause) {
+ super(msg);
+ this.cause = cause;
+ }
+
+ /**
+ * Prints this throwable and its backtrace to the specified print stream.
+ *
+ * @param stream <code>PrintStream</code> to use for output
+ */
+ public void printStackTrace(PrintStream stream) {
+ super.printStackTrace(stream);
+ if (cause != null) {
+ stream.println("Caused by:");
+ cause.printStackTrace(stream);
+ }
+ }
+
+ /**
+ * Prints this throwable and its backtrace to the specified
+ * print writer.
+ *
+ * @param writer <code>PrintWriter</code> to use for output
+ */
+ public void printStackTrace(PrintWriter writer) {
+ super.printStackTrace(writer);
+ if (cause != null) {
+ writer.println("Caused by:");
+ cause.printStackTrace(writer);
+ }
+ }
+
+ public Throwable getCause() {
+ return cause;
+ }
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/MultipartStream.java b/b_1_2_1/src/java/org/apache/commons/fileupload/MultipartStream.java
new file mode 100644
index 0000000..87969c5
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/MultipartStream.java
@@ -0,0 +1,1073 @@
+/*
+ * 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.fileupload;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.commons.fileupload.util.Closeable;
+import org.apache.commons.fileupload.util.Streams;
+
+/**
+ * <p> Low level API for processing file uploads.
+ *
+ * <p> This class can be used to process data streams conforming to MIME
+ * 'multipart' format as defined in
+ * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Arbitrarily
+ * large amounts of data in the stream can be processed under constant
+ * memory usage.
+ *
+ * <p> The format of the stream is defined in the following way:<br>
+ *
+ * <code>
+ * multipart-body := preamble 1*encapsulation close-delimiter epilogue<br>
+ * encapsulation := delimiter body CRLF<br>
+ * delimiter := "--" boundary CRLF<br>
+ * close-delimiter := "--" boudary "--"<br>
+ * preamble := <ignore><br>
+ * epilogue := <ignore><br>
+ * body := header-part CRLF body-part<br>
+ * header-part := 1*header CRLF<br>
+ * header := header-name ":" header-value<br>
+ * header-name := <printable ascii characters except ":"><br>
+ * header-value := <any ascii characters except CR & LF><br>
+ * body-data := <arbitrary data><br>
+ * </code>
+ *
+ * <p>Note that body-data can contain another mulipart entity. There
+ * is limited support for single pass processing of such nested
+ * streams. The nested stream is <strong>required</strong> to have a
+ * boundary token of the same length as the parent stream (see {@link
+ * #setBoundary(byte[])}).
+ *
+ * <p>Here is an example of usage of this class.<br>
+ *
+ * <pre>
+ * try {
+ * MultipartStream multipartStream = new MultipartStream(input,
+ * boundary);
+ * boolean nextPart = multipartStream.skipPreamble();
+ * OutputStream output;
+ * while(nextPart) {
+ * header = chunks.readHeader();
+ * // process headers
+ * // create some output stream
+ * multipartStream.readBodyPart(output);
+ * nextPart = multipartStream.readBoundary();
+ * }
+ * } catch(MultipartStream.MalformedStreamException e) {
+ * // the stream failed to follow required syntax
+ * } catch(IOException) {
+ * // a read or write error occurred
+ * }
+ *
+ * </pre>
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ * @author Sean C. Sullivan
+ *
+ * @version $Id$
+ */
+public class MultipartStream {
+ /**
+ * Internal class, which is used to invoke the
+ * {@link ProgressListener}.
+ */
+ static class ProgressNotifier {
+ /** The listener to invoke.
+ */
+ private final ProgressListener listener;
+ /** Number of expected bytes, if known, or -1.
+ */
+ private final long contentLength;
+ /** Number of bytes, which have been read so far.
+ */
+ private long bytesRead;
+ /** Number of items, which have been read so far.
+ */
+ private int items;
+ /** Creates a new instance with the given listener
+ * and content length.
+ * @param pListener The listener to invoke.
+ * @param pContentLength The expected content length.
+ */
+ ProgressNotifier(ProgressListener pListener, long pContentLength) {
+ listener = pListener;
+ contentLength = pContentLength;
+ }
+ /** Called to indicate that bytes have been read.
+ * @param pBytes Number of bytes, which have been read.
+ */
+ void noteBytesRead(int pBytes) {
+ /* Indicates, that the given number of bytes have been read from
+ * the input stream.
+ */
+ bytesRead += pBytes;
+ notifyListener();
+ }
+ /** Called to indicate, that a new file item has been detected.
+ */
+ void noteItem() {
+ ++items;
+ }
+ /** Called for notifying the listener.
+ */
+ private void notifyListener() {
+ if (listener != null) {
+ listener.update(bytesRead, contentLength, items);
+ }
+ }
+ }
+
+ // ----------------------------------------------------- Manifest constants
+
+
+ /**
+ * The Carriage Return ASCII character value.
+ */
+ public static final byte CR = 0x0D;
+
+
+ /**
+ * The Line Feed ASCII character value.
+ */
+ public static final byte LF = 0x0A;
+
+
+ /**
+ * The dash (-) ASCII character value.
+ */
+ public static final byte DASH = 0x2D;
+
+
+ /**
+ * The maximum length of <code>header-part</code> that will be
+ * processed (10 kilobytes = 10240 bytes.).
+ */
+ public static final int HEADER_PART_SIZE_MAX = 10240;
+
+
+ /**
+ * The default length of the buffer used for processing a request.
+ */
+ protected static final int DEFAULT_BUFSIZE = 4096;
+
+
+ /**
+ * A byte sequence that marks the end of <code>header-part</code>
+ * (<code>CRLFCRLF</code>).
+ */
+ protected static final byte[] HEADER_SEPARATOR = {
+ CR, LF, CR, LF };
+
+
+ /**
+ * A byte sequence that that follows a delimiter that will be
+ * followed by an encapsulation (<code>CRLF</code>).
+ */
+ protected static final byte[] FIELD_SEPARATOR = {
+ CR, LF};
+
+
+ /**
+ * A byte sequence that that follows a delimiter of the last
+ * encapsulation in the stream (<code>--</code>).
+ */
+ protected static final byte[] STREAM_TERMINATOR = {
+ DASH, DASH};
+
+
+ /**
+ * A byte sequence that precedes a boundary (<code>CRLF--</code>).
+ */
+ protected static final byte[] BOUNDARY_PREFIX = {
+ CR, LF, DASH, DASH};
+
+
+ // ----------------------------------------------------------- Data members
+
+
+ /**
+ * The input stream from which data is read.
+ */
+ private final InputStream input;
+
+
+ /**
+ * The length of the boundary token plus the leading <code>CRLF--</code>.
+ */
+ private int boundaryLength;
+
+
+ /**
+ * The amount of data, in bytes, that must be kept in the buffer in order
+ * to detect delimiters reliably.
+ */
+ private int keepRegion;
+
+
+ /**
+ * The byte sequence that partitions the stream.
+ */
+ private byte[] boundary;
+
+
+ /**
+ * The length of the buffer used for processing the request.
+ */
+ private final int bufSize;
+
+
+ /**
+ * The buffer used for processing the request.
+ */
+ private final byte[] buffer;
+
+
+ /**
+ * The index of first valid character in the buffer.
+ * <br>
+ * 0 <= head < bufSize
+ */
+ private int head;
+
+
+ /**
+ * The index of last valid characer in the buffer + 1.
+ * <br>
+ * 0 <= tail <= bufSize
+ */
+ private int tail;
+
+
+ /**
+ * The content encoding to use when reading headers.
+ */
+ private String headerEncoding;
+
+
+ /**
+ * The progress notifier, if any, or null.
+ */
+ private final ProgressNotifier notifier;
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Creates a new instance.
+ * @deprecated Use {@link #MultipartStream(InputStream, byte[],
+ * org.apache.commons.fileupload.MultipartStream.ProgressNotifier)},
+ * or {@link #MultipartStream(InputStream, byte[], int,
+ * org.apache.commons.fileupload.MultipartStream.ProgressNotifier)}
+ */
+ public MultipartStream() {
+ this(null, null, null);
+ }
+
+ /**
+ * <p> Constructs a <code>MultipartStream</code> with a custom size buffer
+ * and no progress notifier.
+ *
+ * <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.
+ *
+ * @param input The <code>InputStream</code> to serve as a data source.
+ * @param boundary The token used for dividing the stream into
+ * <code>encapsulations</code>.
+ * @param bufSize The size of the buffer to be used, in bytes.
+ *
+ * @see #MultipartStream(InputStream, byte[],
+ * MultipartStream.ProgressNotifier)
+ * @deprecated Use {@link #MultipartStream(InputStream, byte[], int,
+ * org.apache.commons.fileupload.MultipartStream.ProgressNotifier)}.
+ */
+ public MultipartStream(InputStream input, byte[] boundary, int bufSize) {
+ this(input, boundary, bufSize, null);
+ }
+
+ /**
+ * <p> Constructs a <code>MultipartStream</code> 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.
+ *
+ * @param input The <code>InputStream</code> to serve as a data source.
+ * @param boundary The token used for dividing the stream into
+ * <code>encapsulations</code>.
+ * @param bufSize The size of the buffer to be used, in bytes.
+ * @param pNotifier The notifier, which is used for calling the
+ * progress listener, if any.
+ *
+ * @see #MultipartStream(InputStream, byte[],
+ * MultipartStream.ProgressNotifier)
+ */
+ MultipartStream(InputStream input,
+ byte[] boundary,
+ int bufSize,
+ ProgressNotifier pNotifier) {
+ this.input = input;
+ this.bufSize = bufSize;
+ this.buffer = new byte[bufSize];
+ this.notifier = pNotifier;
+
+ // We prepend CR/LF to the boundary to chop trailng CR/LF from
+ // body-data tokens.
+ this.boundary = new byte[boundary.length + BOUNDARY_PREFIX.length];
+ this.boundaryLength = boundary.length + BOUNDARY_PREFIX.length;
+ this.keepRegion = this.boundary.length;
+ System.arraycopy(BOUNDARY_PREFIX, 0, this.boundary, 0,
+ BOUNDARY_PREFIX.length);
+ System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length,
+ boundary.length);
+
+ head = 0;
+ tail = 0;
+ }
+
+
+ /**
+ * <p> Constructs a <code>MultipartStream</code> with a default size buffer.
+ *
+ * @param input The <code>InputStream</code> to serve as a data source.
+ * @param boundary The token used for dividing the stream into
+ * <code>encapsulations</code>.
+ * @param pNotifier An object for calling the progress listener, if any.
+ *
+ *
+ * @see #MultipartStream(InputStream, byte[], int,
+ * MultipartStream.ProgressNotifier)
+ */
+ MultipartStream(InputStream input,
+ byte[] boundary,
+ ProgressNotifier pNotifier) {
+ this(input, boundary, DEFAULT_BUFSIZE, pNotifier);
+ }
+
+ /**
+ * <p> Constructs a <code>MultipartStream</code> with a default size buffer.
+ *
+ * @param input The <code>InputStream</code> to serve as a data source.
+ * @param boundary The token used for dividing the stream into
+ * <code>encapsulations</code>.
+ *
+ * @deprecated Use {@link #MultipartStream(InputStream, byte[],
+ * MultipartStream.ProgressNotifier)}.
+ * @see #MultipartStream(InputStream, byte[], int,
+ * MultipartStream.ProgressNotifier)
+ */
+ public MultipartStream(InputStream input,
+ byte[] boundary) {
+ this(input, boundary, DEFAULT_BUFSIZE, null);
+ }
+
+ // --------------------------------------------------------- Public methods
+
+
+ /**
+ * Retrieves the character encoding used when reading the headers of an
+ * individual part. When not specified, or <code>null</code>, the platform
+ * default encoding is used.
+
+ *
+ * @return The encoding used to read part headers.
+ */
+ public String getHeaderEncoding() {
+ return headerEncoding;
+ }
+
+
+ /**
+ * Specifies the character encoding to be used when reading the headers of
+ * individual parts. When not specified, or <code>null</code>, the platform
+ * default encoding is used.
+ *
+ * @param encoding The encoding used to read part headers.
+ */
+ public void setHeaderEncoding(String encoding) {
+ headerEncoding = encoding;
+ }
+
+
+ /**
+ * Reads a byte from the <code>buffer</code>, and refills it as
+ * necessary.
+ *
+ * @return The next byte from the input stream.
+ *
+ * @throws IOException if there is no more data available.
+ */
+ public byte readByte() throws IOException {
+ // Buffer depleted ?
+ if (head == tail) {
+ head = 0;
+ // Refill.
+ tail = input.read(buffer, head, bufSize);
+ if (tail == -1) {
+ // No more data available.
+ throw new IOException("No more data is available");
+ }
+ if (notifier != null) {
+ notifier.noteBytesRead(tail);
+ }
+ }
+ return buffer[head++];
+ }
+
+
+ /**
+ * Skips a <code>boundary</code> token, and checks whether more
+ * <code>encapsulations</code> are contained in the stream.
+ *
+ * @return <code>true</code> if there are more encapsulations in
+ * this stream; <code>false</code> otherwise.
+ *
+ * @throws MalformedStreamException if the stream ends unexpecetedly or
+ * fails to follow required syntax.
+ */
+ public boolean readBoundary()
+ throws MalformedStreamException {
+ byte[] marker = new byte[2];
+ boolean nextChunk = false;
+
+ head += boundaryLength;
+ try {
+ marker[0] = readByte();
+ if (marker[0] == LF) {
+ // Work around IE5 Mac bug with input type=image.
+ // Because the boundary delimiter, not including the trailing
+ // CRLF, must not appear within any file (RFC 2046, section
+ // 5.1.1), we know the missing CR is due to a buggy browser
+ // rather than a file containing something similar to a
+ // boundary.
+ return true;
+ }
+
+ marker[1] = readByte();
+ if (arrayequals(marker, STREAM_TERMINATOR, 2)) {
+ nextChunk = false;
+ } else if (arrayequals(marker, FIELD_SEPARATOR, 2)) {
+ nextChunk = true;
+ } else {
+ throw new MalformedStreamException(
+ "Unexpected characters follow a boundary");
+ }
+ } catch (IOException e) {
+ throw new MalformedStreamException("Stream ended unexpectedly");
+ }
+ return nextChunk;
+ }
+
+
+ /**
+ * <p>Changes the boundary token used for partitioning the stream.
+ *
+ * <p>This method allows single pass processing of nested multipart
+ * streams.
+ *
+ * <p>The boundary token of the nested stream is <code>required</code>
+ * to be of the same length as the boundary token in parent stream.
+ *
+ * <p>Restoring the parent stream boundary token after processing of a
+ * nested stream is left to the application.
+ *
+ * @param boundary The boundary to be used for parsing of the nested
+ * stream.
+ *
+ * @throws IllegalBoundaryException if the <code>boundary</code>
+ * has a different length than the one
+ * being currently parsed.
+ */
+ public void setBoundary(byte[] boundary)
+ throws IllegalBoundaryException {
+ if (boundary.length != boundaryLength - BOUNDARY_PREFIX.length) {
+ throw new IllegalBoundaryException(
+ "The length of a boundary token can not be changed");
+ }
+ System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length,
+ boundary.length);
+ }
+
+
+ /**
+ * <p>Reads the <code>header-part</code> of the current
+ * <code>encapsulation</code>.
+ *
+ * <p>Headers are returned verbatim to the input stream, including the
+ * trailing <code>CRLF</code> marker. Parsing is left to the
+ * application.
+ *
+ * <p><strong>TODO</strong> allow limiting maximum header size to
+ * protect against abuse.
+ *
+ * @return The <code>header-part</code> of the current encapsulation.
+ *
+ * @throws MalformedStreamException if the stream ends unexpecetedly.
+ */
+ public String readHeaders()
+ throws MalformedStreamException {
+ int i = 0;
+ byte b;
+ // to support multi-byte characters
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ int size = 0;
+ while (i < HEADER_SEPARATOR.length) {
+ try {
+ b = readByte();
+ } catch (IOException e) {
+ throw new MalformedStreamException("Stream ended unexpectedly");
+ }
+ if (++size > HEADER_PART_SIZE_MAX) {
+ throw new MalformedStreamException(
+ "Header section has more than " + HEADER_PART_SIZE_MAX
+ + " bytes (maybe it is not properly terminated)");
+ }
+ if (b == HEADER_SEPARATOR[i]) {
+ i++;
+ } else {
+ i = 0;
+ }
+ baos.write(b);
+ }
+
+ String headers = null;
+ if (headerEncoding != null) {
+ try {
+ headers = baos.toString(headerEncoding);
+ } catch (UnsupportedEncodingException e) {
+ // Fall back to platform default if specified encoding is not
+ // supported.
+ headers = baos.toString();
+ }
+ } else {
+ headers = baos.toString();
+ }
+
+ return headers;
+ }
+
+
+ /**
+ * <p>Reads <code>body-data</code> from the current
+ * <code>encapsulation</code> and writes its contents into the
+ * output <code>Stream</code>.
+ *
+ * <p>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}).
+ *
+ * @param output The <code>Stream</code> 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.
+ * @throws IOException if an i/o error occurs.
+ */
+ public int readBodyData(OutputStream output)
+ throws MalformedStreamException, IOException {
+ final InputStream istream = newInputStream();
+ return (int) Streams.copy(istream, output, false);
+ }
+
+ /**
+ * Creates a new {@link ItemInputStream}.
+ * @return A new instance of {@link ItemInputStream}.
+ */
+ ItemInputStream newInputStream() {
+ return new ItemInputStream();
+ }
+
+ /**
+ * <p> Reads <code>body-data</code> from the current
+ * <code>encapsulation</code> and discards it.
+ *
+ * <p>Use this method to skip encapsulations you don't need or don't
+ * understand.
+ *
+ * @return The amount of data discarded.
+ *
+ * @throws MalformedStreamException if the stream ends unexpectedly.
+ * @throws IOException if an i/o error occurs.
+ */
+ public int discardBodyData()
+ throws MalformedStreamException,
+ IOException {
+ return readBodyData(null);
+ }
+
+
+ /**
+ * Finds the beginning of the first <code>encapsulation</code>.
+ *
+ * @return <code>true</code> if an <code>encapsulation</code> was found in
+ * the stream.
+ *
+ * @throws IOException if an i/o error occurs.
+ */
+ public boolean skipPreamble()
+ throws IOException {
+ // First delimiter may be not preceeded with a CRLF.
+ System.arraycopy(boundary, 2, boundary, 0, boundary.length - 2);
+ boundaryLength = boundary.length - 2;
+ try {
+ // Discard all data up to the delimiter.
+ discardBodyData();
+
+ // Read boundary - if succeded, the stream contains an
+ // encapsulation.
+ return readBoundary();
+ } catch (MalformedStreamException e) {
+ return false;
+ } finally {
+ // Restore delimiter.
+ System.arraycopy(boundary, 0, boundary, 2, boundary.length - 2);
+ boundaryLength = boundary.length;
+ boundary[0] = CR;
+ boundary[1] = LF;
+ }
+ }
+
+
+ /**
+ * Compares <code>count</code> first bytes in the arrays
+ * <code>a</code> and <code>b</code>.
+ *
+ * @param a The first array to compare.
+ * @param b The second array to compare.
+ * @param count How many bytes should be compared.
+ *
+ * @return <code>true</code> if <code>count</code> first bytes in arrays
+ * <code>a</code> and <code>b</code> are equal.
+ */
+ public static boolean arrayequals(byte[] a,
+ byte[] b,
+ int count) {
+ for (int i = 0; i < count; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ /**
+ * Searches for a byte of specified value in the <code>buffer</code>,
+ * starting at the specified <code>position</code>.
+ *
+ * @param value The value to find.
+ * @param pos The starting position for searching.
+ *
+ * @return The position of byte found, counting from beginning of the
+ * <code>buffer</code>, or <code>-1</code> if not found.
+ */
+ protected int findByte(byte value,
+ int pos) {
+ for (int i = pos; i < tail; i++) {
+ if (buffer[i] == value) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+
+ /**
+ * Searches for the <code>boundary</code> in the <code>buffer</code>
+ * region delimited by <code>head</code> and <code>tail</code>.
+ *
+ * @return The position of the boundary found, counting from the
+ * beginning of the <code>buffer</code>, or <code>-1</code> if
+ * not found.
+ */
+ protected int findSeparator() {
+ int first;
+ int match = 0;
+ int maxpos = tail - boundaryLength;
+ for (first = head;
+ (first <= maxpos) && (match != boundaryLength);
+ first++) {
+ first = findByte(boundary[0], first);
+ if (first == -1 || (first > maxpos)) {
+ return -1;
+ }
+ for (match = 1; match < boundaryLength; match++) {
+ if (buffer[first + match] != boundary[match]) {
+ break;
+ }
+ }
+ }
+ if (match == boundaryLength) {
+ return first - 1;
+ }
+ return -1;
+ }
+
+ /**
+ * Thrown to indicate that the input stream fails to follow the
+ * required syntax.
+ */
+ public static class MalformedStreamException
+ extends IOException {
+ /**
+ * Constructs a <code>MalformedStreamException</code> with no
+ * detail message.
+ */
+ public MalformedStreamException() {
+ super();
+ }
+
+ /**
+ * Constructs an <code>MalformedStreamException</code> with
+ * the specified detail message.
+ *
+ * @param message The detail message.
+ */
+ public MalformedStreamException(String message) {
+ super(message);
+ }
+ }
+
+
+ /**
+ * Thrown upon attempt of setting an invalid boundary token.
+ */
+ public static class IllegalBoundaryException
+ extends IOException {
+ /**
+ * Constructs an <code>IllegalBoundaryException</code> with no
+ * detail message.
+ */
+ public IllegalBoundaryException() {
+ super();
+ }
+
+ /**
+ * Constructs an <code>IllegalBoundaryException</code> with
+ * the specified detail message.
+ *
+ * @param message The detail message.
+ */
+ public IllegalBoundaryException(String message) {
+ super(message);
+ }
+ }
+
+ /**
+ * An {@link InputStream} for reading an items contents.
+ */
+ public class ItemInputStream extends InputStream implements Closeable {
+ /** The number of bytes, which have been read so far.
+ */
+ private long total;
+ /** The number of bytes, which must be hold, because
+ * they might be a part of the boundary.
+ */
+ private int pad;
+ /** The current offset in the buffer.
+ */
+ private int pos;
+ /** Whether the stream is already closed.
+ */
+ private boolean closed;
+
+ /**
+ * Creates a new instance.
+ */
+ ItemInputStream() {
+ findSeparator();
+ }
+
+ /**
+ * Called for finding the separator.
+ */
+ private void findSeparator() {
+ pos = MultipartStream.this.findSeparator();
+ if (pos == -1) {
+ if (tail - head > keepRegion) {
+ pad = keepRegion;
+ } else {
+ pad = tail - head;
+ }
+ }
+ }
+
+ /**
+ * Returns the number of bytes, which have been read
+ * by the stream.
+ * @return Number of bytes, which have been read so far.
+ */
+ public long getBytesRead() {
+ return total;
+ }
+
+ /**
+ * Returns the number of bytes, which are currently
+ * available, without blocking.
+ * @throws IOException An I/O error occurs.
+ * @return Number of bytes in the buffer.
+ */
+ public int available() throws IOException {
+ if (pos == -1) {
+ return tail - head - pad;
+ }
+ return pos - head;
+ }
+
+ /** Offset when converting negative bytes to integers.
+ */
+ private static final int BYTE_POSITIVE_OFFSET = 256;
+
+ /**
+ * Returns the next byte in the stream.
+ * @return The next byte in the stream, as a non-negative
+ * integer, or -1 for EOF.
+ * @throws IOException An I/O error occurred.
+ */
+ public int read() throws IOException {
+ if (closed) {
+ throw new FileItemStream.ItemSkippedException();
+ }
+ if (available() == 0) {
+ if (makeAvailable() == 0) {
+ return -1;
+ }
+ }
+ ++total;
+ int b = buffer[head++];
+ if (b >= 0) {
+ return b;
+ }
+ return b + BYTE_POSITIVE_OFFSET;
+ }
+
+ /**
+ * Reads bytes into the given buffer.
+ * @param b The destination buffer, where to write to.
+ * @param off Offset of the first byte in the buffer.
+ * @param len Maximum number of bytes to read.
+ * @return Number of bytes, which have been actually read,
+ * or -1 for EOF.
+ * @throws IOException An I/O error occurred.
+ */
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (closed) {
+ throw new FileItemStream.ItemSkippedException();
+ }
+ if (len == 0) {
+ return 0;
+ }
+ int res = available();
+ if (res == 0) {
+ res = makeAvailable();
+ if (res == 0) {
+ return -1;
+ }
+ }
+ res = Math.min(res, len);
+ System.arraycopy(buffer, head, b, off, res);
+ head += res;
+ total += res;
+ return res;
+ }
+
+ /**
+ * Closes the input stream.
+ * @throws IOException An I/O error occurred.
+ */
+ public void close() throws IOException {
+ close(false);
+ }
+
+ /**
+ * Closes the input stream.
+ * @param pCloseUnderlying Whether to close the underlying stream
+ * (hard close)
+ * @throws IOException An I/O error occurred.
+ */
+ public void close(boolean pCloseUnderlying) throws IOException {
+ if (closed) {
+ return;
+ }
+ if (pCloseUnderlying) {
+ closed = true;
+ input.close();
+ } else {
+ for (;;) {
+ int av = available();
+ if (av == 0) {
+ av = makeAvailable();
+ if (av == 0) {
+ break;
+ }
+ }
+ skip(av);
+ }
+ }
+ closed = true;
+ }
+
+ /**
+ * Skips the given number of bytes.
+ * @param bytes Number of bytes to skip.
+ * @return The number of bytes, which have actually been
+ * skipped.
+ * @throws IOException An I/O error occurred.
+ */
+ public long skip(long bytes) throws IOException {
+ if (closed) {
+ throw new FileItemStream.ItemSkippedException();
+ }
+ int av = available();
+ if (av == 0) {
+ av = makeAvailable();
+ if (av == 0) {
+ return 0;
+ }
+ }
+ long res = Math.min(av, bytes);
+ head += res;
+ return res;
+ }
+
+ /**
+ * Attempts to read more data.
+ * @return Number of available bytes
+ * @throws IOException An I/O error occurred.
+ */
+ private int makeAvailable() throws IOException {
+ if (pos != -1) {
+ return 0;
+ }
+
+ // Move the data to the beginning of the buffer.
+ total += tail - head - pad;
+ System.arraycopy(buffer, tail - pad, buffer, 0, pad);
+
+ // Refill buffer with new data.
+ head = 0;
+ tail = pad;
+
+ for (;;) {
+ int bytesRead = input.read(buffer, tail, bufSize - tail);
+ if (bytesRead == -1) {
+ // The last pad amount is left in the buffer.
+ // Boundary can't be in there so signal an error
+ // condition.
+ final String msg = "Stream ended unexpectedly";
+ throw new MalformedStreamException(msg);
+ }
+ if (notifier != null) {
+ notifier.noteBytesRead(bytesRead);
+ }
+ tail += bytesRead;
+
+ findSeparator();
+ int av = available();
+
+ if (av > 0 || pos != -1) {
+ return av;
+ }
+ }
+ }
+
+ /**
+ * Returns, whether the stream is closed.
+ * @return True, if the stream is closed, otherwise false.
+ */
+ public boolean isClosed() {
+ return closed;
+ }
+ }
+
+ // ------------------------------------------------------ Debugging methods
+
+
+ // These are the methods that were used to debug this stuff.
+ /*
+
+ // Dump data.
+ protected void dump()
+ {
+ System.out.println("01234567890");
+ byte[] temp = new byte[buffer.length];
+ for(int i=0; i<buffer.length; i++)
+ {
+ if (buffer[i] == 0x0D || buffer[i] == 0x0A)
+ {
+ temp[i] = 0x21;
+ }
+ else
+ {
+ temp[i] = buffer[i];
+ }
+ }
+ System.out.println(new String(temp));
+ int i;
+ for (i=0; i<head; i++)
+ System.out.print(" ");
+ System.out.println("h");
+ for (i=0; i<tail; i++)
+ System.out.print(" ");
+ System.out.println("t");
+ System.out.flush();
+ }
+
+ // Main routine, for testing purposes only.
+ //
+ // @param args A String[] with the command line arguments.
+ // @throws Exception, a generic exception.
+ public static void main( String[] args )
+ throws Exception
+ {
+ File boundaryFile = new File("boundary.dat");
+ int boundarySize = (int)boundaryFile.length();
+ byte[] boundary = new byte[boundarySize];
+ FileInputStream input = new FileInputStream(boundaryFile);
+ input.read(boundary,0,boundarySize);
+
+ input = new FileInputStream("multipart.dat");
+ MultipartStream chunks = new MultipartStream(input, boundary);
+
+ int i = 0;
+ String header;
+ OutputStream output;
+ boolean nextChunk = chunks.skipPreamble();
+ while (nextChunk)
+ {
+ header = chunks.readHeaders();
+ System.out.println("!"+header+"!");
+ System.out.println("wrote part"+i+".dat");
+ output = new FileOutputStream("part"+(i++)+".dat");
+ chunks.readBodyData(output);
+ nextChunk = chunks.readBoundary();
+ }
+ }
+
+ */
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/ParameterParser.java b/b_1_2_1/src/java/org/apache/commons/fileupload/ParameterParser.java
new file mode 100644
index 0000000..28e56fd
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/ParameterParser.java
@@ -0,0 +1,329 @@
+/*
+ * 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.fileupload;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A simple parser intended to parse sequences of name/value pairs.
+ * Parameter values are exptected to be enclosed in quotes if they
+ * contain unsafe characters, such as '=' characters or separators.
+ * Parameter values are optional and can be omitted.
+ *
+ * <p>
+ * <code>param1 = value; param2 = "anything goes; really"; param3</code>
+ * </p>
+ *
+ * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
+ */
+
+public class ParameterParser {
+ /**
+ * String to be parsed.
+ */
+ private char[] chars = null;
+
+ /**
+ * Current position in the string.
+ */
+ private int pos = 0;
+
+ /**
+ * Maximum position in the string.
+ */
+ private int len = 0;
+
+ /**
+ * Start of a token.
+ */
+ private int i1 = 0;
+
+ /**
+ * End of a token.
+ */
+ private int i2 = 0;
+
+ /**
+ * Whether names stored in the map should be converted to lower case.
+ */
+ private boolean lowerCaseNames = false;
+
+ /**
+ * Default ParameterParser constructor.
+ */
+ public ParameterParser() {
+ super();
+ }
+
+ /**
+ * Are there any characters left to parse?
+ *
+ * @return <tt>true</tt> if there are unparsed characters,
+ * <tt>false</tt> otherwise.
+ */
+ private boolean hasChar() {
+ return this.pos < this.len;
+ }
+
+ /**
+ * 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 <tt>true</tt> if quotation marks are expected,
+ * <tt>false</tt> otherwise.
+ * @return the token
+ */
+ private String getToken(boolean quoted) {
+ // Trim leading white spaces
+ while ((i1 < i2) && (Character.isWhitespace(chars[i1]))) {
+ i1++;
+ }
+ // Trim trailing white spaces
+ while ((i2 > i1) && (Character.isWhitespace(chars[i2 - 1]))) {
+ i2--;
+ }
+ // Strip away quotation marks if necessary
+ if (quoted) {
+ if (((i2 - i1) >= 2)
+ && (chars[i1] == '"')
+ && (chars[i2 - 1] == '"')) {
+ i1++;
+ i2--;
+ }
+ }
+ String result = null;
+ if (i2 > i1) {
+ result = new String(chars, i1, i2 - i1);
+ }
+ return result;
+ }
+
+ /**
+ * Tests if the given character is present in the array of characters.
+ *
+ * @param ch the character to test for presense in the array of characters
+ * @param charray the array of characters to test against
+ *
+ * @return <tt>true</tt> if the character is present in the array of
+ * characters, <tt>false</tt> otherwise.
+ */
+ private boolean isOneOf(char ch, final char[] charray) {
+ boolean result = false;
+ for (int i = 0; i < charray.length; i++) {
+ if (ch == charray[i]) {
+ result = true;
+ break;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * 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
+ *
+ * @return the token
+ */
+ private String parseToken(final char[] terminators) {
+ char ch;
+ i1 = pos;
+ i2 = pos;
+ while (hasChar()) {
+ ch = chars[pos];
+ if (isOneOf(ch, terminators)) {
+ break;
+ }
+ i2++;
+ pos++;
+ }
+ return getToken(false);
+ }
+
+ /**
+ * 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
+ *
+ * @return the token
+ */
+ private String parseQuotedToken(final char[] terminators) {
+ char ch;
+ i1 = pos;
+ i2 = pos;
+ boolean quoted = false;
+ boolean charEscaped = false;
+ while (hasChar()) {
+ ch = chars[pos];
+ if (!quoted && isOneOf(ch, terminators)) {
+ break;
+ }
+ if (!charEscaped && ch == '"') {
+ quoted = !quoted;
+ }
+ charEscaped = (!charEscaped && ch == '\\');
+ i2++;
+ pos++;
+
+ }
+ return getToken(true);
+ }
+
+ /**
+ * Returns <tt>true</tt> if parameter names are to be converted to lower
+ * case when name/value pairs are parsed.
+ *
+ * @return <tt>true</tt> if parameter names are to be
+ * converted to lower case when name/value pairs are parsed.
+ * Otherwise returns <tt>false</tt>
+ */
+ public boolean isLowerCaseNames() {
+ return this.lowerCaseNames;
+ }
+
+ /**
+ * Sets the flag if parameter names are to be converted to lower case when
+ * name/value pairs are parsed.
+ *
+ * @param b <tt>true</tt> if parameter names are to be
+ * converted to lower case when name/value pairs are parsed.
+ * <tt>false</tt> otherwise.
+ */
+ public void setLowerCaseNames(boolean b) {
+ this.lowerCaseNames = b;
+ }
+
+ /**
+ * 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 separators the name/value pairs separators
+ *
+ * @return a map of name/value pairs
+ */
+ public Map parse(final String str, char[] separators) {
+ if (separators == null || separators.length == 0) {
+ return new HashMap();
+ }
+ char separator = separators[0];
+ if (str != null) {
+ int idx = str.length();
+ for (int i = 0; i < separators.length; i++) {
+ int tmp = str.indexOf(separators[i]);
+ if (tmp != -1) {
+ if (tmp < idx) {
+ idx = tmp;
+ separator = separators[i];
+ }
+ }
+ }
+ }
+ return parse(str, separator);
+ }
+
+ /**
+ * 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 separator the name/value pairs separator
+ *
+ * @return a map of name/value pairs
+ */
+ public Map parse(final String str, char separator) {
+ if (str == null) {
+ return new HashMap();
+ }
+ return parse(str.toCharArray(), separator);
+ }
+
+ /**
+ * Extracts a map of name/value pairs from the given array of
+ * characters. Names are expected to be unique.
+ *
+ * @param chars 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
+ */
+ public Map parse(final char[] chars, char separator) {
+ if (chars == null) {
+ return new HashMap();
+ }
+ return parse(chars, 0, chars.length, separator);
+ }
+
+ /**
+ * Extracts a map of name/value pairs from the given array of
+ * characters. Names are expected to be unique.
+ *
+ * @param chars 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 parse(
+ final char[] chars,
+ int offset,
+ int length,
+ char separator) {
+
+ if (chars == null) {
+ return new HashMap();
+ }
+ HashMap params = new HashMap();
+ this.chars = chars;
+ this.pos = offset;
+ this.len = length;
+
+ String paramName = null;
+ String paramValue = null;
+ while (hasChar()) {
+ paramName = parseToken(new char[] {
+ '=', separator });
+ paramValue = null;
+ if (hasChar() && (chars[pos] == '=')) {
+ pos++; // skip '='
+ paramValue = parseQuotedToken(new char[] {
+ separator });
+ }
+ if (hasChar() && (chars[pos] == separator)) {
+ pos++; // skip separator
+ }
+ if ((paramName != null) && (paramName.length() > 0)) {
+ if (this.lowerCaseNames) {
+ paramName = paramName.toLowerCase();
+ }
+ params.put(paramName, paramValue);
+ }
+ }
+ return params;
+ }
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/ProgressListener.java b/b_1_2_1/src/java/org/apache/commons/fileupload/ProgressListener.java
new file mode 100644
index 0000000..00a0d27
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/ProgressListener.java
@@ -0,0 +1,34 @@
+/*
+ * 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.fileupload;
+
+
+/**
+ * The {@link ProgressListener} may be used to display a progress bar
+ * or do stuff like that.
+ */
+public interface ProgressListener {
+ /** Updates the listeners status information.
+ * @param pBytesRead The total number of bytes, which have been read
+ * so far.
+ * @param pContentLength The total number of bytes, which are being
+ * read. May be -1, if this number is unknown.
+ * @param pItems The number of the field, which is currently being
+ * read. (0 = no item so far, 1 = first item is being read, ...)
+ */
+ void update(long pBytesRead, long pContentLength, int pItems);
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/RequestContext.java b/b_1_2_1/src/java/org/apache/commons/fileupload/RequestContext.java
new file mode 100644
index 0000000..6ff7d5c
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/RequestContext.java
@@ -0,0 +1,64 @@
+/*
+ * 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.fileupload;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * <p>Abstracts access to the request information needed for file uploads. This
+ * interfsace should be implemented for each type of request that may be
+ * handled by FileUpload, such as servlets and portlets.</p>
+ *
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ *
+ * @since FileUpload 1.1
+ *
+ * @version $Id$
+ */
+public interface RequestContext {
+
+ /**
+ * Retrieve the character encoding for the request.
+ *
+ * @return The character encoding for the request.
+ */
+ String getCharacterEncoding();
+
+ /**
+ * Retrieve the content type of the request.
+ *
+ * @return The content type of the request.
+ */
+ String getContentType();
+
+ /**
+ * Retrieve the content length of the request.
+ *
+ * @return The content length of the request.
+ */
+ int getContentLength();
+
+ /**
+ * Retrieve the input stream for the request.
+ *
+ * @return The input stream for the request.
+ *
+ * @throws IOException if a problem occurs.
+ */
+ InputStream getInputStream() throws IOException;
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/disk/DiskFileItem.java b/b_1_2_1/src/java/org/apache/commons/fileupload/disk/DiskFileItem.java
new file mode 100644
index 0000000..e5f4eda
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/disk/DiskFileItem.java
@@ -0,0 +1,734 @@
+/*
+ * 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.fileupload.disk;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Map;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemHeaders;
+import org.apache.commons.fileupload.FileItemHeadersSupport;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.ParameterParser;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.DeferredFileOutputStream;
+
+
+/**
+ * <p> The default implementation of the
+ * {@link org.apache.commons.fileupload.FileItem FileItem} interface.
+ *
+ * <p> After retrieving an instance of this class from a {@link
+ * org.apache.commons.fileupload.DiskFileUpload DiskFileUpload} instance (see
+ * {@link org.apache.commons.fileupload.DiskFileUpload
+ * #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>When using the <code>DiskFileItemFactory</code>, then you should
+ * 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
+ * automatically when the class {@link org.apache.commons.io.FileCleaner}
+ * is loaded.
+ * 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>
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:sean@informage.net">Sean Legassick</a>
+ * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:jmcnally@apache.org">John McNally</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ * @author Sean C. Sullivan
+ *
+ * @since FileUpload 1.1
+ *
+ * @version $Id$
+ */
+public class DiskFileItem
+ implements FileItem, FileItemHeadersSupport {
+
+ // ----------------------------------------------------- Manifest constants
+
+ /**
+ * The UID to use when serializing this instance.
+ */
+ private static final long serialVersionUID = 2237570099615271025L;
+
+
+ /**
+ * Default content charset to be used when no explicit charset
+ * parameter is provided by the sender. Media subtypes of the
+ * "text" type are defined to have a default charset value of
+ * "ISO-8859-1" when received via HTTP.
+ */
+ public static final String DEFAULT_CHARSET = "ISO-8859-1";
+
+
+ // ----------------------------------------------------------- Data members
+
+
+ /**
+ * UID used in unique file name generation.
+ */
+ private static final String UID =
+ new java.rmi.server.UID().toString()
+ .replace(':', '_').replace('-', '_');
+
+ /**
+ * Counter used in unique identifier generation.
+ */
+ private static int counter = 0;
+
+
+ /**
+ * The name of the form field as provided by the browser.
+ */
+ private String fieldName;
+
+
+ /**
+ * The content type passed by the browser, or <code>null</code> if
+ * not defined.
+ */
+ private String contentType;
+
+
+ /**
+ * Whether or not this item is a simple form field.
+ */
+ private boolean isFormField;
+
+
+ /**
+ * The original filename in the user's filesystem.
+ */
+ private 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 int sizeThreshold;
+
+
+ /**
+ * The directory in which uploaded files will be stored, if stored on disk.
+ */
+ private 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;
+
+ /**
+ * File to allow for serialization of the content of this item.
+ */
+ private File dfosFile;
+
+ /**
+ * The file items headers.
+ */
+ private FileItemHeaders headers;
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Constructs a new <code>DiskFileItem</code> instance.
+ *
+ * @param fieldName The name of the form field.
+ * @param contentType The content type passed by the browser or
+ * <code>null</code> 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 filename in the user's filesystem, or
+ * <code>null</code> 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(String fieldName,
+ String contentType, boolean isFormField, String fileName,
+ int sizeThreshold, File repository) {
+ this.fieldName = fieldName;
+ this.contentType = contentType;
+ this.isFormField = isFormField;
+ this.fileName = fileName;
+ this.sizeThreshold = sizeThreshold;
+ this.repository = repository;
+ }
+
+
+ // ------------------------------- Methods from javax.activation.DataSource
+
+
+ /**
+ * Returns 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.
+ */
+ public InputStream getInputStream()
+ throws IOException {
+ if (!isInMemory()) {
+ return new FileInputStream(dfos.getFile());
+ }
+
+ if (cachedContent == null) {
+ cachedContent = dfos.getData();
+ }
+ return new ByteArrayInputStream(cachedContent);
+ }
+
+
+ /**
+ * Returns the content type passed by the agent or <code>null</code> if
+ * not defined.
+ *
+ * @return The content type passed by the agent or <code>null</code> if
+ * not defined.
+ */
+ public String getContentType() {
+ return contentType;
+ }
+
+
+ /**
+ * Returns the content charset passed by the agent or <code>null</code> if
+ * not defined.
+ *
+ * @return The content charset passed by the agent or <code>null</code> if
+ * not defined.
+ */
+ public String getCharSet() {
+ ParameterParser parser = new ParameterParser();
+ parser.setLowerCaseNames(true);
+ // Parameter parser can handle null input
+ Map params = parser.parse(getContentType(), ';');
+ return (String) params.get("charset");
+ }
+
+
+ /**
+ * Returns the original filename in the client's filesystem.
+ *
+ * @return The original filename in the client's filesystem.
+ */
+ public String getName() {
+ return fileName;
+ }
+
+
+ // ------------------------------------------------------- FileItem methods
+
+
+ /**
+ * Provides a hint as to whether or not the file contents will be read
+ * from memory.
+ *
+ * @return <code>true</code> if the file contents will be read
+ * from memory; <code>false</code> otherwise.
+ */
+ public boolean isInMemory() {
+ if (cachedContent != null) {
+ return true;
+ }
+ return dfos.isInMemory();
+ }
+
+
+ /**
+ * Returns the size of the file.
+ *
+ * @return The size of the file, in bytes.
+ */
+ public long getSize() {
+ if (size >= 0) {
+ return size;
+ } else if (cachedContent != null) {
+ return cachedContent.length;
+ } else if (dfos.isInMemory()) {
+ return dfos.getData().length;
+ } else {
+ return dfos.getFile().length();
+ }
+ }
+
+
+ /**
+ * Returns 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.
+ */
+ public byte[] get() {
+ if (isInMemory()) {
+ if (cachedContent == null) {
+ cachedContent = dfos.getData();
+ }
+ return cachedContent;
+ }
+
+ byte[] fileData = new byte[(int) getSize()];
+ FileInputStream fis = null;
+
+ try {
+ fis = new FileInputStream(dfos.getFile());
+ fis.read(fileData);
+ } catch (IOException e) {
+ fileData = null;
+ } finally {
+ if (fis != null) {
+ try {
+ fis.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+
+ return fileData;
+ }
+
+
+ /**
+ * Returns 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.
+ */
+ public String getString(final String charset)
+ throws UnsupportedEncodingException {
+ return new String(get(), charset);
+ }
+
+
+ /**
+ * Returns 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.
+ *
+ * @return The contents of the file, as a string.
+ *
+ * @todo Consider making this method throw UnsupportedEncodingException.
+ */
+ public String getString() {
+ byte[] rawdata = get();
+ String charset = getCharSet();
+ if (charset == null) {
+ charset = DEFAULT_CHARSET;
+ }
+ try {
+ return new String(rawdata, charset);
+ } catch (UnsupportedEncodingException e) {
+ return new String(rawdata);
+ }
+ }
+
+
+ /**
+ * A convenience method to write an uploaded item to disk. 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>
+ * 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>
+ * 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.
+ *
+ * @param file The <code>File</code> into which the uploaded item should
+ * be stored.
+ *
+ * @throws Exception if an error occurs.
+ */
+ public void write(File file) throws Exception {
+ if (isInMemory()) {
+ FileOutputStream fout = null;
+ try {
+ fout = new FileOutputStream(file);
+ fout.write(get());
+ } finally {
+ if (fout != null) {
+ fout.close();
+ }
+ }
+ } else {
+ File outputFile = getStoreLocation();
+ if (outputFile != null) {
+ // 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 (!outputFile.renameTo(file)) {
+ BufferedInputStream in = null;
+ BufferedOutputStream out = null;
+ try {
+ in = new BufferedInputStream(
+ new FileInputStream(outputFile));
+ out = new BufferedOutputStream(
+ new FileOutputStream(file));
+ IOUtils.copy(in, out);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+ }
+ } else {
+ /*
+ * For whatever reason we cannot write the
+ * file to disk.
+ */
+ throw new FileUploadException(
+ "Cannot write uploaded file to disk!");
+ }
+ }
+ }
+
+
+ /**
+ * Deletes the underlying storage for a file item, including deleting any
+ * associated temporary disk file. Although this storage will be deleted
+ * automatically when the <code>FileItem</code> instance is garbage
+ * collected, this method can be used to ensure that this is done at an
+ * earlier time, thus preserving system resources.
+ */
+ public void delete() {
+ cachedContent = null;
+ File outputFile = getStoreLocation();
+ if (outputFile != null && outputFile.exists()) {
+ outputFile.delete();
+ }
+ }
+
+
+ /**
+ * Returns the name of the field in the multipart form corresponding to
+ * this file item.
+ *
+ * @return The name of the form field.
+ *
+ * @see #setFieldName(java.lang.String)
+ *
+ */
+ public String getFieldName() {
+ return fieldName;
+ }
+
+
+ /**
+ * Sets the field name used to reference this file item.
+ *
+ * @param fieldName The name of the form field.
+ *
+ * @see #getFieldName()
+ *
+ */
+ public void setFieldName(String fieldName) {
+ this.fieldName = fieldName;
+ }
+
+
+ /**
+ * Determines whether or not a <code>FileItem</code> instance represents
+ * a simple form field.
+ *
+ * @return <code>true</code> if the instance represents a simple form
+ * field; <code>false</code> if it represents an uploaded file.
+ *
+ * @see #setFormField(boolean)
+ *
+ */
+ public boolean isFormField() {
+ return isFormField;
+ }
+
+
+ /**
+ * Specifies whether or not a <code>FileItem</code> instance represents
+ * a simple form field.
+ *
+ * @param state <code>true</code> if the instance represents a simple form
+ * field; <code>false</code> if it represents an uploaded file.
+ *
+ * @see #isFormField()
+ *
+ */
+ public void setFormField(boolean state) {
+ isFormField = state;
+ }
+
+
+ /**
+ * Returns 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 contensts of the file.
+ *
+ * @throws IOException if an error occurs.
+ */
+ public OutputStream getOutputStream()
+ throws IOException {
+ if (dfos == null) {
+ File outputFile = getTempFile();
+ dfos = new DeferredFileOutputStream(sizeThreshold, outputFile);
+ }
+ return dfos;
+ }
+
+
+ // --------------------------------------------------------- Public methods
+
+
+ /**
+ * Returns the {@link java.io.File} object for the <code>FileItem</code>'s
+ * data's temporary location on the disk. Note that for
+ * <code>FileItem</code>s that have their data stored in memory,
+ * this method will return <code>null</code>. 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</code> if the data is stored in
+ * memory.
+ */
+ public File getStoreLocation() {
+ return dfos == null ? null : dfos.getFile();
+ }
+
+
+ // ------------------------------------------------------ Protected methods
+
+
+ /**
+ * Removes the file contents from the temporary storage.
+ */
+ protected void finalize() {
+ File outputFile = dfos.getFile();
+
+ if (outputFile != null && outputFile.exists()) {
+ outputFile.delete();
+ }
+ }
+
+
+ /**
+ * 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</code> instance;
+ * the file will be deleted when the instance is garbage collected.
+ *
+ * @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 = new File(System.getProperty("java.io.tmpdir"));
+ }
+
+ String tempFileName =
+ "upload_" + UID + "_" + getUniqueId() + ".tmp";
+
+ tempFile = new File(tempDir, tempFileName);
+ }
+ return tempFile;
+ }
+
+
+ // -------------------------------------------------------- Private methods
+
+
+ /**
+ * Returns an identifier that is unique within the class loader used to
+ * load this class, but does not have random-like apearance.
+ *
+ * @return A String with the non-random looking instance identifier.
+ */
+ private static String getUniqueId() {
+ final int limit = 100000000;
+ int current;
+ synchronized (DiskFileItem.class) {
+ current = counter++;
+ }
+ 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;
+ }
+
+
+
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @return a string representation of this object.
+ */
+ public String toString() {
+ return "name=" + this.getName()
+ + ", StoreLocation="
+ + String.valueOf(this.getStoreLocation())
+ + ", size="
+ + this.getSize()
+ + "bytes, "
+ + "isFormField=" + isFormField()
+ + ", FieldName="
+ + this.getFieldName();
+ }
+
+
+ // -------------------------------------------------- Serialization methods
+
+
+ /**
+ * Writes the state of this object during serialization.
+ *
+ * @param out The stream to which the state should be written.
+ *
+ * @throws IOException if an error occurs.
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ // Read the data
+ if (dfos.isInMemory()) {
+ cachedContent = get();
+ } else {
+ cachedContent = null;
+ dfosFile = dfos.getFile();
+ }
+
+ // write out values
+ out.defaultWriteObject();
+ }
+
+ /**
+ * Reads the state of this object during deserialization.
+ *
+ * @param in The stream from which the state should be read.
+ *
+ * @throws IOException if an error occurs.
+ * @throws ClassNotFoundException if class cannot be found.
+ */
+ private void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException {
+ // read values
+ in.defaultReadObject();
+
+ OutputStream output = getOutputStream();
+ if (cachedContent != null) {
+ output.write(cachedContent);
+ } else {
+ FileInputStream input = new FileInputStream(dfosFile);
+ IOUtils.copy(input, output);
+ dfosFile.delete();
+ dfosFile = null;
+ }
+ output.close();
+
+ cachedContent = null;
+ }
+
+ /**
+ * Returns the file item headers.
+ * @return The file items headers.
+ */
+ public FileItemHeaders getHeaders() {
+ return headers;
+ }
+
+ /**
+ * Sets the file item headers.
+ * @param pHeaders The file items headers.
+ */
+ public void setHeaders(FileItemHeaders pHeaders) {
+ headers = pHeaders;
+ }
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/disk/DiskFileItemFactory.java b/b_1_2_1/src/java/org/apache/commons/fileupload/disk/DiskFileItemFactory.java
new file mode 100644
index 0000000..38073e7
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/disk/DiskFileItemFactory.java
@@ -0,0 +1,227 @@
+/*
+ * 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.fileupload.disk;
+
+import java.io.File;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.io.FileCleaningTracker;
+
+
+/**
+ * <p>The default {@link org.apache.commons.fileupload.FileItemFactory}
+ * implementation. This implementation creates
+ * {@link org.apache.commons.fileupload.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:
+ * <ul>
+ * <li>Size threshold is 10KB.</li>
+ * <li>Repository is the system default temp directory, as returned by
+ * <code>System.getProperty("java.io.tmpdir")</code>.</li>
+ * </ul>
+ * </p>
+ *
+ * <p>When using the <code>DiskFileItemFactory</code>, then you should
+ * 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.)
+ * Cleaning up those files is done by an instance of
+ * {@link FileCleaningTracker}, and an associated thread. In a complex
+ * environment, for example in a web application, you should consider
+ * terminating this thread, for example, when your web application
+ * ends. See the section on "Resource cleanup"
+ * in the users guide of commons-fileupload.</p>
+ *
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ *
+ * @since FileUpload 1.1
+ *
+ * @version $Id$
+ */
+public class DiskFileItemFactory implements FileItemFactory {
+
+ // ----------------------------------------------------- Manifest constants
+
+
+ /**
+ * The default threshold above which uploads will be stored on disk.
+ */
+ public static final int DEFAULT_SIZE_THRESHOLD = 10240;
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * 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;
+
+
+ /**
+ * <p>The instance of {@link FileCleaningTracker}, which is responsible
+ * for deleting temporary files.</p>
+ * <p>May be null, if tracking files is not required.</p>
+ */
+ private FileCleaningTracker fileCleaningTracker;
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * 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(int sizeThreshold, File repository) {
+ this.sizeThreshold = sizeThreshold;
+ this.repository = repository;
+ }
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * Returns 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;
+ }
+
+
+ /**
+ * 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(File repository) {
+ this.repository = repository;
+ }
+
+
+ /**
+ * Returns 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 size threshold beyond which files are written directly to disk.
+ *
+ * @param sizeThreshold The size threshold, in bytes.
+ *
+ * @see #getSizeThreshold()
+ *
+ */
+ public void setSizeThreshold(int sizeThreshold) {
+ this.sizeThreshold = sizeThreshold;
+ }
+
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * Create a new {@link org.apache.commons.fileupload.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</code> if this is a plain form field;
+ * <code>false</code> 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.
+ */
+ public FileItem createItem(String fieldName, String contentType,
+ boolean isFormField, String fileName) {
+ DiskFileItem result = new DiskFileItem(fieldName, contentType,
+ isFormField, fileName, sizeThreshold, repository);
+ FileCleaningTracker tracker = getFileCleaningTracker();
+ if (tracker != null) {
+ tracker.track(result.getTempFile(), this);
+ }
+ return result;
+ }
+
+
+ /**
+ * Returns the tracker, which is responsible for deleting temporary
+ * files.
+ * @return An instance of {@link FileCleaningTracker}, defaults to
+ * {@link org.apache.commons.io.FileCleaner#getInstance()}. Null,
+ * if temporary files aren't tracked.
+ */
+ public FileCleaningTracker getFileCleaningTracker() {
+ return fileCleaningTracker;
+ }
+
+ /**
+ * Returns the tracker, which is responsible for deleting temporary
+ * files.
+ * @param pTracker An instance of {@link FileCleaningTracker},
+ * which will from now on track the created files. May be null
+ * to disable tracking.
+ */
+ public void setFileCleaningTracker(FileCleaningTracker pTracker) {
+ fileCleaningTracker = pTracker;
+ }
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/disk/package.html b/b_1_2_1/src/java/org/apache/commons/fileupload/disk/package.html
new file mode 100644
index 0000000..08e3028
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/disk/package.html
@@ -0,0 +1,58 @@
+<!--
+ 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.
+-->
+<!-- $Id$ -->
+<html>
+ <head>
+ <title>Overview of the org.apache.commons.fileupload.disk component</title>
+ </head>
+ <body>
+ <p>
+ A disk-based implementation of the
+ {@link org.apache.commons.fileupload.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.fileupload.disk.DiskFileItemFactory DiskFileItemFactory}
+ would be created, configured, and then passed to a
+ {@link org.apache.commons.fileupload.FileUpload FileUpload}
+ implementation such as
+ {@link org.apache.commons.fileupload.servlet.ServletFileUpload ServletFileUpload}
+ or
+ {@link org.apache.commons.fileupload.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="http://commons.apache.org/fileupload/using.html" target="_top">User Guide</a>
+ for further details and examples of how to use this package.
+ </p>
+ </body>
+</html>
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/package.html b/b_1_2_1/src/java/org/apache/commons/fileupload/package.html
new file mode 100644
index 0000000..55d2723
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/package.html
@@ -0,0 +1,90 @@
+<!--
+ 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.
+-->
+<!-- $Id$ -->
+<html>
+ <head>
+ <title>Overview of the org.apache.commons.fileupload component</title>
+ </head>
+ <body>
+ <p>
+ A component for handling HTML file uploads as specified by
+ <a href="http://www.ietf.org/rfc/rfc1867.txt" target="_top">RFC 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.fileupload.FileUpload FileUpload} such as
+ {@link org.apache.commons.fileupload.servlet.ServletFileUpload ServletFileUpload}
+ or
+ {@link org.apache.commons.fileupload.portlet.PortletFileUpload PortletFileUpload},
+ together with a factory for
+ {@link org.apache.commons.fileupload.FileItem FileItem} instances,
+ such as
+ {@link org.apache.commons.fileupload.disk.DiskFileItemFactory DiskFileItemFactory}.
+ </p>
+ <p>
+ 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) {
+ 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);
+ // maximum size before a FileUploadException will be thrown
+ upload.setSizeMax(1000000);
+
+ List fileItems = upload.parseRequest(req);
+ // assume we know there are two files. The first file is a small
+ // text file, the second is unknown and is written to a file on
+ // the server
+ Iterator i = fileItems.iterator();
+ String comment = ((FileItem)i.next()).getString();
+ FileItem fi = (FileItem)i.next();
+ // filename on the client
+ String fileName = fi.getName();
+ // save comment and filename to database
+ ...
+ // write the file
+ fi.write(new File("/www/uploads/", fileName));
+ }
+</pre>
+ <p>
+ In the example above, the first file is loaded into memory as a
+ <code>String</code>. Before calling the <code>getString</code> 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="http://commons.apache.org/fileupload/using.html" target="_top">User Guide</a>
+ for further details and examples of how to use this package.
+ </p>
+ </body>
+</html>
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/portlet/PortletFileUpload.java b/b_1_2_1/src/java/org/apache/commons/fileupload/portlet/PortletFileUpload.java
new file mode 100644
index 0000000..13440d7
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/portlet/PortletFileUpload.java
@@ -0,0 +1,142 @@
+/*
+ * 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.fileupload.portlet;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.portlet.ActionRequest;
+
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.FileItemIterator;
+import org.apache.commons.fileupload.FileUpload;
+import org.apache.commons.fileupload.FileUploadBase;
+import org.apache.commons.fileupload.FileUploadException;
+
+/**
+ * <p>High level API for processing file uploads.</p>
+ *
+ * <p>This class handles multiple files per single HTML widget, sent using
+ * <code>multipart/mixed</code> encoding type, as specified by
+ * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. Use {@link
+ * #parseRequest(javax.servlet.http.HttpServletRequest)} to acquire a list
+ * of {@link org.apache.commons.fileupload.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>
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ * @author Sean C. Sullivan
+ *
+ * @since FileUpload 1.1
+ *
+ * @version $Id$
+ */
+public class PortletFileUpload extends FileUpload {
+
+ // ---------------------------------------------------------- Class methods
+
+
+ /**
+ * Utility method that determines whether the request contains multipart
+ * content.
+ *
+ * @param request The portlet request to be evaluated. Must be non-null.
+ *
+ * @return <code>true</code> if the request is multipart;
+ * <code>false</code> otherwise.
+ */
+ public static final boolean isMultipartContent(ActionRequest request) {
+ return FileUploadBase.isMultipartContent(
+ new PortletRequestContext(request));
+ }
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Constructs an uninitialised instance of this class. A factory must be
+ * configured, using <code>setFileItemFactory()</code>, before attempting
+ * to parse requests.
+ *
+ * @see FileUpload#FileUpload(FileItemFactory)
+ */
+ public PortletFileUpload() {
+ super();
+ }
+
+
+ /**
+ * Constructs an instance of this class which uses the supplied factory to
+ * create <code>FileItem</code> instances.
+ *
+ * @see FileUpload#FileUpload()
+ * @param fileItemFactory The factory to use for creating file items.
+ */
+ public PortletFileUpload(FileItemFactory fileItemFactory) {
+ super(fileItemFactory);
+ }
+
+
+ // --------------------------------------------------------- Public methods
+
+
+ /**
+ * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
+ * compliant <code>multipart/form-data</code> stream.
+ *
+ * @param request The portlet request to be parsed.
+ *
+ * @return A list of <code>FileItem</code> 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(ActionRequest request)
+ throws FileUploadException {
+ return parseRequest(new PortletRequestContext(request));
+ }
+
+ /**
+ * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
+ * compliant <code>multipart/form-data</code> stream.
+ *
+ * @param request The portlet request to be parsed.
+ *
+ * @return An iterator to instances of <code>FileItemStream</code>
+ * 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(ActionRequest request)
+ throws FileUploadException, IOException {
+ return super.getItemIterator(new PortletRequestContext(request));
+ }
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/portlet/PortletRequestContext.java b/b_1_2_1/src/java/org/apache/commons/fileupload/portlet/PortletRequestContext.java
new file mode 100644
index 0000000..e1cda25
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/portlet/PortletRequestContext.java
@@ -0,0 +1,108 @@
+/*
+ * 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.fileupload.portlet;
+
+import java.io.InputStream;
+import java.io.IOException;
+import javax.portlet.ActionRequest;
+import org.apache.commons.fileupload.RequestContext;
+
+/**
+ * <p>Provides access to the request information needed for a request made to
+ * a portlet.</p>
+ *
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ *
+ * @since FileUpload 1.1
+ *
+ * @version $Id$
+ */
+public class PortletRequestContext implements RequestContext {
+
+ // ----------------------------------------------------- Instance Variables
+
+ /**
+ * The request for which the context is being provided.
+ */
+ private ActionRequest request;
+
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Construct a context for this request.
+ *
+ * @param request The request to which this context applies.
+ */
+ public PortletRequestContext(ActionRequest request) {
+ this.request = request;
+ }
+
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * Retrieve the character encoding for the request.
+ *
+ * @return The character encoding for the request.
+ */
+ public String getCharacterEncoding() {
+ return request.getCharacterEncoding();
+ }
+
+ /**
+ * Retrieve the content type of the request.
+ *
+ * @return The content type of the request.
+ */
+ public String getContentType() {
+ return request.getContentType();
+ }
+
+ /**
+ * Retrieve the content length of the request.
+ *
+ * @return The content length of the request.
+ */
+ public int getContentLength() {
+ return request.getContentLength();
+ }
+
+ /**
+ * Retrieve the input stream for the request.
+ *
+ * @return The input stream for the request.
+ *
+ * @throws IOException if a problem occurs.
+ */
+ public InputStream getInputStream() throws IOException {
+ return request.getPortletInputStream();
+ }
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @return a string representation of this object.
+ */
+ public String toString() {
+ return "ContentLength="
+ + this.getContentLength()
+ + ", ContentType="
+ + this.getContentType();
+ }
+
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/portlet/package.html b/b_1_2_1/src/java/org/apache/commons/fileupload/portlet/package.html
new file mode 100644
index 0000000..43e3296
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/portlet/package.html
@@ -0,0 +1,49 @@
+<!--
+ 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.
+-->
+<!-- $Id$ -->
+<html>
+ <head>
+ <title>Overview of the org.apache.commons.fileupload.portlet component</title>
+ </head>
+ <body>
+ <p>
+ An implementation of
+ {@link org.apache.commons.fileupload.FileUpload FileUpload}
+ for use in portlets conforming to JSR 168. This implementation requires
+ only access to the portlet's current <code>ActionRequest</code> instance,
+ and a suitable
+ {@link org.apache.commons.fileupload.FileItemFactory FileItemFactory}
+ implementation, such as
+ {@link org.apache.commons.fileupload.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="http://commons.apache.org/fileupload/using.html" target="_top">User Guide</a>
+ for further details and examples of how to use this package.
+ </p>
+ </body>
+</html>
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/servlet/FileCleanerCleanup.java b/b_1_2_1/src/java/org/apache/commons/fileupload/servlet/FileCleanerCleanup.java
new file mode 100644
index 0000000..5ef6e6e
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/servlet/FileCleanerCleanup.java
@@ -0,0 +1,83 @@
+/*
+ * 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.fileupload.servlet;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletContextEvent;
+
+import org.apache.commons.io.FileCleaningTracker;
+
+
+/**
+ * A servlet context listener, which ensures that the
+ * {@link org.apache.commons.io.FileCleaner FileCleaner'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.
+ */
+ public static final String FILE_CLEANING_TRACKER_ATTRIBUTE
+ = FileCleanerCleanup.class.getName() + ".FileCleaningTracker";
+
+ /**
+ * Returns the instance of {@link FileCleaningTracker}, which is
+ * associated with the given {@link ServletContext}.
+ * @param pServletContext The servlet context to query
+ * @return The contexts tracker
+ */
+ public static FileCleaningTracker
+ getFileCleaningTracker(ServletContext pServletContext) {
+ return (FileCleaningTracker)
+ pServletContext.getAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE);
+ }
+
+ /**
+ * Sets the instance of {@link FileCleaningTracker}, which is
+ * associated with the given {@link ServletContext}.
+ * @param pServletContext The servlet context to modify
+ * @param pTracker The tracker to set
+ */
+ public static void setFileCleaningTracker(ServletContext pServletContext,
+ FileCleaningTracker pTracker) {
+ pServletContext.setAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE, pTracker);
+ }
+
+ /**
+ * Called when the web application is initialized. Does
+ * nothing.
+ * @param sce The servlet context, used for calling
+ * {@link #setFileCleaningTracker(ServletContext, FileCleaningTracker)}.
+ */
+ public void contextInitialized(ServletContextEvent sce) {
+ setFileCleaningTracker(sce.getServletContext(),
+ new FileCleaningTracker());
+ }
+
+ /**
+ * Called when the web application is being destroyed.
+ * Calls {@link FileCleaningTracker#exitWhenFinished()}.
+ * @param sce The servlet context, used for calling
+ * {@link #getFileCleaningTracker(ServletContext)}.
+ */
+ public void contextDestroyed(ServletContextEvent sce) {
+ getFileCleaningTracker(sce.getServletContext()).exitWhenFinished();
+ }
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/servlet/ServletFileUpload.java b/b_1_2_1/src/java/org/apache/commons/fileupload/servlet/ServletFileUpload.java
new file mode 100644
index 0000000..ba1a6d1
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/servlet/ServletFileUpload.java
@@ -0,0 +1,150 @@
+/*
+ * 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.fileupload.servlet;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.FileItemIterator;
+import org.apache.commons.fileupload.FileUpload;
+import org.apache.commons.fileupload.FileUploadException;
+
+/**
+ * <p>High level API for processing file uploads.</p>
+ *
+ * <p>This class handles multiple files per single HTML widget, sent using
+ * <code>multipart/mixed</code> 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.fileupload.FileItem}s associated with a given HTML
+ * widget.</p>
+ *
+ * <p>How the data for individual parts is stored is determined by the factory
+ * used to create them; a given part may be in memory, on disk, or somewhere
+ * else.</p>
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
+ * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ * @author Sean C. Sullivan
+ *
+ * @version $Id$
+ */
+public class ServletFileUpload extends FileUpload {
+
+ // ---------------------------------------------------------- Class methods
+
+
+ /**
+ * 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</code> if the request is multipart;
+ * <code>false</code> otherwise.
+ */
+ public static final boolean isMultipartContent(
+ HttpServletRequest request) {
+ if (!"post".equals(request.getMethod().toLowerCase())) {
+ return false;
+ }
+ String contentType = request.getContentType();
+ if (contentType == null) {
+ return false;
+ }
+ if (contentType.toLowerCase().startsWith(MULTIPART)) {
+ return true;
+ }
+ return false;
+ }
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Constructs an uninitialised instance of this class. A factory must be
+ * configured, using <code>setFileItemFactory()</code>, before attempting
+ * to parse requests.
+ *
+ * @see FileUpload#FileUpload(FileItemFactory)
+ */
+ public ServletFileUpload() {
+ super();
+ }
+
+
+ /**
+ * Constructs an instance of this class which uses the supplied factory to
+ * create <code>FileItem</code> instances.
+ *
+ * @see FileUpload#FileUpload()
+ * @param fileItemFactory The factory to use for creating file items.
+ */
+ public ServletFileUpload(FileItemFactory fileItemFactory) {
+ super(fileItemFactory);
+ }
+
+
+ // --------------------------------------------------------- Public methods
+
+
+ /**
+ * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
+ * compliant <code>multipart/form-data</code> stream.
+ *
+ * @param request The servlet request to be parsed.
+ *
+ * @return A list of <code>FileItem</code> 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(HttpServletRequest request)
+ throws FileUploadException {
+ return parseRequest(new ServletRequestContext(request));
+ }
+
+
+ /**
+ * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
+ * compliant <code>multipart/form-data</code> stream.
+ *
+ * @param request The servlet request to be parsed.
+ *
+ * @return An iterator to instances of <code>FileItemStream</code>
+ * 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(HttpServletRequest request)
+ throws FileUploadException, IOException {
+ return super.getItemIterator(new ServletRequestContext(request));
+ }
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/servlet/ServletRequestContext.java b/b_1_2_1/src/java/org/apache/commons/fileupload/servlet/ServletRequestContext.java
new file mode 100644
index 0000000..4587934
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/servlet/ServletRequestContext.java
@@ -0,0 +1,107 @@
+/*
+ * 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.fileupload.servlet;
+
+import java.io.InputStream;
+import java.io.IOException;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.fileupload.RequestContext;
+
+/**
+ * <p>Provides access to the request information needed for a request made to
+ * an HTTP servlet.</p>
+ *
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ *
+ * @since FileUpload 1.1
+ *
+ * @version $Id$
+ */
+public class ServletRequestContext implements RequestContext {
+
+ // ----------------------------------------------------- Instance Variables
+
+ /**
+ * The request for which the context is being provided.
+ */
+ private HttpServletRequest request;
+
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Construct a context for this request.
+ *
+ * @param request The request to which this context applies.
+ */
+ public ServletRequestContext(HttpServletRequest request) {
+ this.request = request;
+ }
+
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * Retrieve the character encoding for the request.
+ *
+ * @return The character encoding for the request.
+ */
+ public String getCharacterEncoding() {
+ return request.getCharacterEncoding();
+ }
+
+ /**
+ * Retrieve the content type of the request.
+ *
+ * @return The content type of the request.
+ */
+ public String getContentType() {
+ return request.getContentType();
+ }
+
+ /**
+ * Retrieve the content length of the request.
+ *
+ * @return The content length of the request.
+ */
+ public int getContentLength() {
+ return request.getContentLength();
+ }
+
+ /**
+ * Retrieve the input stream for the request.
+ *
+ * @return The input stream for the request.
+ *
+ * @throws IOException if a problem occurs.
+ */
+ public InputStream getInputStream() throws IOException {
+ return request.getInputStream();
+ }
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @return a string representation of this object.
+ */
+ public String toString() {
+ return "ContentLength="
+ + this.getContentLength()
+ + ", ContentType="
+ + this.getContentType();
+ }
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/servlet/package.html b/b_1_2_1/src/java/org/apache/commons/fileupload/servlet/package.html
new file mode 100644
index 0000000..81dab3f
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/servlet/package.html
@@ -0,0 +1,49 @@
+<!--
+ 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.
+-->
+<!-- $Id$ -->
+<html>
+ <head>
+ <title>Overview of the org.apache.commons.fileupload.servlet component</title>
+ </head>
+ <body>
+ <p>
+ An implementation of
+ {@link org.apache.commons.fileupload.FileUpload FileUpload}
+ for use in servlets conforming to JSR 53. This implementation requires
+ only access to the servlet's current <code>HttpServletRequest</code>
+ instance, and a suitable
+ {@link org.apache.commons.fileupload.FileItemFactory FileItemFactory}
+ implementation, such as
+ {@link org.apache.commons.fileupload.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="http://commons.apache.org/fileupload/using.html" target="_top">User Guide</a>
+ for further details and examples of how to use this package.
+ </p>
+ </body>
+</html>
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/util/Closeable.java b/b_1_2_1/src/java/org/apache/commons/fileupload/util/Closeable.java
new file mode 100644
index 0000000..51d6f4a
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/util/Closeable.java
@@ -0,0 +1,38 @@
+/*
+ * 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.fileupload.util;
+
+import java.io.IOException;
+
+
+/**
+ * Interface of an object, which may be closed.
+ */
+public interface Closeable {
+ /**
+ * Closes the object.
+ * @throws IOException An I/O error occurred.
+ */
+ void close() throws IOException;
+
+ /**
+ * Returns, whether the object is already closed.
+ * @return True, if the object is closed, otherwise false.
+ * @throws IOException An I/O error occurred.
+ */
+ boolean isClosed() throws IOException;
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/util/FileItemHeadersImpl.java b/b_1_2_1/src/java/org/apache/commons/fileupload/util/FileItemHeadersImpl.java
new file mode 100644
index 0000000..7ee3e60
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/util/FileItemHeadersImpl.java
@@ -0,0 +1,89 @@
+/*
+ * 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.fileupload.util;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.fileupload.FileItemHeaders;
+
+/**
+ * Default implementation of the {@link FileItemHeaders} interface.
+ *
+ * @author Michael C. Macaluso
+ * @since 1.3
+ */
+public class FileItemHeadersImpl implements FileItemHeaders, Serializable {
+ private static final long serialVersionUID = -4455695752627032559L;
+
+ /**
+ * Map of <code>String</code> keys to a <code>List</code> of
+ * <code>String</code> instances.
+ */
+ private final Map headerNameToValueListMap = new HashMap();
+
+ /**
+ * List to preserve order of headers as added. This would not be
+ * needed if a <code>LinkedHashMap</code> could be used, but don't
+ * want to depend on 1.4.
+ */
+ private final List headerNameList = new ArrayList();
+
+ public String getHeader(String name) {
+ String nameLower = name.toLowerCase();
+ List headerValueList = (List) headerNameToValueListMap.get(nameLower);
+ if (null == headerValueList) {
+ return null;
+ }
+ return (String) headerValueList.get(0);
+ }
+
+ public Iterator getHeaderNames() {
+ return headerNameList.iterator();
+ }
+
+ public Iterator getHeaders(String name) {
+ String nameLower = name.toLowerCase();
+ List headerValueList = (List) headerNameToValueListMap.get(nameLower);
+ if (null == headerValueList) {
+ return Collections.EMPTY_LIST.iterator();
+ }
+ return headerValueList.iterator();
+ }
+
+ /**
+ * Method to add header values to this instance.
+ *
+ * @param name name of this header
+ * @param value value of this header
+ */
+ public synchronized void addHeader(String name, String value) {
+ String nameLower = name.toLowerCase();
+ List headerValueList = (List) headerNameToValueListMap.get(nameLower);
+ if (null == headerValueList) {
+ headerValueList = new ArrayList();
+ headerNameToValueListMap.put(nameLower, headerValueList);
+ headerNameList.add(nameLower);
+ }
+ headerValueList.add(value);
+ }
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/util/LimitedInputStream.java b/b_1_2_1/src/java/org/apache/commons/fileupload/util/LimitedInputStream.java
new file mode 100644
index 0000000..e65d335
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/util/LimitedInputStream.java
@@ -0,0 +1,155 @@
+/*
+ * 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.fileupload.util;
+
+import java.io.FilterInputStream;
+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.
+ */
+public abstract class LimitedInputStream
+ extends FilterInputStream implements Closeable {
+ /**
+ * The maximum size of an item, in bytes.
+ */
+ private long sizeMax;
+ /**
+ * The current number of bytes.
+ */
+ private long count;
+ /**
+ * Whether this stream is already closed.
+ */
+ private boolean closed;
+
+ /**
+ * Creates a new instance.
+ * @param pIn The input stream, which shall be limited.
+ * @param pSizeMax The limit; no more than this number of bytes
+ * shall be returned by the source stream.
+ */
+ public LimitedInputStream(InputStream pIn, long pSizeMax) {
+ super(pIn);
+ sizeMax = pSizeMax;
+ }
+
+ /**
+ * Called to indicate, that the input streams limit has
+ * been exceeded.
+ * @param pSizeMax The input streams limit, in bytes.
+ * @param pCount The actual number of bytes.
+ * @throws IOException The called method is expected
+ * to raise an IOException.
+ */
+ protected abstract void raiseError(long pSizeMax, long pCount)
+ throws IOException;
+
+ /** Called to check, whether the input streams
+ * limit is reached.
+ * @throws IOException The given limit is exceeded.
+ */
+ private void checkLimit() throws IOException {
+ if (count > sizeMax) {
+ raiseError(sizeMax, count);
+ }
+ }
+
+ /**
+ * Reads the next byte of data from this input stream. The value
+ * byte is returned as an <code>int</code> in the range
+ * <code>0</code> to <code>255</code>. If no byte is available
+ * because the end of the stream has been reached, the value
+ * <code>-1</code> 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()</code> and returns the result.
+ *
+ * @return the next byte of data, or <code>-1</code> if the end of the
+ * stream is reached.
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public int read() throws IOException {
+ int res = super.read();
+ if (res != -1) {
+ count++;
+ checkLimit();
+ }
+ return res;
+ }
+
+ /**
+ * Reads up to <code>len</code> bytes of data from this input stream
+ * into an array of bytes. If <code>len</code> is not zero, the method
+ * blocks until some input is available; otherwise, no
+ * bytes are read and <code>0</code> is returned.
+ * <p>
+ * This method simply performs <code>in.read(b, off, len)</code>
+ * and returns the result.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off The start offset in the destination array
+ * <code>b</code>.
+ * @param len the maximum number of bytes read.
+ * @return the total number of bytes read into the buffer, or
+ * <code>-1</code> if there is no more data because the end of
+ * the stream has been reached.
+ * @exception NullPointerException If <code>b</code> is <code>null</code>.
+ * @exception IndexOutOfBoundsException If <code>off</code> is negative,
+ * <code>len</code> is negative, or <code>len</code> is greater than
+ * <code>b.length - off</code>
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public int read(byte[] b, int off, int len) throws IOException {
+ int res = super.read(b, off, len);
+ if (res > 0) {
+ count += res;
+ checkLimit();
+ }
+ return res;
+ }
+
+ /**
+ * Returns, whether this stream is already closed.
+ * @return True, if the stream is closed, otherwise false.
+ * @throws IOException An I/O error occurred.
+ */
+ public boolean isClosed() throws IOException {
+ return closed;
+ }
+
+ /**
+ * Closes this input stream and releases any system resources
+ * associated with the stream.
+ * This
+ * method simply performs <code>in.close()</code>.
+ *
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.FilterInputStream#in
+ */
+ public void close() throws IOException {
+ closed = true;
+ super.close();
+ }
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/util/Streams.java b/b_1_2_1/src/java/org/apache/commons/fileupload/util/Streams.java
new file mode 100644
index 0000000..53e0387
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/util/Streams.java
@@ -0,0 +1,166 @@
+/*
+ * 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.fileupload.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+
+/** Utility class for working with streams.
+ */
+public final class Streams {
+ /**
+ * Private constructor, to prevent instantiation.
+ * This class has only static methods.
+ */
+ private Streams() {
+ // Does nothing
+ }
+
+ /**
+ * Default buffer size for use in
+ * {@link #copy(InputStream, OutputStream, boolean)}.
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+ /**
+ * Copies the contents of the given {@link InputStream}
+ * to the given {@link OutputStream}. Shortcut for
+ * <pre>
+ * copy(pInputStream, pOutputStream, new byte[8192]);
+ * </pre>
+ * @param pInputStream The input stream, which is being read.
+ * It is guaranteed, that {@link InputStream#close()} is called
+ * on the stream.
+ * @param pOutputStream The output stream, to which data should
+ * be written. May be null, in which case the input streams
+ * contents are simply discarded.
+ * @param pClose True guarantees, that {@link OutputStream#close()}
+ * is called on the stream. False indicates, that only
+ * {@link OutputStream#flush()} should be called finally.
+ *
+ * @return Number of bytes, which have been copied.
+ * @throws IOException An I/O error occurred.
+ */
+ public static long copy(InputStream pInputStream,
+ OutputStream pOutputStream, boolean pClose)
+ throws IOException {
+ return copy(pInputStream, pOutputStream, pClose,
+ new byte[DEFAULT_BUFFER_SIZE]);
+ }
+
+ /**
+ * Copies the contents of the given {@link InputStream}
+ * to the given {@link OutputStream}.
+ * @param pIn The input stream, which is being read.
+ * It is guaranteed, that {@link InputStream#close()} is called
+ * on the stream.
+ * @param pOut The output stream, to which data should
+ * be written. May be null, in which case the input streams
+ * contents are simply discarded.
+ * @param pClose True guarantees, that {@link OutputStream#close()}
+ * is called on the stream. False indicates, that only
+ * {@link OutputStream#flush()} should be called finally.
+ * @param pBuffer Temporary buffer, which is to be used for
+ * copying data.
+ * @return Number of bytes, which have been copied.
+ * @throws IOException An I/O error occurred.
+ */
+ public static long copy(InputStream pIn,
+ OutputStream pOut, boolean pClose,
+ byte[] pBuffer)
+ throws IOException {
+ OutputStream out = pOut;
+ InputStream in = pIn;
+ try {
+ long total = 0;
+ for (;;) {
+ int res = in.read(pBuffer);
+ if (res == -1) {
+ break;
+ }
+ if (res > 0) {
+ total += res;
+ if (out != null) {
+ out.write(pBuffer, 0, res);
+ }
+ }
+ }
+ if (out != null) {
+ if (pClose) {
+ out.close();
+ } else {
+ out.flush();
+ }
+ out = null;
+ }
+ in.close();
+ in = null;
+ return total;
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (Throwable t) {
+ /* Ignore me */
+ }
+ }
+ if (pClose && out != null) {
+ try {
+ out.close();
+ } catch (Throwable t) {
+ /* Ignore me */
+ }
+ }
+ }
+ }
+
+ /**
+ * This convenience method allows to read a
+ * {@link org.apache.commons.fileupload.FileItemStream}'s
+ * content into a string. The platform's default character encoding
+ * is used for converting bytes into characters.
+ * @param pStream The input stream to read.
+ * @see #asString(InputStream, String)
+ * @return The streams contents, as a string.
+ * @throws IOException An I/O error occurred.
+ */
+ public static String asString(InputStream pStream) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ copy(pStream, baos, true);
+ return baos.toString();
+ }
+
+ /**
+ * This convenience method allows to read a
+ * {@link org.apache.commons.fileupload.FileItemStream}'s
+ * content into a string, using the given character encoding.
+ * @param pStream The input stream to read.
+ * @param pEncoding The character encoding, typically "UTF-8".
+ * @see #asString(InputStream)
+ * @return The streams contents, as a string.
+ * @throws IOException An I/O error occurred.
+ */
+ public static String asString(InputStream pStream, String pEncoding)
+ throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ copy(pStream, baos, true);
+ return baos.toString(pEncoding);
+ }
+}
diff --git a/b_1_2_1/src/java/org/apache/commons/fileupload/util/package.html b/b_1_2_1/src/java/org/apache/commons/fileupload/util/package.html
new file mode 100644
index 0000000..cce56c7
--- /dev/null
+++ b/b_1_2_1/src/java/org/apache/commons/fileupload/util/package.html
@@ -0,0 +1,29 @@
+<!--
+ 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.
+-->
+<!-- $Id: package.html 479262 2006-11-26 03:09:24Z niallp $ -->
+<html>
+ <head>
+ <title>Overview of the org.apache.commons.fileupload.util component</title>
+ </head>
+ <body>
+ <p>
+ 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.
+ </p>
+ </body>
+</html>
diff --git a/b_1_2_1/src/main/assembly/bin.xml b/b_1_2_1/src/main/assembly/bin.xml
new file mode 100644
index 0000000..dcb3262
--- /dev/null
+++ b/b_1_2_1/src/main/assembly/bin.xml
@@ -0,0 +1,39 @@
+<!--
+ 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.
+-->
+<assembly>
+ <id>bin</id>
+ <formats>
+ <format>tar.gz</format>
+ <format>zip</format>
+ </formats>
+ <includeSiteDirectory>true</includeSiteDirectory>
+ <fileSets>
+ <fileSet>
+ <includes>
+ <include>LICENSE.txt</include>
+ <include>NOTICE.txt</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target</directory>
+ <outputDirectory>lib</outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/b_1_2_1/src/main/assembly/src.xml b/b_1_2_1/src/main/assembly/src.xml
new file mode 100755
index 0000000..d120803
--- /dev/null
+++ b/b_1_2_1/src/main/assembly/src.xml
@@ -0,0 +1,46 @@
+<!--
+ 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.
+-->
+<assembly>
+ <id>src</id>
+ <formats>
+ <format>tar.gz</format>
+ <format>zip</format>
+ </formats>
+ <baseDirectory>${artifactId}-${version}-src</baseDirectory>
+ <fileSets>
+ <fileSet>
+ <includes>
+ <include>build-gump.xml</include>
+ <include>build.xml</include>
+ <include>doap_fileupload.rdf</include>
+ <include>gump.xml</include>
+ <include>LICENSE.txt</include>
+ <include>maven.xml</include>
+ <include>NOTICE.txt</include>
+ <include>pom.xml</include>
+ <include>project.properties</include>
+ <include>project.xml</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>src</directory>
+ </fileSet>
+ <fileSet>
+ <directory>xdocs</directory>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/b_1_2_1/src/media/logo.xcf b/b_1_2_1/src/media/logo.xcf
new file mode 100644
index 0000000..6a6408e
--- /dev/null
+++ b/b_1_2_1/src/media/logo.xcf
Binary files differ
diff --git a/b_1_2_1/src/site/resources/images/jakarta-logo-blue.gif b/b_1_2_1/src/site/resources/images/jakarta-logo-blue.gif
new file mode 100644
index 0000000..de02eea
--- /dev/null
+++ b/b_1_2_1/src/site/resources/images/jakarta-logo-blue.gif
Binary files differ
diff --git a/b_1_2_1/src/site/resources/images/logo.gif b/b_1_2_1/src/site/resources/images/logo.gif
new file mode 100644
index 0000000..2e54ed6
--- /dev/null
+++ b/b_1_2_1/src/site/resources/images/logo.gif
Binary files differ
diff --git a/b_1_2_1/src/site/resources/images/logo.png b/b_1_2_1/src/site/resources/images/logo.png
new file mode 100644
index 0000000..df8e9e5
--- /dev/null
+++ b/b_1_2_1/src/site/resources/images/logo.png
Binary files differ
diff --git a/b_1_2_1/src/site/site.xml b/b_1_2_1/src/site/site.xml
new file mode 100644
index 0000000..e0f902c
--- /dev/null
+++ b/b_1_2_1/src/site/site.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ 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 name="FileUpload">
+
+ <bannerRight>
+ <name>Commons FileUpload</name>
+ <src>/images/logo.png</src>
+ <href>/index.html</href>
+ </bannerRight>
+
+ <body>
+
+ <menu name="Commons FileUpload">
+ <item name="Overview" href="/index.html"/>
+ <item name="User guide" href="/using.html"/>
+ <item name="Streaming API" href="/streaming.html"/>
+ <item name="FAQ" href="/faq.html"/>
+ <item name="Javadoc" href="apidocs/index.html"/>
+ <item name="Mailing lists" href="/mail-lists.html"/>
+ <item name="Team" href="/team-list.html"/>
+ <item name="Tasks" href="/tasks.html"/>
+ <item name="SVN repository" href="/source-repository.html"/>
+ </menu>
+
+ </body>
+</project>
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/DefaultFileItemTest.java b/b_1_2_1/src/test/org/apache/commons/fileupload/DefaultFileItemTest.java
new file mode 100644
index 0000000..939201a
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/DefaultFileItemTest.java
@@ -0,0 +1,373 @@
+/*
+ * 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.fileupload;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+import org.apache.commons.fileupload.DefaultFileItem;
+import org.apache.commons.fileupload.DefaultFileItemFactory;
+
+
+/**
+ * Unit tests for {@link org.apache.commons.fileupload.DefaultFileItem}.
+ *
+ * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
+ */
+public class DefaultFileItemTest extends TestCase
+ {
+
+ /**
+ * Content type for regular form items.
+ */
+ private static final String textContentType = "text/plain";
+
+ /**
+ * Content type for file uploads.
+ */
+ private static final String fileContentType = "application/octet-stream";
+
+ /**
+ * Very low threshold for testing memory versus disk options.
+ */
+ private static final int threshold = 16;
+
+ /**
+ * Standard JUnit test case constructor.
+ *
+ * @param name The name of the test case.
+ */
+ public DefaultFileItemTest(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Test construction of a regular text field.
+ */
+ public void testTextFieldConstruction()
+ {
+ FileItemFactory factory = createFactory(null);
+ String textFieldName = "textField";
+
+ FileItem item = factory.createItem(
+ textFieldName,
+ textContentType,
+ true,
+ null
+ );
+ assertNotNull(item);
+ assertEquals(item.getFieldName(), textFieldName);
+ assertEquals(item.getContentType(), textContentType);
+ assertTrue(item.isFormField());
+ assertNull(item.getName());
+ }
+
+ /**
+ * Test construction of a file field.
+ */
+ public void testFileFieldConstruction()
+ {
+ FileItemFactory factory = createFactory(null);
+ String fileFieldName = "fileField";
+ String fileName = "originalFileName";
+
+ FileItem item = factory.createItem(
+ fileFieldName,
+ fileContentType,
+ false,
+ fileName
+ );
+ assertNotNull(item);
+ assertEquals(item.getFieldName(), fileFieldName);
+ assertEquals(item.getContentType(), fileContentType);
+ assertFalse(item.isFormField());
+ assertEquals(item.getName(), fileName);
+ }
+
+ /**
+ * Test creation of a field for which the amount of data falls below the
+ * configured threshold.
+ */
+ public void testBelowThreshold()
+ {
+ FileItemFactory factory = createFactory(null);
+ String textFieldName = "textField";
+ String textFieldValue = "0123456789";
+ byte[] testFieldValueBytes = textFieldValue.getBytes();
+
+ FileItem item = factory.createItem(
+ textFieldName,
+ textContentType,
+ true,
+ null
+ );
+ assertNotNull(item);
+
+ try
+ {
+ OutputStream os = item.getOutputStream();
+ os.write(testFieldValueBytes);
+ os.close();
+ }
+ catch(IOException e)
+ {
+ fail("Unexpected IOException");
+ }
+ assertTrue(item.isInMemory());
+ assertEquals(item.getSize(), testFieldValueBytes.length);
+ assertTrue(Arrays.equals(item.get(), testFieldValueBytes));
+ assertEquals(item.getString(), textFieldValue);
+ }
+
+ /**
+ * Test creation of a field for which the amount of data falls above the
+ * configured threshold, where no specific repository is configured.
+ */
+ public void testAboveThresholdDefaultRepository()
+ {
+ doTestAboveThreshold(null);
+ }
+
+ /**
+ * Test creation of a field for which the amount of data falls above the
+ * configured threshold, where a specific repository is configured.
+ */
+ public void testAboveThresholdSpecifiedRepository()
+ {
+ String tempPath = System.getProperty("java.io.tmpdir");
+ String tempDirName = "testAboveThresholdSpecifiedRepository";
+ File tempDir = new File(tempPath, tempDirName);
+ tempDir.mkdir();
+ doTestAboveThreshold(tempDir);
+ assertTrue(tempDir.delete());
+ }
+
+ /**
+ * Common code for cases where the amount of data is above the configured
+ * threshold, but the ultimate destination of the data has not yet been
+ * determined.
+ *
+ * @param repository The directory within which temporary files will be
+ * created.
+ */
+ public void doTestAboveThreshold(File repository)
+ {
+ FileItemFactory factory = createFactory(repository);
+ String textFieldName = "textField";
+ String textFieldValue = "01234567890123456789";
+ byte[] testFieldValueBytes = textFieldValue.getBytes();
+
+ FileItem item = factory.createItem(
+ textFieldName,
+ textContentType,
+ true,
+ null
+ );
+ assertNotNull(item);
+
+ try
+ {
+ OutputStream os = item.getOutputStream();
+ os.write(testFieldValueBytes);
+ os.close();
+ }
+ catch(IOException e)
+ {
+ fail("Unexpected IOException");
+ }
+ assertFalse(item.isInMemory());
+ assertEquals(item.getSize(), testFieldValueBytes.length);
+ assertTrue(Arrays.equals(item.get(), testFieldValueBytes));
+ assertEquals(item.getString(), textFieldValue);
+
+ assertTrue(item instanceof DefaultFileItem);
+ DefaultFileItem dfi = (DefaultFileItem) item;
+ File storeLocation = dfi.getStoreLocation();
+ assertNotNull(storeLocation);
+ assertTrue(storeLocation.exists());
+ assertEquals(storeLocation.length(), testFieldValueBytes.length);
+
+ if (repository != null)
+ {
+ assertEquals(storeLocation.getParentFile(), repository);
+ }
+
+ item.delete();
+ }
+
+
+ /**
+ * Creates a new <code>FileItemFactory</code> and returns it, obscuring
+ * from the caller the underlying implementation of this interface.
+ *
+ * @param repository The directory within which temporary files will be
+ * created.
+ * @return the new <code>FileItemFactory</code> instance.
+ */
+ protected FileItemFactory createFactory(File repository)
+ {
+ return new DefaultFileItemFactory(threshold, repository);
+ }
+
+
+ static final String CHARSET_ISO88591 = "ISO-8859-1";
+ static final String CHARSET_ASCII = "US-ASCII";
+ static final String CHARSET_UTF8 = "UTF-8";
+ static final String CHARSET_KOI8_R = "KOI8_R";
+ static final String CHARSET_WIN1251 = "Cp1251";
+
+ static final int SWISS_GERMAN_STUFF_UNICODE [] =
+ {
+ 0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
+ };
+
+ static final int SWISS_GERMAN_STUFF_ISO8859_1 [] =
+ {
+ 0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
+ };
+
+ static final int SWISS_GERMAN_STUFF_UTF8 [] =
+ {
+ 0x47, 0x72, 0xC3, 0xBC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xC3, 0xA4,
+ 0x6D, 0xC3, 0xA4
+ };
+
+ static final int RUSSIAN_STUFF_UNICODE [] =
+ {
+ 0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438,
+ 0x432, 0x435, 0x442
+ };
+
+ static final int RUSSIAN_STUFF_UTF8 [] =
+ {
+ 0xD0, 0x92, 0xD1, 0x81, 0xD0, 0xB5, 0xD0, 0xBC, 0x5F,
+ 0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0,
+ 0xB5, 0xD1, 0x82
+ };
+
+ static final int RUSSIAN_STUFF_KOI8R [] =
+ {
+ 0xF7, 0xD3, 0xC5, 0xCD, 0x5F, 0xD0, 0xD2, 0xC9, 0xD7,
+ 0xC5, 0xD4
+ };
+
+ static final int RUSSIAN_STUFF_WIN1251 [] =
+ {
+ 0xC2, 0xF1, 0xE5, 0xEC, 0x5F, 0xEF, 0xF0, 0xE8, 0xE2,
+ 0xE5, 0xF2
+ };
+
+
+ private static String constructString(int[] unicodeChars)
+ {
+ StringBuffer buffer = new StringBuffer();
+ if (unicodeChars != null)
+ {
+ for (int i = 0; i < unicodeChars.length; i++)
+ {
+ buffer.append((char) unicodeChars[i]);
+ }
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Test construction of content charset.
+ */
+ public void testContentCharSet() throws Exception
+ {
+ FileItemFactory factory = createFactory(null);
+
+ String teststr = constructString(SWISS_GERMAN_STUFF_UNICODE);
+
+ FileItem item =
+ factory.createItem(
+ "doesnotmatter",
+ "text/plain; charset=" + CHARSET_ISO88591,
+ true,
+ null);
+ OutputStream outstream = item.getOutputStream();
+ for (int i = 0; i < SWISS_GERMAN_STUFF_ISO8859_1.length; i++)
+ {
+ outstream.write(SWISS_GERMAN_STUFF_ISO8859_1[i]);
+ }
+ outstream.close();
+ assertEquals(teststr, teststr, item.getString());
+
+ item =
+ factory.createItem(
+ "doesnotmatter",
+ "text/plain; charset=" + CHARSET_UTF8,
+ true,
+ null);
+ outstream = item.getOutputStream();
+ for (int i = 0; i < SWISS_GERMAN_STUFF_UTF8.length; i++)
+ {
+ outstream.write(SWISS_GERMAN_STUFF_UTF8[i]);
+ }
+ outstream.close();
+ assertEquals(teststr, teststr, item.getString());
+
+ teststr = constructString(RUSSIAN_STUFF_UNICODE);
+
+ item =
+ factory.createItem(
+ "doesnotmatter",
+ "text/plain; charset=" + CHARSET_KOI8_R,
+ true,
+ null);
+ outstream = item.getOutputStream();
+ for (int i = 0; i < RUSSIAN_STUFF_KOI8R.length; i++)
+ {
+ outstream.write(RUSSIAN_STUFF_KOI8R[i]);
+ }
+ outstream.close();
+ assertEquals(teststr, teststr, item.getString());
+
+ item =
+ factory.createItem(
+ "doesnotmatter",
+ "text/plain; charset=" + CHARSET_WIN1251,
+ true,
+ null);
+ outstream = item.getOutputStream();
+ for (int i = 0; i < RUSSIAN_STUFF_WIN1251.length; i++)
+ {
+ outstream.write(RUSSIAN_STUFF_WIN1251[i]);
+ }
+ outstream.close();
+ assertEquals(teststr, teststr, item.getString());
+
+ item =
+ factory.createItem(
+ "doesnotmatter",
+ "text/plain; charset=" + CHARSET_UTF8,
+ true,
+ null);
+ outstream = item.getOutputStream();
+ for (int i = 0; i < RUSSIAN_STUFF_UTF8.length; i++)
+ {
+ outstream.write(RUSSIAN_STUFF_UTF8[i]);
+ }
+ outstream.close();
+ assertEquals(teststr, teststr, item.getString());
+ }
+}
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/DiskFileItemSerializeTest.java b/b_1_2_1/src/test/org/apache/commons/fileupload/DiskFileItemSerializeTest.java
new file mode 100644
index 0000000..6c57fc8
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/DiskFileItemSerializeTest.java
@@ -0,0 +1,269 @@
+/*
+ * 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.fileupload;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import junit.framework.TestCase;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+
+
+/**
+ * Serialization Unit tests for
+ * {@link org.apache.commons.fileupload.disk.DiskFileItem}.
+ */
+public class DiskFileItemSerializeTest extends TestCase
+ {
+
+ /**
+ * Content type for regular form items.
+ */
+ private static final String textContentType = "text/plain";
+
+ /**
+ * Content type for file uploads.
+ */
+ private static final String fileContentType = "application/octet-stream";
+
+ /**
+ * Very low threshold for testing memory versus disk options.
+ */
+ private static final int threshold = 16;
+
+ /**
+ * Standard JUnit test case constructor.
+ *
+ * @param name The name of the test case.
+ */
+ public DiskFileItemSerializeTest(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Test creation of a field for which the amount of data falls below the
+ * configured threshold.
+ */
+ public void testBelowThreshold()
+ {
+
+ // Create the FileItem
+ byte[] testFieldValueBytes = createContentBytes(threshold - 1);
+ FileItem item = createFileItem(testFieldValueBytes);
+
+ // Check state is as expected
+ assertTrue("Initial: in memory", item.isInMemory());
+ assertEquals("Initial: size", item.getSize(), testFieldValueBytes.length);
+ compareBytes("Initial", item.get(), testFieldValueBytes);
+
+ // Serialize & Deserialize
+ try
+ {
+ FileItem newItem = (FileItem)serializeDeserialize(item);
+
+ // Test deserialized content is as expected
+ assertTrue("Check in memory", newItem.isInMemory());
+ compareBytes("Check", testFieldValueBytes, newItem.get());
+
+ // Compare FileItem's (except byte[])
+ compareFileItems(item, newItem);
+
+ }
+ catch(Exception e)
+ {
+ fail("Error Serializing/Deserializing: " + e);
+ }
+
+
+ }
+
+ /**
+ * Test creation of a field for which the amount of data equals the
+ * configured threshold.
+ */
+ public void testThreshold() {
+ // Create the FileItem
+ byte[] testFieldValueBytes = createContentBytes(threshold);
+ FileItem item = createFileItem(testFieldValueBytes);
+
+ // Check state is as expected
+ assertTrue("Initial: in memory", item.isInMemory());
+ assertEquals("Initial: size", item.getSize(), testFieldValueBytes.length);
+ compareBytes("Initial", item.get(), testFieldValueBytes);
+
+
+ // Serialize & Deserialize
+ try
+ {
+ FileItem newItem = (FileItem)serializeDeserialize(item);
+
+ // Test deserialized content is as expected
+ assertTrue("Check in memory", newItem.isInMemory());
+ compareBytes("Check", testFieldValueBytes, newItem.get());
+
+ // Compare FileItem's (except byte[])
+ compareFileItems(item, newItem);
+
+ }
+ catch(Exception e)
+ {
+ fail("Error Serializing/Deserializing: " + e);
+ }
+ }
+
+ /**
+ * Test creation of a field for which the amount of data falls above the
+ * configured threshold.
+ */
+ public void testAboveThreshold() {
+
+ // Create the FileItem
+ byte[] testFieldValueBytes = createContentBytes(threshold + 1);
+ FileItem item = createFileItem(testFieldValueBytes);
+
+ // Check state is as expected
+ assertFalse("Initial: in memory", item.isInMemory());
+ assertEquals("Initial: size", item.getSize(), testFieldValueBytes.length);
+ compareBytes("Initial", item.get(), testFieldValueBytes);
+
+ // Serialize & Deserialize
+ try
+ {
+ FileItem newItem = (FileItem)serializeDeserialize(item);
+
+ // Test deserialized content is as expected
+ assertFalse("Check in memory", newItem.isInMemory());
+ compareBytes("Check", testFieldValueBytes, newItem.get());
+
+ // Compare FileItem's (except byte[])
+ compareFileItems(item, newItem);
+
+ }
+ catch(Exception e)
+ {
+ fail("Error Serializing/Deserializing: " + e);
+ }
+ }
+
+ /**
+ * Compare FileItem's (except the byte[] content)
+ */
+ private void compareFileItems(FileItem origItem, FileItem newItem) {
+ assertTrue("Compare: is in Memory", origItem.isInMemory() == newItem.isInMemory());
+ assertTrue("Compare: is Form Field", origItem.isFormField() == newItem.isFormField());
+ assertEquals("Compare: Field Name", origItem.getFieldName(), newItem.getFieldName());
+ assertEquals("Compare: Content Type", origItem.getContentType(), newItem.getContentType());
+ assertEquals("Compare: File Name", origItem.getName(), newItem.getName());
+ }
+
+ /**
+ * Compare content bytes.
+ */
+ private void compareBytes(String text, byte[] origBytes, byte[] newBytes) {
+ if (origBytes == null) {
+ fail(text + " origBytes are null");
+ }
+ if (newBytes == null) {
+ fail(text + " newBytes are null");
+ }
+ assertEquals(text + " byte[] length", origBytes.length, newBytes.length);
+ for (int i = 0; i < origBytes.length; i++) {
+ assertEquals(text + " byte[" + i + "]", origBytes[i], newBytes[i]);
+ }
+ }
+
+ /**
+ * Create content bytes of a specified size.
+ */
+ private byte[] createContentBytes(int size) {
+ StringBuffer buffer = new StringBuffer(size);
+ byte count = 0;
+ for (int i = 0; i < size; i++) {
+ buffer.append(count+"");
+ count++;
+ if (count > 9) {
+ count = 0;
+ }
+ }
+ return buffer.toString().getBytes();
+ }
+
+ /**
+ * Create a FileItem with the specfied content bytes.
+ */
+ private FileItem createFileItem(byte[] contentBytes) {
+ FileItemFactory factory = new DiskFileItemFactory(threshold, null);
+ String textFieldName = "textField";
+
+ FileItem item = factory.createItem(
+ textFieldName,
+ textContentType,
+ true,
+ "My File Name"
+ );
+ try
+ {
+ OutputStream os = item.getOutputStream();
+ os.write(contentBytes);
+ os.close();
+ }
+ catch(IOException e)
+ {
+ fail("Unexpected IOException" + e);
+ }
+
+ return item;
+
+ }
+
+ /**
+ * Do serialization and deserialization.
+ */
+ private Object serializeDeserialize(Object target) {
+
+ // Serialize the test object
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(target);
+ oos.flush();
+ oos.close();
+ } catch (Exception e) {
+ fail("Exception during serialization: " + e);
+ }
+
+ // Deserialize the test object
+ Object result = null;
+ try {
+ ByteArrayInputStream bais =
+ new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ result = ois.readObject();
+ bais.close();
+ } catch (Exception e) {
+ fail("Exception during deserialization: " + e);
+ }
+ return result;
+
+ }
+
+}
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/FileItemHeadersTest.java b/b_1_2_1/src/test/org/apache/commons/fileupload/FileItemHeadersTest.java
new file mode 100644
index 0000000..af5bf82
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/FileItemHeadersTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.fileupload;
+
+import java.util.Iterator;
+
+import org.apache.commons.fileupload.util.FileItemHeadersImpl;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests {@link FileItemHeaders} and
+ * {@link FileItemHeadersImpl}.
+ *
+ * @author Michael C. Macaluso
+ */
+public class FileItemHeadersTest extends TestCase {
+ /**
+ * @throws Exception
+ */
+ public void testFileItemHeaders() throws Exception {
+ FileItemHeadersImpl aMutableFileItemHeaders = new FileItemHeadersImpl();
+ aMutableFileItemHeaders.addHeader("Content-Disposition", "form-data; name=\"FileItem\"; filename=\"file1.txt\"");
+ aMutableFileItemHeaders.addHeader("Content-Type", "text/plain");
+
+ aMutableFileItemHeaders.addHeader("TestHeader", "headerValue1");
+ aMutableFileItemHeaders.addHeader("TestHeader", "headerValue2");
+ aMutableFileItemHeaders.addHeader("TestHeader", "headerValue3");
+ aMutableFileItemHeaders.addHeader("testheader", "headerValue4");
+
+ Iterator headerNameEnumeration = aMutableFileItemHeaders.getHeaderNames();
+ assertEquals("content-disposition", (String) headerNameEnumeration.next());
+ assertEquals("content-type", (String) headerNameEnumeration.next());
+ assertEquals("testheader", (String) headerNameEnumeration.next());
+ assertFalse(headerNameEnumeration.hasNext());
+
+ 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");
+ assertNull(aMutableFileItemHeaders.getHeader("DummyHeader"));
+
+ Iterator headerValueEnumeration;
+
+ headerValueEnumeration = aMutableFileItemHeaders.getHeaders("Content-Type");
+ assertTrue(headerValueEnumeration.hasNext());
+ assertEquals(headerValueEnumeration.next(), "text/plain");
+ assertFalse(headerValueEnumeration.hasNext());
+
+ headerValueEnumeration = aMutableFileItemHeaders.getHeaders("content-type");
+ assertTrue(headerValueEnumeration.hasNext());
+ assertEquals(headerValueEnumeration.next(), "text/plain");
+ assertFalse(headerValueEnumeration.hasNext());
+
+ headerValueEnumeration = aMutableFileItemHeaders.getHeaders("TestHeader");
+ assertTrue(headerValueEnumeration.hasNext());
+ assertEquals(headerValueEnumeration.next(), "headerValue1");
+ assertTrue(headerValueEnumeration.hasNext());
+ assertEquals(headerValueEnumeration.next(), "headerValue2");
+ assertTrue(headerValueEnumeration.hasNext());
+ assertEquals(headerValueEnumeration.next(), "headerValue3");
+ assertTrue(headerValueEnumeration.hasNext());
+ assertEquals(headerValueEnumeration.next(), "headerValue4");
+ assertFalse(headerValueEnumeration.hasNext());
+
+ headerValueEnumeration = aMutableFileItemHeaders.getHeaders("DummyHeader");
+ assertFalse(headerValueEnumeration.hasNext());
+ }
+
+}
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/FileUploadTestCase.java b/b_1_2_1/src/test/org/apache/commons/fileupload/FileUploadTestCase.java
new file mode 100644
index 0000000..f8b8a3b
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/FileUploadTestCase.java
@@ -0,0 +1,54 @@
+/*
+ * 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.fileupload;
+
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+
+import junit.framework.TestCase;
+
+
+/**
+ * Base class for deriving test cases.
+ */
+public abstract class FileUploadTestCase extends TestCase {
+ protected static final String CONTENT_TYPE = "multipart/form-data; boundary=---1234";
+
+ protected List parseUpload(byte[] bytes) throws FileUploadException {
+ return parseUpload(bytes, CONTENT_TYPE);
+ }
+
+ protected List parseUpload(byte[] bytes, String contentType) throws FileUploadException {
+ ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
+ HttpServletRequest request = new MockHttpServletRequest(bytes, contentType);
+
+ List fileItems = upload.parseRequest(request);
+ return fileItems;
+ }
+
+ protected List parseUpload(String content)
+ throws UnsupportedEncodingException, FileUploadException
+ {
+ byte[] bytes = content.getBytes("US-ASCII");
+ return parseUpload(bytes, CONTENT_TYPE);
+ }
+}
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/HttpServletRequestFactory.java b/b_1_2_1/src/test/org/apache/commons/fileupload/HttpServletRequestFactory.java
new file mode 100644
index 0000000..c7c8e8e
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/HttpServletRequestFactory.java
@@ -0,0 +1,66 @@
+/*
+ * 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.fileupload;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+final class HttpServletRequestFactory
+{
+ static public HttpServletRequest createHttpServletRequestWithNullContentType()
+ {
+ byte[] requestData = "foobar".getBytes();
+ return new MockHttpServletRequest(
+ requestData,
+ null);
+ }
+
+ static public HttpServletRequest createValidHttpServletRequest(
+ final String[] strFileNames)
+ {
+ // todo - provide a real implementation
+
+ StringBuffer sbRequestData = new StringBuffer();
+
+ for (int i = 0; i < strFileNames.length; i++)
+ {
+ sbRequestData.append(strFileNames[i]);
+ }
+
+ byte[] requestData = null;
+ requestData = sbRequestData.toString().getBytes();
+
+ return new MockHttpServletRequest(
+ requestData,
+ FileUploadBase.MULTIPART_FORM_DATA);
+ }
+
+ static public HttpServletRequest createInvalidHttpServletRequest()
+ {
+ byte[] requestData = "foobar".getBytes();
+ return new MockHttpServletRequest(
+ requestData,
+ FileUploadBase.MULTIPART_FORM_DATA);
+ }
+}
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/MockHttpServletRequest.java b/b_1_2_1/src/test/org/apache/commons/fileupload/MockHttpServletRequest.java
new file mode 100644
index 0000000..c43ac73
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/MockHttpServletRequest.java
@@ -0,0 +1,553 @@
+/*
+ * 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.fileupload;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+/**
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+class MockHttpServletRequest implements HttpServletRequest
+{
+
+ private final InputStream m_requestData;
+ private final int length;
+ private String m_strContentType;
+ private Map m_headers = new java.util.HashMap();
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Creates a new instance with the given request data
+ * and content type.
+ */
+ public MockHttpServletRequest(
+ final InputStream requestData,
+ final int requestLength,
+ final String strContentType)
+ {
+ m_requestData = requestData;
+ length = requestLength;
+ m_strContentType = strContentType;
+ m_headers.put(FileUploadBase.CONTENT_TYPE, strContentType);
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getAuthType()
+ */
+ public String getAuthType()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getCookies()
+ */
+ public Cookie[] getCookies()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getDateHeader(String)
+ */
+ public long getDateHeader(String arg0)
+ {
+ return 0;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getHeader(String)
+ */
+ public String getHeader(String headerName)
+ {
+ return (String) m_headers.get(headerName);
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getHeaders(String)
+ */
+ public Enumeration getHeaders(String arg0)
+ {
+ // todo - implement
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getHeaderNames()
+ */
+ public Enumeration getHeaderNames()
+ {
+ // todo - implement
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getIntHeader(String)
+ */
+ public int getIntHeader(String arg0)
+ {
+ return 0;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getMethod()
+ */
+ public String getMethod()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getPathInfo()
+ */
+ public String getPathInfo()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getPathTranslated()
+ */
+ public String getPathTranslated()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getContextPath()
+ */
+ public String getContextPath()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getQueryString()
+ */
+ public String getQueryString()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getRemoteUser()
+ */
+ public String getRemoteUser()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#isUserInRole(String)
+ */
+ public boolean isUserInRole(String arg0)
+ {
+ return false;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
+ */
+ public Principal getUserPrincipal()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId()
+ */
+ public String getRequestedSessionId()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getRequestURI()
+ */
+ public String getRequestURI()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getRequestURL()
+ */
+ public StringBuffer getRequestURL()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getServletPath()
+ */
+ public String getServletPath()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getSession(boolean)
+ */
+ public HttpSession getSession(boolean arg0)
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getSession()
+ */
+ public HttpSession getSession()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
+ */
+ public boolean isRequestedSessionIdValid()
+ {
+ return false;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie()
+ */
+ public boolean isRequestedSessionIdFromCookie()
+ {
+ return false;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL()
+ */
+ public boolean isRequestedSessionIdFromURL()
+ {
+ return false;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl()
+ * @deprecated
+ */
+ public boolean isRequestedSessionIdFromUrl()
+ {
+ return false;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getAttribute(String)
+ */
+ public Object getAttribute(String arg0)
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getAttributeNames()
+ */
+ public Enumeration getAttributeNames()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getCharacterEncoding()
+ */
+ public String getCharacterEncoding()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#setCharacterEncoding(String)
+ */
+ public void setCharacterEncoding(String arg0)
+ throws UnsupportedEncodingException
+ {
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getContentLength()
+ */
+ public int getContentLength()
+ {
+ int iLength = 0;
+
+ if (null == m_requestData)
+ {
+ iLength = -1;
+ }
+ else
+ {
+ iLength = length;
+ }
+ return iLength;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getContentType()
+ */
+ public String getContentType()
+ {
+ return m_strContentType;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getInputStream()
+ */
+ public ServletInputStream getInputStream() throws IOException
+ {
+ ServletInputStream sis = new MyServletInputStream(m_requestData);
+ return sis;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getParameter(String)
+ */
+ public String getParameter(String arg0)
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getParameterNames()
+ */
+ public Enumeration getParameterNames()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getParameterValues(String)
+ */
+ public String[] getParameterValues(String arg0)
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getParameterMap()
+ */
+ public Map getParameterMap()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getProtocol()
+ */
+ public String getProtocol()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getScheme()
+ */
+ public String getScheme()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getServerName()
+ */
+ public String getServerName()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getLocalName()
+ */
+ public String getLocalName()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getServerPort()
+ */
+ public int getServerPort()
+ {
+ return 0;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getLocalPort()
+ */
+ public int getLocalPort()
+ {
+ return 0;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getRemotePort()
+ */
+ public int getRemotePort()
+ {
+ return 0;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getReader()
+ */
+ public BufferedReader getReader() throws IOException
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getRemoteAddr()
+ */
+ public String getRemoteAddr()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getLocalAddr()
+ */
+ public String getLocalAddr()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getRemoteHost()
+ */
+ public String getRemoteHost()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#setAttribute(String, Object)
+ */
+ public void setAttribute(String arg0, Object arg1)
+ {
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#removeAttribute(String)
+ */
+ public void removeAttribute(String arg0)
+ {
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getLocale()
+ */
+ public Locale getLocale()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getLocales()
+ */
+ public Enumeration getLocales()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#isSecure()
+ */
+ public boolean isSecure()
+ {
+ return false;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getRequestDispatcher(String)
+ */
+ public RequestDispatcher getRequestDispatcher(String arg0)
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getRealPath(String)
+ * @deprecated
+ */
+ public String getRealPath(String arg0)
+ {
+ return null;
+ }
+
+ /**
+ *
+ *
+ *
+ *
+ */
+ private static class MyServletInputStream
+ extends javax.servlet.ServletInputStream
+ {
+ private final InputStream in;
+
+ /**
+ * Creates a new instance, which returns the given
+ * streams data.
+ */
+ public MyServletInputStream(InputStream pStream)
+ {
+ in = pStream;
+ }
+
+ public int read() throws IOException
+ {
+ return in.read();
+ }
+
+ public int read(byte b[], int off, int len) throws IOException
+ {
+ return in.read(b, off, len);
+ }
+ }
+}
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/MockPortletRequest.java b/b_1_2_1/src/test/org/apache/commons/fileupload/MockPortletRequest.java
new file mode 100644
index 0000000..a085af1
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/MockPortletRequest.java
@@ -0,0 +1,316 @@
+/*
+ * 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.fileupload;
+
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.portlet.PortalContext;
+import javax.portlet.PortletMode;
+import javax.portlet.PortletPreferences;
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletSession;
+import javax.portlet.WindowState;
+
+/**
+ * A mock portlet request, useful for unit testing and offline utilities
+ *
+ * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
+ * @version $Id$
+ */
+public class MockPortletRequest implements PortletRequest
+{
+ MockPortletSession session = null;
+
+ public MockPortletRequest()
+ {
+ session = new MockPortletSession();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#isWindowStateAllowed(javax.portlet.WindowState)
+ */
+ public boolean isWindowStateAllowed(WindowState state)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#isPortletModeAllowed(javax.portlet.PortletMode)
+ */
+ public boolean isPortletModeAllowed(PortletMode mode)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getPortletMode()
+ */
+ public PortletMode getPortletMode()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getWindowState()
+ */
+ public WindowState getWindowState()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getPreferences()
+ */
+ public PortletPreferences getPreferences()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getPortletSession()
+ */
+ public PortletSession getPortletSession()
+ {
+ return session;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getPortletSession(boolean)
+ */
+ public PortletSession getPortletSession(boolean create)
+ {
+ if (session == null)
+ {
+ session = new MockPortletSession();
+ }
+ return session;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getProperty(java.lang.String)
+ */
+ public String getProperty(String name)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getProperties(java.lang.String)
+ */
+ public Enumeration getProperties(String name)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getPropertyNames()
+ */
+ public Enumeration getPropertyNames()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getPortalContext()
+ */
+ public PortalContext getPortalContext()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getAuthType()
+ */
+ public String getAuthType()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getContextPath()
+ */
+ public String getContextPath()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getRemoteUser()
+ */
+ public String getRemoteUser()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getUserPrincipal()
+ */
+ public Principal getUserPrincipal()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#isUserInRole(java.lang.String)
+ */
+ public boolean isUserInRole(String role)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getAttribute(java.lang.String)
+ */
+ public Object getAttribute(String name)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getAttributeNames()
+ */
+ public Enumeration getAttributeNames()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getParameter(java.lang.String)
+ */
+ public String getParameter(String name)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getParameterNames()
+ */
+ public Enumeration getParameterNames()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getParameterValues(java.lang.String)
+ */
+ public String[] getParameterValues(String name)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getParameterMap()
+ */
+ public Map getParameterMap()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#isSecure()
+ */
+ public boolean isSecure()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#setAttribute(java.lang.String, java.lang.Object)
+ */
+ public void setAttribute(String name, Object o)
+ {
+ // TODO Auto-generated method stub
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#removeAttribute(java.lang.String)
+ */
+ public void removeAttribute(String name)
+ {
+ // TODO Auto-generated method stub
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getRequestedSessionId()
+ */
+ public String getRequestedSessionId()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#isRequestedSessionIdValid()
+ */
+ public boolean isRequestedSessionIdValid()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getResponseContentType()
+ */
+ public String getResponseContentType()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getResponseContentTypes()
+ */
+ public Enumeration getResponseContentTypes()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getLocale()
+ */
+ public Locale getLocale()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getScheme()
+ */
+ public String getScheme()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getServerName()
+ */
+ public String getServerName()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletRequest#getServerPort()
+ */
+ public int getServerPort()
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public Enumeration getLocales()
+ {
+ return null;
+ }
+
+}
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/MockPortletSession.java b/b_1_2_1/src/test/org/apache/commons/fileupload/MockPortletSession.java
new file mode 100644
index 0000000..cbcd048
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/MockPortletSession.java
@@ -0,0 +1,171 @@
+/*
+ * 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.fileupload;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import javax.portlet.PortletContext;
+import javax.portlet.PortletSession;
+
+/**
+ * A mock portlet session, useful for unit testing and offline utilities
+ * Note: currently doesn't support scoping
+ *
+ * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
+ * @version $Id$
+ */
+public class MockPortletSession implements PortletSession
+{
+ // Hashtable (not HashMap) makes enumerations easier to work with
+ Hashtable attributes = new Hashtable();
+
+ public MockPortletSession()
+ {
+ }
+
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#getAttribute(java.lang.String)
+ */
+ public Object getAttribute(String name)
+ {
+ return attributes.get(name);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#getAttribute(java.lang.String, int)
+ */
+ public Object getAttribute(String name, int scope)
+ {
+ return attributes.get(name);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#getAttributeNames(int)
+ */
+ public Enumeration getAttributeNames(int scope)
+ {
+ return attributes.keys();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#getCreationTime()
+ */
+ public long getCreationTime()
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#getId()
+ */
+ public String getId()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#getLastAccessedTime()
+ */
+ public long getLastAccessedTime()
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#getMaxInactiveInterval()
+ */
+ public int getMaxInactiveInterval()
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#invalidate()
+ */
+ public void invalidate()
+ {
+ // TODO Auto-generated method stub
+ }
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#isNew()
+ */
+ public boolean isNew()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#removeAttribute(java.lang.String)
+ */
+ public void removeAttribute(String name)
+ {
+ attributes.remove(name);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#removeAttribute(java.lang.String, int)
+ */
+ public void removeAttribute(String name, int scope)
+ {
+ attributes.remove(name);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#setAttribute(java.lang.String, java.lang.Object)
+ */
+ public void setAttribute(String name, Object value)
+ {
+ attributes.put(name, value);
+ }
+
+ public Enumeration getAttributeNames()
+ {
+ return this.getAttributeNames(PortletSession.PORTLET_SCOPE);
+ }
+
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#setAttribute(java.lang.String, java.lang.Object, int)
+ */
+ public void setAttribute(String name, Object value, int scope)
+ {
+ attributes.put(name, value);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#setMaxInactiveInterval(int)
+ */
+ public void setMaxInactiveInterval(int interval)
+ {
+ // TODO Auto-generated method stub
+ }
+ /* (non-Javadoc)
+ * @see javax.portlet.PortletSession#getPortletContext()
+ */
+ public PortletContext getPortletContext()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/MultipartStreamTest.java b/b_1_2_1/src/test/org/apache/commons/fileupload/MultipartStreamTest.java
new file mode 100644
index 0000000..6144aa9
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/MultipartStreamTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.fileupload;
+
+
+import junit.framework.TestCase;
+import java.io.*;
+
+
+/**
+ * Unit tests {@link org.apache.commons.fileupload.MultipartStream}.
+ *
+ * @author Sean C. Sullivan
+ *
+ */
+public class MultipartStreamTest extends TestCase
+{
+ static private final String BOUNDARY_TEXT = "myboundary";
+
+ public void testThreeParamConstructor() throws Exception {
+ final String strData = "foobar";
+ final byte[] contents = strData.getBytes();
+ InputStream input = new ByteArrayInputStream(contents);
+ byte[] boundary = BOUNDARY_TEXT.getBytes();
+ int iBufSize = boundary.length;
+ MultipartStream ms = new MultipartStream(
+ input,
+ boundary,
+ iBufSize,
+ new MultipartStream.ProgressNotifier(null, contents.length));
+ }
+
+ public void testTwoParamConstructor() throws Exception {
+ final String strData = "foobar";
+ final byte[] contents = strData.getBytes();
+ InputStream input = new ByteArrayInputStream(contents);
+ byte[] boundary = BOUNDARY_TEXT.getBytes();
+ MultipartStream ms = new MultipartStream(
+ input,
+ boundary,
+ new MultipartStream.ProgressNotifier(null, contents.length));
+ }
+}
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/ParameterParserTest.java b/b_1_2_1/src/test/org/apache/commons/fileupload/ParameterParserTest.java
new file mode 100644
index 0000000..dc75fb1
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/ParameterParserTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.fileupload;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import java.util.Map;
+
+/**
+ * Unit tests for {@link ParameterParser}.
+ *
+ * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
+ */
+public class ParameterParserTest extends TestCase
+{
+
+ // ------------------------------------------------------------ Constructor
+ public ParameterParserTest(String testName)
+ {
+ super(testName);
+ }
+
+ // ------------------------------------------------------------------- Main
+ public static void main(String args[])
+ {
+ String[] testCaseName = { ParameterParserTest.class.getName()};
+ junit.textui.TestRunner.main(testCaseName);
+ }
+
+ // ------------------------------------------------------- TestCase Methods
+
+ public static Test suite()
+ {
+ return new TestSuite(ParameterParserTest.class);
+ }
+
+ public void testParsing()
+ {
+ String s =
+ "test; test1 = stuff ; test2 = \"stuff; stuff\"; test3=\"stuff";
+ ParameterParser parser = new ParameterParser();
+ Map params = parser.parse(s, ';');
+ assertEquals(null, params.get("test"));
+ assertEquals("stuff", params.get("test1"));
+ assertEquals("stuff; stuff", params.get("test2"));
+ assertEquals("\"stuff", params.get("test3"));
+
+ params = parser.parse(s, new char[] { ',', ';' });
+ assertEquals(null, params.get("test"));
+ assertEquals("stuff", params.get("test1"));
+ assertEquals("stuff; stuff", params.get("test2"));
+ assertEquals("\"stuff", params.get("test3"));
+
+ s = " test , test1=stuff , , test2=, test3, ";
+ params = parser.parse(s, ',');
+ assertEquals(null, params.get("test"));
+ assertEquals("stuff", params.get("test1"));
+ assertEquals(null, params.get("test2"));
+ assertEquals(null, params.get("test3"));
+
+ s = " test";
+ params = parser.parse(s, ';');
+ assertEquals(null, params.get("test"));
+
+ s = " ";
+ params = parser.parse(s, ';');
+ assertEquals(0, params.size());
+
+ s = " = stuff ";
+ params = parser.parse(s, ';');
+ assertEquals(0, params.size());
+ }
+
+ public void testContentTypeParsing()
+ {
+ String s = "text/plain; Charset=UTF-8";
+ ParameterParser parser = new ParameterParser();
+ parser.setLowerCaseNames(true);
+ Map params = parser.parse(s, ';');
+ assertEquals("UTF-8", params.get("charset"));
+ }
+
+ public void testParsingEscapedChars()
+ {
+ String s = "param = \"stuff\\\"; more stuff\"";
+ ParameterParser parser = new ParameterParser();
+ Map params = parser.parse(s, ';');
+ assertEquals(1, params.size());
+ assertEquals("stuff\\\"; more stuff", params.get("param"));
+
+ s = "param = \"stuff\\\\\"; anotherparam";
+ params = parser.parse(s, ';');
+ assertEquals(2, params.size());
+ assertEquals("stuff\\\\", params.get("param"));
+ assertNull(params.get("anotherparam"));
+ }
+
+ // See: http://issues.apache.org/jira/browse/FILEUPLOAD-139
+ public void testFileUpload139()
+ {
+ ParameterParser parser = new ParameterParser();
+ String s = "Content-type: multipart/form-data , boundary=AaB03x";
+ Map params = parser.parse(s, new char[] { ',', ';' });
+ assertEquals("AaB03x", params.get("boundary"));
+
+ s = "Content-type: multipart/form-data, boundary=AaB03x";
+ params = parser.parse(s, new char[] { ';', ',' });
+ assertEquals("AaB03x", params.get("boundary"));
+
+ s = "Content-type: multipart/mixed, boundary=BbC04y";
+ params = parser.parse(s, new char[] { ',', ';' });
+ assertEquals("BbC04y", params.get("boundary"));
+ }
+}
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/ProgressListenerTest.java b/b_1_2_1/src/test/org/apache/commons/fileupload/ProgressListenerTest.java
new file mode 100644
index 0000000..f4715e3
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/ProgressListenerTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.fileupload;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.fileupload.ProgressListener;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+
+
+/** Tests the progress listener.
+ */
+public class ProgressListenerTest extends FileUploadTestCase {
+ private class ProgressListenerImpl implements ProgressListener {
+ private final long expectedContentLength;
+ private final int expectedItems;
+ private Long bytesRead;
+ private Integer items;
+ ProgressListenerImpl(long pContentLength, int pItems) {
+ expectedContentLength = pContentLength;
+ expectedItems = pItems;
+ }
+ public void update(long pBytesRead, long pContentLength, int pItems) {
+ assertTrue(pBytesRead >= 0 && pBytesRead <= expectedContentLength);
+ assertTrue(pContentLength == -1 || pContentLength == expectedContentLength);
+ assertTrue(pItems >= 0 && pItems <= expectedItems);
+
+ assertTrue(bytesRead == null || pBytesRead >= bytesRead.longValue());
+ bytesRead = new Long(pBytesRead);
+ assertTrue(items == null || pItems >= items.intValue());
+ items = new Integer(pItems);
+ }
+ void checkFinished(){
+ assertEquals(expectedContentLength, bytesRead.longValue());
+ assertEquals(expectedItems, items.intValue());
+ }
+ }
+
+ /**
+ * Parse a very long file upload by using a progress listener.
+ */
+ public void testProgressListener() throws Exception {
+ final int NUM_ITEMS = 512;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ for (int i = 0; i < NUM_ITEMS; i++) {
+ String header = "-----1234\r\n"
+ + "Content-Disposition: form-data; name=\"field" + (i+1) + "\"\r\n"
+ + "\r\n";
+ baos.write(header.getBytes("US-ASCII"));
+ for (int j = 0; j < 16384+i; j++) {
+ baos.write((byte) j);
+ }
+ baos.write("\r\n".getBytes("US-ASCII"));
+ }
+ baos.write("-----1234--\r\n".getBytes("US-ASCII"));
+ byte[] contents = baos.toByteArray();
+
+ MockHttpServletRequest request = new MockHttpServletRequest(contents, "multipart/form-data; boundary=---1234");
+ runTest(NUM_ITEMS, contents.length, request);
+ request = new MockHttpServletRequest(contents, "multipart/form-data; boundary=---1234"){
+ public int getContentLength() {
+ return -1;
+ }
+ };
+ runTest(NUM_ITEMS, contents.length, request);
+ }
+
+ private void runTest(final int NUM_ITEMS, long pContentLength, MockHttpServletRequest request) throws FileUploadException, IOException {
+ ServletFileUpload upload = new ServletFileUpload();
+ ProgressListenerImpl listener = new ProgressListenerImpl(pContentLength, NUM_ITEMS);
+ upload.setProgressListener(listener);
+ FileItemIterator iter = upload.getItemIterator(request);
+ for (int i = 0; i < NUM_ITEMS; i++) {
+ FileItemStream stream = iter.next();
+ InputStream istream = stream.openStream();
+ for (int j = 0; j < 16384+i; j++) {
+ /**
+ * This used to be
+ * assertEquals((byte) j, (byte) istream.read());
+ * but this seems to trigger a bug in JRockit, so
+ * we express the same like this:
+ */
+ byte b1 = (byte) j;
+ byte b2 = (byte) istream.read();
+ if (b1 != b2) {
+ fail("Expected " + b1 + ", got " + b2);
+ }
+ }
+ assertEquals(-1, istream.read());
+ }
+ assertTrue(!iter.hasNext());
+ listener.checkFinished();
+ }
+}
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/ServletFileUploadTest.java b/b_1_2_1/src/test/org/apache/commons/fileupload/ServletFileUploadTest.java
new file mode 100644
index 0000000..3428ce9
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/ServletFileUploadTest.java
@@ -0,0 +1,301 @@
+/*
+ * 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.fileupload;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Unit tests {@link org.apache.commons.fileupload.DiskFileUpload}.
+ *
+ * @author <a href="mailto:jmcnally@apache.org">John McNally</a>
+ * @author Sean C. Sullivan
+ *
+ */
+public class ServletFileUploadTest extends FileUploadTestCase
+{
+ public void testWithInvalidRequest()
+ {
+ FileUploadBase fu = null;
+
+ fu = new DiskFileUpload();
+
+ HttpServletRequest req = HttpServletRequestFactory.createInvalidHttpServletRequest();
+
+
+ try
+ {
+ fu.parseRequest(req);
+ fail("testWithInvalidRequest: expected exception was not thrown");
+ }
+ catch (FileUploadException expected)
+ {
+ // this exception is expected
+ }
+
+ }
+
+
+ public void testWithNullContentType()
+ {
+ FileUploadBase fu = new DiskFileUpload();
+
+ HttpServletRequest req = HttpServletRequestFactory.createHttpServletRequestWithNullContentType();
+
+ try
+ {
+ fu.parseRequest(req);
+ fail("testWithNullContentType: expected exception was not thrown");
+ }
+ catch (DiskFileUpload.InvalidContentTypeException expected)
+ {
+ // this exception is expected
+ }
+ catch (FileUploadException unexpected)
+ {
+ fail("testWithNullContentType: unexpected exception was thrown");
+ }
+
+ }
+
+
+ public void testFileUpload()
+ throws IOException, FileUploadException
+ {
+ List fileItems = parseUpload("-----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" +
+ "Content-Disposition: form-data; name=\"field\"\r\n" +
+ "\r\n" +
+ "fieldValue\r\n" +
+ "-----1234\r\n" +
+ "Content-Disposition: form-data; name=\"multi\"\r\n" +
+ "\r\n" +
+ "value1\r\n" +
+ "-----1234\r\n" +
+ "Content-Disposition: form-data; name=\"multi\"\r\n" +
+ "\r\n" +
+ "value2\r\n" +
+ "-----1234--\r\n");
+ assertEquals(4, fileItems.size());
+
+ FileItem file = (FileItem) fileItems.get(0);
+ assertEquals("file", file.getFieldName());
+ assertFalse(file.isFormField());
+ assertEquals("This is the content of the file\n", file.getString());
+ assertEquals("text/whatever", file.getContentType());
+ assertEquals("foo.tab", file.getName());
+
+ FileItem field = (FileItem) fileItems.get(1);
+ assertEquals("field", field.getFieldName());
+ assertTrue(field.isFormField());
+ assertEquals("fieldValue", field.getString());
+
+ FileItem multi0 = (FileItem) fileItems.get(2);
+ assertEquals("multi", multi0.getFieldName());
+ assertTrue(multi0.isFormField());
+ assertEquals("value1", multi0.getString());
+
+ FileItem multi1 = (FileItem) fileItems.get(3);
+ assertEquals("multi", multi1.getFieldName());
+ assertTrue(multi1.isFormField());
+ assertEquals("value2", multi1.getString());
+ }
+
+ public void testFilenameCaseSensitivity()
+ throws IOException, FileUploadException
+ {
+ List fileItems = parseUpload("-----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");
+ assertEquals(1, fileItems.size());
+
+ FileItem file = (FileItem) fileItems.get(0);
+ assertEquals("FiLe", file.getFieldName());
+ assertEquals("FOO.tab", file.getName());
+ }
+
+ /**
+ * This is what the browser does if you submit the form without choosing a file.
+ */
+ public void testEmptyFile()
+ throws UnsupportedEncodingException, FileUploadException
+ {
+ List fileItems = parseUpload ("-----1234\r\n" +
+ "Content-Disposition: form-data; name=\"file\"; filename=\"\"\r\n" +
+ "\r\n" +
+ "\r\n" +
+ "-----1234--\r\n");
+ assertEquals(1, fileItems.size());
+
+ FileItem file = (FileItem) fileItems.get(0);
+ assertFalse(file.isFormField());
+ assertEquals("", file.getString());
+ assertEquals("", file.getName());
+ }
+
+ /**
+ * 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.)
+ */
+ public void testIE5MacBug()
+ throws UnsupportedEncodingException, FileUploadException
+ {
+ List fileItems = parseUpload("-----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");
+
+ assertEquals(4, fileItems.size());
+
+ FileItem field1 = (FileItem) fileItems.get(0);
+ assertEquals("field1", field1.getFieldName());
+ assertTrue(field1.isFormField());
+ assertEquals("fieldValue", field1.getString());
+
+ FileItem submitX = (FileItem) fileItems.get(1);
+ assertEquals("submitName.x", submitX.getFieldName());
+ assertTrue(submitX.isFormField());
+ assertEquals("42", submitX.getString());
+
+ FileItem submitY = (FileItem) fileItems.get(2);
+ assertEquals("submitName.y", submitY.getFieldName());
+ assertTrue(submitY.isFormField());
+ assertEquals("21", submitY.getString());
+
+ FileItem field2 = (FileItem) fileItems.get(3);
+ assertEquals("field2", field2.getFieldName());
+ assertTrue(field2.isFormField());
+ assertEquals("fieldValue2", field2.getString());
+ }
+
+ /**
+ * Test for <a href="http://issues.apache.org/jira/browse/FILEUPLOAD-62">FILEUPLOAD</a>
+ */
+ public void testFILEUPLOAD62() throws Exception {
+ final String contentType = "multipart/form-data; boundary=AaB03x";
+ final String request =
+ "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"field1\"\r\n" +
+ "\r\n" +
+ "Joe Blow\r\n" +
+ "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"pics\"\r\n" +
+ "Content-type: multipart/mixed; boundary=BbC04y\r\n" +
+ "\r\n" +
+ "--BbC04y\r\n" +
+ "Content-disposition: attachment; filename=\"file1.txt\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "... contents of file1.txt ...\r\n" +
+ "--BbC04y\r\n" +
+ "Content-disposition: attachment; filename=\"file2.gif\"\r\n" +
+ "Content-type: image/gif\r\n" +
+ "Content-Transfer-Encoding: binary\r\n" +
+ "\r\n" +
+ "...contents of file2.gif...\r\n" +
+ "--BbC04y--\r\n" +
+ "--AaB03x--";
+ List fileItems = parseUpload(request.getBytes("US-ASCII"), contentType);
+ assertEquals(3, fileItems.size());
+ FileItem item0 = (FileItem) fileItems.get(0);
+ assertEquals("field1", item0.getFieldName());
+ assertNull(item0.getName());
+ assertEquals("Joe Blow", new String(item0.get()));
+ FileItem item1 = (FileItem) fileItems.get(1);
+ assertEquals("pics", item1.getFieldName());
+ assertEquals("file1.txt", item1.getName());
+ assertEquals("... contents of file1.txt ...", new String(item1.get()));
+ FileItem item2 = (FileItem) fileItems.get(2);
+ assertEquals("pics", item2.getFieldName());
+ assertEquals("file2.gif", item2.getName());
+ assertEquals("...contents of file2.gif...", new String(item2.get()));
+ }
+
+ public void testFoldedHeaders()
+ throws IOException, FileUploadException {
+ List fileItems = parseUpload("-----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" +
+ "Content-Disposition: form-data; \r\n" +
+ "\tname=\"field\"\r\n" +
+ "\r\n" +
+ "fieldValue\r\n" +
+ "-----1234\r\n" +
+ "Content-Disposition: form-data;\r\n" +
+ " name=\"multi\"\r\n" +
+ "\r\n" +
+ "value1\r\n" +
+ "-----1234\r\n" +
+ "Content-Disposition: form-data; name=\"multi\"\r\n" +
+ "\r\n" +
+ "value2\r\n" +
+ "-----1234--\r\n");
+ assertEquals(4, fileItems.size());
+
+ FileItem file = (FileItem) fileItems.get(0);
+ assertEquals("file", file.getFieldName());
+ assertFalse(file.isFormField());
+ assertEquals("This is the content of the file\n", file.getString());
+ assertEquals("text/whatever", file.getContentType());
+ assertEquals("foo.tab", file.getName());
+
+ FileItem field = (FileItem) fileItems.get(1);
+ assertEquals("field", field.getFieldName());
+ assertTrue(field.isFormField());
+ assertEquals("fieldValue", field.getString());
+
+ FileItem multi0 = (FileItem) fileItems.get(2);
+ assertEquals("multi", multi0.getFieldName());
+ assertTrue(multi0.isFormField());
+ assertEquals("value1", multi0.getString());
+
+ FileItem multi1 = (FileItem) fileItems.get(3);
+ assertEquals("multi", multi1.getFieldName());
+ assertTrue(multi1.isFormField());
+ assertEquals("value2", multi1.getString());
+ }
+}
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/SizesTest.java b/b_1_2_1/src/test/org/apache/commons/fileupload/SizesTest.java
new file mode 100644
index 0000000..01e79e2
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/SizesTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.fileupload;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+
+
+/**
+ * Unit test for items with varying sizes.
+ */
+public class SizesTest extends FileUploadTestCase
+{
+ /** Runs a test with varying file sizes.
+ */
+ public void testFileUpload()
+ throws IOException, FileUploadException
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ int add = 16;
+ int num = 0;
+ for (int i = 0; i < 16384; i += add) {
+ if (++add == 32) {
+ add = 16;
+ }
+ String header = "-----1234\r\n"
+ + "Content-Disposition: form-data; name=\"field" + (num++) + "\"\r\n"
+ + "\r\n";
+ baos.write(header.getBytes("US-ASCII"));
+ for (int j = 0; j < i; j++) {
+ baos.write((byte) j);
+ }
+ baos.write("\r\n".getBytes("US-ASCII"));
+ }
+ baos.write("-----1234--\r\n".getBytes("US-ASCII"));
+
+ List fileItems = parseUpload(baos.toByteArray());
+ Iterator fileIter = fileItems.iterator();
+ add = 16;
+ num = 0;
+ for (int i = 0; i < 16384; i += add) {
+ if (++add == 32) {
+ add = 16;
+ }
+ FileItem item = (FileItem) fileIter.next();
+ assertEquals("field" + (num++), item.getFieldName());
+ 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 limiting the file size works.
+ */
+ 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("US-ASCII"), CONTENT_TYPE);
+ List fileItems = upload.parseRequest(req);
+ assertEquals(1, fileItems.size());
+ FileItem item = (FileItem) 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("US-ASCII"), CONTENT_TYPE);
+ fileItems = upload.parseRequest(req);
+ assertEquals(1, fileItems.size());
+ item = (FileItem) 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("US-ASCII"), CONTENT_TYPE);
+ try {
+ upload.parseRequest(req);
+ fail("Expected exception.");
+ } catch (FileUploadBase.FileSizeLimitExceededException e) {
+ assertEquals(30, e.getPermittedSize());
+ }
+ }
+}
diff --git a/b_1_2_1/src/test/org/apache/commons/fileupload/StreamingTest.java b/b_1_2_1/src/test/org/apache/commons/fileupload/StreamingTest.java
new file mode 100644
index 0000000..5cc5408
--- /dev/null
+++ b/b_1_2_1/src/test/org/apache/commons/fileupload/StreamingTest.java
@@ -0,0 +1,212 @@
+/*
+ * 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.fileupload;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.util.Iterator;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload.FileUploadBase.IOFileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.fileupload.servlet.ServletRequestContext;
+
+import junit.framework.TestCase;
+
+
+/**
+ * Unit test for items with varying sizes.
+ */
+public class StreamingTest extends TestCase
+{
+ /**
+ * Tests a file upload with varying file sizes.
+ */
+ public void testFileUpload()
+ throws IOException, FileUploadException
+ {
+ byte[] request = newRequest();
+ List fileItems = parseUpload(request);
+ Iterator fileIter = fileItems.iterator();
+ int add = 16;
+ int num = 0;
+ for (int i = 0; i < 16384; i += add) {
+ if (++add == 32) {
+ add = 16;
+ }
+ FileItem item = (FileItem) fileIter.next();
+ assertEquals("field" + (num++), item.getFieldName());
+ byte[] bytes = item.get();
+ assertEquals(i, bytes.length);
+ for (int j = 0; j < i; j++) {
+ assertEquals((byte) j, bytes[j]);
+ }
+ }
+ assertTrue(!fileIter.hasNext());
+ }
+
+
+ /**
+ * Tests, whether an invalid request throws a proper
+ * exception.
+ */
+ public void testFileUploadException()
+ throws IOException, FileUploadException {
+ byte[] request = newRequest();
+ byte[] invalidRequest = new byte[request.length-11];
+ System.arraycopy(request, 0, invalidRequest, 0, request.length-11);
+ try {
+ parseUpload(invalidRequest);
+ fail("Expected EndOfStreamException");
+ } catch (IOFileUploadException e) {
+ assertTrue(e.getCause() instanceof MultipartStream.MalformedStreamException);
+ }
+ }
+
+ /**
+ * Tests, whether an IOException is properly delegated.
+ */
+ public void testIOException()
+ throws IOException {
+ byte[] request = newRequest();
+ InputStream stream = new FilterInputStream(new ByteArrayInputStream(request)){
+ private int num;
+ public int read() throws IOException {
+ if (++num > 123) {
+ throw new IOException("123");
+ }
+ return super.read();
+ }
+ public int read(byte[] pB, int pOff, int pLen)
+ throws IOException {
+ for (int i = 0; i < pLen; i++) {
+ int res = read();
+ if (res == -1) {
+ return i == 0 ? -1 : i;
+ }
+ pB[pOff+i] = (byte) res;
+ }
+ return pLen;
+ }
+ };
+ try {
+ parseUpload(stream, request.length);
+ fail("Expected IOException");
+ } catch (FileUploadException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ assertEquals("123", e.getCause().getMessage());
+ }
+ }
+
+ /**
+ * Test for FILEUPLOAD-135
+ */
+ public void testFILEUPLOAD135()
+ throws IOException, FileUploadException
+ {
+ byte[] request = newShortRequest();
+ final ByteArrayInputStream bais = new ByteArrayInputStream(request);
+ List fileItems = parseUpload(new InputStream() {
+ public int read()
+ throws IOException
+ {
+ return bais.read();
+ }
+ public int read(byte b[], int off, int len) throws IOException
+ {
+ return bais.read(b, off, Math.min(len, 3));
+ }
+
+ }, request.length);
+ Iterator fileIter = fileItems.iterator();
+ assertTrue(fileIter.hasNext());
+ FileItem item = (FileItem) fileIter.next();
+ assertEquals("field", item.getFieldName());
+ byte[] bytes = item.get();
+ assertEquals(3, bytes.length);
+ assertEquals((byte)'1', bytes[0]);
+ assertEquals((byte)'2', bytes[1]);
+ assertEquals((byte)'3', bytes[2]);
+ assertTrue(!fileIter.hasNext());
+ }
+
+ private List parseUpload(byte[] bytes) throws FileUploadException {
+ return parseUpload(new ByteArrayInputStream(bytes), bytes.length);
+ }
+
+ private List parseUpload(InputStream pStream, int pLength)
+ throws FileUploadException {
+ String contentType = "multipart/form-data; boundary=---1234";
+
+ FileUploadBase upload = new ServletFileUpload();
+ upload.setFileItemFactory(new DiskFileItemFactory());
+ HttpServletRequest request = new MockHttpServletRequest(pStream,
+ pLength, contentType);
+
+ List fileItems = upload.parseRequest(new ServletRequestContext(request));
+ return fileItems;
+ }
+
+ private String getHeader(String pField) {
+ return "-----1234\r\n"
+ + "Content-Disposition: form-data; name=\"" + pField + "\"\r\n"
+ + "\r\n";
+
+ }
+
+ private String getFooter() {
+ return "-----1234--\r\n";
+ }
+
+ private byte[] newShortRequest() throws IOException {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final OutputStreamWriter osw = new OutputStreamWriter(baos, "US-ASCII");
+ osw.write(getHeader("field"));
+ osw.write("123");
+ osw.write("\r\n");
+ osw.write(getFooter());
+ osw.close();
+ return baos.toByteArray();
+ }
+
+ private byte[] newRequest() throws IOException {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final OutputStreamWriter osw = new OutputStreamWriter(baos, "US-ASCII");
+ int add = 16;
+ int num = 0;
+ for (int i = 0; i < 16384; i += add) {
+ if (++add == 32) {
+ add = 16;
+ }
+ osw.write(getHeader("field" + (num++)));
+ osw.flush();
+ for (int j = 0; j < i; j++) {
+ baos.write((byte) j);
+ }
+ osw.write("\r\n");
+ }
+ osw.write(getFooter());
+ osw.close();
+ return baos.toByteArray();
+ }
+}
diff --git a/b_1_2_1/xdocs/customizing.xml b/b_1_2_1/xdocs/customizing.xml
new file mode 100644
index 0000000..5aa8832
--- /dev/null
+++ b/b_1_2_1/xdocs/customizing.xml
@@ -0,0 +1,35 @@
+<?xml version="1.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.
+-->
+
+<document>
+
+ <properties>
+ <title>Customizing FileUpload</title>
+ <author email="martinc@apache.org">Martin Cooper</author>
+ </properties>
+
+<body>
+
+ <section name="Customizing FileUpload">
+ <p>
+ TODO: Document usage of factories and subclassing for customization.
+ </p>
+ </section>
+
+</body>
+</document>
diff --git a/b_1_2_1/xdocs/cvs-usage.xml b/b_1_2_1/xdocs/cvs-usage.xml
new file mode 100644
index 0000000..8d598ff
--- /dev/null
+++ b/b_1_2_1/xdocs/cvs-usage.xml
@@ -0,0 +1,45 @@
+<?xml version="1.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.
+-->
+<document>
+ <properties>
+ <title>Source Repository</title>
+ <author email="dev@commons.apache.org">Commons Documentation Team</author>
+ </properties>
+ <body>
+<!-- ================================================== -->
+<section name="Source repository">
+<p>
+ Apache Commons FileUpload is hosted on the Apache
+ <a href="http://subversion.tigris.org/">Subversion</a> repository.
+</p>
+<p>
+ The project URL is:<br />
+ <code>http://svn.apache.org/repos/asf/commons/proper/fileupload/trunk</code>
+</p>
+<p>
+ The best way to view the repository in a browser is via the
+ <a href="http://svn.apache.org/viewvc/commons/proper/fileupload/trunk/">Subversion viewer</a>.
+</p>
+<p>
+ The alternative is to use the
+ <a href="http://svn.apache.org/repos/asf/commons/proper/fileupload/trunk/">native Subversion</a> display.
+</p>
+</section>
+<!-- ================================================== -->
+</body>
+</document>
diff --git a/b_1_2_1/xdocs/faq.fml b/b_1_2_1/xdocs/faq.fml
new file mode 100644
index 0000000..75f1a86
--- /dev/null
+++ b/b_1_2_1/xdocs/faq.fml
@@ -0,0 +1,125 @@
+<?xml version="1.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.
+-->
+
+<faqs title="FileUpload FAQ">
+
+ <part id="general">
+ <title>General</title>
+
+ <faq id="empty-parse">
+ <question>
+ Why is parseRequest() returning no items?
+ </question>
+ <answer>
+ This most commonly happens when the request has already been parsed, or
+ processed in some other way. Since the input stream has aleady been
+ consumed by that earlier process, it is no longer available for parsing
+ by Commons FileUpload.
+ </answer>
+ </faq>
+
+ <faq id="read-timeout">
+ <question>
+ Why am I getting "Read timed out" exceptions while parsing?
+ </question>
+ <answer>
+ The most common cause of these exceptions is when FileUpload is being
+ used on a site that is using the Tomcat ISAPI redirector. There was a
+ bug in earlier versions of that component that caused problems with
+ multipart requests. The bug was fixed some time ago, so you probably
+ just need to pick up a newer version. See the
+ <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=15278">Tomcat bug report</a>
+ for full details.
+ </answer>
+ </faq>
+
+ <faq id="class-not-found">
+ <question>
+ Why is NoClassDefFoundError being thrown?
+ </question>
+ <answer>
+ <p>There are two common causes for this error. </p>
+
+ <p>Firstly, it might simply mean that you do not have the Commons IO
+ jar in your classpath. FileUpload depends on IO (see
+ <a href="dependencies.html">dependencies</a>) - you can tell if
+ this is the case if the missing class is within the
+ <code>org.apache.commons.io</code> package. </p>
+
+ <p>Secondly this happens when attempting to rely on a shared copy of
+ the Commons FileUpload jar file provided by your web container. The
+ solution is to include the FileUpload jar file as part of your own
+ web application, instead of relying on the container. The same may
+ hold for FileUpload's IO dependency. </p>
+ </answer>
+ </faq>
+
+ <faq id="whole-path-from-IE">
+ <question>
+ Why does FileItem.getName() return the whole path, and not just the file name?
+ </question>
+ <answer>
+ Internet Explorer provides the entire path to the uploaded file and not
+ just the base file name. Since FileUpload provides exactly what was
+ supplied by the client (browser), you may want to remove this path
+ information in your application. You can do that using the following
+ method from Commons IO (which you already have, since it is used by
+ FileUpload).
+ <pre>
+ String fileName = item.getName();
+ if (fileName != null) {
+ filename = FilenameUtils.getName(filename);
+ }
+ </pre>
+ </answer>
+ </faq>
+ </part>
+
+ <part id="struts">
+ <title>FileUpload and Struts</title>
+
+ <faq id="parse-in-action-fails">
+ <question>
+ I'm using FileUpload in an Action, but it's not working. Why?
+ </question>
+ <answer>
+ Struts recognises multipart requests, and parses them automatically,
+ presenting the request parameters to your code in the same manner as
+ if they were regular request parameters. Since Struts has already
+ processed the request, and made it available in your form bean, the
+ input stream is no longer available for parsing, so attempting to do
+ so with FileUpload will fail.
+ </answer>
+ </faq>
+
+ <faq id="howto-parse-in-action">
+ <question>
+ But I need to parse the request myself. How can I do that?
+ </question>
+ <answer>
+ Struts parses multipart a request as a part of the process of populating
+ your form bean from that request. If, for some reason, you need to have
+ full control over the multipart parsing, you can do so by configuring
+ your action mapping without an associated form bean. (A better way of
+ doing this, however, is to replace the default multipart handler with
+ your own. See the Struts documentation for details.)
+ </answer>
+ </faq>
+ </part>
+
+</faqs>
diff --git a/b_1_2_1/xdocs/images/jakarta-logo-blue.gif b/b_1_2_1/xdocs/images/jakarta-logo-blue.gif
new file mode 100644
index 0000000..de02eea
--- /dev/null
+++ b/b_1_2_1/xdocs/images/jakarta-logo-blue.gif
Binary files differ
diff --git a/b_1_2_1/xdocs/images/logo.gif b/b_1_2_1/xdocs/images/logo.gif
new file mode 100644
index 0000000..2e54ed6
--- /dev/null
+++ b/b_1_2_1/xdocs/images/logo.gif
Binary files differ
diff --git a/b_1_2_1/xdocs/images/logo.png b/b_1_2_1/xdocs/images/logo.png
new file mode 100644
index 0000000..df8e9e5
--- /dev/null
+++ b/b_1_2_1/xdocs/images/logo.png
Binary files differ
diff --git a/b_1_2_1/xdocs/index.xml b/b_1_2_1/xdocs/index.xml
new file mode 100644
index 0000000..452b084
--- /dev/null
+++ b/b_1_2_1/xdocs/index.xml
@@ -0,0 +1,132 @@
+<?xml version="1.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.
+-->
+
+<document>
+
+ <properties>
+ <title>Home</title>
+ <author email="martinc@apache.org">Martin Cooper</author>
+ </properties>
+
+ <body>
+
+ <section name="Commons FileUpload">
+ <p>
+ The Commons <strong>FileUpload</strong> package makes it easy to add
+ robust, high-performance, file upload capability to your servlets and
+ web applications.
+ </p>
+ <p>
+ FileUpload parses HTTP requests which conform to
+ <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>,
+ "Form-based File Upload in HTML". That is, if an HTTP request is
+ submitted using the POST method, and with a content type of
+ "multipart/form-data", then FileUpload can parse that request, and
+ make the results available in a manner easily used by the caller.
+ </p>
+ </section>
+
+ <section name="Documentation">
+ <p>
+ The following documentation is available:
+ <ul>
+ <li><a href="using.html">User Guide</a></li>
+ <li><a href="streaming.html">Streaming API</a></li>
+ <li><a href="faq.html">Frequently Asked Questions</a></li>
+ <li><a href="apidocs/index.html">JavaDoc API</a></li>
+ <li><a href="maven-reports.html">Project Reports</a></li>
+ </ul>
+ You can also <a href="cvs-usage.html">browse</a> the Subversion repository.
+ </p>
+ </section>
+
+ <section name="Downloading">
+ <subsection name='Full Releases'>
+ <p>
+ <strong>FileUpload 1.2.1</strong> - 01 January 2008
+ <ul>
+ <li>Download the binary and source distributions from a mirror site
+ <a href='http://commons.apache.org/downloads/download_fileupload.cgi'>here</a>
+ </li>
+ </ul>
+ </p>
+ <p>
+ <strong>FileUpload 1.2</strong> - 13 February 2007
+ <ul>
+ <li>Download the binary and source distributions from a mirror site
+ <a href='http://commons.apache.org/downloads/download_fileupload.cgi'>here</a>
+ </li>
+ </ul>
+ </p>
+ <p>
+ <strong>FileUpload 1.1.1</strong> - 08 June 2006
+ <ul>
+ <li>Download the binary and source distributions from a mirror site
+ <a href='http://commons.apache.org/downloads/download_fileupload.cgi'>here</a>
+ </li>
+ </ul>
+ </p>
+ <p>
+ <strong>FileUpload 1.1</strong> - 22 Dec 2005
+ <ul>
+ <li>Download the binary and source distributions from a mirror site
+ <a href='http://commons.apache.org/downloads/download_fileupload.cgi'>here</a>
+ </li>
+ </ul>
+ </p>
+ <p>
+ <strong>FileUpload 1.0</strong> - 24 Jun 2003
+ <ul>
+ <li>Download the binary and source distributions from a mirror site
+ <a href='http://commons.apache.org/downloads/download_fileupload.cgi'>here</a>
+ </li>
+ </ul>
+ </p>
+ </subsection>
+ <subsection name='Releases Candidates'>
+ <p>
+ None available.
+ </p>
+ </subsection>
+ <subsection name='Nightly Builds'>
+ <p>
+ Nightly builds are built every day from the current SVN HEAD. This is
+ the latest code and so should be treated with caution!
+ </p>
+ <p>
+ Download nightly builds from
+ <a href='http://people.apache.org/builds/commons/nightly/commons-fileupload/'>here</a>.
+ </p>
+ </subsection>
+ </section>
+
+ <section name="Support">
+ <p>
+ The <a href="mail-lists.html">Apache Commons mailing lists</a> act as
+ the main support forum. The <em>user</em> list is suitable for most library
+ usage queries. The <em>dev</em> list is intended for development discussion.
+ Please remember that the lists are shared between all commons components,
+ so prefix your e-mail subject line with <em>[fileupload]</em>.
+ </p>
+ <p>
+ Issues may be reported via <a href="issue-tracking.html">ASF JIRA</a>.
+ </p>
+ </section>
+ </body>
+
+</document>
diff --git a/b_1_2_1/xdocs/issue-tracking.xml b/b_1_2_1/xdocs/issue-tracking.xml
new file mode 100644
index 0000000..e3acb80
--- /dev/null
+++ b/b_1_2_1/xdocs/issue-tracking.xml
@@ -0,0 +1,67 @@
+<?xml version="1.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.
+-->
+<document>
+ <properties>
+ <title>Issue Tracking</title>
+ <author email="dev@commons.apache.org">Commons Documentation Team</author>
+ </properties>
+<body>
+<!-- ================================================== -->
+<section name="Issue Tracking">
+<p>
+ Commons FileUpload uses <a href="http://issues.apache.org/jira/browse/FILEUPLOAD">ASF JIRA</a> for tracking issues.
+</p>
+<p>
+ To use JIRA you may need to <a href="http://issues.apache.org/jira/secure/Signup!default.jspa">create an account</a>
+ (if you have previously created/updated Commons issues using Bugzilla an account will have been automatically
+ created and you can use the <a href="http://issues.apache.org/jira/secure/ForgotPassword!default.jspa">Forgot Password</a>
+ page to get a new password).
+</p>
+<p>
+ If you would like to report a bug, or raise an enhancement request against
+ Commons FileUpload please do the following:
+ <ol>
+ <li><a href="http://issues.apache.org/jira/secure/IssueNavigator.jspa?reset=true&pid=12310476&sorter/field=issuekey&sorter/order=DESC&status=1&status=4">Search existing open bugs</a>.
+ If you find your issue listed then please add a comment with your details.</li>
+ <li><a href="http://mail-archives.apache.org/mod_mbox/commons-dev/">Search the mailing list archive</a>.
+ You may find your issue or idea has already been discussed.</li>
+ <li>Decide if your issue is a bug or an enhancement.</li>
+ <li>Submit either a <a href="http://issues.apache.org/jira/secure/CreateIssueDetails!init.jspa?pid=12310476&issuetype=1&priority=4&assignee=-1">bug report</a>
+ or <a href="http://issues.apache.org/jira/secure/CreateIssueDetails!init.jspa?pid=12310476&issuetype=4&priority=4&assignee=-1">enhancement request</a>.</li>
+ </ol>
+</p>
+<p>
+ Please also remember these points:
+ <ul>
+ <li>The more information you provide, the better we can help you.</li>
+ <li>Test cases are vital, particularly for any proposed enhancements.</li>
+ <li>The developers of Commons FileUpload are all unpaid volunteers.</li>
+ </ul>
+</p>
+<p>
+ You may also find these links useful:
+ <ul>
+ <li><a href="http://issues.apache.org/jira/secure/IssueNavigator.jspa?reset=true&pid=12310476&sorter/field=issuekey&sorter/order=DESC&status=1&status=4">All Open FileUpload bugs</a></li>
+ <li><a href="http://issues.apache.org/jira/secure/IssueNavigator.jspa?reset=true&pid=12310476&sorter/field=issuekey&sorter/order=DESC&status=5&status=6">All Resolved FileUpload bugs</a></li>
+ <li><a href="http://issues.apache.org/jira/secure/IssueNavigator.jspa?reset=true&pid=12310476&sorter/field=issuekey&sorter/order=DESC">All FileUpload bugs</a></li>
+ </ul>
+</p>
+</section>
+<!-- ================================================== -->
+</body>
+</document>
diff --git a/b_1_2_1/xdocs/navigation.xml b/b_1_2_1/xdocs/navigation.xml
new file mode 100644
index 0000000..0db18a7
--- /dev/null
+++ b/b_1_2_1/xdocs/navigation.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ 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.
+-->
+<!DOCTYPE org.apache.commons.menus SYSTEM 'http://commons.apache.org/build/maven-build.dtd'>
+<project name="FileUpload">
+
+ <title>FileUpload</title>
+ <organizationLogo href="http://commons.apache.org/images/logo.png">
+ Commons
+ </organizationLogo>
+
+ <body>
+ <links>
+ <item name="Commons" href="http://commons.apache.org/"/>
+ </links>
+
+ <menu name="Commons FileUpload">
+ <item name="Overview" href="/index.html"/>
+ <item name="User guide" href="/using.html"/>
+ <item name="Streaming API" href="/streaming.html"/>
+ <!--item name="Customization" href="/customizing.html"/-->
+ <item name="FAQ" href="/faq.html"/>
+ <item name="Javadoc" href="apidocs/index.html"/>
+ <item name="Mailing lists" href="/mail-lists.html"/>
+ <item name="Team" href="/team-list.html"/>
+ <item name="Tasks" href="/tasks.html"/>
+ <item name="SVN repository" href="/cvs-usage.html"/>
+ </menu>
+
+ &commons;
+
+ </body>
+</project>
diff --git a/b_1_2_1/xdocs/overview.xml b/b_1_2_1/xdocs/overview.xml
new file mode 100644
index 0000000..6d04a5a
--- /dev/null
+++ b/b_1_2_1/xdocs/overview.xml
@@ -0,0 +1,64 @@
+<?xml version="1.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.
+-->
+
+<document>
+
+ <properties>
+ <title>Fileupload Overview</title>
+ <author email="rdonkin@apache.org">Robert Burrell Donkin</author>
+ </properties>
+
+<body>
+
+ <section name="Using FileUpload">
+ <p>
+ Your application should detect whether or not FileUpload should be
+ invoked, based on the HTTP method and the content type of the request.
+ </p>
+ <p>
+ Assuming that you have decided that FileUpload should be invoked, you
+ might write the following code to handle a file upload request:
+<pre>
+ // Create a new file upload handler
+ DiskFileUpload upload = new DiskFileUpload();
+
+ // Set upload parameters
+ upload.setSizeMax(MAX_UPLOAD_SIZE);
+ upload.setSizeThreshold(MAX_MEMORY_SIZE);
+ upload.setRepositoryPath(TEMP_DIR);
+
+ // Parse the request
+ List items = upload.parseRequest(request);
+
+ // Process the uploaded fields
+ Iterator iter = items.iterator();
+ while (iter.hasNext()) {
+ FileItem item = (FileItem) iter.next();
+
+ if (item.isFormField()) {
+ processTextParameter(request, item);
+ } else {
+ processFileParameter(request, item);
+ }
+ }
+</pre>
+ </p>
+ </section>
+
+</body>
+</document>
diff --git a/b_1_2_1/xdocs/streaming.xml b/b_1_2_1/xdocs/streaming.xml
new file mode 100644
index 0000000..2b80186
--- /dev/null
+++ b/b_1_2_1/xdocs/streaming.xml
@@ -0,0 +1,88 @@
+<?xml version="1.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.
+-->
+
+<document>
+
+ <properties>
+ <title>The Streaming API</title>
+ </properties>
+
+<body>
+
+ <section name="Why Streaming?">
+ <p>
+ The traditional API, which is described in the <a href="using.html">User
+ Guide</a>, assumes, that file items must be stored somewhere, before
+ they are actually accessable by the user. This approach is convenient,
+ because it allows easy access to an items contents. On the other hand,
+ it is memory and time consuming.
+ </p>
+ <p>
+ The streaming API allows you to trade a little bit of convenience for
+ optimal performance and and a low memory profile. Additionally, the
+ API is more lightweight, thus easier to understand.
+ </p>
+ </section>
+
+ <section name="How it works">
+ <p>
+ Again, the <code>FileUpload</code> class is used for accessing the
+ form fields and fields in the order, in which they have been sent
+ by the client. However, the <code>FileItemFactory</code> is completely
+ ignored.
+ </p>
+ </section>
+
+ <section name="Parsing the request">
+ <p>
+ First of all, do not forget to ensure, that a request actually is a
+ a file upload request. This is typically done using the same static
+ method, which you already know from the traditional API.
+ </p>
+<source><![CDATA[// Check that we have a file upload request
+boolean isMultipart = ServletFileUpload.isMultipartContent(request);]]></source>
+ <p>
+ Now we are ready to parse the request into its constituent items. Here's
+ how we do it:
+ </p>
+<source><![CDATA[
+// Create a new file upload handler
+ServletFileUpload upload = new ServletFileUpload();
+
+// Parse the request
+FileItemIterator iter = upload.getItemIterator(request);
+while (iter.hasNext()) {
+ FileItemStream item = iter.next();
+ String name = item.getFieldName();
+ InputStream stream = item.openStream();
+ if (item.isFormField()) {
+ System.out.println("Form field " + name + " with value "
+ + Streams.asString(stream) + " detected.");
+ } else {
+ System.out.println("File field " + name + " with file name "
+ + item.getName() + " detected.");
+ // Process the input stream
+ ...
+ }
+}]]></source>
+ <p>
+ That's all that's needed. Really!
+ </p>
+ </section>
+</body>
+</document>
diff --git a/b_1_2_1/xdocs/style/project.css b/b_1_2_1/xdocs/style/project.css
new file mode 100644
index 0000000..c1d541c
--- /dev/null
+++ b/b_1_2_1/xdocs/style/project.css
@@ -0,0 +1 @@
+@import url("http://commons.apache.org/style/commons-maven.css");
diff --git a/b_1_2_1/xdocs/tasks.xml b/b_1_2_1/xdocs/tasks.xml
new file mode 100644
index 0000000..e6dce09
--- /dev/null
+++ b/b_1_2_1/xdocs/tasks.xml
@@ -0,0 +1,137 @@
+<?xml version="1.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.
+-->
+
+<document>
+ <properties>
+ <title>TODO</title>
+ <author email="rdonkin@apache.org">Robert Burrell Donkin</author>
+ </properties>
+
+ <body>
+ <section name="TODO list">
+ <p>
+ The following is a list of items that need to be completed in
+ Fileupload. Contributions are welcome!
+ </p>
+
+ <subsection name="High priority">
+ </subsection>
+
+ <subsection name="Medium priority">
+ <ul>
+ <li>
+ <strong>Additional unit tests</strong> to increase code coverage.
+ </li>
+ <li>
+ <strong>Documentation</strong> for the customization capabilities.
+ </li>
+ </ul>
+ </subsection>
+
+ <subsection name="Low priority">
+ </subsection>
+
+ </section>
+
+ <section name='Completed'>
+ <subsection name="Since 1.0 Beta 1 Release">
+ <ul>
+ <li>
+ Split the <code>FileUpload</code> class into an abstract base class
+ and two concrete classes, one of which is specific to a disk-based
+ repository and the other a more generic implementation.
+ </li>
+ <li>
+ Replaced the ad hoc <code>newInstance()</code> means of creating
+ <code>FileItem</code> instances with a factory-based scheme for
+ much greater flexibility and simpler customization. This change
+ also eliminates a dependency on Commons BeanUtils.
+ </li>
+ <li>
+ Change the semantics of the size threshold to apply to the size of
+ individual items, instead of the size of the overall request. This
+ is in line with the original documentation, and better meets user
+ expectations.
+ </li>
+ <li>
+ Added unit tests for exceptional conditions, and to test new
+ functionality.
+ </li>
+ </ul>
+ </subsection>
+ </section>
+
+ <section name="Deprecated">
+ <subsection name="Since 1.0 Beta 1 Release">
+ <ul>
+ <li>
+ In the <code>FileItem</code> interface, the <code>setIsFormField()</code>
+ method has been replaced by the <code>setFormField()</code> method.
+ </li>
+ <li>
+ In the <code>FileItem</code> interface, the <code>write(String)</code>
+ method has been replaced by the <code>write(File)</code> method.
+ </li>
+ <li>
+ The <code>sizeThreshold</code> property of the <code>FileUpload</code>
+ class has been moved to the <code>DiskFileUpload</code> class.
+ </li>
+ <li>
+ The <code>repositoryPath</code> property of the <code>FileUpload</code>
+ class has been moved to the <code>DiskFileUpload</code> class.
+ </li>
+ <li>
+ The disk-specific <code>parseRequest()</code> method of the
+ <code>FileUpload</code> class has been moved to the
+ <code>DiskFileUpload</code> class.
+ </li>
+ </ul>
+ </subsection>
+ </section>
+
+ <section name="Backwards Incompatible Changes">
+ <subsection name="Since 1.0 Beta 1">
+ <ul>
+ <li>
+ <code>FileItem.newInstance()</code> has been replaced by the use of
+ factories to create new <code>FileItem</code> instances.
+ </li>
+ <li>
+ The <code>storeLocation</code> property of the <code>FileItem</code>
+ interface has been removed, since it is (disk-based) implementation
+ specific.
+ </li>
+ </ul>
+ </subsection>
+ </section>
+
+ <section name="Semantic Changes">
+ <subsection name="Since 1.0 Beta 1">
+ <ul>
+ <li>
+ The <code>sizeThreshold</code> property now applies to the size of
+ each item, rather than the size of the request as a whole. This is
+ more in keeping which user expectations, as well as matching the
+ original documentation.
+ </li>
+ </ul>
+ </subsection>
+ </section>
+ </body>
+</document>
+
diff --git a/b_1_2_1/xdocs/using.xml b/b_1_2_1/xdocs/using.xml
new file mode 100644
index 0000000..7dbee66
--- /dev/null
+++ b/b_1_2_1/xdocs/using.xml
@@ -0,0 +1,442 @@
+<?xml version="1.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.
+-->
+
+<document>
+
+ <properties>
+ <title>Using FileUpload</title>
+ <author email="martinc@apache.org">Martin Cooper</author>
+ </properties>
+
+<body>
+
+ <section name="Using FileUpload">
+ <p>
+ FileUpload can be used in a number of different ways, depending upon the
+ requirements of your application. In the simplest case, you will call a
+ single method to parse the servlet request, and then process the list of
+ items as they apply to your application. At the other end of the scale,
+ you might decide to customize FileUpload to take full control of the way
+ in which individual items are stored; for example, you might decide to
+ stream the content into a database.
+ </p>
+ <p>
+ Here, we will describe the basic principles of FileUpload, and illustrate
+ some of the simpler - and most common - usage patterns. Customization of
+ FileUpload is described <a href="customizing.html">elsewhere</a>.
+ </p>
+ <p>
+ FileUpload depends on Commons IO, so make sure you have the version
+ mentioned on the <a href="dependencies.html">dependencies page</a> in
+ your classpath before continuing.
+ </p>
+ </section>
+
+ <section name="How it works">
+ <p>
+ A file upload request comprises an ordered list of <em>items</em> that
+ are encoded according to
+ <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>,
+ "Form-based File Upload in HTML". FileUpload can parse such a request
+ and provide your application with a list of the individual uploaded
+ items. Each such item implements the <code>FileItem</code> interface,
+ regardless of its underlying implementation.
+ </p>
+ <p>
+ This page describes the traditional API of the commons fileupload
+ library. The traditional API is a convenient approach. However, for
+ ultimate performance, you might prefer the faster
+ <a href="streaming.html">Streaming API</a>.
+ </p>
+ <p>
+ Each file item has a number of properties that might be of interest for
+ your application. For example, every item has a name and a content type,
+ and can provide an <code>InputStream</code> to access its data. On the
+ other hand, you may need to process items differently, depending upon
+ whether the item is a regular form field - that is, the data came from
+ an ordinary text box or similar HTML field - or an uploaded file. The
+ <code>FileItem</code> interface provides the methods to make such a
+ determination, and to access the data in the most appropriate manner.
+ </p>
+ <p>
+ FileUpload creates new file items using a <code>FileItemFactory</code>.
+ This is what gives FileUpload most of its flexibility. The factory has
+ ultimate control over how each item is created. The factory implementation
+ that currently ships with FileUpload stores the item's data in memory or
+ on disk, depending on the size of the item (i.e. bytes of data). However,
+ this behavior can be customized to suit your application.
+ </p>
+ </section>
+
+ <section name="Servlets and Portlets">
+ <p>
+ Starting with version 1.1, FileUpload supports file upload requests in
+ both servlet and portlet environments. The usage is almost identical in
+ the two environments, so the remainder of this document refers only to
+ the servlet environment.
+ </p>
+ <p>
+ If you are building a portlet application, the following are the two
+ distinctions you should make as you read this document:
+ <ul>
+ <li>
+ Where you see references to the <code>ServletFileUpload</code> class,
+ substitute the <code>PortletFileUpload</code> class.
+ </li>
+ <li>
+ Where you see references to the <code>HttpServletRequest</code> class,
+ substitute the <code>ActionRequest</code> class.
+ </li>
+ </ul>
+ </p>
+ </section>
+
+ <section name="Parsing the request">
+ <p>
+ Before you can work with the uploaded items, of course, you need to parse
+ the request itself. Ensuring that the request is actually a file upload
+ request is straightforward, but FileUpload makes it simplicity itself, by
+ providing a static method to do just that.
+ </p>
+<source><![CDATA[// Check that we have a file upload request
+boolean isMultipart = ServletFileUpload.isMultipartContent(request);]]></source>
+ <p>
+ Now we are ready to parse the request into its constituent items.
+ </p>
+ <subsection name="The simplest case">
+ <p>
+ The simplest usage scenario is the following:
+ <ul>
+ <li>
+ Uploaded items should be retained in memory as long as they are
+ reasonably small.
+ </li>
+ <li>
+ Larger items should be written to a temporary file on disk.
+ </li>
+ <li>
+ Very large upload requests should not be permitted.
+ </li>
+ <li>
+ The built-in defaults for the maximum size of an item to
+ be retained in memory, the maximum permitted size of an upload
+ request, and the location of temporary files are acceptable.
+ </li>
+ </ul>
+ </p>
+ <p>
+ Handling a request in this scenario couldn't be much simpler:
+ </p>
+<source><![CDATA[// Create a factory for disk-based file items
+FileItemFactory factory = new DiskFileItemFactory();
+
+// Create a new file upload handler
+ServletFileUpload upload = new ServletFileUpload(factory);
+
+// Parse the request
+List /* FileItem */ items = upload.parseRequest(request);]]></source>
+ <p>
+ That's all that's needed. Really!
+ </p>
+ <p>
+ The result of the parse is a <code>List</code> of file items, each of
+ which implements the <code>FileItem</code> interface. Processing these
+ items is discussed below.
+ </p>
+ </subsection>
+
+ <subsection name="Exercising more control">
+ <p>
+ If your usage scenario is close to the simplest case, described above,
+ but you need a little more control, you can easily customize the
+ behavior of the upload handler or the file item factory or both. The
+ following example shows several configuration options:
+ </p>
+<source><![CDATA[// Create a factory for disk-based file items
+DiskFileItemFactory factory = new DiskFileItemFactory();
+
+// Set factory constraints
+factory.setSizeThreshold(yourMaxMemorySize);
+factory.setRepository(yourTempDirectory);
+
+// Create a new file upload handler
+ServletFileUpload upload = new ServletFileUpload(factory);
+
+// Set overall request size constraint
+upload.setSizeMax(yourMaxRequestSize);
+
+// Parse the request
+List /* FileItem */ items = upload.parseRequest(request);]]></source>
+ <p>
+ Of course, each of the configuration methods is independent of the
+ others, but if you want to configure the factory all at once, you can
+ do that with an alternative constructor, like this:
+ </p>
+<source><![CDATA[// Create a factory for disk-based file items
+DiskFileItemFactory factory = new DiskFileItemFactory(
+ yourMaxMemorySize, yourTempDirectory);]]></source>
+ <p>
+ Should you need further control over the parsing of the request, such
+ as storing the items elsewhere - for example, in a database - you will
+ need to look into <a href="customizing.html">customizing</a> FileUpload.
+ </p>
+ </subsection>
+ </section>
+
+ <section name="Processing the uploaded items">
+ <p>
+ Once the parse has completed, you will have a <code>List</code> of file
+ items that you need to process. In most cases, you will want to handle
+ file uploads differently from regular form fields, so you might process
+ the list like this:
+ </p>
+<source><![CDATA[// Process the uploaded items
+Iterator iter = items.iterator();
+while (iter.hasNext()) {
+ FileItem item = (FileItem) iter.next();
+
+ if (item.isFormField()) {
+ processFormField(item);
+ } else {
+ processUploadedFile(item);
+ }
+}]]></source>
+ <p>
+ For a regular form field, you will most likely be interested only in the
+ name of the item, and its <code>String</code> value. As you might expect,
+ accessing these is very simple.
+ </p>
+<source><![CDATA[// Process a regular form field
+if (item.isFormField()) {
+ String name = item.getFieldName();
+ String value = item.getString();
+ ...
+}]]></source>
+ <p>
+ For a file upload, there are several different things you might want to
+ know before you process the content. Here is an example of some of the
+ methods you might be interested in.
+ </p>
+<source><![CDATA[// Process a file upload
+if (!item.isFormField()) {
+ String fieldName = item.getFieldName();
+ String fileName = item.getName();
+ String contentType = item.getContentType();
+ boolean isInMemory = item.isInMemory();
+ long sizeInBytes = item.getSize();
+ ...
+}]]></source>
+ <p>
+ With uploaded files, you generally will not want to access them via
+ memory, unless they are small, or unless you have no other alternative.
+ Rather, you will want to process the content as a stream, or write the
+ entire file to its ultimate location. FileUpload provides simple means of
+ accomplishing both of these.
+ </p>
+<source><![CDATA[// Process a file upload
+if (writeToFile) {
+ File uploadedFile = new File(...);
+ item.write(uploadedFile);
+} else {
+ InputStream uploadedStream = item.getInputStream();
+ ...
+ uploadedStream.close();
+}]]></source>
+ <p>
+ Note that, in the default implementation of FileUpload, <code>write()</code>
+ will attempt to rename the file to the specified destination, if the data
+ is already in a temporary file. Actually copying the data is only done if
+ the the rename fails, for some reason, or if the data was in memory.
+ </p>
+ <p>
+ If you do need to access the uploaded data in memory, you need simply
+ call the <code>get()</code> method to obtain the data as an array of
+ bytes.
+ </p>
+<source><![CDATA[// Process a file upload in memory
+byte[] data = item.get();
+...]]></source>
+ </section>
+
+ <section name="Resource cleanup">
+ <p>
+ This section applies only, if you are using the
+ <a href="apidocs/org/apache/commons/fileupload/disk/DiskFileItem.html">DiskFileItem</a>.
+ In other words, it applies, if your uploaded files are written to
+ temporary files before processing them.
+ </p>
+ <p>
+ Such temporary files are deleted automatically, if they are no longer
+ used (more precisely, if the corresponding instance of <code>java.io.File</code>
+ is garbage collected. This is done silently by the <code>org.apache.commons.io.FileCleaner</code>
+ class, which starts a reaper thread.
+ </p>
+ <p>
+ This reaper thread should be stopped, if it is no longer needed. In
+ a servlet environment, this is done by using a special servlet
+ context listener, called
+ <a href="apidocs/org/apache/commons/fileupload/servlet/FileCleanerCleanup.html">FileCleanerCleanup</a>.
+ To do so, add a section like the following to your <code>web.xml</code>:
+ </p>
+<source><![CDATA[
+<web-app>
+ ...
+ <listener>
+ <listener-class>
+ org.apache.commons.fileupload.servlet.FileCleanerCleanup
+ </listener-class>
+ </listener>
+ ...
+</web-app>
+]]></source>
+
+ <subsection name="Creating a DiskFileItemFactory">
+ <p>
+ The FileCleanerCleanup provides an instance of
+ <code>org.apache.commons.io.FileCleaningTracker</code>. This
+ instance must be used when creating a
+ <code>org.apache.commons.fileupload.disk.DiskFileItemFactory</code>.
+ This should be done by calling a method like the following:
+ </p>
+<source><![CDATA[
+ public static DiskFileItemFactory newDiskFileItemFactory(ServletContext context,
+ File repository) {
+ FileCleaningTracker fileCleaningTracker
+ = FileCleanerCleanup.getFileCleaningTracker(context);
+ return new DiskFileItemFactory(fileCleaningTracker,
+ DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD,
+ repository);
+ }
+]]></source>
+ </subsection>
+
+ <subsection name="Disabling cleanup of temporary files">
+ <p>
+ To disable tracking of temporary files, you may set the
+ <code>FileCleaningTracker</code> to null. Consequently,
+ created files will no longer be tracked. In particular,
+ they will no longer be deleted automatically.</p>
+ </subsection>
+ </section>
+
+ <section name="Interaction with virus scanners">
+ <p>
+ Virus scanners running on the same system as the web container can cause
+ some unexpected behaviours for applications using FileUpload. This section
+ describes some of the behaviours that you might encounter, and provides
+ some ideas for how to handle them.
+ </p>
+ <p>
+ The default implementation of FileUpload will cause uploaded items above
+ a certain size threshold to be written to disk. As soon as such a file is
+ closed, any virus scanner on the system will wake up and inspect it, and
+ potentially quarantine the file - that is, move it to a special location
+ where it will not cause problems. This, of course, will be a surprise to
+ the application developer, since the uploaded file item will no longer be
+ available for processing. On the other hand, uploaded items below that
+ same threshold will be held in memory, and therefore will not be seen by
+ virus scanners. This allows for the possibility of a virus being retained
+ in some form (although if it is ever written to disk, the virus scanner
+ would locate and inspect it).
+ </p>
+ <p>
+ One commonly used solution is to set aside one directory on the system
+ into which all uploaded files will be placed, and to configure the virus
+ scanner to ignore that directory. This ensures that files will not be
+ ripped out from under the application, but then leaves responsibility for
+ virus scanning up to the application developer. Scanning the uploaded
+ files for viruses can then be performed by an external process, which
+ might move clean or cleaned files to an "approved" location, or by
+ integrating a virus scanner within the application itself. The details of
+ configuring an external process or integrating virus scanning into an
+ application are outside the scope of this document.
+ </p>
+ </section>
+
+ <section name="Watching progress">
+ <p>
+ If you expect really large file uploads, then it would be nice to report
+ to your users, how much is already received. Even HTML pages allow to
+ implement a progress bar by returning a multipart/replace response,
+ or something like that.
+ </p>
+ <p>
+ Watching the upload progress may be done by supplying a progress listener:
+ </p>
+<source><![CDATA[//Create a progress listener
+ProgressListener progressListener = new ProgressListener(){
+ public void update(long pBytesRead, long pContentLength, int pItems) {
+ System.out.println("We are currently reading item " + pItems);
+ if (pContentLength == -1) {
+ System.out.println("So far, " + pBytesRead + " bytes have been read.");
+ } else {
+ System.out.println("So far, " + pBytesRead + " of " + pContentLength
+ + " bytes have been read.");
+ }
+ }
+};
+upload.setProgressListener(progressListener);
+]]></source>
+ <p>
+ Do yourself a favour and implement your first progress listener just
+ like the above, because it shows you a pitfall: The progress listener
+ is called quite frequently. Depending on the servlet engine and other
+ environment factory, it may be called for any network packet! In
+ other words, your progress listener may become a performance problem!
+ A typical solution might be, to reduce the progress listeners activity.
+ For example, you might emit a message only, if the number of megabytes
+ has changed:
+ </p>
+<source><![CDATA[//Create a progress listener
+ProgressListener progressListener = new ProgressListener(){
+ private long megaBytes = -1;
+ public void update(long pBytesRead, long pContentLength, int pItems) {
+ long mBytes = pBytesRead / 1000000;
+ if (megaBytes == mBytes) {
+ return;
+ }
+ megaBytes = mBytes;
+ System.out.println("We are currently reading item " + pItems);
+ if (pContentLength == -1) {
+ System.out.println("So far, " + pBytesRead + " bytes have been read.");
+ } else {
+ System.out.println("So far, " + pBytesRead + " of " + pContentLength
+ + " bytes have been read.");
+ }
+ }
+};
+]]></source>
+ </section>
+
+ <section name="What's next">
+ <p>
+ Hopefully this page has provided you with a good idea of how to use
+ FileUpload in your own applications. For more detail on the methods
+ introduced here, as well as other available methods, you should refer
+ to the <a href="apidocs/index.html">JavaDocs</a>.
+ </p>
+ <p>
+ The usage described here should satisfy a large majority of file upload
+ needs. However, should you have more complex requirements, FileUpload
+ should still be able to help you, with it's flexible
+ <a href="customizing.html">customization</a> capabilities.
+ </p>
+ </section>
+
+</body>
+</document>