[libcommons-cli-java] 14/31: Imported Upstream version 1.2

Tony Mancill tmancill at moszumanska.debian.org
Mon Jun 22 05:52:46 UTC 2015


This is an automated email from the git hooks/post-receive script.

tmancill pushed a commit to branch master
in repository libcommons-cli-java.

commit 1cf38acee280f4bdaa3c9c1a9384bfd0aab975eb
Author: tony mancill <tmancill at debian.org>
Date:   Mon Jun 22 04:36:20 2015 +0000

    Imported Upstream version 1.2
---
 NOTICE.txt                                         |   2 +-
 README.txt                                         |  31 +-
 RELEASE-NOTES.txt                                  | 104 ++--
 build.xml                                          | 166 -------
 maven.xml                                          |  47 --
 pom.xml                                            | 250 ++++++++++
 project.properties                                 |  38 --
 project.xml                                        | 202 --------
 src/assembly/bin.xml                               |  44 ++
 src/assembly/src.xml                               |  45 ++
 .../commons/cli/UtilTest.java => conf/HEADER.txt}  |  14 -
 src/conf/MANIFEST.MF                               |  25 +-
 src/conf/checkstyle.xml                            | 189 +++++++
 .../commons/cli/AlreadySelectedException.java      |  64 ++-
 src/java/org/apache/commons/cli/BasicParser.java   |  14 +-
 src/java/org/apache/commons/cli/CommandLine.java   | 121 ++++-
 .../org/apache/commons/cli/CommandLineParser.java  |  37 +-
 src/java/org/apache/commons/cli/GnuParser.java     | 143 ++----
 src/java/org/apache/commons/cli/HelpFormatter.java | 255 +++++-----
 .../commons/cli/MissingArgumentException.java      |  48 +-
 .../apache/commons/cli/MissingOptionException.java |  73 ++-
 src/java/org/apache/commons/cli/Option.java        | 171 ++++---
 src/java/org/apache/commons/cli/OptionBuilder.java |  82 ++-
 src/java/org/apache/commons/cli/OptionGroup.java   |  47 +-
 .../org/apache/commons/cli/OptionValidator.java    |  34 +-
 src/java/org/apache/commons/cli/Options.java       |  89 ++--
 .../org/apache/commons/cli/ParseException.java     |  19 +-
 src/java/org/apache/commons/cli/Parser.java        | 196 ++++----
 .../apache/commons/cli/PatternOptionBuilder.java   | 136 +++--
 src/java/org/apache/commons/cli/PosixParser.java   | 153 +++---
 src/java/org/apache/commons/cli/TypeHandler.java   | 118 ++---
 .../commons/cli/UnrecognizedOptionException.java   |  48 +-
 src/java/org/apache/commons/cli/Util.java          |  23 +-
 src/java/org/apache/commons/cli/overview.html      |  65 ++-
 src/java/org/apache/commons/cli/package.html       |  17 +-
 src/test/data/.hidden.txt                          |   1 -
 src/test/data/readable.txt                         |   1 -
 src/test/data/writable.txt                         |   1 -
 .../org/apache/commons/cli/ApplicationTest.java    | 190 +++++--
 .../apache/commons/cli/ArgumentIsOptionTest.java   |  89 ++--
 .../org/apache/commons/cli/BasicParserTest.java}   |  51 +-
 src/test/org/apache/commons/cli/BugsTest.java      | 441 ++++++-----------
 src/test/org/apache/commons/cli/BuildTest.java     | 102 ----
 .../org/apache/commons/cli/CommandLineTest.java    |  51 ++
 src/test/org/apache/commons/cli/GnuParseTest.java  | 270 ----------
 .../cli/{UtilTest.java => GnuParserTest.java}      |  17 +-
 .../apache/commons/cli/HelpFormatterExamples.java  | 113 -----
 .../org/apache/commons/cli/HelpFormatterTest.java  | 551 +++++++++++++++------
 .../apache/commons/cli/LongOptionWithShort.java    | 114 -----
 .../org/apache/commons/cli/OptionBuilderTest.java  |  88 ++--
 .../org/apache/commons/cli/OptionGroupTest.java    | 271 ++++------
 src/test/org/apache/commons/cli/OptionTest.java    | 222 ++++++---
 src/test/org/apache/commons/cli/OptionsTest.java   | 129 +++--
 .../org/apache/commons/cli/ParseRequiredTest.java  |  99 ++--
 src/test/org/apache/commons/cli/ParseTest.java     | 291 -----------
 .../org/apache/commons/cli/ParserTestCase.java     | 306 ++++++++++++
 .../commons/cli/PatternOptionBuilderTest.java      | 198 ++++++--
 .../org/apache/commons/cli/PosixParserTest.java    | 188 +++++++
 src/test/org/apache/commons/cli/UtilTest.java      |  13 +-
 src/test/org/apache/commons/cli/ValueTest.java     | 407 +++++----------
 src/test/org/apache/commons/cli/ValuesTest.java    | 127 ++---
 .../org/apache/commons/cli/bug/BugCLI133Test.java  |   8 +-
 .../org/apache/commons/cli/bug/BugCLI13Test.java   |  10 +-
 .../bug/{BugCLI51Test.java => BugCLI148Test.java}  |  45 +-
 .../org/apache/commons/cli/bug/BugCLI162Test.java  | 285 +++++++++++
 .../org/apache/commons/cli/bug/BugCLI18Test.java   |  35 +-
 .../org/apache/commons/cli/bug/BugCLI71Test.java   |  15 +-
 67 files changed, 4070 insertions(+), 3769 deletions(-)

diff --git a/NOTICE.txt b/NOTICE.txt
index b7535ae..72eb32a 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,5 +1,5 @@
 Apache Commons CLI
-Copyright 2001-2007 The Apache Software Foundation
+Copyright 2001-2009 The Apache Software Foundation
 
 This product includes software developed by
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.txt b/README.txt
index 1b2aa23..46f5e9e 100644
--- a/README.txt
+++ b/README.txt
@@ -1,41 +1,26 @@
-Jakarta Commons CLI
+Apache Commons CLI
 ===================
 
-Welcome to the CLI component of the Jakarta Commons project.
+Welcome to the CLI 1.x component of the Apache Commons project.
 
 The information in this file is relevant if you have
 downloaded a CLI source distribution.
 
-For testing the project, you will need JUnit (if you use
-maven this will be automatically installed and configured
-for you):
-
-  http://www.junit.org/
-
-There are two ways to build CLI, either with Ant or Maven 1.
-
-Ant can be found here :
-
-  http://jakarta.apache.org/ant
-
-and to build and test the system use:
-
-  ant dist
-
-Maven 1 can be found here :
+CLI is built with Maven 2, which can be found here:
 
   http://maven.apache.org
 
 and to build and test the system use:
 
-  maven clean jar
+  mvn clean package
 
 The system will build and test itself.
 
-For complete documentation type:
+For complete documentation and to create a local copy of the
+CLI project website, type:
 
-  maven site
+  mvn site
 
 Good luck!
 
--The CLI Team
+- The Apache Commons Team
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 1f20417..fe5dca0 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -1,61 +1,73 @@
-$Id: RELEASE-NOTES.txt 553359 2007-07-05 01:35:30Z bayard $
+$Id: RELEASE-NOTES.txt 695235 2008-09-14 15:26:10Z ebourg $
 
-			Commons CLI Package
-			   Version 1.1
-			    Release Notes
+            Commons CLI Package
+                Version 1.2
+               Release Notes
 
 
 INTRODUCTION:
 
-This document contains the release notes for this version of the Commons CLI package. Commons CLI provides a simple API for working with the command line arguments and options.
+This document contains the release notes for this version of the Commons CLI
+package. Commons CLI provides a simple API for working with the command line
+arguments and options.
 
-CLI 1.1 is a bugfix release of CLI. The following changes notable API changes were made: 
+Commons CLI 1.2 is a bugfix release. The following notable changes were made:
 
- * The Parser abstract class has two additional parse methods that take a Properties parameter. 
- * The HelpFormatter class had publicly accessible fields. These should now be accessed via get/set methods and the public fields are deprecated. 
- * The Option class addValue(String) method now throws UnsupportedOperationException. 
- * OptionValidator is a newly added class. 
- * Option's now have equals(Object) and hashCode() methods. 
- * The Option class also received two new methods, setDescription(String) and hasValueSeparator();boolean. 
+ * A major regression introduced in CLI 1.1 that prevented the usage of repeated options has been fixed.
+ * Several parser issues have been fixed, especially with the PosixParser.
+ * HelpFormatter now wraps the lines properly
+ * The ordering of the option in the help message can now be defined.
+ * Various API enhancements (improved exceptions, serializable classes)
 
-The jar should be API backwards compatible, though if you were calling addValue(String) then you won't be happy. Please let us know your use case if that is so. 
+Commons CLI 1.2 is binary compatible with the previous versions, except for
+the OptionValidator class that is no longer public.
+
+More information can be found on the project site at http://commons.apache.org/cli
 
-For more information, read the documentation on the project site at http://jakarta.apache.org/commons/cli/
 
 NEW FEATURES:
 
-  CLI-78 - Setting description of a Option. 
+  * The method getOptionProperties() in the CommandLine class was added
+    to retrieve easily the key/value pairs specified with options like
+    -Dkey1=value1 -Dkey2=value2.
+
+  * GnuParser now supports long options with an '=' sign
+    (ie. --foo=bar and -foo=bar) (CLI-157)
+
+  * The ordering of options can be defined in help messages. (CLI-155)
+
 
 BUG FIXES:
 
-DEPRECATIONS:
-
-CHANGES: 
-
-  CLI-2   - Wrong usage summary. 
-  CLI-5   - Dependecy on commons-lang-2.0 but commons-lang-1.0 is obtained. 
-  CLI-8   - Line separator as first char for helpformatter (footer) throws exception. 
-  CLI-13  - CommandLine.getOptionValue() behaves contrary to docs. 
-  CLI-21  - clone method in Option should use super.clone(). 
-  CLI-23  - Passing properties in Parser does not work for options with a single argument. 
-  CLI-26  - Only long options without short option seems to be noticed. 
-  CLI-28  - Infinite Loop in Command-Line processing. 
-  CLI-29  - Options should not be able to be added more than once. 
-  CLI-35  - HelpFormatter doesn't sort options properly. 
-  CLI-38  - HelpFormatter doesn't function correctly for options with only LongOpt. 
-  CLI-44  - Document enhancement. 
-  CLI-45  - Documentation errors. 
-  CLI-51  - Parameter value "-something" misinterpreted as a parameter. 
-  CLI-56  - clone() method doesn't fully clone contents. 
-  CLI-59  - No Javadoc for HelpFormatter!. 
-  CLI-65  - Parser breaks up command line parms into single characters. 
-  CLI-67  - Missing arguments in HelpFormatter.renderOptions(..). 
-  CLI-69  - Error parsing option arguments. 
-  CLI-71  - A weakness of parser. 
-  CLI-129 - CLI_1_BRANCH build.xml doesn't work. 
-  CLI-130 - Remove the Commons Lang dependency. 
-  CLI-131 - Options class returns options in random order. 
-  CLI-132 - MissingOptionException should contain a useful error message. 
-  CLI-133 - NullPointerException in Util.stripLeadingHyphens when passed a null argument. 
-  CLI-134 - 1.1 is not backwards compatible because it adds methods to the CommandLineParser interface. 
-  CLI-135 - Backwards compatibility between 1.1 and 1.0 broken due to Option.addValue removal. 
+  * The number of arguments defined for an option specifies the arguments
+    per occurrence of the option and not for all occurrences. (CLI-137)
+
+  * PosixParser no longer ignores unrecognized short options. (CLI-164)
+
+  * PosixParser no longer stops the bursting process of a token if stopAtNonOption
+    is enabled and a non option character is encountered. (CLI-163)
+
+  * PosixParser no longer keeps processing the tokens after an unrecognized
+    long option when stopAtNonOption is enabled. (CLI-165)
+
+  * Required options are properly checked if an Options instance is used twice
+    to parse a command line. (CLI-156)
+
+  * The line wrapping in HelpFormatter now works properly. (CLI-151)
+
+
+CHANGES:
+
+  * The message of MissingOptionException has been improved. (CLI-149)
+
+  * The exceptions have been enhanced with methods to retrieve easily
+    the related options. (CLI-86)
+
+  * Option.toString() now reports arguments properly. (CLI-141)
+
+  * The Parser class has been changed to be more easily extendable. (CLI-142)
+
+  * The following classes are now serializable: Option, OptionGroup,
+    CommandLine and Options. (CLI-140)
+
+  * OptionValidator is no longer public, its methods were all private.
diff --git a/build.xml b/build.xml
deleted file mode 100644
index 6cdbf03..0000000
--- a/build.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--build.xml generated by maven from project.xml version 1.1
-  on date July 4 2007, time 1948-->
-
-<project default="jar" name="commons-cli" basedir=".">
-  <property name="defaulttargetdir" value="target">
-  </property>
-  <property name="libdir" value="target/lib">
-  </property>
-  <property name="classesdir" value="target/classes">
-  </property>
-  <property name="testclassesdir" value="target/test-classes">
-  </property>
-  <property name="testclassesdir" value="target/test-classes">
-  </property>
-  <property name="testreportdir" value="target/test-reports">
-  </property>
-  <property name="distdir" value="dist">
-  </property>
-  <property name="javadocdir" value="dist/docs/api">
-  </property>
-  <property name="final.name" value="commons-cli-1.1">
-  </property>
-  <path id="build.classpath">
-    <fileset dir="${libdir}">
-      <include name="**/*.jar">
-      </include>
-    </fileset>
-  </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>
-  </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="src/java">
-        </pathelement>
-      </src>
-      <classpath refid="build.classpath">
-      </classpath>
-    </javac>
-    <mkdir dir="${classesdir}/META-INF">
-    </mkdir>
-    <copy todir="${classesdir}/META-INF">
-      <fileset dir=".">
-        <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="./" 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="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="src/test">
-        </pathelement>
-      </src>
-      <classpath>
-        <path refid="build.classpath">
-        </path>
-        <pathelement path="${classesdir}">
-        </pathelement>
-      </classpath>
-    </javac>
-  </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; 2002-2007 Apache Software Foundation. All Rights Reserved.">
-    </property>
-    <property name="title" value="CLI 1.1 API">
-    </property>
-    <javadoc use="true" private="true" destdir="${javadocdir}" author="true" version="true" sourcepath="src/java" packagenames="org.apache.commons.*">
-      <classpath>
-        <path refid="build.classpath">
-        </path>
-      </classpath>
-    </javadoc>
-  </target>
-  <target name="get-deps" unless="noget" depends="init">
-    <!--Proxy settings works only with a JDK 1.2 and higher.-->
-
-    <setproxy>
-    </setproxy>
-    <get dest="${libdir}/junit-3.8.1.jar" usetimestamp="true" ignoreerrors="true" src="http://repo1.maven.org/maven/junit/jars/junit-3.8.1.jar">
-    </get>
-  </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/maven.xml b/maven.xml
deleted file mode 100644
index 953c587..0000000
--- a/maven.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<project default="jar:jar"
-  xmlns:j="jelly:core">
-
-  <!-- Ensures that the release notes and NOTICE.txt are included in the
-       source distro.
-   -->
-  <postGoal name="dist:prepare-src-filesystem">
-    <j:set var="maven.dist.src.assembly.dir" value="${pom.getPluginContext('maven-dist-plugin').getVariable('maven.dist.src.assembly.dir')}" />
-    <copy todir="${maven.dist.src.assembly.dir}">
-      <fileset file="${basedir}/NOTICE.txt"/>
-      <fileset file="${basedir}/RELEASE-NOTES.txt"/>
-    </copy>
-  </postGoal>
-
-  <!-- Ensures that release notes NOTICE.txt is added to the binary distro -->
-  <preGoal name="dist:build-bin">
-    <copy todir="${maven.dist.bin.assembly.dir}">
-      <fileset file="${basedir}/NOTICE.txt"/>
-      <fileset file="${basedir}/RELEASE-NOTES.txt"/>
-    </copy>
-  </preGoal>
-
- <preGoal name="dist:prepare-bin-filesystem">
-   <attainGoal name="ant:generate-build"/>
- </preGoal>
-
- <preGoal name="dist:prepare-src-filesystem">
-   <attainGoal name="ant:generate-build"/>
- </preGoal>
-
-</project>
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..21e6d30
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.commons</groupId>
+    <artifactId>commons-parent</artifactId>
+    <version>11</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>commons-cli</groupId>
+  <artifactId>commons-cli</artifactId>
+  <version>1.2</version>
+  <name>Commons CLI</name>
+
+  <inceptionYear>2002</inceptionYear>
+  <description>
+    Commons CLI provides a simple API for presenting, processing and validating a command line interface.
+  </description>
+
+  <url>http://commons.apache.org/cli/</url>
+
+  <issueManagement>
+    <system>jira</system>
+    <url>http://issues.apache.org/jira/browse/CLI</url>
+  </issueManagement>
+
+  <scm>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/cli/branches/cli-1.x/</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/cli/branches/cli-1.x/</developerConnection>
+    <url>http://svn.apache.org/viewvc/commons/proper/cli/branches/cli-1.x/</url>
+  </scm>
+
+  <developers>
+    <developer>
+      <name>James Strachan</name>
+      <id>jstrachan</id>
+      <email>jstrachan at apache.org</email>
+      <organization>SpiritSoft, Inc.</organization>
+    </developer>
+    <developer>
+      <name>Bob McWhirter</name>
+      <id>bob</id>
+      <email>bob at werken.com</email>
+      <organization>Werken</organization>
+      <roles>
+        <role>contributed ideas and code from werken.opt</role>
+      </roles>
+    </developer>
+    <developer>
+      <name>John Keyes</name>
+      <id>jkeyes</id>
+      <email>jbjk at mac.com</email>
+      <organization>integral Source</organization>
+      <roles>
+        <role>contributed ideas and code from Optz</role>
+      </roles>
+    </developer>
+    <developer>
+      <name>Rob Oxspring</name>
+      <id>roxspring</id>
+      <email>roxspring at imapmail.org</email>
+      <organization>Indigo Stone</organization>
+      <roles>
+        <role>designed CLI2</role>
+      </roles>
+    </developer>
+  </developers>
+
+  <contributors>
+    <contributor>
+      <name>Peter Donald</name>
+      <roles>
+        <role>contributed ideas and code from Avalon Excalibur's cli package</role>
+      </roles>
+    </contributor>
+    <contributor>
+      <name>Brian Egge</name>
+      <roles>
+        <role>made the 1.1 release happen</role>
+      </roles>
+    </contributor>
+    <contributor>
+      <name>Berin Loritsch</name>
+      <email>bloritsch at apache.org</email>
+      <roles>
+        <role>helped in the Avalon CLI merge</role>
+      </roles>
+    </contributor>
+    <contributor>
+      <name>Peter Maddocks</name>
+      <email>peter_maddocks at hp.com</email>
+      <organization>Hewlett-Packard</organization>
+      <roles>
+        <role>supplied patch</role>
+      </roles>
+    </contributor>
+    <contributor>
+      <name>Andrew Shirley</name>
+      <roles>
+        <role>lots of fixes for 1.1</role>
+      </roles>
+    </contributor>
+  </contributors>
+
+  <dependencies>
+    <!-- used for unit tests -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <properties>
+    <maven.compile.source>1.4</maven.compile.source>
+    <maven.compile.target>1.4</maven.compile.target>
+    <commons.componentid>cli</commons.componentid>
+    <commons.release.version>1.2</commons.release.version>
+    <commons.release.name>commons-cli-${commons.release.version}</commons.release.name>
+    <commons.osgi.symbolicName>org.apache.commons.cli</commons.osgi.symbolicName>
+    <commons.binary.suffix />
+    <commons.jira.id>CLI</commons.jira.id>
+    <commons.jira.pid>12310463</commons.jira.pid>
+    <!-- The RC version used in the staging repository URL. -->
+    <commons.rc.version>RC7</commons.rc.version>    
+  </properties>
+
+  <build>
+    <sourceDirectory>src/java</sourceDirectory>
+    <testSourceDirectory>src/test</testSourceDirectory>
+    <resources>
+      <resource>
+        <directory>.</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>NOTICE.txt</include>
+          <include>LICENSE.txt</include>
+        </includes>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <configuration>
+          <descriptors>
+            <descriptor>src/assembly/bin.xml</descriptor>
+            <descriptor>src/assembly/src.xml</descriptor>
+          </descriptors>
+          <tarLongFileMode>gnu</tarLongFileMode>
+        </configuration>
+      </plugin>
+      <!--
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-ant-plugin</artifactId>
+        <version>2.1.1-SNAPSHOT</version>
+      </plugin>
+      -->
+    </plugins>
+  </build>
+
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>findbugs-maven-plugin</artifactId>
+        <version>1.2</version>
+        <configuration>
+          <threshold>Normal</threshold>
+          <effort>Default</effort>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <configuration>
+          <configLocation>src/conf/checkstyle.xml</configLocation>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-pmd-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>cobertura-maven-plugin</artifactId>
+        <version>2.2</version>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>clirr-maven-plugin</artifactId>
+        <version>2.2.1</version>
+        <configuration>
+          <comparisonVersion>1.1</comparisonVersion>
+        </configuration>
+      </plugin>
+    </plugins>
+  </reporting>
+
+
+  <profiles>
+    <!-- Profile to let Gump choose the name of the jar file generated -->
+    <profile>
+      <id>gump</id>
+      <activation>
+        <property>
+          <name>maven.final.name</name>
+        </property>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-jar-plugin</artifactId>
+            <configuration>
+              <finalName>${maven.final.name}</finalName>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>rc</id>
+      <distributionManagement>
+        <!-- Cannot define in parent ATM, see COMMONSSITE-26 -->
+        <site>
+          <id>apache.website</id>
+          <name>Apache Commons Release Candidate Staging Site</name>
+          <url>${commons.deployment.protocol}://people.apache.org/www/people.apache.org/builds/commons/${commons.componentid}/${commons.release.version}/${commons.rc.version}/site</url>
+        </site>
+      </distributionManagement>
+    </profile>
+  </profiles>
+
+</project>
diff --git a/project.properties b/project.properties
deleted file mode 100644
index 7e0f95f..0000000
--- a/project.properties
+++ /dev/null
@@ -1,38 +0,0 @@
-# -------------------------------------------------------------------
-# P R O J E C T  P R O P E R T I E S
-# -------------------------------------------------------------------
-maven.repo.remote=http://repo1.maven.org/maven
-
-maven.changelog.factory=org.apache.maven.svnlib.SvnChangeLogFactory
-
-maven.changes.issue.template=http://issues.apache.org/jira/browse/%ISSUE%
-
-compile.debug = on
-compile.optimize = off
-compile.deprecation = off
-
-maven.compile.source=1.3
-maven.compile.target=1.3
-
-maven.jarResources.basedir=${basedir}/src/java
-
-# Make the source distro unzip to a different directory
-maven.dist.src.assembly.dir=${maven.dist.assembly.dir}/src/${maven.final.name}-src
-
-# Reset the checkstyle properties to use the default sun settings
-maven.checkstyle.properties=
-maven.checkstyle.format=sun
-
-maven.xdoc.date=left
-maven.xdoc.version=${pom.currentVersion}
-maven.xdoc.developmentProcessUrl=http://jakarta.apache.org/commons/charter.html
-maven.xdoc.poweredby.image=maven-feather.png
-
-maven.javadoc.links=http://java.sun.com/j2se/1.4/docs/api/
-
-# Jar Manifest and Additional Attributes
-maven.jar.manifest=${basedir}/src/conf/MANIFEST.MF
-maven.jar.manifest.attributes.list=Implementation-Vendor-Id,X-Compile-Source-JDK,X-Compile-Target-JDK
-maven.jar.manifest.attribute.Implementation-Vendor-Id=org.apache
-maven.jar.manifest.attribute.X-Compile-Source-JDK=${maven.compile.source}
-maven.jar.manifest.attribute.X-Compile-Target-JDK=${maven.compile.target}
diff --git a/project.xml b/project.xml
deleted file mode 100644
index 66b7171..0000000
--- a/project.xml
+++ /dev/null
@@ -1,202 +0,0 @@
-<?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>
-  <groupId>commons-cli</groupId>
-  <artifactId>commons-cli</artifactId>
-  <name>CLI</name>
-  <currentVersion>1.1</currentVersion>
-  <inceptionYear>2002</inceptionYear>
-  <shortDescription>Commons CLI</shortDescription>
-  <description>
-    Commons CLI provides a simple API for presenting, processing and
-    validating a command line interface.
-  </description>
-  <logo>/images/logo.png</logo>
-
-  <url>http://jakarta.apache.org/commons/cli/</url>
-  <package>org.apache.commons</package>
-
-  <organization>
-    <name>Apache Software Foundation</name>
-    <url>http://www.apache.org</url>
-    <logo>http://jakarta.apache.org/images/original-jakarta-logo.gif</logo>
-  </organization>
-
-  <licenses>
-    <license>
-      <name>The Apache Software License, Version 2.0</name>
-      <url>/LICENSE.txt</url>
-      <distribution>repo</distribution>
-    </license>
-  </licenses>
-
-  <gumpRepositoryId>jakarta</gumpRepositoryId>
-  <issueTrackingUrl>http://issues.apache.org/jira/</issueTrackingUrl>
-  <siteAddress>people.apache.org</siteAddress>
-  <siteDirectory>/www/jakarta.apache.org/commons/cli/</siteDirectory>
-  <distributionDirectory>/www/jakarta.apache.org/builds/jakarta-commons/cli/</distributionDirectory>
-
-  <repository>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/jakarta/commons/proper/cli/trunk</connection>
-    <url>http://svn.apache.org/repos/asf/jakarta/commons/proper/cli/trunk</url>
-  </repository>
-
-  <mailingLists>
-    <mailingList>
-      <name>Commons Dev List</name>
-      <subscribe>commons-dev-subscribe at jakarta.apache.org</subscribe>
-      <unsubscribe>commons-dev-unsubscribe at jakarta.apache.org</unsubscribe>
-      <archive>http://mail-archives.apache.org/mod_mbox/jakarta-commons-dev/</archive>
-    </mailingList>
-    <mailingList>
-      <name>Commons User List</name>
-      <subscribe>commons-user-subscribe at jakarta.apache.org</subscribe>
-      <unsubscribe>commons-user-unsubscribe at jakarta.apache.org</unsubscribe>
-      <archive>http://mail-archives.apache.org/mod_mbox/jakarta-commons-user/</archive>
-    </mailingList>
-  </mailingLists>
-
-  <developers>
-    <developer>
-      <name>James Strachan</name>
-      <id>jstrachan</id>
-      <email>jstrachan at apache.org</email>
-      <organization>SpiritSoft, Inc.</organization>
-    </developer>
-    <developer>
-      <name>Bob McWhirter</name>
-      <id>bob</id>
-      <email>bob at werken.com</email>
-      <organization>Werken</organization>
-      <roles>
-        <role>contributed ideas and code from werken.opt</role>
-      </roles>
-    </developer>
-    <developer>
-      <name>John Keyes</name>
-      <id>jkeyes</id>
-      <email>jbjk at mac.com</email>
-      <organization>integral Source</organization>
-      <roles>
-        <role>contributed ideas and code from Optz</role>
-      </roles>
-    </developer>
-    <developer>
-      <name>Rob Oxspring</name>
-      <id>roxspring</id>
-      <email>roxspring at imapmail.org</email>
-      <organization>Indigo Stone</organization>
-      <roles>
-        <role>designed CLI2</role>
-      </roles>
-    </developer>
-  </developers>
-
-  <contributors>
-    <contributor>
-      <name>Peter Donald</name>
-      <roles>
-        <role>contributed ideas and code from Avalon Excalibur's cli package</role>
-      </roles>
-    </contributor>
-    <contributor>
-      <name>Brian Egge</name>
-      <roles>
-        <role>made the 1.1 release happen</role>
-      </roles>
-    </contributor>
-    <contributor>
-      <name>Berin Loritsch</name>
-      <email>bloritsch at apache.org</email>
-      <roles>
-        <role>helped in the Avalon CLI merge</role>
-      </roles>
-    </contributor>
-    <contributor>
-      <name>Peter Maddocks</name>
-      <email>peter_maddocks at hp.com</email>
-      <organization>Hewlett-Packard</organization>
-      <roles>
-        <role>supplied patch</role>
-      </roles>
-    </contributor>
-    <contributor>
-      <name>Andrew Shirley</name>
-      <roles>
-        <role>lots of fixes for 1.1 and 2.0</role>
-      </roles>
-    </contributor>
-  </contributors>
-
-  <dependencies>
-
-    <!-- used for unit tests -->
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>3.8.1</version>
-      <properties>
-       <scope>test</scope>
-       <comment>
-        Required only for testing.
-       </comment>
-      </properties>
-    </dependency>
-
-  </dependencies>
-
-  <build>
-    <nagEmailAddress>commons-dev at jakarta.apache.org</nagEmailAddress>
-    <sourceDirectory>src/java</sourceDirectory>
-    <unitTestSourceDirectory>src/test</unitTestSourceDirectory>
-
-    <!-- Unit test classes -->
-    <unitTest>
-      <includes>
-        <include>**/*Test.java</include>
-      </includes>
-    </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>
-
-    <!-- Pointless given tht the code is most definitely not 'sun' style -->
-    <!--report>maven-checkstyle-plugin</report-->  
-
-    <report>maven-javadoc-plugin</report>
-    <report>maven-junit-report-plugin</report>
-    <report>maven-jxr-plugin</report>
-    <report>maven-license-plugin</report>
-    <report>maven-pmd-plugin</report>
-    <!--
-    <report>maven-simian-plugin</report>
-    <report>maven-jcoverage-plugin</report>
-    <report>maven-findbugs-plugin</report>
-    -->
-  </reports>
-</project>
diff --git a/src/assembly/bin.xml b/src/assembly/bin.xml
new file mode 100644
index 0000000..5762291
--- /dev/null
+++ b/src/assembly/bin.xml
@@ -0,0 +1,44 @@
+<!--
+ 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>false</includeSiteDirectory>
+    <fileSets>
+        <fileSet>
+            <includes>
+                <include>LICENSE.txt</include>
+                <include>NOTICE.txt</include>
+                <include>RELEASE-NOTES.txt</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>target</directory>
+            <outputDirectory></outputDirectory>
+            <includes>
+                <include>*.jar</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>target/site/apidocs</directory>
+            <outputDirectory>apidocs</outputDirectory>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/src/assembly/src.xml b/src/assembly/src.xml
new file mode 100644
index 0000000..f3c0bda
--- /dev/null
+++ b/src/assembly/src.xml
@@ -0,0 +1,45 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<assembly>
+    <id>src</id>
+    <formats>
+        <format>tar.gz</format>
+        <format>zip</format>
+    </formats>
+    <baseDirectory>${project.artifactId}-${commons.release.version}-src</baseDirectory>
+    <fileSets>
+        <fileSet>
+            <includes>
+                <include>build.xml</include>
+                <include>build.properties</include>
+                <include>CLI2Converter.java</include>
+                <include>CLI2ConverterTest.java</include>
+                <include>LICENSE.txt</include>
+                <include>NOTICE.txt</include>
+                <include>pom.xml</include>
+                <include>README.txt</include>
+                <include>RELEASE-NOTES.txt</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>src</directory>
+        </fileSet>
+        <fileSet>
+            <directory>xdocs</directory>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/src/test/org/apache/commons/cli/UtilTest.java b/src/conf/HEADER.txt
similarity index 68%
copy from src/test/org/apache/commons/cli/UtilTest.java
copy to src/conf/HEADER.txt
index 3aae1d1..8c563ab 100644
--- a/src/test/org/apache/commons/cli/UtilTest.java
+++ b/src/conf/HEADER.txt
@@ -14,17 +14,3 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.cli;
-
-import junit.framework.TestCase;
-
-/**
- * @author brianegge
- */
-public class UtilTest extends TestCase {
-    public void testStripLeadingHyphens() {
-        assertEquals("f", Util.stripLeadingHyphens("-f"));
-        assertEquals("foo", Util.stripLeadingHyphens("--foo"));
-        assertNull(Util.stripLeadingHyphens(null));
-    }
-}
diff --git a/src/conf/MANIFEST.MF b/src/conf/MANIFEST.MF
index 02ae373..cd23a6e 100644
--- a/src/conf/MANIFEST.MF
+++ b/src/conf/MANIFEST.MF
@@ -1,4 +1,21 @@
-Implementation-Title: Jakarta Commons CLI
-Specification-Title: Jakarta Commons CLI
-Specification-Vendor: Apache Software Foundation
-Specification-Version: 1.1
+Manifest-Version: 1.0
+Implementation-Title: Commons CLI
+Implementation-Vendor: The Apache Software Foundation
+Implementation-Vendor-Id: org.apache
+Implementation-Version: 1.2-SNAPSHOT
+Specification-Title: Commons CLI
+Specification-Vendor: The Apache Software Foundation
+Specification-Version: 1.2-SNAPSHOT
+X-Compile-Source-JDK: 1.3
+X-Compile-Target-JDK: 1.3
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Import-Package: org.apache.commons.cli;version="1.2.0.SNAPSHOT"
+Export-Package: org.apache.commons.cli;version="1.2.0.SNAPSHOT"
+Bundle-Version: 1.2.0.SNAPSHOT
+Bundle-Name: Commons CLI
+Bundle-Description: Commons CLI provides a simple API for presenting,
+ processing and validating a command line interface.
+Bundle-DocURL: http://commons.apache.org/cli/
+Bundle-ManifestVersion: 2
+Bundle-Vendor: The Apache Software Foundation
+Bundle-SymbolicName: org.apache.commons.cli
diff --git a/src/conf/checkstyle.xml b/src/conf/checkstyle.xml
new file mode 100644
index 0000000..b027be6
--- /dev/null
+++ b/src/conf/checkstyle.xml
@@ -0,0 +1,189 @@
+<?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 that checks the commons-cli coding conventions -->
+
+<module name="Checker">
+    <property name="localeLanguage" value="en"/>
+
+    <!-- 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"/>
+
+    <!-- Exceptions -->
+    <!--
+    <module name="SuppressionFilter">
+        <property name="file" value="conf/checkstyle-suppressions.xml"/>
+    </module>
+    -->
+
+    <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="public"/>
+            <property name="allowUndeclaredRTE" value="true"/>
+            <property name="allowMissingJavadoc" value="true"/>
+        </module>
+        <module name="JavadocType">
+            <property name="authorFormat" value="\S"/>
+        </module>
+        <module name="JavadocVariable"/>
+
+
+        <!-- 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">
+            <property name="headerFile" value="src/conf/HEADER.txt"/>
+        </module>
+
+        <!-- Following interprets the header file as regular expressions. -->
+        <!-- <module name="RegexpHeader"/>                                -->
+
+
+        <!-- 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"/>-->
+        <module name="LineLength">
+            <property name="max" value="120"/>
+        </module>
+        <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="TabCharacter"/>
+        <module name="WhitespaceAfter"/>
+        <module name="WhitespaceAround">
+          <property name="tokens" value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LCURLY, LE, LITERAL_ASSERT, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN, STAR, STAR_ASSIGN [...]
+        </module>
+
+
+
+        <!-- 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"/>
+        <module name="EmptyBlock"/>
+        <module name="LeftCurly">
+            <property name="option" value="nl"/>
+        </module>
+        <module name="NeedBraces"/>
+        <module name="RightCurly">
+            <property name="option" value="alone"/>
+        </module>
+
+
+        <!-- Checks for common coding problems               -->
+        <!-- See http://checkstyle.sf.net/config_coding.html -->
+        <module name="CovariantEquals"/>
+        <module name="DoubleCheckedLocking"/>
+        <module name="EqualsHashCode"/>
+        <module name="IllegalInstantiation"/>
+        <module name="InnerAssignment"/>
+        <module name="MagicNumber">
+            <property name="ignoreNumbers" value="-1,0,1,2,3"/>
+        </module>
+        <module name="RedundantThrows">
+            <property name="allowUnchecked" value="true"/>
+        </module>
+        <module name="SimplifyBooleanExpression"/>
+        <module name="SimplifyBooleanReturn"/>
+        <module name="StringLiteralEquality"/>
+        <module name="SuperClone"/>
+        <module name="SuperFinalize"/>
+        <module name="DeclarationOrder"/>
+        <module name="ExplicitInitialization"/>
+        <module name="DefaultComesLast"/>
+        <module name="FallThrough"/>
+        <module name="MultipleVariableDeclarations"/>
+        <module name="UnnecessaryParentheses"/>
+
+        <!-- Checks for class design                         -->
+        <!-- See http://checkstyle.sf.net/config_design.html -->
+        <module name="FinalClass"/>
+        <module name="HideUtilityClassConstructor"/>
+        <module name="InterfaceIsType"/>
+        <module name="VisibilityModifier">
+            <property name="protectedAllowed" value="true"/>
+        </module>
+
+
+
+        <!-- Miscellaneous other checks.                   -->
+        <!-- See http://checkstyle.sf.net/config_misc.html -->
+        <module name="ArrayTypeStyle"/>
+        <!--
+        <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/src/java/org/apache/commons/cli/AlreadySelectedException.java b/src/java/org/apache/commons/cli/AlreadySelectedException.java
index aea7807..a5ed661 100644
--- a/src/java/org/apache/commons/cli/AlreadySelectedException.java
+++ b/src/java/org/apache/commons/cli/AlreadySelectedException.java
@@ -14,21 +14,27 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
-/** 
- * <p>Thrown when more than one option in an option group
- * has been provided.</p>
+/**
+ * Thrown when more than one option in an option group
+ * has been provided.
  *
  * @author John Keyes ( john at integralsource.com )
- * @see ParseException
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
  */
-public class AlreadySelectedException
-    extends ParseException {
+public class AlreadySelectedException extends ParseException
+{
+    /** The option group selected. */
+    private OptionGroup group;
+
+    /** The option that triggered the exception. */
+    private Option option;
 
-    /** 
-     * <p>Construct a new <code>AlreadySelectedException</code> 
-     * with the specified detail message.</p>
+    /**
+     * Construct a new <code>AlreadySelectedException</code>
+     * with the specified detail message.
      *
      * @param message the detail message
      */
@@ -36,4 +42,42 @@ public class AlreadySelectedException
     {
         super(message);
     }
-}
\ No newline at end of file
+
+    /**
+     * Construct a new <code>AlreadySelectedException</code>
+     * for the specified option group.
+     *
+     * @param group  the option group already selected
+     * @param option the option that triggered the exception
+     * @since 1.2
+     */
+    public AlreadySelectedException(OptionGroup group, Option option)
+    {
+        this("The option '" + option.getKey() + "' was specified but an option from this group "
+                + "has already been selected: '" + group.getSelected() + "'");
+        this.group = group;
+        this.option = option;
+    }
+
+    /**
+     * Returns the option group where another option has been selected.
+     *
+     * @return the related option group
+     * @since 1.2
+     */
+    public OptionGroup getOptionGroup()
+    {
+        return group;
+    }
+
+    /**
+     * Returns the option that was added to the group and triggered the exception.
+     *
+     * @return the related option
+     * @since 1.2
+     */
+    public Option getOption()
+    {
+        return option;
+    }
+}
diff --git a/src/java/org/apache/commons/cli/BasicParser.java b/src/java/org/apache/commons/cli/BasicParser.java
index 24ce212..a89a84a 100644
--- a/src/java/org/apache/commons/cli/BasicParser.java
+++ b/src/java/org/apache/commons/cli/BasicParser.java
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
 /**
@@ -21,13 +22,13 @@ package org.apache.commons.cli;
  * the {@link Parser#flatten(Options,String[],boolean) flatten} method.
  *
  * @author John Keyes (john at integralsource.com)
- * @see Parser
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
  */
-public class BasicParser extends Parser {
-
+public class BasicParser extends Parser
+{
     /**
      * <p>A simple implementation of {@link Parser}'s abstract
-     * {@link Parser#flatten(Options,String[],boolean) flatten} method.</p>
+     * {@link Parser#flatten(Options, String[], boolean) flatten} method.</p>
      *
      * <p><b>Note:</b> <code>options</code> and <code>stopAtNonOption</code>
      * are not used in this <code>flatten</code> method.</p>
@@ -38,10 +39,9 @@ public class BasicParser extends Parser {
      * when an non option is found.
      * @return The <code>arguments</code> String array.
      */
-    protected String[] flatten(Options options, String[] arguments, 
-                               boolean stopAtNonOption)
+    protected String[] flatten(Options options, String[] arguments, boolean stopAtNonOption)
     {
         // just echo the arguments
         return arguments;
     }
-}
\ No newline at end of file
+}
diff --git a/src/java/org/apache/commons/cli/CommandLine.java b/src/java/org/apache/commons/cli/CommandLine.java
index 190161c..14137af 100644
--- a/src/java/org/apache/commons/cli/CommandLine.java
+++ b/src/java/org/apache/commons/cli/CommandLine.java
@@ -14,18 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
+import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Set;
-import java.util.HashSet;
+import java.util.Properties;
 
-/** 
- * <p>Represents list of arguments parsed against
- * a {@link Options} descriptor.<p>
+/**
+ * Represents list of arguments parsed against a {@link Options} descriptor.
  *
  * <p>It allows querying of a boolean {@link #hasOption(String opt)},
  * in addition to retrieving the {@link #getOptionValue(String opt)}
@@ -37,17 +38,17 @@ import java.util.HashSet;
  * @author bob mcwhirter (bob @ werken.com)
  * @author <a href="mailto:jstrachan at apache.org">James Strachan</a>
  * @author John Keyes (john at integralsource.com)
+ * @version $Revision: 735247 $, $Date: 2009-01-17 00:23:35 -0800 (Sat, 17 Jan 2009) $
  */
-public class CommandLine {
+public class CommandLine implements Serializable
+{
+    private static final long serialVersionUID = 1L;
 
     /** the unrecognised options/arguments */
     private List args = new LinkedList();
 
     /** the processed options */
-    private Set options = new HashSet();
-
-    /** Map of unique options for ease to get complete list of options */
-//    private Set allOptions = new HashSet();
+    private List options = new ArrayList();
 
     /**
      * Creates a command line.
@@ -65,7 +66,7 @@ public class CommandLine {
      */
     public boolean hasOption(String opt)
     {
-        return options.contains( resolveOption(opt));
+        return options.contains(resolveOption(opt));
     }
 
     /** 
@@ -84,9 +85,30 @@ public class CommandLine {
      *
      * @param opt the name of the option
      * @return the type of this <code>Option</code>
+     * @deprecated due to System.err message. Instead use getParsedOptionValue(String)
      */
     public Object getOptionObject(String opt)
     {
+        try {
+            return getParsedOptionValue(opt);
+        } catch(ParseException pe) {
+            System.err.println("Exception found converting " + opt + " to desired type: " + 
+                pe.getMessage() );
+            return null;
+        }
+    }
+
+    /**
+     * Return a version of this <code>Option</code> converted to a particular type. 
+     *
+     * @param opt the name of the option
+     * @return the value parsed into a particluar object
+     * @throws ParseException if there are problems turning the option value into the desired type
+     * @see PatternOptionBuilder
+     */
+    public Object getParsedOptionValue(String opt)
+    throws ParseException
+    {
         String res = getOptionValue(opt);
 
         Option option = resolveOption(opt);
@@ -146,35 +168,41 @@ public class CommandLine {
      */
     public String[] getOptionValues(String opt)
     {
-        Option key = resolveOption( opt );
+        List values = new ArrayList();
 
-        if (options.contains(key))
+        for (Iterator it = options.iterator(); it.hasNext();)
         {
-            return key.getValues();
+            Option option = (Option) it.next();
+            if (opt.equals(option.getOpt()) || opt.equals(option.getLongOpt()))
+            {
+                values.addAll(option.getValuesList());
+            }
         }
 
-        return null;
-        }
+        return values.isEmpty() ? null : (String[]) values.toArray(new String[values.size()]);
+    }
 
     /**
-     * <p>Retrieves the option object given the long or short option as a String</p>
+     * Retrieves the option object given the long or short option as a String
+     * 
      * @param opt short or long name of the option
      * @return Canonicalized option
      */
-    private Option resolveOption( String opt )
+    private Option resolveOption(String opt)
     {
         opt = Util.stripLeadingHyphens(opt);
-        for ( Iterator it = options.iterator(); it.hasNext(); )
+        for (Iterator it = options.iterator(); it.hasNext();)
         {
             Option option = (Option) it.next();
             if (opt.equals(option.getOpt()))
             {
                 return option;
             }
-            if (opt.equals( option.getLongOpt()))
+
+            if (opt.equals(option.getLongOpt()))
             {
                 return option;
-        }
+            }
 
         }
         return null;
@@ -196,7 +224,7 @@ public class CommandLine {
      * Retrieve the argument, if any, of an option.
      *
      * @param opt name of the option
-     * @param defaultValue is the default value to be returned if the option 
+     * @param defaultValue is the default value to be returned if the option
      * is not specified
      * @return Value of the argument if option is set, and has an argument,
      * otherwise <code>defaultValue</code>.
@@ -212,7 +240,7 @@ public class CommandLine {
      * Retrieve the argument, if any, of an option.
      *
      * @param opt character name of the option
-     * @param defaultValue is the default value to be returned if the option 
+     * @param defaultValue is the default value to be returned if the option
      * is not specified
      * @return Value of the argument if option is set, and has an argument,
      * otherwise <code>defaultValue</code>.
@@ -222,6 +250,46 @@ public class CommandLine {
         return getOptionValue(String.valueOf(opt), defaultValue);
     }
 
+    /**
+     * Retrieve the map of values associated to the option. This is convenient
+     * for options specifying Java properties like <tt>-Dparam1=value1
+     * -Dparam2=value2</tt>. The first argument of the option is the key, and
+     * the 2nd argument is the value. If the option has only one argument
+     * (<tt>-Dfoo</tt>) it is considered as a boolean flag and the value is
+     * <tt>"true"</tt>.
+     *
+     * @param opt name of the option
+     * @return The Properties mapped by the option, never <tt>null</tt>
+     *         even if the option doesn't exists
+     * @since 1.2
+     */
+    public Properties getOptionProperties(String opt)
+    {
+        Properties props = new Properties();
+
+        for (Iterator it = options.iterator(); it.hasNext();)
+        {
+            Option option = (Option) it.next();
+
+            if (opt.equals(option.getOpt()) || opt.equals(option.getLongOpt()))
+            {
+                List values = option.getValuesList();
+                if (values.size() >= 2)
+                {
+                    // use the first 2 arguments as the key/value pair
+                    props.put(values.get(0), values.get(1));
+                }
+                else if (values.size() == 1)
+                {
+                    // no explicit value, handle it as a boolean
+                    props.put(values.get(0), "true");
+                }
+            }
+        }
+
+        return props;
+    }
+
     /** 
      * Retrieve any left-over non-recognized options and arguments
      *
@@ -279,8 +347,7 @@ public class CommandLine {
     }
 
     /**
-     * Add an option to the command line.  The values of 
-     * the option are stored.
+     * Add an option to the command line.  The values of the option are stored.
      *
      * @param opt the processed option
      */
@@ -292,7 +359,7 @@ public class CommandLine {
     /**
      * Returns an iterator over the Option members of CommandLine.
      *
-     * @return an <code>Iterator</code> over the processed {@link Option} 
+     * @return an <code>Iterator</code> over the processed {@link Option}
      * members of this {@link CommandLine}
      */
     public Iterator iterator()
@@ -315,4 +382,4 @@ public class CommandLine {
         // return the array
         return (Option[]) processed.toArray(optionsArray);
     }
-}
\ No newline at end of file
+}
diff --git a/src/java/org/apache/commons/cli/CommandLineParser.java b/src/java/org/apache/commons/cli/CommandLineParser.java
index f165d99..f507231 100644
--- a/src/java/org/apache/commons/cli/CommandLineParser.java
+++ b/src/java/org/apache/commons/cli/CommandLineParser.java
@@ -14,19 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.cli;
 
-import java.util.Properties;
+package org.apache.commons.cli;
 
 /**
- * A class that implements the <code>CommandLineParser</code> interface 
+ * A class that implements the <code>CommandLineParser</code> interface
  * can parse a String array according to the {@link Options} specified
  * and return a {@link CommandLine}.
  *
  * @author John Keyes (john at integralsource.com)
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
  */
-public interface CommandLineParser {
-
+public interface CommandLineParser
+{
     /**
      * Parse the arguments according to the specified options.
      *
@@ -37,8 +37,7 @@ public interface CommandLineParser {
      * @throws ParseException if there are any problems encountered
      * while parsing the command line tokens.
      */
-    CommandLine parse(Options options, String[] arguments)
-               throws ParseException;
+    CommandLine parse(Options options, String[] arguments) throws ParseException;
 
     /**
      * Parse the arguments according to the specified options and
@@ -52,11 +51,10 @@ public interface CommandLineParser {
      * @throws ParseException if there are any problems encountered
      * while parsing the command line tokens.
      */
-    /* To maintain binary compatibility, this is commented out. 
-       It is still in the abstract Parser class, so most users will 
-       still reap the benefit. 
-    CommandLine parse(Options options, String[] arguments, 
-                      Properties properties)
+    /* To maintain binary compatibility, this is commented out.
+       It is still in the abstract Parser class, so most users will
+       still reap the benefit.
+    CommandLine parse(Options options, String[] arguments, Properties properties)
                throws ParseException;
      */
 
@@ -72,9 +70,7 @@ public interface CommandLineParser {
      * @throws ParseException if there are any problems encountered
      * while parsing the command line tokens.
      */
-    CommandLine parse(Options options, String[] arguments, 
-                      boolean stopAtNonOption)
-               throws ParseException;
+    CommandLine parse(Options options, String[] arguments, boolean stopAtNonOption) throws ParseException;
 
     /**
      * Parse the arguments according to the specified options and
@@ -89,11 +85,10 @@ public interface CommandLineParser {
      * @throws ParseException if there are any problems encountered
      * while parsing the command line tokens.
      */
-    /* To maintain binary compatibility, this is commented out. 
-       It is still in the abstract Parser class, so most users will 
-       still reap the benefit. 
-    CommandLine parse(Options options, String[] arguments, 
-                      Properties properties, boolean stopAtNonOption)
-               throws ParseException;
+    /* To maintain binary compatibility, this is commented out.
+       It is still in the abstract Parser class, so most users will
+       still reap the benefit.
+    CommandLine parse(Options options, String[] arguments, Properties properties, boolean stopAtNonOption)
+            throws ParseException;
      */
 }
diff --git a/src/java/org/apache/commons/cli/GnuParser.java b/src/java/org/apache/commons/cli/GnuParser.java
index dd5f3d7..9aff6aa 100644
--- a/src/java/org/apache/commons/cli/GnuParser.java
+++ b/src/java/org/apache/commons/cli/GnuParser.java
@@ -14,154 +14,89 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
- * The class GnuParser provides an implementation of the 
- * {@link Parser#flatten(Options,String[],boolean) flatten} method.
+ * The class GnuParser provides an implementation of the
+ * {@link Parser#flatten(Options, String[], boolean) flatten} method.
  *
  * @author John Keyes (john at integralsource.com)
- * @see Parser
- * @version $Revision: 542151 $
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
  */
-public class GnuParser extends Parser {
-
-    /** holder for flattened tokens */
-    private ArrayList tokens = new ArrayList();
-
-    /**
-     * <p>Resets the members to their original state i.e. remove
-     * all of <code>tokens</code> entries.
-     */
-    private void init()
-    {
-        tokens.clear();
-    }
-
+public class GnuParser extends Parser
+{
     /**
-     * <p>This flatten method does so using the following rules:
+     * This flatten method does so using the following rules:
      * <ol>
-     *  <li>If an {@link Option} exists for the first character of 
-     *  the <code>arguments</code> entry <b>AND</b> an {@link Option} 
-     *  does not exist for the whole <code>argument</code> then
-     *  add the first character as an option to the processed tokens
-     *  list e.g. "-D" and add the rest of the entry to the also.</li>
-     *  <li>Otherwise just add the token to the processed tokens list.
-     *  </li>
+     *   <li>If an {@link Option} exists for the first character of
+     *   the <code>arguments</code> entry <b>AND</b> an {@link Option}
+     *   does not exist for the whole <code>argument</code> then
+     *   add the first character as an option to the processed tokens
+     *   list e.g. "-D" and add the rest of the entry to the also.</li>
+     *   <li>Otherwise just add the token to the processed tokens list.</li>
      * </ol>
-     * </p>
      *
-     * @param options The Options to parse the arguments by.
-     * @param arguments The arguments that have to be flattened.
-     * @param stopAtNonOption specifies whether to stop 
-     * flattening when a non option has been encountered
+     * @param options         The Options to parse the arguments by.
+     * @param arguments       The arguments that have to be flattened.
+     * @param stopAtNonOption specifies whether to stop flattening when
+     *                        a non option has been encountered
      * @return a String array of the flattened arguments
      */
-    protected String[] flatten(Options options, String[] arguments, 
-                               boolean stopAtNonOption)
+    protected String[] flatten(Options options, String[] arguments, boolean stopAtNonOption)
     {
-        init();
+        List tokens = new ArrayList();
 
         boolean eatTheRest = false;
-        Option currentOption = null;
 
         for (int i = 0; i < arguments.length; i++)
         {
-            if ("--".equals(arguments[i]))
+            String arg = arguments[i];
+
+            if ("--".equals(arg))
             {
                 eatTheRest = true;
                 tokens.add("--");
             }
-            else if ("-".equals(arguments[i]))
+            else if ("-".equals(arg))
             {
                 tokens.add("-");
             }
-            else if (arguments[i].startsWith("-"))
+            else if (arg.startsWith("-"))
             {
-                Option option = options.getOption(arguments[i]);
+                String opt = Util.stripLeadingHyphens(arg);
 
-                // this is not an Option
-                if (option == null)
+                if (options.hasOption(opt))
                 {
-                    // handle special properties Option
-                    Option specialOption = 
-                            options.getOption(arguments[i].substring(0, 2));
-
-                    if (specialOption != null)
-                    {
-                        tokens.add(arguments[i].substring(0, 2));
-                        tokens.add(arguments[i].substring(2));
-                    }
-                    else if (stopAtNonOption)
-                    {
-                        eatTheRest = true;
-                        tokens.add(arguments[i]);
-                    }
-                    else
-                    {
-                        tokens.add(arguments[i]);
-                    }
+                    tokens.add(arg);
                 }
                 else
                 {
-                    // WARNING: Findbugs reports major problems with the following code. 
-                    //          As option cannot be null, currentOption cannot and 
-                    //          much of the code below is never going to be run.
-
-                    currentOption = option;
-
-                    // special option
-                    Option specialOption = 
-                            options.getOption(arguments[i].substring(0, 2));
-
-                    if ((specialOption != null) && (option == null))
-                    {
-                        tokens.add(arguments[i].substring(0, 2));
-                        tokens.add(arguments[i].substring(2));
-                    }
-                    else if ((currentOption != null) && currentOption.hasArg())
-                    {
-                        if (currentOption.hasArg())
-                        {
-                            tokens.add(arguments[i]);
-                            currentOption = null;
-                        }
-                        else if (currentOption.hasArgs())
-                        {
-                            tokens.add(arguments[i]);
-                        }
-                        else if (stopAtNonOption)
-                        {
-                            eatTheRest = true;
-                            tokens.add("--");
-                            tokens.add(arguments[i]);
-                        }
-                        else
-                        {
-                            tokens.add(arguments[i]);
-                        }
-                    }
-                    else if (currentOption != null)
+                    if (opt.indexOf('=') != -1 && options.hasOption(opt.substring(0, opt.indexOf('='))))
                     {
-                        tokens.add(arguments[i]);
+                        // the format is --foo=value or -foo=value
+                        tokens.add(arg.substring(0, arg.indexOf('='))); // --foo
+                        tokens.add(arg.substring(arg.indexOf('=') + 1)); // value
                     }
-                    else if (stopAtNonOption)
+                    else if (options.hasOption(arg.substring(0, 2)))
                     {
-                        eatTheRest = true;
-                        tokens.add("--");
-                        tokens.add(arguments[i]);
+                        // the format is a special properties option (-Dproperty=value)
+                        tokens.add(arg.substring(0, 2)); // -D
+                        tokens.add(arg.substring(2)); // property=value
                     }
                     else
                     {
-                        tokens.add(arguments[i]);
+                        eatTheRest = stopAtNonOption;
+                        tokens.add(arg);
                     }
                 }
             }
             else
             {
-                tokens.add(arguments[i]);
+                tokens.add(arg);
             }
 
             if (eatTheRest)
diff --git a/src/java/org/apache/commons/cli/HelpFormatter.java b/src/java/org/apache/commons/cli/HelpFormatter.java
index 639b9d5..5fddef9 100644
--- a/src/java/org/apache/commons/cli/HelpFormatter.java
+++ b/src/java/org/apache/commons/cli/HelpFormatter.java
@@ -14,10 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
 import java.io.PrintWriter;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -30,8 +30,10 @@ import java.util.List;
  *
  * @author Slawek Zachcial
  * @author John Keyes (john at integralsource.com)
- **/
-public class HelpFormatter {
+ * @version $Revision: 751120 $, $Date: 2009-03-06 14:45:57 -0800 (Fri, 06 Mar 2009) $
+ */
+public class HelpFormatter
+{
     // --------------------------------------------------------------- Constants
 
     /** default number of characters per line */
@@ -46,7 +48,7 @@ public class HelpFormatter {
      */
     public static final int DEFAULT_DESC_PAD = 3;
 
-    /** the string to display at the begining of the usage statement */
+    /** the string to display at the beginning of the usage statement */
     public static final String DEFAULT_SYNTAX_PREFIX = "usage: ";
 
     /** default prefix for shortOpts */
@@ -126,6 +128,13 @@ public class HelpFormatter {
     public String defaultArgName = DEFAULT_ARG_NAME;
 
     /**
+     * Comparator used to sort the options when they output in help text
+     * 
+     * Defaults to case-insensitive alphabetical sorting by option key
+     */
+    protected Comparator optionComparator = new OptionComparator();
+
+    /**
      * Sets the 'width'.
      *
      * @param width the new value of 'width'
@@ -142,7 +151,7 @@ public class HelpFormatter {
      */
     public int getWidth()
     {
-        return this.defaultWidth;
+        return defaultWidth;
     }
 
     /**
@@ -162,7 +171,7 @@ public class HelpFormatter {
      */
     public int getLeftPadding()
     {
-        return this.defaultLeftPad;
+        return defaultLeftPad;
     }
 
     /**
@@ -182,7 +191,7 @@ public class HelpFormatter {
      */
     public int getDescPadding()
     {
-        return this.defaultDescPad;
+        return defaultDescPad;
     }
 
     /**
@@ -202,7 +211,7 @@ public class HelpFormatter {
      */
     public String getSyntaxPrefix()
     {
-        return this.defaultSyntaxPrefix;
+        return defaultSyntaxPrefix;
     }
 
     /**
@@ -222,7 +231,7 @@ public class HelpFormatter {
      */
     public String getNewLine()
     {
-        return this.defaultNewLine;
+        return defaultNewLine;
     }
 
     /**
@@ -242,7 +251,7 @@ public class HelpFormatter {
      */
     public String getOptPrefix()
     {
-        return this.defaultOptPrefix;
+        return defaultOptPrefix;
     }
 
     /**
@@ -262,7 +271,7 @@ public class HelpFormatter {
      */
     public String getLongOptPrefix()
     {
-        return this.defaultLongOptPrefix;
+        return defaultLongOptPrefix;
     }
 
     /**
@@ -282,16 +291,40 @@ public class HelpFormatter {
      */
     public String getArgName()
     {
-        return this.defaultArgName;
+        return defaultArgName;
     }
 
+    /**
+     * Comparator used to sort the options when they output in help text
+     * 
+     * Defaults to case-insensitive alphabetical sorting by option key
+     */
+    public Comparator getOptionComparator()
+    {
+        return optionComparator;
+    }
 
-    // ------------------------------------------------------------------ Public
+    /**
+     * Set the comparator used to sort the options when they output in help text
+     * 
+     * Passing in a null parameter will set the ordering to the default mode
+     */
+    public void setOptionComparator(Comparator comparator)
+    {
+        if (comparator == null)
+        {
+            this.optionComparator = new OptionComparator();
+        }
+        else
+        {
+            this.optionComparator = comparator;
+        }
+    }
 
     /**
-     * <p>Print the help for <code>options</code> with the specified
+     * Print the help for <code>options</code> with the specified
      * command line syntax.  This method prints help information to
-     * System.out.</p>
+     * System.out.
      *
      * @param cmdLineSyntax the syntax for this application
      * @param options the Options instance
@@ -302,77 +335,72 @@ public class HelpFormatter {
     }
 
     /**
-     * <p>Print the help for <code>options</code> with the specified
+     * Print the help for <code>options</code> with the specified
      * command line syntax.  This method prints help information to 
-     * System.out.</p>
+     * System.out.
      *
      * @param cmdLineSyntax the syntax for this application
      * @param options the Options instance
-     * @param autoUsage whether to print an automatically generated 
+     * @param autoUsage whether to print an automatically generated
      * usage statement
      */
-    public void printHelp(String cmdLineSyntax, Options options, 
-                          boolean autoUsage)
+    public void printHelp(String cmdLineSyntax, Options options, boolean autoUsage)
     {
         printHelp(defaultWidth, cmdLineSyntax, null, options, null, autoUsage);
     }
 
     /**
-     * <p>Print the help for <code>options</code> with the specified
+     * Print the help for <code>options</code> with the specified
      * command line syntax.  This method prints help information to
-     * System.out.</p>
+     * System.out.
      *
      * @param cmdLineSyntax the syntax for this application
      * @param header the banner to display at the begining of the help
      * @param options the Options instance
      * @param footer the banner to display at the end of the help
      */
-    public void printHelp(String cmdLineSyntax, String header, Options options, 
-                          String footer)
+    public void printHelp(String cmdLineSyntax, String header, Options options, String footer)
     {
         printHelp(cmdLineSyntax, header, options, footer, false);
     }
 
     /**
-     * <p>Print the help for <code>options</code> with the specified
+     * Print the help for <code>options</code> with the specified
      * command line syntax.  This method prints help information to 
-     * System.out.</p>
+     * System.out.
      *
      * @param cmdLineSyntax the syntax for this application
      * @param header the banner to display at the begining of the help
      * @param options the Options instance
      * @param footer the banner to display at the end of the help
-     * @param autoUsage whether to print an automatically generated 
+     * @param autoUsage whether to print an automatically generated
      * usage statement
      */
-    public void printHelp(String cmdLineSyntax, String header, Options options, 
-                          String footer, boolean autoUsage)
+    public void printHelp(String cmdLineSyntax, String header, Options options, String footer, boolean autoUsage)
     {
-        printHelp(defaultWidth, cmdLineSyntax, header, options, footer, 
-                  autoUsage);
+        printHelp(defaultWidth, cmdLineSyntax, header, options, footer, autoUsage);
     }
 
     /**
-     * <p>Print the help for <code>options</code> with the specified
+     * Print the help for <code>options</code> with the specified
      * command line syntax.  This method prints help information to
-     * System.out.</p>
+     * System.out.
      *
      * @param width the number of characters to be displayed on each line
      * @param cmdLineSyntax the syntax for this application
-     * @param header the banner to display at the begining of the help
+     * @param header the banner to display at the beginning of the help
      * @param options the Options instance
      * @param footer the banner to display at the end of the help
      */
-    public void printHelp(int width, String cmdLineSyntax, String header, 
-                          Options options, String footer)
+    public void printHelp(int width, String cmdLineSyntax, String header, Options options, String footer)
     {
         printHelp(width, cmdLineSyntax, header, options, footer, false);
     }
 
     /**
-     * <p>Print the help for <code>options</code> with the specified
+     * Print the help for <code>options</code> with the specified
      * command line syntax.  This method prints help information to
-     * System.out.</p>
+     * System.out.
      *
      * @param width the number of characters to be displayed on each line
      * @param cmdLineSyntax the syntax for this application
@@ -382,19 +410,18 @@ public class HelpFormatter {
      * @param autoUsage whether to print an automatically generated 
      * usage statement
      */
-    public void printHelp(int width, String cmdLineSyntax, String header, 
+    public void printHelp(int width, String cmdLineSyntax, String header,
                           Options options, String footer, boolean autoUsage)
     {
         PrintWriter pw = new PrintWriter(System.out);
 
-        printHelp(pw, width, cmdLineSyntax, header, options, defaultLeftPad, 
-                  defaultDescPad, footer, autoUsage);
+        printHelp(pw, width, cmdLineSyntax, header, options, defaultLeftPad, defaultDescPad, footer, autoUsage);
         pw.flush();
     }
 
     /**
-     * <p>Print the help for <code>options</code> with the specified
-     * command line syntax.</p>
+     * Print the help for <code>options</code> with the specified
+     * command line syntax.
      *
      * @param pw the writer to which the help will be written
      * @param width the number of characters to be displayed on each line
@@ -406,19 +433,20 @@ public class HelpFormatter {
      * @param descPad the number of characters of padding to be prefixed
      * to each description line
      * @param footer the banner to display at the end of the help
+     *
+     * @throws IllegalStateException if there is no room to print a line
      */
     public void printHelp(PrintWriter pw, int width, String cmdLineSyntax, 
                           String header, Options options, int leftPad, 
                           int descPad, String footer)
     {
-        printHelp(pw, width, cmdLineSyntax, header, options, leftPad, descPad, 
-                  footer, false);
+        printHelp(pw, width, cmdLineSyntax, header, options, leftPad, descPad, footer, false);
     }
 
 
     /**
-     * <p>Print the help for <code>options</code> with the specified
-     * command line syntax.</p>
+     * Print the help for <code>options</code> with the specified
+     * command line syntax.
      *
      * @param pw the writer to which the help will be written
      * @param width the number of characters to be displayed on each line
@@ -430,11 +458,13 @@ public class HelpFormatter {
      * @param descPad the number of characters of padding to be prefixed
      * to each description line
      * @param footer the banner to display at the end of the help
-     * @param autoUsage whether to print an automatically generated 
+     * @param autoUsage whether to print an automatically generated
      * usage statement
+     *
+     * @throws IllegalStateException if there is no room to print a line
      */
-    public void printHelp(PrintWriter pw, int width, String cmdLineSyntax, 
-                          String header, Options options, int leftPad, 
+    public void printHelp(PrintWriter pw, int width, String cmdLineSyntax,
+                          String header, Options options, int leftPad,
                           int descPad, String footer, boolean autoUsage)
     {
         if ((cmdLineSyntax == null) || (cmdLineSyntax.length() == 0))
@@ -473,12 +503,10 @@ public class HelpFormatter {
      * @param options The command line Options
      *
      */
-    public void printUsage(PrintWriter pw, int width, String app, 
-                           Options options)
+    public void printUsage(PrintWriter pw, int width, String app, Options options)
     {
         // initialise the string buffer
-        StringBuffer buff = new StringBuffer(defaultSyntaxPrefix).append(app)
-                                                                 .append(" ");
+        StringBuffer buff = new StringBuffer(defaultSyntaxPrefix).append(app).append(" ");
 
         // create a list for processed option groups
         final Collection processedGroups = new ArrayList();
@@ -487,7 +515,7 @@ public class HelpFormatter {
         Option option;
 
         List optList = new ArrayList(options.getOptions());
-        Collections.sort(optList, new OptionComparator());
+        Collections.sort(optList, getOptionComparator());
         // iterate over the options
         for (Iterator i = optList.iterator(); i.hasNext();)
         {
@@ -529,8 +557,7 @@ public class HelpFormatter {
 
 
         // call printWrapped
-        printWrapped(pw, width, buff.toString().indexOf(' ') + 1, 
-                     buff.toString());
+        printWrapped(pw, width, buff.toString().indexOf(' ') + 1, buff.toString());
     }
 
     /**
@@ -541,8 +568,7 @@ public class HelpFormatter {
      * @param group the group to append
      * @see #appendOption(StringBuffer,Option,boolean)
      */
-    private static void appendOptionGroup(final StringBuffer buff, 
-                                          final OptionGroup group)
+    private void appendOptionGroup(final StringBuffer buff, final OptionGroup group)
     {
         if (!group.isRequired())
         {
@@ -550,7 +576,7 @@ public class HelpFormatter {
         }
 
         List optList = new ArrayList(group.getOptions());
-        Collections.sort(optList, new OptionComparator());
+        Collections.sort(optList, getOptionComparator());
         // for each option in the OptionGroup
         for (Iterator i = optList.iterator(); i.hasNext();)
         {
@@ -576,9 +602,7 @@ public class HelpFormatter {
      * @param option the Option to append
      * @param required whether the Option is required or not
      */
-    private static void appendOption(final StringBuffer buff, 
-                                     final Option option, 
-                                     final boolean required)
+    private static void appendOption(final StringBuffer buff, final Option option, final boolean required)
     {
         if (!required)
         {
@@ -595,7 +619,7 @@ public class HelpFormatter {
         }
 
         // if the Option has a value
-        if (option.hasArg() && (option.getArgName() != null))
+        if (option.hasArg() && option.hasArgName())
         {
             buff.append(" <").append(option.getArgName()).append(">");
         }
@@ -608,8 +632,8 @@ public class HelpFormatter {
     }
 
     /**
-     * <p>Print the cmdLineSyntax to the specified writer, using the
-     * specified width.</p>
+     * Print the cmdLineSyntax to the specified writer, using the
+     * specified width.
      *
      * @param pw The printWriter to write the help to
      * @param width The number of characters per line for the usage statement.
@@ -619,8 +643,7 @@ public class HelpFormatter {
     {
         int argPos = cmdLineSyntax.indexOf(' ') + 1;
 
-        printWrapped(pw, width, defaultSyntaxPrefix.length() + argPos, 
-                     defaultSyntaxPrefix + cmdLineSyntax);
+        printWrapped(pw, width, defaultSyntaxPrefix.length() + argPos, defaultSyntaxPrefix + cmdLineSyntax);
     }
 
     /**
@@ -645,7 +668,7 @@ public class HelpFormatter {
     }
 
     /**
-     * <p>Print the specified text to the specified PrintWriter.</p>
+     * Print the specified text to the specified PrintWriter.
      *
      * @param pw The printWriter to write the help to
      * @param width The number of characters to display per line
@@ -657,15 +680,14 @@ public class HelpFormatter {
     }
 
     /**
-     * <p>Print the specified text to the specified PrintWriter.</p>
+     * Print the specified text to the specified PrintWriter.
      *
      * @param pw The printWriter to write the help to
      * @param width The number of characters to display per line
      * @param nextLineTabStop The position on the next line for the first tab.
      * @param text The text to be written to the PrintWriter
      */
-    public void printWrapped(PrintWriter pw, int width, int nextLineTabStop, 
-                             String text)
+    public void printWrapped(PrintWriter pw, int width, int nextLineTabStop, String text)
     {
         StringBuffer sb = new StringBuffer(text.length());
 
@@ -676,8 +698,8 @@ public class HelpFormatter {
     // --------------------------------------------------------------- Protected
 
     /**
-     * <p>Render the specified Options and return the rendered Options
-     * in a StringBuffer.</p>
+     * Render the specified Options and return the rendered Options
+     * in a StringBuffer.
      *
      * @param sb The StringBuffer to place the rendered Options into.
      * @param width The number of characters to display per line
@@ -689,9 +711,7 @@ public class HelpFormatter {
      *
      * @return the StringBuffer with the rendered Options contents.
      */
-    protected StringBuffer renderOptions(StringBuffer sb, int width, 
-                                         Options options, int leftPad, 
-                                         int descPad)
+    protected StringBuffer renderOptions(StringBuffer sb, int width, Options options, int leftPad, int descPad)
     {
         final String lpad = createPadding(leftPad);
         final String dpad = createPadding(descPad);
@@ -703,30 +723,27 @@ public class HelpFormatter {
         int max = 0;
         StringBuffer optBuf;
         List prefixList = new ArrayList();
-        Option option;
+
         List optList = options.helpOptions();
 
-        Collections.sort(optList, new OptionComparator());
+        Collections.sort(optList, getOptionComparator());
 
         for (Iterator i = optList.iterator(); i.hasNext();)
         {
-            option = (Option) i.next();
+            Option option = (Option) i.next();
             optBuf = new StringBuffer(8);
 
             if (option.getOpt() == null)
             {
-                optBuf.append(lpad).append("   " + defaultLongOptPrefix)
-                      .append(option.getLongOpt());
+                optBuf.append(lpad).append("   " + defaultLongOptPrefix).append(option.getLongOpt());
             }
             else
             {
-                optBuf.append(lpad).append(defaultOptPrefix)
-                      .append(option.getOpt());
+                optBuf.append(lpad).append(defaultOptPrefix).append(option.getOpt());
 
                 if (option.hasLongOpt())
                 {
-                    optBuf.append(',').append(defaultLongOptPrefix)
-                          .append(option.getLongOpt());
+                    optBuf.append(',').append(defaultLongOptPrefix).append(option.getLongOpt());
                 }
             }
 
@@ -743,14 +760,14 @@ public class HelpFormatter {
             }
 
             prefixList.add(optBuf);
-            max = (optBuf.length() > max)       ? optBuf.length() : max;
+            max = (optBuf.length() > max) ? optBuf.length() : max;
         }
 
         int x = 0;
 
         for (Iterator i = optList.iterator(); i.hasNext();)
         {
-            option = (Option) i.next();
+            Option option = (Option) i.next();
             optBuf = new StringBuffer(prefixList.get(x++).toString());
 
             if (optBuf.length() < max)
@@ -779,8 +796,8 @@ public class HelpFormatter {
     }
 
     /**
-     * <p>Render the specified text and return the rendered Options
-     * in a StringBuffer.</p>
+     * Render the specified text and return the rendered Options
+     * in a StringBuffer.
      *
      * @param sb The StringBuffer to place the rendered text into.
      * @param width The number of characters to display per line
@@ -802,6 +819,12 @@ public class HelpFormatter {
         }
         sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
 
+        if (nextLineTabStop >= width)
+        {
+            // stops infinite loop happening
+            nextLineTabStop = 1;
+        }
+
         // all following lines must be padded with nextLineTabStop space 
         // characters
         final String padding = createPadding(nextLineTabStop);
@@ -809,7 +832,7 @@ public class HelpFormatter {
         while (true)
         {
             text = padding + text.substring(pos).trim();
-            pos = findWrapPos(text, width, nextLineTabStop);
+            pos = findWrapPos(text, width, 0);
 
             if (pos == -1)
             {
@@ -817,22 +840,27 @@ public class HelpFormatter {
 
                 return sb;
             }
+            
+            if ( (text.length() > width) && (pos == nextLineTabStop - 1) ) 
+            {
+                pos = width;
+            }
 
             sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
         }
     }
 
     /**
-     * Finds the next text wrap position after <code>startPos</code> for the 
+     * Finds the next text wrap position after <code>startPos</code> for the
      * text in <code>text</code> with the column width <code>width</code>.
      * The wrap point is the last postion before startPos+width having a 
      * whitespace character (space, \n, \r).
      *
      * @param text The text being searched for the wrap position
      * @param width width of the wrapped text
-     * @param startPos position from which to start the lookup whitespace 
+     * @param startPos position from which to start the lookup whitespace
      * character
-     * @return postion on which the text must be wrapped or -1 if the wrap 
+     * @return postion on which the text must be wrapped or -1 if the wrap
      * position is at the end of the text
      */
     protected int findWrapPos(String text, int width, int startPos)
@@ -841,11 +869,11 @@ public class HelpFormatter {
 
         // the line ends before the max wrap pos or a new line char found
         if (((pos = text.indexOf('\n', startPos)) != -1 && pos <= width)
-            || ((pos = text.indexOf('\t', startPos)) != -1 && pos <= width))
+                || ((pos = text.indexOf('\t', startPos)) != -1 && pos <= width))
         {
-            return pos+1;
+            return pos + 1;
         }
-        else if ((startPos + width) >= text.length())
+        else if (startPos + width >= text.length())
         {
             return -1;
         }
@@ -857,7 +885,7 @@ public class HelpFormatter {
         char c;
 
         while ((pos >= startPos) && ((c = text.charAt(pos)) != ' ')
-               && (c != '\n') && (c != '\r'))
+                && (c != '\n') && (c != '\r'))
         {
             --pos;
         }
@@ -878,11 +906,11 @@ public class HelpFormatter {
             ++pos;
         }
 
-        return (pos == text.length())        ? (-1) : pos;
+        return (pos == text.length()) ? (-1) : pos;
     }
 
     /**
-     * <p>Return a String of padding of length <code>len</code>.</p>
+     * Return a String of padding of length <code>len</code>.
      *
      * @param len The length of the String of padding to create.
      *
@@ -901,7 +929,7 @@ public class HelpFormatter {
     }
 
     /**
-     * <p>Remove the trailing whitespace from the specified String.</p>
+     * Remove the trailing whitespace from the specified String.
      *
      * @param s The String to remove the trailing padding from.
      *
@@ -928,28 +956,27 @@ public class HelpFormatter {
     // ---------------------------------------------------------------- Private
     // ---------------------------------------------------------- Inner classes
     /**
-     * <p>This class implements the <code>Comparator</code> interface
-     * for comparing Options.</p>
+     * This class implements the <code>Comparator</code> interface
+     * for comparing Options.
      */
-    private static class OptionComparator
-        implements Comparator {
+    private static class OptionComparator implements Comparator
+    {
 
         /**
-         * <p>Compares its two arguments for order. Returns a negative 
-         * integer, zero, or a positive integer as the first argument 
-         * is less than, equal to, or greater than the second.</p>
+         * Compares its two arguments for order. Returns a negative
+         * integer, zero, or a positive integer as the first argument
+         * is less than, equal to, or greater than the second.
          *
          * @param o1 The first Option to be compared.
          * @param o2 The second Option to be compared.
-         *
-         * @return a negative integer, zero, or a positive integer as 
-         * the first argument is less than, equal to, or greater than the 
-         * second.
+         * @return a negative integer, zero, or a positive integer as
+         *         the first argument is less than, equal to, or greater than the
+         *         second.
          */
         public int compare(Object o1, Object o2)
         {
-            Option opt1 = (Option)o1;
-            Option opt2 = (Option)o2;
+            Option opt1 = (Option) o1;
+            Option opt2 = (Option) o2;
 
             return opt1.getKey().compareToIgnoreCase(opt2.getKey());
         }
diff --git a/src/java/org/apache/commons/cli/MissingArgumentException.java b/src/java/org/apache/commons/cli/MissingArgumentException.java
index 3b3378e..c5d33ea 100644
--- a/src/java/org/apache/commons/cli/MissingArgumentException.java
+++ b/src/java/org/apache/commons/cli/MissingArgumentException.java
@@ -14,21 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
-/** 
- * <p>Thrown when an option requiring an argument
- * is not provided with an argument.</p>
+/**
+ * Thrown when an option requiring an argument
+ * is not provided with an argument.
  *
  * @author John Keyes (john at integralsource.com)
- * @see ParseException
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
  */
-public class MissingArgumentException
-    extends ParseException {
+public class MissingArgumentException extends ParseException
+{
+    /** The option requiring additional arguments */
+    private Option option;
 
-    /** 
-     * <p>Construct a new <code>MissingArgumentException</code> 
-     * with the specified detail message.</p>
+    /**
+     * Construct a new <code>MissingArgumentException</code>
+     * with the specified detail message.
      *
      * @param message the detail message
      */
@@ -36,4 +39,29 @@ public class MissingArgumentException
     {
         super(message);
     }
-}
\ No newline at end of file
+
+    /**
+     * Construct a new <code>MissingArgumentException</code>
+     * with the specified detail message.
+     *
+     * @param option the option requiring an argument
+     * @since 1.2
+     */
+    public MissingArgumentException(Option option)
+    {
+        this("Missing argument for option: " + option.getKey());
+        this.option = option;
+    }
+
+    /**
+     * Return the option requiring an argument that wasn't provided
+     * on the command line.
+     *
+     * @return the related option
+     * @since 1.2
+     */
+    public Option getOption()
+    {
+        return option;
+    }
+}
diff --git a/src/java/org/apache/commons/cli/MissingOptionException.java b/src/java/org/apache/commons/cli/MissingOptionException.java
index b877b76..9ad5905 100644
--- a/src/java/org/apache/commons/cli/MissingOptionException.java
+++ b/src/java/org/apache/commons/cli/MissingOptionException.java
@@ -14,20 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
-/** 
- * <p>Thrown when a required option has not been provided.</p>
+import java.util.List;
+import java.util.Iterator;
+
+/**
+ * Thrown when a required option has not been provided.
  *
  * @author John Keyes ( john at integralsource.com )
- * @see ParseException
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
  */
-public class MissingOptionException
-    extends ParseException {
+public class MissingOptionException extends ParseException
+{
+    /** The list of missing options */
+    private List missingOptions;
 
-    /** 
-     * <p>Construct a new <code>MissingSelectedException</code> 
-     * with the specified detail message.</p>
+    /**
+     * Construct a new <code>MissingSelectedException</code>
+     * with the specified detail message.
      *
      * @param message the detail message
      */
@@ -35,4 +41,53 @@ public class MissingOptionException
     {
         super(message);
     }
-}
\ No newline at end of file
+
+    /**
+     * Constructs a new <code>MissingSelectedException</code> with the
+     * specified list of missing options.
+     *
+     * @param missingOptions the list of missing options
+     * @since 1.2
+     */
+    public MissingOptionException(List missingOptions)
+    {
+        this(createMessage(missingOptions));
+        this.missingOptions = missingOptions;
+    }
+
+    /**
+     * Return the list of options (as strings) missing in the command line parsed.
+     *
+     * @return the missing options
+     * @since 1.2
+     */
+    public List getMissingOptions()
+    {
+        return missingOptions;
+    }
+
+    /**
+     * Build the exception message from the specified list of options.
+     *
+     * @param missingOptions
+     * @since 1.2
+     */
+    private static String createMessage(List missingOptions)
+    {
+        StringBuffer buff = new StringBuffer("Missing required option");
+        buff.append(missingOptions.size() == 1 ? "" : "s");
+        buff.append(": ");
+
+        Iterator it = missingOptions.iterator();
+        while (it.hasNext())
+        {
+            buff.append(it.next());
+            if (it.hasNext())
+            {
+                buff.append(", ");
+            }
+        }
+
+        return buff.toString();
+    }
+}
diff --git a/src/java/org/apache/commons/cli/Option.java b/src/java/org/apache/commons/cli/Option.java
index 76a24d3..af33ae8 100644
--- a/src/java/org/apache/commons/cli/Option.java
+++ b/src/java/org/apache/commons/cli/Option.java
@@ -14,9 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
+import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.List;
 
 /** <p>Describes a single command-line option.  It maintains
  * information regarding the short-name of the option, the long-name,
@@ -31,49 +34,44 @@ import java.util.ArrayList;
  *
  * @author bob mcwhirter (bob @ werken.com)
  * @author <a href="mailto:jstrachan at apache.org">James Strachan</a>
- * @version $Revision: 551821 $
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
  */
-public class Option implements Cloneable {
+public class Option implements Cloneable, Serializable
+{
+    private static final long serialVersionUID = 1L;
 
-    /** constant that specifies the number of argument values has 
-        not been specified */
+    /** constant that specifies the number of argument values has not been specified */
     public static final int UNINITIALIZED = -1;
 
     /** constant that specifies the number of argument values is infinite */
     public static final int UNLIMITED_VALUES = -2;
 
-    /** opt the name of the option */
+    /** the name of the option */
     private String opt;
 
-    /** longOpt is the long representation of the option */
+    /** the long representation of the option */
     private String longOpt;
 
-    /** hasArg specifies whether this option has an associated argument */
-    private boolean hasArg;
-
-    /** argName specifies the name of the argument for this option */
+    /** the name of the argument for this option */
     private String argName = "arg";
 
     /** description of the option */
     private String description;
 
-    /** required specifies whether this option is required to be present */
+    /** specifies whether this option is required to be present */
     private boolean required;
 
     /** specifies whether the argument value of this Option is optional */
     private boolean optionalArg;
 
-    /** 
-     * numberOfArgs specifies the number of argument values this option 
-     * can have 
-     */
+    /** the number of argument values this option can have */
     private int numberOfArgs = UNINITIALIZED;
 
     /** the type of this Option */
     private Object type;
 
     /** the list of argument values **/
-    private ArrayList values = new ArrayList();
+    private List values = new ArrayList();
 
     /** the character that is the value separator */
     private char valuesep;
@@ -87,8 +85,7 @@ public class Option implements Cloneable {
      * @throws IllegalArgumentException if there are any non valid
      * Option characters in <code>opt</code>.
      */
-    public Option(String opt, String description)
-           throws IllegalArgumentException
+    public Option(String opt, String description) throws IllegalArgumentException
     {
         this(opt, null, false, description);
     }
@@ -103,8 +100,7 @@ public class Option implements Cloneable {
      * @throws IllegalArgumentException if there are any non valid
      * Option characters in <code>opt</code>.
      */
-    public Option(String opt, boolean hasArg, String description)
-           throws IllegalArgumentException
+    public Option(String opt, boolean hasArg, String description) throws IllegalArgumentException
     {
         this(opt, null, hasArg, description);
     }
@@ -120,8 +116,7 @@ public class Option implements Cloneable {
      * @throws IllegalArgumentException if there are any non valid
      * Option characters in <code>opt</code>.
      */
-    public Option(String opt, String longOpt, boolean hasArg, 
-                  String description)
+    public Option(String opt, String longOpt, boolean hasArg, String description)
            throws IllegalArgumentException
     {
         // ensure that the option is valid
@@ -136,7 +131,6 @@ public class Option implements Cloneable {
             this.numberOfArgs = 1;
         }
 
-        this.hasArg = hasArg;
         this.description = description;
     }
 
@@ -162,10 +156,10 @@ public class Option implements Cloneable {
         // if 'opt' is null, then it is a 'long' option
         if (opt == null)
         {
-            return this.longOpt;
+            return longOpt;
         }
 
-        return this.opt;
+        return opt;
     }
 
     /** 
@@ -180,7 +174,7 @@ public class Option implements Cloneable {
      */
     public String getOpt()
     {
-        return this.opt;
+        return opt;
     }
 
     /**
@@ -190,7 +184,7 @@ public class Option implements Cloneable {
      */
     public Object getType()
     {
-        return this.type;
+        return type;
     }
 
     /**
@@ -210,7 +204,7 @@ public class Option implements Cloneable {
      */
     public String getLongOpt()
     {
-        return this.longOpt;
+        return longOpt;
     }
 
     /**
@@ -239,7 +233,7 @@ public class Option implements Cloneable {
      */
     public boolean hasOptionalArg()
     {
-        return this.optionalArg;
+        return optionalArg;
     }
 
     /** 
@@ -249,7 +243,7 @@ public class Option implements Cloneable {
      */
     public boolean hasLongOpt()
     {
-        return (this.longOpt != null);
+        return longOpt != null;
     }
 
     /** 
@@ -259,7 +253,7 @@ public class Option implements Cloneable {
      */
     public boolean hasArg()
     {
-        return (this.numberOfArgs > 0) || (numberOfArgs == UNLIMITED_VALUES);
+        return numberOfArgs > 0 || numberOfArgs == UNLIMITED_VALUES;
     }
 
     /** 
@@ -269,13 +263,14 @@ public class Option implements Cloneable {
      */
     public String getDescription()
     {
-        return this.description;
+        return description;
     }
 
-   /** 
+    /**
      * Sets the self-documenting description of this Option
      *
      * @param description The description of this option
+     * @since 1.1
      */
     public void setDescription(String description)
     {
@@ -289,7 +284,7 @@ public class Option implements Cloneable {
      */
     public boolean isRequired()
     {
-        return this.required;
+        return required;
     }
 
     /**
@@ -319,7 +314,7 @@ public class Option implements Cloneable {
      */
     public String getArgName()
     {
-        return this.argName;
+        return argName;
     }
 
     /**
@@ -331,7 +326,7 @@ public class Option implements Cloneable {
      */
     public boolean hasArgName()
     {
-        return (this.argName != null && this.argName.length() > 0);
+        return argName != null && argName.length() > 0;
     }
 
     /** 
@@ -341,8 +336,7 @@ public class Option implements Cloneable {
      */
     public boolean hasArgs()
     {
-        return (this.numberOfArgs > 1) 
-                || (this.numberOfArgs == UNLIMITED_VALUES);
+        return numberOfArgs > 1 || numberOfArgs == UNLIMITED_VALUES;
     }
 
     /** 
@@ -373,17 +367,18 @@ public class Option implements Cloneable {
      */
     public char getValueSeparator()
     {
-        return this.valuesep;
+        return valuesep;
     }
 
     /**
      * Return whether this Option has specified a value separator.
      * 
      * @return whether this Option has specified a value separator.
+     * @since 1.1
      */
     public boolean hasValueSeparator()
     {
-        return (this.valuesep > 0);
+        return valuesep > 0;
     }
 
     /** 
@@ -393,7 +388,7 @@ public class Option implements Cloneable {
      */
     public int getArgs()
     {
-        return this.numberOfArgs;
+        return numberOfArgs;
     }
 
     /**
@@ -405,11 +400,11 @@ public class Option implements Cloneable {
     {
         switch (numberOfArgs)
         {
-        case UNINITIALIZED:
-            throw new RuntimeException("NO_ARGS_ALLOWED");
+            case UNINITIALIZED:
+                throw new RuntimeException("NO_ARGS_ALLOWED");
 
-        default:
-            processValue(value);
+            default:
+                processValue(value);
         }
     }
 
@@ -444,21 +439,17 @@ public class Option implements Cloneable {
                     break;
                 }
 
-
                 // store
                 add(value.substring(0, index));
 
-
                 // parse
                 value = value.substring(index + 1);
 
-
                 // get new index
                 index = value.indexOf(sep);
             }
         }
 
-
         // store the actual value or the last value that has been parsed
         add(value);
     }
@@ -479,9 +470,8 @@ public class Option implements Cloneable {
             throw new RuntimeException("Cannot add value, list full.");
         }
 
-
         // store value
-        this.values.add(value);
+        values.add(value);
     }
 
     /**
@@ -493,7 +483,7 @@ public class Option implements Cloneable {
      */
     public String getValue()
     {
-        return hasNoValues() ? null : (String) this.values.get(0);
+        return hasNoValues() ? null : (String) values.get(0);
     }
 
     /**
@@ -508,10 +498,9 @@ public class Option implements Cloneable {
      * @throws IndexOutOfBoundsException if index is less than 1
      * or greater than the number of the values for this Option.
      */
-    public String getValue(int index)
-        throws IndexOutOfBoundsException
+    public String getValue(int index) throws IndexOutOfBoundsException
     {
-        return hasNoValues() ? null : (String) this.values.get(index);
+        return hasNoValues() ? null : (String) values.get(index);
     }
 
     /**
@@ -540,17 +529,16 @@ public class Option implements Cloneable {
      */
     public String[] getValues()
     {
-        return hasNoValues()
-               ? null : (String[]) this.values.toArray(new String[this.values.size()]);
+        return hasNoValues() ? null : (String[]) values.toArray(new String[values.size()]);
     }
 
     /**
      * @return the values of this Option as a List
      * or null if there are no values
      */
-    public java.util.List getValuesList()
+    public List getValuesList()
     {
-        return this.values;
+        return values;
     }
 
     /** 
@@ -562,25 +550,29 @@ public class Option implements Cloneable {
     {
         StringBuffer buf = new StringBuffer().append("[ option: ");
 
-        buf.append(this.opt);
+        buf.append(opt);
 
-        if (this.longOpt != null)
+        if (longOpt != null)
         {
-            buf.append(" ").append(this.longOpt);
+            buf.append(" ").append(longOpt);
         }
 
         buf.append(" ");
 
-        if (hasArg)
+        if (hasArgs())
         {
-            buf.append("+ARG");
+            buf.append("[ARG...]");
+        }
+        else if (hasArg())
+        {
+            buf.append(" [ARG]");
         }
 
-        buf.append(" :: ").append(this.description);
+        buf.append(" :: ").append(description);
 
-        if (this.type != null)
+        if (type != null)
         {
-            buf.append(" :: ").append(this.type);
+            buf.append(" :: ").append(type);
         }
 
         buf.append(" ]");
@@ -595,16 +587,16 @@ public class Option implements Cloneable {
      */
     private boolean hasNoValues()
     {
-        return this.values.size() == 0;
+        return values.isEmpty();
     }
 
-    public boolean equals( Object o )
+    public boolean equals(Object o)
     {
-        if ( this == o )
+        if (this == o)
         {
             return true;
         }
-        if ( o == null || getClass() != o.getClass() )
+        if (o == null || getClass() != o.getClass())
         {
             return false;
         }
@@ -612,11 +604,11 @@ public class Option implements Cloneable {
         Option option = (Option) o;
 
 
-        if ( opt != null ? !opt.equals( option.opt ) : option.opt != null )
+        if (opt != null ? !opt.equals(option.opt) : option.opt != null)
         {
             return false;
         }
-        if ( longOpt != null ? !longOpt.equals( option.longOpt ) : option.longOpt != null )
+        if (longOpt != null ? !longOpt.equals(option.longOpt) : option.longOpt != null)
         {
             return false;
         }
@@ -627,8 +619,8 @@ public class Option implements Cloneable {
     public int hashCode()
     {
         int result;
-        result = ( opt != null ? opt.hashCode() : 0 );
-        result = 31 * result + ( longOpt != null ? longOpt.hashCode() : 0 );
+        result = (opt != null ? opt.hashCode() : 0);
+        result = 31 * result + (longOpt != null ? longOpt.hashCode() : 0);
         return result;
     }
 
@@ -642,25 +634,29 @@ public class Option implements Cloneable {
      *
      * @throws RuntimeException
      */
-    public Object clone() {
-        try {
+    public Object clone()
+    {
+        try
+        {
             Option option = (Option) super.clone();
             option.values = new ArrayList(values);
             return option;
-        } catch(CloneNotSupportedException cnse) {
+        }
+        catch (CloneNotSupportedException cnse)
+        {
             throw new RuntimeException("A CloneNotSupportedException was thrown: " + cnse.getMessage());
         }
     }
 
     /**
-     * <p>Clear the Option values. After a 
-     * parse is complete, these are left with data in them 
-     * and they need clearing if another parse is done. </p>
+     * Clear the Option values. After a parse is complete, these are left with
+     * data in them and they need clearing if another parse is done.
      *
      * See: <a href="https://issues.apache.org/jira/browse/CLI-71">CLI-71</a>
      */
-    void clearValues() {
-        this.values.clear();
+    void clearValues()
+    {
+        values.clear();
     }
 
     /**
@@ -669,11 +665,10 @@ public class Option implements Cloneable {
      * @deprecated
      * @throws UnsupportedOperationException
      */
-    public boolean addValue(String value) {
-        throw new UnsupportedOperationException(
-           "The addValue method is not intended for client use. " + 
-           "Subclasses should use the addValueForProcessing method instead. "
-           );
+    public boolean addValue(String value)
+    {
+        throw new UnsupportedOperationException("The addValue method is not intended for client use. "
+                + "Subclasses should use the addValueForProcessing method instead. ");
     }
 
 }
diff --git a/src/java/org/apache/commons/cli/OptionBuilder.java b/src/java/org/apache/commons/cli/OptionBuilder.java
index f1888a8..93816c1 100644
--- a/src/java/org/apache/commons/cli/OptionBuilder.java
+++ b/src/java/org/apache/commons/cli/OptionBuilder.java
@@ -14,20 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
 /**
- * <p>OptionBuilder allows the user to create Options using descriptive
- * methods.</p>
- * <p>Details on the Builder pattern can be found at 
+ * OptionBuilder allows the user to create Options using descriptive methods.
+ *
+ * <p>Details on the Builder pattern can be found at
  * <a href="http://c2.com/cgi-bin/wiki?BuilderPattern">
  * http://c2.com/cgi-bin/wiki?BuilderPattern</a>.</p>
  *
  * @author John Keyes (john at integralsource.com)
+ * @version $Revision: 754830 $, $Date: 2009-03-16 00:26:44 -0700 (Mon, 16 Mar 2009) $
  * @since 1.0
  */
-public class OptionBuilder {
-
+public final class OptionBuilder
+{
     /** long option */
     private static String longopt;
 
@@ -115,14 +117,13 @@ public class OptionBuilder {
      */
     public static OptionBuilder hasArg(boolean hasArg)
     {
-        OptionBuilder.numberOfArgs = (hasArg == true) ? 1 : Option.UNINITIALIZED;
+        OptionBuilder.numberOfArgs = hasArg ? 1 : Option.UNINITIALIZED;
 
         return instance;
     }
 
     /**
-     * The next Option created will have the specified argument value 
-     * name.
+     * The next Option created will have the specified argument value name.
      *
      * @param name the name for the argument value
      * @return the OptionBuilder instance
@@ -221,8 +222,7 @@ public class OptionBuilder {
     }
 
     /**
-     * The next Option created can have <code>num</code> 
-     * argument values.
+     * The next Option created can have <code>num</code> argument values.
      *
      * @param num the number of args that the option can have
      * @return the OptionBuilder instance
@@ -248,8 +248,7 @@ public class OptionBuilder {
     }
 
     /**
-     * The next Option can have an unlimited number of
-     * optional arguments.
+     * The next Option can have an unlimited number of optional arguments.
      *
      * @return the OptionBuilder instance
      */
@@ -262,8 +261,7 @@ public class OptionBuilder {
     }
 
     /**
-     * The next Option can have the specified number of 
-     * optional arguments.
+     * The next Option can have the specified number of optional arguments.
      *
      * @param numArgs - the maximum number of optional arguments
      * the next Option created can have.
@@ -278,7 +276,7 @@ public class OptionBuilder {
     }
 
     /**
-     * The next Option created will have a value that will be an instance 
+     * The next Option created will have a value that will be an instance
      * of <code>type</code>.
      *
      * @param newType the type of the Options argument value
@@ -305,7 +303,7 @@ public class OptionBuilder {
     }
 
     /**
-     * Create an Option using the current settings and with 
+     * Create an Option using the current settings and with
      * the specified Option <code>char</code>.
      *
      * @param opt the character representation of the Option
@@ -313,8 +311,7 @@ public class OptionBuilder {
      * @throws IllegalArgumentException if <code>opt</code> is not
      * a valid character.  See Option.
      */
-    public static Option create(char opt)
-                         throws IllegalArgumentException
+    public static Option create(char opt) throws IllegalArgumentException
     {
         return create(String.valueOf(opt));
     }
@@ -323,14 +320,13 @@ public class OptionBuilder {
      * Create an Option using the current settings
      *
      * @return the Option instance
-     * @throws IllegalArgumentException if <code>longOpt</code> has
-     * not been set.  
+     * @throws IllegalArgumentException if <code>longOpt</code> has not been set.
      */
-    public static Option create()
-                         throws IllegalArgumentException
+    public static Option create() throws IllegalArgumentException
     {
         if (longopt == null)
         {
+            OptionBuilder.reset();
             throw new IllegalArgumentException("must specify longopt");
         }
 
@@ -338,36 +334,36 @@ public class OptionBuilder {
     }
 
     /**
-     * Create an Option using the current settings and with 
+     * Create an Option using the current settings and with
      * the specified Option <code>char</code>.
      *
-     * @param opt the <code>java.lang.String</code> representation 
+     * @param opt the <code>java.lang.String</code> representation
      * of the Option
      * @return the Option instance
      * @throws IllegalArgumentException if <code>opt</code> is not
      * a valid character.  See Option.
      */
-    public static Option create(String opt)
-                         throws IllegalArgumentException
+    public static Option create(String opt) throws IllegalArgumentException
     {
-        // create the option
-        Option option = new Option(opt, description);
-
-
-        // set the option properties
-        option.setLongOpt(longopt);
-        option.setRequired(required);
-        option.setOptionalArg(optionalArg);
-        option.setArgs(numberOfArgs);
-        option.setType(type);
-        option.setValueSeparator(valuesep);
-        option.setArgName(argName);
-
-
-        // reset the OptionBuilder properties
-        OptionBuilder.reset();
+        Option option = null;
+        try {
+            // create the option
+            option = new Option(opt, description);
+
+            // set the option properties
+            option.setLongOpt(longopt);
+            option.setRequired(required);
+            option.setOptionalArg(optionalArg);
+            option.setArgs(numberOfArgs);
+            option.setType(type);
+            option.setValueSeparator(valuesep);
+            option.setArgName(argName);
+        } finally {
+            // reset the OptionBuilder properties
+            OptionBuilder.reset();
+        }
 
         // return the Option instance
         return option;
     }
-}
\ No newline at end of file
+}
diff --git a/src/java/org/apache/commons/cli/OptionGroup.java b/src/java/org/apache/commons/cli/OptionGroup.java
index 675bcb1..28b6399 100644
--- a/src/java/org/apache/commons/cli/OptionGroup.java
+++ b/src/java/org/apache/commons/cli/OptionGroup.java
@@ -14,21 +14,27 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
+import java.io.Serializable;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Map;
 
 /**
  * A group of mutually exclusive options.
+ *
  * @author John Keyes ( john at integralsource.com )
- * @version $Revision: 542144 $
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
  */
-public class OptionGroup {
-
+public class OptionGroup implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+    
     /** hold the options */
-    private HashMap optionMap = new HashMap();
+    private Map optionMap = new HashMap();
 
     /** the name of the selected option */
     private String selected;
@@ -37,16 +43,16 @@ public class OptionGroup {
     private boolean required;
 
     /**
-     * add <code>opt</code> to this group
+     * Add the specified <code>Option</code> to this group.
      *
-     * @param opt the option to add to this group
-     * @return this option group with opt added
+     * @param option the option to add to this group
+     * @return this option group with the option added
      */
-    public OptionGroup addOption(Option opt)
+    public OptionGroup addOption(Option option)
     {
         // key   - option name
         // value - the option
-        optionMap.put(opt.getKey(), opt);
+        optionMap.put(option.getKey(), option);
 
         return this;
     }
@@ -71,26 +77,24 @@ public class OptionGroup {
     }
 
     /**
-     * set the selected option of this group to <code>name</code>.
-     * @param opt the option that is selected
+     * Set the selected option of this group to <code>name</code>.
+     *
+     * @param option the option that is selected
      * @throws AlreadySelectedException if an option from this group has 
      * already been selected.
      */
-    public void setSelected(Option opt)
-                     throws AlreadySelectedException
+    public void setSelected(Option option) throws AlreadySelectedException
     {
         // if no option has already been selected or the 
         // same option is being reselected then set the
         // selected member variable
-        if ((this.selected == null) || this.selected.equals(opt.getOpt()))
+        if (selected == null || selected.equals(option.getOpt()))
         {
-            this.selected = opt.getOpt();
+            selected = option.getOpt();
         }
         else
         {
-            throw new AlreadySelectedException("an option from this group has "
-                                               + "already been selected: '"
-                                               + selected + "'");
+            throw new AlreadySelectedException(this, option);
         }
     }
 
@@ -117,11 +121,12 @@ public class OptionGroup {
      */
     public boolean isRequired()
     {
-        return this.required;
+        return required;
     }
 
     /**
-     * <p>Returns the stringified version of this OptionGroup.</p>
+     * Returns the stringified version of this OptionGroup.
+     * 
      * @return the stringified representation of this group
      */
     public String toString()
@@ -160,4 +165,4 @@ public class OptionGroup {
 
         return buff.toString();
     }
-}
\ No newline at end of file
+}
diff --git a/src/java/org/apache/commons/cli/OptionValidator.java b/src/java/org/apache/commons/cli/OptionValidator.java
index 265a277..5e32e18 100644
--- a/src/java/org/apache/commons/cli/OptionValidator.java
+++ b/src/java/org/apache/commons/cli/OptionValidator.java
@@ -14,19 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
 /**
  * Validates an Option string.
  *
  * @author John Keyes ( john at integralsource.com )
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
+ * @since 1.1
  */
-public class OptionValidator {
-
+class OptionValidator
+{
     /**
-     * <p>Validates whether <code>opt</code> is a permissable Option
+     * Validates whether <code>opt</code> is a permissable Option
      * shortOpt.  The rules that specify if the <code>opt</code>
-     * is valid are:</p>
+     * is valid are:
+     *
      * <ul>
      *  <li><code>opt</code> is not NULL</li>
      *  <li>a single character <code>opt</code> that is either
@@ -38,8 +42,7 @@ public class OptionValidator {
      * @param opt The option string to validate
      * @throws IllegalArgumentException if the Option is not valid.
      */
-    static void validateOption(String opt)
-                        throws IllegalArgumentException
+    static void validateOption(String opt) throws IllegalArgumentException
     {
         // check that opt is not NULL
         if (opt == null)
@@ -54,8 +57,7 @@ public class OptionValidator {
 
             if (!isValidOpt(ch))
             {
-                throw new IllegalArgumentException("illegal option value '" + ch
-                                                   + "'");
+                throw new IllegalArgumentException("illegal option value '" + ch + "'");
             }
         }
 
@@ -68,28 +70,26 @@ public class OptionValidator {
             {
                 if (!isValidChar(chars[i]))
                 {
-                    throw new IllegalArgumentException(
-                            "opt contains illegal character value '" + chars[i]
-                            + "'");
+                    throw new IllegalArgumentException("opt contains illegal character value '" + chars[i] + "'");
                 }
             }
         }
     }
 
     /**
-     * <p>Returns whether the specified character is a valid Option.</p>
+     * Returns whether the specified character is a valid Option.
      *
      * @param c the option to validate
-     * @return true if <code>c</code> is a letter, ' ', '?' or '@', 
-     * otherwise false.
+     * @return true if <code>c</code> is a letter, ' ', '?' or '@',
+     *         otherwise false.
      */
     private static boolean isValidOpt(char c)
     {
-        return (isValidChar(c) || (c == ' ') || (c == '?') || c == '@');
+        return isValidChar(c) || c == ' ' || c == '?' || c == '@';
     }
 
     /**
-     * <p>Returns whether the specified character is a valid character.</p>
+     * Returns whether the specified character is a valid character.
      *
      * @param c the character to validate
      * @return true if <code>c</code> is a letter.
@@ -98,4 +98,4 @@ public class OptionValidator {
     {
         return Character.isJavaIdentifierPart(c);
     }
-}
\ No newline at end of file
+}
diff --git a/src/java/org/apache/commons/cli/Options.java b/src/java/org/apache/commons/cli/Options.java
index bec089c..0370be8 100644
--- a/src/java/org/apache/commons/cli/Options.java
+++ b/src/java/org/apache/commons/cli/Options.java
@@ -14,8 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -25,7 +27,8 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
-/** <p>Main entry-point into the library.</p>
+/**
+ * <p>Main entry-point into the library.</p>
  *
  * <p>Options represents a collection of {@link Option} objects, which
  * describe the possible options for a command-line.<p>
@@ -38,9 +41,11 @@ import java.util.Map;
  *
  * @author bob mcwhirter (bob @ werken.com)
  * @author <a href="mailto:jstrachan at apache.org">James Strachan</a>
- * @version $Revision: 542144 $
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
  */
-public class Options {
+public class Options implements Serializable
+{
+    private static final long serialVersionUID = 1L;
 
     /** a map of the options with the character key */
     private Map shortOpts = new HashMap();
@@ -54,13 +59,6 @@ public class Options {
     /** a map of the option groups */
     private Map optionGroups = new HashMap();
 
-    /** Construct a new Options descriptor
-     */
-    public Options()
-    {
-        // nothing to do
-    }
-
     /**
      * Add the specified option group.
      *
@@ -80,7 +78,6 @@ public class Options {
         {
             Option option = (Option) options.next();
 
-
             // an Option cannot be required if it is in an
             // OptionGroup, either the group is required or
             // nothing is required
@@ -92,16 +89,18 @@ public class Options {
 
         return this;
     }
-    
+
     /**
      * Lists the OptionGroups that are members of this Options instance.
+     *
      * @return a Collection of OptionGroup instances.
      */
-    Collection getOptionGroups(){
-    	return new HashSet(optionGroups.values());
+    Collection getOptionGroups()
+    {
+        return new HashSet(optionGroups.values());
     }
 
-    /** 
+    /**
      * Add an option that only contains a short-name.
      * It may be specified as requiring an argument.
      *
@@ -117,7 +116,7 @@ public class Options {
         return this;
     }
 
-    /** 
+    /**
      * Add an option that contains a short-name and a long-name.
      * It may be specified as requiring an argument.
      *
@@ -127,8 +126,7 @@ public class Options {
      * @param description Self-documenting description
      * @return the resulting Options instance
      */
-    public Options addOption(String opt, String longOpt, boolean hasArg, 
-                             String description)
+    public Options addOption(String opt, String longOpt, boolean hasArg, String description)
     {
         addOption(new Option(opt, longOpt, hasArg, description));
 
@@ -138,7 +136,7 @@ public class Options {
     /**
      * Adds an option instance
      *
-     * @param opt the option that is to be added 
+     * @param opt the option that is to be added
      * @return the resulting Options instance
      */
     public Options addOption(Option opt)
@@ -152,10 +150,11 @@ public class Options {
         }
 
         // if the option is required add it to the required list
-        if (opt.isRequired() ) 
+        if (opt.isRequired())
         {
-            if( requiredOpts.contains(key) ) {
-                requiredOpts.remove( requiredOpts.indexOf(key) );
+            if (requiredOpts.contains(key))
+            {
+                requiredOpts.remove(requiredOpts.indexOf(key));
             }
             requiredOpts.add(key);
         }
@@ -165,7 +164,7 @@ public class Options {
         return this;
     }
 
-    /** 
+    /**
      * Retrieve a read-only list of options in this set
      *
      * @return read-only Collection of {@link Option} objects in this descriptor
@@ -182,38 +181,22 @@ public class Options {
      */
     List helpOptions()
     {
-        List opts = new ArrayList(shortOpts.values());
-
-        // now look through the long opts to see if there are any Long-opt
-        // only options
-        Iterator iter = longOpts.values().iterator();
-
-        while (iter.hasNext())
-        {
-            Object item = iter.next();
-
-            if (!opts.contains(item))
-            {
-                opts.add(item);
-            }
-        }
-
-        return new ArrayList(opts);
+        return new ArrayList(shortOpts.values());
     }
 
-    /** 
-     * Returns the required options as a
-     * <code>java.util.Collection</code>.
+    /**
+     * Returns the required options.
      *
-     * @return Collection of required options
+     * @return List of required options
      */
     public List getRequiredOptions()
     {
         return requiredOpts;
     }
 
-    /** 
-     * Retrieve the named {@link Option}
+    /**
+     * Retrieve the {@link Option} matching the long or short name specified.
+     * The leading hyphens in the name are ignored (up to 2).
      *
      * @param opt short or long name of the {@link Option}
      * @return the option represented by opt
@@ -230,9 +213,8 @@ public class Options {
         return (Option) longOpts.get(opt);
     }
 
-    /** 
-     * Returns whether the named {@link Option} is a member
-     * of this {@link Options}.
+    /**
+     * Returns whether the named {@link Option} is a member of this {@link Options}.
      *
      * @param opt short or long name of the {@link Option}
      * @return true if the named {@link Option} is a member
@@ -245,9 +227,8 @@ public class Options {
         return shortOpts.containsKey(opt) || longOpts.containsKey(opt);
     }
 
-    /** 
-     * Returns the OptionGroup the <code>opt</code>
-     * belongs to.
+    /**
+     * Returns the OptionGroup the <code>opt</code> belongs to.
      * @param opt the option whose OptionGroup is being queried.
      *
      * @return the OptionGroup if <code>opt</code> is part
@@ -258,7 +239,7 @@ public class Options {
         return (OptionGroup) optionGroups.get(opt.getKey());
     }
 
-    /** 
+    /**
      * Dump state, suitable for debugging.
      *
      * @return Stringified form of this object
@@ -275,4 +256,4 @@ public class Options {
 
         return buf.toString();
     }
-}
\ No newline at end of file
+}
diff --git a/src/java/org/apache/commons/cli/ParseException.java b/src/java/org/apache/commons/cli/ParseException.java
index 7212e0f..cb13320 100644
--- a/src/java/org/apache/commons/cli/ParseException.java
+++ b/src/java/org/apache/commons/cli/ParseException.java
@@ -14,19 +14,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
-/** 
- * <p>Base for Exceptions thrown during parsing of a command-line.</p>
+/**
+ * Base for Exceptions thrown during parsing of a command-line.
  *
  * @author bob mcwhirter (bob @ werken.com)
- * @version $Revision: 542144 $
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
  */
-public class ParseException extends Exception {
-
-    /** 
-     * <p>Construct a new <code>ParseException</code> 
-     * with the specified detail message.</p>
+public class ParseException extends Exception
+{
+    /**
+     * Construct a new <code>ParseException</code>
+     * with the specified detail message.
      *
      * @param message the detail message
      */
@@ -34,4 +35,4 @@ public class ParseException extends Exception {
     {
         super(message);
     }
-}
\ No newline at end of file
+}
diff --git a/src/java/org/apache/commons/cli/Parser.java b/src/java/org/apache/commons/cli/Parser.java
index a3fe43e..d6826f5 100644
--- a/src/java/org/apache/commons/cli/Parser.java
+++ b/src/java/org/apache/commons/cli/Parser.java
@@ -14,8 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.Iterator;
@@ -24,16 +26,15 @@ import java.util.ListIterator;
 import java.util.Properties;
 
 /**
- * <p><code>Parser</code> creates {@link CommandLine}s.</p>
+ * <code>Parser</code> creates {@link CommandLine}s.
  *
  * @author John Keyes (john at integralsource.com)
- * @see Parser
- * @version $Revision: 551815 $
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
  */
-public abstract class Parser implements CommandLineParser {
-
+public abstract class Parser implements CommandLineParser
+{
     /** commandline instance */
-    private CommandLine cmd;
+    protected CommandLine cmd;
 
     /** current Options */
     private Options options;
@@ -41,23 +42,37 @@ public abstract class Parser implements CommandLineParser {
     /** list of required options strings */
     private List requiredOptions;
 
+    protected void setOptions(final Options options)
+    {
+        this.options = options;
+        this.requiredOptions = new ArrayList(options.getRequiredOptions());
+    }
+
+    protected Options getOptions()
+    {
+        return options;
+    }
+
+    protected List getRequiredOptions()
+    {
+        return requiredOptions;
+    }
+
     /**
-     * <p>Subclasses must implement this method to reduce
-     * the <code>arguments</code> that have been passed to the parse 
-     * method.</p>
+     * Subclasses must implement this method to reduce
+     * the <code>arguments</code> that have been passed to the parse method.
      *
      * @param opts The Options to parse the arguments by.
      * @param arguments The arguments that have to be flattened.
-     * @param stopAtNonOption specifies whether to stop 
+     * @param stopAtNonOption specifies whether to stop
      * flattening when a non option has been encountered
      * @return a String array of the flattened arguments
      */
-    protected abstract String[] flatten(Options opts, String[] arguments, 
-                                        boolean stopAtNonOption);
+    protected abstract String[] flatten(Options opts, String[] arguments, boolean stopAtNonOption);
 
     /**
-     * <p>Parses the specified <code>arguments</code> 
-     * based on the specifed {@link Options}.</p>
+     * Parses the specified <code>arguments</code> based
+     * on the specifed {@link Options}.
      *
      * @param options the <code>Options</code>
      * @param arguments the <code>arguments</code>
@@ -65,49 +80,41 @@ public abstract class Parser implements CommandLineParser {
      * @throws ParseException if an error occurs when parsing the
      * arguments.
      */
-    public CommandLine parse(Options options, String[] arguments)
-                      throws ParseException
+    public CommandLine parse(Options options, String[] arguments) throws ParseException
     {
         return parse(options, arguments, null, false);
     }
 
     /**
-     * Parse the arguments according to the specified options and
-     * properties.
+     * Parse the arguments according to the specified options and properties.
      *
-     * @param options the specified Options
-     * @param arguments the command line arguments
+     * @param options    the specified Options
+     * @param arguments  the command line arguments
      * @param properties command line option name-value pairs
      * @return the list of atomic option and value tokens
-     *
      * @throws ParseException if there are any problems encountered
-     * while parsing the command line tokens.
+     *                        while parsing the command line tokens.
+     *
+     * @since 1.1
      */
-    public CommandLine parse(Options options, String[] arguments, 
-                             Properties properties)
-        throws ParseException
+    public CommandLine parse(Options options, String[] arguments, Properties properties) throws ParseException
     {
         return parse(options, arguments, properties, false);
     }
 
     /**
-     * <p>Parses the specified <code>arguments</code> 
-     * based on the specifed {@link Options}.</p>
-     *
-     * @param options the <code>Options</code>
-     * @param arguments the <code>arguments</code>
-     * @param stopAtNonOption specifies whether to stop 
-     * interpreting the arguments when a non option has 
-     * been encountered and to add them to the CommandLines
-     * args list.
+     * Parses the specified <code>arguments</code>
+     * based on the specifed {@link Options}.
      *
+     * @param options         the <code>Options</code>
+     * @param arguments       the <code>arguments</code>
+     * @param stopAtNonOption specifies whether to stop interpreting the
+     *                        arguments when a non option has been encountered
+     *                        and to add them to the CommandLines args list.
      * @return the <code>CommandLine</code>
-     * @throws ParseException if an error occurs when parsing the
-     * arguments.
+     * @throws ParseException if an error occurs when parsing the arguments.
      */
-    public CommandLine parse(Options options, String[] arguments, 
-                             boolean stopAtNonOption)
-        throws ParseException
+    public CommandLine parse(Options options, String[] arguments, boolean stopAtNonOption) throws ParseException
     {
         return parse(options, arguments, null, stopAtNonOption);
     }
@@ -126,21 +133,22 @@ public abstract class Parser implements CommandLineParser {
      *
      * @throws ParseException if there are any problems encountered
      * while parsing the command line tokens.
+     *
+     * @since 1.1
      */
-    public CommandLine parse(Options options, String[] arguments, 
-                             Properties properties, boolean stopAtNonOption)
-        throws ParseException
+    public CommandLine parse(Options options, String[] arguments, Properties properties, boolean stopAtNonOption)
+            throws ParseException
     {
-        // initialise members
-        this.options = options;
-
         // clear out the data in options in case it's been used before (CLI-71)
-        for (Iterator it = options.helpOptions().iterator(); it.hasNext();) {
+        for (Iterator it = options.helpOptions().iterator(); it.hasNext();)
+        {
             Option opt = (Option) it.next();
             opt.clearValues();
         }
 
-        requiredOptions = options.getRequiredOptions();
+        // initialise members
+        setOptions(options);
+
         cmd = new CommandLine();
 
         boolean eatTheRest = false;
@@ -150,9 +158,7 @@ public abstract class Parser implements CommandLineParser {
             arguments = new String[0];
         }
 
-        List tokenList = Arrays.asList(flatten(this.options, 
-                                               arguments, 
-                                               stopAtNonOption));
+        List tokenList = Arrays.asList(flatten(getOptions(), arguments, stopAtNonOption));
 
         ListIterator iterator = tokenList.listIterator();
 
@@ -183,7 +189,7 @@ public abstract class Parser implements CommandLineParser {
             // the value is an option
             else if (t.startsWith("-"))
             {
-                if (stopAtNonOption && !options.hasOption(t))
+                if (stopAtNonOption && !getOptions().hasOption(t))
                 {
                     eatTheRest = true;
                     cmd.addArg(t);
@@ -228,12 +234,11 @@ public abstract class Parser implements CommandLineParser {
     }
 
     /**
-     * <p>Sets the values of Options using the values in 
-     * <code>properties</code>.</p>
+     * Sets the values of Options using the values in <code>properties</code>.
      *
      * @param properties The value properties to be processed.
      */
-    private void processProperties(Properties properties)
+    protected void processProperties(Properties properties)
     {
         if (properties == null)
         {
@@ -246,15 +251,14 @@ public abstract class Parser implements CommandLineParser {
 
             if (!cmd.hasOption(option))
             {
-                Option opt = options.getOption(option);
+                Option opt = getOptions().getOption(option);
 
                 // get the value from the properties instance
                 String value = properties.getProperty(option);
 
                 if (opt.hasArg())
                 {
-                    if ((opt.getValues() == null)
-                        || (opt.getValues().length == 0))
+                    if (opt.getValues() == null || opt.getValues().length == 0)
                     {
                         try
                         {
@@ -266,9 +270,9 @@ public abstract class Parser implements CommandLineParser {
                         }
                     }
                 }
-                else if (!("yes".equalsIgnoreCase(value) 
-                           || "true".equalsIgnoreCase(value)
-                           || "1".equalsIgnoreCase(value)))
+                else if (!("yes".equalsIgnoreCase(value)
+                        || "true".equalsIgnoreCase(value)
+                        || "1".equalsIgnoreCase(value)))
                 {
                     // if the value is not yes, true or 1 then don't add the
                     // option to the CommandLine
@@ -281,38 +285,24 @@ public abstract class Parser implements CommandLineParser {
     }
 
     /**
-     * <p>Throws a {@link MissingOptionException} if all of the
-     * required options are no present.</p>
+     * Throws a {@link MissingOptionException} if all of the required options
+     * are not present.
      *
      * @throws MissingOptionException if any of the required Options
      * are not present.
      */
-    private void checkRequiredOptions()
-        throws MissingOptionException
+    protected void checkRequiredOptions() throws MissingOptionException
     {
-        // if there are required options that have not been
-        // processsed
-        if (requiredOptions.size() > 0)
+        // if there are required options that have not been processsed
+        if (!getRequiredOptions().isEmpty())
         {
-            Iterator iter = requiredOptions.iterator();
-            StringBuffer buff = new StringBuffer("Missing required option");
-            buff.append(requiredOptions.size() == 1 ? "" : "s");
-            buff.append(": ");
-
-
-            // loop through the required options
-            while (iter.hasNext())
-            {
-                buff.append(iter.next());
-            }
-
-            throw new MissingOptionException(buff.toString());
+            throw new MissingOptionException(getRequiredOptions());
         }
     }
 
     /**
      * <p>Process the argument values for the specified Option
-     * <code>opt</code> using the values retrieved from the 
+     * <code>opt</code> using the values retrieved from the
      * specified iterator <code>iter</code>.
      *
      * @param opt The current Option
@@ -322,8 +312,7 @@ public abstract class Parser implements CommandLineParser {
      * @throws ParseException if an argument value is required
      * and it is has not been found.
      */
-    public void processArgs(Option opt, ListIterator iter)
-        throws ParseException
+    public void processArgs(Option opt, ListIterator iter) throws ParseException
     {
         // loop until an option is found
         while (iter.hasNext())
@@ -331,7 +320,7 @@ public abstract class Parser implements CommandLineParser {
             String str = (String) iter.next();
 
             // found an Option, not an argument
-            if (options.hasOption(str) && str.startsWith("-"))
+            if (getOptions().hasOption(str) && str.startsWith("-"))
             {
                 iter.previous();
                 break;
@@ -340,7 +329,7 @@ public abstract class Parser implements CommandLineParser {
             // found a value
             try
             {
-                opt.addValueForProcessing( Util.stripLeadingAndTrailingQuotes(str) );
+                opt.addValueForProcessing(Util.stripLeadingAndTrailingQuotes(str));
             }
             catch (RuntimeException exp)
             {
@@ -349,56 +338,50 @@ public abstract class Parser implements CommandLineParser {
             }
         }
 
-        if ((opt.getValues() == null) && !opt.hasOptionalArg())
+        if (opt.getValues() == null && !opt.hasOptionalArg())
         {
-            throw new MissingArgumentException("Missing argument for option:"
-                                               + opt.getKey());
+            throw new MissingArgumentException(opt);
         }
     }
 
     /**
-     * <p>Process the Option specified by <code>arg</code>
-     * using the values retrieved from the specfied iterator
-     * <code>iter</code>.
+     * Process the Option specified by <code>arg</code> using the values
+     * retrieved from the specfied iterator <code>iter</code>.
      *
      * @param arg The String value representing an Option
-     * @param iter The iterator over the flattened command 
-     * line arguments.
+     * @param iter The iterator over the flattened command line arguments.
      *
-     * @throws ParseException if <code>arg</code> does not
-     * represent an Option
+     * @throws ParseException if <code>arg</code> does not represent an Option
      */
-    private void processOption(String arg, ListIterator iter)
-        throws ParseException
+    protected void processOption(String arg, ListIterator iter) throws ParseException
     {
-        boolean hasOption = options.hasOption(arg);
+        boolean hasOption = getOptions().hasOption(arg);
 
         // if there is no option throw an UnrecognisedOptionException
         if (!hasOption)
         {
-            throw new UnrecognizedOptionException("Unrecognized option: " 
-                                                  + arg);
+            throw new UnrecognizedOptionException("Unrecognized option: " + arg, arg);
         }
-        
+
         // get the option represented by arg
-        final Option opt = options.getOption(arg);
+        Option opt = (Option) getOptions().getOption(arg).clone();
 
         // if the option is a required option remove the option from
         // the requiredOptions list
         if (opt.isRequired())
         {
-            requiredOptions.remove(opt.getKey());
+            getRequiredOptions().remove(opt.getKey());
         }
 
         // if the option is in an OptionGroup make that option the selected
         // option of the group
-        if (options.getOptionGroup(opt) != null)
+        if (getOptions().getOptionGroup(opt) != null)
         {
-            OptionGroup group = options.getOptionGroup(opt);
+            OptionGroup group = getOptions().getOptionGroup(opt);
 
             if (group.isRequired())
             {
-                requiredOptions.remove(group);
+                getRequiredOptions().remove(group);
             }
 
             group.setSelected(opt);
@@ -410,7 +393,6 @@ public abstract class Parser implements CommandLineParser {
             processArgs(opt, iter);
         }
 
-
         // set the option on the command line
         cmd.addOption(opt);
     }
diff --git a/src/java/org/apache/commons/cli/PatternOptionBuilder.java b/src/java/org/apache/commons/cli/PatternOptionBuilder.java
index 893e73d..6176027 100644
--- a/src/java/org/apache/commons/cli/PatternOptionBuilder.java
+++ b/src/java/org/apache/commons/cli/PatternOptionBuilder.java
@@ -14,9 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
-/** 
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.Date;
+
+/**
  * <p>
  * Allows Options to be created from a single String.
  * The pattern contains various single character flags and via
@@ -35,141 +41,123 @@ package org.apache.commons.cli;
  *
  * <p>
  * For example, the following allows command line flags of '-v -p string-value -f /dir/file'.
+ * The exclamation mark precede a mandatory option.
  * </p>
- * <code>Options options = PatternOptionBuilder.parsePattern("vp:f/");</code>
+ * <code>Options options = PatternOptionBuilder.parsePattern("vp:!f/");</code>
  *
  * <p>
- * TODO These need to break out to OptionType and also 
+ * TODO These need to break out to OptionType and also
  * to be pluggable.
  * </p>
  *
- * @author Henri Yandell (bayard @ generationjava.com)
- * @version $Revision: 542144 $
+ * @version $Revision: 734339 $, $Date: 2009-01-13 21:56:47 -0800 (Tue, 13 Jan 2009) $
  */
-public class PatternOptionBuilder {
-
+public class PatternOptionBuilder
+{
     /** String class */
-    public static final Class STRING_VALUE = java.lang.String.class;
+    public static final Class STRING_VALUE = String.class;
 
     /** Object class */
-    public static final Class OBJECT_VALUE = java.lang.Object.class;
+    public static final Class OBJECT_VALUE = Object.class;
 
     /** Number class */
-    public static final Class NUMBER_VALUE = java.lang.Number.class;
+    public static final Class NUMBER_VALUE = Number.class;
 
     /** Date class */
-    public static final Class DATE_VALUE = java.util.Date.class;
+    public static final Class DATE_VALUE = Date.class;
 
     /** Class class */
-    public static final Class CLASS_VALUE = java.lang.Class.class;
+    public static final Class CLASS_VALUE = Class.class;
 
-    /// can we do this one?? 
+    /// can we do this one??
     // is meant to check that the file exists, else it errors.
     // ie) it's for reading not writing.
 
     /** FileInputStream class */
-    public static final Class EXISTING_FILE_VALUE = 
-            java.io.FileInputStream.class;
+    public static final Class EXISTING_FILE_VALUE = FileInputStream.class;
 
     /** File class */
-    public static final Class FILE_VALUE = java.io.File.class;
+    public static final Class FILE_VALUE = File.class;
 
     /** File array class */
-    public static final Class FILES_VALUE = java.io.File[].class;
+    public static final Class FILES_VALUE = File[].class;
 
     /** URL class */
-    public static final Class URL_VALUE = java.net.URL.class;
+    public static final Class URL_VALUE = URL.class;
 
     /**
-     * <p>Retrieve the class that <code>ch</code> represents.</p>
+     * Retrieve the class that <code>ch</code> represents.
      *
      * @param ch the specified character
      * @return The class that <code>ch</code> represents
      */
     public static Object getValueClass(char ch)
     {
-        if (ch == '@')
-        {
-            return PatternOptionBuilder.OBJECT_VALUE;
-        }
-        else if (ch == ':')
-        {
-            return PatternOptionBuilder.STRING_VALUE;
-        }
-        else if (ch == '%')
-        {
-            return PatternOptionBuilder.NUMBER_VALUE;
-        }
-        else if (ch == '+')
-        {
-            return PatternOptionBuilder.CLASS_VALUE;
-        }
-        else if (ch == '#')
-        {
-            return PatternOptionBuilder.DATE_VALUE;
-        }
-        else if (ch == '<')
+        switch (ch)
         {
-            return PatternOptionBuilder.EXISTING_FILE_VALUE;
-        }
-        else if (ch == '>')
-        {
-            return PatternOptionBuilder.FILE_VALUE;
-        }
-        else if (ch == '*')
-        {
-            return PatternOptionBuilder.FILES_VALUE;
-        }
-        else if (ch == '/')
-        {
-            return PatternOptionBuilder.URL_VALUE;
+            case '@':
+                return PatternOptionBuilder.OBJECT_VALUE;
+            case ':':
+                return PatternOptionBuilder.STRING_VALUE;
+            case '%':
+                return PatternOptionBuilder.NUMBER_VALUE;
+            case '+':
+                return PatternOptionBuilder.CLASS_VALUE;
+            case '#':
+                return PatternOptionBuilder.DATE_VALUE;
+            case '<':
+                return PatternOptionBuilder.EXISTING_FILE_VALUE;
+            case '>':
+                return PatternOptionBuilder.FILE_VALUE;
+            case '*':
+                return PatternOptionBuilder.FILES_VALUE;
+            case '/':
+                return PatternOptionBuilder.URL_VALUE;
         }
 
         return null;
     }
 
     /**
-     * <p>Returns whether <code>ch</code> is a value code, i.e.
-     * whether it represents a class in a pattern.</p>
-     * 
+     * Returns whether <code>ch</code> is a value code, i.e.
+     * whether it represents a class in a pattern.
+     *
      * @param ch the specified character
      * @return true if <code>ch</code> is a value code, otherwise false.
      */
     public static boolean isValueCode(char ch)
     {
-        if ((ch != '@') && (ch != ':') && (ch != '%') && (ch != '+')
-            && (ch != '#') && (ch != '<') && (ch != '>') && (ch != '*')
-            && (ch != '/') && (ch != '!'))
-        {
-            return false;
-        }
-
-        return true;
+        return ch == '@'
+                || ch == ':'
+                || ch == '%'
+                || ch == '+'
+                || ch == '#'
+                || ch == '<'
+                || ch == '>'
+                || ch == '*'
+                || ch == '/'
+                || ch == '!';
     }
 
     /**
-     * <p>Returns the {@link Options} instance represented by 
-     * <code>pattern</code>.</p>
+     * Returns the {@link Options} instance represented by <code>pattern</code>.
      *
      * @param pattern the pattern string
      * @return The {@link Options} instance
      */
     public static Options parsePattern(String pattern)
     {
-        int sz = pattern.length();
-
         char opt = ' ';
-        char ch = ' ';
         boolean required = false;
         Object type = null;
 
         Options options = new Options();
 
-        for (int i = 0; i < sz; i++)
+        for (int i = 0; i < pattern.length(); i++)
         {
-            ch = pattern.charAt(i);
+            char ch = pattern.charAt(i);
 
-            // a value code comes after an option and specifies 
+            // a value code comes after an option and specifies
             // details about it
             if (!isValueCode(ch))
             {
@@ -178,7 +166,7 @@ public class PatternOptionBuilder {
                     OptionBuilder.hasArg(type != null);
                     OptionBuilder.isRequired(required);
                     OptionBuilder.withType(type);
-                    
+
                     // we have a previous one to deal with
                     options.addOption(OptionBuilder.create(opt));
                     required = false;
@@ -203,7 +191,7 @@ public class PatternOptionBuilder {
             OptionBuilder.hasArg(type != null);
             OptionBuilder.isRequired(required);
             OptionBuilder.withType(type);
-            
+
             // we have a final one to deal with
             options.addOption(OptionBuilder.create(opt));
         }
diff --git a/src/java/org/apache/commons/cli/PosixParser.java b/src/java/org/apache/commons/cli/PosixParser.java
index 3f91680..d384b23 100644
--- a/src/java/org/apache/commons/cli/PosixParser.java
+++ b/src/java/org/apache/commons/cli/PosixParser.java
@@ -14,24 +14,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
+import java.util.List;
 
 /**
- * The class PosixParser provides an implementation of the 
+ * The class PosixParser provides an implementation of the
  * {@link Parser#flatten(Options,String[],boolean) flatten} method.
  *
  * @author John Keyes (john at integralsource.com)
- * @see Parser
- * @version $Revision: 542151 $
+ * @version $Revision: 695760 $, $Date: 2008-09-16 01:05:03 -0700 (Tue, 16 Sep 2008) $
  */
-public class PosixParser extends Parser {
-
+public class PosixParser extends Parser
+{
     /** holder for flattened tokens */
-    private ArrayList tokens = new ArrayList();
+    private List tokens = new ArrayList();
 
     /** specifies if bursting should continue */
     private boolean eatTheRest;
@@ -43,15 +44,14 @@ public class PosixParser extends Parser {
     private Options options;
 
     /**
-     * <p>Resets the members to their original state i.e. remove
-     * all of <code>tokens</code> entries, set <code>eatTheRest</code>
-     * to false and set <code>currentOption</code> to null.</p>
+     * Resets the members to their original state i.e. remove
+     * all of <code>tokens</code> entries and set <code>eatTheRest</code>
+     * to false.
      */
     private void init()
     {
         eatTheRest = false;
         tokens.clear();
-        currentOption = null;
     }
 
     /**
@@ -73,14 +73,14 @@ public class PosixParser extends Parser {
      *  is a valid {@link Option} id.  If it is a valid id, then add the
      *  entry to the list of processed tokens and set the current {@link Option}
      *  member.  If it is not a valid id and <code>stopAtNonOption</code>
-     *  is true, then the remaining entries are copied to the list of 
+     *  is true, then the remaining entries are copied to the list of
      *  processed tokens.  Otherwise, the current entry is ignored.</li>
      *  <li>if the current <code>arguments</code> entry is more than two
      *  characters in length and the first character is "<b>-</b>" then
      *  we need to burst the entry to determine its constituents.  For more
-     *  information on the bursting algorithm see 
+     *  information on the bursting algorithm see
      *  {@link PosixParser#burstToken(String, boolean) burstToken}.</li>
-     *  <li>if the current <code>arguments</code> entry is not handled 
+     *  <li>if the current <code>arguments</code> entry is not handled
      *  by any of the previous rules, then the entry is added to the list
      *  of processed tokens.</li>
      * </ol>
@@ -92,53 +92,53 @@ public class PosixParser extends Parser {
      * when an non option is found.
      * @return The flattened <code>arguments</code> String array.
      */
-    protected String[] flatten(Options options, String[] arguments, 
-                               boolean stopAtNonOption)
+    protected String[] flatten(Options options, String[] arguments, boolean stopAtNonOption)
     {
         init();
         this.options = options;
 
         // an iterator for the command line tokens
         Iterator iter = Arrays.asList(arguments).iterator();
-        String token;
 
         // process each command line token
         while (iter.hasNext())
         {
             // get the next command line token
-            token = (String) iter.next();
+            String token = (String) iter.next();
 
-            // handle SPECIAL TOKEN
+            // handle long option --foo or --foo=bar
             if (token.startsWith("--"))
             {
-                if (token.indexOf('=') != -1)
+                int pos = token.indexOf('=');
+                String opt = pos == -1 ? token : token.substring(0, pos); // --foo
+
+                if (!options.hasOption(opt))
                 {
-                    tokens.add(token.substring(0, token.indexOf('=')));
-                    tokens.add(token.substring(token.indexOf('=') + 1, 
-                                               token.length()));
+                    processNonOptionToken(token, stopAtNonOption);
                 }
                 else
                 {
-                    tokens.add(token);
+                    currentOption = options.getOption(opt);
+                    
+                    tokens.add(opt);
+                    if (pos != -1)
+                    {
+                        tokens.add(token.substring(pos + 1));
+                    }
                 }
             }
 
             // single hyphen
             else if ("-".equals(token))
             {
-                processSingleHyphen(token);
+                tokens.add(token);
             }
             else if (token.startsWith("-"))
             {
-                int tokenLength = token.length();
-
-                if (tokenLength == 2)
+                if (token.length() == 2 || options.hasOption(token))
                 {
                     processOptionToken(token, stopAtNonOption);
                 }
-                else if (options.hasOption(token)) {
-                	tokens.add(token);
-                }
                 // requires bursting
                 else
                 {
@@ -147,14 +147,7 @@ public class PosixParser extends Parser {
             }
             else
             {
-                if (stopAtNonOption)
-                {
-                    process(token);
-                }
-                else
-                {
-                    tokens.add(token);
-                }
+                processNonOptionToken(token, stopAtNonOption);
             }
 
             gobble(iter);
@@ -164,7 +157,7 @@ public class PosixParser extends Parser {
     }
 
     /**
-     * <p>Adds the remaining tokens to the processed tokens list.</p>
+     * Adds the remaining tokens to the processed tokens list.
      *
      * @param iter An iterator over the remaining tokens
      */
@@ -180,58 +173,30 @@ public class PosixParser extends Parser {
     }
 
     /**
-     * <p>If there is a current option and it can have an argument
-     * value then add the token to the processed tokens list and 
-     * set the current option to null.</p>
-     * <p>If there is a current option and it can have argument
-     * values then add the token to the processed tokens list.</p>
-     * <p>If there is not a current option add the special token
-     * "<b>--</b>" and the current <code>value</code> to the processed
-     * tokens list.  The add all the remaining <code>argument</code>
-     * values to the processed tokens list.</p>
+     * Add the special token "<b>--</b>" and the current <code>value</code>
+     * to the processed tokens list. Then add all the remaining
+     * <code>argument</code> values to the processed tokens list.
      *
      * @param value The current token
      */
-    private void process(String value)
+    private void processNonOptionToken(String value, boolean stopAtNonOption)
     {
-        if ((currentOption != null) && currentOption.hasArg())
-        {
-            if (currentOption.hasArg())
-            {
-                tokens.add(value);
-                currentOption = null;
-            }
-            else if (currentOption.hasArgs())
-            {
-                tokens.add(value);
-            }
-        }
-        else
+        if (stopAtNonOption && (currentOption == null || !currentOption.hasArg()))
         {
             eatTheRest = true;
             tokens.add("--");
-            tokens.add(value);
         }
-    }
 
-    /**
-     * <p>If it is a hyphen then add the hyphen directly to
-     * the processed tokens list.</p>
-     *
-     * @param hyphen The hyphen token
-     */
-    private void processSingleHyphen(String hyphen)
-    {
-        tokens.add(hyphen);
+        tokens.add(value);
     }
 
     /**
      * <p>If an {@link Option} exists for <code>token</code> then
-     * set the current option and add the token to the processed 
-     * list.</p>
+     * add the token to the processed list.</p>
+     *
      * <p>If an {@link Option} does not exist and <code>stopAtNonOption</code>
-     * is set then ignore the current token and add the remaining tokens
-     * to the processed tokens list directly.</p>
+     * is set then add the remaining tokens to the processed tokens list
+     * directly.</p>
      *
      * @param token The current option token
      * @param stopAtNonOption Specifies whether flattening should halt
@@ -239,38 +204,40 @@ public class PosixParser extends Parser {
      */
     private void processOptionToken(String token, boolean stopAtNonOption)
     {
-        if (this.options.hasOption(token))
+        if (stopAtNonOption && !options.hasOption(token))
         {
-            currentOption = this.options.getOption(token);
-            tokens.add(token);
+            eatTheRest = true;
         }
-        else if (stopAtNonOption)
+
+        if (options.hasOption(token))
         {
-            eatTheRest = true;
+            currentOption = options.getOption(token);
         }
+
+        tokens.add(token);
     }
 
     /**
-     * <p>Breaks <code>token</code> into its constituent parts
+     * Breaks <code>token</code> into its constituent parts
      * using the following algorithm.
+     *
      * <ul>
      *  <li>ignore the first character ("<b>-</b>")</li>
      *  <li>foreach remaining character check if an {@link Option}
      *  exists with that id.</li>
      *  <li>if an {@link Option} does exist then add that character
      *  prepended with "<b>-</b>" to the list of processed tokens.</li>
-     *  <li>if the {@link Option} can have an argument value and there 
-     *  are remaining characters in the token then add the remaining 
+     *  <li>if the {@link Option} can have an argument value and there
+     *  are remaining characters in the token then add the remaining
      *  characters as a token to the list of processed tokens.</li>
-     *  <li>if an {@link Option} does <b>NOT</b> exist <b>AND</b> 
+     *  <li>if an {@link Option} does <b>NOT</b> exist <b>AND</b>
      *  <code>stopAtNonOption</code> <b>IS</b> set then add the special token
-     *  "<b>--</b>" followed by the remaining characters and also 
+     *  "<b>--</b>" followed by the remaining characters and also
      *  the remaining tokens directly to the processed tokens list.</li>
      *  <li>if an {@link Option} does <b>NOT</b> exist <b>AND</b>
      *  <code>stopAtNonOption</code> <b>IS NOT</b> set then add that
      *  character prepended with "<b>-</b>".</li>
      * </ul>
-     * </p>
      *
      * @param token The current token to be <b>burst</b>
      * @param stopAtNonOption Specifies whether to stop processing
@@ -278,14 +245,11 @@ public class PosixParser extends Parser {
      */
     protected void burstToken(String token, boolean stopAtNonOption)
     {
-        int tokenLength = token.length();
-
-        for (int i = 1; i < tokenLength; i++)
+        for (int i = 1; i < token.length(); i++)
         {
             String ch = String.valueOf(token.charAt(i));
-            boolean hasOption = options.hasOption(ch);
 
-            if (hasOption)
+            if (options.hasOption(ch))
             {
                 tokens.add("-" + ch);
                 currentOption = options.getOption(ch);
@@ -299,7 +263,8 @@ public class PosixParser extends Parser {
             }
             else if (stopAtNonOption)
             {
-                process(token.substring(i));
+                processNonOptionToken(token.substring(i), true);
+                break;
             }
             else
             {
diff --git a/src/java/org/apache/commons/cli/TypeHandler.java b/src/java/org/apache/commons/cli/TypeHandler.java
index c6b3728..5289b82 100644
--- a/src/java/org/apache/commons/cli/TypeHandler.java
+++ b/src/java/org/apache/commons/cli/TypeHandler.java
@@ -1,4 +1,4 @@
-/*
+/**
  * 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.
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
 import java.io.File;
@@ -24,19 +25,18 @@ import java.net.URL;
 import java.util.Date;
 
 /**
-  * This is a temporary implementation. TypeHandler will handle the 
-  * pluggableness of OptionTypes and it will direct all of these types 
-  * of conversion functionalities to ConvertUtils component in Commons 
-  * alreayd. BeanUtils I think.
+  * This is a temporary implementation. TypeHandler will handle the
+  * pluggableness of OptionTypes and it will direct all of these types
+  * of conversion functionalities to ConvertUtils component in Commons
+  * already. BeanUtils I think.
   *
-  * @author Henri Yandell (bayard @ generationjava.com)
-  * @version $Revision: 542151 $
+  * @version $Revision: 741425 $, $Date: 2009-02-05 22:10:54 -0800 (Thu, 05 Feb 2009) $
   */
-public class TypeHandler {
-
+public class TypeHandler
+{
     /**
-     * <p>Returns the <code>Object</code> of type <code>obj</code>
-     * with the value of <code>str</code>.</p>
+     * Returns the <code>Object</code> of type <code>obj</code>
+     * with the value of <code>str</code>.
      *
      * @param str the command line value
      * @param obj the type of argument
@@ -44,13 +44,14 @@ public class TypeHandler {
      * the value of <code>str</code>.
      */
     public static Object createValue(String str, Object obj)
+    throws ParseException
     {
         return createValue(str, (Class) obj);
     }
 
     /**
-     * <p>Returns the <code>Object</code> of type <code>clazz</code>
-     * with the value of <code>str</code>.</p>
+     * Returns the <code>Object</code> of type <code>clazz</code>
+     * with the value of <code>str</code>.
      *
      * @param str the command line value
      * @param clazz the type of argument
@@ -58,6 +59,7 @@ public class TypeHandler {
      * the value of <code>str</code>.
      */
     public static Object createValue(String str, Class clazz)
+    throws ParseException
     {
         if (PatternOptionBuilder.STRING_VALUE == clazz)
         {
@@ -102,25 +104,24 @@ public class TypeHandler {
     }
 
     /**
-      * <p>Create an Object from the classname and empty constructor.</p>
+      * Create an Object from the classname and empty constructor.
       *
-      * @param str the argument value
-      * @return the initialised object, or null if it couldn't create 
+      * @param classname the argument value
+      * @return the initialised object, or null if it couldn't create
       * the Object.
       */
-    public static Object createObject(String str)
+    public static Object createObject(String classname)
+    throws ParseException
     {
         Class cl = null;
 
         try
         {
-            cl = Class.forName(str);
+            cl = Class.forName(classname);
         }
         catch (ClassNotFoundException cnfe)
         {
-            System.err.println("Unable to find: " + str);
-
-            return null;
+            throw new ParseException("Unable to find the class: " + classname);
         }
 
         Object instance = null;
@@ -129,130 +130,117 @@ public class TypeHandler {
         {
             instance = cl.newInstance();
         }
-        catch (InstantiationException cnfe)
+        catch (Exception e)
         {
-            System.err.println("InstantiationException; Unable to create: "
-                               + str);
-
-            return null;
-        }
-        catch (IllegalAccessException cnfe)
-        {
-            System.err.println("IllegalAccessException; Unable to create: "
-                               + str);
-
-            return null;
+            throw new ParseException(e.getClass().getName() + "; Unable to create an instance of: " + classname);
         }
 
         return instance;
     }
 
     /**
-     * <p>Create a number from a String. If a . is present, it creates a 
-     *    Double, otherwise a Long. </p>
+     * Create a number from a String. If a . is present, it creates a
+     * Double, otherwise a Long.
      *
      * @param str the value
      * @return the number represented by <code>str</code>, if <code>str</code>
      * is not a number, null is returned.
      */
     public static Number createNumber(String str)
+    throws ParseException
     {
         try
         {
-            if( str != null )
+            if (str.indexOf('.') != -1)
+            {
+                return Double.valueOf(str);
+            }
+            else
             {
-                if( str.indexOf('.') != -1 )
-                {
-                    return Double.valueOf(str);
-                }
-                else
-                {
-                    return Long.valueOf(str);
-                }
+                return Long.valueOf(str);
             }
         }
-        catch (NumberFormatException nfe)
+        catch (NumberFormatException e)
         {
-            System.err.println(nfe.getMessage());
+            throw new ParseException(e.getMessage());
         }
-
-        return null;
     }
 
     /**
-     * <p>Returns the class whose name is <code>str</code>.</p>
+     * Returns the class whose name is <code>classname</code>.
      *
-     * @param str the class name
+     * @param classname the class name
      * @return The class if it is found, otherwise return null
      */
-    public static Class createClass(String str)
+    public static Class createClass(String classname)
+    throws ParseException
     {
         try
         {
-            return Class.forName(str);
+            return Class.forName(classname);
         }
-        catch (ClassNotFoundException cnfe)
+        catch (ClassNotFoundException e)
         {
-            System.err.println("Unable to find: " + str);
-
-            return null;
+            throw new ParseException("Unable to find the class: " + classname);
         }
     }
 
     /**
-     * <p>Returns the date represented by <code>str</code>.</p>
+     * Returns the date represented by <code>str</code>.
      *
      * @param str the date string
      * @return The date if <code>str</code> is a valid date string,
      * otherwise return null.
      */
     public static Date createDate(String str)
+    throws ParseException
     {
         throw new UnsupportedOperationException("Not yet implemented");
     }
 
     /**
-     * <p>Returns the URL represented by <code>str</code>.</p>
+     * Returns the URL represented by <code>str</code>.
      *
      * @param str the URL string
      * @return The URL is <code>str</code> is well-formed, otherwise
      * return null.
      */
     public static URL createURL(String str)
+    throws ParseException
     {
         try
         {
             return new URL(str);
         }
-        catch (MalformedURLException mue)
+        catch (MalformedURLException e)
         {
-            System.err.println("Unable to parse: " + str);
-
-            return null;
+            throw new ParseException("Unable to parse the URL: " + str);
         }
     }
 
     /**
-     * <p>Returns the File represented by <code>str</code>.</p>
+     * Returns the File represented by <code>str</code>.
      *
      * @param str the File location
      * @return The file represented by <code>str</code>.
      */
     public static File createFile(String str)
+    throws ParseException
     {
         return new File(str);
     }
 
     /**
-     * <p>Returns the File[] represented by <code>str</code>.</p>
+     * Returns the File[] represented by <code>str</code>.
      *
      * @param str the paths to the files
      * @return The File[] represented by <code>str</code>.
      */
     public static File[] createFiles(String str)
+    throws ParseException
     {
         // to implement/port:
         //        return FileW.findFiles(str);
-        return null;
+        throw new UnsupportedOperationException("Not yet implemented");
     }
 }
diff --git a/src/java/org/apache/commons/cli/UnrecognizedOptionException.java b/src/java/org/apache/commons/cli/UnrecognizedOptionException.java
index e7d5d35..d06b05f 100644
--- a/src/java/org/apache/commons/cli/UnrecognizedOptionException.java
+++ b/src/java/org/apache/commons/cli/UnrecognizedOptionException.java
@@ -14,21 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
-/** 
- * <p>Exception thrown during parsing signalling an unrecognized
- * option was seen.<p>
+/**
+ * Exception thrown during parsing signalling an unrecognized
+ * option was seen.
  *
  * @author bob mcwhiter (bob @ werken.com)
- * @version $Revision: 542144 $
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
  */
-public class UnrecognizedOptionException
-    extends ParseException {
+public class UnrecognizedOptionException extends ParseException
+{
+    /** The  unrecognized option */
+    private String option;
 
-    /** 
-     * <p>Construct a new <code>UnrecognizedArgumentException</code> 
-     * with the specified detail message.</p>
+    /**
+     * Construct a new <code>UnrecognizedArgumentException</code>
+     * with the specified detail message.
      *
      * @param message the detail message
      */
@@ -36,4 +39,29 @@ public class UnrecognizedOptionException
     {
         super(message);
     }
-}
\ No newline at end of file
+
+    /**
+     * Construct a new <code>UnrecognizedArgumentException</code>
+     * with the specified option and detail message.
+     *
+     * @param message the detail message
+     * @param option  the unrecognized option
+     * @since 1.2
+     */
+    public UnrecognizedOptionException(String message, String option)
+    {
+        this(message);
+        this.option = option;
+    }
+
+    /**
+     * Returns the unrecognized option.
+     *
+     * @return the related option
+     * @since 1.2
+     */
+    public String getOption()
+    {
+        return option;
+    }
+}
diff --git a/src/java/org/apache/commons/cli/Util.java b/src/java/org/apache/commons/cli/Util.java
index 94e97e3..4efa307 100644
--- a/src/java/org/apache/commons/cli/Util.java
+++ b/src/java/org/apache/commons/cli/Util.java
@@ -14,18 +14,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
 /**
  * Contains useful helper methods for classes within this package.
  *
  * @author John Keyes (john at integralsource.com)
+ * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
  */
-class Util {
-
+class Util
+{
     /**
-     * <p>Remove the hyphens from the begining of <code>str</code> and
-     * return the new String.</p>
+     * Remove the hyphens from the begining of <code>str</code> and
+     * return the new String.
      *
      * @param str The string from which the hyphens should be removed.
      *
@@ -33,7 +35,8 @@ class Util {
      */
     static String stripLeadingHyphens(String str)
     {
-        if (str == null) {
+        if (str == null)
+        {
             return null;
         }
         if (str.startsWith("--"))
@@ -59,12 +62,14 @@ class Util {
      */
     static String stripLeadingAndTrailingQuotes(String str)
     {
-        if (str.startsWith("\"")) {
+        if (str.startsWith("\""))
+        {
             str = str.substring(1, str.length());
         }
-        if (str.endsWith("\"")) {
-            str = str.substring(0, str.length()-1);
+        if (str.endsWith("\""))
+        {
+            str = str.substring(0, str.length() - 1);
         }
         return str;
     }
-}
\ No newline at end of file
+}
diff --git a/src/java/org/apache/commons/cli/overview.html b/src/java/org/apache/commons/cli/overview.html
index eadba1e..eec9ce7 100644
--- a/src/java/org/apache/commons/cli/overview.html
+++ b/src/java/org/apache/commons/cli/overview.html
@@ -1,28 +1,43 @@
+<!--
+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.
+-->
 <body>
- 
-    <p>Commons CLI -- version ##VERSION## (##QUALITY##)</p>
-
-	<p>The commons-cli package aides in parsing command-line arguments.</p>
-
-	<p>Allow command-line arguments to be parsed against a descriptor of
-	valid options (long and short), potentially with arguments.</p>
-
-	<p>command-line arguments may be of the typical <code>String[]</code>
-	form, but also may be a <code>java.util.List</code>.  Indexes allow
-	for parsing only a portion of the command-line.  Also, functionality
-	for parsing the command-line in phases is built in, allowing for
-	'cvs-style' command-lines, where some global options are specified
-	before a 'command' argument, and command-specific options are
-	specified after the command argument:
-	
-	<code>
-	<pre>
-		myApp -p <port> command -p <printer>
-	</pre>
-	</code>
-	
-
-	<p>The homepage for the project is
-	<a href="http://jakarta.apache.org/commons/">jakarta commons/</a>
+
+    <p>Commons CLI -- version 1.2</p>
+
+    <p>The commons-cli package aides in parsing command-line arguments.</p>
+
+    <p>Allow command-line arguments to be parsed against a descriptor of
+    valid options (long and short), potentially with arguments.</p>
+
+    <p>command-line arguments may be of the typical <code>String[]</code>
+    form, but also may be a <code>java.util.List</code>.  Indexes allow
+    for parsing only a portion of the command-line.  Also, functionality
+    for parsing the command-line in phases is built in, allowing for
+    'cvs-style' command-lines, where some global options are specified
+    before a 'command' argument, and command-specific options are
+    specified after the command argument:
+
+    <code>
+    <pre>
+        myApp -p <port> command -p <printer>
+    </pre>
+    </code>
+
+
+    <p>The homepage for the project is
+    <a href="http://commons.apache.org">Apache Commons/</a>
 </body>
diff --git a/src/java/org/apache/commons/cli/package.html b/src/java/org/apache/commons/cli/package.html
index 5bf2066..20ebdde 100644
--- a/src/java/org/apache/commons/cli/package.html
+++ b/src/java/org/apache/commons/cli/package.html
@@ -1,6 +1,21 @@
+<!--
+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.
+-->
 <body>
 
-    Commons CLI 1.0
+    Commons CLI 1.2
 
 </body>
diff --git a/src/test/data/.hidden.txt b/src/test/data/.hidden.txt
deleted file mode 100644
index d18fa71..0000000
--- a/src/test/data/.hidden.txt
+++ /dev/null
@@ -1 +0,0 @@
-Hidden text file.
diff --git a/src/test/data/readable.txt b/src/test/data/readable.txt
deleted file mode 100644
index cada839..0000000
--- a/src/test/data/readable.txt
+++ /dev/null
@@ -1 +0,0 @@
-Readable text file.
diff --git a/src/test/data/writable.txt b/src/test/data/writable.txt
deleted file mode 100644
index 53f7f5d..0000000
--- a/src/test/data/writable.txt
+++ /dev/null
@@ -1 +0,0 @@
-Writable text file.
diff --git a/src/test/org/apache/commons/cli/ApplicationTest.java b/src/test/org/apache/commons/cli/ApplicationTest.java
index 169433a..673c2a6 100644
--- a/src/test/org/apache/commons/cli/ApplicationTest.java
+++ b/src/test/org/apache/commons/cli/ApplicationTest.java
@@ -14,22 +14,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
-import junit.framework.Test;
 import junit.framework.TestCase;
-import junit.framework.TestSuite;
 
 /**
+ * This is a collection of tests that test real world applications command lines.
+ *
  * <p>
- * This is a collection of tests that test real world
- * applications command lines.
- * </p>
- * 
- * <p>
- * The following are the applications that are tested:
+ * The following applications are tested:
  * <ul>
- * <li>Ant</li>
+ *   <li>ls</li>
+ *   <li>Ant</li>
+ *   <li>Groovy</li>
+ *   <li>man</li>
  * </ul>
  * </p>
  *
@@ -37,19 +36,7 @@ import junit.framework.TestSuite;
  */
 public class ApplicationTest extends TestCase {
 
-    public static Test suite() { 
-        return new TestSuite(ApplicationTest.class); 
-    }
-
-    public ApplicationTest(String name)
-    {
-        super(name);
-    }
-    
-    /**
-     *	
-     */
-    public void testLs() {
+    public void testLs() throws Exception {
         // create the command line parser
         CommandLineParser parser = new PosixParser();
         Options options = new Options();
@@ -58,8 +45,8 @@ public class ApplicationTest extends TestCase {
         options.addOption( "b", "escape", false, "print octal escapes for nongraphic characters" );
         options.addOption( OptionBuilder.withLongOpt( "block-size" )
                                         .withDescription( "use SIZE-byte blocks" )
-                                        .withValueSeparator( '=' )
                                         .hasArg()
+                                        .withArgName("SIZE")
                                         .create() );
         options.addOption( "B", "ignore-backups", false, "do not list implied entried ending with ~");
         options.addOption( "c", false, "with -lt: sort by, and show, ctime (time of last modification of file status information) with -l:show ctime and sort by name otherwise: sort by ctime" );
@@ -67,20 +54,15 @@ public class ApplicationTest extends TestCase {
 
         String[] args = new String[]{ "--block-size=10" };
 
-        try {
-            CommandLine line = parser.parse( options, args );
-            assertTrue( line.hasOption( "block-size" ) );
-            assertEquals( line.getOptionValue( "block-size" ), "10" );
-        }
-        catch( ParseException exp ) {
-            fail( "Unexpected exception:" + exp.getMessage() );
-        }
+        CommandLine line = parser.parse( options, args );
+        assertTrue( line.hasOption( "block-size" ) );
+        assertEquals( line.getOptionValue( "block-size" ), "10" );
     }
 
     /**
      * Ant test
      */
-    public void testAnt() {
+    public void testAnt() throws Exception {
         // use the GNU parser
         CommandLineParser parser = new GnuParser( );
         Options options = new Options();
@@ -90,7 +72,6 @@ public class ApplicationTest extends TestCase {
         options.addOption( "quiet", false, "be extra quiet" );
         options.addOption( "verbose", false, "be extra verbose" );
         options.addOption( "debug", false, "print debug information" );
-        options.addOption( "version", false, "produce logging information without adornments" );
         options.addOption( "logfile", true, "use given file for log" );
         options.addOption( "logger", true, "the class which is to perform the logging" );
         options.addOption( "listener", true, "add an instance of a class as a project listener" );
@@ -106,26 +87,135 @@ public class ApplicationTest extends TestCase {
             "-Dproperty=value", "-Dproperty1=value1",
             "-projecthelp" };
 
-        try {
-            CommandLine line = parser.parse( options, args );
+        CommandLine line = parser.parse( options, args );
 
-            // check multiple values
-            String[] opts = line.getOptionValues( "D" );
-            assertEquals( "property", opts[0] );
-            assertEquals( "value", opts[1] );
-            assertEquals( "property1", opts[2] );
-            assertEquals( "value1", opts[3] );
+        // check multiple values
+        String[] opts = line.getOptionValues( "D" );
+        assertEquals( "property", opts[0] );
+        assertEquals( "value", opts[1] );
+        assertEquals( "property1", opts[2] );
+        assertEquals( "value1", opts[3] );
 
-            // check single value
-            assertEquals( line.getOptionValue( "buildfile"), "mybuild.xml" );
+        // check single value
+        assertEquals( line.getOptionValue( "buildfile"), "mybuild.xml" );
 
-            // check option
-            assertTrue( line.hasOption( "projecthelp") );
-        }
-        catch( ParseException exp ) {
-            fail( "Unexpected exception:" + exp.getMessage() );
-        }
+        // check option
+        assertTrue( line.hasOption( "projecthelp") );
+    }
+
+    public void testGroovy() throws Exception {
+        Options options = new Options();
+
+        options.addOption(
+            OptionBuilder.withLongOpt("define").
+                withDescription("define a system property").
+                hasArg(true).
+                withArgName("name=value").
+                create('D'));
+        options.addOption(
+            OptionBuilder.hasArg(false)
+            .withDescription("usage information")
+            .withLongOpt("help")
+            .create('h'));
+        options.addOption(
+            OptionBuilder.hasArg(false)
+            .withDescription("debug mode will print out full stack traces")
+            .withLongOpt("debug")
+            .create('d'));
+        options.addOption(
+            OptionBuilder.hasArg(false)
+            .withDescription("display the Groovy and JVM versions")
+            .withLongOpt("version")
+            .create('v'));
+        options.addOption(
+            OptionBuilder.withArgName("charset")
+            .hasArg()
+            .withDescription("specify the encoding of the files")
+            .withLongOpt("encoding")
+            .create('c'));
+        options.addOption(
+            OptionBuilder.withArgName("script")
+            .hasArg()
+            .withDescription("specify a command line script")
+            .create('e'));
+        options.addOption(
+            OptionBuilder.withArgName("extension")
+            .hasOptionalArg()
+            .withDescription("modify files in place; create backup if extension is given (e.g. \'.bak\')")
+            .create('i'));
+        options.addOption(
+            OptionBuilder.hasArg(false)
+            .withDescription("process files line by line using implicit 'line' variable")
+            .create('n'));
+        options.addOption(
+            OptionBuilder.hasArg(false)
+            .withDescription("process files line by line and print result (see also -n)")
+            .create('p'));
+        options.addOption(
+            OptionBuilder.withArgName("port")
+            .hasOptionalArg()
+            .withDescription("listen on a port and process inbound lines")
+            .create('l'));
+        options.addOption(
+            OptionBuilder.withArgName("splitPattern")
+            .hasOptionalArg()
+            .withDescription("split lines using splitPattern (default '\\s') using implicit 'split' variable")
+            .withLongOpt("autosplit")
+            .create('a'));
+
+        Parser parser = new PosixParser();
+        CommandLine line = parser.parse(options, new String[] { "-e", "println 'hello'" }, true);
+
+        assertTrue(line.hasOption('e'));
+        assertEquals("println 'hello'", line.getOptionValue('e'));
+    }
+
+    /**
+     * author Slawek Zachcial
+     */
+    public void testMan()
+    {
+        String cmdLine =
+                "man [-c|-f|-k|-w|-tZT device] [-adlhu7V] [-Mpath] [-Ppager] [-Slist] " +
+                        "[-msystem] [-pstring] [-Llocale] [-eextension] [section] page ...";
+        Options options = new Options().
+                addOption("a", "all", false, "find all matching manual pages.").
+                addOption("d", "debug", false, "emit debugging messages.").
+                addOption("e", "extension", false, "limit search to extension type 'extension'.").
+                addOption("f", "whatis", false, "equivalent to whatis.").
+                addOption("k", "apropos", false, "equivalent to apropos.").
+                addOption("w", "location", false, "print physical location of man page(s).").
+                addOption("l", "local-file", false, "interpret 'page' argument(s) as local filename(s)").
+                addOption("u", "update", false, "force a cache consistency check.").
+                //FIXME - should generate -r,--prompt string
+                addOption("r", "prompt", true, "provide 'less' pager with prompt.").
+                addOption("c", "catman", false, "used by catman to reformat out of date cat pages.").
+                addOption("7", "ascii", false, "display ASCII translation or certain latin1 chars.").
+                addOption("t", "troff", false, "use troff format pages.").
+                //FIXME - should generate -T,--troff-device device
+                addOption("T", "troff-device", true, "use groff with selected device.").
+                addOption("Z", "ditroff", false, "use groff with selected device.").
+                addOption("D", "default", false, "reset all options to their default values.").
+                //FIXME - should generate -M,--manpath path
+                addOption("M", "manpath", true, "set search path for manual pages to 'path'.").
+                //FIXME - should generate -P,--pager pager
+                addOption("P", "pager", true, "use program 'pager' to display output.").
+                //FIXME - should generate -S,--sections list
+                addOption("S", "sections", true, "use colon separated section list.").
+                //FIXME - should generate -m,--systems system
+                addOption("m", "systems", true, "search for man pages from other unix system(s).").
+                //FIXME - should generate -L,--locale locale
+                addOption("L", "locale", true, "define the locale for this particular man search.").
+                //FIXME - should generate -p,--preprocessor string
+                addOption("p", "preprocessor", true, "string indicates which preprocessor to run.\n" +
+                         " e - [n]eqn  p - pic     t - tbl\n" +
+                         " g - grap    r - refer   v - vgrind").
+                addOption("V", "version", false, "show version.").
+                addOption("h", "help", false, "show this usage message.");
 
+        HelpFormatter hf = new HelpFormatter();
+        //hf.printHelp(cmdLine, opts);
+        hf.printHelp(60, cmdLine, null, options, null);
     }
 
-}
\ No newline at end of file
+}
diff --git a/src/test/org/apache/commons/cli/ArgumentIsOptionTest.java b/src/test/org/apache/commons/cli/ArgumentIsOptionTest.java
index 61ca1b9..d71b0c4 100644
--- a/src/test/org/apache/commons/cli/ArgumentIsOptionTest.java
+++ b/src/test/org/apache/commons/cli/ArgumentIsOptionTest.java
@@ -14,87 +14,62 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
-import junit.framework.Test;
 import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
 
-public class ArgumentIsOptionTest extends TestCase {
+public class ArgumentIsOptionTest extends TestCase
+{
     private Options options = null;
     private CommandLineParser parser = null;
 
-    public ArgumentIsOptionTest(String name) {
-        super(name);
-    }
-
-    public static Test suite() {
-        return new TestSuite(ArgumentIsOptionTest.class);
-    }
-
-    public void setUp() {
-        options = new Options().addOption("p", false, "Option p").addOption("attr",
-                true, "Option accepts argument");
+    public void setUp()
+    {
+        options = new Options().addOption("p", false, "Option p").addOption("attr", true, "Option accepts argument");
 
         parser = new PosixParser();
     }
 
-    public void tearDown() {
-    }
-
-    public void testOptionAndOptionWithArgument() {
-        String[] args = new String[] {
+    public void testOptionAndOptionWithArgument() throws Exception
+    {
+        String[] args = new String[]{
                 "-p",
                 "-attr",
                 "p"
-            };
+        };
 
-        try {
-            CommandLine cl = parser.parse(options, args);
-            assertTrue("Confirm -p is set", cl.hasOption("p"));
-            assertTrue("Confirm -attr is set", cl.hasOption("attr"));
-            assertTrue("Confirm arg of -attr",
-                cl.getOptionValue("attr").equals("p"));
-            assertTrue("Confirm all arguments recognized", cl.getArgs().length == 0);
-        }
-        catch (ParseException e) {
-            fail(e.toString());
-        }
+        CommandLine cl = parser.parse(options, args);
+        assertTrue("Confirm -p is set", cl.hasOption("p"));
+        assertTrue("Confirm -attr is set", cl.hasOption("attr"));
+        assertTrue("Confirm arg of -attr", cl.getOptionValue("attr").equals("p"));
+        assertTrue("Confirm all arguments recognized", cl.getArgs().length == 0);
     }
 
-    public void testOptionWithArgument() {
-        String[] args = new String[] {
+    public void testOptionWithArgument() throws Exception
+    {
+        String[] args = new String[]{
                 "-attr",
                 "p"
-            };
+        };
 
-        try {
-            CommandLine cl = parser.parse(options, args);
-            assertFalse("Confirm -p is set", cl.hasOption("p"));
-            assertTrue("Confirm -attr is set", cl.hasOption("attr"));
-            assertTrue("Confirm arg of -attr",
+        CommandLine cl = parser.parse(options, args);
+        assertFalse("Confirm -p is set", cl.hasOption("p"));
+        assertTrue("Confirm -attr is set", cl.hasOption("attr"));
+        assertTrue("Confirm arg of -attr",
                 cl.getOptionValue("attr").equals("p"));
-            assertTrue("Confirm all arguments recognized", cl.getArgs().length == 0);
-        }
-        catch (ParseException e) {
-            fail(e.toString());
-        }
+        assertTrue("Confirm all arguments recognized", cl.getArgs().length == 0);
     }
 
-    public void testOption() {
-        String[] args = new String[] {
+    public void testOption() throws Exception
+    {
+        String[] args = new String[]{
                 "-p"
-            };
+        };
 
-        try {
-            CommandLine cl = parser.parse(options, args);
-            assertTrue("Confirm -p is set", cl.hasOption("p"));
-            assertFalse("Confirm -attr is not set", cl.hasOption("attr"));
-            assertTrue("Confirm all arguments recognized", cl.getArgs().length == 0);
-        }
-        catch (ParseException e) {
-            fail(e.toString());
-        }
+        CommandLine cl = parser.parse(options, args);
+        assertTrue("Confirm -p is set", cl.hasOption("p"));
+        assertFalse("Confirm -attr is not set", cl.hasOption("attr"));
+        assertTrue("Confirm all arguments recognized", cl.getArgs().length == 0);
     }
 }
diff --git a/src/java/org/apache/commons/cli/MissingArgumentException.java b/src/test/org/apache/commons/cli/BasicParserTest.java
similarity index 50%
copy from src/java/org/apache/commons/cli/MissingArgumentException.java
copy to src/test/org/apache/commons/cli/BasicParserTest.java
index 3b3378e..32db57e 100644
--- a/src/java/org/apache/commons/cli/MissingArgumentException.java
+++ b/src/test/org/apache/commons/cli/BasicParserTest.java
@@ -14,26 +14,43 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
-/** 
- * <p>Thrown when an option requiring an argument
- * is not provided with an argument.</p>
- *
- * @author John Keyes (john at integralsource.com)
- * @see ParseException
+/**
+ * @author Emmanuel Bourg
+ * @version $Revision: 695410 $, $Date: 2008-09-15 03:25:38 -0700 (Mon, 15 Sep 2008) $
  */
-public class MissingArgumentException
-    extends ParseException {
+public class BasicParserTest extends ParserTestCase
+{
+    public void setUp()
+    {
+        super.setUp();
+        parser = new BasicParser();
+    }
+
+    public void testPropertiesOption() throws Exception
+    {
+        // not supported by the BasicParser
+    }
+
+    public void testShortWithEqual() throws Exception
+    {
+        // not supported by the BasicParser
+    }
+
+    public void testShortWithoutEqual() throws Exception
+    {
+        // not supported by the BasicParser
+    }
+
+    public void testLongWithEqual() throws Exception
+    {
+        // not supported by the BasicParser
+    }
 
-    /** 
-     * <p>Construct a new <code>MissingArgumentException</code> 
-     * with the specified detail message.</p>
-     *
-     * @param message the detail message
-     */
-    public MissingArgumentException(String message)
+    public void testLongWithEqualSingleDash() throws Exception
     {
-        super(message);
+        // not supported by the BasicParser
     }
-}
\ No newline at end of file
+}
diff --git a/src/test/org/apache/commons/cli/BugsTest.java b/src/test/org/apache/commons/cli/BugsTest.java
index 0f8494b..b246368 100644
--- a/src/test/org/apache/commons/cli/BugsTest.java
+++ b/src/test/org/apache/commons/cli/BugsTest.java
@@ -14,177 +14,117 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.util.Iterator;
 import java.util.Properties;
 
-import junit.framework.Test;
 import junit.framework.TestCase;
-import junit.framework.TestSuite;
 
 public class BugsTest extends TestCase
 {
-    /** CommandLine instance */
-    private CommandLine _cmdline = null;
-    private Option _option = null;
-
-    public static Test suite() { 
-        return new TestSuite( BugsTest.class );
-    }
-
-    public BugsTest( String name )
+    public void test11457() throws Exception
     {
-        super( name );
-    }
-
-    public void setUp()
-    {
-    }
-
-    public void tearDown()
-    {
-    }
-
-    public void test11457() {
         Options options = new Options();
-        options.addOption( OptionBuilder.withLongOpt( "verbose" )
-                           .create() );
-        String[] args = new String[] { "--verbose" };
+        options.addOption(OptionBuilder.withLongOpt("verbose").create());
+        String[] args = new String[]{"--verbose"};
 
         CommandLineParser parser = new PosixParser();
 
-        try {
-            CommandLine cmd = parser.parse( options, args );
-            assertTrue( cmd.hasOption( "verbose" ) );
-        }        
-        catch( ParseException exp ) {
-            exp.printStackTrace();
-            fail( "Unexpected Exception: " + exp.getMessage() );
-        }
+        CommandLine cmd = parser.parse(options, args);
+        assertTrue(cmd.hasOption("verbose"));
     }
 
-    public void test11458()
+    public void test11458() throws Exception
     {
         Options options = new Options();
-        options.addOption( OptionBuilder.withValueSeparator( '=' )
-                           .hasArgs()
-                           .create( 'D' ) );
-        options.addOption( OptionBuilder.withValueSeparator( ':' )
-                           .hasArgs()
-                           .create( 'p' ) );
-        String[] args = new String[] { "-DJAVA_HOME=/opt/java" ,
-        "-pfile1:file2:file3" };
+        options.addOption( OptionBuilder.withValueSeparator( '=' ).hasArgs().create( 'D' ) );
+        options.addOption( OptionBuilder.withValueSeparator( ':' ).hasArgs().create( 'p' ) );
+        String[] args = new String[] { "-DJAVA_HOME=/opt/java" , "-pfile1:file2:file3" };
 
         CommandLineParser parser = new PosixParser();
 
-        try {
-            CommandLine cmd = parser.parse( options, args );
-
-            String[] values = cmd.getOptionValues( 'D' );
-
-            assertEquals( values[0], "JAVA_HOME" );
-            assertEquals( values[1], "/opt/java" );
-
-            values = cmd.getOptionValues( 'p' );
-
-            assertEquals( values[0], "file1" );
-            assertEquals( values[1], "file2" );
-            assertEquals( values[2], "file3" );
-
-            java.util.Iterator iter = cmd.iterator();
-            while( iter.hasNext() ) {
-                Option opt = (Option)iter.next();
-                switch( opt.getId() ) {
-                    case 'D':
-                        assertEquals( opt.getValue( 0 ), "JAVA_HOME" );
-                        assertEquals( opt.getValue( 1 ), "/opt/java" );
-                        break;
-                    case 'p':
-                        assertEquals( opt.getValue( 0 ), "file1" );
-                        assertEquals( opt.getValue( 1 ), "file2" );
-                        assertEquals( opt.getValue( 2 ), "file3" );
-                        break;
-                    default:
-                        fail( "-D option not found" );
-                }
+        CommandLine cmd = parser.parse(options, args);
+
+        String[] values = cmd.getOptionValues('D');
+
+        assertEquals(values[0], "JAVA_HOME");
+        assertEquals(values[1], "/opt/java");
+
+        values = cmd.getOptionValues('p');
+
+        assertEquals(values[0], "file1");
+        assertEquals(values[1], "file2");
+        assertEquals(values[2], "file3");
+
+        Iterator iter = cmd.iterator();
+        while (iter.hasNext())
+        {
+            Option opt = (Option) iter.next();
+            switch (opt.getId())
+            {
+                case 'D':
+                    assertEquals(opt.getValue(0), "JAVA_HOME");
+                    assertEquals(opt.getValue(1), "/opt/java");
+                    break;
+                case 'p':
+                    assertEquals(opt.getValue(0), "file1");
+                    assertEquals(opt.getValue(1), "file2");
+                    assertEquals(opt.getValue(2), "file3");
+                    break;
+                default:
+                    fail("-D option not found");
             }
         }
-        catch( ParseException exp ) {
-            fail( "Unexpected Exception:\nMessage:" + exp.getMessage() 
-                  + "Type: " + exp.getClass().getName() );
-        }
     }
 
-    public void test11680()
+    public void test11680() throws Exception
     {
         Options options = new Options();
         options.addOption("f", true, "foobar");
-	options.addOption("m", true, "missing");
-        String[] args = new String[] { "-f" , "foo" };
+        options.addOption("m", true, "missing");
+        String[] args = new String[]{"-f", "foo"};
 
         CommandLineParser parser = new PosixParser();
 
-        try {
-            CommandLine cmd = parser.parse( options, args );
+        CommandLine cmd = parser.parse(options, args);
 
-            try {
-                cmd.getOptionValue( "f", "default f");
-                cmd.getOptionValue( "m", "default m");
-            }
-            catch( NullPointerException exp ) {
-                fail( "NullPointer caught: " + exp.getMessage() );
-            }
-        }
-        catch( ParseException exp ) {
-            fail( "Unexpected Exception: " + exp.getMessage() );
-        }
+        cmd.getOptionValue("f", "default f");
+        cmd.getOptionValue("m", "default m");
     }
 
-    public void test11456()
+    public void test11456() throws Exception
     {
         // Posix 
         Options options = new Options();
-        options.addOption( OptionBuilder.hasOptionalArg()
-                           .create( 'a' ) );
-        options.addOption( OptionBuilder.hasArg()
-                           .create( 'b' ) );
+        options.addOption( OptionBuilder.hasOptionalArg().create( 'a' ) );
+        options.addOption( OptionBuilder.hasArg().create( 'b' ) );
         String[] args = new String[] { "-a", "-bvalue" };
 
         CommandLineParser parser = new PosixParser();
 
-        try {
-            CommandLine cmd = parser.parse( options, args );
-            assertEquals( cmd.getOptionValue( 'b' ), "value" );
-        }
-        catch( ParseException exp ) {
-            fail( "Unexpected Exception: " + exp.getMessage() );
-        }
+        CommandLine cmd = parser.parse( options, args );
+        assertEquals( cmd.getOptionValue( 'b' ), "value" );
 
         // GNU
         options = new Options();
-        options.addOption( OptionBuilder.hasOptionalArg()
-                           .create( 'a' ) );
-        options.addOption( OptionBuilder.hasArg()
-                           .create( 'b' ) );
+        options.addOption( OptionBuilder.hasOptionalArg().create( 'a' ) );
+        options.addOption( OptionBuilder.hasArg().create( 'b' ) );
         args = new String[] { "-a", "-b", "value" };
 
         parser = new GnuParser();
 
-        try {
-            CommandLine cmd = parser.parse( options, args );
-            assertEquals( cmd.getOptionValue( 'b' ), "value" );
-        }
-        catch( ParseException exp ) {
-            fail( "Unexpected Exception: " + exp.getMessage() );
-        }
-
+        cmd = parser.parse( options, args );
+        assertEquals( cmd.getOptionValue( 'b' ), "value" );
     }
 
-    public void test12210() {
+    public void test12210() throws Exception
+    {
         // create the main options object which will handle the first parameter
         Options mainOptions = new Options();
         // There can be 2 main exclusive options:  -exec|-rep
@@ -202,13 +142,13 @@ public class BugsTest extends TestCase
 
         // for the exec option, there are 2 options...
         Options execOptions = new Options();
-        execOptions.addOption("exec_opt1",false," desc");
-        execOptions.addOption("exec_opt2",false," desc");
+        execOptions.addOption("exec_opt1", false, " desc");
+        execOptions.addOption("exec_opt2", false, " desc");
 
         // similarly, for rep there are 2 options...
         Options repOptions = new Options();
-        repOptions.addOption("repopto",false,"desc");
-        repOptions.addOption("repoptt",false,"desc");
+        repOptions.addOption("repopto", false, "desc");
+        repOptions.addOption("repoptt", false, "desc");
 
         // create the parser
         GnuParser parser = new GnuParser();
@@ -218,31 +158,29 @@ public class BugsTest extends TestCase
         // first parse the main options to see what the user has specified
         // We set stopAtNonOption to true so it does not touch the remaining
         // options
-        try {
-            CommandLine cmd = parser.parse(mainOptions,argv,true);
-            // get the remaining options...
-            argv = cmd.getArgs();
-
-            if(cmd.hasOption("exec")){
-                cmd = parser.parse(execOptions,argv,false);
-                // process the exec_op1 and exec_opt2...
-                assertTrue( cmd.hasOption("exec_opt1") );
-                assertTrue( cmd.hasOption("exec_opt2") );
-            }
-            else if(cmd.hasOption("rep")){
-                cmd = parser.parse(repOptions,argv,false);
-                // process the rep_op1 and rep_opt2...
-            }
-            else {
-                fail( "exec option not found" );
-            }
+        CommandLine cmd = parser.parse(mainOptions,argv,true);
+        // get the remaining options...
+        argv = cmd.getArgs();
+
+        if(cmd.hasOption("exec"))
+        {
+            cmd = parser.parse(execOptions,argv,false);
+            // process the exec_op1 and exec_opt2...
+            assertTrue( cmd.hasOption("exec_opt1") );
+            assertTrue( cmd.hasOption("exec_opt2") );
         }
-        catch( ParseException exp ) {
-            fail( "Unexpected exception: " + exp.getMessage() );
+        else if(cmd.hasOption("rep"))
+        {
+            cmd = parser.parse(repOptions,argv,false);
+            // process the rep_op1 and rep_opt2...
+        }
+        else {
+            fail( "exec option not found" );
         }
     }
 
-    public void test13425() {
+    public void test13425() throws Exception
+    {
         Options options = new Options();
         Option oldpass = OptionBuilder.withLongOpt( "old-password" )
             .withDescription( "Use this option to specify the old password" )
@@ -264,27 +202,28 @@ public class BugsTest extends TestCase
 
         Parser parser = new PosixParser();
 
-        try {
-            CommandLine line = parser.parse( options, args );
+        try
+        {
+            parser.parse( options, args );
         }
         // catch the exception and leave the method
-        catch( Exception exp ) {
+        catch( Exception exp )
+        {
             assertTrue( exp != null );
             return;
         }
         fail( "MissingArgumentException not caught." );
     }
 
-    public void test13666() {
+    public void test13666() throws Exception
+    {
         Options options = new Options();
-        Option dir = OptionBuilder.withDescription( "dir" )
-                                       .hasArg()
-                                       .create( 'd' );
+        Option dir = OptionBuilder.withDescription( "dir" ).hasArg().create( 'd' );
         options.addOption( dir );
         
-        
         final PrintStream oldSystemOut = System.out;
-        try{
+        try
+        {
             final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
             final PrintStream print = new PrintStream(bytes);
             
@@ -294,21 +233,20 @@ public class BugsTest extends TestCase
             bytes.reset();
             
             System.setOut(new PrintStream(bytes));
-            try {
-                HelpFormatter formatter = new HelpFormatter();
-                formatter.printHelp( "dir", options );
-            }
-            catch( Exception exp ) {
-                fail( "Unexpected Exception: " + exp.getMessage() );
-            }
+
+            HelpFormatter formatter = new HelpFormatter();
+            formatter.printHelp( "dir", options );
+
             assertEquals("usage: dir"+eol+" -d <arg>   dir"+eol,bytes.toString());
         }
-        finally {
+        finally
+        {
             System.setOut(oldSystemOut);
         }
     }
 
-    public void test13935() {
+    public void test13935() throws Exception
+    {
         OptionGroup directions = new OptionGroup();
 
         Option left = new Option( "l", "left", false, "go left" );
@@ -329,52 +267,63 @@ public class BugsTest extends TestCase
         boolean exception = false;
 
         String[] args = new String[] {  };
-        try {
-            CommandLine line = parser.parse( opts, args );
+        try
+        {
+            CommandLine line = parser.parse(opts, args);
         }
-        catch( ParseException exp ) {
+        catch (ParseException exp)
+        {
             exception = true;
         }
 
-        if( !exception ) {
-            fail( "Expected exception not caught.");
+        if (!exception)
+        {
+            fail("Expected exception not caught.");
         }
 
         exception = false;
 
         args = new String[] { "-s" };
-        try {
-            CommandLine line = parser.parse( opts, args );
+        try
+        {
+            CommandLine line = parser.parse(opts, args);
         }
-        catch( ParseException exp ) {
+        catch (ParseException exp)
+        {
             exception = true;
         }
 
-        if( !exception ) {
-            fail( "Expected exception not caught.");
+        if (!exception)
+        {
+            fail("Expected exception not caught.");
         }
 
         exception = false;
 
         args = new String[] { "-s", "-l" };
-        try {
-            CommandLine line = parser.parse( opts, args );
+        try
+        {
+            parser.parse(opts, args);
         }
-        catch( ParseException exp ) {
-            fail( "Unexpected exception: " + exp.getClass().getName() + ":" + exp.getMessage() );
+        catch (ParseException exp)
+        {
+            fail("Unexpected exception: " + exp.getClass().getName() + ":" + exp.getMessage());
         }
 
         opts.addOption( forward );
         args = new String[] { "-s", "-l", "-f" };
-        try {
-            CommandLine line = parser.parse( opts, args );
+        try
+        {
+            parser.parse(opts, args);
         }
-        catch( ParseException exp ) {
-            fail( "Unexpected exception: " + exp.getClass().getName() + ":" + exp.getMessage() );
+        catch (ParseException exp)
+        {
+            fail("Unexpected exception: " + exp.getClass().getName() + ":" + exp.getMessage());
         }
     }
 
-    public void test14786() throws Exception {
+    public void test14786() throws Exception
+    {
         Option o = OptionBuilder.isRequired().withDescription("test").create("test");
         Options opts = new Options();
         opts.addOption(o);
@@ -388,23 +337,25 @@ public class BugsTest extends TestCase
         assertTrue( line.hasOption( "test" ) );
     }
 
-    public void test15046() throws Exception {
+    public void test15046() throws Exception
+    {
         CommandLineParser parser = new PosixParser();
-        final String[] CLI_ARGS = new String[] {"-z", "c"};
-        Option option = new Option("z", "timezone", true, 
-                                   "affected option");
-        Options cliOptions = new Options();
-        cliOptions.addOption(option);
-        parser.parse(cliOptions, CLI_ARGS);
-		
+        String[] CLI_ARGS = new String[] {"-z", "c"};
+
+        Options options = new Options();
+        options.addOption(new Option("z", "timezone", true, "affected option"));
+
+        parser.parse(options, CLI_ARGS);
+        
         //now add conflicting option
-        cliOptions.addOption("c", "conflict", true, "conflict option");
-        CommandLine line = parser.parse(cliOptions, CLI_ARGS);
-        assertEquals( option.getValue(), "c" );
+        options.addOption("c", "conflict", true, "conflict option");
+        CommandLine line = parser.parse(options, CLI_ARGS);
+        assertEquals( line.getOptionValue('z'), "c" );
         assertTrue( !line.hasOption("c") );
     }
 
-    public void test15648() throws Exception {
+    public void test15648() throws Exception
+    {
         CommandLineParser parser = new PosixParser();
         final String[] args = new String[] { "-m", "\"Two Words\"" };
         Option m = OptionBuilder.hasArgs().create("m");
@@ -413,76 +364,9 @@ public class BugsTest extends TestCase
         CommandLine line = parser.parse( options, args );
         assertEquals( "Two Words", line.getOptionValue( "m" ) );
     }
-
-    public void test27635() {
-        Option help = new Option("h", "help", false, "print this message");
-        Option version = new Option("v", "version", false, "print version information");
-        Option newRun = new Option("n", "new", false, "Create NLT cache entries only for new items");
-        Option trackerRun = new Option("t", "tracker", false, "Create NLT cache entries only for tracker items");
-        
-        Option timeLimit = OptionBuilder.withLongOpt("limit")
-                                        .hasArg()
-                                        .withValueSeparator()
-                                        .withDescription("Set time limit for execution, in mintues")
-                                        .create("l");
-        
-        Option age = OptionBuilder.withLongOpt("age")
-                                        .hasArg()
-                                        .withValueSeparator()
-                                        .withDescription("Age (in days) of cache item before being recomputed")
-                                        .create("a");
-        
-        Option server = OptionBuilder.withLongOpt("server")
-                                        .hasArg()
-                                        .withValueSeparator()
-                                        .withDescription("The NLT server address")
-                                        .create("s");
-        
-        Option numResults = OptionBuilder.withLongOpt("results")
-                                        .hasArg()
-                                        .withValueSeparator()
-                                        .withDescription("Number of results per item")
-                                        .create("r");
-        
-        Option configFile = OptionBuilder.withLongOpt("config")
-                                        .hasArg()
-                                        .withValueSeparator()
-                                        .withDescription("Use the specified configuration file")
-                                        .create();
-        
-        Options mOptions = new Options();
-        mOptions.addOption(help);
-        mOptions.addOption(version);
-        mOptions.addOption(newRun);
-        mOptions.addOption(trackerRun);
-        mOptions.addOption(timeLimit);
-        mOptions.addOption(age);
-        mOptions.addOption(server);
-        mOptions.addOption(numResults);
-        mOptions.addOption(configFile);
-        
-        HelpFormatter formatter = new HelpFormatter();
-        final String EOL = System.getProperty("line.separator");
-        StringWriter out = new StringWriter();
-        formatter.printHelp(new PrintWriter(out),80,"commandline","header",mOptions,2,2,"footer",true);
-        assertEquals(
-                "usage: commandline [-a <arg>] [--config <arg>] [-h] [-l <arg>] [-n] [-r <arg>]" + EOL +
-                "       [-s <arg>] [-t] [-v]" + EOL +
-                "header"+EOL+
-                "  -a,--age <arg>      Age (in days) of cache item before being recomputed"+EOL+
-                "     --config <arg>   Use the specified configuration file"+EOL+
-                "  -h,--help           print this message"+EOL+
-                "  -l,--limit <arg>    Set time limit for execution, in mintues"+EOL+
-                "  -n,--new            Create NLT cache entries only for new items"+EOL+
-                "  -r,--results <arg>  Number of results per item"+EOL+
-                "  -s,--server <arg>   The NLT server address"+EOL+
-                "  -t,--tracker        Create NLT cache entries only for tracker items"+EOL+
-                "  -v,--version        print version information"+EOL+
-                "footer"+EOL
-                ,out.toString());
-    }
     
-    public void test31148() throws ParseException {
+    public void test31148() throws ParseException
+    {
         Option multiArgOption = new Option("o","option with multiple args");
         multiArgOption.setArgs(1);
         
@@ -498,40 +382,5 @@ public class BugsTest extends TestCase
         assertTrue(cl.hasOption('o'));
         assertEquals("ovalue",cl.getOptionValue('o'));
     }
-    
-    public void test21215() {
-        Options options = new Options();
-        HelpFormatter formatter = new HelpFormatter();
-        String SEP = System.getProperty("line.separator");
-        String header = SEP+"Header";
-        String footer = "Footer";
-        StringWriter out = new StringWriter();
-        formatter.printHelp(new PrintWriter(out),80, "foobar", header, options, 2, 2, footer, true);
-        assertEquals(
-                "usage: foobar"+SEP+
-                ""+SEP+
-                "Header"+SEP+
-                ""+SEP+
-                "Footer"+SEP
-                ,out.toString());
-    }
-    
-    public void test19383() {
-        Options options = new Options();
-        options.addOption(new Option("a","aaa",false,"aaaaaaa"));
-        options.addOption(new Option(null,"bbb",false,"bbbbbbb"));
-        options.addOption(new Option("c",null,false,"ccccccc"));
-        
-        HelpFormatter formatter = new HelpFormatter();
-        String SEP = System.getProperty("line.separator");
-        StringWriter out = new StringWriter();
-        formatter.printHelp(new PrintWriter(out),80, "foobar", "", options, 2, 2, "", true);
-        assertEquals(
-                "usage: foobar [-a] [--bbb] [-c]"+SEP+
-                "  -a,--aaa  aaaaaaa"+SEP+
-                "     --bbb  bbbbbbb"+SEP+
-                "  -c        ccccccc"+SEP
-                ,out.toString());
-    }
 
 }
diff --git a/src/test/org/apache/commons/cli/BuildTest.java b/src/test/org/apache/commons/cli/BuildTest.java
deleted file mode 100644
index 7a3abb9..0000000
--- a/src/test/org/apache/commons/cli/BuildTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.cli;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class BuildTest extends TestCase
-{
-
-    public static Test suite() { 
-        return new TestSuite(BuildTest.class); 
-    }
-
-    public BuildTest(String name)
-    {
-        super(name);
-    }
-
-    public void setUp()
-    {
-
-    }
-
-    public void tearDown()
-    {
-
-    }
-
-    public void testSimple()
-    {
-        Options opts = new Options();
-        
-        opts.addOption("a",
-                       false,
-                       "toggle -a");
-
-        opts.addOption("b",
-                       true,
-                       "toggle -b");
-    }
-
-    public void testDuplicateSimple()
-    {
-        Options opts = new Options();
-        opts.addOption("a",
-                       false,
-                       "toggle -a");
-
-        opts.addOption("a",
-                       true,
-                       "toggle -a*");
-        
-        assertEquals( "last one in wins", "toggle -a*", opts.getOption("a").getDescription() );
-    }
-
-    public void testLong()
-    {
-        Options opts = new Options();
-        
-        opts.addOption("a",
-                       "--a",
-                       false,
-                       "toggle -a");
-
-        opts.addOption("b",
-                       "--b",
-                       true,
-                       "set -b");
-
-    }
-
-    public void testDuplicateLong()
-    {
-        Options opts = new Options();
-        opts.addOption("a",
-                       "--a",
-                       false,
-                       "toggle -a");
-
-        opts.addOption("a",
-                       "--a",
-                       false,
-                       "toggle -a*");
-        assertEquals( "last one in wins", "toggle -a*", opts.getOption("a").getDescription() );
-    }
-}
diff --git a/src/test/org/apache/commons/cli/CommandLineTest.java b/src/test/org/apache/commons/cli/CommandLineTest.java
new file mode 100644
index 0000000..c6d1bbe
--- /dev/null
+++ b/src/test/org/apache/commons/cli/CommandLineTest.java
@@ -0,0 +1,51 @@
+/**
+ * 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.cli;
+
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Emmanuel Bourg
+ * @version $Revision: 667595 $, $Date: 2008-06-13 10:03:31 -0700 (Fri, 13 Jun 2008) $
+ */
+public class CommandLineTest extends TestCase
+{
+    public void testGetOptionProperties() throws Exception
+    {
+        String[] args = new String[] { "-Dparam1=value1", "-Dparam2=value2", "-Dparam3", "-Dparam4=value4", "-D", "--property", "foo=bar" };
+
+        Options options = new Options();
+        options.addOption(OptionBuilder.withValueSeparator().hasOptionalArgs(2).create('D'));
+        options.addOption(OptionBuilder.withValueSeparator().hasArgs(2).withLongOpt("property").create());
+
+        Parser parser = new GnuParser();
+        CommandLine cl = parser.parse(options, args);
+
+        Properties props = cl.getOptionProperties("D");
+        assertNotNull("null properties", props);
+        assertEquals("number of properties in " + props, 4, props.size());
+        assertEquals("property 1", "value1", props.getProperty("param1"));
+        assertEquals("property 2", "value2", props.getProperty("param2"));
+        assertEquals("property 3", "true", props.getProperty("param3"));
+        assertEquals("property 4", "value4", props.getProperty("param4"));
+
+        assertEquals("property with long format", "bar", cl.getOptionProperties("property").getProperty("foo"));
+    }
+}
diff --git a/src/test/org/apache/commons/cli/GnuParseTest.java b/src/test/org/apache/commons/cli/GnuParseTest.java
deleted file mode 100644
index 504b59c..0000000
--- a/src/test/org/apache/commons/cli/GnuParseTest.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.cli;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class GnuParseTest extends TestCase
-{
-    private Options _options = null;
-    private Parser _parser = null;
-
-    public static Test suite() { 
-        return new TestSuite( GnuParseTest.class ); 
-    }
-
-    public GnuParseTest( String name )
-    {
-        super( name );
-    }
-
-    public void setUp()
-    {
-        _options = new Options()
-            .addOption("a",
-                       "enable-a",
-                       false,
-                       "turn [a] on or off")
-            .addOption("b",
-                       "bfile",
-                       true,
-                       "set the value of [b]")
-            .addOption("c",
-                       "copt",
-                       false,
-                       "turn [c] on or off");
-
-        _parser = new GnuParser( );
-    }
-
-    public void tearDown()
-    {
-
-    }
-
-    public void testSimpleShort()
-    {
-        String[] args = new String[] { "-a",
-                                       "-b", "toast",
-                                       "foo", "bar" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args);
-            
-            assertTrue( "Confirm -a is set", cl.hasOption("a") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
-            assertTrue( "Confirm size of extra args", cl.getArgList().size() == 2);
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-    }
-
-    public void testSimpleLong()
-    {
-        String[] args = new String[] { "--enable-a",
-                                       "--bfile", "toast",
-                                       "foo", "bar" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args);
-            
-            assertTrue( "Confirm -a is set", cl.hasOption("a") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
-            assertTrue( "Confirm size of extra args", cl.getArgList().size() == 2);
-        } 
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-    }
-
-    public void testExtraOption()
-    {
-        String[] args = new String[] { "-a", "-d", "-b", "toast",
-                                       "foo", "bar" };
-
-        boolean caught = false;
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args);
-            
-            assertTrue( "Confirm -a is set", cl.hasOption("a") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "confirm arg of -b", cl.getOptionValue("b").equals("toast") );
-            assertTrue( "Confirm size of extra args", cl.getArgList().size() == 3);
-        }
-        catch (UnrecognizedOptionException e)
-        {
-            caught = true;
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-        assertTrue( "Confirm UnrecognizedOptionException caught", caught );
-    }
-
-    public void testMissingArg()
-    {
-
-        String[] args = new String[] { "-b" };
-
-        boolean caught = false;
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args);
-        }
-        catch (MissingArgumentException e)
-        {
-            caught = true;
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-
-        assertTrue( "Confirm MissingArgumentException caught", caught );
-    }
-
-    public void testStop()
-    {
-        String[] args = new String[] { "-c",
-                                       "foober",
-                                       "-b",
-                                       "toast" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args, true);
-            assertTrue( "Confirm -c is set", cl.hasOption("c") );
-            assertTrue( "Confirm  3 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 3);
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-    }
-
-    public void testMultiple()
-    {
-        String[] args = new String[] { "-c",
-                                       "foobar",
-                                       "-b",
-                                       "toast" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args, true);
-            assertTrue( "Confirm -c is set", cl.hasOption("c") );
-            assertTrue( "Confirm  3 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 3);
-
-            cl = _parser.parse(_options, cl.getArgs() );
-
-            assertTrue( "Confirm -c is not set", ! cl.hasOption("c") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
-            assertTrue( "Confirm  1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
-            assertTrue( "Confirm  value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("foobar") );
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-    }
-
-    public void testMultipleWithLong()
-    {
-        String[] args = new String[] { "--copt",
-                                       "foobar",
-                                       "--bfile", "toast" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options,args,
-                                            true);
-            assertTrue( "Confirm -c is set", cl.hasOption("c") );
-            assertTrue( "Confirm  3 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 3);
-
-            cl = _parser.parse(_options, cl.getArgs() );
-
-            assertTrue( "Confirm -c is not set", ! cl.hasOption("c") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
-            assertTrue( "Confirm  1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
-            assertTrue( "Confirm  value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("foobar") );
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-    }
-
-    public void testDoubleDash()
-    {
-        String[] args = new String[] { "--copt",
-                                       "--",
-                                       "-b", "toast" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args);
-
-            assertTrue( "Confirm -c is set", cl.hasOption("c") );
-            assertTrue( "Confirm -b is not set", ! cl.hasOption("b") );
-            assertTrue( "Confirm 2 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 2);
-
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-    }
-
-    public void testSingleDash()
-    {
-        String[] args = new String[] { "--copt",
-                                       "-b", "-",
-                                       "-a",
-                                       "-" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args);
-
-            assertTrue( "Confirm -a is set", cl.hasOption("a") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("-") );
-            assertTrue( "Confirm 1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
-            assertTrue( "Confirm value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("-") );
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-        
-    }
-}
diff --git a/src/test/org/apache/commons/cli/UtilTest.java b/src/test/org/apache/commons/cli/GnuParserTest.java
similarity index 72%
copy from src/test/org/apache/commons/cli/UtilTest.java
copy to src/test/org/apache/commons/cli/GnuParserTest.java
index 3aae1d1..43f80fa 100644
--- a/src/test/org/apache/commons/cli/UtilTest.java
+++ b/src/test/org/apache/commons/cli/GnuParserTest.java
@@ -14,17 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.cli;
 
-import junit.framework.TestCase;
+package org.apache.commons.cli;
 
-/**
- * @author brianegge
- */
-public class UtilTest extends TestCase {
-    public void testStripLeadingHyphens() {
-        assertEquals("f", Util.stripLeadingHyphens("-f"));
-        assertEquals("foo", Util.stripLeadingHyphens("--foo"));
-        assertNull(Util.stripLeadingHyphens(null));
+public class GnuParserTest extends ParserTestCase
+{
+    public void setUp()
+    {
+        super.setUp();
+        parser = new GnuParser();
     }
 }
diff --git a/src/test/org/apache/commons/cli/HelpFormatterExamples.java b/src/test/org/apache/commons/cli/HelpFormatterExamples.java
deleted file mode 100644
index 071c00b..0000000
--- a/src/test/org/apache/commons/cli/HelpFormatterExamples.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.cli;
-
-/** 
- * A sample program shpwing the use of Options and the HelpFormatter class 
- *
- * @author Slawek Zachcial
- **/
-public class HelpFormatterExamples
-{
-   // --------------------------------------------------------------- Constants
-
-   // ------------------------------------------------------------------ Static
-
-   public static void main( String[] args )
-   {
-      System.out.println("\n#\n# 'man' example\n#");
-      manExample();
-/*
-      System.out.println("\n#\n# 'bzip2' example\n#");
-      bzip2Example();
-      System.out.println("\n#\n# 'ls' example\n#");
-      lsExample();
-*/
-   }
-
-   static void manExample()
-   {
-      String cmdLine =
-         "man [-c|-f|-k|-w|-tZT device] [-adlhu7V] [-Mpath] [-Ppager] [-Slist] " +
-         "[-msystem] [-pstring] [-Llocale] [-eextension] [section] page ...";
-      Options opts =
-         new Options().
-         addOption("a", "all",            false, "find all matching manual pages.").
-         addOption("d", "debug",          false, "emit debugging messages.").
-         addOption("e", "extension",      false, "limit search to extension type 'extension'.").
-         addOption("f", "whatis",         false, "equivalent to whatis.").
-         addOption("k", "apropos",        false, "equivalent to apropos.").
-         addOption("w", "location",       false, "print physical location of man page(s).").
-         addOption("l", "local-file",     false, "interpret 'page' argument(s) as local filename(s)").
-         addOption("u", "update",         false, "force a cache consistency check.").
-         //FIXME - should generate -r,--prompt string
-         addOption("r", "prompt",         true,  "provide 'less' pager with prompt.").
-         addOption("c", "catman",         false, "used by catman to reformat out of date cat pages.").
-         addOption("7", "ascii",          false, "display ASCII translation or certain latin1 chars.").
-         addOption("t", "troff",          false, "use troff format pages.").
-         //FIXME - should generate -T,--troff-device device
-         addOption("T", "troff-device",   true,  "use groff with selected device.").
-         addOption("Z", "ditroff",        false, "use groff with selected device.").
-         addOption("D", "default",        false, "reset all options to their default values.").
-         //FIXME - should generate -M,--manpath path
-         addOption("M", "manpath",        true,  "set search path for manual pages to 'path'.").
-         //FIXME - should generate -P,--pager pager
-         addOption("P", "pager",          true,  "use program 'pager' to display output.").
-         //FIXME - should generate -S,--sections list
-         addOption("S", "sections",       true,  "use colon separated section list.").
-         //FIXME - should generate -m,--systems system
-         addOption("m", "systems",        true,  "search for man pages from other unix system(s).").
-         //FIXME - should generate -L,--locale locale
-         addOption("L", "locale",         true,  "defaine the locale for this particular man search.").
-         //FIXME - should generate -p,--preprocessor string
-         addOption("p", "preprocessor",   true,  "string indicates which preprocessor to run.\n" +
-                                                 " e - [n]eqn  p - pic     t - tbl\n" +
-                                                 " g - grap    r - refer   v - vgrind").
-         addOption("V", "version",        false, "show version.").
-         addOption("h", "help",           false, "show this usage message.");
-
-      HelpFormatter hf = new HelpFormatter();
-      //hf.printHelp(cmdLine, opts);
-      hf.printHelp(60, cmdLine, null, opts, null);
-   }
-
-   static void bzip2Example()
-   {
-      System.out.println( "Coming soon" );
-   }
-
-   static void lsExample()
-   {
-      System.out.println( "Coming soon" );
-   }
-
-
-   // -------------------------------------------------------------- Attributes
-
-   // ------------------------------------------------------------ Constructors
-   
-   // ------------------------------------------------------------------ Public
-
-   // --------------------------------------------------------------- Protected
-
-   // ------------------------------------------------------- Package protected   
-   
-   // ----------------------------------------------------------------- Private
-   
-   // ----------------------------------------------------------- Inner classes
-
-}
diff --git a/src/test/org/apache/commons/cli/HelpFormatterTest.java b/src/test/org/apache/commons/cli/HelpFormatterTest.java
index 5b8fbf3..10ecab3 100644
--- a/src/test/org/apache/commons/cli/HelpFormatterTest.java
+++ b/src/test/org/apache/commons/cli/HelpFormatterTest.java
@@ -14,13 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
 import java.io.ByteArrayOutputStream;
 import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Comparator;
 
 import junit.framework.TestCase;
-import junit.framework.TestSuite;
 
 /** 
  * Test case for the HelpFormatter class 
@@ -28,160 +30,170 @@ import junit.framework.TestSuite;
  * @author Slawek Zachcial
  * @author John Keyes ( john at integralsource.com )
  * @author brianegge
- **/
+ */
 public class HelpFormatterTest extends TestCase
 {
+    private static final String EOL = System.getProperty("line.separator");
+
+    public void testFindWrapPos() throws Exception
+    {
+        HelpFormatter hf = new HelpFormatter();
+
+        String text = "This is a test.";
+        //text width should be max 8; the wrap position is 7
+        assertEquals("wrap position", 7, hf.findWrapPos(text, 8, 0));
+        //starting from 8 must give -1 - the wrap pos is after end
+        assertEquals("wrap position 2", -1, hf.findWrapPos(text, 8, 8));
+        //if there is no a good position before width to make a wrapping look for the next one
+        text = "aaaa aa";
+        assertEquals("wrap position 3", 4, hf.findWrapPos(text, 3, 0));
+    }
+
+    public void testPrintWrapped() throws Exception
+    {
+        StringBuffer sb = new StringBuffer();
+        HelpFormatter hf = new HelpFormatter();
+
+        String text = "This is a test.";
+
+        String expected = "This is a" + hf.getNewLine() + "test.";
+        hf.renderWrappedText(sb, 12, 0, text);
+        assertEquals("single line text", expected, sb.toString());
+
+        sb.setLength(0);
+        expected = "This is a" + hf.getNewLine() + "    test.";
+        hf.renderWrappedText(sb, 12, 4, text);
+        assertEquals("single line padded text", expected, sb.toString());
+
+        text = "  -p,--period <PERIOD>  PERIOD is time duration of form " +
+               "DATE[-DATE] where DATE has form YYYY[MM[DD]]";
+
+        sb.setLength(0);
+        expected = "  -p,--period <PERIOD>  PERIOD is time duration of" +
+                hf.getNewLine() +
+                "                        form DATE[-DATE] where DATE" +
+                hf.getNewLine() +
+                "                        has form YYYY[MM[DD]]";
+        hf.renderWrappedText(sb, 53, 24, text);
+        assertEquals("single line padded text 2", expected, sb.toString());
+
+        text = "aaaa aaaa aaaa" + hf.getNewLine() +
+               "aaaaaa" + hf.getNewLine() +
+               "aaaaa";
+
+        expected = text;
+        sb.setLength(0);
+        hf.renderWrappedText(sb, 16, 0, text);
+        assertEquals("multi line text", expected, sb.toString());
+
+        expected = "aaaa aaaa aaaa" + hf.getNewLine() +
+                   "    aaaaaa" + hf.getNewLine() +
+                   "    aaaaa";
+        sb.setLength(0);
+        hf.renderWrappedText(sb, 16, 4, text);
+        assertEquals("multi-line padded text", expected, sb.toString());
+    }
+
+    public void testPrintOptions() throws Exception
+    {
+        StringBuffer sb = new StringBuffer();
+        HelpFormatter hf = new HelpFormatter();
+        final int leftPad = 1;
+        final int descPad = 3;
+        final String lpad = hf.createPadding(leftPad);
+        final String dpad = hf.createPadding(descPad);
+        Options options = null;
+        String expected = null;
+
+        options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa");
+        expected = lpad + "-a" + dpad + "aaaa aaaa aaaa aaaa aaaa";
+        hf.renderOptions(sb, 60, options, leftPad, descPad);
+        assertEquals("simple non-wrapped option", expected, sb.toString());
+
+        int nextLineTabStop = leftPad + descPad + "-a".length();
+        expected = lpad + "-a" + dpad + "aaaa aaaa aaaa" + hf.getNewLine() +
+                   hf.createPadding(nextLineTabStop) + "aaaa aaaa";
+        sb.setLength(0);
+        hf.renderOptions(sb, nextLineTabStop + 17, options, leftPad, descPad);
+        assertEquals("simple wrapped option", expected, sb.toString());
+
+
+        options = new Options().addOption("a", "aaa", false, "dddd dddd dddd dddd");
+        expected = lpad + "-a,--aaa" + dpad + "dddd dddd dddd dddd";
+        sb.setLength(0);
+        hf.renderOptions(sb, 60, options, leftPad, descPad);
+        assertEquals("long non-wrapped option", expected, sb.toString());
 
-   private static final String EOL = System.getProperty("line.separator");
-
-   public static void main( String[] args )
-   {
-      String[] testName = { HelpFormatterTest.class.getName() };
-      junit.textui.TestRunner.main(testName);
-   }
-
-   public static TestSuite suite()
-   {
-      return new TestSuite(HelpFormatterTest.class);
-   }
-
-   public HelpFormatterTest( String s )
-   {
-      super( s );
-   }
-
-   public void testFindWrapPos()
-      throws Exception
-   {
-      HelpFormatter hf = new HelpFormatter();
-
-      String text = "This is a test.";
-      //text width should be max 8; the wrap postition is 7
-      assertEquals("wrap position", 7, hf.findWrapPos(text, 8, 0));
-      //starting from 8 must give -1 - the wrap pos is after end
-      assertEquals("wrap position 2", -1, hf.findWrapPos(text, 8, 8));
-      //if there is no a good position before width to make a wrapping look for the next one
-      text = "aaaa aa";
-      assertEquals("wrap position 3", 4, hf.findWrapPos(text, 3, 0));
-   }
-
-   public void testPrintWrapped()
-      throws Exception
-   {
-      StringBuffer sb = new StringBuffer();
-      HelpFormatter hf = new HelpFormatter();
-
-      String text = "This is a test.";
-      String expected;
-
-      expected = "This is a" + hf.getNewLine() + "test.";
-      hf.renderWrappedText(sb, 12, 0, text);
-      assertEquals("single line text", expected, sb.toString());
-
-      sb.setLength(0);
-      expected = "This is a" + hf.getNewLine() + "    test.";
-      hf.renderWrappedText(sb, 12, 4, text);
-      assertEquals("single line padded text", expected, sb.toString());
-
-      text =
-         "aaaa aaaa aaaa" + hf.getNewLine() +
-         "aaaaaa" + hf.getNewLine() +
-         "aaaaa";
-
-      expected = text;
-      sb.setLength(0);
-      hf.renderWrappedText(sb, 16, 0, text);
-      assertEquals("multi line text", expected, sb.toString());
-
-      expected =
-         "aaaa aaaa aaaa" + hf.getNewLine() +
-         "    aaaaaa" + hf.getNewLine() +
-         "    aaaaa";
-      sb.setLength(0);
-      hf.renderWrappedText(sb, 16, 4, text);
-      assertEquals("multi-line padded text", expected, sb.toString());
-   }
-
-   public void testPrintOptions()
-   throws Exception
-   {
-       StringBuffer sb = new StringBuffer();
-       HelpFormatter hf = new HelpFormatter();
-       final int leftPad = 1;
-       final int descPad = 3;
-       final String lpad = hf.createPadding(leftPad);
-       final String dpad = hf.createPadding(descPad);
-       Options options = null;
-       String expected = null;
-
-       options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa");
-       expected = lpad + "-a" + dpad + "aaaa aaaa aaaa aaaa aaaa";
-       hf.renderOptions(sb, 60, options, leftPad, descPad);
-       assertEquals("simple non-wrapped option", expected, sb.toString());
-
-       int nextLineTabStop = leftPad+descPad+"-a".length();
-       expected =
-           lpad + "-a" + dpad + "aaaa aaaa aaaa" + hf.getNewLine() +
-           hf.createPadding(nextLineTabStop) + "aaaa aaaa";
-       sb.setLength(0);
-       hf.renderOptions(sb, nextLineTabStop+17, options, leftPad, descPad);
-       assertEquals("simple wrapped option", expected, sb.toString());
-
-
-       options = new Options().addOption("a", "aaa", false, "dddd dddd dddd dddd");
-       expected = lpad + "-a,--aaa" + dpad + "dddd dddd dddd dddd";
-       sb.setLength(0);
-       hf.renderOptions(sb, 60, options, leftPad, descPad);
-       assertEquals("long non-wrapped option", expected, sb.toString());
-
-       nextLineTabStop = leftPad+descPad+"-a,--aaa".length();
-       expected =
-           lpad + "-a,--aaa" + dpad + "dddd dddd" + hf.getNewLine() +
-           hf.createPadding(nextLineTabStop) + "dddd dddd";
-       sb.setLength(0);
-       hf.renderOptions(sb, 25, options, leftPad, descPad);
-       assertEquals("long wrapped option", expected, sb.toString());
-
-       options = new Options().
-           addOption("a", "aaa", false, "dddd dddd dddd dddd").
-           addOption("b", false, "feeee eeee eeee eeee");
-       expected =
-           lpad + "-a,--aaa" + dpad + "dddd dddd" + hf.getNewLine() +
-           hf.createPadding(nextLineTabStop) + "dddd dddd" + hf.getNewLine() +
-           lpad + "-b      " + dpad + "feeee eeee" + hf.getNewLine() +
-           hf.createPadding(nextLineTabStop) + "eeee eeee";
-       sb.setLength(0);
-       hf.renderOptions(sb, 25, options, leftPad, descPad);
-       assertEquals("multiple wrapped options", expected, sb.toString());
-   }
-
-   public void testAutomaticUsage()
-   throws Exception
-   {
-       HelpFormatter hf = new HelpFormatter();
-       Options options = null;
-       String expected = "usage: app [-a]";
-       ByteArrayOutputStream out = new ByteArrayOutputStream( );
-       PrintWriter pw = new PrintWriter( out );
-
-       options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa");
-       hf.printUsage( pw, 60, "app", options );
-       pw.flush();
-       assertEquals("simple auto usage", expected, out.toString().trim());
-       out.reset();
-
-       expected = "usage: app [-a] [-b]";
-       options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa")
-       .addOption("b", false, "bbb" );
-       hf.printUsage( pw, 60, "app", options );
-       pw.flush();
-       assertEquals("simple auto usage", expected, out.toString().trim());
-       out.reset();
-   }
+        nextLineTabStop = leftPad + descPad + "-a,--aaa".length();
+        expected = lpad + "-a,--aaa" + dpad + "dddd dddd" + hf.getNewLine() +
+                   hf.createPadding(nextLineTabStop) + "dddd dddd";
+        sb.setLength(0);
+        hf.renderOptions(sb, 25, options, leftPad, descPad);
+        assertEquals("long wrapped option", expected, sb.toString());
+
+        options = new Options().
+                addOption("a", "aaa", false, "dddd dddd dddd dddd").
+                addOption("b", false, "feeee eeee eeee eeee");
+        expected = lpad + "-a,--aaa" + dpad + "dddd dddd" + hf.getNewLine() +
+                   hf.createPadding(nextLineTabStop) + "dddd dddd" + hf.getNewLine() +
+                   lpad + "-b      " + dpad + "feeee eeee" + hf.getNewLine() +
+                   hf.createPadding(nextLineTabStop) + "eeee eeee";
+        sb.setLength(0);
+        hf.renderOptions(sb, 25, options, leftPad, descPad);
+        assertEquals("multiple wrapped options", expected, sb.toString());
+    }
+
+    public void testPrintHelpWithEmptySyntax()
+    {
+        HelpFormatter formatter = new HelpFormatter();
+        try
+        {
+            formatter.printHelp(null, new Options());
+            fail("null command line syntax should be rejected");
+        }
+        catch (IllegalArgumentException e)
+        {
+            // expected
+        }
+
+        try
+        {
+            formatter.printHelp("", new Options());
+            fail("empty command line syntax should be rejected");
+        }
+        catch (IllegalArgumentException e)
+        {
+            // expected
+        }
+    }
+
+    public void testAutomaticUsage() throws Exception
+    {
+        HelpFormatter hf = new HelpFormatter();
+        Options options = null;
+        String expected = "usage: app [-a]";
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        PrintWriter pw = new PrintWriter(out);
+
+        options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa");
+        hf.printUsage(pw, 60, "app", options);
+        pw.flush();
+        assertEquals("simple auto usage", expected, out.toString().trim());
+        out.reset();
+
+        expected = "usage: app [-a] [-b]";
+        options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa")
+                .addOption("b", false, "bbb");
+        hf.printUsage(pw, 60, "app", options);
+        pw.flush();
+        assertEquals("simple auto usage", expected, out.toString().trim());
+        out.reset();
+    }
 
     // This test ensures the options are properly sorted
     // See https://issues.apache.org/jira/browse/CLI-131
-    public void testPrintUsage() {
+    public void testPrintUsage()
+    {
         Option optionA = new Option("a", "first");
         Option optionB = new Option("b", "second");
         Option optionC = new Option("c", "third");
@@ -197,4 +209,245 @@ public class HelpFormatterTest extends TestCase
         assertEquals("usage: app [-a] [-b] [-c]" + EOL, bytesOut.toString());
     }
 
+    // uses the test for CLI-131 to implement CLI-155
+    public void testPrintSortedUsage()
+    {
+        Options opts = new Options();
+        opts.addOption(new Option("a", "first"));
+        opts.addOption(new Option("b", "second"));
+        opts.addOption(new Option("c", "third"));
+
+        HelpFormatter helpFormatter = new HelpFormatter();
+        helpFormatter.setOptionComparator(new Comparator()
+        {
+            public int compare(Object o1, Object o2)
+            {
+                // reverses the fuctionality of the default comparator
+                Option opt1 = (Option) o1;
+                Option opt2 = (Option) o2;
+                return opt2.getKey().compareToIgnoreCase(opt1.getKey());
+            }
+        });
+
+        StringWriter out = new StringWriter();
+        helpFormatter.printUsage(new PrintWriter(out), 80, "app", opts);
+
+        assertEquals("usage: app [-c] [-b] [-a]" + EOL, out.toString());
+    }
+
+    public void testPrintSortedUsageWithNullComparator()
+    {
+        Options opts = new Options();
+        opts.addOption(new Option("a", "first"));
+        opts.addOption(new Option("b", "second"));
+        opts.addOption(new Option("c", "third"));
+
+        HelpFormatter helpFormatter = new HelpFormatter();
+        helpFormatter.setOptionComparator(null);
+
+        StringWriter out = new StringWriter();
+        helpFormatter.printUsage(new PrintWriter(out), 80, "app", opts);
+
+        assertEquals("usage: app [-a] [-b] [-c]" + EOL, out.toString());
+    }
+
+    public void testPrintOptionGroupUsage()
+    {
+        OptionGroup group = new OptionGroup();
+        group.addOption(OptionBuilder.create("a"));
+        group.addOption(OptionBuilder.create("b"));
+        group.addOption(OptionBuilder.create("c"));
+
+        Options options = new Options();
+        options.addOptionGroup(group);
+
+        StringWriter out = new StringWriter();
+
+        HelpFormatter formatter = new HelpFormatter();
+        formatter.printUsage(new PrintWriter(out), 80, "app", options);
+
+        assertEquals("usage: app [-a | -b | -c]" + EOL, out.toString());
+    }
+
+    public void testPrintRequiredOptionGroupUsage()
+    {
+        OptionGroup group = new OptionGroup();
+        group.addOption(OptionBuilder.create("a"));
+        group.addOption(OptionBuilder.create("b"));
+        group.addOption(OptionBuilder.create("c"));
+        group.setRequired(true);
+
+        Options options = new Options();
+        options.addOptionGroup(group);
+
+        StringWriter out = new StringWriter();
+
+        HelpFormatter formatter = new HelpFormatter();
+        formatter.printUsage(new PrintWriter(out), 80, "app", options);
+
+        assertEquals("usage: app -a | -b | -c" + EOL, out.toString());
+    }
+
+    public void testPrintOptionWithEmptyArgNameUsage()
+    {
+        Option option = new Option("f", true, null);
+        option.setArgName("");
+        option.setRequired(true);
+
+        Options options = new Options();
+        options.addOption(option);
+
+        StringWriter out = new StringWriter();
+
+        HelpFormatter formatter = new HelpFormatter();
+        formatter.printUsage(new PrintWriter(out), 80, "app", options);
+
+        assertEquals("usage: app -f" + EOL, out.toString());
+    }
+
+    public void testRtrim()
+    {
+        HelpFormatter formatter = new HelpFormatter();
+
+        assertEquals(null, formatter.rtrim(null));
+        assertEquals("", formatter.rtrim(""));
+        assertEquals("  foo", formatter.rtrim("  foo  "));
+    }
+
+    public void testAccessors()
+    {
+        HelpFormatter formatter = new HelpFormatter();
+
+        formatter.setArgName("argname");
+        assertEquals("arg name", "argname", formatter.getArgName());
+
+        formatter.setDescPadding(3);
+        assertEquals("desc padding", 3, formatter.getDescPadding());
+
+        formatter.setLeftPadding(7);
+        assertEquals("left padding", 7, formatter.getLeftPadding());
+
+        formatter.setLongOptPrefix("~~");
+        assertEquals("long opt prefix", "~~", formatter.getLongOptPrefix());
+
+        formatter.setNewLine("\n");
+        assertEquals("new line", "\n", formatter.getNewLine());
+
+        formatter.setOptPrefix("~");
+        assertEquals("opt prefix", "~", formatter.getOptPrefix());
+
+        formatter.setSyntaxPrefix("-> ");
+        assertEquals("syntax prefix", "-> ", formatter.getSyntaxPrefix());
+
+        formatter.setWidth(80);
+        assertEquals("width", 80, formatter.getWidth());
+    }
+    
+    public void testHeaderStartingWithLineSeparator()
+    {
+        // related to Bugzilla #21215
+        Options options = new Options();
+        HelpFormatter formatter = new HelpFormatter();
+        String header = EOL + "Header";
+        String footer = "Footer";
+        StringWriter out = new StringWriter();
+        formatter.printHelp(new PrintWriter(out), 80, "foobar", header, options, 2, 2, footer, true);
+        assertEquals(
+                "usage: foobar" + EOL +
+                "" + EOL +
+                "Header" + EOL +
+                "" + EOL +
+                "Footer" + EOL
+                , out.toString());
+    }
+
+    public void testOptionWithoutShortFormat()
+    {
+        // related to Bugzilla #19383 (CLI-67)
+        Options options = new Options();
+        options.addOption(new Option("a", "aaa", false, "aaaaaaa"));
+        options.addOption(new Option(null, "bbb", false, "bbbbbbb"));
+        options.addOption(new Option("c", null, false, "ccccccc"));
+
+        HelpFormatter formatter = new HelpFormatter();
+        StringWriter out = new StringWriter();
+        formatter.printHelp(new PrintWriter(out), 80, "foobar", "", options, 2, 2, "", true);
+        assertEquals(
+                "usage: foobar [-a] [--bbb] [-c]" + EOL +
+                "  -a,--aaa  aaaaaaa" + EOL +
+                "     --bbb  bbbbbbb" + EOL +
+                "  -c        ccccccc" + EOL
+                , out.toString());
+    }
+    
+
+    public void testOptionWithoutShortFormat2()
+    {
+        // related to Bugzilla #27635 (CLI-26)
+        Option help = new Option("h", "help", false, "print this message");
+        Option version = new Option("v", "version", false, "print version information");
+        Option newRun = new Option("n", "new", false, "Create NLT cache entries only for new items");
+        Option trackerRun = new Option("t", "tracker", false, "Create NLT cache entries only for tracker items");
+        
+        Option timeLimit = OptionBuilder.withLongOpt("limit")
+                                        .hasArg()
+                                        .withValueSeparator()
+                                        .withDescription("Set time limit for execution, in mintues")
+                                        .create("l");
+        
+        Option age = OptionBuilder.withLongOpt("age")
+                                        .hasArg()
+                                        .withValueSeparator()
+                                        .withDescription("Age (in days) of cache item before being recomputed")
+                                        .create("a");
+        
+        Option server = OptionBuilder.withLongOpt("server")
+                                        .hasArg()
+                                        .withValueSeparator()
+                                        .withDescription("The NLT server address")
+                                        .create("s");
+        
+        Option numResults = OptionBuilder.withLongOpt("results")
+                                        .hasArg()
+                                        .withValueSeparator()
+                                        .withDescription("Number of results per item")
+                                        .create("r");
+        
+        Option configFile = OptionBuilder.withLongOpt("config")
+                                        .hasArg()
+                                        .withValueSeparator()
+                                        .withDescription("Use the specified configuration file")
+                                        .create();
+        
+        Options mOptions = new Options();
+        mOptions.addOption(help);
+        mOptions.addOption(version);
+        mOptions.addOption(newRun);
+        mOptions.addOption(trackerRun);
+        mOptions.addOption(timeLimit);
+        mOptions.addOption(age);
+        mOptions.addOption(server);
+        mOptions.addOption(numResults);
+        mOptions.addOption(configFile);
+        
+        HelpFormatter formatter = new HelpFormatter();
+        final String EOL = System.getProperty("line.separator");
+        StringWriter out = new StringWriter();
+        formatter.printHelp(new PrintWriter(out),80,"commandline","header",mOptions,2,2,"footer",true);
+        assertEquals(
+                "usage: commandline [-a <arg>] [--config <arg>] [-h] [-l <arg>] [-n] [-r <arg>]" + EOL +
+                "       [-s <arg>] [-t] [-v]" + EOL +
+                "header"+EOL+
+                "  -a,--age <arg>      Age (in days) of cache item before being recomputed"+EOL+
+                "     --config <arg>   Use the specified configuration file"+EOL+
+                "  -h,--help           print this message"+EOL+
+                "  -l,--limit <arg>    Set time limit for execution, in mintues"+EOL+
+                "  -n,--new            Create NLT cache entries only for new items"+EOL+
+                "  -r,--results <arg>  Number of results per item"+EOL+
+                "  -s,--server <arg>   The NLT server address"+EOL+
+                "  -t,--tracker        Create NLT cache entries only for tracker items"+EOL+
+                "  -v,--version        print version information"+EOL+
+                "footer"+EOL
+                ,out.toString());
+    }
 }
diff --git a/src/test/org/apache/commons/cli/LongOptionWithShort.java b/src/test/org/apache/commons/cli/LongOptionWithShort.java
deleted file mode 100644
index 0fb46e3..0000000
--- a/src/test/org/apache/commons/cli/LongOptionWithShort.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.cli;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-
-/**
- * <p>
- * This is a collection of tests that test real world
- * applications command lines focusing on options with
- * long and short names.
- * </p>
- */
-public class LongOptionWithShort extends TestCase {
-    public LongOptionWithShort(String name) {
-        super(name);
-    }
-
-    public static Test suite() {
-        return new TestSuite(LongOptionWithShort.class);
-    }
-
-    /**
-     *
-     */
-    public void testLongOptionWithShort() {
-        Option help = new Option("h", "help", false, "print this message");
-        Option version = new Option("v", "version", false,
-                "print version information");
-        Option newRun = new Option("n", "new", false,
-                "Create NLT cache entries only for new items");
-        Option trackerRun = new Option("t", "tracker", false,
-                "Create NLT cache entries only for tracker items");
-
-        Option timeLimit = OptionBuilder.withLongOpt("limit").hasArg()
-                                        .withValueSeparator()
-                                        .withDescription("Set time limit for execution, in mintues")
-                                        .create("l");
-
-        Option age = OptionBuilder.withLongOpt("age").hasArg()
-                                  .withValueSeparator()
-                                  .withDescription("Age (in days) of cache item before being recomputed")
-                                  .create("a");
-
-        Option server = OptionBuilder.withLongOpt("server").hasArg()
-                                     .withValueSeparator()
-                                     .withDescription("The NLT server address")
-                                     .create("s");
-
-        Option numResults = OptionBuilder.withLongOpt("results").hasArg()
-                                         .withValueSeparator()
-                                         .withDescription("Number of results per item")
-                                         .create("r");
-
-        Option configFile = OptionBuilder.withLongOpt("file").hasArg()
-                                         .withValueSeparator()
-                                         .withDescription("Use the specified configuration file")
-                                         .create();
-
-        Options options = new Options();
-        options.addOption(help);
-        options.addOption(version);
-        options.addOption(newRun);
-        options.addOption(trackerRun);
-        options.addOption(timeLimit);
-        options.addOption(age);
-        options.addOption(server);
-        options.addOption(numResults);
-        options.addOption(configFile);
-
-        // create the command line parser
-        CommandLineParser parser = new PosixParser();
-
-        String[] args = new String[] {
-                "-v",
-                "-l",
-                "10",
-                "-age",
-                "5",
-                "-file",
-                "filename"
-            };
-
-        try {
-            CommandLine line = parser.parse(options, args);
-            assertTrue(line.hasOption("v"));
-            assertEquals(line.getOptionValue("l"), "10");
-            assertEquals(line.getOptionValue("limit"), "10");
-            assertEquals(line.getOptionValue("a"), "5");
-            assertEquals(line.getOptionValue("age"), "5");
-            assertEquals(line.getOptionValue("file"), "filename");
-        }
-        catch (ParseException exp) {
-            fail("Unexpected exception:" + exp.getMessage());
-        }
-    }
-}
diff --git a/src/test/org/apache/commons/cli/OptionBuilderTest.java b/src/test/org/apache/commons/cli/OptionBuilderTest.java
index ff460f4..b445a67 100644
--- a/src/test/org/apache/commons/cli/OptionBuilderTest.java
+++ b/src/test/org/apache/commons/cli/OptionBuilderTest.java
@@ -14,28 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
-import junit.framework.Test;
 import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-import junit.textui.TestRunner;
 
 public class OptionBuilderTest extends TestCase {
 
-    public OptionBuilderTest( String name ) {
-        super( name );
-    }
-
-    public static Test suite() { 
-        return new TestSuite( OptionBuilderTest.class ); 
-    }
-
-    public static void main( String args[] ) { 
-        TestRunner.run( suite() );
-    }
-
     public void testCompleteOption( ) {
         Option simple = OptionBuilder.withLongOpt( "simple option")
                                      .hasArg( )
@@ -103,30 +88,19 @@ public class OptionBuilderTest extends TestCase {
         assertTrue( !base.hasArg() );
     }
 
-    public void testSpecialOptChars() {
-
+    public void testSpecialOptChars() throws Exception
+    {
         // '?'
-        try {
-            Option opt = OptionBuilder.withDescription( "help options" )
-                                      .create( '?' );
-            assertEquals( "?", opt.getOpt() );
-        }
-        catch( IllegalArgumentException arg ) {
-            fail( "IllegalArgumentException caught" );
-        }
+        Option opt1 = OptionBuilder.withDescription("help options").create('?');
+        assertEquals("?", opt1.getOpt());
 
         // '@'
-        try {
-            Option opt = OptionBuilder.withDescription( "read from stdin" )
-                                      .create( '@' );
-            assertEquals( "@", opt.getOpt() );
-        }
-        catch( IllegalArgumentException arg ) {
-            fail( "IllegalArgumentException caught" );
-        }
+        Option opt2 = OptionBuilder.withDescription("read from stdin").create('@');
+        assertEquals("@", opt2.getOpt());
     }
 
-    public void testOptionArgNumbers() {
+    public void testOptionArgNumbers()
+    {
         Option opt = OptionBuilder.withDescription( "option description" )
                                   .hasArgs( 2 )
                                   .create( 'o' );
@@ -136,8 +110,7 @@ public class OptionBuilderTest extends TestCase {
     public void testIllegalOptions() {
         // bad single character option
         try {
-            Option opt = OptionBuilder.withDescription( "option description" )
-                                      .create( '"' );
+            OptionBuilder.withDescription( "option description" ).create( '"' );
             fail( "IllegalArgumentException not caught" );
         }
         catch( IllegalArgumentException exp ) {
@@ -162,4 +135,43 @@ public class OptionBuilderTest extends TestCase {
             fail( "IllegalArgumentException caught" );
         }
     }
-}
\ No newline at end of file
+
+    public void testCreateIncompleteOption() {
+        try
+        {
+            OptionBuilder.hasArg().create();
+            fail("Incomplete option should be rejected");
+        }
+        catch (IllegalArgumentException e)
+        {
+            // expected
+            
+            // implicitly reset the builder
+            OptionBuilder.create( "opt" );
+        }
+    }
+
+    public void testBuilderIsResettedAlways() {
+        try
+        {
+            OptionBuilder.withDescription("JUnit").create('"');
+            fail("IllegalArgumentException expected");
+        }
+        catch (IllegalArgumentException e)
+        {
+            // expected
+        }
+        assertNull("we inherited a description", OptionBuilder.create('x').getDescription());
+
+        try
+        {
+            OptionBuilder.withDescription("JUnit").create();
+            fail("IllegalArgumentException expected");
+        }
+        catch (IllegalArgumentException e)
+        {
+            // expected
+        }
+        assertNull("we inherited a description", OptionBuilder.create('x').getDescription());
+    }
+}
diff --git a/src/test/org/apache/commons/cli/OptionGroupTest.java b/src/test/org/apache/commons/cli/OptionGroupTest.java
index 6f6a6a6..7dcf219 100644
--- a/src/test/org/apache/commons/cli/OptionGroupTest.java
+++ b/src/test/org/apache/commons/cli/OptionGroupTest.java
@@ -14,33 +14,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
-import junit.framework.Test;
 import junit.framework.TestCase;
-import junit.framework.TestSuite;
 
 /**
  * @author John Keyes (john at integralsource.com)
- * @version $Revision: 542144 $
+ * @version $Revision: 751120 $
  */
 public class OptionGroupTest extends TestCase
 {
-
     private Options _options = null;
     private CommandLineParser parser = new PosixParser();
 
-
-    public static Test suite() 
-    { 
-        return new TestSuite ( OptionGroupTest.class ); 
-    }
-
-    public OptionGroupTest( String name )
-    {
-        super( name );
-    }
-
     public void setUp()
     {
         Option file = new Option( "f", "file", false, "file to process" );
@@ -68,214 +55,174 @@ public class OptionGroupTest extends TestCase
         _options.addOption( "r", "revision", false, "revision number" );
     }
 
-    public void tearDown()
-    {
-    }
-
-    public void testSingleOptionFromGroup()
+    public void testSingleOptionFromGroup() throws Exception
     {
         String[] args = new String[] { "-f" };
 
-        try
-        {
-            CommandLine cl = parser.parse( _options, args);
-
-            assertTrue( "Confirm -r is NOT set", !cl.hasOption("r") );
-            assertTrue( "Confirm -f is set", cl.hasOption("f") );
-            assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
-            assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
-            assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
-            assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
+        CommandLine cl = parser.parse( _options, args);
+
+        assertTrue( "Confirm -r is NOT set", !cl.hasOption("r") );
+        assertTrue( "Confirm -f is set", cl.hasOption("f") );
+        assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+        assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
+        assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+        assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
     }
 
-    public void testSingleOption()
+    public void testSingleOption() throws Exception
     {
         String[] args = new String[] { "-r" };
 
-        try
-        {
-            CommandLine cl = parser.parse( _options, args);
-
-            assertTrue( "Confirm -r is set", cl.hasOption("r") );
-            assertTrue( "Confirm -f is NOT set", !cl.hasOption("f") );
-            assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
-            assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
-            assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
-            assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
+        CommandLine cl = parser.parse( _options, args);
+
+        assertTrue( "Confirm -r is set", cl.hasOption("r") );
+        assertTrue( "Confirm -f is NOT set", !cl.hasOption("f") );
+        assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+        assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
+        assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+        assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
     }
 
-    public void testTwoValidOptions()
+    public void testTwoValidOptions() throws Exception
     {
         String[] args = new String[] { "-r", "-f" };
 
-        try
-        {
-            CommandLine cl = parser.parse( _options, args);
-
-            assertTrue( "Confirm -r is set", cl.hasOption("r") );
-            assertTrue( "Confirm -f is set", cl.hasOption("f") );
-            assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
-            assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
-            assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
-            assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
+        CommandLine cl = parser.parse( _options, args);
+
+        assertTrue( "Confirm -r is set", cl.hasOption("r") );
+        assertTrue( "Confirm -f is set", cl.hasOption("f") );
+        assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+        assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
+        assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+        assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
     }
 
-    public void testSingleLongOption()
+    public void testSingleLongOption() throws Exception
     {
         String[] args = new String[] { "--file" };
 
-        try
-        {
-            CommandLine cl = parser.parse( _options, args);
-
-            assertTrue( "Confirm -r is NOT set", !cl.hasOption("r") );
-            assertTrue( "Confirm -f is set", cl.hasOption("f") );
-            assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
-            assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
-            assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
-            assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
+        CommandLine cl = parser.parse( _options, args);
+
+        assertTrue( "Confirm -r is NOT set", !cl.hasOption("r") );
+        assertTrue( "Confirm -f is set", cl.hasOption("f") );
+        assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+        assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
+        assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+        assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
     }
 
-    public void testTwoValidLongOptions()
+    public void testTwoValidLongOptions() throws Exception
     {
         String[] args = new String[] { "--revision", "--file" };
 
-        try
-        {
-            CommandLine cl = parser.parse( _options, args);
-
-            assertTrue( "Confirm -r is set", cl.hasOption("r") );
-            assertTrue( "Confirm -f is set", cl.hasOption("f") );
-            assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
-            assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
-            assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
-            assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
+        CommandLine cl = parser.parse( _options, args);
+
+        assertTrue( "Confirm -r is set", cl.hasOption("r") );
+        assertTrue( "Confirm -f is set", cl.hasOption("f") );
+        assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+        assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
+        assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+        assertTrue( "Confirm no extra args", cl.getArgList().size() == 0);
     }
 
-    public void testNoOptionsExtraArgs()
+    public void testNoOptionsExtraArgs() throws Exception
     {
         String[] args = new String[] { "arg1", "arg2" };
 
-        try
-        {
-            CommandLine cl = parser.parse( _options, args);
-
-            assertTrue( "Confirm -r is NOT set", !cl.hasOption("r") );
-            assertTrue( "Confirm -f is NOT set", !cl.hasOption("f") );
-            assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
-            assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
-            assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
-            assertTrue( "Confirm TWO extra args", cl.getArgList().size() == 2);
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
+        CommandLine cl = parser.parse( _options, args);
+
+        assertTrue( "Confirm -r is NOT set", !cl.hasOption("r") );
+        assertTrue( "Confirm -f is NOT set", !cl.hasOption("f") );
+        assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+        assertTrue( "Confirm -s is NOT set", !cl.hasOption("s") );
+        assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+        assertTrue( "Confirm TWO extra args", cl.getArgList().size() == 2);
     }
 
-    public void testTwoOptionsFromGroup()
+    public void testTwoOptionsFromGroup() throws Exception
     {
         String[] args = new String[] { "-f", "-d" };
 
         try
         {
-            CommandLine cl = parser.parse( _options, args);
+            parser.parse( _options, args);
             fail( "two arguments from group not allowed" );
         }
-        catch (ParseException e)
+        catch (AlreadySelectedException e)
         {
-            if( !( e instanceof AlreadySelectedException ) )
-            {
-                fail( "incorrect exception caught:" + e.getMessage() );
-            }
+            assertNotNull("null option group", e.getOptionGroup());
+            assertEquals("selected option", "f", e.getOptionGroup().getSelected());
+            assertEquals("option", "d", e.getOption().getOpt());
         }
     }
 
-    public void testTwoLongOptionsFromGroup()
+    public void testTwoLongOptionsFromGroup() throws Exception
     {
         String[] args = new String[] { "--file", "--directory" };
 
         try
         {
-            CommandLine cl = parser.parse( _options, args);
+            parser.parse(_options, args);
             fail( "two arguments from group not allowed" );
         }
-        catch (ParseException e)
+        catch (AlreadySelectedException e)
         {
-            if( !( e instanceof AlreadySelectedException ) )
-            {
-                fail( "incorrect exception caught:" + e.getMessage() );
-            }
+            assertNotNull("null option group", e.getOptionGroup());
+            assertEquals("selected option", "f", e.getOptionGroup().getSelected());
+            assertEquals("option", "d", e.getOption().getOpt());
         }
     }
 
-    public void testTwoOptionsFromDifferentGroup()
+    public void testTwoOptionsFromDifferentGroup() throws Exception
     {
         String[] args = new String[] { "-f", "-s" };
 
-        try
-        {
-            CommandLine cl = parser.parse( _options, args);
-            assertTrue( "Confirm -r is NOT set", !cl.hasOption("r") );
-            assertTrue( "Confirm -f is set", cl.hasOption("f") );
-            assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
-            assertTrue( "Confirm -s is set", cl.hasOption("s") );
-            assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
-            assertTrue( "Confirm NO extra args", cl.getArgList().size() == 0);
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
+        CommandLine cl = parser.parse( _options, args);
+        assertTrue( "Confirm -r is NOT set", !cl.hasOption("r") );
+        assertTrue( "Confirm -f is set", cl.hasOption("f") );
+        assertTrue( "Confirm -d is NOT set", !cl.hasOption("d") );
+        assertTrue( "Confirm -s is set", cl.hasOption("s") );
+        assertTrue( "Confirm -c is NOT set", !cl.hasOption("c") );
+        assertTrue( "Confirm NO extra args", cl.getArgList().size() == 0);
     }
 
-    public void testValidLongOnlyOptions()
+    public void testValidLongOnlyOptions() throws Exception
     {
-        try
-        {
-            CommandLine cl = parser.parse( _options, new String[]{"--export"});
-            assertTrue( "Confirm --export is set", cl.hasOption("export") );
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-                            
-        try
-        {
-            CommandLine cl = parser.parse( _options, new String[]{"--import"});
-            assertTrue( "Confirm --import is set", cl.hasOption("import") );
+        CommandLine cl1 = parser.parse(_options, new String[]{"--export"});
+        assertTrue("Confirm --export is set", cl1.hasOption("export"));
+
+        CommandLine cl2 = parser.parse(_options, new String[]{"--import"});
+        assertTrue("Confirm --import is set", cl2.hasOption("import"));
+    }
+
+    public void testToString()
+    {
+        OptionGroup group1 = new OptionGroup();
+        group1.addOption(new Option(null, "foo", false, "Foo"));
+        group1.addOption(new Option(null, "bar", false, "Bar"));
+
+        if (!"[--bar Bar, --foo Foo]".equals(group1.toString())) {
+            assertEquals("[--foo Foo, --bar Bar]", group1.toString());
         }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
+
+        OptionGroup group2 = new OptionGroup();
+        group2.addOption(new Option("f", "foo", false, "Foo"));
+        group2.addOption(new Option("b", "bar", false, "Bar"));
+
+        if (!"[-b Bar, -f Foo]".equals(group2.toString())) {
+            assertEquals("[-f Foo, -b Bar]", group2.toString());
         }
     }
 
+    public void testGetNames()
+    {
+        OptionGroup group = new OptionGroup();
+        group.addOption(OptionBuilder.create('a'));
+        group.addOption(OptionBuilder.create('b'));
 
+        assertNotNull("null names", group.getNames());
+        assertEquals(2, group.getNames().size());
+        assertTrue(group.getNames().contains("a"));
+        assertTrue(group.getNames().contains("b"));
+    }
 }
diff --git a/src/test/org/apache/commons/cli/OptionTest.java b/src/test/org/apache/commons/cli/OptionTest.java
index 10af03f..d7b069b 100644
--- a/src/test/org/apache/commons/cli/OptionTest.java
+++ b/src/test/org/apache/commons/cli/OptionTest.java
@@ -1,82 +1,140 @@
-/*
- * 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.cli;
-
-import junit.framework.TestCase;
-
-/**
- * @author brianegge
- */
-public class OptionTest extends TestCase {
-
-   private static class TestOption extends Option {
-        public TestOption(String opt, boolean hasArg, String description) throws IllegalArgumentException {
-            super(opt, hasArg, description);
-        }
-        public boolean addValue(String value) {
-            addValueForProcessing(value);
-            return true;
-        }
-   }
-
-   public void testClear() {
-       TestOption option = new TestOption("x", true, "");
-       assertEquals(0, option.getValuesList().size());
-       option.addValue("a");
-       assertEquals(1, option.getValuesList().size());
-       option.clearValues();
-       assertEquals(0, option.getValuesList().size());
-   }
-
-    // See http://issues.apache.org/jira/browse/CLI-21
-    public void testClone() throws CloneNotSupportedException {
-        TestOption a = new TestOption("a", true, "");
-        TestOption b = (TestOption) a.clone();
-        assertEquals(a, b);
-        assertNotSame(a, b);
-        a.setDescription("a");
-        assertEquals("", b.getDescription());
-        b.setArgs(2);
-        b.addValue("b1");
-        b.addValue("b2");
-        assertEquals(1, a.getArgs());
-        assertEquals(0, a.getValuesList().size());
-        assertEquals(2, b.getValues().length);
-    }
-
-    private static class DefaultOption extends Option {
-
-        private final String defaultValue;
-
-        public DefaultOption(String opt, String description, String defaultValue) throws IllegalArgumentException {
-            super(opt, true, description);
-            this.defaultValue = defaultValue;
-        }
-
-        public String getValue() {
-            return super.getValue() != null ? super.getValue() : defaultValue;
-        }
-    }
-
-    public void testSubclass() throws CloneNotSupportedException {
-        Option option = new DefaultOption("f", "file", "myfile.txt");
-        Option clone = (Option) option.clone();
-        assertEquals("myfile.txt", clone.getValue());
-        assertEquals(DefaultOption.class, clone.getClass());
-    }
-
-}
+/*
+ * 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.cli;
+
+import junit.framework.TestCase;
+
+/**
+ * @author brianegge
+ */
+public class OptionTest extends TestCase
+{
+    private static class TestOption extends Option
+    {
+        public TestOption(String opt, boolean hasArg, String description) throws IllegalArgumentException
+        {
+            super(opt, hasArg, description);
+        }
+
+        public boolean addValue(String value)
+        {
+            addValueForProcessing(value);
+            return true;
+        }
+    }
+
+    public void testClear()
+    {
+        TestOption option = new TestOption("x", true, "");
+        assertEquals(0, option.getValuesList().size());
+        option.addValue("a");
+        assertEquals(1, option.getValuesList().size());
+        option.clearValues();
+        assertEquals(0, option.getValuesList().size());
+    }
+
+    // See http://issues.apache.org/jira/browse/CLI-21
+    public void testClone() throws CloneNotSupportedException
+    {
+        TestOption a = new TestOption("a", true, "");
+        TestOption b = (TestOption) a.clone();
+        assertEquals(a, b);
+        assertNotSame(a, b);
+        a.setDescription("a");
+        assertEquals("", b.getDescription());
+        b.setArgs(2);
+        b.addValue("b1");
+        b.addValue("b2");
+        assertEquals(1, a.getArgs());
+        assertEquals(0, a.getValuesList().size());
+        assertEquals(2, b.getValues().length);
+    }
+
+    private static class DefaultOption extends Option
+    {
+        private final String defaultValue;
+
+        public DefaultOption(String opt, String description, String defaultValue) throws IllegalArgumentException
+        {
+            super(opt, true, description);
+            this.defaultValue = defaultValue;
+        }
+
+        public String getValue()
+        {
+            return super.getValue() != null ? super.getValue() : defaultValue;
+        }
+    }
+
+    public void testSubclass() throws CloneNotSupportedException
+    {
+        Option option = new DefaultOption("f", "file", "myfile.txt");
+        Option clone = (Option) option.clone();
+        assertEquals("myfile.txt", clone.getValue());
+        assertEquals(DefaultOption.class, clone.getClass());
+    }
+
+    public void testHasArgName()
+    {
+        Option option = new Option("f", null);
+
+        option.setArgName(null);
+        assertFalse(option.hasArgName());
+
+        option.setArgName("");
+        assertFalse(option.hasArgName());
+
+        option.setArgName("file");
+        assertTrue(option.hasArgName());
+    }
+
+    public void testHasArgs()
+    {
+        Option option = new Option("f", null);
+
+        option.setArgs(0);
+        assertFalse(option.hasArgs());
+
+        option.setArgs(1);
+        assertFalse(option.hasArgs());
+
+        option.setArgs(10);
+        assertTrue(option.hasArgs());
+
+        option.setArgs(Option.UNLIMITED_VALUES);
+        assertTrue(option.hasArgs());
+
+        option.setArgs(Option.UNINITIALIZED);
+        assertFalse(option.hasArgs());
+    }
+
+    public void testGetValue()
+    {
+        Option option = new Option("f", null);
+        option.setArgs(Option.UNLIMITED_VALUES);
+
+        assertEquals("default", option.getValue("default"));
+        assertEquals(null, option.getValue(0));
+
+        option.addValueForProcessing("foo");
+        
+        assertEquals("foo", option.getValue());
+        assertEquals("foo", option.getValue(0));
+        assertEquals("foo", option.getValue("default"));
+    }
+}
diff --git a/src/test/org/apache/commons/cli/OptionsTest.java b/src/test/org/apache/commons/cli/OptionsTest.java
index af7fac8..24ec03e 100644
--- a/src/test/org/apache/commons/cli/OptionsTest.java
+++ b/src/test/org/apache/commons/cli/OptionsTest.java
@@ -14,63 +14,67 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
 import java.util.ArrayList;
 import java.util.Collection;
 
-import junit.framework.Test;
 import junit.framework.TestCase;
-import junit.framework.TestSuite;
 
 /**
  * @author Rob Oxspring roxspring at apache.org
- * @version $Revision: 544360 $
+ * @version $Revision: 680311 $
  */
 public class OptionsTest extends TestCase
 {
+    public void testSimple()
+    {
+        Options opts = new Options();
 
-    public static Test suite() 
-    { 
-        return new TestSuite ( OptionsTest.class ); 
+        opts.addOption("a", false, "toggle -a");
+        opts.addOption("b", true, "toggle -b");
+
+        assertTrue(opts.hasOption("a"));
+        assertTrue(opts.hasOption("b"));
     }
 
-    public OptionsTest( String name )
+    public void testDuplicateSimple()
     {
-        super( name );
+        Options opts = new Options();
+        opts.addOption("a", false, "toggle -a");
+        opts.addOption("a", true, "toggle -a*");
+
+        assertEquals("last one in wins", "toggle -a*", opts.getOption("a").getDescription());
     }
 
-    public void setUp()
+    public void testLong()
     {
+        Options opts = new Options();
+
+        opts.addOption("a", "--a", false, "toggle -a");
+        opts.addOption("b", "--b", true, "set -b");
+
+        assertTrue(opts.hasOption("a"));
+        assertTrue(opts.hasOption("b"));
     }
 
-    public void tearDown()
+    public void testDuplicateLong()
     {
+        Options opts = new Options();
+        opts.addOption("a", "--a", false, "toggle -a");
+        opts.addOption("a", "--a", false, "toggle -a*");
+        assertEquals("last one in wins", "toggle -a*", opts.getOption("a").getDescription());
     }
-    
-    public void testHelpOptions(){
-        
-        Option longOnly1 = OptionBuilder
-            .withLongOpt("long-only1")
-            .create();
-        
-        Option longOnly2 = OptionBuilder
-            .withLongOpt("long-only2")
-            .create();
-                
-        Option shortOnly1 = OptionBuilder
-            .create("1");
-                
-        Option shortOnly2 = OptionBuilder
-            .create("2");
-                
-        Option bothA = OptionBuilder
-            .withLongOpt("bothA")
-            .create("a");
-                
-        Option bothB = OptionBuilder
-            .withLongOpt("bothB")
-            .create("b");
+
+    public void testHelpOptions()
+    {
+        Option longOnly1 = OptionBuilder.withLongOpt("long-only1").create();
+        Option longOnly2 = OptionBuilder.withLongOpt("long-only2").create();
+        Option shortOnly1 = OptionBuilder.create("1");
+        Option shortOnly2 = OptionBuilder.create("2");
+        Option bothA = OptionBuilder.withLongOpt("bothA").create("a");
+        Option bothB = OptionBuilder.withLongOpt("bothB").create("b");
         
         Options options = new Options();
         options.addOption(longOnly1);
@@ -90,32 +94,69 @@ public class OptionsTest extends TestCase
         
         Collection helpOptions = options.helpOptions();
         
-        assertTrue("Everything in all should be in help",helpOptions.containsAll(allOptions));
-        assertTrue("Everything in help should be in all",allOptions.containsAll(helpOptions));        
+        assertTrue("Everything in all should be in help", helpOptions.containsAll(allOptions));
+        assertTrue("Everything in help should be in all", allOptions.containsAll(helpOptions));        
     }
 
-    public void testMissingOptionException() throws ParseException {
+    public void testMissingOptionException() throws ParseException
+    {
         Options options = new Options();
         options.addOption(OptionBuilder.isRequired().create("f"));
-        try {
+        try
+        {
             new PosixParser().parse(options, new String[0]);
             fail("Expected MissingOptionException to be thrown");
-        } catch (MissingOptionException e) {
+        }
+        catch (MissingOptionException e)
+        {
             assertEquals("Missing required option: f", e.getMessage());
         }
     }
 
-    public void testMissingOptionsException() throws ParseException {
+    public void testMissingOptionsException() throws ParseException
+    {
         Options options = new Options();
         options.addOption(OptionBuilder.isRequired().create("f"));
         options.addOption(OptionBuilder.isRequired().create("x"));
-        try {
+        try
+        {
             new PosixParser().parse(options, new String[0]);
             fail("Expected MissingOptionException to be thrown");
-        } catch (MissingOptionException e) {
-            assertEquals("Missing required options: fx", e.getMessage());
+        }
+        catch (MissingOptionException e)
+        {
+            assertEquals("Missing required options: f, x", e.getMessage());
         }
     }
 
-}
+    public void testToString()
+    {
+        Options options = new Options();
+        options.addOption("f", "foo", true, "Foo");
+        options.addOption("b", "bar", false, "Bar");
 
+        String s = options.toString();
+        assertNotNull("null string returned", s);
+        assertTrue("foo option missing", s.toLowerCase().indexOf("foo") != -1);
+        assertTrue("bar option missing", s.toLowerCase().indexOf("bar") != -1);
+    }
+
+    public void testGetOptionsGroups()
+    {
+        Options options = new Options();
+
+        OptionGroup group1 = new OptionGroup();
+        group1.addOption(OptionBuilder.create('a'));
+        group1.addOption(OptionBuilder.create('b'));
+
+        OptionGroup group2 = new OptionGroup();
+        group2.addOption(OptionBuilder.create('x'));
+        group2.addOption(OptionBuilder.create('y'));
+
+        options.addOptionGroup(group1);
+        options.addOptionGroup(group2);
+
+        assertNotNull(options.getOptionGroups());
+        assertEquals(2, options.getOptionGroups().size());
+    }
+}
diff --git a/src/test/org/apache/commons/cli/ParseRequiredTest.java b/src/test/org/apache/commons/cli/ParseRequiredTest.java
index f457b8f..7f4d0ee 100644
--- a/src/test/org/apache/commons/cli/ParseRequiredTest.java
+++ b/src/test/org/apache/commons/cli/ParseRequiredTest.java
@@ -14,31 +14,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
-import junit.framework.Test;
 import junit.framework.TestCase;
-import junit.framework.TestSuite;
 
 /**
  * @author John Keyes (john at integralsource.com)
- * @version $Revision: 542144 $
+ * @version $Revision: 678662 $
  */
 public class ParseRequiredTest extends TestCase
 {
-
     private Options _options = null;
     private CommandLineParser parser = new PosixParser();
 
-    public static Test suite() { 
-        return new TestSuite(ParseRequiredTest.class); 
-    }
-
-    public ParseRequiredTest(String name)
-    {
-        super(name);
-    }
-
     public void setUp()
     {
         _options = new Options()
@@ -53,64 +42,96 @@ public class ParseRequiredTest extends TestCase
                                      .create( 'b' ) );
     }
 
-    public void tearDown()
+    public void testWithRequiredOption() throws Exception
     {
+        String[] args = new String[] {  "-b", "file" };
 
+        CommandLine cl = parser.parse(_options,args);
+
+        assertTrue( "Confirm -a is NOT set", !cl.hasOption("a") );
+        assertTrue( "Confirm -b is set", cl.hasOption("b") );
+        assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("file") );
+        assertTrue( "Confirm NO of extra args", cl.getArgList().size() == 0);
     }
 
-    public void testWithRequiredOption()
+    public void testOptionAndRequiredOption() throws Exception
     {
-        String[] args = new String[] {  "-b", "file" };
+        String[] args = new String[] {  "-a", "-b", "file" };
+
+        CommandLine cl = parser.parse(_options,args);
+
+        assertTrue( "Confirm -a is set", cl.hasOption("a") );
+        assertTrue( "Confirm -b is set", cl.hasOption("b") );
+        assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("file") );
+        assertTrue( "Confirm NO of extra args", cl.getArgList().size() == 0);
+    }
+
+    public void testMissingRequiredOption()
+    {
+        String[] args = new String[] { "-a" };
 
         try
         {
             CommandLine cl = parser.parse(_options,args);
-            
-            assertTrue( "Confirm -a is NOT set", !cl.hasOption("a") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("file") );
-            assertTrue( "Confirm NO of extra args", cl.getArgList().size() == 0);
+            fail( "exception should have been thrown" );
+        }
+        catch (MissingOptionException e)
+        {
+            assertEquals( "Incorrect exception message", "Missing required option: b", e.getMessage() );
+            assertTrue(e.getMissingOptions().contains("b"));
         }
         catch (ParseException e)
         {
-            fail( e.toString() );
+            fail( "expected to catch MissingOptionException" );
         }
     }
 
-    public void testOptionAndRequiredOption()
+    public void testMissingRequiredOptions()
     {
-        String[] args = new String[] {  "-a", "-b", "file" };
+        String[] args = new String[] { "-a" };
+
+        _options.addOption( OptionBuilder.withLongOpt( "cfile" )
+                                     .hasArg()
+                                     .isRequired()
+                                     .withDescription( "set the value of [c]" )
+                                     .create( 'c' ) );
 
         try
         {
             CommandLine cl = parser.parse(_options,args);
-
-            assertTrue( "Confirm -a is set", cl.hasOption("a") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("file") );
-            assertTrue( "Confirm NO of extra args", cl.getArgList().size() == 0);
+            fail( "exception should have been thrown" );
+        }
+        catch (MissingOptionException e)
+        {
+            assertEquals( "Incorrect exception message", "Missing required options: b, c", e.getMessage() );
+            assertTrue(e.getMissingOptions().contains("b"));
+            assertTrue(e.getMissingOptions().contains("c"));
         }
         catch (ParseException e)
         {
-            fail( e.toString() );
+            fail( "expected to catch MissingOptionException" );
         }
     }
 
-    public void testMissingRequiredOption()
+    public void testReuseOptionsTwice() throws Exception
     {
-        String[] args = new String[] { "-a" };
+        Options opts = new Options();
+		opts.addOption(OptionBuilder.isRequired().create('v'));
+
+		GnuParser parser = new GnuParser();
+
+        // first parsing
+        parser.parse(opts, new String[] { "-v" });
 
         try
         {
-            CommandLine cl = parser.parse(_options,args);
-            fail( "exception should have been thrown" );
+            // second parsing, with the same Options instance and an invalid command line
+            parser.parse(opts, new String[0]);
+            fail("MissingOptionException not thrown");
         }
-        catch (ParseException e)
+        catch (MissingOptionException e)
         {
-            if( !( e instanceof MissingOptionException ) )
-            {
-                fail( "expected to catch MissingOptionException" );
-            }
+            // expected
         }
     }
 
diff --git a/src/test/org/apache/commons/cli/ParseTest.java b/src/test/org/apache/commons/cli/ParseTest.java
deleted file mode 100644
index b70bcd2..0000000
--- a/src/test/org/apache/commons/cli/ParseTest.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.cli;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class ParseTest extends TestCase
-{
-
-    private Options _options = null;
-    private Parser _parser = null;
-
-    public static Test suite() { 
-        return new TestSuite(ParseTest.class); 
-    }
-
-    public ParseTest(String name)
-    {
-        super(name);
-    }
-
-    public void setUp()
-    {
-        _options = new Options()
-            .addOption("a",
-                       "enable-a",
-                       false,
-                       "turn [a] on or off")
-            .addOption("b",
-                       "bfile",
-                       true,
-                       "set the value of [b]")
-            .addOption("c",
-                       "copt",
-                       false,
-                       "turn [c] on or off");
-
-        _parser = new PosixParser();
-    }
-
-    public void tearDown()
-    {
-
-    }
-
-    public void testSimpleShort()
-    {
-        String[] args = new String[] { "-a",
-                                       "-b", "toast",
-                                       "foo", "bar" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args);
-            
-            assertTrue( "Confirm -a is set", cl.hasOption("a") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
-            assertTrue( "Confirm size of extra args", cl.getArgList().size() == 2);
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-    }
-
-    public void testSimpleLong()
-    {
-        String[] args = new String[] { "--enable-a",
-                                       "--bfile", "toast",
-                                       "foo", "bar" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args);
-            
-            assertTrue( "Confirm -a is set", cl.hasOption("a") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
-            assertTrue( "Confirm arg of --bfile", cl.getOptionValue( "bfile" ).equals( "toast" ) );
-            assertTrue( "Confirm size of extra args", cl.getArgList().size() == 2);
-        } 
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-    }
-
-    public void testComplexShort()
-    {
-        String[] args = new String[] { "-acbtoast",
-                                       "foo", "bar" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args);
-            
-            assertTrue( "Confirm -a is set", cl.hasOption("a") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "Confirm -c is set", cl.hasOption("c") );
-            assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
-            assertTrue( "Confirm size of extra args", cl.getArgList().size() == 2);
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-    }
-
-    public void testExtraOption()
-    {
-        String[] args = new String[] { "-adbtoast",
-                                       "foo", "bar" };
-
-        boolean caught = false;
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args);
-            
-            assertTrue( "Confirm -a is set", cl.hasOption("a") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "confirm arg of -b", cl.getOptionValue("b").equals("toast") );
-            assertTrue( "Confirm size of extra args", cl.getArgList().size() == 3);
-        }
-        catch (UnrecognizedOptionException e)
-        {
-            caught = true;
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-        assertTrue( "Confirm UnrecognizedOptionException caught", caught );
-    }
-
-    public void testMissingArg()
-    {
-
-        String[] args = new String[] { "-acb" };
-
-        boolean caught = false;
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args);
-        }
-        catch (MissingArgumentException e)
-        {
-            caught = true;
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-
-        assertTrue( "Confirm MissingArgumentException caught", caught );
-    }
-
-    public void testStop()
-    {
-        String[] args = new String[] { "-c",
-                                       "foober",
-                                       "-btoast" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args, true);
-            assertTrue( "Confirm -c is set", cl.hasOption("c") );
-            assertTrue( "Confirm  2 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 2);
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-    }
-
-    public void testMultiple()
-    {
-        String[] args = new String[] { "-c",
-                                       "foobar",
-                                       "-btoast" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args, true);
-            assertTrue( "Confirm -c is set", cl.hasOption("c") );
-            assertTrue( "Confirm  2 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 2);
-
-            cl = _parser.parse(_options, cl.getArgs() );
-
-            assertTrue( "Confirm -c is not set", ! cl.hasOption("c") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
-            assertTrue( "Confirm  1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
-            assertTrue( "Confirm  value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("foobar") );
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-    }
-
-    public void testMultipleWithLong()
-    {
-        String[] args = new String[] { "--copt",
-                                       "foobar",
-                                       "--bfile", "toast" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options,args,
-                                            true);
-            assertTrue( "Confirm -c is set", cl.hasOption("c") );
-            assertTrue( "Confirm  3 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 3);
-
-            cl = _parser.parse(_options, cl.getArgs() );
-
-            assertTrue( "Confirm -c is not set", ! cl.hasOption("c") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
-            assertTrue( "Confirm  1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
-            assertTrue( "Confirm  value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("foobar") );
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-    }
-
-    public void testDoubleDash()
-    {
-        String[] args = new String[] { "--copt",
-                                       "--",
-                                       "-b", "toast" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args);
-
-            assertTrue( "Confirm -c is set", cl.hasOption("c") );
-            assertTrue( "Confirm -b is not set", ! cl.hasOption("b") );
-            assertTrue( "Confirm 2 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 2);
-
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-    }
-
-    public void testSingleDash()
-    {
-        String[] args = new String[] { "--copt",
-                                       "-b", "-",
-                                       "-a",
-                                       "-" };
-
-        try
-        {
-            CommandLine cl = _parser.parse(_options, args);
-
-            assertTrue( "Confirm -a is set", cl.hasOption("a") );
-            assertTrue( "Confirm -b is set", cl.hasOption("b") );
-            assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("-") );
-            assertTrue( "Confirm 1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
-            assertTrue( "Confirm value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("-") );
-        }
-        catch (ParseException e)
-        {
-            fail( e.toString() );
-        }
-        
-    }
-}
diff --git a/src/test/org/apache/commons/cli/ParserTestCase.java b/src/test/org/apache/commons/cli/ParserTestCase.java
new file mode 100644
index 0000000..ad83e3f
--- /dev/null
+++ b/src/test/org/apache/commons/cli/ParserTestCase.java
@@ -0,0 +1,306 @@
+/**
+ * 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.cli;
+
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+/**
+ * Abstract test case testing common parser features.
+ *
+ * @author Emmanuel Bourg
+ * @version $Revision: 695672 $, $Date: 2008-09-15 15:19:11 -0700 (Mon, 15 Sep 2008) $
+ */
+public abstract class ParserTestCase extends TestCase
+{
+    protected Parser parser;
+
+    protected Options options;
+
+    public void setUp()
+    {
+        options = new Options()
+            .addOption("a", "enable-a", false, "turn [a] on or off")
+            .addOption("b", "bfile", true, "set the value of [b]")
+            .addOption("c", "copt", false, "turn [c] on or off");
+    }
+
+    public void testSimpleShort() throws Exception
+    {
+        String[] args = new String[] { "-a",
+                                       "-b", "toast",
+                                       "foo", "bar" };
+
+        CommandLine cl = parser.parse(options, args);
+
+        assertTrue("Confirm -a is set", cl.hasOption("a"));
+        assertTrue("Confirm -b is set", cl.hasOption("b"));
+        assertTrue("Confirm arg of -b", cl.getOptionValue("b").equals("toast"));
+        assertTrue("Confirm size of extra args", cl.getArgList().size() == 2);
+    }
+
+    public void testSimpleLong() throws Exception
+    {
+        String[] args = new String[] { "--enable-a",
+                                       "--bfile", "toast",
+                                       "foo", "bar" };
+
+        CommandLine cl = parser.parse(options, args);
+
+        assertTrue( "Confirm -a is set", cl.hasOption("a") );
+        assertTrue( "Confirm -b is set", cl.hasOption("b") );
+        assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
+        assertTrue( "Confirm arg of --bfile", cl.getOptionValue( "bfile" ).equals( "toast" ) );
+        assertTrue( "Confirm size of extra args", cl.getArgList().size() == 2);
+    }
+
+    public void testMultiple() throws Exception
+    {
+        String[] args = new String[] { "-c",
+                                       "foobar",
+                                       "-b", "toast" };
+
+        CommandLine cl = parser.parse(options, args, true);
+        assertTrue("Confirm -c is set", cl.hasOption("c"));
+        assertTrue("Confirm  3 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 3);
+
+        cl = parser.parse(options, cl.getArgs());
+
+        assertTrue("Confirm -c is not set", !cl.hasOption("c"));
+        assertTrue("Confirm -b is set", cl.hasOption("b"));
+        assertTrue("Confirm arg of -b", cl.getOptionValue("b").equals("toast"));
+        assertTrue("Confirm  1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
+        assertTrue("Confirm  value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("foobar"));
+    }
+
+    public void testMultipleWithLong() throws Exception
+    {
+        String[] args = new String[] { "--copt",
+                                       "foobar",
+                                       "--bfile", "toast" };
+
+        CommandLine cl = parser.parse(options, args, true);
+        assertTrue("Confirm -c is set", cl.hasOption("c"));
+        assertTrue("Confirm  3 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 3);
+
+        cl = parser.parse(options, cl.getArgs());
+
+        assertTrue("Confirm -c is not set", !cl.hasOption("c"));
+        assertTrue("Confirm -b is set", cl.hasOption("b"));
+        assertTrue("Confirm arg of -b", cl.getOptionValue("b").equals("toast"));
+        assertTrue("Confirm  1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
+        assertTrue("Confirm  value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("foobar"));
+    }
+
+    public void testUnrecognizedOption() throws Exception
+    {
+        String[] args = new String[] { "-a", "-d", "-b", "toast", "foo", "bar" };
+
+        try
+        {
+            parser.parse(options, args);
+            fail("UnrecognizedOptionException wasn't thrown");
+        }
+        catch (UnrecognizedOptionException e)
+        {
+            assertEquals("-d", e.getOption());
+        }
+    }    
+
+    public void testMissingArg() throws Exception
+    {
+        String[] args = new String[] { "-b" };
+
+        boolean caught = false;
+
+        try
+        {
+            parser.parse(options, args);
+        }
+        catch (MissingArgumentException e)
+        {
+            caught = true;
+            assertEquals("option missing an argument", "b", e.getOption().getOpt());
+        }
+
+        assertTrue( "Confirm MissingArgumentException caught", caught );
+    }
+
+    public void testDoubleDash() throws Exception
+    {
+        String[] args = new String[] { "--copt",
+                                       "--",
+                                       "-b", "toast" };
+
+        CommandLine cl = parser.parse(options, args);
+
+        assertTrue("Confirm -c is set", cl.hasOption("c"));
+        assertTrue("Confirm -b is not set", !cl.hasOption("b"));
+        assertTrue("Confirm 2 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 2);
+    }
+
+    public void testSingleDash() throws Exception
+    {
+        String[] args = new String[] { "--copt",
+                                       "-b", "-",
+                                       "-a",
+                                       "-" };
+
+        CommandLine cl = parser.parse(options, args);
+
+        assertTrue("Confirm -a is set", cl.hasOption("a"));
+        assertTrue("Confirm -b is set", cl.hasOption("b"));
+        assertTrue("Confirm arg of -b", cl.getOptionValue("b").equals("-"));
+        assertTrue("Confirm 1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
+        assertTrue("Confirm value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("-"));
+    }
+
+    public void testStopAtUnexpectedArg() throws Exception
+    {
+        String[] args = new String[] { "-c",
+                                       "foober",
+                                       "-b",
+                                       "toast" };
+
+        CommandLine cl = parser.parse(options, args, true);
+        assertTrue("Confirm -c is set", cl.hasOption("c"));
+        assertTrue("Confirm  3 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 3);
+    }
+
+   public void testStopAtExpectedArg() throws Exception
+    {
+        String[] args = new String[]{"-b", "foo"};
+
+        CommandLine cl = parser.parse(options, args, true);
+
+        assertTrue("Confirm -b is set", cl.hasOption('b'));
+        assertEquals("Confirm -b is set", "foo", cl.getOptionValue('b'));
+        assertTrue("Confirm no extra args: " + cl.getArgList().size(), cl.getArgList().size() == 0);
+    }
+
+    public void testStopAtNonOptionShort() throws Exception
+    {
+        String[] args = new String[]{"-z",
+                                     "-a",
+                                     "-btoast"};
+
+        CommandLine cl = parser.parse(options, args, true);
+        assertFalse("Confirm -a is not set", cl.hasOption("a"));
+        assertTrue("Confirm  3 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 3);
+    }
+
+    public void testStopAtNonOptionLong() throws Exception
+    {
+        String[] args = new String[]{"--zop==1",
+                                     "-abtoast",
+                                     "--b=bar"};
+
+        CommandLine cl = parser.parse(options, args, true);
+
+        assertFalse("Confirm -a is not set", cl.hasOption("a"));
+        assertFalse("Confirm -b is not set", cl.hasOption("b"));
+        assertTrue("Confirm  3 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 3);
+    }
+
+    public void testNegativeArgument() throws Exception
+    {
+        String[] args = new String[] { "-b", "-1"} ;
+
+        CommandLine cl = parser.parse(options, args);
+        assertEquals("-1", cl.getOptionValue("b"));
+    }
+
+    public void testArgumentStartingWithHyphen() throws Exception
+    {
+        String[] args = new String[]{"-b", "-foo"};
+
+        CommandLine cl = parser.parse(options, args);
+        assertEquals("-foo", cl.getOptionValue("b"));
+    }
+
+    public void testShortWithEqual() throws Exception
+    {
+        String[] args = new String[] { "-f=bar" };
+
+        Options options = new Options();
+        options.addOption(OptionBuilder.withLongOpt("foo").hasArg().create('f'));
+
+        CommandLine cl = parser.parse(options, args);
+
+        assertEquals("bar", cl.getOptionValue("foo"));
+    }
+
+    public void testShortWithoutEqual() throws Exception
+    {
+        String[] args = new String[] { "-fbar" };
+
+        Options options = new Options();
+        options.addOption(OptionBuilder.withLongOpt("foo").hasArg().create('f'));
+
+        CommandLine cl = parser.parse(options, args);
+
+        assertEquals("bar", cl.getOptionValue("foo"));
+    }
+
+    public void testLongWithEqual() throws Exception
+    {
+        String[] args = new String[] { "--foo=bar" };
+
+        Options options = new Options();
+        options.addOption(OptionBuilder.withLongOpt("foo").hasArg().create('f'));
+
+        CommandLine cl = parser.parse(options, args);
+
+        assertEquals("bar", cl.getOptionValue("foo"));
+    }
+
+    public void testLongWithEqualSingleDash() throws Exception
+    {
+        String[] args = new String[] { "-foo=bar" };
+
+        Options options = new Options();
+        options.addOption(OptionBuilder.withLongOpt("foo").hasArg().create('f'));
+
+        CommandLine cl = parser.parse(options, args);
+
+        assertEquals("bar", cl.getOptionValue("foo"));
+    }
+
+    public void testPropertiesOption() throws Exception
+    {
+        String[] args = new String[] { "-Jsource=1.5", "-J", "target", "1.5", "foo" };
+
+        Options options = new Options();
+        options.addOption(OptionBuilder.withValueSeparator().hasArgs(2).create('J'));
+
+        CommandLine cl = parser.parse(options, args);
+
+        List values = Arrays.asList(cl.getOptionValues("J"));
+        assertNotNull("null values", values);
+        assertEquals("number of values", 4, values.size());
+        assertEquals("value 1", "source", values.get(0));
+        assertEquals("value 2", "1.5", values.get(1));
+        assertEquals("value 3", "target", values.get(2));
+        assertEquals("value 4", "1.5", values.get(3));
+        List argsleft = cl.getArgList();
+        assertEquals("Should be 1 arg left",1,argsleft.size());
+        assertEquals("Expecting foo","foo",argsleft.get(0));
+    }
+}
diff --git a/src/test/org/apache/commons/cli/PatternOptionBuilderTest.java b/src/test/org/apache/commons/cli/PatternOptionBuilderTest.java
index 9a8f3ab..d2df17a 100644
--- a/src/test/org/apache/commons/cli/PatternOptionBuilderTest.java
+++ b/src/test/org/apache/commons/cli/PatternOptionBuilderTest.java
@@ -14,65 +14,161 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
+import java.io.File;
+import java.net.URL;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Vector;
+
 import junit.framework.TestCase;
-import junit.framework.TestSuite;
 
 /** 
  * Test case for the PatternOptionBuilder class 
  *
- * @author Henri Yandell
- **/
-public class PatternOptionBuilderTest
-extends TestCase
+ * @version $Revision: 741427 $, $Date: 2009-02-05 22:11:37 -0800 (Thu, 05 Feb 2009) $
+ */
+public class PatternOptionBuilderTest extends TestCase
 {
+    public void testSimplePattern() throws Exception
+    {
+        Options options = PatternOptionBuilder.parsePattern("a:b at cde>f+n%t/m*z#");
+        String[] args = new String[] {"-c", "-a", "foo", "-b", "java.util.Vector", "-e", "build.xml", "-f", "java.util.Calendar", "-n", "4.5", "-t", "http://commons.apache.org", "-z", "Thu Jun 06 17:48:57 EDT 2002", "-m", "test*"};
+
+        CommandLineParser parser = new PosixParser();
+        CommandLine line = parser.parse(options, args);
+
+        assertEquals("flag a", "foo", line.getOptionValue("a"));
+        assertEquals("string flag a", "foo", line.getOptionObject("a"));
+        assertEquals("object flag b", new Vector(), line.getOptionObject("b"));
+        assertTrue("boolean true flag c", line.hasOption("c"));
+        assertFalse("boolean false flag d", line.hasOption("d"));
+        assertEquals("file flag e", new File("build.xml"), line.getOptionObject("e"));
+        assertEquals("class flag f", Calendar.class, line.getOptionObject("f"));
+        assertEquals("number flag n", new Double(4.5), line.getOptionObject("n"));
+        assertEquals("url flag t", new URL("http://commons.apache.org"), line.getOptionObject("t"));
+
+        // tests the char methods of CommandLine that delegate to the String methods
+        assertEquals("flag a", "foo", line.getOptionValue('a'));
+        assertEquals("string flag a", "foo", line.getOptionObject('a'));
+        assertEquals("object flag b", new Vector(), line.getOptionObject('b'));
+        assertTrue("boolean true flag c", line.hasOption('c'));
+        assertFalse("boolean false flag d", line.hasOption('d'));
+        assertEquals("file flag e", new File("build.xml"), line.getOptionObject('e'));
+        assertEquals("class flag f", Calendar.class, line.getOptionObject('f'));
+        assertEquals("number flag n", new Double(4.5), line.getOptionObject('n'));
+        assertEquals("url flag t", new URL("http://commons.apache.org"), line.getOptionObject('t'));
+
+        // FILES NOT SUPPORTED YET
+        try {
+            assertEquals("files flag m", new File[0], line.getOptionObject('m'));
+            fail("Multiple files are not supported yet, should have failed");
+        } catch(UnsupportedOperationException uoe) {
+            // expected
+        }
+
+        // DATES NOT SUPPORTED YET
+        try {
+            assertEquals("date flag z", new Date(1023400137276L), line.getOptionObject('z'));
+            fail("Date is not supported yet, should have failed");
+        } catch(UnsupportedOperationException uoe) {
+            // expected
+        }
+    }
+
+    public void testEmptyPattern() throws Exception
+    {
+        Options options = PatternOptionBuilder.parsePattern("");
+        assertTrue(options.getOptions().isEmpty());
+    }
+
+    public void testUntypedPattern() throws Exception
+    {
+        Options options = PatternOptionBuilder.parsePattern("abc");
+        CommandLineParser parser = new PosixParser();
+        CommandLine line = parser.parse(options, new String[] { "-abc" });
+
+        assertTrue(line.hasOption('a'));
+        assertNull("value a", line.getOptionObject('a'));
+        assertTrue(line.hasOption('b'));
+        assertNull("value b", line.getOptionObject('b'));
+        assertTrue(line.hasOption('c'));
+        assertNull("value c", line.getOptionObject('c'));
+    }
+
+    public void testNumberPattern() throws Exception
+    {
+        Options options = PatternOptionBuilder.parsePattern("n%d%x%");
+        CommandLineParser parser = new PosixParser();
+        CommandLine line = parser.parse(options, new String[] { "-n", "1", "-d", "2.1", "-x", "3,5" });
+
+        assertEquals("n object class", Long.class, line.getOptionObject("n").getClass());
+        assertEquals("n value", new Long(1), line.getOptionObject("n"));
+
+        assertEquals("d object class", Double.class, line.getOptionObject("d").getClass());
+        assertEquals("d value", new Double(2.1), line.getOptionObject("d"));
+
+        assertNull("x object", line.getOptionObject("x"));
+    }
+
+    public void testClassPattern() throws Exception
+    {
+        Options options = PatternOptionBuilder.parsePattern("c+d+");
+        CommandLineParser parser = new PosixParser();
+        CommandLine line = parser.parse(options, new String[] { "-c", "java.util.Calendar", "-d", "System.DateTime" });
+
+        assertEquals("c value", Calendar.class, line.getOptionObject("c"));
+        assertNull("d value", line.getOptionObject("d"));
+    }
+
+    public void testObjectPattern() throws Exception
+    {
+        Options options = PatternOptionBuilder.parsePattern("o at i@n@");
+        CommandLineParser parser = new PosixParser();
+        CommandLine line = parser.parse(options, new String[] { "-o", "java.lang.String", "-i", "java.util.Calendar", "-n", "System.DateTime" });
+
+        assertEquals("o value", "", line.getOptionObject("o"));
+        assertNull("i value", line.getOptionObject("i"));
+        assertNull("n value", line.getOptionObject("n"));
+    }
+
+    public void testURLPattern() throws Exception
+    {
+        Options options = PatternOptionBuilder.parsePattern("u/v/");
+        CommandLineParser parser = new PosixParser();
+        CommandLine line = parser.parse(options, new String[] { "-u", "http://commons.apache.org", "-v", "foo://commons.apache.org" });
+
+        assertEquals("u value", new URL("http://commons.apache.org"), line.getOptionObject("u"));
+        assertNull("v value", line.getOptionObject("v"));
+    }
+
+    public void testExistingFilePattern() throws Exception
+    {
+        Options options = PatternOptionBuilder.parsePattern("f<");
+        CommandLineParser parser = new PosixParser();
+        CommandLine line = parser.parse(options, new String[] { "-f", "test.properties" });
+
+        assertEquals("f value", new File("test.properties"), line.getOptionObject("f"));
+
+        // todo test if an error is returned if the file doesn't exists (when it's implemented)
+    }
 
-   public static TestSuite suite()
-   {
-      return new TestSuite(PatternOptionBuilderTest.class);
-   }
-
-   public void testSimplePattern()
-   {
-       try {
-           Options options = PatternOptionBuilder.parsePattern("a:b at cde>f+n%t/");
-           String[] args = new String[] { "-c", "-a", "foo", "-b", "java.util.Vector", "-e", "build.xml", "-f", "java.util.Calendar", "-n", "4.5", "-t", "http://jakarta.apache.org/" };
-      
-           CommandLineParser parser = new PosixParser();
-           CommandLine line = parser.parse(options,args);
-
-           assertEquals("flag a", "foo", line.getOptionValue("a"));
-           assertEquals("string flag a", "foo", line.getOptionObject("a"));
-           assertEquals("object flag b", new java.util.Vector(), line.getOptionObject("b"));
-           assertTrue("boolean true flag c", line.hasOption("c"));
-           assertFalse("boolean false flag d", line.hasOption("d"));
-           assertEquals("file flag e", new java.io.File("build.xml"), line.getOptionObject("e"));
-           assertEquals("class flag f", java.util.Calendar.class, line.getOptionObject("f"));
-           assertEquals("number flag n", new Double(4.5), line.getOptionObject("n"));
-           assertEquals("url flag t", new java.net.URL("http://jakarta.apache.org/"), line.getOptionObject("t"));
-
-           // tests the char methods of CommandLine that delegate to the String methods
-           assertEquals("flag a", "foo", line.getOptionValue('a'));
-           assertEquals("string flag a", "foo", line.getOptionObject('a'));
-           assertEquals("object flag b", new java.util.Vector(), line.getOptionObject('b'));
-           assertTrue("boolean true flag c", line.hasOption('c'));
-           assertFalse("boolean false flag d", line.hasOption('d'));
-           assertEquals("file flag e", new java.io.File("build.xml"), line.getOptionObject('e'));
-           assertEquals("class flag f", java.util.Calendar.class, line.getOptionObject('f'));
-           assertEquals("number flag n", new Double(4.5), line.getOptionObject('n'));
-           assertEquals("url flag t", new java.net.URL("http://jakarta.apache.org/"), line.getOptionObject('t'));
-
-           /// DATES NOT SUPPORTED YET.
-           //      assertEquals("number flag t", new java.util.Date(1023400137276L), line.getOptionObject('z'));
-           //     input is:  "Thu Jun 06 17:48:57 EDT 2002"
-       }
-       catch( ParseException exp ) {
-           fail( exp.getMessage() );
-       }
-       catch( java.net.MalformedURLException exp ) {
-           fail( exp.getMessage() );
-       }
-   }
+    public void testRequiredOption() throws Exception
+    {
+        Options options = PatternOptionBuilder.parsePattern("!n%m%");
+        CommandLineParser parser = new PosixParser();
 
+        try
+        {
+            parser.parse(options, new String[]{""});
+            fail("MissingOptionException wasn't thrown");
+        }
+        catch (MissingOptionException e)
+        {
+            assertEquals(1, e.getMissingOptions().size());
+            assertTrue(e.getMissingOptions().contains("n"));
+        }
+    }
 }
diff --git a/src/test/org/apache/commons/cli/PosixParserTest.java b/src/test/org/apache/commons/cli/PosixParserTest.java
new file mode 100644
index 0000000..be63f5d
--- /dev/null
+++ b/src/test/org/apache/commons/cli/PosixParserTest.java
@@ -0,0 +1,188 @@
+/**
+ * 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.cli;
+
+/**
+ * Test case for the PosixParser.
+ *
+ * @version $Revision: 695410 $, $Date: 2008-09-15 03:25:38 -0700 (Mon, 15 Sep 2008) $
+ */
+public class PosixParserTest extends ParserTestCase
+{
+    public void setUp()
+    {
+        super.setUp();
+        parser = new PosixParser();
+    }
+
+    public void testBursting() throws Exception
+    {
+        String[] args = new String[] { "-acbtoast",
+                                       "foo", "bar" };
+
+        CommandLine cl = parser.parse(options, args);
+
+        assertTrue( "Confirm -a is set", cl.hasOption("a") );
+        assertTrue( "Confirm -b is set", cl.hasOption("b") );
+        assertTrue( "Confirm -c is set", cl.hasOption("c") );
+        assertTrue( "Confirm arg of -b", cl.getOptionValue("b").equals("toast") );
+        assertTrue( "Confirm size of extra args", cl.getArgList().size() == 2);
+    }
+
+    public void testUnrecognizedOptionWithBursting() throws Exception
+    {
+        String[] args = new String[] { "-adbtoast", "foo", "bar" };
+
+        try
+        {
+            parser.parse(options, args);
+            fail("UnrecognizedOptionException wasn't thrown");
+        }
+        catch (UnrecognizedOptionException e)
+        {
+            assertEquals("-adbtoast", e.getOption());
+        }
+    }
+
+    public void testMissingArgWithBursting() throws Exception
+    {
+        String[] args = new String[] { "-acb" };
+
+        boolean caught = false;
+
+        try
+        {
+            parser.parse(options, args);
+        }
+        catch (MissingArgumentException e)
+        {
+            caught = true;
+            assertEquals("option missing an argument", "b", e.getOption().getOpt());
+        }
+
+        assertTrue( "Confirm MissingArgumentException caught", caught );
+    }
+
+    public void testStopBursting() throws Exception
+    {
+        String[] args = new String[] { "-azc" };
+
+        CommandLine cl = parser.parse(options, args, true);
+        assertTrue( "Confirm -a is set", cl.hasOption("a") );
+        assertFalse( "Confirm -c is not set", cl.hasOption("c") );
+
+        assertTrue( "Confirm  1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
+        assertTrue(cl.getArgList().contains("zc"));
+    }
+
+    public void testStopBursting2() throws Exception
+    {
+        String[] args = new String[] { "-c",
+                                       "foobar",
+                                       "-btoast" };
+
+        CommandLine cl = parser.parse(options, args, true);
+        assertTrue("Confirm -c is set", cl.hasOption("c"));
+        assertTrue("Confirm  2 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 2);
+
+        cl = parser.parse(options, cl.getArgs());
+
+        assertTrue("Confirm -c is not set", !cl.hasOption("c"));
+        assertTrue("Confirm -b is set", cl.hasOption("b"));
+        assertTrue("Confirm arg of -b", cl.getOptionValue("b").equals("toast"));
+        assertTrue("Confirm  1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
+        assertTrue("Confirm  value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("foobar"));
+    }
+
+    /**
+     * Real world test with long and short options.
+     */
+    public void testLongOptionWithShort() throws Exception {
+        Option help = new Option("h", "help", false, "print this message");
+        Option version = new Option("v", "version", false, "print version information");
+        Option newRun = new Option("n", "new", false, "Create NLT cache entries only for new items");
+        Option trackerRun = new Option("t", "tracker", false, "Create NLT cache entries only for tracker items");
+
+        Option timeLimit = OptionBuilder.withLongOpt("limit").hasArg()
+                                        .withValueSeparator()
+                                        .withDescription("Set time limit for execution, in minutes")
+                                        .create("l");
+
+        Option age = OptionBuilder.withLongOpt("age").hasArg()
+                                  .withValueSeparator()
+                                  .withDescription("Age (in days) of cache item before being recomputed")
+                                  .create("a");
+
+        Option server = OptionBuilder.withLongOpt("server").hasArg()
+                                     .withValueSeparator()
+                                     .withDescription("The NLT server address")
+                                     .create("s");
+
+        Option numResults = OptionBuilder.withLongOpt("results").hasArg()
+                                         .withValueSeparator()
+                                         .withDescription("Number of results per item")
+                                         .create("r");
+
+        Option configFile = OptionBuilder.withLongOpt("file").hasArg()
+                                         .withValueSeparator()
+                                         .withDescription("Use the specified configuration file")
+                                         .create();
+
+        Options options = new Options();
+        options.addOption(help);
+        options.addOption(version);
+        options.addOption(newRun);
+        options.addOption(trackerRun);
+        options.addOption(timeLimit);
+        options.addOption(age);
+        options.addOption(server);
+        options.addOption(numResults);
+        options.addOption(configFile);
+
+        // create the command line parser
+        CommandLineParser parser = new PosixParser();
+
+        String[] args = new String[] {
+                "-v",
+                "-l",
+                "10",
+                "-age",
+                "5",
+                "-file",
+                "filename"
+            };
+
+        CommandLine line = parser.parse(options, args);
+        assertTrue(line.hasOption("v"));
+        assertEquals(line.getOptionValue("l"), "10");
+        assertEquals(line.getOptionValue("limit"), "10");
+        assertEquals(line.getOptionValue("a"), "5");
+        assertEquals(line.getOptionValue("age"), "5");
+        assertEquals(line.getOptionValue("file"), "filename");
+    }
+
+    public void testLongWithEqualSingleDash() throws Exception
+    {
+        // not supported by the PosixParser
+    }
+
+    public void testShortWithEqual() throws Exception
+    {
+        // not supported by the PosixParser
+    }
+}
diff --git a/src/test/org/apache/commons/cli/UtilTest.java b/src/test/org/apache/commons/cli/UtilTest.java
index 3aae1d1..c8c614a 100644
--- a/src/test/org/apache/commons/cli/UtilTest.java
+++ b/src/test/org/apache/commons/cli/UtilTest.java
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
 import junit.framework.TestCase;
@@ -21,10 +22,18 @@ import junit.framework.TestCase;
 /**
  * @author brianegge
  */
-public class UtilTest extends TestCase {
-    public void testStripLeadingHyphens() {
+public class UtilTest extends TestCase
+{
+    public void testStripLeadingHyphens()
+    {
         assertEquals("f", Util.stripLeadingHyphens("-f"));
         assertEquals("foo", Util.stripLeadingHyphens("--foo"));
+        assertEquals("-foo", Util.stripLeadingHyphens("---foo"));
         assertNull(Util.stripLeadingHyphens(null));
     }
+
+    public void testStripLeadingAndTrailingQuotes()
+    {
+        assertEquals("foo", Util.stripLeadingAndTrailingQuotes("\"foo\""));
+    }
 }
diff --git a/src/test/org/apache/commons/cli/ValueTest.java b/src/test/org/apache/commons/cli/ValueTest.java
index 1af91bf..c7d764a 100644
--- a/src/test/org/apache/commons/cli/ValueTest.java
+++ b/src/test/org/apache/commons/cli/ValueTest.java
@@ -14,74 +14,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.cli;
 
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
+package org.apache.commons.cli;
 
 import java.util.Arrays;
 import java.util.Properties;
 
+import junit.framework.TestCase;
+
 public class ValueTest extends TestCase
 {
-
-    public static Test suite() { 
-        return new TestSuite(ValueTest.class); 
-    }
-
     private CommandLine _cl = null;
-    private CommandLine _clOptional = null;
     private Options opts = new Options();
 
-    public ValueTest(String name)
+    public void setUp() throws Exception
     {
-        super(name);
-    }
-
-    public void setUp()
-    {
-        opts.addOption("a",
-                       false,
-                       "toggle -a");
-
-        opts.addOption("b",
-                       true,
-                       "set -b");
-
-        opts.addOption("c",
-                       "c",
-                       false,
-                       "toggle -c");
-
-        opts.addOption("d",
-                       "d",
-                       true,
-                       "set -d");
-
-        opts.addOption( OptionBuilder.hasOptionalArg()
-                        .create( 'e') );
-
-        opts.addOption( OptionBuilder.hasOptionalArg()
-                        .withLongOpt( "fish" )
-                        .create( ) );
-
-        opts.addOption( OptionBuilder.hasOptionalArgs()
-                        .withLongOpt( "gravy" )
-                        .create( ) );
-
-        opts.addOption( OptionBuilder.hasOptionalArgs( 2 )
-                        .withLongOpt( "hide" )
-                        .create( ) );
-
-        opts.addOption( OptionBuilder.hasOptionalArgs( 2 )
-                        .create( 'i' ) );
-
-        opts.addOption( OptionBuilder.hasOptionalArgs( )
-                        .create( 'j' ) );
-
-        opts.addOption( OptionBuilder.hasArgs( ).withValueSeparator( ',' )
-                        .create( 'k' ) );
+        opts.addOption("a", false, "toggle -a");
+        opts.addOption("b", true, "set -b");
+        opts.addOption("c", "c", false, "toggle -c");
+        opts.addOption("d", "d", true, "set -d");
+
+        opts.addOption(OptionBuilder.hasOptionalArg().create('e'));
+        opts.addOption(OptionBuilder.hasOptionalArg().withLongOpt("fish").create());
+        opts.addOption(OptionBuilder.hasOptionalArgs().withLongOpt("gravy").create());
+        opts.addOption(OptionBuilder.hasOptionalArgs(2).withLongOpt("hide").create());
+        opts.addOption(OptionBuilder.hasOptionalArgs(2).create('i'));
+        opts.addOption(OptionBuilder.hasOptionalArgs().create('j'));
+        opts.addOption(OptionBuilder.hasArgs().withValueSeparator(',').create('k'));
 
         String[] args = new String[] { "-a",
             "-b", "foo",
@@ -89,20 +48,8 @@ public class ValueTest extends TestCase
             "--d", "bar" 
         };
 
-        try
-        {
-            Parser parser = new PosixParser();
-            _cl = parser.parse(opts,args);
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
-    }
-
-    public void tearDown()
-    {
-
+        Parser parser = new PosixParser();
+        _cl = parser.parse(opts,args);
     }
 
     public void testShortNoArg()
@@ -131,137 +78,88 @@ public class ValueTest extends TestCase
         assertEquals( _cl.getOptionValue("d"), "bar");
     }
 
-    public void testShortOptionalArgNoValue()
+    public void testShortOptionalArgNoValue() throws Exception
     {
-        String[] args = new String[] { "-e"
-        };
-        try
-        {
-            Parser parser = new PosixParser();
-            CommandLine cmd = parser.parse(opts,args);
-            assertTrue( cmd.hasOption("e") );
-            assertNull( cmd.getOptionValue("e") );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
+        String[] args = new String[] { "-e" };
+
+        Parser parser = new PosixParser();
+        CommandLine cmd = parser.parse(opts,args);
+        assertTrue( cmd.hasOption("e") );
+        assertNull( cmd.getOptionValue("e") );
     }
 
-    public void testShortOptionalArgValue()
+    public void testShortOptionalArgValue() throws Exception
     {
-        String[] args = new String[] { "-e", "everything"
-        };
-        try
-        {
-            Parser parser = new PosixParser();
-            CommandLine cmd = parser.parse(opts,args);
-            assertTrue( cmd.hasOption("e") );
-            assertEquals( "everything", cmd.getOptionValue("e") );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
+        String[] args = new String[] { "-e", "everything" };
+
+        Parser parser = new PosixParser();
+        CommandLine cmd = parser.parse(opts,args);
+        assertTrue( cmd.hasOption("e") );
+        assertEquals( "everything", cmd.getOptionValue("e") );
     }
 
-    public void testLongOptionalNoValue()
+    public void testLongOptionalNoValue() throws Exception
     {
-        String[] args = new String[] { "--fish"
-        };
-        try
-        {
-            Parser parser = new PosixParser();
-            CommandLine cmd = parser.parse(opts,args);
-            assertTrue( cmd.hasOption("fish") );
-            assertNull( cmd.getOptionValue("fish") );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
+        String[] args = new String[] { "--fish" };
+
+        Parser parser = new PosixParser();
+        CommandLine cmd = parser.parse(opts,args);
+        assertTrue( cmd.hasOption("fish") );
+        assertNull( cmd.getOptionValue("fish") );
     }
 
-    public void testLongOptionalArgValue()
+    public void testLongOptionalArgValue() throws Exception
     {
-        String[] args = new String[] { "--fish", "face"
-        };
-        try
-        {
-            Parser parser = new PosixParser();
-            CommandLine cmd = parser.parse(opts,args);
-            assertTrue( cmd.hasOption("fish") );
-            assertEquals( "face", cmd.getOptionValue("fish") );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
+        String[] args = new String[] { "--fish", "face" };
+
+        Parser parser = new PosixParser();
+        CommandLine cmd = parser.parse(opts,args);
+        assertTrue( cmd.hasOption("fish") );
+        assertEquals( "face", cmd.getOptionValue("fish") );
     }
 
-    public void testShortOptionalArgValues()
+    public void testShortOptionalArgValues() throws Exception
     {
-        String[] args = new String[] { "-j", "ink", "idea"
-        };
-        try
-        {
-            Parser parser = new PosixParser();
-            CommandLine cmd = parser.parse(opts,args);
-            assertTrue( cmd.hasOption("j") );
-            assertEquals( "ink", cmd.getOptionValue("j") );
-            assertEquals( "ink", cmd.getOptionValues("j")[0] );
-            assertEquals( "idea", cmd.getOptionValues("j")[1] );
-            assertEquals( cmd.getArgs().length, 0 );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
+        String[] args = new String[] { "-j", "ink", "idea" };
+
+        Parser parser = new PosixParser();
+        CommandLine cmd = parser.parse(opts,args);
+        assertTrue( cmd.hasOption("j") );
+        assertEquals( "ink", cmd.getOptionValue("j") );
+        assertEquals( "ink", cmd.getOptionValues("j")[0] );
+        assertEquals( "idea", cmd.getOptionValues("j")[1] );
+        assertEquals( cmd.getArgs().length, 0 );
     }
 
-    public void testLongOptionalArgValues()
+    public void testLongOptionalArgValues() throws Exception
     {
-        String[] args = new String[] { "--gravy", "gold", "garden"
-        };
-        try
-        {
-            Parser parser = new PosixParser();
-            CommandLine cmd = parser.parse(opts,args);
-            assertTrue( cmd.hasOption("gravy") );
-            assertEquals( "gold", cmd.getOptionValue("gravy") );
-            assertEquals( "gold", cmd.getOptionValues("gravy")[0] );
-            assertEquals( "garden", cmd.getOptionValues("gravy")[1] );
-            assertEquals( cmd.getArgs().length, 0 );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
+        String[] args = new String[] { "--gravy", "gold", "garden" };
+
+        Parser parser = new PosixParser();
+        CommandLine cmd = parser.parse(opts,args);
+        assertTrue( cmd.hasOption("gravy") );
+        assertEquals( "gold", cmd.getOptionValue("gravy") );
+        assertEquals( "gold", cmd.getOptionValues("gravy")[0] );
+        assertEquals( "garden", cmd.getOptionValues("gravy")[1] );
+        assertEquals( cmd.getArgs().length, 0 );
     }
 
-    public void testShortOptionalNArgValues()
+    public void testShortOptionalNArgValues() throws Exception
     {
-        String[] args = new String[] { "-i", "ink", "idea", "isotope", "ice"
-        };
-        try
-        {
-            Parser parser = new PosixParser();
-            CommandLine cmd = parser.parse(opts,args);
-            assertTrue( cmd.hasOption("i") );
-            assertEquals( "ink", cmd.getOptionValue("i") );
-            assertEquals( "ink", cmd.getOptionValues("i")[0] );
-            assertEquals( "idea", cmd.getOptionValues("i")[1] );
-            assertEquals( cmd.getArgs().length, 2 );
-            assertEquals( "isotope", cmd.getArgs()[0] );
-            assertEquals( "ice", cmd.getArgs()[1] );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
+        String[] args = new String[] { "-i", "ink", "idea", "isotope", "ice" };
+
+        Parser parser = new PosixParser();
+        CommandLine cmd = parser.parse(opts,args);
+        assertTrue( cmd.hasOption("i") );
+        assertEquals( "ink", cmd.getOptionValue("i") );
+        assertEquals( "ink", cmd.getOptionValues("i")[0] );
+        assertEquals( "idea", cmd.getOptionValues("i")[1] );
+        assertEquals( cmd.getArgs().length, 2 );
+        assertEquals( "isotope", cmd.getArgs()[0] );
+        assertEquals( "ice", cmd.getArgs()[1] );
     }
 
-    public void testLongOptionalNArgValues()
+    public void testLongOptionalNArgValues() throws Exception
     {
         String[] args = new String[] { 
             "--hide", "house", "hair", "head"
@@ -269,43 +167,29 @@ public class ValueTest extends TestCase
 
         Parser parser = new PosixParser();
 
-        try
-        {
-            CommandLine cmd = parser.parse(opts,args);
-            assertTrue( cmd.hasOption("hide") );
-            assertEquals( "house", cmd.getOptionValue("hide") );
-            assertEquals( "house", cmd.getOptionValues("hide")[0] );
-            assertEquals( "hair", cmd.getOptionValues("hide")[1] );
-            assertEquals( cmd.getArgs().length, 1 );
-            assertEquals( "head", cmd.getArgs()[0] );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
+        CommandLine cmd = parser.parse(opts,args);
+        assertTrue( cmd.hasOption("hide") );
+        assertEquals( "house", cmd.getOptionValue("hide") );
+        assertEquals( "house", cmd.getOptionValues("hide")[0] );
+        assertEquals( "hair", cmd.getOptionValues("hide")[1] );
+        assertEquals( cmd.getArgs().length, 1 );
+        assertEquals( "head", cmd.getArgs()[0] );
     }
 
-    public void testPropertyOptionSingularValue()
+    public void testPropertyOptionSingularValue() throws Exception
     {
         Properties properties = new Properties();
         properties.setProperty( "hide", "seek" );
 
         Parser parser = new PosixParser();
         
-        try
-        {
-            CommandLine cmd = parser.parse(opts, null, properties);
-            assertTrue( cmd.hasOption("hide") );
-            assertEquals( "seek", cmd.getOptionValue("hide") );
-            assertTrue( !cmd.hasOption("fake") );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
+        CommandLine cmd = parser.parse(opts, null, properties);
+        assertTrue( cmd.hasOption("hide") );
+        assertEquals( "seek", cmd.getOptionValue("hide") );
+        assertTrue( !cmd.hasOption("fake") );
     }
 
-    public void testPropertyOptionFlags()
+    public void testPropertyOptionFlags() throws Exception
     {
         Properties properties = new Properties();
         properties.setProperty( "a", "true" );
@@ -313,69 +197,46 @@ public class ValueTest extends TestCase
         properties.setProperty( "e", "1" );
 
         Parser parser = new PosixParser();
-        
-        try
-        {
-            CommandLine cmd = parser.parse(opts, null, properties);
-            assertTrue( cmd.hasOption("a") );
-            assertTrue( cmd.hasOption("c") );
-            assertTrue( cmd.hasOption("e") );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
+
+        CommandLine cmd = parser.parse(opts, null, properties);
+        assertTrue( cmd.hasOption("a") );
+        assertTrue( cmd.hasOption("c") );
+        assertTrue( cmd.hasOption("e") );
+
 
         properties = new Properties();
         properties.setProperty( "a", "false" );
         properties.setProperty( "c", "no" );
         properties.setProperty( "e", "0" );
-        try
-        {
-            CommandLine cmd = parser.parse(opts, null, properties);
-            assertTrue( !cmd.hasOption("a") );
-            assertTrue( !cmd.hasOption("c") );
-            assertTrue( !cmd.hasOption("e") );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
+
+        cmd = parser.parse(opts, null, properties);
+        assertTrue( !cmd.hasOption("a") );
+        assertTrue( !cmd.hasOption("c") );
+        assertTrue( !cmd.hasOption("e") );
+
 
         properties = new Properties();
         properties.setProperty( "a", "TRUE" );
         properties.setProperty( "c", "nO" );
         properties.setProperty( "e", "TrUe" );
-        try
-        {
-            CommandLine cmd = parser.parse(opts, null, properties);
-            assertTrue( cmd.hasOption("a") );
-            assertTrue( !cmd.hasOption("c") );
-            assertTrue( cmd.hasOption("e") );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
 
+        cmd = parser.parse(opts, null, properties);
+        assertTrue( cmd.hasOption("a") );
+        assertTrue( !cmd.hasOption("c") );
+        assertTrue( cmd.hasOption("e") );
+
+        
         properties = new Properties();
         properties.setProperty( "a", "just a string" );
         properties.setProperty( "e", "" );
-        try
-        {
-            CommandLine cmd = parser.parse(opts, null, properties);
-            assertTrue( !cmd.hasOption("a") );
-            assertTrue( !cmd.hasOption("c") );
-            assertTrue( !cmd.hasOption("e") );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
 
+        cmd = parser.parse(opts, null, properties);
+        assertTrue( !cmd.hasOption("a") );
+        assertTrue( !cmd.hasOption("c") );
+        assertTrue( !cmd.hasOption("e") );
     } 
 
-    public void testPropertyOptionMultipleValues()
+    public void testPropertyOptionMultipleValues() throws Exception
     {
         Properties properties = new Properties();
         properties.setProperty( "k", "one,two" );
@@ -385,19 +246,13 @@ public class ValueTest extends TestCase
         String[] values = new String[] {
             "one", "two"
         };
-        try
-        {
-            CommandLine cmd = parser.parse(opts, null, properties);
-            assertTrue( cmd.hasOption("k") );
-            assertTrue( Arrays.equals( values, cmd.getOptionValues('k') ) );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
+
+        CommandLine cmd = parser.parse(opts, null, properties);
+        assertTrue( cmd.hasOption("k") );
+        assertTrue( Arrays.equals( values, cmd.getOptionValues('k') ) );
     }
 
-    public void testPropertyOverrideValues()
+    public void testPropertyOverrideValues() throws Exception
     {
         String[] args = new String[] { 
             "-j",
@@ -408,20 +263,14 @@ public class ValueTest extends TestCase
 
         Properties properties = new Properties();
         properties.setProperty( "j", "seek" );
-        try
-        {
-            Parser parser = new PosixParser();
-            CommandLine cmd = parser.parse(opts, args, properties);
-            assertTrue( cmd.hasOption("j") );
-            assertEquals( "found", cmd.getOptionValue("j") );
-            assertTrue( cmd.hasOption("i") );
-            assertEquals( "ink", cmd.getOptionValue("i") );
-            assertTrue( !cmd.hasOption("fake") );
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
+
+        Parser parser = new PosixParser();
+        CommandLine cmd = parser.parse(opts, args, properties);
+        assertTrue( cmd.hasOption("j") );
+        assertEquals( "found", cmd.getOptionValue("j") );
+        assertTrue( cmd.hasOption("i") );
+        assertEquals( "ink", cmd.getOptionValue("i") );
+        assertTrue( !cmd.hasOption("fake") );
     }
 
 }
diff --git a/src/test/org/apache/commons/cli/ValuesTest.java b/src/test/org/apache/commons/cli/ValuesTest.java
index 2135f2d..83eeb98 100644
--- a/src/test/org/apache/commons/cli/ValuesTest.java
+++ b/src/test/org/apache/commons/cli/ValuesTest.java
@@ -14,95 +14,36 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli;
 
 import java.util.Arrays;
 
-import junit.framework.Test;
 import junit.framework.TestCase;
-import junit.framework.TestSuite;
 
 public class ValuesTest extends TestCase
 {
     /** CommandLine instance */
     private CommandLine _cmdline = null;
-    private Option _option = null;
-
-    public static Test suite() { 
-        return new TestSuite( ValuesTest.class );
-    }
 
-    public ValuesTest( String name )
+    public void setUp() throws Exception
     {
-        super( name );
-    }
+        Options options = new Options();
+
+        options.addOption("a", false, "toggle -a");
+        options.addOption("b", true, "set -b");
+        options.addOption("c", "c", false, "toggle -c");
+        options.addOption("d", "d", true, "set -d");
+
+        options.addOption(OptionBuilder.withLongOpt("e").hasArgs().withDescription("set -e ").create('e'));
+        options.addOption("f", "f", false, "jk");
+        options.addOption(OptionBuilder.withLongOpt("g").hasArgs(2).withDescription("set -g").create('g'));
+        options.addOption(OptionBuilder.withLongOpt("h").hasArgs(2).withDescription("set -h").create('h'));
+        options.addOption(OptionBuilder.withLongOpt("i").withDescription("set -i").create('i'));
+        options.addOption(OptionBuilder.withLongOpt("j").hasArgs().withDescription("set -j").withValueSeparator('=').create('j'));
+        options.addOption(OptionBuilder.withLongOpt("k").hasArgs().withDescription("set -k").withValueSeparator('=').create('k'));
+        options.addOption(OptionBuilder.withLongOpt("m").hasArgs().withDescription("set -m").withValueSeparator().create('m'));
 
-    public void setUp()
-    {
-        Options opts = new Options();
-
-        opts.addOption("a",
-                       false,
-                       "toggle -a");
-
-        opts.addOption("b",
-                       true,
-                       "set -b");
-
-        opts.addOption("c",
-                       "c",
-                       false,
-                       "toggle -c");
-
-        opts.addOption("d",
-                       "d",
-                       true,
-                       "set -d");
-        
-        opts.addOption( OptionBuilder.withLongOpt( "e" )
-                                     .hasArgs()
-                                     .withDescription( "set -e ")
-                                     .create( 'e' ) );
-
-        opts.addOption("f",
-                       "f",
-                       false,
-                       "jk");
-        
-        opts.addOption( OptionBuilder.withLongOpt( "g" )
-                        .hasArgs( 2 )
-                        .withDescription( "set -g")
-                        .create( 'g' ) );
-
-        opts.addOption( OptionBuilder.withLongOpt( "h" )
-                        .hasArgs( 2 )
-                        .withDescription( "set -h")
-                        .create( 'h' ) );
-
-        opts.addOption( OptionBuilder.withLongOpt( "i" )
-                        .withDescription( "set -i")
-                        .create( 'i' ) );
-
-        opts.addOption( OptionBuilder.withLongOpt( "j" )
-                        .hasArgs( )
-                        .withDescription( "set -j")
-                        .withValueSeparator( '=' )
-                        .create( 'j' ) );
-
-        opts.addOption( OptionBuilder.withLongOpt( "k" )
-                        .hasArgs( )
-                        .withDescription( "set -k")
-                        .withValueSeparator( '=' )
-                        .create( 'k' ) );
-
-        _option = OptionBuilder.withLongOpt( "m" )
-                        .hasArgs( )
-                        .withDescription( "set -m")
-                        .withValueSeparator( )
-                        .create( 'm' );
-
-        opts.addOption( _option );
-        
         String[] args = new String[] { "-a",
                                        "-b", "foo",
                                        "--c",
@@ -121,19 +62,7 @@ public class ValuesTest extends TestCase
 
         CommandLineParser parser = new PosixParser();
 
-        try
-        {
-            _cmdline = parser.parse(opts,args);
-        }
-        catch (ParseException e)
-        {
-            fail("Cannot setUp() CommandLine: " + e.toString());
-        }
-    }
-
-    public void tearDown()
-    {
-
+        _cmdline = parser.parse(options,args);
     }
 
     public void testShortArgs()
@@ -149,11 +78,11 @@ public class ValuesTest extends TestCase
     {
         assertTrue( _cmdline.hasOption("b") );
         assertTrue( _cmdline.getOptionValue("b").equals("foo"));
-        assertTrue( _cmdline.getOptionValues("b").length == 1);
+        assertEquals(1, _cmdline.getOptionValues("b").length);
 
         assertTrue( _cmdline.hasOption("d") );
         assertTrue( _cmdline.getOptionValue("d").equals("bar"));
-        assertTrue( _cmdline.getOptionValues("d").length == 1);
+        assertEquals(1, _cmdline.getOptionValues("d").length);
     }
 
     public void testMultipleArgValues()
@@ -161,7 +90,7 @@ public class ValuesTest extends TestCase
         String[] result = _cmdline.getOptionValues("e");
         String[] values = new String[] { "one", "two" };
         assertTrue( _cmdline.hasOption("e") );
-        assertTrue( _cmdline.getOptionValues("e").length == 2);
+        assertEquals(2, _cmdline.getOptionValues("e").length);
         assertTrue( Arrays.equals( values, _cmdline.getOptionValues("e") ) );
     }
 
@@ -170,7 +99,7 @@ public class ValuesTest extends TestCase
         String[] result = _cmdline.getOptionValues("g");
         String[] values = new String[] { "val1", "val2" };
         assertTrue( _cmdline.hasOption("g") );
-        assertTrue( _cmdline.getOptionValues("g").length == 2);
+        assertEquals(2, _cmdline.getOptionValues("g").length);
         assertTrue( Arrays.equals( values, _cmdline.getOptionValues("g") ) );
     }
 
@@ -180,14 +109,14 @@ public class ValuesTest extends TestCase
         String[] values = new String[] { "val1", "val2" };
         assertTrue( _cmdline.hasOption("i") );
         assertTrue( _cmdline.hasOption("h") );
-        assertTrue( _cmdline.getOptionValues("h").length == 2);
+        assertEquals(2, _cmdline.getOptionValues("h").length);
         assertTrue( Arrays.equals( values, _cmdline.getOptionValues("h") ) );
     }
 
     public void testExtraArgs()
     {
         String[] args = new String[] { "arg1", "arg2", "arg3" };
-        assertTrue( _cmdline.getArgs().length == 3 );         
+        assertEquals(3, _cmdline.getArgs().length);
         assertTrue( Arrays.equals( args, _cmdline.getArgs() ) );
     }
 
@@ -206,16 +135,16 @@ public class ValuesTest extends TestCase
         values = new String[] { "key1", "value1", "key2", "value2" };
         assertTrue( _cmdline.hasOption( "k" ) );
         assertTrue( _cmdline.hasOption( 'k' ) );
-        assertTrue( _cmdline.getOptionValues( "k" ).length == 4 );
-        assertTrue( _cmdline.getOptionValues( 'k' ).length == 4 );
+        assertEquals(4, _cmdline.getOptionValues( "k" ).length);
+        assertEquals(4, _cmdline.getOptionValues( 'k' ).length);
         assertTrue( Arrays.equals( values, _cmdline.getOptionValues( "k" ) ) );
         assertTrue( Arrays.equals( values, _cmdline.getOptionValues( 'k' ) ) );
 
         values = new String[] { "key", "value" };
         assertTrue( _cmdline.hasOption( "m" ) );
         assertTrue( _cmdline.hasOption( 'm' ) );
-        assertTrue( _cmdline.getOptionValues( "m" ).length == 2);
-        assertTrue( _cmdline.getOptionValues( 'm' ).length == 2);
+        assertEquals(2, _cmdline.getOptionValues( "m" ).length);
+        assertEquals(2, _cmdline.getOptionValues( 'm' ).length);
         assertTrue( Arrays.equals( values, _cmdline.getOptionValues( "m" ) ) );
         assertTrue( Arrays.equals( values, _cmdline.getOptionValues( 'm' ) ) );
     }
diff --git a/src/test/org/apache/commons/cli/bug/BugCLI133Test.java b/src/test/org/apache/commons/cli/bug/BugCLI133Test.java
index 0ada0bc..42d13c1 100644
--- a/src/test/org/apache/commons/cli/bug/BugCLI133Test.java
+++ b/src/test/org/apache/commons/cli/bug/BugCLI133Test.java
@@ -14,10 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli.bug;
 
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.PosixParser;
+
 import junit.framework.TestCase;
-import org.apache.commons.cli.*;
 
 /**
  * @author brianegge
diff --git a/src/test/org/apache/commons/cli/bug/BugCLI13Test.java b/src/test/org/apache/commons/cli/bug/BugCLI13Test.java
index 7e63dfa..bc94b2a 100644
--- a/src/test/org/apache/commons/cli/bug/BugCLI13Test.java
+++ b/src/test/org/apache/commons/cli/bug/BugCLI13Test.java
@@ -14,9 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.cli.bug;
 
-import junit.framework.TestCase;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.OptionBuilder;
@@ -24,14 +24,14 @@ import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
 import org.apache.commons.cli.PosixParser;
 
+import junit.framework.TestCase;
+
 /**
  * @author brianegge
  */
-public class BugCLI13Test
-    extends TestCase
+public class BugCLI13Test extends TestCase
 {
-    public void testCLI13()
-        throws ParseException
+    public void testCLI13() throws ParseException
     {
         final String debugOpt = "debug";
         Option debug = OptionBuilder
diff --git a/src/test/org/apache/commons/cli/bug/BugCLI51Test.java b/src/test/org/apache/commons/cli/bug/BugCLI148Test.java
similarity index 63%
rename from src/test/org/apache/commons/cli/bug/BugCLI51Test.java
rename to src/test/org/apache/commons/cli/bug/BugCLI148Test.java
index 7fca189..4668468 100644
--- a/src/test/org/apache/commons/cli/bug/BugCLI51Test.java
+++ b/src/test/org/apache/commons/cli/bug/BugCLI148Test.java
@@ -1,41 +1,53 @@
-/*
+/**
  * 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
- * 
+ *
+ *     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.cli.bug;
 
-import junit.framework.TestCase;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
 import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
 import org.apache.commons.cli.PosixParser;
-import org.apache.commons.cli.OptionBuilder;
-import org.apache.commons.cli.Option;
+
+import junit.framework.TestCase;
 
 /**
+ * http://issues.apache.org/jira/browse/CLI-148
+ *
  * @author brianegge
  */
-public class BugCLI51Test
-    extends TestCase
-{
-    public void test() throws Exception
+public class BugCLI148Test  extends TestCase {
+
+    public void testWorkaround1() throws Exception
     {
         Options options = buildCommandLineOptions();
         CommandLineParser parser = new PosixParser();
-        String[] args = new String[] {"-t", "-something" };
+        String[] args = new String[] {"-t-something" };
+        CommandLine commandLine;
+        commandLine = parser.parse( options, args );
+        assertEquals("-something", commandLine.getOptionValue( 't'));
+    }
+
+    public void testWorkaround2() throws Exception
+    {
+        Options options = buildCommandLineOptions();
+        CommandLineParser parser = new PosixParser();
+        String[] args = new String[] {"-t", "\"-something\"" };
         CommandLine commandLine;
         commandLine = parser.parse( options, args );
         assertEquals("-something", commandLine.getOptionValue( 't'));
@@ -43,9 +55,12 @@ public class BugCLI51Test
 
     private Options buildCommandLineOptions()
     {
-        Option opt = OptionBuilder.withArgName( "t").hasArg().create('t');
+        Option t = OptionBuilder.withArgName( "t").hasArg().create('t');
+        Option s = OptionBuilder.withArgName( "s").hasArg().create('s');
         Options options = new Options();
-        options.addOption( opt);
+        options.addOption( t);
+        options.addOption( s);
         return options;
     }
+
 }
diff --git a/src/test/org/apache/commons/cli/bug/BugCLI162Test.java b/src/test/org/apache/commons/cli/bug/BugCLI162Test.java
new file mode 100644
index 0000000..14e1a60
--- /dev/null
+++ b/src/test/org/apache/commons/cli/bug/BugCLI162Test.java
@@ -0,0 +1,285 @@
+/*
+ * 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.cli.bug;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.sql.ParameterMetaData;
+import java.sql.Types;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+
+public class BugCLI162Test extends TestCase {
+    /** Constant for the line separator.*/
+    private static final String CR = System.getProperty("line.separator");
+
+    public void testInfiniteLoop() {
+        Options options = new Options();
+        options.addOption("h", "help", false, "This is a looooong description");
+        HelpFormatter formatter = new HelpFormatter();
+        formatter.setWidth(20);
+        formatter.printHelp("app", options); // used to hang & crash
+    }
+
+    public void testPrintHelpLongLines() throws ParseException, IOException {
+        // Constants used for options
+        final String OPT = "-";
+
+        final String OPT_COLUMN_NAMES = "l";
+
+        final String OPT_CONNECTION = "c";
+
+        final String OPT_DESCRIPTION = "e";
+
+        final String OPT_DRIVER = "d";
+
+        final String OPT_DRIVER_INFO = "n";
+
+        final String OPT_FILE_BINDING = "b";
+
+        final String OPT_FILE_JDBC = "j";
+
+        final String OPT_FILE_SFMD = "f";
+
+        final String OPT_HELP = "h";
+
+        final String OPT_HELP_ = "help";
+
+        final String OPT_INTERACTIVE = "i";
+
+        final String OPT_JDBC_TO_SFMD = "2";
+
+        final String OPT_JDBC_TO_SFMD_L = "jdbc2sfmd";
+
+        final String OPT_METADATA = "m";
+
+        final String OPT_PARAM_MODES_INT = "o";
+
+        final String OPT_PARAM_MODES_NAME = "O";
+
+        final String OPT_PARAM_NAMES = "a";
+
+        final String OPT_PARAM_TYPES_INT = "y";
+
+        final String OPT_PARAM_TYPES_NAME = "Y";
+
+        final String OPT_PASSWORD = "p";
+
+        final String OPT_PASSWORD_L = "password";
+
+        final String OPT_SQL = "s";
+
+        final String OPT_SQL_L = "sql";
+
+        final String OPT_SQL_SPLIT_DEFAULT = "###";
+
+        final String OPT_SQL_SPLIT_L = "splitSql";
+
+        final String OPT_STACK_TRACE = "t";
+
+        final String OPT_TIMING = "g";
+
+        final String OPT_TRIM_L = "trim";
+
+        final String OPT_USER = "u";
+
+        final String OPT_WRITE_TO_FILE = "w";
+
+        final String _PMODE_IN = "IN";
+
+        final String _PMODE_INOUT = "INOUT";
+
+        final String _PMODE_OUT = "OUT";
+
+        final String _PMODE_UNK = "Unknown";
+
+        final String PMODES = _PMODE_IN + ", " + _PMODE_INOUT + ", " + _PMODE_OUT + ", " + _PMODE_UNK;
+
+        // Options build
+        Options commandLineOptions;
+        commandLineOptions = new Options();
+        commandLineOptions.addOption(OPT_HELP, OPT_HELP_, false, "Prints help and quits");
+        commandLineOptions.addOption(OPT_DRIVER, "driver", true, "JDBC driver class name");
+        commandLineOptions.addOption(OPT_DRIVER_INFO, "info", false, "Prints driver information and properties. If "
+            + OPT
+            + OPT_CONNECTION
+            + " is not specified, all drivers on the classpath are displayed.");
+        commandLineOptions.addOption(OPT_CONNECTION, "url", true, "Connection URL");
+        commandLineOptions.addOption(OPT_USER, "user", true, "A database user name");
+        commandLineOptions
+                .addOption(
+                        OPT_PASSWORD,
+                        OPT_PASSWORD_L,
+                        true,
+                        "The database password for the user specified with the "
+                            + OPT
+                            + OPT_USER
+                            + " option. You can obfuscate the password with org.mortbay.jetty.security.Password, see http://docs.codehaus.org/display/JETTY/Securing+Passwords");
+        commandLineOptions.addOption(OPT_SQL, OPT_SQL_L, true, "Runs SQL or {call stored_procedure(?, ?)} or {?=call function(?, ?)}");
+        commandLineOptions.addOption(OPT_FILE_SFMD, "sfmd", true, "Writes a SFMD file for the given SQL");
+        commandLineOptions.addOption(OPT_FILE_BINDING, "jdbc", true, "Writes a JDBC binding node file for the given SQL");
+        commandLineOptions.addOption(OPT_FILE_JDBC, "node", true, "Writes a JDBC node file for the given SQL (internal debugging)");
+        commandLineOptions.addOption(OPT_WRITE_TO_FILE, "outfile", true, "Writes the SQL output to the given file");
+        commandLineOptions.addOption(OPT_DESCRIPTION, "description", true,
+                "SFMD description. A default description is used if omited. Example: " + OPT + OPT_DESCRIPTION + " \"Runs such and such\"");
+        commandLineOptions.addOption(OPT_INTERACTIVE, "interactive", false,
+                "Runs in interactive mode, reading and writing from the console, 'go' or '/' sends a statement");
+        commandLineOptions.addOption(OPT_TIMING, "printTiming", false, "Prints timing information");
+        commandLineOptions.addOption(OPT_METADATA, "printMetaData", false, "Prints metadata information");
+        commandLineOptions.addOption(OPT_STACK_TRACE, "printStack", false, "Prints stack traces on errors");
+        Option option = new Option(OPT_COLUMN_NAMES, "columnNames", true, "Column XML names; default names column labels. Example: "
+            + OPT
+            + OPT_COLUMN_NAMES
+            + " \"cname1 cname2\"");
+        commandLineOptions.addOption(option);
+        option = new Option(OPT_PARAM_NAMES, "paramNames", true, "Parameter XML names; default names are param1, param2, etc. Example: "
+            + OPT
+            + OPT_PARAM_NAMES
+            + " \"pname1 pname2\"");
+        commandLineOptions.addOption(option);
+        //
+        OptionGroup pOutTypesOptionGroup = new OptionGroup();
+        String pOutTypesOptionGroupDoc = OPT + OPT_PARAM_TYPES_INT + " and " + OPT + OPT_PARAM_TYPES_NAME + " are mutually exclusive.";
+        final String typesClassName = Types.class.getName();
+        option = new Option(OPT_PARAM_TYPES_INT, "paramTypes", true, "Parameter types from "
+            + typesClassName
+            + ". "
+            + pOutTypesOptionGroupDoc
+            + " Example: "
+            + OPT
+            + OPT_PARAM_TYPES_INT
+            + " \"-10 12\"");
+        commandLineOptions.addOption(option);
+        option = new Option(OPT_PARAM_TYPES_NAME, "paramTypeNames", true, "Parameter "
+            + typesClassName
+            + " names. "
+            + pOutTypesOptionGroupDoc
+            + " Example: "
+            + OPT
+            + OPT_PARAM_TYPES_NAME
+            + " \"CURSOR VARCHAR\"");
+        commandLineOptions.addOption(option);
+        commandLineOptions.addOptionGroup(pOutTypesOptionGroup);
+        //
+        OptionGroup modesOptionGroup = new OptionGroup();
+        String modesOptionGroupDoc = OPT + OPT_PARAM_MODES_INT + " and " + OPT + OPT_PARAM_MODES_NAME + " are mutually exclusive.";
+        option = new Option(OPT_PARAM_MODES_INT, "paramModes", true, "Parameters modes ("
+            + ParameterMetaData.parameterModeIn
+            + "=IN, "
+            + ParameterMetaData.parameterModeInOut
+            + "=INOUT, "
+            + ParameterMetaData.parameterModeOut
+            + "=OUT, "
+            + ParameterMetaData.parameterModeUnknown
+            + "=Unknown"
+            + "). "
+            + modesOptionGroupDoc
+            + " Example for 2 parameters, OUT and IN: "
+            + OPT
+            + OPT_PARAM_MODES_INT
+            + " \""
+            + ParameterMetaData.parameterModeOut
+            + " "
+            + ParameterMetaData.parameterModeIn
+            + "\"");
+        modesOptionGroup.addOption(option);
+        option = new Option(OPT_PARAM_MODES_NAME, "paramModeNames", true, "Parameters mode names ("
+            + PMODES
+            + "). "
+            + modesOptionGroupDoc
+            + " Example for 2 parameters, OUT and IN: "
+            + OPT
+            + OPT_PARAM_MODES_NAME
+            + " \""
+            + _PMODE_OUT
+            + " "
+            + _PMODE_IN
+            + "\"");
+        modesOptionGroup.addOption(option);
+        commandLineOptions.addOptionGroup(modesOptionGroup);
+        option = new Option(null, OPT_TRIM_L, true,
+                "Trims leading and trailing spaces from all column values. Column XML names can be optionally specified to set which columns to trim.");
+        option.setOptionalArg(true);
+        commandLineOptions.addOption(option);
+        option = new Option(OPT_JDBC_TO_SFMD, OPT_JDBC_TO_SFMD_L, true,
+                "Converts the JDBC file in the first argument to an SMFD file specified in the second argument.");
+        option.setArgs(2);
+        commandLineOptions.addOption(option);
+        new HelpFormatter().printHelp(this.getClass().getName(), commandLineOptions);
+    }
+
+    public void testLongLineChunking() throws ParseException, IOException {
+        Options options = new Options();
+        options.addOption("x", "extralongarg", false,
+                                     "This description has ReallyLongValuesThatAreLongerThanTheWidthOfTheColumns " +
+                                     "and also other ReallyLongValuesThatAreHugerAndBiggerThanTheWidthOfTheColumnsBob, " +
+                                     "yes. ");
+        HelpFormatter formatter = new HelpFormatter();
+        StringWriter sw = new StringWriter();
+        formatter.printHelp(new PrintWriter(sw), 35, this.getClass().getName(), "Header", options, 0, 5, "Footer");
+        String expected = "usage:" + CR +
+                          "       org.apache.commons.cli.bug.B" + CR +
+                          "       ugCLI162Test" + CR +
+                          "Header" + CR +
+                          "-x,--extralongarg     This" + CR +
+                          "                      description" + CR +
+                          "                      has" + CR +
+                          "                      ReallyLongVal" + CR +
+                          "                      uesThatAreLon" + CR +
+                          "                      gerThanTheWid" + CR +
+                          "                      thOfTheColumn" + CR +
+                          "                      s and also" + CR +
+                          "                      other" + CR +
+                          "                      ReallyLongVal" + CR +
+                          "                      uesThatAreHug" + CR +
+                          "                      erAndBiggerTh" + CR +
+                          "                      anTheWidthOfT" + CR +
+                          "                      heColumnsBob," + CR +
+                          "                      yes." + CR +
+                          "Footer" + CR;
+        assertEquals( "Long arguments did not split as expected", expected, sw.toString() );
+    }
+
+    public void testLongLineChunkingIndentIgnored() throws ParseException, IOException {
+        Options options = new Options();
+        options.addOption("x", "extralongarg", false, "This description is Long." );
+        HelpFormatter formatter = new HelpFormatter();
+        StringWriter sw = new StringWriter();
+        formatter.printHelp(new PrintWriter(sw), 22, this.getClass().getName(), "Header", options, 0, 5, "Footer");
+        System.err.println(sw.toString());
+        String expected = "usage:" + CR +
+                          "       org.apache.comm" + CR +
+                          "       ons.cli.bug.Bug" + CR +
+                          "       CLI162Test" + CR +
+                          "Header" + CR +
+                          "-x,--extralongarg" + CR +
+                          " This description is" + CR +
+                          " Long." + CR +
+                          "Footer" + CR;
+        assertEquals( "Long arguments did not split as expected", expected, sw.toString() );
+    }
+
+}
diff --git a/src/test/org/apache/commons/cli/bug/BugCLI18Test.java b/src/test/org/apache/commons/cli/bug/BugCLI18Test.java
index 9ba3ca3..7a04698 100644
--- a/src/test/org/apache/commons/cli/bug/BugCLI18Test.java
+++ b/src/test/org/apache/commons/cli/bug/BugCLI18Test.java
@@ -14,30 +14,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.cli.bug;
 
-import org.apache.commons.cli.*;
+package org.apache.commons.cli.bug;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
 
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+
 import junit.framework.TestCase;
 
 /**
  * http://issues.apache.org/jira/browse/CLI-18
  */
-public class BugCLI18Test extends TestCase {
-
-  public void testCLI18() {
-    Options options = new Options();
-    options.addOption(new Option("a","aaa",false,"aaaaaaa"));
-    options.addOption(new Option(null,"bbb",false,"bbbbbbb dksh fkshd fkhs dkfhsdk fhskd hksdks dhfowehfsdhfkjshf skfhkshf sf jkshfk sfh skfh skf f"));
-    options.addOption(new Option("c",null,false,"ccccccc"));
-
-    HelpFormatter formatter = new HelpFormatter();
-    StringWriter out = new StringWriter();
-
-    formatter.printHelp(new PrintWriter(out),80, "foobar", "dsfkfsh kdh hsd hsdh fkshdf ksdh fskdh fsdh fkshfk sfdkjhskjh fkjh fkjsh khsdkj hfskdhf skjdfh ksf khf s", options, 2, 2, "blort j jgj j jg jhghjghjgjhgjhg jgjhgj jhg jhg hjg jgjhghjg jhg hjg jhgjg jgjhghjg jg jgjhgjgjg jhg jhgjh" + '\r' + '\n' + "rarrr", true);
-  }
+public class BugCLI18Test extends TestCase
+{
+    public void testCLI18()
+    {
+        Options options = new Options();
+        options.addOption(new Option("a", "aaa", false, "aaaaaaa"));
+        options.addOption(new Option(null, "bbb", false, "bbbbbbb dksh fkshd fkhs dkfhsdk fhskd hksdks dhfowehfsdhfkjshf skfhkshf sf jkshfk sfh skfh skf f"));
+        options.addOption(new Option("c", null, false, "ccccccc"));
+
+        HelpFormatter formatter = new HelpFormatter();
+        StringWriter out = new StringWriter();
+
+        formatter.printHelp(new PrintWriter(out), 80, "foobar", "dsfkfsh kdh hsd hsdh fkshdf ksdh fskdh fsdh fkshfk sfdkjhskjh fkjh fkjsh khsdkj hfskdhf skjdfh ksf khf s", options, 2, 2, "blort j jgj j jg jhghjghjgjhgjhg jgjhgj jhg jhg hjg jgjhghjg jhg hjg jhgjg jgjhghjg jg jgjhgjgjg jhg jhgjh" + '\r' + '\n' + "rarrr", true);
+    }
 }
-
diff --git a/src/test/org/apache/commons/cli/bug/BugCLI71Test.java b/src/test/org/apache/commons/cli/bug/BugCLI71Test.java
index e2bd2d1..c0d8ec1 100644
--- a/src/test/org/apache/commons/cli/bug/BugCLI71Test.java
+++ b/src/test/org/apache/commons/cli/bug/BugCLI71Test.java
@@ -14,11 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+
 package org.apache.commons.cli.bug;
 
-import junit.framework.TestCase;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.MissingArgumentException;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.PosixParser;
 
-import org.apache.commons.cli.*;
+import junit.framework.TestCase;
 
 public class BugCLI71Test extends TestCase {
 
@@ -60,8 +67,8 @@ public class BugCLI71Test extends TestCase {
         try {
             CommandLine line = parser.parse( options, args);
             fail("MissingArgumentException expected");
-        } catch(MissingArgumentException mae) {
-            // expected
+        } catch(MissingArgumentException e) {
+            assertEquals("option missing an argument", "k", e.getOption().getOpt());
         }
     }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/libcommons-cli-java.git



More information about the pkg-java-commits mailing list