[libcommons-cli-java] 01/31: Imported Upstream version 1.0

Tony Mancill tmancill at moszumanska.debian.org
Mon Jun 22 05:52:45 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 9f88773035367d3c68268e3f1d18c6e3c7e3f586
Author: tony mancill <tmancill at debian.org>
Date:   Mon Jun 22 04:35:35 2015 +0000

    Imported Upstream version 1.0
---
 .cvsignore                                         |   7 +
 LICENSE.txt                                        |  60 +++
 README.txt                                         |  42 ++
 RELEASE-NOTES.txt                                  |  26 +
 build-gump.xml                                     |  36 ++
 build.xml                                          | 158 ++++++
 gump.xml                                           |  40 ++
 maven.xml                                          |   4 +
 project.properties                                 |  32 ++
 project.xml                                        |  87 ++++
 src/conf/MANIFEST.MF                               |   6 +
 .../commons/cli/AlreadySelectedException.java      |  81 +++
 src/java/org/apache/commons/cli/BasicParser.java   |  92 ++++
 src/java/org/apache/commons/cli/CommandLine.java   | 328 ++++++++++++
 .../org/apache/commons/cli/CommandLineParser.java  |  97 ++++
 src/java/org/apache/commons/cli/GnuParser.java     | 187 +++++++
 src/java/org/apache/commons/cli/HelpFormatter.java | 540 +++++++++++++++++++
 .../commons/cli/MissingArgumentException.java      |  82 +++
 .../apache/commons/cli/MissingOptionException.java |  81 +++
 src/java/org/apache/commons/cli/Option.java        | 575 +++++++++++++++++++++
 src/java/org/apache/commons/cli/OptionBuilder.java | 368 +++++++++++++
 src/java/org/apache/commons/cli/OptionGroup.java   | 184 +++++++
 src/java/org/apache/commons/cli/Options.java       | 299 +++++++++++
 .../org/apache/commons/cli/ParseException.java     |  82 +++
 src/java/org/apache/commons/cli/Parser.java        | 283 ++++++++++
 .../apache/commons/cli/PatternOptionBuilder.java   | 204 ++++++++
 src/java/org/apache/commons/cli/PosixParser.java   | 314 +++++++++++
 src/java/org/apache/commons/cli/TypeHandler.java   | 253 +++++++++
 .../commons/cli/UnrecognizedOptionException.java   |  82 +++
 src/java/org/apache/commons/cli/overview.html      |  28 +
 src/java/org/apache/commons/cli/package.html       |   6 +
 .../org/apache/commons/cli/ApplicationTest.java    | 115 +++++
 src/test/org/apache/commons/cli/BugsTest.java      | 346 +++++++++++++
 src/test/org/apache/commons/cli/BuildTest.java     |  96 ++++
 src/test/org/apache/commons/cli/GnuParseTest.java  | 264 ++++++++++
 .../apache/commons/cli/HelpFormatterExamples.java  | 106 ++++
 .../org/apache/commons/cli/OptionBuilderTest.java  | 158 ++++++
 .../org/apache/commons/cli/OptionGroupTest.java    | 244 +++++++++
 .../org/apache/commons/cli/ParseRequiredTest.java  | 111 ++++
 src/test/org/apache/commons/cli/ParseTest.java     | 284 ++++++++++
 .../commons/cli/PatternOptionBuilderTest.java      |  83 +++
 .../org/apache/commons/cli/TestHelpFormatter.java  | 171 ++++++
 src/test/org/apache/commons/cli/ValueTest.java     | 272 ++++++++++
 src/test/org/apache/commons/cli/ValuesTest.java    | 248 +++++++++
 xdocs/images/1x1.gif                               | Bin 0 -> 43 bytes
 xdocs/index.xml                                    |  29 ++
 xdocs/introduction.xml                             |  87 ++++
 xdocs/navigation.xml                               |  14 +
 xdocs/properties.xml                               |  97 ++++
 xdocs/usage.xml                                    | 350 +++++++++++++
 50 files changed, 7739 insertions(+)

diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..b487296
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,7 @@
+build.properties
+dist
+target
+velocity.log
+.project
+
+maven.log
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..a8684f1
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,60 @@
+/*
+ * $Header: /home/cvs/jakarta-commons/LICENSE,v 1.4 2002/04/11 13:24:02 dion Exp $
+ * $Revision: 1.4 $
+ * $Date: 2002/04/11 13:24:02 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..05ca410
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,42 @@
+Jakarta Commons CLI
+===================
+
+Welcome to the CLI component of the Jakarta 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.
+
+Ant can be found here :
+
+  http://jakarta.apache.org/ant
+
+and to build and test the system use:
+
+  ant dist
+
+Maven can be found here :
+
+  http://jakarta.apache.org/turbine/maven/
+
+and to build and test the system use:
+
+  maven java:jar
+
+The system will build and test itself.
+
+For complete documentation and to create a local copy of the
+CLI project website, type:
+
+  maven site
+
+Good luck!
+
+-The CLI Team
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
new file mode 100644
index 0000000..f29b7b2
--- /dev/null
+++ b/RELEASE-NOTES.txt
@@ -0,0 +1,26 @@
+$Id: RELEASE-NOTES.txt,v 1.1 2002/11/06 05:09:21 bayard Exp $
+
+			Commons CLI Package
+			   Version 1.0
+			    Release Notes
+
+
+INTRODUCTION:
+
+This document contains the release notes for this version of the Commons
+CLI package. Commons CLI provdes a simple API for working with the command line arguments and options.
+
+This is the first release of the CLI component, therefore all features are new, 
+there are no bug-fixes, nothing is deprecated and there are no changes.
+
+For more information, read the documentation on the project site at 
+http://jakarta.apache.org/commons/cli/
+
+NEW FEATURES:
+
+BUG FIXES:
+
+DEPRECATIONS:
+
+CHANGES: 
+
diff --git a/build-gump.xml b/build-gump.xml
new file mode 100644
index 0000000..b5d7d58
--- /dev/null
+++ b/build-gump.xml
@@ -0,0 +1,36 @@
+<!--
+
+  WARNING: This file is generated! Do not edit by hand!
+  
+-->
+
+<project name="maven" default="jar" basedir=".">
+
+  <target
+    name="jar">
+    
+    <property name="maven.build.dir" value="target"/>
+    <property name="maven.build.dest" value="${maven.build.dir}/classes"/>
+    
+    <mkdir dir="${maven.build.dest}"/>
+    
+    <javac
+      destdir="${maven.build.dest}"
+      excludes="**/package.html"
+      debug="false"
+      deprecation="false"
+      optimize="false">
+      <src>
+         <pathelement location="src/java"/>
+      </src>
+    </javac>
+
+    <jar
+      jarfile="${maven.build.dir}/${maven.final.name}.jar"
+      basedir="${maven.build.dest}"
+      excludes="**/package.html"
+    />
+    
+  </target>
+
+</project>
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..28a5ef1
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project default="jar" name="commons-cli" basedir=".">
+  
+  <property name="defaulttargetdir" value="target"></property> 
+  <property name="classesdir" value="target/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="target/docs/apidocs"></property>
+  <property name="final.name" value="commons-cli-1.0-beta-2-dev"></property>
+  
+  <target name="init" description="o Initializes some properties">
+
+    <condition property="noget">
+      <equals arg2="only" arg1="${build.sysclasspath}"></equals>
+    </condition>
+  </target>
+    
+  <target name="jar" description="o Create the jar" 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>
+        <fileset dir="lib">
+          <include name="*.jar"></include>
+        </fileset>
+      </classpath>
+    </javac>
+
+    
+    <jar jarfile="target/${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}"></fileset>
+    </copy>
+  </target>
+ 
+  <target name="test" description="o Run the test cases" depends="compile-tests">
+    <mkdir dir="${testreportdir}"></mkdir>
+    <junit dir="./" printSummary="yes" fork="true" haltonerror="true">
+      <sysproperty key="basedir" value="src/test"></sysproperty>
+      <formatter type="xml"></formatter>
+      <formatter usefile="true" type="plain"></formatter>
+      <classpath>
+        <fileset dir="lib">
+          <include name="*.jar"></include>
+        </fileset>
+        <pathelement location="target/${final.name}.jar"></pathelement>
+        <pathelement path="${testclassesdir}"></pathelement>
+      </classpath>
+      <batchtest todir="${testreportdir}">
+        <fileset dir="src/test">
+              
+                <include name="**/*Test*.java"></include>
+              
+              
+        </fileset>
+      </batchtest>
+    </junit>
+  </target>
+
+  <target name="compile-tests" depends="jar">
+    <mkdir dir="${testclassesdir}"></mkdir>
+    <javac destdir="${testclassesdir}" deprecation="true" debug="true" optimize="false" excludes="**/package.html">
+      <src>
+        <pathelement location="src/test"></pathelement>
+      </src>
+      <classpath>
+        <fileset dir="lib">
+          <include name="*.jar"></include>
+        </fileset>
+        <pathelement location="target/${final.name}.jar"></pathelement>
+      </classpath>
+    </javac>
+
+    
+   
+    
+ 
+    <copy todir="${testclassesdir}">
+      <fileset dir="src/test">
+      
+      
+      </fileset>
+    </copy>
+    
+  </target>
+
+  <target name="javadoc" description="o Generate javadoc" depends="jar">
+ 
+ 
+    <mkdir dir="${javadocdir}"></mkdir>
+ 
+    
+    <tstamp>
+      <format pattern="2002-yyyy" property="year"></format>
+    </tstamp>
+ 
+    <property name="copyright" value="Copyright &copy;  Apache Software Foundation. All Rights Reserved."></property>
+ 
+    <property name="title" value="CLI 1.0-beta-2-dev API"></property>
+ 
+    <javadoc use="true" private="true" destdir="${javadocdir}" author="true" version="true" sourcepath="src/java" packagenames="org.apache.commons.cli.*">
+      <classpath>
+        <fileset dir="lib">
+          <include name="*.jar"></include>
+        </fileset>
+        <pathelement location="target/${final.name}.jar"></pathelement>
+      </classpath>
+    </javadoc>
+ 
+  </target>
+
+  <target name="get-deps" unless="noget" depends="init">
+  
+    <mkdir dir="lib"></mkdir>
+    
+    <get dest="lib/commons-logging-1.0.jar" usetimestamp="true" ignoreerrors="true" src="http://www.ibiblio.org/maven/commons-logging/jars/commons-logging-1.0.jar"></get>
+    <get dest="lib/commons-lang-SNAPSHOT.jar" usetimestamp="true" ignoreerrors="true" src="http://www.ibiblio.org/maven/commons-lang/jars/commons-lang-SNAPSHOT.jar"></get>
+    <get dest="lib/junit-3.7.jar" usetimestamp="true" ignoreerrors="true" src="http://www.ibiblio.org/maven/junit/jars/junit-3.7.jar"></get>
+  
+  </target>
+
+  
+  
+  
+  
+  
+  
+  
+  
+
+  <target name="install-maven">
+
+    
+
+    <get dest="${user.home}/maven-install-latest.jar" usetimestamp="true" src="${maven.repo.remote}/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/gump.xml b/gump.xml
new file mode 100644
index 0000000..34dda13
--- /dev/null
+++ b/gump.xml
@@ -0,0 +1,40 @@
+<module name="commons-cli">
+
+
+  <description>Commons CLI</description>
+  <url href="http://jakarta.apache.org/commons/sandbox/cli.html"/>
+  
+  <cvs repository="jakarta"/>
+  
+  <!-- This is really the cvs module. We need to change this but -->
+  <!-- I will leave this for now until everything works.         -->
+  
+  <project name="commons-cli">
+    
+    <!-- Standard Maven target to produce Javadocs, source -->
+    <!-- and binary distributions.                         -->
+    <ant buildfile="build-gump.xml" target="jar">
+      <property name="maven.final.name" value="commons-cli-@@DATE@@"/>
+    </ant>
+
+    <package>org.apache.commons.cli</package>
+
+    <!-- All Maven projects need Ant and Xerces to build. -->
+    <depend project="jakarta-ant"/>
+    <depend project="xml-xerces"/>
+
+    <depend project="commons-logging"/>
+    <depend project="commons-lang"/>
+
+    <work nested="target/classes"/>
+    <home nested="target"/>
+    <jar name="commons-cli-@@DATE@@.jar"/>
+    <javadoc nested="docs/apidocs"/>
+
+    <nag from="Maven Developers <turbine-maven-dev at jakarta.apache.org>"
+         to="commons-dev at jakarta.apache.org"/>
+
+    
+  </project>
+  
+</module>
diff --git a/maven.xml b/maven.xml
new file mode 100644
index 0000000..1a28e1d
--- /dev/null
+++ b/maven.xml
@@ -0,0 +1,4 @@
+<project default="java:jar"
+  xmlns:j="jelly:core">
+
+</project>
diff --git a/project.properties b/project.properties
new file mode 100644
index 0000000..db972c6
--- /dev/null
+++ b/project.properties
@@ -0,0 +1,32 @@
+# -------------------------------------------------------------------
+# P R O J E C T  P R O P E R T I E S
+# -------------------------------------------------------------------
+
+compile.debug = on
+compile.optimize = off
+compile.deprecation = off
+
+maven.jarResources.basedir=${basedir}/src/java
+ 
+# coding standards
+
+maven.checkstyle.rcurly = ignore
+maven.checkstyle.lcurly.type = ignore
+maven.checkstyle.lcurly.method = ignore
+maven.checkstyle.lcurly.other = ignore
+maven.checkstyle.header.file = LICENSE.txt
+maven.checkstyle.header.ignore.line = 1,2,3,4
+maven.checkstyle.const.pattern = ^[A-Z0-9_]*$
+maven.checkstyle.static.pattern = ^[a-zA-Z][a-zA-Z0-9_]*$
+maven.checkstyle.member.pattern = ^[_]?[a-z]?[a-zA-Z0-9]*$
+maven.checkstyle.ignore.line.len.pattern = ^[ \* \$]+[.]*
+
+maven.checkstyle.javadoc.scope = protected
+
+# disable these non-critical errors to highlight
+# more important ones like missing javadoc
+
+maven.checkstyle.max.line.len = 100
+maven.checkstyle.ignore.whitespace = true
+maven.checkstyle.ignore.public.in.interface = true
+
diff --git a/project.xml b/project.xml
new file mode 100644
index 0000000..60a5661
--- /dev/null
+++ b/project.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project>
+  <extend>../project.xml</extend>
+  <id>commons-cli</id>
+  <name>CLI</name>
+
+  <currentVersion>1.0</currentVersion>
+  <inceptionYear>2002</inceptionYear>
+  <shortDescription>Commons CLI</shortDescription>
+  <gumpRepositoryId>jakarta</gumpRepositoryId>
+  <logo>/images/1x1.gif</logo>
+  
+  <description>
+  	Commons CLI provides a simple API for working with the command line arguments and options.
+  </description>
+  
+  <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>
+    </developer>
+    <developer>
+      <name>John Keyes</name>
+      <id>jkeyes</id>
+      <email>jbjk at mac.com</email>
+      <organization>integral Source</organization>
+    </developer>
+  </developers>
+
+  <contributors>
+    <!-- Helped in merging Avalon CLI -->
+    <contributor>
+      <name>Berin Loritsch</name>
+      <email>bloritsch at apache.org</email>
+      <id>bloritsch</id>
+      <roles>
+        <role>helped in the Avalon CLI merge</role>
+      </roles>
+    </contributor>
+    <!-- Supplied patch -->
+    <contributor>
+      <name>Peter Maddocks</name>
+      <email>peter_maddocks at hp.com</email>
+      <organization>Hewlett-Packard</organization>
+      <roles>
+        <role>supplied patch</role>
+      </roles>
+    </contributor>
+  </contributors>
+
+  <dependencies>
+    
+    <dependency>
+      <id>commons-logging</id>
+      <version>1.0</version>
+    </dependency>
+    
+    <dependency>
+      <id>commons-lang</id>
+      <version>1.0</version>
+    </dependency>
+  
+    <dependency>
+      <id>junit</id>
+      <version>3.7</version>
+    </dependency>
+  
+  </dependencies>
+  
+  <build>
+    <!-- Unit test classes -->
+    <unitTest>
+      <includes>
+        <include>**/*Test*.java</include>
+      </includes>
+    </unitTest>
+  </build>
+</project>
diff --git a/src/conf/MANIFEST.MF b/src/conf/MANIFEST.MF
new file mode 100644
index 0000000..d2989c5
--- /dev/null
+++ b/src/conf/MANIFEST.MF
@@ -0,0 +1,6 @@
+Extension-Name: org.apache.commons.cli
+Specification-Vendor: Apache Software Foundation
+Specification-Version: 1.0
+Implementation-Vendor: Apache Software Foundation
+Implementation-Version: 1.0-dev
+
diff --git a/src/java/org/apache/commons/cli/AlreadySelectedException.java b/src/java/org/apache/commons/cli/AlreadySelectedException.java
new file mode 100644
index 0000000..6dcd3cb
--- /dev/null
+++ b/src/java/org/apache/commons/cli/AlreadySelectedException.java
@@ -0,0 +1,81 @@
+/*
+ * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli/AlreadySelectedException.java,v 1.4 2002/06/06 09:37:26 jstrachan Exp $
+ * $Revision: 1.4 $
+ * $Date: 2002/06/06 09:37:26 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.commons.cli;
+
+/** 
+ * <p>Thrown when more than one option in an option group
+ * has been provided.</p>
+ *
+ * @author John Keyes ( john at integralsource.com )
+ * @see ParseException
+ */
+public class AlreadySelectedException extends ParseException {
+
+    /** 
+     * <p>Construct a new <code>AlreadySelectedException</code> 
+     * with the specified detail message.</p>
+     *
+     * @param message the detail message
+     */
+    public AlreadySelectedException( String message ) {
+        super( message );
+    }
+}
diff --git a/src/java/org/apache/commons/cli/BasicParser.java b/src/java/org/apache/commons/cli/BasicParser.java
new file mode 100644
index 0000000..a3526ef
--- /dev/null
+++ b/src/java/org/apache/commons/cli/BasicParser.java
@@ -0,0 +1,92 @@
+/*
+ * $Header: /home/cvspublic/jakarta-commons/cli/src/java/org/apache/commons/cli/BasicParser.java,v 1.3 2002/09/19 22:59:43 jkeyes Exp $
+ * $Revision: 1.3 $
+ * $Date: 2002/09/19 22:59:43 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.commons.cli;
+
+/**
+ * The class BasicParser provides a very simple implementation of
+ * the {@link Parser#flatten(Options,String[],boolean) flatten} method.
+ *
+ * @author John Keyes (john at integralsource.com)
+ * @see Parser
+ */
+public class BasicParser extends Parser {
+
+    /**
+     * <p>A simple implementation of {@link Parser}'s abstract
+     * {@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>
+     *
+     * @param options The command line {@link Options}
+     * @param arguments The command line arguments to be parsed
+     * @param stopAtNonOption Specifies whether to stop flattening
+     * when an non option is found.
+     * @return The <code>arguments</code> String array.
+     */
+    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
new file mode 100644
index 0000000..8b45ea2
--- /dev/null
+++ b/src/java/org/apache/commons/cli/CommandLine.java
@@ -0,0 +1,328 @@
+/*
+ * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli/CommandLine.java,v 1.4 2002/06/06 22:32:37 bayard Exp $
+ * $Revision: 1.4 $
+ * $Date: 2002/06/06 22:32:37 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.commons.cli;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Map;
+
+/** 
+ * <p>Represents list of arguments parsed against
+ * a {@link Options} descriptor.<p>
+ *
+ * <p>It allows querying of a boolean {@link #hasOption(String opt)},
+ * in addition to retrieving the {@link #getOptionValue(String opt)}
+ * for options requiring arguments.</p>
+ *
+ * <p>Additionally, any left-over or unrecognized arguments,
+ * are available for further processing.</p>
+ *
+ * @author bob mcwhirter (bob @ werken.com)
+ * @author <a href="mailto:jstrachan at apache.org">James Strachan</a>
+ * @author John Keyes (john at integralsource.com)
+ */
+public class CommandLine {
+    
+    /** the unrecognised options/arguments */
+    private List args    = new LinkedList();
+
+    /** the processed options */
+    private Map options = new HashMap();
+
+    /** Map of unique options for ease to get complete list of options */
+    private Map hashcodeMap = new HashMap();
+
+    /** the processed options */
+    private Option[] optionsArray;
+
+    /**
+     * <p>Creates a command line.</p>
+     */
+    CommandLine() {
+    }
+    
+    /** 
+     * <p>Query to see if an option has been set.</p>
+     *
+     * @param opt Short name of the option
+     * @return true if set, false if not
+     */
+    public boolean hasOption(String opt) {
+        return options.containsKey( opt );
+    }
+
+    /** 
+     * <p>Query to see if an option has been set.</p>
+     *
+     * @param opt character name of the option
+     * @return true if set, false if not
+     */
+    public boolean hasOption( char opt ) {
+        return hasOption( String.valueOf( opt ) );
+    }
+
+    /**
+     * <p>Return the <code>Object</code> type of this <code>Option</code>.</p>
+     *
+     * @param opt the name of the option
+     * @return the type of this <code>Option</code>
+     */
+    public Object getOptionObject( String opt ) {
+        String res = getOptionValue( opt );
+        
+        Object type = ((Option)((List)options.get(opt)).iterator().next()).getType();
+        return res == null ? null : TypeHandler.createValue(res, type);
+    }
+
+    /**
+     * <p>Return the <code>Object</code> type of this <code>Option</code>.</p>
+     *
+     * @param opt the name of the option
+     * @return the type of opt
+     */
+    public Object getOptionObject( char opt ) {
+        return getOptionObject( String.valueOf( opt ) );
+    }
+
+    /** 
+     * <p>Retrieve the argument, if any, of this option.</p>
+     *
+     * @param opt the name of the option
+     * @return Value of the argument if option is set, and has an argument,
+     * otherwise null.
+     */
+    public String getOptionValue( String opt ) {
+        String[] values = getOptionValues(opt);
+        return (values == null) ? null : values[0];
+    }
+
+    /** 
+     * <p>Retrieve the argument, if any, of this option.</p>
+     *
+     * @param opt the character name of the option
+     * @return Value of the argument if option is set, and has an argument,
+     * otherwise null.
+     */
+    public String getOptionValue( char opt ) {
+        return getOptionValue( String.valueOf( opt ) );
+    }
+
+    /** 
+     * <p>Retrieves the array of values, if any, of an option.</p>
+     *
+     * @param opt string name of the option
+     * @return Values of the argument if option is set, and has an argument,
+     * otherwise null.
+     */
+    public String[] getOptionValues( String opt ) {
+        List values = new java.util.ArrayList();
+
+        if( options.containsKey( opt ) ) {
+            List opts = (List)options.get( opt );
+            Iterator iter = opts.iterator();
+
+            while( iter.hasNext() ) {
+                Option optt = (Option)iter.next();
+                values.addAll( optt.getValuesList() );
+            }
+        }
+        return (values.size() == 0) ? null : (String[])values.toArray(new String[]{});
+    }
+
+    /** 
+     * <p>Retrieves the array of values, if any, of an option.</p>
+     *
+     * @param opt character name of the option
+     * @return Values of the argument if option is set, and has an argument,
+     * otherwise null.
+     */
+    public String[] getOptionValues( char opt ) {
+        return getOptionValues( String.valueOf( opt ) );
+    }
+    
+    /** 
+     * <p>Retrieve the argument, if any, of an option.</p>
+     *
+     * @param opt name of 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>.
+     */
+    public String getOptionValue( String opt, String defaultValue ) {
+        String answer = getOptionValue( opt );
+        return ( answer != null ) ? answer : defaultValue;
+    }
+    
+    /** 
+     * <p>Retrieve the argument, if any, of an option.</p>
+     *
+     * @param opt character name of 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>.
+     */
+    public String getOptionValue( char opt, String defaultValue ) {
+        return getOptionValue( String.valueOf( opt ), defaultValue );
+    }
+
+    /** 
+     * <p>Retrieve any left-over non-recognized options and arguments</p>
+     *
+     * @return remaining items passed in but not parsed as an array
+     */
+    public String[] getArgs() {
+        String[] answer = new String[ args.size() ];
+        args.toArray( answer );
+        return answer;
+    }
+    
+    /** 
+     * <p>Retrieve any left-over non-recognized options and arguments</p>
+     *
+     * @return remaining items passed in but not parsed as a <code>List</code>.
+     */
+    public List getArgList() {
+        return args;
+    }
+    
+    /** 
+     * jkeyes
+     * - commented out until it is implemented properly
+     * <p>Dump state, suitable for debugging.</p>
+     *
+     * @return Stringified form of this object
+     */
+    /*
+    public String toString() {
+        StringBuffer buf = new StringBuffer();
+        
+        buf.append( "[ CommandLine: [ options: " );
+        buf.append( options.toString() );
+        buf.append( " ] [ args: ");
+        buf.append( args.toString() );
+        buf.append( " ] ]" );
+        
+        return buf.toString();
+    }
+    */
+
+    /**
+     * <p>Add left-over unrecognized option/argument.</p>
+     *
+     * @param arg the unrecognised option/argument.
+     */
+    void addArg(String arg) {
+        args.add( arg );
+    }
+        
+    /**
+     * <p>Add an option to the command line.  The values of 
+     * the option are stored.</p>
+     *
+     * @param opt the processed option
+     */
+    void addOption( Option opt ) {
+        hashcodeMap.put( new Integer( opt.hashCode() ), opt );
+
+        String key = opt.getOpt();
+        if( " ".equals(key) ) {
+            key = opt.getLongOpt();
+        }
+
+        if( options.get( key ) != null ) {
+            ((java.util.List)options.get( key )).add( opt );
+        }
+        else {
+            options.put( key, new java.util.ArrayList() );
+            ((java.util.List)options.get( key ) ).add( opt );
+        }
+    }
+
+    /**
+     * <p>Returns an iterator over the Option members of CommandLine.</p>
+     *
+     * @return an <code>Iterator</code> over the processed {@link Option} 
+     * members of this {@link CommandLine}
+     */
+    public Iterator iterator( ) {
+        return hashcodeMap.values().iterator();
+    }
+
+    /**
+     * <p>Returns an array of the processed {@link Option}s.</p>
+     *
+     * @return an array of the processed {@link Option}s.
+     */
+    public Option[] getOptions( ) {
+        Collection processed = hashcodeMap.values();
+
+        // reinitialise array
+        optionsArray = new Option[ processed.size() ];
+
+        // return the array
+        return (Option[]) processed.toArray( optionsArray );
+    }
+
+}
diff --git a/src/java/org/apache/commons/cli/CommandLineParser.java b/src/java/org/apache/commons/cli/CommandLineParser.java
new file mode 100644
index 0000000..f2e6186
--- /dev/null
+++ b/src/java/org/apache/commons/cli/CommandLineParser.java
@@ -0,0 +1,97 @@
+/*
+ * $Header: /home/cvspublic/jakarta-commons/cli/src/java/org/apache/commons/cli/CommandLineParser.java,v 1.4 2002/09/19 22:59:43 jkeyes Exp $
+ * $Revision: 1.4 $
+ * $Date: 2002/09/19 22:59:43 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.commons.cli;
+
+/**
+ * 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)
+ */
+public interface CommandLineParser {
+    
+    /**
+     * Parse the arguments according to the specified options.
+     *
+     * @param options the specified Options
+     * @param arguments the command line arguments
+     * @return the list of atomic option and value tokens
+     * @throws ParseException if there are any problems encountered
+     * while parsing the command line tokens.
+     */
+    public CommandLine parse( Options options, String[] arguments )
+    throws ParseException;
+
+    /**
+     * Parse the arguments according to the specified options.
+     *
+     * @param options the specified Options
+     * @param arguments the command line arguments
+     * @param stopAtNonOption specifies whether to continue parsing the
+     * arguments if a non option is encountered.
+     * @return the list of atomic option and value tokens
+     * @throws ParseException if there are any problems encountered
+     * while parsing the command line tokens.
+     */
+    public CommandLine parse( Options options, String[] arguments, boolean stopAtNonOption )
+    throws ParseException;
+}
\ No newline at end of file
diff --git a/src/java/org/apache/commons/cli/GnuParser.java b/src/java/org/apache/commons/cli/GnuParser.java
new file mode 100644
index 0000000..198c015
--- /dev/null
+++ b/src/java/org/apache/commons/cli/GnuParser.java
@@ -0,0 +1,187 @@
+/*
+ * $Header: /home/cvspublic/jakarta-commons/cli/src/java/org/apache/commons/cli/GnuParser.java,v 1.10 2002/09/19 22:59:43 jkeyes Exp $
+ * $Revision: 1.10 $
+ * $Date: 2002/09/19 22:59:43 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.commons.cli;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * 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: 1.10 $
+ */
+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();
+    }
+
+    /**
+     * <p>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>
+     * </ol>
+     * </p>
+     */
+    protected String[] flatten( Options options, 
+                                String[] arguments, 
+                                boolean stopAtNonOption )
+    {
+        init();
+        boolean eatTheRest = false;
+        Option currentOption = null;
+
+        for( int i = 0; i < arguments.length; i++ ) {
+            if( "--".equals( arguments[i] ) ) {
+                eatTheRest = true;
+                tokens.add( "--" );
+            }
+            else if ( "-".equals( arguments[i] ) ) {
+                tokens.add( "-" );
+            }
+            else if( arguments[i].startsWith( "-" ) ) {
+                Option option = options.getOption( arguments[i] );
+
+                // this is not an Option
+                if( option == null ) {
+                    // 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] );
+                    }
+                }
+                else {
+                    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 ) {
+                        tokens.add( arguments[i] );
+                    } 
+                    else if ( stopAtNonOption ) {
+                        eatTheRest = true;
+                        tokens.add( "--" );
+                        tokens.add( arguments[i] );
+                    }
+                    else {
+                        tokens.add( arguments[i] );
+                    }
+                }
+            }
+            else {
+                tokens.add( arguments[i] );
+            }
+
+            if( eatTheRest ) {
+                for( i++; i < arguments.length; i++ ) {
+                    tokens.add( arguments[i] );
+                }
+            }
+        }
+        return (String[])tokens.toArray( new String[] {} );
+    }
+}
\ No newline at end of file
diff --git a/src/java/org/apache/commons/cli/HelpFormatter.java b/src/java/org/apache/commons/cli/HelpFormatter.java
new file mode 100644
index 0000000..1cffbf5
--- /dev/null
+++ b/src/java/org/apache/commons/cli/HelpFormatter.java
@@ -0,0 +1,540 @@
+/*
+ * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli/CommandLine.java,v 1.4 2002/06/06 22:32:37 bayard Exp $
+ * $Revision: 1.4 $
+ * $Date: 2002/06/06 22:32:37 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+/** 
+ * A formatter of help messages for the current command line options
+ *
+ * @author Slawek Zachcial
+ * @author John Keyes (john at integralsource.com)
+ **/
+public class HelpFormatter
+{
+   // --------------------------------------------------------------- Constants
+
+   public static final int DEFAULT_WIDTH              = 74;
+   public static final int DEFAULT_LEFT_PAD           = 1;
+   public static final int DEFAULT_DESC_PAD           = 3;
+   public static final String DEFAULT_SYNTAX_PREFIX   = "usage: ";
+   public static final String DEFAULT_OPT_PREFIX      = "-";
+   public static final String DEFAULT_LONG_OPT_PREFIX = "--";
+   public static final String DEFAULT_ARG_NAME        = "arg";
+
+   // ------------------------------------------------------------------ Static
+
+   // -------------------------------------------------------------- Attributes
+
+   public int defaultWidth;
+   public int defaultLeftPad;
+   public int defaultDescPad;
+   public String defaultSyntaxPrefix;
+   public String defaultNewLine;
+   public String defaultOptPrefix;
+   public String defaultLongOptPrefix;
+   public String defaultArgName;
+
+   // ------------------------------------------------------------ Constructors
+   public HelpFormatter()
+   {
+      defaultWidth = DEFAULT_WIDTH;
+      defaultLeftPad = DEFAULT_LEFT_PAD;
+      defaultDescPad = DEFAULT_DESC_PAD;
+      defaultSyntaxPrefix = DEFAULT_SYNTAX_PREFIX;
+      defaultNewLine = System.getProperty("line.separator");
+      defaultOptPrefix = DEFAULT_OPT_PREFIX;
+      defaultLongOptPrefix = DEFAULT_LONG_OPT_PREFIX;
+      defaultArgName = DEFAULT_ARG_NAME;
+   }
+
+   // ------------------------------------------------------------------ Public
+
+   public void printHelp( String cmdLineSyntax,
+                          Options options )
+   {
+       printHelp( defaultWidth, cmdLineSyntax, null, options, null, false );
+   }
+
+   public void printHelp( String cmdLineSyntax,
+                          Options options,
+                          boolean autoUsage )
+   {
+       printHelp( defaultWidth, cmdLineSyntax, null, options, null, autoUsage );
+   }
+
+   public void printHelp( String cmdLineSyntax,
+                          String header,
+                          Options options,
+                          String footer )
+   {
+       printHelp( cmdLineSyntax, header, options, footer, false );
+   }
+
+   public void printHelp( String cmdLineSyntax,
+                          String header,
+                          Options options,
+                          String footer,
+                          boolean autoUsage )
+   {
+      printHelp(defaultWidth, cmdLineSyntax, header, options, footer, autoUsage );
+   }
+   
+   public void printHelp( int width,
+                          String cmdLineSyntax,
+                          String header,
+                          Options options,
+                          String footer )
+   {
+       printHelp( width, cmdLineSyntax, header, options, footer, false );
+   }
+
+   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 );
+      pw.flush();
+   }
+   public void printHelp( PrintWriter pw,
+                          int width,
+                          String cmdLineSyntax,
+                          String header,
+                          Options options,
+                          int leftPad,
+                          int descPad,
+                          String footer )
+   throws IllegalArgumentException
+   {
+       printHelp( pw, width, cmdLineSyntax, header, options, leftPad, descPad, footer, false );
+   }
+
+   public void printHelp( PrintWriter pw,
+                          int width,
+                          String cmdLineSyntax,
+                          String header,
+                          Options options,
+                          int leftPad,
+                          int descPad,
+                          String footer,
+                          boolean autoUsage )
+      throws IllegalArgumentException
+   {
+      if ( cmdLineSyntax == null || cmdLineSyntax.length() == 0 )
+      {
+         throw new IllegalArgumentException("cmdLineSyntax not provided");
+      }
+
+      if ( autoUsage ) {
+          printUsage( pw, width, cmdLineSyntax, options );
+      }
+      else {
+          printUsage( pw, width, cmdLineSyntax );
+      }
+
+      if ( header != null && header.trim().length() > 0 )
+      {
+         printWrapped( pw, width, header );
+      }
+      printOptions( pw, width, options, leftPad, descPad );
+      if ( footer != null && footer.trim().length() > 0 )
+      {
+         printWrapped( pw, width, footer );
+      }
+   }
+
+   /**
+    * <p>Prints the usage statement for the specified application.</p>
+    *
+    * @param pw The PrintWriter to print the usage statement 
+    * @param width ??
+    * @param appName The application name
+    * @param options The command line Options
+    *
+    */
+   public void printUsage( PrintWriter pw, int width, String app, Options options ) 
+   {
+       // initialise the string buffer
+       StringBuffer buff = new StringBuffer( defaultSyntaxPrefix ).append( app ).append( " " );
+       
+       // create a list for processed option groups
+       ArrayList list = new ArrayList();
+
+       // temp variable
+       Option option;
+
+       // iterate over the options
+       for ( Iterator i = options.getOptions().iterator(); i.hasNext(); )
+       {
+           // get the next Option
+           option = (Option) i.next();
+
+           // check if the option is part of an OptionGroup
+           OptionGroup group = options.getOptionGroup( option );
+
+           // if the option is part of a group and the group has not already
+           // been processed
+           if( group != null && !list.contains(group)) {
+
+               // add the group to the processed list
+               list.add( group );
+
+               // get the names of the options from the OptionGroup
+               Collection names = group.getNames();
+
+               buff.append( "[" ); 
+
+               // for each option in the OptionGroup
+               for( Iterator iter = names.iterator(); iter.hasNext(); ) {
+                   buff.append( iter.next() );
+                   if( iter.hasNext() ) {
+                       buff.append( " | " );
+                   }
+               }
+               buff.append( "]" );
+           }
+           // if the Option is not part of an OptionGroup
+           else {
+               // if the Option is not a required option
+               if( !option.isRequired() ) {
+                   buff.append( "[" );
+               }
+               
+               if( !" ".equals( option.getOpt() ) ) {
+                   buff.append( "-" ).append( option.getOpt() );
+               }
+               else {
+                   buff.append( "--" ).append( option.getLongOpt() );
+               }
+
+               if( option.hasArg() ){
+                   buff.append( " " );
+               }
+
+               // if the Option has a value
+               if( option.hasArg() ) {
+                   buff.append( option.getArgName() );
+               }
+
+               // if the Option is not a required option
+               if( !option.isRequired() ) {
+                   buff.append( "]" );
+               }
+               buff.append( " " );
+           }
+       }
+
+       // call printWrapped
+       printWrapped( pw, width, buff.toString().indexOf(' ')+1,
+                     buff.toString() );
+   }
+
+   public void printUsage( PrintWriter pw, int width, String cmdLineSyntax )
+   {
+      int argPos = cmdLineSyntax.indexOf(' ') + 1;
+      printWrapped(pw, width, defaultSyntaxPrefix.length() + argPos,
+                   defaultSyntaxPrefix + cmdLineSyntax);
+   }
+
+   public void printOptions( PrintWriter pw, int width, Options options, int leftPad, int descPad )
+   {
+      StringBuffer sb = new StringBuffer();
+      renderOptions(sb, width, options, leftPad, descPad);
+      pw.println(sb.toString());
+   }
+
+   public void printWrapped( PrintWriter pw, int width, String text )
+   {
+      printWrapped(pw, width, 0, text);
+   }
+
+   public void printWrapped( PrintWriter pw, int width, int nextLineTabStop, String text )
+   {
+      StringBuffer sb = new StringBuffer(text.length());
+      renderWrappedText(sb, width, nextLineTabStop, text);
+      pw.println(sb.toString());
+   }
+
+   // --------------------------------------------------------------- Protected
+
+   protected StringBuffer renderOptions( StringBuffer sb,
+                                         int width,
+                                         Options options,
+                                         int leftPad,
+                                         int descPad )
+   {
+      final String lpad = createPadding(leftPad);
+      final String dpad = createPadding(descPad);
+
+      //first create list containing only <lpad>-a,--aaa where -a is opt and --aaa is
+      //long opt; in parallel look for the longest opt string
+      //this list will be then used to sort options ascending
+      int max = 0;
+      StringBuffer optBuf;
+      List prefixList = new ArrayList();
+      Option option;
+      List optList = options.helpOptions();
+      Collections.sort( optList, new StringBufferComparator() );
+      for ( Iterator i = optList.iterator(); i.hasNext(); )
+      {
+         option = (Option) i.next();
+         optBuf = new StringBuffer(8);
+
+         if (option.getOpt().equals(" "))
+         {
+             optBuf.append(lpad).append("   " + defaultLongOptPrefix).append(option.getLongOpt());
+         }
+         else
+         {
+             optBuf.append(lpad).append(defaultOptPrefix).append(option.getOpt());
+             if ( option.hasLongOpt() )
+             {
+                optBuf.append(',').append(defaultLongOptPrefix).append(option.getLongOpt());
+             }
+
+         }
+
+         if( option.hasArg() ) {
+             if( option.hasArgName() ) {
+                 optBuf.append(" <").append( option.getArgName() ).append( '>' );
+             }
+             else {
+                 optBuf.append(' ');
+             }
+         }
+
+         prefixList.add(optBuf);
+         max = optBuf.length() > max ? optBuf.length() : max;
+      }
+      int x = 0;
+      for ( Iterator i = optList.iterator(); i.hasNext(); )
+      {
+         option = (Option) i.next();
+         optBuf = new StringBuffer( prefixList.get( x++ ).toString() );
+
+         if ( optBuf.length() < max )
+         {
+             optBuf.append(createPadding(max - optBuf.length()));
+         }
+         optBuf.append( dpad );
+         
+         int nextLineTabStop = max + descPad;
+         renderWrappedText(sb, width, nextLineTabStop,
+                           optBuf.append(option.getDescription()).toString());
+         if ( i.hasNext() )
+         {
+             sb.append(defaultNewLine);
+         }
+      }
+
+      return sb;
+   }
+
+   protected StringBuffer renderWrappedText( StringBuffer sb,
+                                             int width,
+                                             int nextLineTabStop,
+                                             String text )
+   {
+      int pos = findWrapPos( text, width, 0);
+      if ( pos == -1 )
+      {
+         sb.append(rtrim(text));
+         return sb;
+      }
+      else
+      {
+         sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
+      }
+
+      //all following lines must be padded with nextLineTabStop space characters
+      final String padding = createPadding(nextLineTabStop);
+
+      while ( true )
+      {
+         text = padding + text.substring(pos).trim();
+         pos = findWrapPos( text, width, nextLineTabStop );
+         if ( pos == -1 )
+         {
+            sb.append(text);
+            return sb;
+         }
+
+         sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
+      }
+
+   }
+
+   /**
+    * Finds the next text wrap position after <code>startPos</code> for the text
+    * in <code>sb</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 sb text to be analyzed
+    * @param width width of the wrapped text
+    * @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 position is at the end
+    *         of the text
+    */
+   protected int findWrapPos( String text, int width, int startPos )
+   {
+      int pos = -1;
+      // 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) )
+      {
+         return pos;
+      }
+      else if ( (startPos + width) >= text.length() )
+      {
+         return -1;
+      }
+
+      //look for the last whitespace character before startPos+width
+      pos = startPos + width;
+      char c;
+      while ( pos >= startPos && (c = text.charAt(pos)) != ' ' && c != '\n' && c != '\r' )
+      {
+         --pos;
+      }
+      //if we found it - just return
+      if ( pos > startPos )
+      {
+         return pos;
+      }
+      else
+      {
+         //must look for the first whitespace chearacter after startPos + width
+         pos = startPos + width;
+         while ( pos <= text.length() && (c = text.charAt(pos)) != ' ' && c != '\n' && c != '\r' )
+         {
+            ++pos;
+         }
+         return pos == text.length() ? -1 : pos;
+      }
+   }
+
+   protected String createPadding(int len)
+   {
+      StringBuffer sb = new StringBuffer(len);
+      for ( int i = 0; i < len; ++i )
+      {
+         sb.append(' ');
+      }
+      return sb.toString();
+   }
+
+   protected String rtrim( String s )
+   {
+      if ( s == null || s.length() == 0 )
+      {
+         return s;
+      }
+
+      int pos = s.length();
+      while ( pos >= 0 && Character.isWhitespace(s.charAt(pos-1)) )
+      {
+         --pos;
+      }
+      return s.substring(0, pos);
+   }
+
+   // ------------------------------------------------------- Package protected
+   
+   // ----------------------------------------------------------------- Private
+   
+   // ----------------------------------------------------------- Inner classes
+
+    private static class StringBufferComparator
+    implements Comparator
+    {
+        public int compare( Object o1, Object o2 )
+        {
+            String str1 = stripPrefix(o1.toString());
+            String str2 = stripPrefix(o2.toString());
+            return (str1.compareTo(str2));
+        }
+
+        private String stripPrefix(String strOption)
+        {
+            // Strip any leading '-' characters
+            int iStartIndex = strOption.lastIndexOf('-');
+            if (iStartIndex == -1)
+            {
+              iStartIndex = 0;
+            }
+            return strOption.substring(iStartIndex);
+
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/cli/MissingArgumentException.java b/src/java/org/apache/commons/cli/MissingArgumentException.java
new file mode 100644
index 0000000..23b23bd
--- /dev/null
+++ b/src/java/org/apache/commons/cli/MissingArgumentException.java
@@ -0,0 +1,82 @@
+/*
+ * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli/MissingArgumentException.java,v 1.2 2002/06/06 09:37:26 jstrachan Exp $
+ * $Revision: 1.2 $
+ * $Date: 2002/06/06 09:37:26 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+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
+ */
+public class MissingArgumentException extends ParseException {
+    
+    /** 
+     * <p>Construct a new <code>MissingArgumentException</code> 
+     * with the specified detail message.</p>
+     *
+     * @param message the detail message
+     */
+    public MissingArgumentException( String message ) {
+        super( message );
+    }
+}
diff --git a/src/java/org/apache/commons/cli/MissingOptionException.java b/src/java/org/apache/commons/cli/MissingOptionException.java
new file mode 100644
index 0000000..7a8157b
--- /dev/null
+++ b/src/java/org/apache/commons/cli/MissingOptionException.java
@@ -0,0 +1,81 @@
+/*
+ * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli/MissingOptionException.java,v 1.2 2002/06/06 09:37:26 jstrachan Exp $
+ * $Revision: 1.2 $
+ * $Date: 2002/06/06 09:37:26 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+/** 
+ * <p>Thrown when a required option has not been provided.</p>
+ *
+ * @author John Keyes ( john at integralsource.com )
+ * @see ParseException
+ */
+public class MissingOptionException extends ParseException {
+    
+    /** 
+     * <p>Construct a new <code>MissingSelectedException</code> 
+     * with the specified detail message.</p>
+     *
+     * @param message the detail message
+     */
+    public MissingOptionException( String message ) {
+        super( message );
+    }
+}
diff --git a/src/java/org/apache/commons/cli/Option.java b/src/java/org/apache/commons/cli/Option.java
new file mode 100644
index 0000000..3868227
--- /dev/null
+++ b/src/java/org/apache/commons/cli/Option.java
@@ -0,0 +1,575 @@
+/*
+ * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli/Option.java,v 1.6 2002/06/06 22:50:14 bayard Exp $
+ * $Revision: 1.6 $
+ * $Date: 2002/06/06 22:50:14 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ * 
+ * $Id: Option.java,v 1.6 2002/06/06 22:50:14 bayard Exp $
+ */
+
+package org.apache.commons.cli;
+
+import java.util.ArrayList;
+
+/** <p>Describes a single command-line option.  It maintains
+ * information regarding the short-name of the option, the long-name,
+ * if any exists, a flag indicating if an argument is required for
+ * this option, and a self-documenting description of the option.</p>
+ *
+ * <p>An Option is not created independantly, but is create through
+ * an instance of {@link Options}.<p>
+ *
+ * @see org.apache.commons.cli.Options
+ * @see org.apache.commons.cli.CommandLine
+ *
+ * @author bob mcwhirter (bob @ werken.com)
+ * @author <a href="mailto:jstrachan at apache.org">James Strachan</a>
+ * @version $Revision: 1.6 $
+ */
+
+public class Option implements Cloneable {
+
+    /** constant that specifies the number of argument values has not been specified */
+    public final static int UNINITIALIZED = -1;
+    
+    /** constant that specifies the number of argument values is infinite */
+    public final static int UNLIMITED_VALUES = -2;
+    
+    /** opt the single character representation of the option */
+    private String opt;
+
+    /** longOpt is 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 */
+    private String argName;
+
+    /** description of the option */
+    private String description;
+
+    /** required 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 
+     */
+    private int numberOfArgs = UNINITIALIZED;   
+
+    /** the type of this Option */
+    private Object type;
+
+    /** the list of argument values **/
+    private ArrayList values = new ArrayList();
+    
+    /** option char (only valid for single character options) */
+    private char id;
+
+    /** the character that is the value separator */
+    private char valuesep;
+
+    /**
+     * <p>Validates whether <code>opt</code> is a permissable Option
+     * shortOpt.  The rules that specify if the <code>opt</code>
+     * is valid are:</p>
+     * <ul>
+     *  <li><code>opt</code> is not NULL</li>
+     *  <li>a single character <code>opt</code> that is either
+     *  ' '(special case), '?', '@' or a letter</li>
+     *  <li>a multi character <code>opt</code> that only contains
+     *  letters.</li>
+     * </ul>
+     *
+     * @param opt The option string to validate
+     * @throws IllegalArgumentException if the Option is not valid.
+     */
+    private void validateOption( String opt ) 
+    throws IllegalArgumentException
+    {
+        // check that opt is not NULL
+        if( opt == null ) {
+            throw new IllegalArgumentException( "opt is null" );
+        }
+        // handle the single character opt
+        else if( opt.length() == 1 ) {
+            char ch = opt.charAt( 0 );
+            if ( !isValidOpt( ch ) ) {
+                throw new IllegalArgumentException( "illegal option value '" 
+                                                    + ch + "'" );
+            }
+            id = ch;
+        }
+        // handle the multi character opt
+        else {
+            char[] chars = opt.toCharArray();
+            for( int i = 0; i < chars.length; i++ ) {
+                if( !isValidChar( chars[i] ) ) {
+                    throw new IllegalArgumentException( "opt contains illegal character value '" + chars[i] + "'" );
+                }
+            }
+        }
+    }
+
+    /**
+     * <p>Returns whether the specified character is a valid Option.</p>
+     *
+     * @param c the option to validate
+     * @return true if <code>c</code> is a letter, ' ', '?' or '@', otherwise false.
+     */
+    private boolean isValidOpt( char c ) {
+        return ( isValidChar( c ) || c == ' ' || c == '?' || c == '@' );
+    }
+
+    /**
+     * <p>Returns whether the specified character is a valid character.</p>
+     *
+     * @param c the character to validate
+     * @return true if <code>c</code> is a letter.
+     */
+    private boolean isValidChar( char c ) {
+        return Character.isJavaIdentifierPart( c );
+    }
+
+    /**
+     * <p>Returns the id of this Option.  This is only set when the
+     * Option shortOpt is a single character.  This is used for switch
+     * statements.</p>
+     *
+     * @return the id of this Option
+     */
+    public int getId( ) {
+        return id;
+    }
+
+    /**
+     * Creates an Option using the specified parameters.
+     *
+     * @param opt short representation of the option
+     * @param hasArg specifies whether the Option takes an argument or not
+     * @param description describes the function of the option
+     */
+    public Option( String opt, String description ) 
+    throws IllegalArgumentException
+    {
+        this( opt, null, false, description );
+    }
+
+    /**
+     * Creates an Option using the specified parameters.
+     *
+     * @param opt short representation of the option
+     * @param hasArg specifies whether the Option takes an argument or not
+     * @param description describes the function of the option
+     */
+    public Option( String opt, boolean hasArg, String description ) 
+    throws IllegalArgumentException
+    {
+        this( opt, null, hasArg, description );
+    }
+    
+    /**
+     * <p>Creates an Option using the specified parameters.</p>
+     *
+     * @param opt short representation of the option
+     * @param longOpt the long representation of the option
+     * @param hasArg specifies whether the Option takes an argument or not
+     * @param description describes the function of the option
+     */
+    public Option( String opt, String longOpt, boolean hasArg, String description ) 
+    throws IllegalArgumentException
+    {
+        // ensure that the option is valid
+        validateOption( opt );
+
+        this.opt          = opt;
+        this.longOpt      = longOpt;
+
+        // if hasArg is set then the number of arguments is 1
+        if( hasArg ) {
+            this.numberOfArgs = 1;
+        }
+
+        this.hasArg       = hasArg;
+        this.description  = description;
+    }
+    
+    /** <p>Retrieve the name of this Option.</p>
+     *
+     * <p>It is this String which can be used with
+     * {@link CommandLine#hasOption(String opt)} and
+     * {@link CommandLine#getOptionValue(String opt)} to check
+     * for existence and argument.<p>
+     *
+     * @return The name of this option
+     */
+    public String getOpt() {
+        return this.opt;
+    }
+
+    /**
+     * <p>Retrieve the type of this Option.</p>
+     * 
+     * @return The type of this option
+     */
+    public Object getType() {
+        return this.type;
+    }
+
+    /**
+     * <p>Sets the type of this Option.</p>
+     *
+     * @param type the type of this Option
+     */
+    public void setType( Object type ) {
+        this.type = type;
+    }
+    
+    /** 
+     * <p>Retrieve the long name of this Option.</p>
+     *
+     * @return Long name of this option, or null, if there is no long name
+     */
+    public String getLongOpt() {
+        return this.longOpt;
+    }
+
+    /**
+     * <p>Sets the long name of this Option.</p>
+     *
+     * @param longOpt the long name of this Option
+     */
+    public void setLongOpt( String longOpt ) {
+        this.longOpt = longOpt;
+    }
+
+    /**
+     * <p>Sets whether this Option can have an optional argument.</p>
+     *
+     * @param optionalArg specifies whether the Option can have
+     * an optional argument.
+     */
+    public void setOptionalArg( boolean optionalArg ) {
+        this.optionalArg = optionalArg;
+    }
+
+    /**
+     * @return whether this Option can have an optional argument
+     */
+    public boolean hasOptionalArg( ) {
+        return this.optionalArg;
+    }
+    
+    /** <p>Query to see if this Option has a long name</p>
+     *
+     * @return boolean flag indicating existence of a long name
+     */
+    public boolean hasLongOpt() {
+        return ( this.longOpt != null );
+    }
+    
+    /** <p>Query to see if this Option requires an argument</p>
+     *
+     * @return boolean flag indicating if an argument is required
+     */
+    public boolean hasArg() {
+        return this.numberOfArgs > 0 || numberOfArgs == UNLIMITED_VALUES;
+    }
+    
+    /** <p>Retrieve the self-documenting description of this Option</p>
+     *
+     * @return The string description of this option
+     */
+    public String getDescription() {
+        return this.description;
+    }
+
+     /** 
+      * <p>Query to see if this Option requires an argument</p>
+      *
+      * @return boolean flag indicating if an argument is required
+      */
+     public boolean isRequired() {
+         return this.required;
+     }
+
+     /**
+      * <p>Sets whether this Option is mandatory.</p>
+      *
+      * @param required specifies whether this Option is mandatory
+      */
+     public void setRequired( boolean required ) {
+         this.required = required;
+     }
+
+     /**
+      * <p>Sets the display name for the argument value.</p>
+      *
+      * @param argName the display name for the argument value.
+      */
+     public void setArgName( String argName ) {
+         this.argName = argName;
+     }
+
+     /**
+      * <p>Gets the display name for the argument value.</p>
+      *
+      * @return the display name for the argument value.
+      */
+     public String getArgName() {
+         return this.argName;
+     }
+
+     /**
+      * <p>Returns whether the display name for the argument value
+      * has been set.</p>
+      *
+      * @return if the display name for the argument value has been
+      * set.
+      */
+     public boolean hasArgName() {
+         return (this.argName != null && this.argName.length() > 0 );
+     }
+
+     /** 
+      * <p>Query to see if this Option can take many values</p>
+      *
+      * @return boolean flag indicating if multiple values are allowed
+      */
+     public boolean hasArgs() {
+         return ( this.numberOfArgs > 1 || this.numberOfArgs == UNLIMITED_VALUES );
+     }
+
+     /** 
+      * <p>Sets the number of argument values this Option can take.</p>
+      *
+      * @param num the number of argument values
+      */
+     public void setArgs( int num ) {
+         this.numberOfArgs = num;
+     }
+
+     /**
+      * <p>Sets the value separator.  For example if the argument value
+      * was a Java property, the value separator would be '='.</p>
+      *
+      * @param sep The value separator.
+      */
+     public void setValueSeparator( char sep ) {
+         this.valuesep = sep;
+     }
+
+     /**
+      * <p>Returns the value separator character.</p>
+      *
+      * @return the value separator character.
+      */
+     public char getValueSeparator() {
+         return this.valuesep;
+     }
+
+     /** 
+      * <p>Returns the number of argument values this Option can take.</p>
+      *
+      * @return num the number of argument values
+      */
+     public int getArgs( ) {
+         return this.numberOfArgs;
+     }
+
+    /** 
+     * <p>Dump state, suitable for debugging.</p>
+     *
+     * @return Stringified form of this object
+     */
+    public String toString() {
+        StringBuffer buf = new StringBuffer().append("[ option: ");
+        
+        buf.append( this.opt );
+        
+        if ( this.longOpt != null ) {
+            buf.append(" ")
+            .append(this.longOpt);
+        }
+        
+        buf.append(" ");
+        
+        if ( hasArg ) {
+            buf.append( "+ARG" );
+        }
+        
+        buf.append(" :: ")
+        .append( this.description );
+        
+        if ( this.type != null ) {
+            buf.append(" :: ")
+            .append( this.type );
+        }
+
+        buf.append(" ]");
+        return buf.toString();
+    }
+
+    /**
+     * <p>Adds the specified value to this Option.</p>
+     * 
+     * @param value is a/the value of this Option
+     */
+    public boolean addValue( String value ) {
+
+        switch( numberOfArgs ) {
+            case UNINITIALIZED:
+                return false;
+            case UNLIMITED_VALUES:
+                if( getValueSeparator() > 0 ) {
+                    int index = 0;
+                    while( (index = value.indexOf( getValueSeparator() ) ) != -1 ) {
+                        this.values.add( value.substring( 0, index ) );
+                        value = value.substring( index+1 );
+                    }
+                }
+                this.values.add( value );
+                return true;
+            default:
+                if( getValueSeparator() > 0 ) {
+                    int index = 0;
+                    while( (index = value.indexOf( getValueSeparator() ) ) != -1 ) {
+                        if( values.size() > numberOfArgs-1 ) {
+                            return false;
+                        }
+                        this.values.add( value.substring( 0, index ) );
+                        value = value.substring( index+1 );
+                    }
+                }
+                if( values.size() > numberOfArgs-1 ) {
+                    return false;
+                }
+                this.values.add( value );
+                return true;
+        }
+    }
+
+    /**
+     * @return the value/first value of this Option or 
+     * <code>null</code> if there are no values.
+     */
+    public String getValue() {
+        return this.values.size()==0 ? null : (String)this.values.get( 0 );
+    }
+
+    /**
+     * @return the specified value of this Option or 
+     * <code>null</code> if there are no values.
+     */
+    public String getValue( int index ) 
+    throws IndexOutOfBoundsException
+    {
+        return ( this.values.size()==0 ) ? null : (String)this.values.get( index );
+    }
+
+    /**
+     * @return the value/first value of this Option or the 
+     * <code>defaultValue</code> if there are no values.
+     */
+    public String getValue( String defaultValue ) {
+        String value = getValue( );
+        return ( value != null ) ? value : defaultValue;
+    }
+
+    /**
+     * @return the values of this Option as a String array 
+     * or null if there are no values
+     */
+    public String[] getValues() {
+        return this.values.size()==0 ? null : (String[])this.values.toArray(new String[]{});
+    }
+
+    /**
+     * @return the values of this Option as a List
+     * or null if there are no values
+     */
+    public java.util.List getValuesList() {
+        return this.values;
+    }
+
+    /**
+     * @return a copy of this Option
+     */
+    public Object clone() {
+        Option option = new Option( getOpt(), getDescription() );
+        option.setArgs( getArgs() );
+        option.setOptionalArg( hasOptionalArg() );
+        option.setRequired( isRequired() );
+        option.setLongOpt( getLongOpt() );
+        option.setType( getType() );
+        option.setValueSeparator( getValueSeparator() );
+        return option;
+    }
+}
diff --git a/src/java/org/apache/commons/cli/OptionBuilder.java b/src/java/org/apache/commons/cli/OptionBuilder.java
new file mode 100644
index 0000000..d5fa11c
--- /dev/null
+++ b/src/java/org/apache/commons/cli/OptionBuilder.java
@@ -0,0 +1,368 @@
+/*
+ * $Header: /home/cvspublic/jakarta-commons/cli/src/java/org/apache/commons/cli/OptionBuilder.java,v 1.12 2002/10/15 22:50:45 jkeyes Exp $
+ * $Revision: 1.12 $
+ * $Date: 2002/10/15 22:50:45 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+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 
+ * <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 )
+ * @since 1.0
+ */
+public class OptionBuilder {
+
+    /** long option */
+    private static String longopt;
+    /** option description */
+    private static String description;
+    /** argument name */
+    private static String argName;
+    /** is required? */
+    private static boolean required;
+    /** the number of arguments */
+    private static int numberOfArgs = Option.UNINITIALIZED;
+    /** option type */
+    private static Object type;
+    /** option can have an optional argument value */
+    private static boolean optionalArg;
+    /** value separator for argument value */
+    private static char valuesep;
+
+    /** option builder instance */
+    private static OptionBuilder instance = new OptionBuilder();
+
+    // private constructor
+    private OptionBuilder() {
+    }
+
+    /**
+     * <p>Resets the member variables to their default values.</p>
+     */
+    private static void reset() {
+        description = null;
+        argName = null;
+        longopt = null;
+        type = null;
+        required = false;
+        numberOfArgs = Option.UNINITIALIZED;
+
+        // PMM 9/6/02 - these were missing
+        optionalArg = false;
+        valuesep = (char) 0;
+    }
+
+    /**
+     * <p>The next Option created will have the following long option value.</p>
+     *
+     * @param longopt the long option value
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder withLongOpt( String longopt ) {
+        instance.longopt = longopt;
+        return instance;
+    }
+
+    /**
+     * <p>The next Option created will require an argument value.</p>
+     *
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder hasArg( ) {
+        instance.numberOfArgs = 1;
+        return instance;
+    }
+
+    /**
+     * <p>The next Option created will require an argument value if
+     * <code>hasArg</code> is true.</p>
+     *
+     * @param hasArg if true then the Option has an argument value
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder hasArg( boolean hasArg ) {
+        instance.numberOfArgs = ( hasArg == true ) ? 1 : Option.UNINITIALIZED;
+        return instance;
+    }
+
+    /**
+     * <p>The next Option created will have the specified argument value 
+     * name.</p>
+     *
+     * @param name the name for the argument value
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder withArgName( String name ) {
+        instance.argName = name;
+        return instance;
+    }
+
+    /**
+     * <p>The next Option created will be required.</p>
+     *
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder isRequired( ) {
+        instance.required = true;
+        return instance;
+    }
+
+    /**
+     * <p>The next Option created uses <code>sep</code> as a means to
+     * separate argument values.</p>
+     *
+     * <b>Example:</b>
+     * <pre>
+     * Option opt = OptionBuilder.withValueSeparator( ':' )
+     *                           .create( 'D' );
+     *
+     * CommandLine line = parser.parse( args );
+     * String propertyName = opt.getValue( 0 );
+     * String propertyValue = opt.getValue( 1 );
+     * </pre>
+     *
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder withValueSeparator( char sep ) {
+        instance.valuesep = sep;
+        return instance;
+    }
+
+    /**
+     * <p>The next Option created uses '<code>=</code>' as a means to
+     * separate argument values.</p>
+     *
+     * <b>Example:</b>
+     * <pre>
+     * Option opt = OptionBuilder.withValueSeparator( )
+     *                           .create( 'D' );
+     *
+     * CommandLine line = parser.parse( args );
+     * String propertyName = opt.getValue( 0 );
+     * String propertyValue = opt.getValue( 1 );
+     * </pre>
+     *
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder withValueSeparator( ) {
+        instance.valuesep = '=';
+        return instance;
+    }
+
+    /**
+     * <p>The next Option created will be required if <code>required</code>
+     * is true.</p>
+     *
+     * @param required if true then the Option is required
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder isRequired( boolean required ) {
+        instance.required = required;
+        return instance;
+    }
+
+    /**
+     * <p>The next Option created can have unlimited argument values.</p>
+     *
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder hasArgs( ) {
+        instance.numberOfArgs = Option.UNLIMITED_VALUES;
+        return instance;
+    }
+
+    /**
+     * <p>The next Option created can have <code>num</code> 
+     * argument values.</p>
+     *
+     * @param num the number of args that the option can have
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder hasArgs( int num ) {
+        instance.numberOfArgs = num;
+        return instance;
+    }
+
+    /**
+     * <p>The next Option can have an optional argument.</p>
+     *
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder hasOptionalArg( ) {
+        instance.numberOfArgs = 1;
+        instance.optionalArg = true;
+        return instance;
+    }
+
+    /**
+     * <p>The next Option can have an unlimited number of
+     * optional arguments.</p>
+     *
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder hasOptionalArgs( ) {
+        instance.numberOfArgs = Option.UNLIMITED_VALUES;
+        instance.optionalArg = true;
+        return instance;
+    }
+
+    /**
+     * <p>The next Option can have the specified number of 
+     * optional arguments.</p>
+     *
+     * @param numArgs - the maximum number of optional arguments
+     * the next Option created can have.
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder hasOptionalArgs( int numArgs ) {
+        instance.numberOfArgs = numArgs;
+        instance.optionalArg = true;
+        return instance;
+    }
+
+    /**
+     * <p>The next Option created will have a value that will be an instance 
+     * of <code>type</code>.</p>
+     *
+     * @param type the type of the Options argument value
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder withType( Object type ) {
+        instance.type = type;
+        return instance;
+    }
+
+    /**
+     * <p>The next Option created will have the specified description</p>
+     *
+     * @param description a description of the Option's purpose
+     * @return the OptionBuilder instance
+     */
+    public static OptionBuilder withDescription( String description ) {
+        instance.description = description;
+        return instance;
+    }
+
+    /**
+     * <p>Create an Option using the current settings and with 
+     * the specified Option <code>char</code>.</p>
+     *
+     * @param opt the character 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( char opt )
+    throws IllegalArgumentException
+    {
+        return create( String.valueOf( opt ) );
+    }
+
+    /**
+     * <p>Create an Option using the current settings</p>
+     *
+     * @return the Option instance
+     * @throws IllegalArgumentException if <code>longOpt</code> has
+     * not been set.  
+     */
+    public static Option create() 
+    throws IllegalArgumentException
+    {
+        if( longopt == null ) {
+            throw new IllegalArgumentException( "must specify longopt" );
+        }
+
+        return create( " " );
+    }
+
+    /**
+     * <p>Create an Option using the current settings and with 
+     * the specified Option <code>char</code>.</p>
+     *
+     * @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
+    {
+        // 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
+        instance.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
new file mode 100644
index 0000000..afa2f8c
--- /dev/null
+++ b/src/java/org/apache/commons/cli/OptionGroup.java
@@ -0,0 +1,184 @@
+/*
+ * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli/OptionGroup.java,v 1.2 2002/06/06 09:37:26 jstrachan Exp $
+ * $Revision: 1.2 $
+ * $Date: 2002/06/06 09:37:26 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * A group of mutually exclusive options.
+ * @author John Keyes ( john at integralsource.com )
+ * @version $Revision: 1.2 $
+ */
+public class OptionGroup {
+
+    /** hold the options */
+    private HashMap optionMap = new HashMap();
+
+    /** the name of the selected option */
+    private String selected;
+
+    /** specified whether this group is required */
+    private boolean required;
+
+    /**
+     * add <code>opt</code> to this group
+     *
+     * @param opt the option to add to this group
+     * @return this option group with opt added
+     */
+    public OptionGroup addOption(Option opt) {
+        // key   - option name
+        // value - the option
+        optionMap.put( "-" + opt.getOpt(), opt );
+        return this;
+    }
+
+    /**
+     * @return the names of the options in this group as a 
+     * <code>Collection</code>
+     */
+    public Collection getNames() {
+        // the key set is the collection of names
+        return optionMap.keySet();
+    }
+
+    /**
+     * @return the options in this group as a <code>Collection</code>
+     */
+    public Collection getOptions() {
+        // the values are the collection of options
+        return optionMap.values();
+    }
+
+    /**
+     * set the selected option of this group to <code>name</code>.
+     * @param opt the option that is selected
+     * @throws AlreadySelectedException if an option from this group has 
+     * already been selected.
+     */
+    public void setSelected(Option opt) 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() ) ) {
+            this.selected = opt.getOpt();
+        }
+        else {
+            throw new AlreadySelectedException( "an option from this group has " + 
+                                                "already been selected: '" + 
+                                                selected + "'");
+        }
+    }
+
+    /**
+     * @return the selected option name
+     */
+    public String getSelected() {
+        return selected;
+    }
+
+    /**
+     * @param required specifies if this group is required
+     */
+    public void setRequired( boolean required ) {
+        this.required = required;
+    }
+
+    /**
+     * Returns whether this option group is required.
+     *
+     * @returns whether this option group is required
+     */
+    public boolean isRequired() {
+        return this.required;
+    }
+
+    /**
+     * <p>Returns the stringified version of this OptionGroup.</p>
+     * @return the stringified representation of this group
+     */
+    public String toString() {
+        StringBuffer buff = new StringBuffer();
+
+        Iterator iter = getOptions().iterator();
+
+        buff.append( "[" );
+        while( iter.hasNext() ) {
+            Option option = (Option)iter.next();
+
+            buff.append( "-" );
+            buff.append( option.getOpt() );
+            buff.append( " " );
+            buff.append( option.getDescription( ) );
+
+            if( iter.hasNext() ) {
+                buff.append( ", " );
+            }
+        }
+        buff.append( "]" );
+
+        return buff.toString();
+    }
+}
diff --git a/src/java/org/apache/commons/cli/Options.java b/src/java/org/apache/commons/cli/Options.java
new file mode 100644
index 0000000..11cf3a8
--- /dev/null
+++ b/src/java/org/apache/commons/cli/Options.java
@@ -0,0 +1,299 @@
+/*
+ * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli/Options.java,v 1.5 2002/06/06 22:32:37 bayard Exp $
+ * $Revision: 1.5 $
+ * $Date: 2002/06/06 22:32:37 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.*;
+
+/** <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>
+ *
+ * <p>It may flexibly parse long and short options, with or without
+ * values.  Additionally, it may parse only a portion of a commandline,
+ * allowing for flexible multi-stage parsing.<p>
+ *
+ * @see org.apache.commons.cli.CommandLine
+ *
+ * @author bob mcwhirter (bob @ werken.com)
+ * @author <a href="mailto:jstrachan at apache.org">James Strachan</a>
+ * @version $Revision: 1.5 $
+ */
+public class Options {
+
+    /** a map of the options with the character key */
+    private Map  shortOpts    = new HashMap();
+
+    /** a map of the options with the long key */
+    private Map  longOpts     = new HashMap();
+
+    /** a map of the required options */
+    private List requiredOpts = new ArrayList();
+    
+    /** a map of the option groups */
+    private Map optionGroups  = new HashMap();
+
+    /** <p>Construct a new Options descriptor</p>
+     */
+    public Options() {        
+    }
+
+    /**
+     * <p>Add the specified option group.</p>
+     *
+     * @param group the OptionGroup that is to be added
+     * @return the resulting Options instance
+     */
+    public Options addOptionGroup( OptionGroup group ) {
+        Iterator options = group.getOptions().iterator();
+
+        if( group.isRequired() ) {
+            requiredOpts.add( group );
+        }
+
+        while( options.hasNext() ) {
+            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
+            option.setRequired( false );
+            addOption( option );
+
+            optionGroups.put( option.getOpt(), group );
+        }
+
+        return this;
+    }
+
+    /** <p>Add an option that only contains a short-name</p>
+     * <p>It may be specified as requiring an argument.</p>
+     *
+     * @param opt Short single-character name of the option.
+     * @param hasArg flag signally if an argument is required after this option
+     * @param description Self-documenting description
+     * @return the resulting Options instance
+     */
+    public Options addOption(String opt, boolean hasArg, String description) {
+        addOption( opt, null, hasArg, description );
+        return this;
+    }
+    
+    /** <p>Add an option that contains a short-name and a long-name</p>
+     * <p>It may be specified as requiring an argument.</p>
+     *
+     * @param opt Short single-character name of the option.
+     * @param longOpt Long multi-character name of the option.
+     * @param hasArg flag signally if an argument is required after this option
+     * @param description Self-documenting description
+     * @return the resulting Options instance
+     */
+    public Options addOption(String opt, String longOpt, boolean hasArg, String description) {
+        addOption( new Option( opt, longOpt, hasArg, description ) );        
+        return this;
+    }
+
+    /**
+     * <p>Adds an option instance</p>
+     *
+     * @param opt the option that is to be added 
+     * @return the resulting Options instance
+     */
+    public Options addOption(Option opt)  {
+        String shortOpt = "-" + opt.getOpt();
+        
+        // add it to the long option list
+        if ( opt.hasLongOpt() ) {
+            longOpts.put( "--" + opt.getLongOpt(), opt );
+        }
+        
+        // if the option is required add it to the required list
+        if ( opt.isRequired() ) {
+            requiredOpts.add( shortOpt );
+        }
+
+        shortOpts.put( shortOpt, opt );
+        
+        return this;
+    }
+    
+    /** <p>Retrieve a read-only list of options in this set</p>
+     *
+     * @return read-only Collection of {@link Option} objects in this descriptor
+     */
+    public Collection getOptions() {
+        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 Collections.unmodifiableCollection( opts );
+    }
+
+    /**
+     * <p>Returns the Options for use by the HelpFormatter.</p>
+     *
+     * @return the List of Options
+     */
+    List helpOptions() {
+        return new ArrayList( shortOpts.values() );
+    }
+
+    /** <p>Returns the required options as a 
+     * <code>java.util.Collection</code>.</p>
+     *
+     * @return Collection of required options
+     */
+    public List getRequiredOptions() {
+        return requiredOpts;
+    }
+    
+    /** <p>Retrieve the named {@link Option}</p>
+     *
+     * @param opt short or long name of the {@link Option}
+     * @return the option represented by opt
+     */
+    public Option getOption( String opt ) {
+
+        Option option = null;
+
+        // short option
+        if( opt.length() == 1 ) {
+            option = (Option)shortOpts.get( "-" + opt );
+        }
+        // long option
+        else if( opt.startsWith( "--" ) ) {
+            option = (Option)longOpts.get( opt );
+        }
+        // a just-in-case
+        else {
+            option = (Option)shortOpts.get( opt );
+        }
+
+        return (option == null) ? null : (Option)option.clone();
+    }
+
+    /** 
+     * <p>Returns whether the named {@link Option} is a member
+     * of this {@link Options}</p>
+     *
+     * @param opt short or long name of the {@link Option}
+     * @return true if the named {@link Option} is a member
+     * of this {@link Options}
+     */
+    public boolean hasOption( String opt ) {
+
+        // short option
+        if( opt.length() == 1 ) {
+            return shortOpts.containsKey( "-" + opt );
+        }
+        // long option
+        else if( opt.startsWith( "--" ) ) {
+            return longOpts.containsKey( opt );
+        }
+        // a just-in-case
+        else {
+            return shortOpts.containsKey( opt );
+        }
+    }
+
+    /** <p>Returns the OptionGroup the <code>opt</code>
+     * belongs to.</p>
+     * @param opt the option whose OptionGroup is being queried.
+     *
+     * @return the OptionGroup if <code>opt</code> is part
+     * of an OptionGroup, otherwise return null
+     */
+    public OptionGroup getOptionGroup( Option opt ) {
+        return (OptionGroup)optionGroups.get( opt.getOpt() );
+    }
+    
+    /** <p>Dump state, suitable for debugging.</p>
+     *
+     * @return Stringified form of this object
+     */
+    public String toString() {
+        StringBuffer buf = new StringBuffer();
+        
+        buf.append("[ Options: [ short ");
+        buf.append( shortOpts.toString() );
+        buf.append( " ] [ long " );
+        buf.append( longOpts );
+        buf.append( " ]");
+        
+        return buf.toString();
+    }
+}
diff --git a/src/java/org/apache/commons/cli/ParseException.java b/src/java/org/apache/commons/cli/ParseException.java
new file mode 100644
index 0000000..dd14a23
--- /dev/null
+++ b/src/java/org/apache/commons/cli/ParseException.java
@@ -0,0 +1,82 @@
+/*
+ * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli/ParseException.java,v 1.2 2002/06/06 09:37:26 jstrachan Exp $
+ * $Revision: 1.2 $
+ * $Date: 2002/06/06 09:37:26 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+/** 
+ * <p>Base for Exceptions thrown during parsing of a command-line.</p>
+ *
+ * @author bob mcwhirter (bob @ werken.com)
+ * @version $Revision: 1.2 $
+ */
+public class ParseException extends Exception 
+{
+    
+    /** 
+     * <p>Construct a new <code>ParseException</code> 
+     * with the specified detail message.</p>
+     *
+     * @param message the detail message
+     */
+    public ParseException( String message ) {
+        super( message );
+    }
+}
diff --git a/src/java/org/apache/commons/cli/Parser.java b/src/java/org/apache/commons/cli/Parser.java
new file mode 100644
index 0000000..b740d13
--- /dev/null
+++ b/src/java/org/apache/commons/cli/Parser.java
@@ -0,0 +1,283 @@
+/*
+ * $Header: /home/cvspublic/jakarta-commons/cli/src/java/org/apache/commons/cli/Parser.java,v 1.7 2002/10/24 23:17:49 jkeyes Exp $
+ * $Revision: 1.7 $
+ * $Date: 2002/10/24 23:17:49 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+/**
+ * <p><code>Parser</code> creates {@link CommandLine}s.</p>
+ *
+ * @author John Keyes (john at integralsource.com)
+ * @see Parser
+ * @version $Revision: 1.7 $
+ */
+public abstract class Parser implements CommandLineParser {
+
+    /** commandline instance */
+    private CommandLine cmd;
+    /** current Options */
+    private Options options;
+    /** list of required options strings */
+    private List requiredOptions;
+
+    /**
+     * <p>Subclasses must implement this method to reduce
+     * the <code>arguments</code> that have been passed to the parse 
+     * method.</p>
+     *
+     * @param opts The Options to parse the arguments by.
+     * @param args 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
+     */
+    abstract protected String[] flatten( Options opts, 
+                                         String[] arguments, 
+                                         boolean stopAtNonOption );
+
+    /**
+     * <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>
+     * @return the <code>CommandLine</code>
+     * @throws ParseException if an error occurs when parsing the
+     * arguments.
+     */
+    public CommandLine parse( Options options, String[] arguments ) 
+    throws ParseException 
+    {
+        return parse( options, arguments, 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.
+     * @return the <code>CommandLine</code>
+     * @throws ParseException if an error occurs when parsing the
+     * arguments.
+     */
+    public CommandLine parse( Options opts, 
+                              String[] arguments, 
+                              boolean stopAtNonOption ) 
+    throws ParseException 
+    {
+        // initialise members
+        options = opts;
+        requiredOptions = options.getRequiredOptions();
+        cmd = new CommandLine();
+
+        boolean eatTheRest = false;
+
+        List tokenList = Arrays.asList( flatten( opts, arguments, stopAtNonOption ) );
+        ListIterator iterator = tokenList.listIterator();
+
+        // process each flattened token
+        while( iterator.hasNext() ) {
+            String t = (String)iterator.next();
+
+            // the value is the double-dash
+            if( "--".equals( t ) ) {
+                eatTheRest = true;
+            }
+            // the value is a single dash
+            else if( "-".equals( t ) ) {
+                if( stopAtNonOption ) {
+                    eatTheRest = true;
+                }
+                else {
+                    cmd.addArg(t );
+                }
+            }
+            // the value is an option
+            else if( t.startsWith( "-" ) ) {
+                if ( stopAtNonOption && !options.hasOption( t ) ) {
+                    eatTheRest = true;
+                    cmd.addArg( t );
+                }
+                else {
+                    processOption( t, iterator );
+                }
+            }
+            // the value is an argument
+            else {
+                cmd.addArg( t );
+                if( stopAtNonOption ) {
+                    eatTheRest = true;
+                }
+            }
+
+            // eat the remaining tokens
+            if( eatTheRest ) {
+                while( iterator.hasNext() ) {
+                    String str = (String)iterator.next();
+                    // ensure only one double-dash is added
+                    if( !"--".equals( str ) ) {
+                        cmd.addArg( str );
+                    }
+                }
+            }
+        }
+        checkRequiredOptions();
+        return cmd;
+    }
+
+    /**
+     * <p>Throws a {@link MissingOptionException} if all of the
+     * required options are no present.</p>
+     */
+    private void checkRequiredOptions()
+    throws MissingOptionException 
+    {
+
+        // if there are required options that have not been
+        // processsed
+        if( requiredOptions.size() > 0 ) {
+            Iterator iter = requiredOptions.iterator();
+            StringBuffer buff = new StringBuffer();
+
+            // loop through the required options
+            while( iter.hasNext() ) {
+                buff.append( iter.next() );
+            }
+
+            throw new MissingOptionException( buff.toString() );
+        }
+    }
+
+    public void processArgs( Option opt, ListIterator iter ) 
+    throws ParseException
+    {
+        // loop until an option is found
+        while( iter.hasNext() ) {
+            String var = (String)iter.next();
+
+            // found an Option
+            if( options.hasOption( var ) ) {
+                iter.previous();
+                break;
+            }
+            // found a value
+            else if( !opt.addValue( var ) ) {
+                iter.previous();
+                break;
+            }
+        }
+
+        if( opt.getValues() == null && !opt.hasOptionalArg() ) {
+            throw new MissingArgumentException( "no argument for:" + opt.getOpt() );
+        }
+    }
+
+    private void processOption( String arg, ListIterator iter ) 
+    throws ParseException
+    {
+        // get the option represented by arg
+        Option opt = null;
+
+        boolean hasOption = options.hasOption( arg );
+
+        // if there is no option throw an UnrecognisedOptionException
+        if( !hasOption ) {
+            throw new UnrecognizedOptionException("Unrecognized option: " + arg);
+        }
+        else {
+            opt = (Option) options.getOption( arg );
+        }
+
+        // if the option is a required option remove the option from
+        // the requiredOptions list
+        if ( opt.isRequired() ) {
+            requiredOptions.remove( "-" + opt.getOpt() );
+        }
+
+        // if the option is in an OptionGroup make that option the selected
+        // option of the group
+        if ( options.getOptionGroup( opt ) != null ) {
+            OptionGroup group = ( OptionGroup ) options.getOptionGroup( opt );
+            if( group.isRequired() ) {
+                requiredOptions.remove( group );
+            }
+            group.setSelected( opt );
+        }
+
+        // if the option takes an argument value
+        if ( opt.hasArg() ) {
+            processArgs( opt, iter );
+        }
+
+        // set the option on the command line
+        cmd.addOption( opt );
+    }
+}
\ No newline at end of file
diff --git a/src/java/org/apache/commons/cli/PatternOptionBuilder.java b/src/java/org/apache/commons/cli/PatternOptionBuilder.java
new file mode 100644
index 0000000..d544e69
--- /dev/null
+++ b/src/java/org/apache/commons/cli/PatternOptionBuilder.java
@@ -0,0 +1,204 @@
+/*
+ * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli/PatternOptionBuilder.java,v 1.2 2002/06/06 22:49:36 bayard Exp $
+ * $Revision: 1.2 $
+ * $Date: 2002/06/06 22:49:36 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+/** 
+ * Allows Options to be created from a single String.
+ *
+ *
+ * @author Henri Yandell (bayard @ generationjava.com)
+ * @version $Revision: 1.2 $
+ */
+public class PatternOptionBuilder {
+
+    /// TODO: These need to break out to OptionType and also to be pluggable.
+
+    /** String class */
+    public static final Class STRING_VALUE        = java.lang.String.class;
+    /** Object class */
+    public static final Class OBJECT_VALUE        = java.lang.Object.class;
+    /** Number class */
+    public static final Class NUMBER_VALUE        = java.lang.Number.class;
+    /** Date class */
+    public static final Class DATE_VALUE          = java.util.Date.class;
+    /** Class class */
+    public static final Class CLASS_VALUE         = java.lang.Class.class;
+
+/// 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;
+    /** File class */
+    public static final Class FILE_VALUE          = java.io.File.class;
+    /** File array class */
+    public static final Class FILES_VALUE         = java.io.File[].class;
+    /** URL class */
+    public static final Class URL_VALUE           = java.net.URL.class;
+
+    /**
+     * <p>Retrieve the class that <code>ch</code> represents.</p>
+     *
+     * @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 == '<') {
+            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;
+        }
+        return null;
+    }
+ 
+    /**
+     * <p>Returns whether <code>ch</code> is a value code, i.e.
+     * whether it represents a class in a pattern.</p>
+     * 
+     * @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 != '/')
+          )
+        {
+            return false;
+        }
+        return true;
+    }       
+ 
+    /**
+     * <p>Returns the {@link Options} instance represented by 
+     * <code>pattern</code>.</p>
+     *
+     * @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++) {
+            ch = pattern.charAt(i);
+
+            // a value code comes after an option and specifies 
+            // details about it
+            if(!isValueCode(ch)) {
+                if(opt != ' ') {
+                    // we have a previous one to deal with
+                    options.addOption( OptionBuilder.hasArg( type != null )
+                                                    .isRequired( required )
+                                                    .withType( type )
+                                                    .create( opt ) );
+                    required = false;
+                    type = null;
+                    opt = ' ';
+                }
+                opt = ch;
+            } else
+            if(ch == '!') {
+                required = true;
+            } else {
+                type = getValueClass(ch);
+            }
+        }
+
+        if(opt != ' ') {
+            // we have a final one to deal with
+            options.addOption( OptionBuilder.hasArg( type != null )
+                                            .isRequired( required )
+                                            .withType( type )
+                                            .create( opt ) );
+        }
+
+        return options;
+    }
+
+}
diff --git a/src/java/org/apache/commons/cli/PosixParser.java b/src/java/org/apache/commons/cli/PosixParser.java
new file mode 100644
index 0000000..3169df6
--- /dev/null
+++ b/src/java/org/apache/commons/cli/PosixParser.java
@@ -0,0 +1,314 @@
+/*
+ * $Header: /home/cvspublic/jakarta-commons/cli/src/java/org/apache/commons/cli/PosixParser.java,v 1.11 2002/09/19 22:59:43 jkeyes Exp $
+ * $Revision: 1.11 $
+ * $Date: 2002/09/19 22:59:43 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.commons.cli;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * 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: 1.11 $
+ */
+public class PosixParser extends Parser {
+
+    /** holder for flattened tokens */
+    private ArrayList tokens = new ArrayList();
+    /** specifies if bursting should continue */
+    private boolean eatTheRest;
+    /** holder for the current option */
+    private Option currentOption;
+    /** the command line Options */
+    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>
+     */
+    private void init() {
+        eatTheRest = false;
+        tokens.clear();
+        currentOption = null;
+    }
+
+    /**
+     * <p>An implementation of {@link Parser}'s abstract
+     * {@link Parser#flatten(Options,String[],boolean) flatten} method.</p>
+     *
+     * <p>The following are the rules used by this flatten method.
+     * <ol>
+     *  <li>if <code>stopAtNonOption</code> is <b>true</b> then do not
+     *  burst anymore of <code>arguments</code> entries, just add each
+     *  successive entry without further processing.  Otherwise, ignore
+     *  <code>stopAtNonOption</code>.</li>
+     *  <li>if the current <code>arguments</code> entry is "<b>--</b>"
+     *  just add the entry to the list of processed tokens</li>
+     *  <li>if the current <code>arguments</code> entry is "<b>-</b>"
+     *  just add the entry to the list of processed tokens</li>
+     *  <li>if the current <code>arguments</code> entry is two characters
+     *  in length and the first character is "<b>-</b>" then check if this
+     *  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 
+     *  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 
+     *  {@link PosixParser#burstToken( String, boolean) burstToken}.</li>
+     *  <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>
+     * </p>
+     *
+     * @param options The command line {@link Options}
+     * @param arguments The command line arguments to be parsed
+     * @param stopAtNonOption Specifies whether to stop flattening
+     * when an non option is found.
+     * @return The flattened <code>arguments</code> String array.
+     */
+    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 = null;
+        
+        // process each command line token
+        while ( iter.hasNext() ) {
+
+            // get the next command line token
+            token = (String) iter.next();
+
+            // handle SPECIAL TOKEN
+            if( token.startsWith( "--" ) ) {
+                if( token.indexOf( '=' ) != -1 ) {
+                    tokens.add( token.substring( 0, token.indexOf( '=' ) ) );
+                    tokens.add( token.substring( token.indexOf( '=' ) + 1,
+                                                 token.length() ) );
+                }
+                else {
+                    tokens.add( token );
+                }	
+            }
+            // single hyphen
+            else if( "-".equals( token ) ) {
+                processSingleHyphen( token );
+            }
+            else if( token.startsWith( "-" ) ) {
+                int tokenLength = token.length();
+                if( tokenLength == 2 ) {
+                    processOptionToken( token, stopAtNonOption );
+                }
+                // requires bursting
+                else {
+                    burstToken( token, stopAtNonOption );
+                }
+            }
+            else {
+                if( stopAtNonOption ) {
+                    process( token );
+                }
+                else {
+                    tokens.add( token );
+                }
+            }
+
+            gobble( iter );
+        }
+
+        return (String[])tokens.toArray( new String[] {} );
+    }
+
+    /**
+     * <p>Adds the remaining tokens to the processed tokens list.</p>
+     *
+     * @param iter An iterator over the remaining tokens
+     */
+    private void gobble( Iterator iter ) {
+        if( eatTheRest ) {
+            while( iter.hasNext() ) {
+                tokens.add( iter.next() );
+            }
+        }
+    }
+
+    /**
+     * <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>
+     *
+     * @param value The current token
+     */
+    private void process( String value ) {
+        if( currentOption != null && currentOption.hasArg() ) {
+            if( currentOption.hasArg() ) {
+                tokens.add( value );
+                currentOption = null;
+            }
+            else if (currentOption.hasArgs() ) {
+                tokens.add( value );
+            }
+        }
+        else {
+            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 );
+    }
+
+    /**
+     * <p>If an {@link Option} exists for <code>token</code> then
+     * set the current option and 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>
+     *
+     * @param token The current option token
+     * @param stopAtNonOption Specifies whether flattening should halt
+     * at the first non option.
+     */
+    private void processOptionToken( String token, boolean stopAtNonOption ) {
+        if( this.options.hasOption( token ) ) {
+            currentOption = this.options.getOption( token );
+            tokens.add( token );
+        }
+        else if( stopAtNonOption ) {
+            eatTheRest = true;
+        }
+    }
+
+    /**
+     * <p>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 
+     *  characters as a token to the list of processed tokens.</li>
+     *  <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 
+     *  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>
+     */
+    protected void burstToken( String token, boolean stopAtNonOption ) {
+        int tokenLength = token.length();
+
+        for( int i = 1; i < tokenLength; i++) {
+            String ch = String.valueOf( token.charAt( i ) );
+            boolean hasOption = options.hasOption( ch );
+
+            if( hasOption ) {
+                tokens.add( "-" + ch );
+                currentOption = options.getOption( ch );
+                if( currentOption.hasArg() && token.length()!=i+1 ) {
+                    tokens.add( token.substring( i+1 ) );
+                    break;
+                }
+            }
+            else if( stopAtNonOption ) {
+                process( token.substring( i ) );
+            }
+            else {
+                tokens.add( "-" + ch );
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/java/org/apache/commons/cli/TypeHandler.java b/src/java/org/apache/commons/cli/TypeHandler.java
new file mode 100644
index 0000000..e0ea277
--- /dev/null
+++ b/src/java/org/apache/commons/cli/TypeHandler.java
@@ -0,0 +1,253 @@
+/*
+ * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli/TypeHandler.java,v 1.2 2002/06/06 22:49:36 bayard Exp $
+ * $Revision: 1.2 $
+ * $Date: 2002/06/06 22:49:36 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+import java.io.File;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Date;
+
+import org.apache.commons.lang.NumberUtils;
+
+/**
+  * 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.
+  *
+  * @author Henri Yandell (bayard @ generationjava.com)
+  * @version $Revision: 1.2 $
+  */    
+public class TypeHandler {
+
+    /**
+     * <p>Returns the <code>Object</code> of type <code>obj</code>
+     * with the value of <code>str</code>.</p>
+     *
+     * @param str the command line value
+     * @param obj the type of argument
+     * @return The instance of <code>obj</code> initialised with
+     * the value of <code>str</code>.
+     */
+    public static Object createValue(String str, Object obj) {
+        return createValue(str, (Class)obj);
+    }
+
+    /**
+     * <p>Returns the <code>Object</code> of type <code>clazz</code>
+     * with the value of <code>str</code>.</p>
+     *
+     * @param str the command line value
+     * @param clazz the type of argument
+     * @return The instance of <code>clazz</code> initialised with
+     * the value of <code>str</code>.
+     */
+    public static Object createValue(String str, Class clazz) {
+        if( PatternOptionBuilder.STRING_VALUE == clazz) {
+            return str;
+        } else
+        if( PatternOptionBuilder.OBJECT_VALUE == clazz) {
+            return createObject(str);
+        } else
+        if( PatternOptionBuilder.NUMBER_VALUE == clazz) {
+            return createNumber(str);
+        } else
+        if( PatternOptionBuilder.DATE_VALUE   == clazz) {
+            return createDate(str);
+        } else
+        if( PatternOptionBuilder.CLASS_VALUE  == clazz) {
+            return createClass(str);
+        } else
+        if( PatternOptionBuilder.FILE_VALUE   == clazz) {
+            return createFile(str);
+        } else
+        if( PatternOptionBuilder.EXISTING_FILE_VALUE   == clazz) {
+            return createFile(str);
+        } else
+        if( PatternOptionBuilder.FILES_VALUE  == clazz) {
+            return createFiles(str);
+        } else
+        if( PatternOptionBuilder.URL_VALUE    == clazz) {
+            return createURL(str);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+      * <p>Create an Object from the classname and empty constructor.</p>
+      *
+      * @param str the argument value
+      * @return the initialised object, or null if it couldn't create the Object.
+      */
+    public static Object createObject(String str) {
+        Class cl = null;
+        try {
+            cl = Class.forName(str);
+        } catch (ClassNotFoundException cnfe) {
+            System.err.println("Unable to find: "+str);
+            return null;
+        }
+
+        Object instance = null;
+
+        try {
+            instance = cl.newInstance();
+        } catch (InstantiationException cnfe) {
+            System.err.println("InstantiationException; Unable to create: "+str);
+            return null;
+        }
+        catch (IllegalAccessException cnfe) {
+            System.err.println("IllegalAccessException; Unable to create: "+str);
+            return null;
+        }
+
+        return instance;
+    }
+
+    /**
+     * <p>Create a number from a String.</p>
+     *
+     * @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) {
+        // Needs to be able to create
+        try {
+            // do searching for decimal point etc, but atm just make an Integer
+            return NumberUtils.createNumber(str);
+        } catch (NumberFormatException nfe) {
+            System.err.println(nfe.getMessage());
+            return null;
+        }
+    }
+
+    /**
+     * <p>Returns the class whose name is <code>str</code>.</p>
+     *
+     * @param str the class name
+     * @return The class if it is found, otherwise return null
+     */
+    public static Class createClass(String str) {
+        try {
+            return Class.forName(str);
+        } catch (ClassNotFoundException cnfe) {
+            System.err.println("Unable to find: "+str);
+            return null;
+        }
+    }
+
+    /**
+     * <p>Returns the date represented by <code>str</code>.</p>
+     *
+     * @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) {
+        Date date = null;
+        if(date == null) {
+            System.err.println("Unable to parse: "+str);
+        }
+        return date;
+    }
+
+    /**
+     * <p>Returns the URL represented by <code>str</code>.</p>
+     *
+     * @param str the URL string
+     * @return The URL is <code>str</code> is well-formed, otherwise
+     * return null.
+     */
+    public static URL createURL(String str) {
+        try {
+            return new URL(str);
+        } catch (MalformedURLException mue) {
+            System.err.println("Unable to parse: "+str);
+            return null;
+        }
+    }
+
+    /**
+     * <p>Returns the File represented by <code>str</code>.</p>
+     *
+     * @param str the File location
+     * @return The file represented by <code>str</code>.
+     */
+    public static File createFile(String str) {
+        return new File(str);
+    }
+
+    /**
+     * <p>Returns the File[] represented by <code>str</code>.</p>
+     *
+     * @param str the paths to the files
+     * @return The File[] represented by <code>str</code>.
+     */
+    public static File[] createFiles(String str) {
+// to implement/port:
+//        return FileW.findFiles(str);
+        return null;
+    }
+
+}
diff --git a/src/java/org/apache/commons/cli/UnrecognizedOptionException.java b/src/java/org/apache/commons/cli/UnrecognizedOptionException.java
new file mode 100644
index 0000000..553efc3
--- /dev/null
+++ b/src/java/org/apache/commons/cli/UnrecognizedOptionException.java
@@ -0,0 +1,82 @@
+/*
+ * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli/UnrecognizedOptionException.java,v 1.2 2002/06/06 09:37:26 jstrachan Exp $
+ * $Revision: 1.2 $
+ * $Date: 2002/06/06 09:37:26 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.cli;
+
+/** 
+ * <p>Exception thrown during parsing signalling an unrecognized
+ * option was seen.<p>
+ *
+ * @author bob mcwhiter (bob @ werken.com)
+ * @version $Revision: 1.2 $
+ */
+public class UnrecognizedOptionException extends ParseException {
+    
+    /** 
+     * <p>Construct a new <code>UnrecognizedArgumentException</code> 
+     * with the specified detail message.</p>
+     *
+     * @param message the detail message
+     */
+    public UnrecognizedOptionException( String message ) {
+        super( message );
+    }
+}
diff --git a/src/java/org/apache/commons/cli/overview.html b/src/java/org/apache/commons/cli/overview.html
new file mode 100644
index 0000000..eadba1e
--- /dev/null
+++ b/src/java/org/apache/commons/cli/overview.html
@@ -0,0 +1,28 @@
+
+<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>
+</body>
diff --git a/src/java/org/apache/commons/cli/package.html b/src/java/org/apache/commons/cli/package.html
new file mode 100644
index 0000000..5dcaef1
--- /dev/null
+++ b/src/java/org/apache/commons/cli/package.html
@@ -0,0 +1,6 @@
+
+<body>
+
+    <p>Commons CLI 1.0</p>
+
+</body>
diff --git a/src/test/org/apache/commons/cli/ApplicationTest.java b/src/test/org/apache/commons/cli/ApplicationTest.java
new file mode 100644
index 0000000..87a43f3
--- /dev/null
+++ b/src/test/org/apache/commons/cli/ApplicationTest.java
@@ -0,0 +1,115 @@
+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.
+ * </p>
+ * 
+ * <p>
+ * The following are the applications that are tested:
+ * <ul>
+ * <li>Ant</li>
+ * </ul>
+ * </p>
+ *
+ * @author John Keyes (john at integralsource.com)
+ */
+public class ApplicationTest extends TestCase {
+
+    public static Test suite() { 
+        return new TestSuite(ApplicationTest.class); 
+    }
+
+    public ApplicationTest(String name)
+    {
+        super(name);
+    }
+    
+    /**
+     *	
+     */
+    public void testLs() {
+        // create the command line parser
+        CommandLineParser parser = new PosixParser();
+        Options options = new Options();
+        options.addOption( "a", "all", false, "do not hide entries starting with ." );
+        options.addOption( "A", "almost-all", false, "do not list implied . and .." );
+        options.addOption( "b", "escape", false, "print octal escapes for nongraphic characters" );
+        options.addOption( OptionBuilder.withLongOpt( "block-size" )
+                                        .withDescription( "use SIZE-byte blocks" )
+                                        .withValueSeparator( '=' )
+                                        .hasArg()
+                                        .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" );
+        options.addOption( "C", false, "list entries by columns" );
+
+        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() );
+        }
+    }
+
+    /**
+     * Ant test
+     */
+    public void testAnt() {
+        // use the GNU parser
+        CommandLineParser parser = new GnuParser( );
+        Options options = new Options();
+        options.addOption( "help", false, "print this message" );
+        options.addOption( "projecthelp", false, "print project help information" );
+        options.addOption( "version", false, "print the version information and exit" );
+        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" );
+        options.addOption( "buildfile", true, "use given buildfile" );
+        options.addOption( OptionBuilder.withDescription( "use value for given property" )
+                                        .hasArgs()
+                                        .withValueSeparator()
+                                        .create( 'D' ) );
+                           //, null, true, , false, true );
+        options.addOption( "find", true, "search for buildfile towards the root of the filesystem and use it" );
+
+        String[] args = new String[]{ "-buildfile", "mybuild.xml",
+            "-Dproperty=value", "-Dproperty1=value1",
+            "-projecthelp" };
+
+        try {
+            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 single value
+            assertEquals( line.getOptionValue( "buildfile"), "mybuild.xml" );
+
+            // check option
+            assertTrue( line.hasOption( "projecthelp") );
+        }
+        catch( ParseException exp ) {
+            fail( "Unexpected exception:" + exp.getMessage() );
+        }
+
+    }
+
+}
\ 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
new file mode 100644
index 0000000..147c5ce
--- /dev/null
+++ b/src/test/org/apache/commons/cli/BugsTest.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ * 
+ * $Id: BugsTest.java,v 1.10 2002/10/24 23:17:49 jkeyes Exp $
+ */
+
+package org.apache.commons.cli;
+
+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 )
+    {
+        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" };
+
+        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() );
+        }
+    }
+
+    public void test11458()
+    {
+        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" };
+
+        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" );
+                }
+            }
+        }
+        catch( ParseException exp ) {
+            fail( "Unexpected Exception:\nMessage:" + exp.getMessage() 
+                  + "Type: " + exp.getClass().getName() );
+        }
+    }
+
+    public void test11680()
+    {
+        Options options = new Options();
+        options.addOption("f", true, "foobar");
+	options.addOption("m", true, "missing");
+        String[] args = new String[] { "-f" , "foo" };
+
+        CommandLineParser parser = new PosixParser();
+
+        try {
+            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() );
+        }
+    }
+
+    public void test11456()
+    {
+        // Posix 
+        Options options = new Options();
+        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() );
+        }
+
+        // GNU
+        options = new Options();
+        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() );
+        }
+
+    }
+
+    public void test12210() {
+        // create the main options object which will handle the first parameter
+        Options mainOptions = new Options();
+        // There can be 2 main exclusive options:  -exec|-rep
+
+        // Therefore, place them in an option group
+
+        String[] argv = new String[] { "-exec", "-exec_opt1", "-exec_opt2" };
+        OptionGroup grp = new OptionGroup();
+
+        grp.addOption(new Option("exec",false,"description for this option"));
+
+        grp.addOption(new Option("rep",false,"description for this option"));
+
+        mainOptions.addOptionGroup(grp);
+
+        // for the exec option, there are 2 options...
+        Options execOptions = new Options();
+        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");
+
+        // create the parser
+        GnuParser parser = new GnuParser();
+
+        // finally, parse the arguments:
+
+        // 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" );
+            }
+        }
+        catch( ParseException exp ) {
+            fail( "Unexpected exception: " + exp.getMessage() );
+        }
+    }
+
+    public void test13425() {
+        Options options = new Options();
+        Option oldpass = OptionBuilder.withLongOpt( "old-password" )
+            .withDescription( "Use this option to specify the old password" )
+            .hasArg()
+            .create( 'o' );
+        Option newpass = OptionBuilder.withLongOpt( "new-password" )
+            .withDescription( "Use this option to specify the new password" )
+            .hasArg()
+            .create( 'n' );
+
+        String[] args = { 
+            "-o", 
+            "-n", 
+            "newpassword" 
+        };
+
+        options.addOption( oldpass );
+        options.addOption( newpass );
+
+        Parser parser = new PosixParser();
+
+        try {
+            CommandLine line = parser.parse( options, args );
+        }
+        // catch the exception and leave the method
+        catch( Exception exp ) {
+            assertTrue( exp != null );
+            return;
+        }
+        fail( "MissingArgumentException not caught." );
+    }
+
+    public void test13666() {
+        Options options = new Options();
+        Option dir = OptionBuilder.withDescription( "dir" )
+                                       .hasArg()
+                                       .create( 'd' );
+        options.addOption( dir );
+        try {
+            HelpFormatter formatter = new HelpFormatter();
+            formatter.printHelp( "dir", options );
+        }
+        catch( Exception exp ) {
+            fail( "Unexpected Exception: " + exp.getMessage() );
+        }
+    }
+
+    public void test13935() {
+        OptionGroup directions = new OptionGroup();
+
+        Option left = new Option( "l", "left", false, "go left" );
+        Option right = new Option( "r", "right", false, "go right" );
+        Option straight = new Option( "s", "straight", false, "go straight" );
+        Option forward = new Option( "f", "forward", false, "go forward" );
+        forward.setRequired( true );
+
+        directions.addOption( left );
+        directions.addOption( right );
+        directions.setRequired( true );
+
+        Options opts = new Options();
+        opts.addOptionGroup( directions );
+        opts.addOption( straight );
+
+        CommandLineParser parser = new PosixParser();
+        boolean exception = false;
+
+        String[] args = new String[] {  };
+        try {
+            CommandLine line = parser.parse( opts, args );
+        }
+        catch( ParseException exp ) {
+            exception = true;
+        }
+
+        if( !exception ) {
+            fail( "Expected exception not caught.");
+        }
+
+        exception = false;
+
+        args = new String[] { "-s" };
+        try {
+            CommandLine line = parser.parse( opts, args );
+        }
+        catch( ParseException exp ) {
+            exception = true;
+        }
+
+        if( !exception ) {
+            fail( "Expected exception not caught.");
+        }
+
+        exception = false;
+
+        args = new String[] { "-s", "-l" };
+        try {
+            CommandLine line = parser.parse( opts, args );
+        }
+        catch( ParseException exp ) {
+            fail( "Unexpected exception: " + exp.getMessage() );
+        }
+
+        opts.addOption( forward );
+        args = new String[] { "-s", "-l", "-f" };
+        try {
+            CommandLine line = parser.parse( opts, args );
+        }
+        catch( ParseException exp ) {
+            fail( "Unexpected exception: " + exp.getMessage() );
+        }
+    }
+}
diff --git a/src/test/org/apache/commons/cli/BuildTest.java b/src/test/org/apache/commons/cli/BuildTest.java
new file mode 100644
index 0000000..88035d7
--- /dev/null
+++ b/src/test/org/apache/commons/cli/BuildTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ * 
+ * $Id: BuildTest.java,v 1.1 2001/12/19 18:16:25 jstrachan Exp $
+ */
+
+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/GnuParseTest.java b/src/test/org/apache/commons/cli/GnuParseTest.java
new file mode 100644
index 0000000..c300bd6
--- /dev/null
+++ b/src/test/org/apache/commons/cli/GnuParseTest.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ * 
+ * $Id: GnuParseTest.java,v 1.3 2002/09/19 22:59:44 jkeyes Exp $
+ */
+
+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 CommandLineParser _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/HelpFormatterExamples.java b/src/test/org/apache/commons/cli/HelpFormatterExamples.java
new file mode 100644
index 0000000..5cb802b
--- /dev/null
+++ b/src/test/org/apache/commons/cli/HelpFormatterExamples.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ * 
+ * $Id: HelpFormatterExamples.java,v 1.2 2002/05/17 11:44:32 jstrachan Exp $
+ */
+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/OptionBuilderTest.java b/src/test/org/apache/commons/cli/OptionBuilderTest.java
new file mode 100644
index 0000000..35ffce8
--- /dev/null
+++ b/src/test/org/apache/commons/cli/OptionBuilderTest.java
@@ -0,0 +1,158 @@
+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( )
+                                     .isRequired( )
+                                     .hasArgs( )
+                                     .withType( new Float( 10 ) )
+                                     .withDescription( "this is a simple option" )
+                                     .create( 's' );
+
+        assertEquals( "s", simple.getOpt() );
+        assertEquals( "simple option", simple.getLongOpt() );
+        assertEquals( "this is a simple option", simple.getDescription() );
+        assertEquals( simple.getType().getClass(), Float.class );
+        assertTrue( simple.hasArg() );
+        assertTrue( simple.isRequired() );
+        assertTrue( simple.hasArgs() );
+    }
+
+    public void testTwoCompleteOptions( ) {
+        Option simple = OptionBuilder.withLongOpt( "simple option")
+                                     .hasArg( )
+                                     .isRequired( )
+                                     .hasArgs( )
+                                     .withType( new Float( 10 ) )
+                                     .withDescription( "this is a simple option" )
+                                     .create( 's' );
+
+        assertEquals( "s", simple.getOpt() );
+        assertEquals( "simple option", simple.getLongOpt() );
+        assertEquals( "this is a simple option", simple.getDescription() );
+        assertEquals( simple.getType().getClass(), Float.class );
+        assertTrue( simple.hasArg() );
+        assertTrue( simple.isRequired() );
+        assertTrue( simple.hasArgs() );
+
+        simple = OptionBuilder.withLongOpt( "dimple option")
+                              .hasArg( )
+                              .withDescription( "this is a dimple option" )
+                              .create( 'd' );
+
+        assertEquals( "d", simple.getOpt() );
+        assertEquals( "dimple option", simple.getLongOpt() );
+        assertEquals( "this is a dimple option", simple.getDescription() );
+        assertNull( simple.getType() );
+        assertTrue( simple.hasArg() );
+        assertTrue( !simple.isRequired() );
+        assertTrue( !simple.hasArgs() );
+    }
+
+    public void testBaseOptionCharOpt() {
+        Option base = OptionBuilder.withDescription( "option description")
+                                   .create( 'o' );
+
+        assertEquals( "o", base.getOpt() );
+        assertEquals( "option description", base.getDescription() );
+        assertTrue( !base.hasArg() );
+    }
+
+    public void testBaseOptionStringOpt() {
+        Option base = OptionBuilder.withDescription( "option description")
+                                   .create( "o" );
+
+        assertEquals( "o", base.getOpt() );
+        assertEquals( "option description", base.getDescription() );
+        assertTrue( !base.hasArg() );
+    }
+
+    public void testSpecialOptChars() {
+
+        // '?'
+        try {
+            Option opt = OptionBuilder.withDescription( "help options" )
+                                      .create( '?' );
+            assertEquals( "?", opt.getOpt() );
+        }
+        catch( IllegalArgumentException arg ) {
+            fail( "IllegalArgumentException caught" );
+        }
+
+        // '@'
+        try {
+            Option opt = OptionBuilder.withDescription( "read from stdin" )
+                                      .create( '@' );
+            assertEquals( "@", opt.getOpt() );
+        }
+        catch( IllegalArgumentException arg ) {
+            fail( "IllegalArgumentException caught" );
+        }
+    }
+
+    public void testOptionArgNumbers() {
+        Option opt = OptionBuilder.withDescription( "option description" )
+                                  .hasArgs( 2 )
+                                  .create( 'o' );
+        assertEquals( 2, opt.getArgs() );
+    }
+
+    public void testIllegalOptions() {
+        // bad single character option
+        try {
+            Option opt = OptionBuilder.withDescription( "option description" )
+                                      .create( '"' );
+            fail( "IllegalArgumentException not caught" );
+        }
+        catch( IllegalArgumentException exp ) {
+            // success
+        }
+
+        // bad character in option string
+        try {
+            Option opt = OptionBuilder.create( "opt`" );
+            fail( "IllegalArgumentException not caught" );
+        }
+        catch( IllegalArgumentException exp ) {
+            // success
+        }
+
+        // null option
+        try {
+            Option opt = OptionBuilder.create( null );
+            fail( "IllegalArgumentException not caught" );
+        }
+        catch( IllegalArgumentException exp ) {
+            // success
+        }
+
+        // valid option 
+        try {
+            Option opt = OptionBuilder.create( "opt" );
+            // success
+        }
+        catch( IllegalArgumentException exp ) {
+            fail( "IllegalArgumentException caught" );
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/test/org/apache/commons/cli/OptionGroupTest.java b/src/test/org/apache/commons/cli/OptionGroupTest.java
new file mode 100644
index 0000000..e9109c3
--- /dev/null
+++ b/src/test/org/apache/commons/cli/OptionGroupTest.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ * 
+ * $Id: OptionGroupTest.java,v 1.1 2002/04/23 16:08:02 jstrachan Exp $
+ */
+
+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: 1.1 $
+ */
+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" );
+        Option dir = new Option( "d", "directory", false, "directory to process" );
+        OptionGroup group = new OptionGroup();
+        group.addOption( file );
+        group.addOption( dir );
+        _options = new Options().addOptionGroup( group );
+
+        Option section = new Option( "s", "section", false, "section to process" );
+        Option chapter = new Option( "c", "chapter", false, "chapter to process" );
+        OptionGroup group2 = new OptionGroup();
+        group2.addOption( section );
+        group2.addOption( chapter );
+
+        _options.addOptionGroup( group2 );
+        _options.addOption( "r", "revision", false, "revision number" );
+    }
+
+    public void tearDown()
+    {
+    }
+
+    public void testSingleOptionFromGroup()
+    {
+        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() );
+        }
+    }
+
+    public void testSingleOption()
+    {
+        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() );
+        }
+    }
+
+    public void testTwoValidOptions()
+    {
+        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() );
+        }
+    }
+
+    public void testSingleLongOption()
+    {
+        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() );
+        }
+    }
+
+    public void testTwoValidLongOptions()
+    {
+        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() );
+        }
+    }
+
+    public void testNoOptionsExtraArgs()
+    {
+        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() );
+        }
+    }
+
+    public void testTwoOptionsFromGroup()
+    {
+        String[] args = new String[] { "-f", "-d" };
+
+        try
+        {
+            CommandLine cl = parser.parse( _options, args);
+            fail( "two arguments from group not allowed" );
+        }
+        catch (ParseException e)
+        {
+            if( !( e instanceof AlreadySelectedException ) )
+            {
+                fail( "incorrect exception caught:" + e.getMessage() );
+            }
+        }
+    }
+
+    public void testTwoLongOptionsFromGroup()
+    {
+        String[] args = new String[] { "--file", "--directory" };
+
+        try
+        {
+            CommandLine cl = parser.parse( _options, args);
+            fail( "two arguments from group not allowed" );
+        }
+        catch (ParseException e)
+        {
+            if( !( e instanceof AlreadySelectedException ) )
+            {
+                fail( "incorrect exception caught:" + e.getMessage() );
+            }
+        }
+    }
+
+    public void testTwoOptionsFromDifferentGroup()
+    {
+        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() );
+        }
+    }
+
+
+}
diff --git a/src/test/org/apache/commons/cli/ParseRequiredTest.java b/src/test/org/apache/commons/cli/ParseRequiredTest.java
new file mode 100644
index 0000000..a2b23ab
--- /dev/null
+++ b/src/test/org/apache/commons/cli/ParseRequiredTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ * 
+ * $Id: ParseRequiredTest.java,v 1.1 2002/04/23 16:08:02 jstrachan Exp $
+ */
+
+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: 1.1 $
+ */
+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()
+            .addOption("a",
+                       "enable-a",
+                       false,
+                       "turn [a] on or off")
+            .addOption( OptionBuilder.withLongOpt( "bfile" )
+                                     .hasArg()
+                                     .isRequired()
+                                     .withDescription( "set the value of [b]" )
+                                     .create( 'b' ) );
+    }
+
+    public void tearDown()
+    {
+
+    }
+
+    public void testWithRequiredOption()
+    {
+        String[] args = new String[] {  "-b", "file" };
+
+        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);
+        }
+        catch (ParseException e)
+        {
+            fail( e.toString() );
+        }
+    }
+
+    public void testOptionAndRequiredOption()
+    {
+        String[] args = new String[] {  "-a", "-b", "file" };
+
+        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);
+        }
+        catch (ParseException e)
+        {
+            fail( e.toString() );
+        }
+    }
+
+    public void testMissingRequiredOption()
+    {
+        String[] args = new String[] { "-a" };
+
+        try
+        {
+            CommandLine cl = parser.parse(_options,args);
+            fail( "exception should have been thrown" );
+        }
+        catch (ParseException e)
+        {
+            if( !( e instanceof MissingOptionException ) )
+            {
+                fail( "expected to catch MissingOptionException" );
+            }
+        }
+    }
+
+}
diff --git a/src/test/org/apache/commons/cli/ParseTest.java b/src/test/org/apache/commons/cli/ParseTest.java
new file mode 100644
index 0000000..f5990c2
--- /dev/null
+++ b/src/test/org/apache/commons/cli/ParseTest.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ * 
+ * $Id: ParseTest.java,v 1.1 2001/12/19 18:16:25 jstrachan Exp $
+ */
+
+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 CommandLineParser _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 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/PatternOptionBuilderTest.java b/src/test/org/apache/commons/cli/PatternOptionBuilderTest.java
new file mode 100644
index 0000000..c0d66ff
--- /dev/null
+++ b/src/test/org/apache/commons/cli/PatternOptionBuilderTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ * 
+ * $Id: PatternOptionBuilderTest.java,v 1.1 2002/06/06 22:09:25 bayard Exp $
+ */
+package org.apache.commons.cli;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.io.StringWriter;
+import java.io.PrintWriter;
+
+/** 
+ * Test case for the PatternOptionBuilder class 
+ *
+ * @author Henri Yandell
+ **/
+public class PatternOptionBuilderTest
+extends TestCase
+{
+    public static void main( String[] args )
+   {
+      String[] testName = { PatternOptionBuilderTest.class.getName() };
+      junit.textui.TestRunner.main(testName);
+   }
+
+   public static TestSuite suite()
+   {
+      return new TestSuite(PatternOptionBuilderTest.class);
+   }
+
+   public PatternOptionBuilderTest( String s )
+   {
+      super( s );
+   }
+
+   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);
+
+           // tests the char methods of CommandLine that delegate to
+           // the String methods
+           assertEquals("flag a", "foo", line.getOptionValue("a"));
+           assertEquals("flag a", "foo", line.getOptionValue('a'));
+           assertEquals("string flag a", "foo", line.getOptionObject("a"));
+           assertEquals("string flag a", "foo", line.getOptionObject('a'));
+           assertEquals("object flag b", new java.util.Vector(), line.getOptionObject("b"));
+           assertEquals("object flag b", new java.util.Vector(), line.getOptionObject('b'));
+           assertEquals("boolean true flag c", true, line.hasOption("c"));
+           assertEquals("boolean true flag c", true, line.hasOption('c'));
+           assertEquals("boolean false flag d", false, line.hasOption("d"));
+           assertEquals("boolean false flag d", false, line.hasOption('d'));
+           assertEquals("file flag e", new java.io.File("build.xml"), line.getOptionObject("e"));
+           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("class flag f", java.util.Calendar.class, line.getOptionObject('f'));
+           assertEquals("number flag n", new Float(4.5), line.getOptionObject("n"));
+           assertEquals("number flag n", new Float(4.5), line.getOptionObject('n'));
+           assertEquals("url flag t", new java.net.URL("http://jakarta.apache.org/"), line.getOptionObject("t"));
+           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() );
+       }
+   }
+
+}
diff --git a/src/test/org/apache/commons/cli/TestHelpFormatter.java b/src/test/org/apache/commons/cli/TestHelpFormatter.java
new file mode 100644
index 0000000..8142dc8
--- /dev/null
+++ b/src/test/org/apache/commons/cli/TestHelpFormatter.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ * 
+ * $Id: TestHelpFormatter.java,v 1.2 2002/05/17 11:44:32 jstrachan Exp $
+ */
+package org.apache.commons.cli;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/** 
+ * Test case for the HelpFormatter class 
+ *
+ * @author Slawek Zachcial
+ * @author John Keyes ( john at integralsource.com )
+ **/
+public class TestHelpFormatter extends TestCase
+{
+   public static void main( String[] args )
+   {
+      String[] testName = { TestHelpFormatter.class.getName() };
+      junit.textui.TestRunner.main(testName);
+   }
+
+   public static TestSuite suite()
+   {
+      return new TestSuite(TestHelpFormatter.class);
+   }
+
+   public TestHelpFormatter( 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.defaultNewLine + "test.";
+      hf.renderWrappedText(sb, 12, 0, text);
+      assertEquals("single line text", expected, sb.toString());
+
+      sb.setLength(0);
+      expected = "This is a" + hf.defaultNewLine + "    test.";
+      hf.renderWrappedText(sb, 12, 4, text);
+      assertEquals("single line padded text", expected, sb.toString());
+
+      text =
+         "aaaa aaaa aaaa" + hf.defaultNewLine +
+         "aaaaaa" + hf.defaultNewLine +
+         "aaaaa";
+
+      expected = text;
+      sb.setLength(0);
+      hf.renderWrappedText(sb, 16, 0, text);
+      assertEquals("multi line text", expected, sb.toString());
+
+      expected =
+         "aaaa aaaa aaaa" + hf.defaultNewLine +
+         "    aaaaaa" + hf.defaultNewLine +
+         "    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.defaultNewLine +
+           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.defaultNewLine +
+           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.defaultNewLine +
+           hf.createPadding(nextLineTabStop) + "dddd dddd" + hf.defaultNewLine +
+           lpad + "-b      " + dpad + "feeee eeee" + hf.defaultNewLine +
+           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 [-b] [-a]";
+       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();
+   }
+}
diff --git a/src/test/org/apache/commons/cli/ValueTest.java b/src/test/org/apache/commons/cli/ValueTest.java
new file mode 100644
index 0000000..21d6f92
--- /dev/null
+++ b/src/test/org/apache/commons/cli/ValueTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ * 
+ * $Id: ValueTest.java,v 1.1 2001/12/19 18:16:25 jstrachan Exp $
+ */
+
+package org.apache.commons.cli;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+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)
+    {
+        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' ) );
+
+        String[] args = new String[] { "-a",
+            "-b", "foo",
+            "--c",
+            "--d", "bar" 
+        };
+
+        try
+        {
+            CommandLineParser parser = new PosixParser();
+            _cl = parser.parse(opts,args);
+        }
+        catch (ParseException e)
+        {
+            fail("Cannot setUp() CommandLine: " + e.toString());
+        }
+    }
+
+    public void tearDown()
+    {
+
+    }
+
+    public void testShortNoArg()
+    {
+        assertTrue( _cl.hasOption("a") );
+        assertNull( _cl.getOptionValue("a") );
+    }
+
+    public void testShortWithArg()
+    {
+        assertTrue( _cl.hasOption("b") );
+        assertNotNull( _cl.getOptionValue("b") );
+        assertEquals( _cl.getOptionValue("b"), "foo");
+    }
+
+    public void testLongNoArg()
+    {
+        assertTrue( _cl.hasOption("c") );
+        assertNull( _cl.getOptionValue("c") );
+    }
+
+    public void testLongWithArg()
+    {
+        assertTrue( _cl.hasOption("d") );
+        assertNotNull( _cl.getOptionValue("d") );
+        assertEquals( _cl.getOptionValue("d"), "bar");
+    }
+
+    public void testShortOptionalArgNoValue()
+    {
+        String[] args = new String[] { "-e"
+        };
+        try
+        {
+            CommandLineParser 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());
+        }
+    }
+
+    public void testShortOptionalArgValue()
+    {
+        String[] args = new String[] { "-e", "everything"
+        };
+        try
+        {
+            CommandLineParser 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());
+        }
+    }
+
+    public void testLongOptionalNoValue()
+    {
+        String[] args = new String[] { "--fish"
+        };
+        try
+        {
+            CommandLineParser 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());
+        }
+    }
+
+    public void testLongOptionalArgValue()
+    {
+        String[] args = new String[] { "--fish", "face"
+        };
+        try
+        {
+            CommandLineParser 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());
+        }
+    }
+
+    public void testShortOptionalArgValues()
+    {
+        String[] args = new String[] { "-j", "ink", "idea"
+        };
+        try
+        {
+            CommandLineParser 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());
+        }
+    }
+
+    public void testLongOptionalArgValues()
+    {
+        String[] args = new String[] { "--gravy", "gold", "garden"
+        };
+        try
+        {
+            CommandLineParser 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());
+        }
+    }
+
+    public void testShortOptionalNArgValues()
+    {
+        String[] args = new String[] { "-i", "ink", "idea", "isotope", "ice"
+        };
+        try
+        {
+            CommandLineParser 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());
+        }
+    }
+
+    public void testLongOptionalNArgValues()
+    {
+        String[] args = new String[] { "--hide", "house", "hair", "head"
+        };
+        try
+        {
+            CommandLineParser parser = new PosixParser();
+            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());
+        }
+    }
+}
diff --git a/src/test/org/apache/commons/cli/ValuesTest.java b/src/test/org/apache/commons/cli/ValuesTest.java
new file mode 100644
index 0000000..c447219
--- /dev/null
+++ b/src/test/org/apache/commons/cli/ValuesTest.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE file.
+ * 
+ * $Id: ValueTest.java,v 1.1 2001/12/19 18:16:25 jstrachan Exp $
+ */
+
+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 )
+    {
+        super( name );
+    }
+
+    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",
+                                       "--d", "bar",
+                                       "-e", "one", "two",
+                                       "-f",
+                                       "arg1", "arg2",
+                                       "-g", "val1", "val2" , "arg3",
+                                       "-h", "val1", "-i",
+                                       "-h", "val2",
+                                       "-jkey=value",
+                                       "-j", "key=value",
+                                       "-kkey1=value1", 
+                                       "-kkey2=value2",
+                                       "-mkey=value"};
+
+        CommandLineParser parser = new PosixParser();
+
+        try
+        {
+            _cmdline = parser.parse(opts,args);
+        }
+        catch (ParseException e)
+        {
+            fail("Cannot setUp() CommandLine: " + e.toString());
+        }
+    }
+
+    public void tearDown()
+    {
+
+    }
+
+    public void testShortArgs()
+    {
+        assertTrue( _cmdline.hasOption("a") );
+        assertTrue( _cmdline.hasOption("c") );
+
+        assertNull( _cmdline.getOptionValues("a") );
+        assertNull( _cmdline.getOptionValues("c") );
+    }
+
+    public void testShortArgsWithValue()
+    {
+        assertTrue( _cmdline.hasOption("b") );
+        assertTrue( _cmdline.getOptionValue("b").equals("foo"));
+        assertTrue( _cmdline.getOptionValues("b").length == 1);
+
+        assertTrue( _cmdline.hasOption("d") );
+        assertTrue( _cmdline.getOptionValue("d").equals("bar"));
+        assertTrue( _cmdline.getOptionValues("d").length == 1);
+    }
+
+    public void testMultipleArgValues()
+    {
+        String[] result = _cmdline.getOptionValues("e");
+        String[] values = new String[] { "one", "two" };
+        assertTrue( _cmdline.hasOption("e") );
+        assertTrue( _cmdline.getOptionValues("e").length == 2);
+        assertTrue( Arrays.equals( values, _cmdline.getOptionValues("e") ) );
+    }
+
+    public void testTwoArgValues()
+    {
+        String[] result = _cmdline.getOptionValues("g");
+        String[] values = new String[] { "val1", "val2" };
+        assertTrue( _cmdline.hasOption("g") );
+        assertTrue( _cmdline.getOptionValues("g").length == 2);
+        assertTrue( Arrays.equals( values, _cmdline.getOptionValues("g") ) );
+    }
+
+    public void testComplexValues()
+    {
+        String[] result = _cmdline.getOptionValues("h");
+        String[] values = new String[] { "val1", "val2" };
+        assertTrue( _cmdline.hasOption("i") );
+        assertTrue( _cmdline.hasOption("h") );
+        assertTrue( _cmdline.getOptionValues("h").length == 2);
+        assertTrue( Arrays.equals( values, _cmdline.getOptionValues("h") ) );
+    }
+
+    public void testExtraArgs()
+    {
+        String[] args = new String[] { "arg1", "arg2", "arg3" };
+        assertTrue( _cmdline.getArgs().length == 3 );         
+        assertTrue( Arrays.equals( args, _cmdline.getArgs() ) );
+    }
+
+    public void testCharSeparator()
+    {
+        // tests the char methods of CommandLine that delegate to
+        // the String methods
+        String[] values = new String[] { "key", "value", "key", "value" };
+        assertTrue( _cmdline.hasOption( "j" ) );
+        assertTrue( _cmdline.hasOption( 'j' ) );
+        assertTrue( _cmdline.getOptionValues( "j" ).length == 4);
+        assertTrue( _cmdline.getOptionValues( 'j' ).length == 4);
+        assertTrue( Arrays.equals( values, _cmdline.getOptionValues( "j" ) ) );
+        assertTrue( Arrays.equals( values, _cmdline.getOptionValues( 'j' ) ) );
+
+        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 );
+        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);
+        assertTrue( Arrays.equals( values, _cmdline.getOptionValues( "m" ) ) );
+        assertTrue( Arrays.equals( values, _cmdline.getOptionValues( 'm' ) ) );
+    }
+
+    /**
+     * jkeyes - commented out this test as the new architecture
+     * breaks this type of functionality.  I have left the test 
+     * here in case I get a brainwave on how to resolve this.
+     */
+    /*
+    public void testGetValue()
+    {
+        // the 'm' option
+        assertTrue( _option.getValues().length == 2 );
+        assertEquals( _option.getValue(), "key" );
+        assertEquals( _option.getValue( 0 ), "key" );
+        assertEquals( _option.getValue( 1 ), "value" );
+
+        try {
+            assertEquals( _option.getValue( 2 ), "key" );
+            fail( "IndexOutOfBounds not caught" );
+        }
+        catch( IndexOutOfBoundsException exp ) {
+            
+        }
+
+        try {
+            assertEquals( _option.getValue( -1 ), "key" );
+            fail( "IndexOutOfBounds not caught" );
+        }
+        catch( IndexOutOfBoundsException exp ) {
+
+        }
+    }
+    */
+}
diff --git a/xdocs/images/1x1.gif b/xdocs/images/1x1.gif
new file mode 100755
index 0000000..35d42e8
Binary files /dev/null and b/xdocs/images/1x1.gif differ
diff --git a/xdocs/index.xml b/xdocs/index.xml
new file mode 100644
index 0000000..c8e57e0
--- /dev/null
+++ b/xdocs/index.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+
+<document>
+
+ <properties>
+  <title></title>
+  <author email="jstrachan at apache.org">James Strachan</author>
+ </properties>
+
+<body>
+
+<section name="CLI : Command Line Interface">
+
+<p>
+   The CLI library provides a simple and easy to use API for working
+   with the command line arguments and options.</p>
+<p>
+   CLI is based on ideas and code from 
+   <ul>
+     <li>werken.opt by Bob Mcwhirter</li>
+     <li>The cli package in Avalon Excalibur by Peter Donald</li>
+     <li>Optz by John Keyes</li>
+   </ul>
+</p>
+
+</section>
+
+</body>
+</document>
diff --git a/xdocs/introduction.xml b/xdocs/introduction.xml
new file mode 100644
index 0000000..a2eb765
--- /dev/null
+++ b/xdocs/introduction.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0"?>
+<document>
+
+  <properties>
+    <author email="jbjk at mac.com">John Keyes</author>
+    <title>Introduction</title>
+  </properties>
+
+  <body>
+    <section name="Introduction">
+      <p>
+        There are three stages to command line processing.  They are the
+        definition, parsing and interrogation stages.  The following 
+        sections will discuss each of these stages in turn, and discuss how
+        to implement them with CLI.
+      </p>
+    </section>
+    <section name="Definition Stage">
+      <p>
+        Each command line must define the set of options that will be used 
+        to define the interface to the application.
+      </p>
+      <p>
+        CLI uses the <a href="apidocs/org/apache/commons/cli/Options.html">
+        Options</a> class, as a container for 
+        <a href="apidocs/org/apache/commons/cli/Options.html">
+        Option</a> instances.  There are two ways to create
+        <code>Option</code>s in CLI.  One of them is via the constuctors,
+        the other way is via the factory methods defined in 
+        <code>Options</code>.
+      </p>
+      <p>
+        The <a href="usage.html">Usage Scenarios</a> document provides
+        examples how to create an <code>Options</code> object and also
+        provides some real world examples.
+      </p>
+      <p>
+        The result of the definition stage is an <code>Options</code> 
+        instance.
+      </p>
+    </section>
+    <section name="Parsing Stage">
+      <p>
+        The parsing stage is where the text passed into the 
+        application via the command line is processed.  The text is 
+        processed according to the rules defined by the parser 
+        implementation.
+      </p>
+      <p>
+        The <code>parse</code> method defined on 
+        <a href="apidocs/org/apache/commons/cli/CommandLineParser.html">
+        CommandLineParser</a> takes an <code>Options</code>
+        instance and a <code>java.util.List</code> of arguments and 
+        returns a 
+        <a href="apidocs/org/apache/commons/cli/CommandLine.html">
+        CommandLine</a>.
+      </p>
+      <p>
+        The result of the parsing stage is a <code>CommandLine</code>
+        instance.
+      </p>
+    </section>
+    <section name="Interrogation Stage">
+      <p>
+        The interrogation stage is where the application querys the
+        <code>CommandLine</code> to decide what execution branch to
+        take depending on boolean options and to use the option values
+        to provide the application data.
+      </p>
+      <p>
+        This stage is implemented in the user code.  The accessor methods 
+        on <code>CommandLine</code> provide the interrogation capability
+        to the user code.
+      </p>
+      <p>
+        The <a href="usage.html">Usage Scenarios</a> document provides examples
+        how to create an <code>Options</code> object.
+      </p>
+      <p>
+        The result of the interrogation stage is that the user code 
+        is fully informed of all the text that was supplied on the command
+        line and processed according to the parser and <code>Options</code>
+        rules.
+      </p>
+    </section>
+  </body>
+</document>
diff --git a/xdocs/navigation.xml b/xdocs/navigation.xml
new file mode 100644
index 0000000..3e4acb9
--- /dev/null
+++ b/xdocs/navigation.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="CLI">
+
+  <title>CLI</title>
+
+  <body>
+    <menu name="User Documentation">
+      <item name="Introduction"      href="/introduction.html"/>
+      <item name="Usage Scenarios"   href="/usage.html"/>
+      <item name="Option Properties" href="/properties.html"/>
+      <item name="Download" href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-cli/v1.0/"/>
+    </menu>
+  </body>
+</project>
diff --git a/xdocs/properties.xml b/xdocs/properties.xml
new file mode 100644
index 0000000..f94b1d9
--- /dev/null
+++ b/xdocs/properties.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<document>
+
+  <properties>
+    <author email="john at integralsource.com">John Keyes</author>
+    <title>Option Properties</title>
+  </properties>
+
+  <body>
+    <section name="Option Properties">
+      <p>
+        The following are the properties that each 
+        <a href="apidocs/org/apache/commons/cli/Options.html">Option</a> has.  All of these
+        can be set using the accessors or using the methods
+        defined on the
+        <a href="apidocs/org/apache/commons/cli/OptionBuilder.html">OptionBuilder</a>.
+      </p>
+      <table>
+        <tr>
+          <th>Name</th>
+          <th>Type</th>
+          <th>Description</th>
+        </tr>
+        <tr>
+          <td>opt</td>
+          <td>java.lang.String</td>
+          <td>the identification string of the Option.</td>
+        </tr>
+        <tr>
+          <td>longOpt</td>
+          <td>java.lang.String</td>
+          <td>an alias and more descriptive identification string</td>
+        </tr>
+        <tr>
+          <td>description</td>
+          <td>java.lang.String</td>
+          <td>a description of the function of the option</td>
+        </tr>
+        <tr>
+          <td>required</td>
+          <td>boolean</td>
+          <td>a flag to say whether the option <b>must</b> appear on 
+            the command line.</td>
+        </tr>
+        <tr>
+          <td>multipleArgs</td>
+          <td>boolean</td>
+          <td>a flag to say whether the option takes multiple argument 
+            values</td>
+        </tr>
+        <tr>
+          <td>arg</td>
+          <td>boolean</td>
+          <td>a flag to say whether the option takes an argument</td>
+        </tr>
+        <tr>
+          <td>args</td>
+          <td>boolean</td>
+          <td>a flag to say whether the option takes more than one argument</td>
+        </tr>
+        <tr>
+          <td>optionalArg</td>
+          <td>boolean</td>
+          <td>a flag to say whether the option's argument is optional</td>
+        </tr>
+        <tr>
+          <td>argName</td>
+          <td>java.lang.String</td>
+          <td>the name of the argument value for the usage statement</td>
+        </tr>
+        <tr>
+          <td>valueSeparator</td>
+          <td>char</td>
+          <td>the character value used to split the argument string, that
+            is used in conjunction with multipleArgs e.g.
+            if the separator is ',' and the argument string is 'a,b,c' then
+            there are three argument values, 'a', 'b' and 'c'.</td>
+        </tr>
+        <tr>
+          <td>type</td>
+          <td>java.lang.Object</td>
+          <td>the type of the argument</td>
+        </tr>
+        <tr>
+          <td>value</td>
+          <td>java.lang.String</td>
+          <td>the value of the option</td>
+        </tr>
+        <tr>
+          <td>values</td>
+          <td>java.lang.String[]</td>
+          <td>the values of the option</td>
+        </tr>
+      </table>
+    </section>
+  </body>
+</document>
diff --git a/xdocs/usage.xml b/xdocs/usage.xml
new file mode 100644
index 0000000..6120814
--- /dev/null
+++ b/xdocs/usage.xml
@@ -0,0 +1,350 @@
+<?xml version="1.0"?>
+<document>
+
+  <properties>
+    <author email="john at integralsource.com">John Keyes</author>
+    <title>Usage Scenarios</title>
+  </properties>
+
+  <body>
+    <section name="Usage Scenarios">
+      <p>
+        The following sections describe some example scenarios on how to 
+        use CLI in applications.
+      </p>
+
+      <subsection name="Using a boolean option">
+        <p>
+          A boolean option is represented on a command line by the presence
+          of the option, i.e. if the option is found then the option value
+          is true, otherwise the value is false.
+        </p>
+        <p>
+          The <code>DateApp</code> utility prints the current date to standard
+          output.  If the <code>-t</code> option is present the current time is 
+          also printed.
+        </p>
+      </subsection>
+      <subsection name="Create the Options">
+        <p>
+          An <a href="apidocs/org/apache/commons/cli/Options.html">
+          Options</a> object must be created and the<code>Option</code> must be 
+          added to it.
+        </p>
+        <source>
+// create Options object
+Options options = new Options();
+
+// add t option
+options.addOption("t", false, "display current time");</source>
+          <p>
+            The <code>addOption</code> method has three parameters.  The first
+            parameter is a <code>java.lang.String</code> that represents the option. 
+            Thesecond paramter is a <code>boolean</code> that specifies whether the
+            option requires an argument or not.  In the case of a boolean option
+            (sometimes referred to as a flag) an argument value is not present so
+            it <code>false</code> is passed.  The third parameter is the description
+            of the option.  This description will be used in the usage text of the
+            application.
+          </p>
+      </subsection>
+      <subsection name="Parsing the command line arguments">
+        <p>
+          The <code>parse</code> methods of <code>Options</code> are used to 
+          parse the command line arguments.  
+        </p>
+        <source>CommandLine cmd = options.parse(args);</source>
+        <p>
+          Now we need to check if the <code>t</code> option is present.  To do
+          this we will interrogate the 
+          <a href="apidocs/org/apache/commons/cli/CommandLine.html">CommandLine
+          </a> object.  The <code>hasOption</code> method takes a 
+          <code>java.lang.String</code> parameter and returns true if the option 
+          represented by the <code>java.lang.String</code> is present, otherwise 
+          it returns false.
+        </p>
+        <source>if(cmd.hasOption("t")) {
+    // print the date and time
+}
+else {
+    // print the date
+}</source>
+      </subsection>
+      <subsection name="International Time">
+        <p>
+          The <code>InternationalDateApp</code> utility extends the 
+          <code>DateApp</code> utility by providing the ability to print the
+          date and time in any country in the world.  To facilitate this a new
+          command line option, <code>c</code>, has been introduced.
+        </p>
+        <source>// add c option
+options.addOption("c", true, "country code");</source>
+        <p>
+          The second parameter is true this time.  This specifies that the
+          <code>c</code> option requires an argument value.  If the required option
+          argument value is specified on the command line it is returned,
+          otherwise <code>null</code> is returned.
+        </p>
+      </subsection>
+      <subsection name="Retrieving the argument value">
+        <p>
+          The <code>getOptionValue</code> methods of <code>Options</code> are
+          used to retrieve the argument values of options.
+        </p>
+        <source>// get c option value
+String countryCode = options.getOptionValue("c");
+
+if(countryCode == null) {
+    // print default date
+}
+else {
+    // print date for country specified by countryCode
+}</source>
+      </subsection>
+    </section>
+
+    <section name="Ant Example">
+      <p>
+        As one of the most ubquituous Java applications 
+        <a href="http://jakarta.apache.org/ant">Ant</a> it will be used
+        here to illustrate how to create the Options required.  The following
+        is the help output for Ant.
+      </p>
+      <source>ant [options] [target [target2 [target3] ...]]
+  Options: 
+  -help                  print this message
+  -projecthelp           print project help information
+  -version               print the version information and exit
+  -quiet                 be extra quiet
+  -verbose               be extra verbose
+  -debug                 print debugging information
+  -emacs                 produce logging information without adornments
+  -logfile <file>        use given file for log
+  -logger <classname>    the class which is to perform logging
+  -listener <classname>  add an instance of class as a project listener
+  -buildfile <file>      use given buildfile
+  -D<property>=<value>   use value for given property
+  -find <file>           search for buildfile towards the root of the
+                         filesystem and use it</source>
+      <subsection name="Boolean Options">
+        <p>
+          Lets create the boolean options for the application as they
+          are the easiest to create.  For clarity the constructors on
+          Option are used here.
+        </p>
+        <source>Option help = new Option( "help", "print this message" );
+Option projecthelp = new Option( "projecthelp", "print project help information" );
+Option version = new Option( "version", "print the version information and exit" );
+Option quiet = new Option( "quiet", "be extra quiet" );
+Option verbose = new Option( "verbose", "be extra verbose" );
+Option debug = new Option( "debug", "print debugging information" );
+Option emacs = new Option( "emacs",
+                           "produce logging information without adornments" );</source>
+      </subsection>
+      <subsection name="Argument Options">
+        <p> 
+          The argument options are created using the OptionBuilder.
+        </p>
+        <source>Option logfile   = OptionBuilder.withArgName( "file" )
+                                .hasArg()
+                                .withDescription(  "use given file for log" )
+                                .create( "file" );
+
+Option logger    = OptionBuilder.withArgName( "classname" )
+                                .hasArg()
+                                .withDescription( "the class which it to perform "
+                                                  + "logging" )
+                                .create( "logger" );
+
+Option listener  = OptionBuilder.withArgName( "classname" )
+                                .hasArg()
+                                .withDescription( "add an instance of class as "
+                                                  + "a project listener" )
+                                .create( "listener"); 
+
+Option buildfile = OptionBuilder.withArgName( "file" )
+                                .hasArg()
+                                .withDescription(  "use given buildfile" )
+                                .create( "buildfile");
+
+Option find      = OptionBuilder.withArgName( "file" )
+                                .hasArg()
+                                .withDescription( "search for buildfile towards the "
+                                  + "root of the filesystem and use it" )
+                                .create( "file" );</source>
+      </subsection>
+      <subsection name="Java Property Option">
+        <p>
+          The last option to create is the Java property and it too is created
+          using the OptionBuilder.
+        </p>
+        <source>Option property  = OptionBuilder.withArgName( "property=value" )
+                                .hasArg()
+                                .withValueSeparator()
+                                .withDescription( "use value for given property" )
+                                .create( "D" );</source>
+      </subsection>
+      <subsection name="Create the Options">
+        <p>
+          Now that we have created each 
+          <a href="apidocs/org/apache/commons/cli/Option.html">Option</a> we need 
+          to create the 
+          <a href="apidocs/org/apache/commons/cli/Options.html">Options</a> 
+          instance.  This is achieved using the 
+          <a href="apidocs/org/apache/commons/cli/CommandLine.html#hasOption(java.lang.String)">addOption</a> 
+          method of <code>Options</code>.
+        </p>
+        <source>Options options = new Options();
+
+options.addOption( help );
+options.addOption( projecthelp );
+options.addOption( version );
+options.addOption( quiet );
+options.addOption( verbose );
+options.addOption( debug );
+options.addOption( emacs );
+options.addOption( logfile );
+options.addOption( logger );
+options.addOption( listener );
+options.addOption( buildfile );
+options.addOption( find );
+options.addOption( property );</source>
+        <p>
+          All the preperation is now complete and we are now ready to
+          parse the command line arguments.
+        </p>
+      </subsection>
+      <subsection name="Create the Parser">
+        <p>
+          We now need to create a Parser.  This will parse the command
+          line arguments, using the rules specified by the Options and
+          return an instance of <a href="apidocs/org/apache/commons/cli/CommandLine.html">CommandLine</a>.
+        </p>
+        <source>public static void main( String[] args ) {
+    // create the parser
+    CommandLineParser parser = new PosixParser();
+    try {
+        // parse the command line arguments
+        CommandLine line = parser.parse( options, args );
+    }
+    catch( ParseException exp ) {
+        // oops, something went wrong
+        System.err.println( "Parsing failed.  Reason: " + exp.getMessage() );
+    }
+}</source>
+      </subsection>
+      <subsection name="Querying the commandline">
+        <p>
+          To see if an option has been passed the<code>hasOption</code>
+          method is used.  The argument value can be retrieved using
+          the <code>getValue</code> method.
+        </p>
+        <source>// has the buildfile argument been passed?
+if( line.hasOption( "buildfile" ) ) {
+    // initialise the member variable
+    this.buildfile = line.getValue( "buildfile" );
+}</source>
+      </subsection>
+      <subsection name="Usage/Help">
+        <p>
+          CLI also provides the means to automatically generate usage
+          and help information.  This is achieved with the
+          <a href="apidocs/org/apache/commons/cli/HelpFormatter.html">HelpFormatter</a>
+          class.
+        </p>
+        <source>// automatically generate the help statement
+HelpFormatter formatter = new HelpFormatter();
+formatter.printHelp( "ant", options );</source>
+        <p>
+          When executed the following output is produced:
+        </p>
+        <source>usage: ant
+-D <property=value>     use value for given property
+-buildfile <file>       use given buildfile
+-debug                  print debugging information
+-emacs                  produce logging information without adornments
+-file <file>            search for buildfile towards the root of the
+                        filesystem and use it
+-help                   print this message
+-listener <classname>   add an instance of class as a project listener
+-logger <classname>     the class which it to perform logging
+-projecthelp            print project help information
+-quiet                  be extra quiet
+-verbose                be extra verbose
+-version                print the version information and exit</source>
+        <p>
+          If you also require to have a usage statement printed 
+          then calling <code>formatter.printHelp( "ant", options, true )</code>
+          will generate a usage statment as well as the help information.
+        </p>
+      </subsection>
+    </section>
+
+    <section name="ls Example">
+      <p>
+        One of the most widely used command line applications in the *nix world
+        is <code>ls</code>.  To parse a command line for an application like this
+        a different parser is required, the
+        <a href="apidocs/org/apache/commons/cli/PosixParser.html">PosixParser</a>.
+        Due to the large number of options required for <code>ls</code> this
+        example will only cover a small proportion of the options.  The following
+        is a section of the help output.
+      </p>
+      <source>Usage: ls [OPTION]... [FILE]...
+List information about the FILEs (the current directory by default).
+Sort entries alphabetically if none of -cftuSUX nor --sort.
+
+-a, --all                  do not hide entries starting with .
+-A, --almost-all           do not list implied . and ..
+-b, --escape               print octal escapes for nongraphic characters
+    --block-size=SIZE      use SIZE-byte blocks
+-B, --ignore-backups       do not list implied entries ending with ~
+-c                         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
+-C                         list entries by columns</source>
+      <p>
+        The following is the code that is used to create the 
+        <a href="apidocs/org/apache/commons/cli/Options.html">Options</a> for this example.
+      </p>
+      <source>// create the command line parser
+CommandLineParser parser = new PosixParser();
+
+// create the Options
+Options options = new Options();
+options.addOption( "a", "all", false, "do not hide entries starting with ." );
+options.addOption( "A", "almost-all", false, "do not list implied . and .." );
+options.addOption( "b", "escape", false, "print octal escapes for nongraphic "
+                                         + "characters" );
+options.addOption( OptionBuilder.withLongOpt( "block-size" )
+                                .withDescription( "use SIZE-byte blocks" )
+                                .withValueSeparator( '=' )
+                                .hasArg()
+                                .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" );
+options.addOption( "C", false, "list entries by columns" );
+
+String[] args = new String[]{ "--block-size=10" };
+
+try {
+    // parse the command line arguments
+    CommandLine line = parser.parse( options, args );
+
+    // validate that block-size has been set
+    if( line.hasOption( "block-size" ) ) {
+        // print the value of block-size
+        System.out.println( line.getOptionValue( "block-size" ) );
+    }
+}
+catch( ParseException exp ) {
+    System.out.println( "Unexpected exception:" + exp.getMessage() );
+}</source>
+    </section>
+  </body>
+</document>

-- 
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