summaryrefslogtreecommitdiffstats
path: root/args4j
diff options
context:
space:
mode:
authorYohann Roussel <yroussel@google.com>2014-03-19 16:25:37 +0100
committerYohann Roussel <yroussel@google.com>2014-03-20 15:13:33 +0100
commit4eceb95409e844fdc33c9c706e1dc307bfd40303 (patch)
treeee9f4f3fc79f757c79081c336bce4f1782c6ccd8 /args4j
parent3d2402901b1a6462e2cf47a6fd09711f327961c3 (diff)
downloadtoolchain_jack-4eceb95409e844fdc33c9c706e1dc307bfd40303.zip
toolchain_jack-4eceb95409e844fdc33c9c706e1dc307bfd40303.tar.gz
toolchain_jack-4eceb95409e844fdc33c9c706e1dc307bfd40303.tar.bz2
Initial Jack import.
Change-Id: I953cf0a520195a7187d791b2885848ad0d5a9b43
Diffstat (limited to 'args4j')
-rw-r--r--args4j/.classpath12
-rw-r--r--args4j/.project17
-rw-r--r--args4j/.settings/org.eclipse.jdt.core.prefs12
-rw-r--r--args4j/Android.mk28
-rw-r--r--args4j/NOTICE25
-rw-r--r--args4j/README.android7
-rw-r--r--args4j/args4j-maven-plugin-example/pom.xml54
-rw-r--r--args4j/args4j-maven-plugin-example/src/main/java/org/kohsuke/args4j/maven/Example.java34
-rw-r--r--args4j/args4j-maven-plugin/pom.xml38
-rw-r--r--args4j/args4j-maven-plugin/src/main/java/org/kohsuke/args4j/maven/Args4jUsageMojo.java123
-rw-r--r--args4j/args4j-tools/LICENSE.txt22
-rw-r--r--args4j/args4j-tools/maven.xml10
-rw-r--r--args4j/args4j-tools/pom.xml107
-rw-r--r--args4j/args4j-tools/project.properties3
-rw-r--r--args4j/args4j-tools/project.xml64
-rw-r--r--args4j/args4j-tools/src/META-INF/services/com.sun.mirror.apt.AnnotationProcessorFactory1
-rw-r--r--args4j/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationProcessorFactoryImpl.java154
-rw-r--r--args4j/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationVisitor.java17
-rw-r--r--args4j/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationVisitorReorderer.java42
-rw-r--r--args4j/args4j-tools/src/org/kohsuke/args4j/apt/HtmlWriter.java41
-rw-r--r--args4j/args4j-tools/src/org/kohsuke/args4j/apt/IsolatingClassLoader.java24
-rw-r--r--args4j/args4j-tools/src/org/kohsuke/args4j/apt/Main.java108
-rw-r--r--args4j/args4j-tools/src/org/kohsuke/args4j/apt/Mode.java8
-rw-r--r--args4j/args4j-tools/src/org/kohsuke/args4j/apt/OptionWithUsage.java17
-rw-r--r--args4j/args4j-tools/src/org/kohsuke/args4j/apt/ReloadingClassLoader.java37
-rw-r--r--args4j/args4j-tools/src/org/kohsuke/args4j/apt/TxtWriter.java40
-rw-r--r--args4j/args4j-tools/src/org/kohsuke/args4j/apt/XmlWriter.java43
-rw-r--r--args4j/args4j-tools/test/org/kohsuke/args4j/apt/AnnotationVisitorReordererTest.java53
-rw-r--r--args4j/args4j/LICENSE.txt25
-rw-r--r--args4j/args4j/examples/SampleAnt.java211
-rw-r--r--args4j/args4j/examples/SampleMain.java102
-rw-r--r--args4j/args4j/examples/SampleStarter.bat47
-rw-r--r--args4j/args4j/examples/SampleStarter.java53
-rw-r--r--args4j/args4j/maven.xml23
-rw-r--r--args4j/args4j/pom.xml41
-rw-r--r--args4j/args4j/project.properties1
-rw-r--r--args4j/args4j/project.xml41
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/Argument.java62
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/ClassParser.java43
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/CmdLineException.java64
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/CmdLineParser.java622
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/Config.java84
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/ExampleMode.java33
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/FieldParser.java33
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/IllegalAnnotationError.java27
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/MapSetter.java71
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/Messages.java35
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/Messages.properties41
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/Messages_de_DE.properties49
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/Messages_ru_RU.properties22
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/NamedOptionDef.java44
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/Option.java169
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/OptionDef.java59
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/Starter.java109
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/XmlParser.java91
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/package.html84
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/AnnotationImpl.java63
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/ArgumentImpl.java13
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/BooleanOptionHandler.java43
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/ByteOptionHandler.java24
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/CharOptionHandler.java28
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/ConfigElement.java25
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/DoubleOptionHandler.java21
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/EnumOptionHandler.java58
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/ExplicitBooleanOptionHandler.java64
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/FieldSetter.java42
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/FileOptionHandler.java29
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/FloatOptionHandler.java26
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/IntOptionHandler.java22
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/LongOptionHandler.java24
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/MapOptionHandler.java32
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/Messages.java27
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/Messages.properties12
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/Messages_de.properties20
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/Messages_ru.properties12
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/MethodSetter.java64
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/MultiValueFieldSetter.java70
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/OneArgumentOptionHandler.java47
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/OptionHandler.java94
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/OptionImpl.java18
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/Parameters.java34
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/RestOfArgumentsHandler.java33
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/Setter.java29
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/Setters.java34
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/ShortOptionHandler.java24
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/StopOptionHandler.java49
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/StringArrayOptionHandler.java79
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/StringOptionHandler.java27
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/URIOptionHandler.java37
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/URLOptionHandler.java36
-rw-r--r--args4j/args4j/src/org/kohsuke/args4j/spi/package.html5
-rw-r--r--args4j/args4j/test/ExampleTest.java56
-rw-r--r--args4j/args4j/test/MandatoryOptionTest.java33
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/Aliased.java8
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/AliasedTest.java30
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/Args4JTestBase.java130
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/ArgumentTest.java82
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/Bean.java9
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/CustomExceptionTest.java55
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/EnumArgument.java6
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/EnumArgumentTest.java43
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/EnumAttribute.java10
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/EnumAttributeTest.java44
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/ExplicitBooleanArgumentTest.java101
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/ExplicitBooleanOptionTest.java110
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/ExternalConfiguredTest.java68
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/ExternalConfiguredTest.xml8
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/FieldParserTest.java35
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/Inheritance.java13
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/InheritanceFather.java6
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/InheritanceGrandfather.java6
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/InheritanceMother.java6
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/InheritanceTest.java54
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/InheritedBean.java8
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/Issue10Test.java29
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/LongUsage.java18
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/LongUsageTest.java26
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/MultivaluedTest.java64
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/NativeTypes.java29
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/NativeTypesTest.java63
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/PrintUsageTest.java36
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/Props.java16
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/PropsTest.java119
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/Setter.java12
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/SetterTest.java64
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/SimpleString.java12
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/SimpleStringTest.java82
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/StopOptionTest.java43
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/StringWithMetavar.java8
-rw-r--r--args4j/args4j/test/org/kohsuke/args4j/StringWithMetavarTest.java41
-rw-r--r--args4j/pom.xml139
-rw-r--r--args4j/project.properties44
-rw-r--r--args4j/project.xml66
-rw-r--r--args4j/release.sh10
-rw-r--r--args4j/src/site/apt/apt.apt9
-rw-r--r--args4j/src/site/apt/implementOptionhandler.apt3
-rw-r--r--args4j/src/site/apt/index.apt51
-rw-r--r--args4j/src/site/apt/sample.apt185
-rw-r--r--args4j/src/site/site.xml20
-rw-r--r--args4j/xdocs/changes.xml78
140 files changed, 6880 insertions, 0 deletions
diff --git a/args4j/.classpath b/args4j/.classpath
new file mode 100644
index 0000000..327c709
--- /dev/null
+++ b/args4j/.classpath
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="args4j-tools/src"/>
+ <classpathentry kind="src" output="args4j/target/examples" path="args4j/examples"/>
+ <classpathentry kind="src" output="args4j/target/classes" path="args4j/src"/>
+ <classpathentry kind="src" output="args4j/target/test-classes" path="args4j/test"/>
+ <classpathentry kind="lib" path="args4j/lib/ant.jar"/>
+ <classpathentry kind="lib" path="C:/jdk/150_14/lib/tools.jar"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/150_14"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/args4j/.project b/args4j/.project
new file mode 100644
index 0000000..95c7aa3
--- /dev/null
+++ b/args4j/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>args4j</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/args4j/.settings/org.eclipse.jdt.core.prefs b/args4j/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..8923d4d
--- /dev/null
+++ b/args4j/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+#Wed Jun 18 20:01:43 CEST 2008
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/args4j/Android.mk b/args4j/Android.mk
new file mode 100644
index 0000000..e3054a4
--- /dev/null
+++ b/args4j/Android.mk
@@ -0,0 +1,28 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, args4j/src)
+
+LOCAL_JAVA_RESOURCE_DIRS := args4j/src/
+
+LOCAL_MODULE := args4j-jack
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
diff --git a/args4j/NOTICE b/args4j/NOTICE
new file mode 100644
index 0000000..c5f4684
--- /dev/null
+++ b/args4j/NOTICE
@@ -0,0 +1,25 @@
+Copyright (c) 2003, Kohsuke Kawaguchi
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+
diff --git a/args4j/README.android b/args4j/README.android
new file mode 100644
index 0000000..1184a5c
--- /dev/null
+++ b/args4j/README.android
@@ -0,0 +1,7 @@
+URL: https://github.com/kohsuke/args4j
+Version: args4j-site-2.0.22
+License: MIT
+Description: "Command line option parser"
+
+Direct link: https://github.com/kohsuke/args4j/tree/args4j-site-2.0.22
+Latest commit 754994797019e326578859f1d12826d72c813d01
diff --git a/args4j/args4j-maven-plugin-example/pom.xml b/args4j/args4j-maven-plugin-example/pom.xml
new file mode 100644
index 0000000..d1f8a94
--- /dev/null
+++ b/args4j/args4j-maven-plugin-example/pom.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>args4j</groupId>
+ <artifactId>args4j-site</artifactId>
+ <version>2.0.22</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>args4j-maven-plugin-example</artifactId>
+ <packaging>jar</packaging>
+ <name>Args4j Maven Plugin Example</name>
+
+ <description>Example of running the maven plugin</description>
+
+ <prerequisites>
+ <maven>2.0</maven>
+ </prerequisites>
+ <inceptionYear>2011</inceptionYear>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.kohsuke.args4j</groupId>
+ <artifactId>args4j-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>usage</goal>
+ </goals>
+ <configuration>
+ <sourceFiles>
+ <sourceFile>org/kohsuke/args4j/maven/Example.java</sourceFile>
+ <sourceFile>../../../../args4j-tools/src/org/kohsuke/args4j/apt/Main.java</sourceFile>
+ <sourceFile>../../../../args4j/examples/SampleAnt.java</sourceFile>
+ <sourceFile>../../../../args4j/examples/SampleMain.java</sourceFile>
+ <sourceFile>../../../../args4j/examples/SampleStarter.java</sourceFile>
+ </sourceFiles>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>args4j</groupId>
+ <artifactId>args4j</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/args4j/args4j-maven-plugin-example/src/main/java/org/kohsuke/args4j/maven/Example.java b/args4j/args4j-maven-plugin-example/src/main/java/org/kohsuke/args4j/maven/Example.java
new file mode 100644
index 0000000..88ad9a5
--- /dev/null
+++ b/args4j/args4j-maven-plugin-example/src/main/java/org/kohsuke/args4j/maven/Example.java
@@ -0,0 +1,34 @@
+package org.kohsuke.args4j.maven;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.Option;
+
+public class Example {
+ @Option(name = "-o", usage="Option")
+ public String option;
+
+ @Option(name = "-r", required = true, usage="Required")
+ public String required;
+
+ public static void main(String[] args) {
+ System.exit(new Example().run(args));
+ }
+
+ private int run(String[] args) {
+ CmdLineParser p = new CmdLineParser(this);
+ try {
+ p.parseArgument(args);
+ run();
+ return 0;
+ } catch (CmdLineException e) {
+ System.err.println(e.getMessage());
+ p.printUsage(System.err);
+ return 1;
+ }
+ }
+
+ private void run() {
+ System.out.format("Option %s Required %s\n", option, required);
+ }
+}
diff --git a/args4j/args4j-maven-plugin/pom.xml b/args4j/args4j-maven-plugin/pom.xml
new file mode 100644
index 0000000..251a190
--- /dev/null
+++ b/args4j/args4j-maven-plugin/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>args4j</groupId>
+ <artifactId>args4j-site</artifactId>
+ <version>2.0.22</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <groupId>org.kohsuke.args4j</groupId>
+ <artifactId>args4j-maven-plugin</artifactId>
+ <packaging>maven-plugin</packaging>
+ <name>Args4j Maven Plugin</name>
+ <description>Automate the generation of </description>
+
+ <prerequisites>
+ <maven>2.0</maven>
+ </prerequisites>
+ <inceptionYear>2011</inceptionYear>
+ <dependencies>
+ <dependency>
+ <groupId>args4j</groupId>
+ <artifactId>args4j-tools</artifactId>
+ <version>${project.version}</version>
+ <classifier>all</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-project</artifactId>
+ <version>2.0.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>2.0</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/args4j/args4j-maven-plugin/src/main/java/org/kohsuke/args4j/maven/Args4jUsageMojo.java b/args4j/args4j-maven-plugin/src/main/java/org/kohsuke/args4j/maven/Args4jUsageMojo.java
new file mode 100644
index 0000000..b1ba66c
--- /dev/null
+++ b/args4j/args4j-maven-plugin/src/main/java/org/kohsuke/args4j/maven/Args4jUsageMojo.java
@@ -0,0 +1,123 @@
+package org.kohsuke.args4j.maven;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.kohsuke.args4j.apt.Main;
+
+import java.io.*;
+import java.util.List;
+
+/**
+ * @goal usage
+ */
+public class Args4jUsageMojo extends AbstractMojo {
+
+ /**
+ * Mode. 'TXT' 'XML' or 'HTML'
+ * @parameter expression="TXT"
+ * @required
+ */
+ private String mode;
+
+ /**
+ * Location of the source files.
+ * @parameter expression="${basedir}/src/main/java"
+ * @required
+ */
+ private String sourceDir;
+
+ /**
+ * directory where the the usage are generated
+ * @parameter expression="${project.build.directory}/args4j"
+ * @required
+ */
+ protected String args4jBuildDirPath;
+
+ /**
+ * @parameter
+ */
+ private List<String> sourceFiles;
+
+ private File jar;
+
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ if (sourceFiles == null || sourceFiles.size() == 0) {
+ getLog().info("No sourceFiles defined. Skipping");
+ return;
+ }
+
+ File args4jBuildDir = new File(args4jBuildDirPath);
+ if (!args4jBuildDir.exists() && !args4jBuildDir.mkdirs()) {
+ throw new MojoExecutionException("Couldn't create the directory " + args4jBuildDir.getAbsolutePath());
+ }
+ try {
+ jar = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath());
+ } catch (Exception e) {
+ throw new MojoExecutionException("Couldn't find the jar of the arg4s tools");
+ }
+
+ getLog().debug("Jar path:" + jar);
+
+ for (String relativeSourceFilePath : sourceFiles) {
+ try {
+
+ File sourceFile = new File(sourceDir, relativeSourceFilePath);
+ if (!sourceFile.exists()) {
+ getLog().warn("Source file " + sourceFile.getAbsolutePath() + " not found. Skipping");
+ continue;
+ }
+
+ getLog().debug("Generating usage for " + sourceFile.getAbsolutePath());
+ generateUsage(sourceFile.getAbsolutePath(), args4jBuildDir);
+ } catch (Exception e) {
+ throw new MojoExecutionException("Failed to generate usage for " + relativeSourceFilePath, e);
+ }
+ }
+ }
+
+ private void generateUsage(String sourceFile, File args4jBuildDir) throws InterruptedException, IOException {
+ String outputDir = args4jBuildDir.getAbsolutePath();
+ ProcessBuilder pb = new ProcessBuilder();
+ pb.command("java","-jar", jar.getAbsolutePath(), "-o", outputDir, "-mode", mode, sourceFile);
+
+ printCommand(pb);
+ Process process = pb.start();
+
+ InputStreamReader isr = dumpOutput(process);
+ int r = process.waitFor();
+
+ isr.close();
+ if (r !=0)
+ throw new IOException("args4j generation failed: "+r);
+ }
+
+ private void printCommand(ProcessBuilder pb) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Running: ");
+ for (String s : pb.command()) {
+ sb.append(s).append(" ");
+ }
+ sb.append("from ").append(dir(pb).getAbsolutePath());
+ getLog().debug(sb.toString());
+ }
+
+ private File dir(ProcessBuilder pb) {
+ File directory = pb.directory();
+ if (directory == null) {
+ return new File(System.getProperty("user.dir"));
+ }
+ return directory;
+ }
+
+ private InputStreamReader dumpOutput(Process process) throws IOException {
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+ while ((line = br.readLine()) != null) {
+ System.out.println(line);
+ }
+ return isr;
+ }
+}
diff --git a/args4j/args4j-tools/LICENSE.txt b/args4j/args4j-tools/LICENSE.txt
new file mode 100644
index 0000000..641c531
--- /dev/null
+++ b/args4j/args4j-tools/LICENSE.txt
@@ -0,0 +1,22 @@
+Copyright (c) 2003, Kohsuke Kawaguchi
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/args4j/args4j-tools/maven.xml b/args4j/args4j-tools/maven.xml
new file mode 100644
index 0000000..27b713f
--- /dev/null
+++ b/args4j/args4j-tools/maven.xml
@@ -0,0 +1,10 @@
+<project xmlns:j="jelly:core" xmlns:u="jelly:util">
+
+ <postGoal name="dist:prepare-bin-filesystem">
+ <!-- copy additional files into the distribution zip/tgz -->
+ <deploy:copy-deps xmlns:deploy="deploy"
+ todir="${maven.dist.bin.archive.dir}/${maven.final.name}"
+ excludes="ant,tools"
+ />
+ </postGoal>
+</project>
diff --git a/args4j/args4j-tools/pom.xml b/args4j/args4j-tools/pom.xml
new file mode 100644
index 0000000..dd25bf4
--- /dev/null
+++ b/args4j/args4j-tools/pom.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>args4j</groupId>
+ <artifactId>args4j-site</artifactId>
+ <version>2.0.22</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>args4j-tools</artifactId>
+ <name>args4j-tools</name>
+ <description>development-time tool for generating additional artifacits</description>
+
+ <properties>
+ <mainClass>org.kohsuke.args4j.apt.Main</mainClass>
+ </properties>
+
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <testSourceDirectory>test</testSourceDirectory>
+ <resources>
+ <resource>
+ <directory>src</directory>
+ <includes>
+ <include>**/*.properties</include>
+ <include>META-INF/services/*</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ <mainClass>${mainClass}}</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>1.4</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <shadedArtifactAttached>true</shadedArtifactAttached>
+ <shadedClassifierName>all</shadedClassifierName>
+ <transformers>
+ <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <mainClass>${mainClass}</mainClass>
+ </transformer>
+ </transformers>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>ant</groupId>
+ <artifactId>ant</artifactId>
+ <version>1.5</version>
+ </dependency>
+ <dependency>
+ <groupId>args4j</groupId>
+ <artifactId>args4j</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>1.8.5</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <profiles>
+ <profile>
+ <id>jdk-tools-jar</id>
+ <activation>
+ <os><family>!mac</family></os>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>jdk</groupId>
+ <artifactId>tools</artifactId>
+ <version>5.0</version>
+ <scope>system</scope>
+ <systemPath>${java.home}/../lib/tools.jar</systemPath>
+ </dependency>
+ </dependencies>
+ </profile>
+ </profiles>
+</project>
diff --git a/args4j/args4j-tools/project.properties b/args4j/args4j-tools/project.properties
new file mode 100644
index 0000000..cc15913
--- /dev/null
+++ b/args4j/args4j-tools/project.properties
@@ -0,0 +1,3 @@
+maven.javanet.release.folder=/dist/tools
+maven.jar.manifest.classpath.add=true
+maven.jar.mainclass=org.kohsuke.args4j.apt.Main
diff --git a/args4j/args4j-tools/project.xml b/args4j/args4j-tools/project.xml
new file mode 100644
index 0000000..7510961
--- /dev/null
+++ b/args4j/args4j-tools/project.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+ <extend>../project.xml</extend>
+
+ <pomVersion>3</pomVersion>
+ <name>args4j-tools</name>
+ <artifactId>args4j-tools</artifactId>
+ <description>development-time tool for generating additional artifacits</description>
+ <shortDescription>development-time tool for generating additional artifacits</shortDescription>
+
+ <dependencies>
+ <dependency>
+ <id>ant</id>
+ <version>1.5</version>
+ </dependency>
+ <dependency>
+ <id>args4j</id>
+ <version>${pom.currentVersion}</version>
+ <properties>
+ <jar.manifest.classpath>true</jar.manifest.classpath>
+ </properties>
+ </dependency>
+ <dependency>
+ <groupId>jdk</groupId>
+ <artifactId>tools</artifactId>
+ <version>5.0</version>
+ <jar>${java.home}/../lib/tools.jar</jar>
+ <url>http://java.sun.com/j2se/5.0/download.html</url>
+ <properties>
+ <comment>Needed to run HttpUnit tests. This is the tools.jar from sun jdk. Jar in not in maven repository
+ but is set to JAVA_HOME/../lib/tools.jar in project.properties</comment>
+ </properties>
+ </dependency>
+ <!--dependency>
+ <id></id>
+ <version></version>
+ </dependency-->
+ </dependencies>
+
+ <build>
+ <nagEmailAddress>kk@kohsuke.org</nagEmailAddress>
+
+ <sourceDirectory>src</sourceDirectory>
+ <unitTestSourceDirectory>test</unitTestSourceDirectory>
+
+ <!-- Resources that are packaged up inside the JAR file -->
+ <resources>
+ <resource>
+ <directory>src</directory>
+ <includes>
+ <include>**/*.properties</include>
+ <include>META-INF/services/*</include>
+ </includes>
+ </resource>
+ </resources>
+
+ <!-- Unit test classes -->
+ <unitTest>
+ <includes>
+ <include>**/Test*.java</include>
+ </includes>
+ </unitTest>
+ </build>
+</project>
diff --git a/args4j/args4j-tools/src/META-INF/services/com.sun.mirror.apt.AnnotationProcessorFactory b/args4j/args4j-tools/src/META-INF/services/com.sun.mirror.apt.AnnotationProcessorFactory
new file mode 100644
index 0000000..69cf068
--- /dev/null
+++ b/args4j/args4j-tools/src/META-INF/services/com.sun.mirror.apt.AnnotationProcessorFactory
@@ -0,0 +1 @@
+org.kohsuke.args4j.apt.AnnotationProcessorFactoryImpl \ No newline at end of file
diff --git a/args4j/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationProcessorFactoryImpl.java b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationProcessorFactoryImpl.java
new file mode 100644
index 0000000..d7148f8
--- /dev/null
+++ b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationProcessorFactoryImpl.java
@@ -0,0 +1,154 @@
+package org.kohsuke.args4j.apt;
+
+import com.sun.mirror.apt.AnnotationProcessor;
+import com.sun.mirror.apt.AnnotationProcessorEnvironment;
+import com.sun.mirror.apt.AnnotationProcessorFactory;
+import com.sun.mirror.declaration.AnnotationTypeDeclaration;
+import com.sun.mirror.declaration.ClassDeclaration;
+import com.sun.mirror.declaration.Declaration;
+import com.sun.mirror.declaration.FieldDeclaration;
+import com.sun.mirror.declaration.MethodDeclaration;
+import com.sun.mirror.declaration.TypeDeclaration;
+import com.sun.mirror.declaration.MemberDeclaration;
+import com.sun.mirror.type.ClassType;
+import com.sun.mirror.util.SimpleDeclarationVisitor;
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.FileInputStream;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Properties;
+
+/**
+ * {@link AnnotationProcessorFactory} to be invoked by APT.
+ *
+ * This class receives options from the Main method through system properties (ouch!).
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class AnnotationProcessorFactoryImpl implements AnnotationProcessorFactory {
+
+ private File outDir;
+ private String format;
+ private Properties resource = null;
+
+ public AnnotationProcessorFactoryImpl() {
+ outDir = new File(System.getProperty("args4j.outdir"));
+ format = System.getProperty("args4j.format");
+
+ String res = System.getProperty("args4j.resource");
+ if(res!=null && res.length()>0) {
+ try {
+ resource = new Properties();
+ resource.load(new FileInputStream(res));
+ } catch (IOException e) {
+ throw new Error(e);
+ }
+ }
+ }
+
+ public Collection<String> supportedOptions() {
+ return Collections.emptyList();
+ }
+
+ public Collection<String> supportedAnnotationTypes() {
+ return Arrays.asList(Option.class.getName(),Argument.class.getName());
+ }
+
+ public AnnotationProcessor getProcessorFor(final Set<AnnotationTypeDeclaration> annotationTypeDeclarations, final AnnotationProcessorEnvironment env) {
+ return new AnnotationProcessor() {
+ public void process() {
+ Collection<Declaration> params = env.getDeclarationsAnnotatedWith((AnnotationTypeDeclaration)env.getTypeDeclaration(Option.class.getName()));
+
+ final Set<TypeDeclaration> optionBeans = new HashSet<TypeDeclaration>();
+ for (Declaration d : params) {
+ d.accept(new SimpleDeclarationVisitor() {
+ public void visitFieldDeclaration(FieldDeclaration f) {
+ TypeDeclaration dt = f.getDeclaringType();
+ optionBeans.add(dt);
+ }
+
+ public void visitMethodDeclaration(MethodDeclaration m) {
+ optionBeans.add(m.getDeclaringType());
+ }
+ });
+ }
+
+ for (TypeDeclaration t : optionBeans) {
+ // make sure that they are on classes
+ if(t instanceof ClassDeclaration) {
+ ClassDeclaration cd = (ClassDeclaration)t;
+ try {
+ AnnotationVisitor writer = createAnnotationVisitor(cd);
+ env.getMessager().printNotice("Processing "+cd.getQualifiedName());
+ scan(cd, writer);
+ } catch (IOException e) {
+ env.getMessager().printError(e.getMessage());
+ }
+ } else {
+ env.getMessager().printError(t.getPosition(),
+ "args4j annotations need to be placed on a class");
+ }
+ }
+ }
+ };
+ }
+
+ private AnnotationVisitor createAnnotationVisitor(ClassDeclaration cd) throws IOException {
+ FileWriter out = new FileWriter(new File(outDir,cd.getQualifiedName()+"."+format.toLowerCase()));
+ AnnotationVisitor writer;
+ if(format.equals("XML"))
+ writer = new XmlWriter(out,cd);
+ else if (format.equals("TXT"))
+ writer = new TxtWriter(out, cd);
+ else
+ writer = new HtmlWriter(out);
+ return new AnnotationVisitorReorderer(writer);
+ }
+
+ private void scan(ClassDeclaration decl, AnnotationVisitor visitor) {
+ while(decl!=null) {
+ for( FieldDeclaration f : decl.getFields() )
+ scan(f, visitor);
+
+ for (MethodDeclaration m : decl.getMethods())
+ scan(m, visitor);
+
+ ClassType sc = decl.getSuperclass();
+ if(sc==null) break;
+
+ decl = sc.getDeclaration();
+ }
+
+ visitor.done();
+ }
+
+ private void scan(MemberDeclaration f, AnnotationVisitor visitor) {
+ Option o = f.getAnnotation(Option.class);
+ if(o==null) return;
+
+ String usage = getUsage(o);
+ if(isOptionHidden(usage)) return;
+
+ visitor.onOption(new OptionWithUsage(o, usage));
+ }
+
+ private boolean isOptionHidden(String usage) {
+ return usage==null || usage.length()==0;
+ }
+
+ private String getUsage(Option o) {
+ if(resource==null)
+ return o.usage();
+ else
+ return resource.getProperty(o.usage());
+ }
+
+}
diff --git a/args4j/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationVisitor.java b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationVisitor.java
new file mode 100644
index 0000000..c5e93d4
--- /dev/null
+++ b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationVisitor.java
@@ -0,0 +1,17 @@
+package org.kohsuke.args4j.apt;
+
+
+import org.kohsuke.args4j.Option;
+
+/**
+ * @author Kohsuke Kawaguchi
+ */
+interface AnnotationVisitor {
+ /**
+ * @deprecated as of 2.0.17 use {@link #onOption(OptionWithUsage)}
+ */
+ @Deprecated
+ void onOption( String name, String usage );
+ void onOption( OptionWithUsage optionWithUsage );
+ void done();
+}
diff --git a/args4j/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationVisitorReorderer.java b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationVisitorReorderer.java
new file mode 100644
index 0000000..735a2cd
--- /dev/null
+++ b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationVisitorReorderer.java
@@ -0,0 +1,42 @@
+package org.kohsuke.args4j.apt;
+
+import java.util.*;
+
+/**
+ * Reorders the annotation according to their canonical name
+ */
+public class AnnotationVisitorReorderer implements AnnotationVisitor {
+ private AnnotationVisitor target;
+
+ private List<OptionWithUsage> arguments = new ArrayList<OptionWithUsage>();
+
+ public AnnotationVisitorReorderer(AnnotationVisitor target) {
+ this.target = target;
+ }
+
+ public void onOption(String name, String usage) {
+ throw new UnsupportedOperationException("method not used");
+ }
+
+ public void onOption(OptionWithUsage optionWithUsage) {
+ arguments.add(optionWithUsage);
+ }
+
+ public void done() {
+ reorderArguments();
+ for (OptionWithUsage argument : arguments) {
+ target.onOption(argument);
+ }
+ target.done();
+ }
+
+ private void reorderArguments() {
+ Collections.sort(arguments, new NaturalOrderOptionsComparator());
+ }
+
+ private static class NaturalOrderOptionsComparator implements Comparator<OptionWithUsage> {
+ public int compare(OptionWithUsage o1, OptionWithUsage o2) {
+ return o1.option.name().compareTo(o2.option.name());
+ }
+ }
+}
diff --git a/args4j/args4j-tools/src/org/kohsuke/args4j/apt/HtmlWriter.java b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/HtmlWriter.java
new file mode 100644
index 0000000..b72fbc6
--- /dev/null
+++ b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/HtmlWriter.java
@@ -0,0 +1,41 @@
+package org.kohsuke.args4j.apt;
+
+import java.io.PrintWriter;
+import java.io.Writer;
+
+/**
+ * Writes the option list as HTML to a {@link Writer}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+class HtmlWriter implements AnnotationVisitor {
+ private final PrintWriter out;
+
+ public HtmlWriter(Writer out) {
+ this.out = new PrintWriter(out);
+ this.out.println("<table class='args4j-usage'>");
+ }
+
+ public void onOption(String name, String usage) {
+ out.println(" <tr>");
+ writeTag("td","args4j-option",name);
+ writeTag("td","args4j-usage",usage);
+ out.println(" </tr>");
+ }
+
+ public void onOption( OptionWithUsage optionWithUsage ) {
+ out.println(" <tr>");
+ writeTag("td","args4j-option",optionWithUsage.option.name());
+ writeTag("td","args4j-usage",optionWithUsage.usage);
+ out.println(" </tr>");
+ }
+
+ private void writeTag(String tag, String cssClass, String value) {
+ out.println(" <"+tag+" class='"+cssClass+"'><![CDATA["+value+"]]></"+tag+">");
+ }
+
+ public void done() {
+ out.println("</table>");
+ out.close();
+ }
+}
diff --git a/args4j/args4j-tools/src/org/kohsuke/args4j/apt/IsolatingClassLoader.java b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/IsolatingClassLoader.java
new file mode 100644
index 0000000..baff8fe
--- /dev/null
+++ b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/IsolatingClassLoader.java
@@ -0,0 +1,24 @@
+package org.kohsuke.args4j.apt;
+
+/**
+ * @author Kohsuke Kawaguchi
+ */
+public class IsolatingClassLoader extends ClassLoader {
+ public IsolatingClassLoader(ClassLoader parent) {
+ super(parent);
+ }
+
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ throw new ClassNotFoundException(name);
+ }
+
+ protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ if(!name.startsWith("org.kohsuke"))
+ return super.loadClass(name,resolve);
+ throw new ClassNotFoundException(name);
+ }
+
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ throw new ClassNotFoundException(name);
+ }
+}
diff --git a/args4j/args4j-tools/src/org/kohsuke/args4j/apt/Main.java b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/Main.java
new file mode 100644
index 0000000..3839447
--- /dev/null
+++ b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/Main.java
@@ -0,0 +1,108 @@
+package org.kohsuke.args4j.apt;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.Option;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Entry point that invokes APT.
+ * @author Kohsuke Kawaguchi
+ */
+public class Main {
+
+ @Option(name="-o",usage="output directory to place generated HTML/XML")
+ private File outDir = new File(".");
+
+ @Option(name="-mode",usage="output format. 'XML' 'TXT' or 'HTML'")
+ private Mode mode = Mode.HTML;
+
+ @Option(name="-res",usage="resource file name to obtain usage strings from.\n"+
+ "Using this option will cause Option.usage() to be used as a key to this resource")
+ private String resourceName = null;
+
+ @Option(name="-r")
+ private boolean hidden = false; // for testing
+
+ @Argument
+ private List<String> aptArgs = new ArrayList<String>();
+
+ public static void main(String[] args) throws Exception {
+ System.exit(new Main().run(args));
+ }
+
+ public int run(String[] args) throws Exception {
+ CmdLineParser parser = new CmdLineParser(this);
+ try {
+ parser.parseArgument(args);
+ } catch (CmdLineException e) {
+ System.err.println(e.getMessage());
+ printUsage(parser);
+ return -1;
+ }
+
+ if(aptArgs.isEmpty()) {
+ printUsage(parser);
+ return 0;
+ }
+
+ // we'll use a separate class loader to reload our classes,
+ // so parameters need to be set as system properties. Ouch!
+ System.setProperty("args4j.outdir",outDir.getPath());
+ System.setProperty("args4j.format",mode.name());
+ if(resourceName==null) resourceName = ""; // can't have null in properties
+ System.setProperty("args4j.resource",resourceName);
+
+ aptArgs.add(0,"-nocompile");
+
+ // locate tools.jar
+ ClassLoader cl = loadToolsJar();
+ Class<?> apt = cl.loadClass("com.sun.tools.apt.Main");
+ Method main = getProcessMethod(apt);
+ return (Integer)main.invoke(null,new Object[]{
+ cl.loadClass("org.kohsuke.args4j.apt.AnnotationProcessorFactoryImpl").newInstance(),
+ aptArgs.toArray(new String[0])});
+ }
+
+ private void printUsage(CmdLineParser parser) {
+ System.err.println("argsj-tools [options...] sourcefiles...");
+ System.err.println(" Generates the list of options in XML/HTML");
+ parser.printUsage(System.err);
+ }
+
+ private Method getProcessMethod(Class<?> apt) {
+ for(Method m : apt.getDeclaredMethods()) {
+ if(!m.getName().equals("process"))
+ continue;
+
+ Class<?>[] p = m.getParameterTypes();
+ if(p.length!=2) continue;
+
+ if(p[1]!=String[].class) continue;
+ if(!p[0].getName().endsWith("AnnotationProcessorFactory")) continue;
+
+ return m;
+ }
+ throw new Error("Unable to find the entry point to APT. Please use the latest version of JDK 5.0");
+ }
+
+ public ClassLoader loadToolsJar() {
+ File jreHome = new File(System.getProperty("java.home"));
+ File toolsJar = new File(jreHome.getParent(), "lib/tools.jar" );
+
+ try {
+ return new ReloadingClassLoader(new URLClassLoader(
+ new URL[]{ toolsJar.toURL() }, new IsolatingClassLoader(Main.class.getClassLoader())) );
+ } catch (MalformedURLException e) {
+ throw new Error(e);
+ }
+ }
+}
diff --git a/args4j/args4j-tools/src/org/kohsuke/args4j/apt/Mode.java b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/Mode.java
new file mode 100644
index 0000000..234254d
--- /dev/null
+++ b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/Mode.java
@@ -0,0 +1,8 @@
+package org.kohsuke.args4j.apt;
+
+/**
+ * @author Kohsuke Kawaguchi
+ */
+public enum Mode {
+ XML, HTML, TXT
+}
diff --git a/args4j/args4j-tools/src/org/kohsuke/args4j/apt/OptionWithUsage.java b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/OptionWithUsage.java
new file mode 100644
index 0000000..d0c72b4
--- /dev/null
+++ b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/OptionWithUsage.java
@@ -0,0 +1,17 @@
+package org.kohsuke.args4j.apt;
+
+import org.kohsuke.args4j.Option;
+
+/**
+ * @author Jerome Lacoste
+*/
+public class OptionWithUsage {
+ final Option option;
+ final String usage;
+
+ OptionWithUsage(Option option, String usage) {
+ this.option = option;
+ this.usage = usage;
+ }
+
+}
diff --git a/args4j/args4j-tools/src/org/kohsuke/args4j/apt/ReloadingClassLoader.java b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/ReloadingClassLoader.java
new file mode 100644
index 0000000..5bb7386
--- /dev/null
+++ b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/ReloadingClassLoader.java
@@ -0,0 +1,37 @@
+package org.kohsuke.args4j.apt;
+
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Used to isolate a child class loader from the parent classloader.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class ReloadingClassLoader extends ClassLoader {
+ protected ReloadingClassLoader(ClassLoader parent) {
+ super(parent);
+ }
+
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ String pathName = name.replace('.','/')+".class";
+
+ InputStream is = getParent().getResourceAsStream(pathName);
+ if (is==null)
+ throw new ClassNotFoundException(name);
+
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buf = new byte[1024];
+ int len;
+ while((len=is.read(buf))>=0)
+ baos.write(buf,0,len);
+
+ buf = baos.toByteArray();
+ return defineClass(name,buf,0,buf.length);
+ } catch (IOException e) {
+ throw new ClassNotFoundException(name,e);
+ }
+ }
+}
diff --git a/args4j/args4j-tools/src/org/kohsuke/args4j/apt/TxtWriter.java b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/TxtWriter.java
new file mode 100644
index 0000000..fc73b5c
--- /dev/null
+++ b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/TxtWriter.java
@@ -0,0 +1,40 @@
+package org.kohsuke.args4j.apt;
+
+import com.sun.mirror.declaration.ClassDeclaration;
+import org.kohsuke.args4j.Option;
+
+import java.io.PrintWriter;
+import java.io.Writer;
+
+/**
+ * Writes the option list as TXT to a {@link java.io.Writer}.
+ *
+ * @author Jerome Lacoste
+ */
+class TxtWriter implements AnnotationVisitor {
+ private final PrintWriter out;
+
+ public TxtWriter(Writer out, ClassDeclaration d) {
+ this.out = new PrintWriter(out);
+ this.out.println("Usage: " + d.getQualifiedName());
+ }
+
+ public void onOption(String name, String usage) {
+ throw new UnsupportedOperationException("never used");
+ }
+
+ public void onOption( OptionWithUsage optionWithUsage) {
+ out.println("\t" + optionWithUsage.option.name() + ": " + required(optionWithUsage.option) + optionWithUsage.usage);
+ }
+
+ private String required(Option option) {
+ if (option.required()) {
+ return "[required] ";
+ }
+ return "[optional] ";
+ }
+
+ public void done() {
+ out.close();
+ }
+}
diff --git a/args4j/args4j-tools/src/org/kohsuke/args4j/apt/XmlWriter.java b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/XmlWriter.java
new file mode 100644
index 0000000..1fcc5e5
--- /dev/null
+++ b/args4j/args4j-tools/src/org/kohsuke/args4j/apt/XmlWriter.java
@@ -0,0 +1,43 @@
+package org.kohsuke.args4j.apt;
+
+import com.sun.mirror.declaration.ClassDeclaration;
+
+import java.io.PrintWriter;
+import java.io.Writer;
+
+/**
+ * Writes the option list as XML to a {@link Writer}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+class XmlWriter implements AnnotationVisitor {
+ private final PrintWriter out;
+
+ public XmlWriter(Writer out, ClassDeclaration d) {
+ this.out = new PrintWriter(out);
+ this.out.println("<usage class=\'"+d.getQualifiedName()+"\'>");
+ }
+
+ public void onOption( String name, String usage ) {
+ out.println(" <option>");
+ writeTag("name",name);
+ writeTag("usage",usage);
+ out.println(" </option>");
+ }
+
+ public void onOption( OptionWithUsage optionWithUsage ) {
+ out.println(" <option>");
+ writeTag("name",optionWithUsage.option.name());
+ writeTag("usage",optionWithUsage.usage);
+ out.println(" </option>");
+ }
+
+ private void writeTag(String tag, String value) {
+ out.println(" <"+tag+"><![CDATA["+value+"]]></"+tag+">");
+ }
+
+ public void done() {
+ out.println("</usage>");
+ out.close();
+ }
+}
diff --git a/args4j/args4j-tools/test/org/kohsuke/args4j/apt/AnnotationVisitorReordererTest.java b/args4j/args4j-tools/test/org/kohsuke/args4j/apt/AnnotationVisitorReordererTest.java
new file mode 100644
index 0000000..c69adfa
--- /dev/null
+++ b/args4j/args4j-tools/test/org/kohsuke/args4j/apt/AnnotationVisitorReordererTest.java
@@ -0,0 +1,53 @@
+package org.kohsuke.args4j.apt;
+
+import junit.framework.TestCase;
+import org.kohsuke.args4j.Option;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class AnnotationVisitorReordererTest extends TestCase {
+
+ private AnnotationVisitor target;
+ private AnnotationVisitorReorderer reorderer;
+
+ final OptionWithUsage optionb = new OptionWithUsage(mockOption("-b"), "optionb");
+ final OptionWithUsage optiona = new OptionWithUsage(mockOption("-a"), "optiona");
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ target = mock(AnnotationVisitor.class);
+ reorderer = new AnnotationVisitorReorderer(target);
+ }
+
+ public void testReorderWithUnorderedAnnotations() throws Exception {
+ simulateOnOptionsThenDone(optionb, optiona);
+ verifyOptionsThenDone(optiona, optionb);
+ }
+
+ public void testReorderWithAlreadyOrderedAnnotations() throws Exception {
+ simulateOnOptionsThenDone(optiona, optionb);
+ verifyOptionsThenDone(optiona, optionb);
+ }
+
+ private void simulateOnOptionsThenDone(OptionWithUsage... options) {
+ for (OptionWithUsage option : options) {
+ reorderer.onOption(option);
+ }
+ reorderer.done();
+ }
+
+ private void verifyOptionsThenDone(OptionWithUsage... options) {
+ for (OptionWithUsage option : options) {
+ verify(target).onOption(option);
+ }
+ verify(target).done();
+ }
+
+ private Option mockOption(String name) {
+ Option option1 = mock(Option.class);
+ when(option1.name()).thenReturn(name);
+ return option1;
+ }
+}
diff --git a/args4j/args4j/LICENSE.txt b/args4j/args4j/LICENSE.txt
new file mode 100644
index 0000000..c5f4684
--- /dev/null
+++ b/args4j/args4j/LICENSE.txt
@@ -0,0 +1,25 @@
+Copyright (c) 2003, Kohsuke Kawaguchi
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+
diff --git a/args4j/args4j/examples/SampleAnt.java b/args4j/args4j/examples/SampleAnt.java
new file mode 100644
index 0000000..6b6dc10
--- /dev/null
+++ b/args4j/args4j/examples/SampleAnt.java
@@ -0,0 +1,211 @@
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.Option;
+
+import java.io.IOException;
+import java.io.File;
+import java.util.List;
+import java.util.Vector;
+import java.util.TreeMap;
+
+/**
+ * Showing the Ant command line interface as args4j annotations.
+ *
+ * @author
+ * Jan Materne
+ */
+// Field are are access by args4j per reflection. The compiler does not know that.
+// So catch these compiler warnings.
+@SuppressWarnings("unused")
+public class SampleAnt {
+
+ // 'normal' use
+ @Option(name="-help",usage="print this message")
+ private boolean help = false;
+
+ // Ant uses abbreviations - a second option to set the
+ // same attribute. Because only one @Option is allowed per element,
+ // we use a workaround: a setter gets the abbreviation
+ // A 'usage' would duplicate the info message, but without the possibility
+ // of '-h' is hidden.
+ @Option(name="-h")
+ private void setHelp(boolean h) { help = h; }
+
+
+
+ @Option(name="-projecthelp",usage="print project help information")
+ private boolean projecthelp;
+
+ @Option(name="-p")
+ private void setProjecthelp(boolean p) { projecthelp = p; }
+
+ @Option(name="-version",usage="print the version information and exit")
+ private boolean version;
+
+ @Option(name="-diagnostics",usage="print information that might be helpful to\ndiagnose or report problems.")
+ private boolean diagnostics;
+
+ @Option(name="-quiet",usage="be extra quiet")
+ private boolean quiet;
+
+ @Option(name="-q")
+ private void setQuiet(boolean q) { quiet = q; }
+
+ @Option(name="-verbose",usage="be extra verbose")
+ private boolean verbose;
+
+ @Option(name="-v")
+ private void setVerbose(boolean v) { verbose = v; }
+
+ @Option(name="-debug",usage="print debugging information")
+ private boolean debug;
+
+ @Option(name="-d")
+ private void setDebug(boolean d) { debug = d; }
+
+ @Option(name="-emacs",usage="produce logging information without adornments")
+ private boolean emacs;
+
+ @Option(name="-e")
+ private void setEmacs(boolean e) { emacs = e; }
+
+ @Option(name="-lib",usage="specifies a path to search for jars and classes",metaVar="<path>")
+ private void setLib(String s) {
+ String[] files = s.split(System.getProperty("path.separator"));
+ for (int i=0; i<files.length; i++) {
+ lib.add(new File(files[i]));
+ }
+ }
+ private List<File> lib = new Vector<File>();
+
+ @Option(name="-logger",usage="the class which is to perform logging",metaVar="<classname>")
+ private String logger;
+
+ @Option(name="-listener",usage="the class which is to perform",metaVar="<classname>")
+ private String listener;
+
+ @Option(name="-noinput",usage="do not allow interactive input")
+ private boolean noinput;
+
+ @Option(name="-buildfile",usage="use given buildfile",metaVar="<file>")
+ private File buildfile;
+
+ // Ant's original is
+ // -buildfile <file> use given buildfile
+ // -file <file> ''
+ // -f <file> ''
+ // How to handle this? Args4J prints the arguments sorted alphabetically.
+ @Option(name="-file",usage=" ''",metaVar="<file>")
+ private void setBuildfile1(File f) { buildfile = f; }
+
+ @Option(name="-f",usage=" ''",metaVar="<file>")
+ private void setBuildfile2(File f) { buildfile = f; }
+
+ //TODO: How to handle that?
+ // -D<property>=<value> use value for given property
+ private TreeMap<String,String> props = new TreeMap<String,String>();
+
+ @Option(name="-keep-going",usage="execute all targets that do not depend\non failed target(s)")
+ private boolean keepGoing;
+
+ @Option(name="-k")
+ private void setKeepGoing(boolean kg) { keepGoing = kg; }
+
+ @Option(name="-propertyfile",usage="load all properties from file with -D\nproperties taking precedence",metaVar="<name>")
+ private File propertyfile;
+
+ @Option(name="-inputhandler",usage="the class which will handle input requests",metaVar="<class>")
+ private String inputhandler;
+
+ //TODO: Another problem
+ // -find <file> (s)earch for buildfile towards the root of
+ // -s <file> the filesystem and use it
+ //problem is: info text has two lines and there are two lines for different option strings
+ @Option(name="-find",usage="(s)earch for buildfile towards the root of\nthe filesystem and use it",metaVar="<file>")
+ private File file;
+
+ @Option(name="-s",metaVar="<file>")
+ private void setFile(File f) { file = f; }
+
+ @Option(name="-nice",usage="A niceness value for the main thread:\n1 (lowest) to 10 (highest); 5 is the default")
+ private void setNice(int n) {
+ if (n>0 && n<11) nice = n;
+ }
+ private int nice = 5;
+
+ @Option(name="-nouserlib",usage="Run ant without using the jar files from\n${user.home}/.ant/lib")
+ private boolean nouserlib;
+
+ @Option(name="-noclasspath",usage="Run ant without using CLASSPATH")
+ private boolean noclasspath;
+
+ @Argument
+ private List<String> targets;
+
+
+
+ public static void main(String[] args) throws IOException {
+ SampleAnt bean = new SampleAnt();
+ try {
+ bean.parseArgs(args);
+ bean.showResult();
+ } catch (IOException ioe) {
+ //no-op
+ }
+ }
+
+ public void parseArgs(String[] args) throws IOException {
+ CmdLineParser parser = new CmdLineParser(this);
+ try {
+ parser.parseArgument(args);
+ } catch( CmdLineException e ) {
+ int start = e.getMessage().indexOf('"')+1;
+ int end = e.getMessage().lastIndexOf('"');
+ String wrongArgument = e.getMessage().substring(start, end);
+ System.err.println("Unknown argument: " + wrongArgument);
+ System.err.println("ant [options] [target [target2 [target3] ...]]");
+ parser.printUsage(System.err);
+ System.err.println();
+ throw new IOException();
+ }
+ }
+
+ public void showResult() {
+ System.out.println("SampleAnt was configured with...");
+ System.out.println(" help : " + help);
+ System.out.println(" projecthelp : " + projecthelp);
+ System.out.println(" version : " + version);
+ System.out.println(" diagnostics : " + diagnostics);
+ System.out.println(" quiet : " + quiet);
+ System.out.println(" verbose : " + verbose);
+ System.out.println(" debug : " + debug);
+ System.out.println(" emacs : " + emacs);
+ System.out.println(" lib");
+ for (File f : lib) {
+ System.out.println(" - " + f);
+ }
+ System.out.println(" logger : " + logger);
+ System.out.println(" listener : " + listener);
+ System.out.println(" noinput : " + noinput);
+ System.out.println(" buildfile : " + buildfile);
+ System.out.println(" properties");
+ for (String key : props.keySet()) {
+ System.out.println(" - " + key + " = " + props.get(key));
+ }
+ System.out.println(" keepGoing : " + keepGoing);
+ System.out.println(" propertyfile : " + propertyfile);
+ System.out.println(" inputhandler : " + inputhandler);
+ System.out.println(" buildfile : " + file);
+ System.out.println(" nice : " + nice);
+ System.out.println(" nouserlib : " + nouserlib);
+ System.out.println(" noclasspath : " + noclasspath);
+ System.out.println("");
+ System.out.println(" targets");
+ for (String t : targets) {
+ System.out.println(" - " + t);
+ }
+ System.out.println("");
+ }
+
+}
diff --git a/args4j/args4j/examples/SampleMain.java b/args4j/args4j/examples/SampleMain.java
new file mode 100644
index 0000000..7704cbf
--- /dev/null
+++ b/args4j/args4j/examples/SampleMain.java
@@ -0,0 +1,102 @@
+import static org.kohsuke.args4j.ExampleMode.ALL;
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.Option;
+import org.kohsuke.args4j.spi.BooleanOptionHandler;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Sample program that shows how you can use args4j.
+ *
+ * @author
+ * Kohsuke Kawaguchi (kk@kohsuke.org)
+ */
+public class SampleMain {
+
+ @Option(name="-r",usage="recursively run something")
+ private boolean recursive;
+
+ @Option(name="-o",usage="output to this file",metaVar="OUTPUT")
+ private File out = new File(".");
+
+ @Option(name="-str") // no usage
+ private String str = "(default value)";
+
+ @Option(name="-n",usage="repeat <n> times\nusage can have new lines in it and also it can be verrrrrrrrrrrrrrrrrry long")
+ private int num = -1;
+
+ // using 'handler=...' allows you to specify a custom OptionHandler
+ // implementation class. This allows you to bind a standard Java type
+ // with a non-standard option syntax
+ @Option(name="-custom",handler=BooleanOptionHandler.class,usage="boolean value for checking the custom handler")
+ private boolean data;
+
+ // receives other command line parameters than options
+ @Argument
+ private List<String> arguments = new ArrayList<String>();
+
+ public static void main(String[] args) throws IOException {
+ new SampleMain().doMain(args);
+ }
+
+ public void doMain(String[] args) throws IOException {
+ CmdLineParser parser = new CmdLineParser(this);
+
+ // if you have a wider console, you could increase the value;
+ // here 80 is also the default
+ parser.setUsageWidth(80);
+
+ try {
+ // parse the arguments.
+ parser.parseArgument(args);
+
+ // you can parse additional arguments if you want.
+ // parser.parseArgument("more","args");
+
+ // after parsing arguments, you should check
+ // if enough arguments are given.
+ if( arguments.isEmpty() )
+ throw new CmdLineException(parser,"No argument is given");
+
+ } catch( CmdLineException e ) {
+ // if there's a problem in the command line,
+ // you'll get this exception. this will report
+ // an error message.
+ System.err.println(e.getMessage());
+ System.err.println("java SampleMain [options...] arguments...");
+ // print the list of available options
+ parser.printUsage(System.err);
+ System.err.println();
+
+ // print option sample. This is useful some time
+ System.err.println(" Example: java SampleMain"+parser.printExample(ALL));
+
+ return;
+ }
+
+ // this will redirect the output to the specified output
+ System.out.println(out);
+
+ if( recursive )
+ System.out.println("-r flag is set");
+
+ if( data )
+ System.out.println("-custom flag is set");
+
+ System.out.println("-str was "+str);
+
+ if( num>=0 )
+ System.out.println("-n was "+num);
+
+ // access non-option arguments
+ System.out.println("other arguments are:");
+ for( String s : arguments )
+ System.out.println(s);
+ }
+}
diff --git a/args4j/args4j/examples/SampleStarter.bat b/args4j/args4j/examples/SampleStarter.bat
new file mode 100644
index 0000000..194ab21
--- /dev/null
+++ b/args4j/args4j/examples/SampleStarter.bat
@@ -0,0 +1,47 @@
+@echo off
+rem This shows how to use the Args4J-Starter class
+set EXE=java -classpath ../target/classes;../target/examples -Dmainclass=SampleStarter org.kohsuke.args4j.Starter
+
+
+rem Error: The system property 'mainclass' must contain the classname to start.
+echo java -classpath ../target/classes;../target/examples org.kohsuke.args4j.Starter
+java -classpath ../target/classes;../target/examples org.kohsuke.args4j.Starter
+echo --------------------------------------------------------------------------
+
+
+rem SampleStarter.run(String[])
+rem - args.length: 0
+rem SampleStarter: name='null' file='null'
+echo %EXE%
+%EXE%
+echo --------------------------------------------------------------------------
+
+
+rem "-wrong" is not a valid option
+rem mainclass [options]
+rem -file FILE : Sets the file
+rem -name VAL : Sets the name
+echo %EXE% -wrong
+%EXE% -wrong
+echo --------------------------------------------------------------------------
+
+
+rem SampleStarter.run(String[])
+rem - args.length: 2
+rem - -name
+rem - Test
+rem SampleStarter: name='Test' file='null'
+echo %EXE% -name Test
+%EXE% -name Test
+echo --------------------------------------------------------------------------
+
+
+rem SampleStarter.run(String[])
+rem - args.length: 4
+rem - -file
+rem - .
+rem - -name
+rem - Hello World
+rem SampleStarter: name='Hello World' file='C:\cvs-repository\args4j\args4j\examples\.'
+echo %EXE% -file . -name "Hello World"
+%EXE% -file . -name "Hello World" \ No newline at end of file
diff --git a/args4j/args4j/examples/SampleStarter.java b/args4j/args4j/examples/SampleStarter.java
new file mode 100644
index 0000000..29f8907
--- /dev/null
+++ b/args4j/args4j/examples/SampleStarter.java
@@ -0,0 +1,53 @@
+import java.io.File;
+
+import org.kohsuke.args4j.Option;
+
+/**
+ * Show the use of the args4j Starter class.
+ * @author Jan Materne
+ * @see SampleStarter.bat
+ */
+public class SampleStarter {
+
+ @Option(name = "-name",usage="Sets the name")
+ public String name;
+
+ @Option(name = "-file",usage="Sets the file")
+ public File file;
+
+ /*
+ * Just do something ...
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("SampleStarter:");
+ buffer.append(" name='");
+ buffer.append(name);
+ buffer.append("' file='");
+ buffer.append( (file!=null) ? file.getAbsoluteFile() : "null" );
+ buffer.append("'");
+ return buffer.toString();
+ }
+
+ /**
+ * First try is to run this <tt>run()</tt> method.
+ */
+ public void xrun() {
+ System.out.println("SampleStarter.run()");
+ System.out.println(this);
+ }
+
+ /**
+ * If you want to get the args-Array from the command line
+ * use the signature <tt>run(String[] args)</tt>. But then there must
+ * not be a run() because that is executed prior to this.
+ * @param args The arguments as specified on the command line
+ */
+ public void run(String[] args) {
+ System.out.println("SampleStarter.run(String[])");
+ System.out.println("- args.length: " + args.length);
+ for (String arg : args) System.out.println(" - " + arg);
+ System.out.println(this);
+ }
+
+}
diff --git a/args4j/args4j/maven.xml b/args4j/args4j/maven.xml
new file mode 100644
index 0000000..462931f
--- /dev/null
+++ b/args4j/args4j/maven.xml
@@ -0,0 +1,23 @@
+<project xmlns:j="jelly:core" xmlns:u="jelly:util">
+
+ <postGoal name="dist:prepare-bin-filesystem">
+ <!-- copy additional files into the distribution zip/tgz -->
+ <copy todir="${maven.dist.bin.archive.dir}/${maven.final.name}/examples">
+ <fileset dir="${basedir}/examples"/>
+ </copy>
+ </postGoal>
+
+ <postGoal name="test:compile">
+ <echo>compile the examples</echo>
+ <mkdir dir="${basedir}/target/examples"/>
+ <javac srcdir="${basedir}/examples"
+ destdir="${basedir}/target/examples"
+ classpath="${basedir}/target/classes">
+ </javac>
+ <echo>Copy test resources</echo>
+ <copy todir="target/test-classes">
+ <fileset dir="test" excludes="**/*.java"/>
+ </copy>
+ </postGoal>
+
+</project> \ No newline at end of file
diff --git a/args4j/args4j/pom.xml b/args4j/args4j/pom.xml
new file mode 100644
index 0000000..6a10c62
--- /dev/null
+++ b/args4j/args4j/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>args4j</groupId>
+ <artifactId>args4j-site</artifactId>
+ <version>2.0.22</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>args4j</artifactId>
+ <name>args4j</name>
+
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <testSourceDirectory>test</testSourceDirectory>
+ <resources>
+ <resource>
+ <directory>src</directory>
+ <includes>
+ <include>**/*.properties</include>
+ <include>META-INF/services/*</include>
+ </includes>
+ </resource>
+ </resources>
+ <testResources>
+ <testResource>
+ <directory>test</directory>
+ <includes>
+ <include>**/*.xml</include>
+ </includes>
+ </testResource>
+ </testResources>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/args4j/args4j/project.properties b/args4j/args4j/project.properties
new file mode 100644
index 0000000..6536eea
--- /dev/null
+++ b/args4j/args4j/project.properties
@@ -0,0 +1 @@
+maven.javanet.release.folder=/dist/runtime
diff --git a/args4j/args4j/project.xml b/args4j/args4j/project.xml
new file mode 100644
index 0000000..ef119ba
--- /dev/null
+++ b/args4j/args4j/project.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+ <extend>../project.xml</extend>
+
+ <pomVersion>3</pomVersion>
+ <name>args4j</name>
+ <artifactId>args4j</artifactId>
+
+ <dependencies>
+ <!-- needed for the test cases inside this Maven project -->
+ <dependency>
+ <id>junit</id>
+ <version>3.8.1</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <nagEmailAddress>kk@kohsuke.org</nagEmailAddress>
+
+ <sourceDirectory>src</sourceDirectory>
+ <unitTestSourceDirectory>test</unitTestSourceDirectory>
+
+ <!-- Resources that are packaged up inside the JAR file -->
+ <resources>
+ <resource>
+ <directory>src</directory>
+ <includes>
+ <include>**/*.properties</include>
+ <include>META-INF/services/*</include>
+ </includes>
+ </resource>
+ </resources>
+
+ <!-- Unit test classes -->
+ <unitTest>
+ <includes>
+ <include>**/*Test.java</include>
+ </includes>
+ </unitTest>
+ </build>
+</project> \ No newline at end of file
diff --git a/args4j/args4j/src/org/kohsuke/args4j/Argument.java b/args4j/args4j/src/org/kohsuke/args4j/Argument.java
new file mode 100644
index 0000000..12e9175
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/Argument.java
@@ -0,0 +1,62 @@
+package org.kohsuke.args4j;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import org.kohsuke.args4j.spi.OptionHandler;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+
+/**
+ * Argument of the command line.
+ *
+ * This works mostly like {@link Option} except the following differences.
+ *
+ * <ol>
+ * <li>Arguments have an index about their relative position on the command line.
+ * </ol>
+ *
+ * @author Kohsuke Kawaguchi
+ * @author Mark Sinke
+ */
+@Retention(RUNTIME)
+@Target({FIELD,METHOD,PARAMETER})
+public @interface Argument {
+ /**
+ * See {@link Option#usage()}.
+ */
+ String usage() default "";
+ /**
+ * See {@link Option#metaVar()}.
+ */
+ String metaVar() default "";
+ /**
+ * See {@link Option#required()}.
+ */
+ boolean required() default false;
+
+ /**
+ * See {@link Option#handler()}.
+ */
+ Class<? extends OptionHandler> handler() default OptionHandler.class;
+
+ /**
+ * Position of the argument.
+ *
+ * <p>
+ * If you define multiple single value properties to bind to arguments,
+ * they should have index=0, index=1, index=2, ... and so on.
+ *
+ * <p>
+ * Multi value properties bound to arguments must be always the last entry.
+ */
+ int index() default 0;
+
+ /**
+ * See {@link Option#multiValued()}.
+ */
+ boolean multiValued() default false;
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/ClassParser.java b/args4j/args4j/src/org/kohsuke/args4j/ClassParser.java
new file mode 100644
index 0000000..047415e
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/ClassParser.java
@@ -0,0 +1,43 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.spi.MethodSetter;
+import org.kohsuke.args4j.spi.Setters;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * Parser for analyzing Args4J annotations in the class hierarchy.
+ *
+ * This can be used to feed option bindings that span across multiple instances.
+ *
+ * @author Jan Materne
+ */
+public class ClassParser {
+ public void parse(Object bean, CmdLineParser parser) {
+ // recursively process all the methods/fields.
+ for( Class c=bean.getClass(); c!=null; c=c.getSuperclass()) {
+ for( Method m : c.getDeclaredMethods() ) {
+ Option o = m.getAnnotation(Option.class);
+ if(o!=null) {
+ parser.addOption(new MethodSetter(parser,bean,m), o);
+ }
+ Argument a = m.getAnnotation(Argument.class);
+ if(a!=null) {
+ parser.addArgument(new MethodSetter(parser,bean,m), a);
+ }
+ }
+
+ for( Field f : c.getDeclaredFields() ) {
+ Option o = f.getAnnotation(Option.class);
+ if(o!=null) {
+ parser.addOption(Setters.create(f,bean),o);
+ }
+ Argument a = f.getAnnotation(Argument.class);
+ if(a!=null) {
+ parser.addArgument(Setters.create(f,bean), a);
+ }
+ }
+ }
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/CmdLineException.java b/args4j/args4j/src/org/kohsuke/args4j/CmdLineException.java
new file mode 100644
index 0000000..7151801
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/CmdLineException.java
@@ -0,0 +1,64 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.spi.OptionHandler;
+
+/**
+ * Signals an error in the user input.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class CmdLineException extends Exception {
+ private static final long serialVersionUID = -8574071211991372980L;
+
+ private CmdLineParser parser;
+
+ /**
+ * @deprecated
+ * Use {@link #CmdLineException(CmdLineParser, String)}
+ */
+ public CmdLineException(String message) {
+ super(message);
+ }
+
+ /**
+ * @deprecated
+ * Use {@link #CmdLineException(CmdLineParser, String, Throwable)}
+ */
+ public CmdLineException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * @deprecated
+ * Use {@link #CmdLineException(CmdLineParser, Throwable)}
+ */
+ public CmdLineException(Throwable cause) {
+ super(cause);
+ }
+
+ public CmdLineException(CmdLineParser parser, String message) {
+ super(message);
+ this.parser = parser;
+ }
+
+ public CmdLineException(CmdLineParser parser, String message, Throwable cause) {
+ super(message, cause);
+ this.parser = parser;
+ }
+
+ public CmdLineException(CmdLineParser parser, Throwable cause) {
+ super(cause);
+ this.parser = parser;
+ }
+
+ /**
+ * Obtains the {@link CmdLineParser} that triggered an exception.
+ *
+ * <p>
+ * Unless you have legacy {@link OptionHandler} that doesn't pass in this information
+ * when it throws an exception, this method should always return a non-null value. a
+ */
+ public CmdLineParser getParser() {
+ return parser;
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/CmdLineParser.java b/args4j/args4j/src/org/kohsuke/args4j/CmdLineParser.java
new file mode 100644
index 0000000..7829416
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/CmdLineParser.java
@@ -0,0 +1,622 @@
+package org.kohsuke.args4j;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import org.kohsuke.args4j.spi.BooleanOptionHandler;
+import org.kohsuke.args4j.spi.ByteOptionHandler;
+import org.kohsuke.args4j.spi.CharOptionHandler;
+import org.kohsuke.args4j.spi.DoubleOptionHandler;
+import org.kohsuke.args4j.spi.EnumOptionHandler;
+import org.kohsuke.args4j.spi.FileOptionHandler;
+import org.kohsuke.args4j.spi.FloatOptionHandler;
+import org.kohsuke.args4j.spi.IntOptionHandler;
+import org.kohsuke.args4j.spi.LongOptionHandler;
+import org.kohsuke.args4j.spi.MapOptionHandler;
+import org.kohsuke.args4j.spi.OptionHandler;
+import org.kohsuke.args4j.spi.Parameters;
+import org.kohsuke.args4j.spi.Setter;
+import org.kohsuke.args4j.spi.ShortOptionHandler;
+import org.kohsuke.args4j.spi.StringOptionHandler;
+import org.kohsuke.args4j.spi.URIOptionHandler;
+import org.kohsuke.args4j.spi.URLOptionHandler;
+
+
+/**
+ * Command line argument owner.
+ *
+ * <p>
+ * For a typical usage, see <a href="https://args4j.dev.java.net/source/browse/args4j/args4j/examples/SampleMain.java?view=markup">this example</a>.
+ *
+ * @author
+ * Kohsuke Kawaguchi (kk@kohsuke.org)
+ */
+public class CmdLineParser {
+ /**
+ * Discovered {@link OptionHandler}s for options.
+ */
+ private final List<OptionHandler> options = new ArrayList<OptionHandler>();
+
+ /**
+ * Discovered {@link OptionHandler}s for arguments.
+ */
+ private final List<OptionHandler> arguments = new ArrayList<OptionHandler>();
+
+ private boolean parsingOptions = true;
+ private OptionHandler currentOptionHandler = null;
+
+ /**
+ * The length of a usage line.
+ * If the usage message is longer than this value, the parser
+ * wraps the line. Defaults to 80.
+ */
+ private int usageWidth = 80;
+
+ /**
+ * Creates a new command line owner that
+ * parses arguments/options and set them into
+ * the given object.
+ *
+ * @param bean
+ * instance of a class annotated by {@link Option} and {@link Argument}.
+ * this object will receive values. If this is null, the processing will
+ * be skipped, which is useful if you'd like to feed metadata from other sources.
+ *
+ * @throws IllegalAnnotationError
+ * if the option bean class is using args4j annotations incorrectly.
+ */
+ public CmdLineParser(Object bean) {
+ // A 'return' in the constructor just skips the rest of the implementation
+ // and returns the new object directly.
+ if (bean==null) return;
+
+ // Parse the metadata and create the setters
+ new ClassParser().parse(bean,this);
+
+ // for display purposes, we like the arguments in argument order, but the options in alphabetical order
+ Collections.sort(options, new Comparator<OptionHandler>() {
+ public int compare(OptionHandler o1, OptionHandler o2) {
+ return o1.option.toString().compareTo(o2.option.toString());
+ }
+ });
+ }
+
+ /**
+ * Programmatically defines an argument (instead of reading it from annotations like you normally do.)
+ *
+ * @param setter the setter for the type
+ * @param a the Argument
+ */
+ public void addArgument(Setter setter, Argument a) {
+ OptionHandler h = createOptionHandler(new OptionDef(a,setter.isMultiValued()),setter);
+ int index = a.index();
+ // make sure the argument will fit in the list
+ while (index >= arguments.size()) {
+ arguments.add(null);
+ }
+ if(arguments.get(index)!=null) {
+ throw new IllegalAnnotationError(Messages.MULTIPLE_USE_OF_ARGUMENT.format(index));
+ }
+ arguments.set(index,h);
+ }
+
+ /**
+ * Programmatically defines an option (instead of reading it from annotations like you normally do.)
+ *
+ * @param setter the setter for the type
+ * @param o the Option
+ */
+ public void addOption(Setter setter, Option o) {
+ checkOptionNotInMap(o.name());
+ for (String alias : o.aliases()) {
+ checkOptionNotInMap(alias);
+ }
+ options.add(createOptionHandler(new NamedOptionDef(o, setter.isMultiValued()), setter));
+ }
+
+ public List<OptionHandler> getArguments() {
+ return arguments;
+ }
+
+ private void checkOptionNotInMap(String name) throws IllegalAnnotationError {
+ if(findOptionByName(name)!=null) {
+ throw new IllegalAnnotationError(Messages.MULTIPLE_USE_OF_OPTION.format(name));
+ }
+ }
+
+ /**
+ * Creates an {@link OptionHandler} that handles the given {@link Option} annotation
+ * and the {@link Setter} instance.
+ */
+ @SuppressWarnings("unchecked")
+ protected OptionHandler createOptionHandler(OptionDef o, Setter setter) {
+
+ Constructor<? extends OptionHandler> handlerType;
+ Class<? extends OptionHandler> h = o.handler();
+
+ if(h==OptionHandler.class) {
+ // infer the type
+
+ // enum is the special case
+ Class t = setter.getType();
+ if(Enum.class.isAssignableFrom(t))
+ return new EnumOptionHandler(this,o,setter,t);
+
+ handlerType = handlerClasses.get(t);
+ if(handlerType==null)
+ throw new IllegalAnnotationError(Messages.UNKNOWN_HANDLER.format(t));
+ } else {
+ handlerType = getConstructor(h);
+ }
+
+ try {
+ return handlerType.newInstance(this,o,setter);
+ } catch (InstantiationException e) {
+ throw new IllegalAnnotationError(e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAnnotationError(e);
+ } catch (InvocationTargetException e) {
+ throw new IllegalAnnotationError(e);
+ }
+ }
+
+ /**
+ * Formats a command line example into a string.
+ *
+ * See {@link #printExample(ExampleMode, ResourceBundle)} for more details.
+ *
+ * @param mode
+ * must not be null.
+ * @return
+ * always non-null.
+ */
+ public String printExample(ExampleMode mode) {
+ return printExample(mode,null);
+ }
+
+ /**
+ * Formats a command line example into a string.
+ *
+ * <p>
+ * This method produces a string like " -d &lt;dir> -v -b",
+ * which is useful for printing a command line example, perhaps
+ * as a part of the usage screen.
+ *
+ *
+ * @param mode
+ * One of the {@link ExampleMode} constants. Must not be null.
+ * This determines what option should be a part of the returned string.
+ * @param rb
+ * If non-null, meta variables (&lt;dir> in the above example)
+ * is treated as a key to this resource bundle, and the associated
+ * value is printed. See {@link Option#metaVar()}. This is to support
+ * localization.
+ *
+ * Passing <tt>null</tt> would print {@link Option#metaVar()} directly.
+ * @return
+ * always non-null. If there's no option, this method returns
+ * just the empty string "". Otherwise, this method returns a
+ * string that contains a space at the beginning (but not at the end.)
+ * This allows you to do something like:
+ *
+ * <pre>System.err.println("java -jar my.jar"+parser.printExample(REQUIRED)+" arg1 arg2");</pre>
+ */
+ public String printExample(ExampleMode mode,ResourceBundle rb) {
+ StringBuilder buf = new StringBuilder();
+
+ for (OptionHandler h : options) {
+ OptionDef option = h.option;
+ if(option.usage().length()==0) continue; // ignore
+ if(!mode.print(option)) continue;
+
+ buf.append(' ');
+ buf.append(h.getNameAndMeta(rb));
+ }
+
+ return buf.toString();
+ }
+
+ /**
+ * Prints the list of options and their usages to the screen.
+ *
+ * <p>
+ * This is a convenience method for calling {@code printUsage(new OutputStreamWriter(out),null)}
+ * so that you can do {@code printUsage(System.err)}.
+ */
+ public void printUsage(OutputStream out) {
+ printUsage(new OutputStreamWriter(out),null);
+ }
+
+ /**
+ * Prints the list of options and their usages to the screen.
+ *
+ * @param rb
+ * if this is non-null, {@link Option#usage()} is treated
+ * as a key to obtain the actual message from this resource bundle.
+ */
+ public void printUsage(Writer out, ResourceBundle rb) {
+ PrintWriter w = new PrintWriter(out);
+ // determine the length of the option + metavar first
+ int len = 0;
+ for (OptionHandler h : arguments) {
+ int curLen = getPrefixLen(h, rb);
+ len = Math.max(len,curLen);
+ }
+ for (OptionHandler h: options) {
+ int curLen = getPrefixLen(h, rb);
+ len = Math.max(len,curLen);
+ }
+
+ // then print
+ for (OptionHandler h : arguments) {
+ printOption(w, h, len, rb);
+ }
+ for (OptionHandler h : options) {
+ printOption(w, h, len, rb);
+ }
+
+ w.flush();
+ }
+
+ /**
+ * Prints the usage information for a given option.
+ * @param out Writer to write into
+ * @param handler handler where to receive the informations
+ * @param len Maximum length of metadata column
+ * @param rb ResourceBundle for I18N
+ */
+ private void printOption(PrintWriter out, OptionHandler handler, int len, ResourceBundle rb) {
+ // Hiding options without usage information
+ if (handler.option.usage() == null || handler.option.usage().length() == 0) {
+ return;
+ }
+
+ // What is the width of the two data columns
+ int widthMetadata = Math.min(len, (usageWidth - 4) / 2);
+ int widthUsage = usageWidth - 4 - widthMetadata;
+
+ // Line wrapping
+ List<String> namesAndMetas = wrapLines(handler.getNameAndMeta(rb), widthMetadata);
+ List<String> usages = wrapLines(localize(handler.option.usage(),rb), widthUsage);
+
+ // Output
+ for(int i=0; i<Math.max(namesAndMetas.size(), usages.size()); i++) {
+ String nameAndMeta = (i >= namesAndMetas.size()) ? "" : namesAndMetas.get(i);
+ String usage = (i >= usages.size()) ? "" : usages.get(i);
+ String format = (nameAndMeta.length() > 0)
+ ? " %1$-" + widthMetadata + "s : %2$-1s"
+ : " %1$-" + widthMetadata + "s %2$-1s";
+ String output = String.format(format, nameAndMeta, usage);
+ out.println(output);
+ }
+ }
+
+ private String localize(String s, ResourceBundle rb) {
+ if(rb!=null) return rb.getString(s);
+ return s;
+ }
+
+ /**
+ * Wraps a line so that the resulting parts are not longer than a given maximum length.
+ * @param line Line to wrap
+ * @param maxLength maximum length for the resulting parts
+ * @return list of all wrapped parts
+ */
+ private List<String> wrapLines(String line, final int maxLength) {
+ List<String> rv = new ArrayList<String>();
+ for (String restOfLine : line.split("\\n")) {
+ while (restOfLine.length() > maxLength) {
+ // try to wrap at space, but don't try too hard as some languages don't even have whitespaces.
+ int lineLength;
+ String candidate = restOfLine.substring(0, maxLength);
+ int sp=candidate.lastIndexOf(' ');
+ if(sp>maxLength*3/4) lineLength=sp;
+ else lineLength=maxLength;
+ rv.add(restOfLine.substring(0, lineLength));
+ restOfLine = restOfLine.substring(lineLength).trim();
+ }
+ rv.add(restOfLine);
+ }
+ return rv;
+ }
+
+ private int getPrefixLen(OptionHandler h, ResourceBundle rb) {
+ if(h.option.usage().length()==0)
+ return 0;
+
+ return h.getNameAndMeta(rb).length();
+ }
+
+ /**
+ * Essentially a pointer over a {@link String} array.
+ * Can move forward, can look ahead.
+ */
+ private class CmdLineImpl implements Parameters {
+ private final String[] args;
+ private int pos;
+
+ CmdLineImpl( String[] args ) {
+ this.args = args;
+ pos = 0;
+ }
+
+ protected boolean hasMore() {
+ return pos<args.length;
+ }
+
+ protected String getCurrentToken() {
+ return args[pos];
+ }
+
+ private void proceed( int n ) {
+ pos += n;
+ }
+
+ public String getParameter(int idx) throws CmdLineException {
+ if( pos+idx>=args.length )
+ throw new CmdLineException(CmdLineParser.this, Messages.MISSING_OPERAND.format(getOptionName()));
+ return args[pos+idx];
+ }
+
+ public int size() {
+ return args.length-pos;
+ }
+ }
+
+ private String getOptionName() {
+ return currentOptionHandler.option.toString();
+ }
+
+ /**
+ * Same as {@link #parseArgument(String[])}
+ */
+ public void parseArgument(Collection<String> args) throws CmdLineException {
+ parseArgument(args.toArray(new String[args.size()]));
+ }
+
+ /**
+ * Parses the command line arguments and set them to the option bean
+ * given in the constructor.
+ *
+ * @param args arguments to parse
+ *
+ * @throws CmdLineException
+ * if there's any error parsing arguments, or if
+ * {@link Option#required() required} option was not given.
+ */
+ public void parseArgument(final String... args) throws CmdLineException {
+ CmdLineImpl cmdLine = new CmdLineImpl(args);
+
+ Set<OptionHandler> present = new HashSet<OptionHandler>();
+ int argIndex = 0;
+
+ while( cmdLine.hasMore() ) {
+ String arg = cmdLine.getCurrentToken();
+ if( isOption(arg) ) {
+ boolean isKeyValuePair = arg.indexOf('=')!=-1;
+ // parse this as an option.
+ currentOptionHandler = isKeyValuePair ? findOptionHandler(arg) : findOptionByName(arg);
+
+ if(currentOptionHandler==null) {
+ // TODO: insert dynamic handler processing
+ throw new CmdLineException(this, Messages.UNDEFINED_OPTION.format(arg));
+ }
+
+ // known option; skip its name
+ cmdLine.proceed(1);
+ } else {
+ if (argIndex >= arguments.size()) {
+ Messages msg = arguments.size() == 0 ? Messages.NO_ARGUMENT_ALLOWED : Messages.TOO_MANY_ARGUMENTS;
+ throw new CmdLineException(this, msg.format(arg));
+ }
+
+ // known argument
+ currentOptionHandler = arguments.get(argIndex);
+ if (!currentOptionHandler.option.isMultiValued())
+ argIndex++;
+ }
+ int diff = currentOptionHandler.parseArguments(cmdLine);
+ cmdLine.proceed(diff);
+ present.add(currentOptionHandler);
+ }
+
+ // make sure that all mandatory options are present
+ for (OptionHandler handler : options)
+ if(handler.option.required() && !present.contains(handler))
+ throw new CmdLineException(this, Messages.REQUIRED_OPTION_MISSING.format(handler.option.toString()));
+
+ // make sure that all mandatory arguments are present
+ for (OptionHandler handler : arguments)
+ if(handler.option.required() && !present.contains(handler))
+ throw new CmdLineException(this, Messages.REQUIRED_ARGUMENT_MISSING.format(handler.option.toString()));
+ }
+
+ private OptionHandler findOptionHandler(String name) {
+ OptionHandler handler = findOptionByName(name);
+ if (handler==null) {
+ // Have not found by its name, maybe its a property?
+ // Search for parts of the name (=prefix) - most specific first
+ for (int i=name.length(); i>1; i--) {
+ String prefix = name.substring(0, i);
+ Map<String,OptionHandler> possibleHandlers = filter(options, prefix);
+ handler = possibleHandlers.get(prefix);
+ if (handler!=null) return handler;
+ }
+ }
+ return handler;
+ }
+
+ /**
+ * Finds a registered OptionHandler by its name or its alias.
+ * @param name name
+ * @return the OptionHandler or <tt>null</tt>
+ */
+ private OptionHandler findOptionByName(String name) {
+ for (OptionHandler h : options) {
+ NamedOptionDef option = (NamedOptionDef)h.option;
+ if (name.equals(option.name())) {
+ return h;
+ }
+ for (String alias : option.aliases()) {
+ if (name.equals(alias)) {
+ return h;
+ }
+ }
+ }
+ return null;
+ }
+
+
+ private Map<String,OptionHandler> filter(List<OptionHandler> opt, String keyFilter) {
+ Map<String,OptionHandler> rv = new TreeMap<String,OptionHandler>();
+ for (OptionHandler h : opt) {
+ if (opt.toString().startsWith(keyFilter)) rv.put(opt.toString(), h);
+ }
+ return rv;
+ }
+
+
+ /**
+ * Returns true if the given token is an option
+ * (as opposed to an argument.)
+ */
+ protected boolean isOption(String arg) {
+ return parsingOptions && arg.startsWith("-");
+ }
+
+
+ /**
+ * All {@link OptionHandler}s known to the {@link CmdLineParser}.
+ *
+ * Constructors of {@link OptionHandler}-derived class keyed by their supported types.
+ */
+ private static final Map<Class,Constructor<? extends OptionHandler>> handlerClasses =
+ Collections.synchronizedMap(new HashMap<Class,Constructor<? extends OptionHandler>>());
+
+ /**
+ * Registers a user-defined {@link OptionHandler} class with args4j.
+ *
+ * <p>
+ * This method allows users to extend the behavior of args4j by writing
+ * their own {@link OptionHandler} implementation.
+ *
+ * @param valueType
+ * The specified handler is used when the field/method annotated by {@link Option}
+ * is of this type.
+ * @param handlerClass
+ * This class must have the constructor that has the same signature as
+ * {@link OptionHandler#OptionHandler(CmdLineParser, OptionDef, Setter)}
+ */
+ public static void registerHandler( Class valueType, Class<? extends OptionHandler> handlerClass ) {
+ if(valueType==null || handlerClass==null)
+ throw new IllegalArgumentException();
+ if(!OptionHandler.class.isAssignableFrom(handlerClass))
+ throw new IllegalArgumentException(Messages.NO_OPTIONHANDLER.format());
+
+ Constructor<? extends OptionHandler> c = getConstructor(handlerClass);
+ handlerClasses.put(valueType,c);
+ }
+
+ private static Constructor<? extends OptionHandler> getConstructor(Class<? extends OptionHandler> handlerClass) {
+ try {
+ return handlerClass.getConstructor(CmdLineParser.class, OptionDef.class, Setter.class);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalArgumentException(Messages.NO_CONSTRUCTOR_ON_HANDLER.format(handlerClass));
+ }
+ }
+
+ static {
+ registerHandler(Boolean.class,BooleanOptionHandler.class);
+ registerHandler(boolean.class,BooleanOptionHandler.class);
+ registerHandler(File.class,FileOptionHandler.class);
+ registerHandler(URL.class, URLOptionHandler.class);
+ registerHandler(URI.class, URIOptionHandler.class);
+ registerHandler(Integer.class,IntOptionHandler.class);
+ registerHandler(int.class,IntOptionHandler.class);
+ registerHandler(Double.class, DoubleOptionHandler.class);
+ registerHandler(double.class,DoubleOptionHandler.class);
+ registerHandler(String.class,StringOptionHandler.class);
+ registerHandler(Byte.class, ByteOptionHandler.class);
+ registerHandler(byte.class, ByteOptionHandler.class);
+ registerHandler(Character.class, CharOptionHandler.class);
+ registerHandler(char.class, CharOptionHandler.class);
+ registerHandler(Float.class, FloatOptionHandler.class);
+ registerHandler(float.class, FloatOptionHandler.class);
+ registerHandler(Long.class, LongOptionHandler.class);
+ registerHandler(long.class, LongOptionHandler.class);
+ registerHandler(Short.class, ShortOptionHandler.class);
+ registerHandler(short.class, ShortOptionHandler.class);
+ // enum is a special case
+ registerHandler(Map.class,MapOptionHandler.class);
+ }
+
+ public void setUsageWidth(int usageWidth) {
+ this.usageWidth = usageWidth;
+ }
+
+ public void stopOptionParsing() {
+ parsingOptions = false;
+ }
+
+ /**
+ * Prints a single-line usage to the screen.
+ *
+ * <p>
+ * This is a convenience method for calling {@code printUsage(new OutputStreamWriter(out),null)}
+ * so that you can do {@code printUsage(System.err)}.
+ */
+ public void printSingleLineUsage(OutputStream out) {
+ printSingleLineUsage(new OutputStreamWriter(out),null);
+ }
+
+ /**
+ * Prints a single-line usage to the screen.
+ *
+ * @param rb
+ * if this is non-null, {@link Option#usage()} is treated
+ * as a key to obtain the actual message from this resource bundle.
+ */
+ public void printSingleLineUsage(Writer w, ResourceBundle rb) {
+ PrintWriter pw = new PrintWriter(w);
+ for (OptionHandler h : arguments) {
+ printSingleLineOption(pw, h, rb);
+ }
+ for (OptionHandler h : options) {
+ printSingleLineOption(pw, h, rb);
+ }
+ pw.flush();
+ }
+
+ private void printSingleLineOption(PrintWriter pw, OptionHandler h, ResourceBundle rb) {
+ pw.print(' ');
+ if (!h.option.required())
+ pw.print('[');
+ pw.print(h.getNameAndMeta(rb));
+ if (h.option.isMultiValued()) {
+ pw.print(" ...");
+ }
+ if (!h.option.required())
+ pw.print(']');
+ }
+
+ private static final Logger LOGGER = Logger.getLogger(CmdLineParser.class.getName());
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/Config.java b/args4j/args4j/src/org/kohsuke/args4j/Config.java
new file mode 100644
index 0000000..005f3d6
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/Config.java
@@ -0,0 +1,84 @@
+package org.kohsuke.args4j;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.kohsuke.args4j.spi.ConfigElement;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+
+/**
+ * Metadataconfiguration.
+ * This class holds all metadata for a class, mainly a list of @Options and @Arguments.
+ *
+ * @author Jan Materne
+ */
+public class Config {
+
+ /** All @Options. */
+ public List<ConfigElement> options = new ArrayList<ConfigElement>();;
+
+ /** All @Arguments. */
+ public List<ConfigElement> arguments = new ArrayList<ConfigElement>();
+
+
+ /**
+ * SAX-Handler for reading the configuration file.
+ * @author Jan Materne
+ */
+ public class ConfigHandler extends DefaultHandler {
+ public ConfigHandler(Config config) {
+ super();
+ this.config = config;
+ }
+
+ Config config;
+ ConfigElement currentCE;
+
+ @Override
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) throws SAXException {
+ if (qName.equals("option") || qName.equals("argument")) {
+ currentCE = new ConfigElement();
+ currentCE.field = attributes.getValue("field");
+ currentCE.handler = attributes.getValue("handler");
+ currentCE.metavar = attributes.getValue("metavar");
+ currentCE.method = attributes.getValue("method");
+ currentCE.name = attributes.getValue("name");
+ currentCE.usage = attributes.getValue("usage");
+ currentCE.multiValued = Boolean.getBoolean(attributes.getValue("multiValued"));
+ currentCE.required = Boolean.getBoolean(attributes.getValue("required"));
+ if (attributes.getValue("aliases") != null) {
+ currentCE.aliases = attributes.getValue("aliases").split(",");
+ } else {
+ currentCE.aliases = new String[]{};
+ }
+ (qName.equals("option") ? config.options : config.arguments).add(currentCE);
+ }
+ }
+ }
+
+ /**
+ * Parses a XML file and returns a Config object holding the information.
+ * @param xml source of the xml data
+ * @return
+ * @throws IOException
+ * @throws SAXException
+ */
+ public static Config parse(InputSource xml) throws IOException, SAXException {
+ Config rv = new Config();
+ XMLReader reader = XMLReaderFactory.createXMLReader();
+ ConfigHandler handler = rv.new ConfigHandler(rv);
+ reader.setContentHandler(handler);
+ reader.parse(xml);
+ return rv;
+ }
+
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/ExampleMode.java b/args4j/args4j/src/org/kohsuke/args4j/ExampleMode.java
new file mode 100644
index 0000000..c3a4b18
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/ExampleMode.java
@@ -0,0 +1,33 @@
+package org.kohsuke.args4j;
+
+/**
+ * Used with {@link CmdLineParser#printExample(ExampleMode)}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public enum ExampleMode {
+ /**
+ * Print all defined options in the example.
+ *
+ * <p>
+ * This would be useful only when you have small number of options.
+ */
+ ALL() {
+ @Override
+ /*package*/ boolean print(OptionDef o) {
+ return true;
+ }
+ },
+
+ /**
+ * Print all {@link Option#required() required} option.
+ */
+ REQUIRED() {
+ @Override
+ /*package*/ boolean print(OptionDef o) {
+ return o.required();
+ }
+ };
+
+ /*package*/ abstract boolean print(OptionDef o);
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/FieldParser.java b/args4j/args4j/src/org/kohsuke/args4j/FieldParser.java
new file mode 100644
index 0000000..4b186d9
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/FieldParser.java
@@ -0,0 +1,33 @@
+package org.kohsuke.args4j;
+
+import java.lang.reflect.Field;
+
+import org.kohsuke.args4j.spi.ConfigElement;
+import org.kohsuke.args4j.spi.OptionImpl;
+import org.kohsuke.args4j.spi.Setters;
+
+/**
+ * This metadata parser makes all field available to the CmdLineParser.
+ * @author Jan Materne
+ *
+ */
+public class FieldParser {
+
+ public void parse(CmdLineParser parser, Object bean) throws ClassNotFoundException {
+ for(Class c=bean.getClass(); c!=null; c=c.getSuperclass()) {
+ System.out.println("Class: " + c);
+ for( Field f : c.getDeclaredFields() ) {
+ Option o = new OptionImpl(createConfigElement(f));
+ parser.addOption(Setters.create(f, bean), o );
+ }
+ }
+ }
+
+ private ConfigElement createConfigElement(Field f) {
+ ConfigElement rv = new ConfigElement();
+ rv.field = f.getName();
+ rv.name = "-" + f.getName();
+ return rv;
+ }
+
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/IllegalAnnotationError.java b/args4j/args4j/src/org/kohsuke/args4j/IllegalAnnotationError.java
new file mode 100644
index 0000000..d7fab10
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/IllegalAnnotationError.java
@@ -0,0 +1,27 @@
+package org.kohsuke.args4j;
+
+/**
+ * Signals an incorrect use of args4j annotations.
+ *
+ * <p>
+ * This only happens when there's something wrong with the way you use
+ * args4j in your code, not when the arguments supplied by the user is
+ * wrong. Hence this class is an {@link Error}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class IllegalAnnotationError extends Error {
+ private static final long serialVersionUID = 2397757838147693218L;
+
+ public IllegalAnnotationError(String message) {
+ super(message);
+ }
+
+ public IllegalAnnotationError(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public IllegalAnnotationError(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/MapSetter.java b/args4j/args4j/src/org/kohsuke/args4j/MapSetter.java
new file mode 100644
index 0000000..d465d73
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/MapSetter.java
@@ -0,0 +1,71 @@
+package org.kohsuke.args4j;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.kohsuke.args4j.spi.Setter;
+
+/**
+ * This setter adds a new entry to a Map.
+ * The value which is passed is split into the Map-key and Map-value by a "=".
+ * <p>
+ * <tt>-map key=value</tt></p>
+ */
+public class MapSetter implements Setter {
+ private final Field f;
+ private final Object bean;
+
+
+ public MapSetter(Object bean, Field f) {
+ super();
+ this.f = f;
+ this.bean = bean;
+ }
+
+ public Class getType() {
+ return f.getType();
+ }
+
+ public boolean isMultiValued() {
+ return false;
+ }
+
+ public void addValue(Object value) {
+ if (String.valueOf(value).indexOf('=') == -1) {
+ throw new RuntimeException(Messages.FORMAT_ERROR_FOR_MAP.format());
+ }
+
+ String[] parts = String.valueOf(value).split("=");
+ String mapKey = parts[0];
+ String mapValue = (parts.length > 1) ? parts[1] : null;
+
+ if (mapKey == null || mapKey.length()==0) {
+ throw new RuntimeException(Messages.MAP_HAS_NO_KEY.format());
+ }
+
+ try {
+ addValue(mapKey, mapValue);
+ } catch (IllegalAccessException _) {
+ // try again
+ f.setAccessible(true);
+ try {
+ addValue(mapKey, mapValue);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAccessError(e.getMessage());
+ }
+ }
+ }
+
+ private void addValue(Object key, Object value) throws IllegalArgumentException, IllegalAccessException {
+ Map map = (Map) f.get(bean);
+ if (map == null) {
+ // Field is null so set it to an empty Map
+ map = new HashMap();
+ // and reset the field on the bean not just the local reference
+ f.set(bean, map);
+ }
+ map.put(key, value);
+ }
+
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/Messages.java b/args4j/args4j/src/org/kohsuke/args4j/Messages.java
new file mode 100644
index 0000000..f65cd16
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/Messages.java
@@ -0,0 +1,35 @@
+package org.kohsuke.args4j;
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+/**
+ * @author Kohsuke Kawaguchi
+ */
+enum Messages {
+ MISSING_OPERAND,
+ UNDEFINED_OPTION,
+ NO_ARGUMENT_ALLOWED,
+ REQUIRED_OPTION_MISSING,
+ TOO_MANY_ARGUMENTS,
+ REQUIRED_ARGUMENT_MISSING,
+ METADATA_ERROR,
+ MULTIPLE_USE_OF_ARGUMENT,
+ MULTIPLE_USE_OF_OPTION,
+ UNKNOWN_HANDLER,
+ NO_OPTIONHANDLER,
+ NO_CONSTRUCTOR_ON_HANDLER,
+ FORMAT_ERROR_FOR_MAP,
+ MAP_HAS_NO_KEY
+ ;
+
+ private static ResourceBundle rb;
+
+ public String format( Object... args ) {
+ synchronized(Messages.class) {
+ if(rb==null)
+ rb = ResourceBundle.getBundle(Messages.class.getName());
+ return MessageFormat.format(rb.getString(name()),args);
+ }
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/Messages.properties b/args4j/args4j/src/org/kohsuke/args4j/Messages.properties
new file mode 100644
index 0000000..e89cd6a
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/Messages.properties
@@ -0,0 +1,41 @@
+MISSING_OPERAND = \
+ Option "{0}" takes an operand
+
+UNDEFINED_OPTION = \
+ "{0}" is not a valid option
+
+NO_ARGUMENT_ALLOWED = \
+ No argument is allowed: {0}
+
+REQUIRED_OPTION_MISSING = \
+ Option "{0}" is required
+
+REQUIRED_ARGUMENT_MISSING = \
+ Argument "{0}" is required
+
+TOO_MANY_ARGUMENTS = \
+ Too many arguments: {0}
+
+METADATA_ERROR = \
+ Problems while reading the args-confguration.
+
+MULTIPLE_USE_OF_ARGUMENT = \
+ Argument with index {0} is used more than once
+
+MULTIPLE_USE_OF_OPTION = \
+ Option name {0} is used more than once
+
+UNKNOWN_HANDLER = \
+ No OptionHandler is registered to handle {0}
+
+NO_OPTIONHANDLER = \
+ Not an OptionHandler class
+
+NO_CONSTRUCTOR_ON_HANDLER = \
+ {0} does not have the proper constructor
+
+FORMAT_ERROR_FOR_MAP = \
+ An argument for setting a Map must contain a "="
+
+MAP_HAS_NO_KEY = \
+ A key must be set. \ No newline at end of file
diff --git a/args4j/args4j/src/org/kohsuke/args4j/Messages_de_DE.properties b/args4j/args4j/src/org/kohsuke/args4j/Messages_de_DE.properties
new file mode 100644
index 0000000..0dcdc72
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/Messages_de_DE.properties
@@ -0,0 +1,49 @@
+# Unicode for Umlauts
+# Ae, ae \u00c4, \u00e4
+# Oe, oe \u00d6, \u00f6
+# Ue, ue \u00dc, \u00fc
+# ss \u00df
+
+
+
+MISSING_OPERAND = \
+ Option "{0}" ben\u00f6tigt einen Operanden
+
+UNDEFINED_OPTION = \
+ "{0}" ist keine g\u00fcltige Option
+
+NO_ARGUMENT_ALLOWED = \
+ Kein Argument erlaubt: {0}
+
+REQUIRED_OPTION_MISSING = \
+ Option "{0}" wird ben\u00f6tigt
+
+REQUIRED_ARGUMENT_MISSING = \
+ Argument "{0}" wird ben\u00f6tigt
+
+TOO_MANY_ARGUMENTS = \
+ Zu viele Argumente: {0}
+
+METADATA_ERROR = \
+ Kann die Args4J-Metadaten nicht lesen
+
+MULTIPLE_USE_OF_ARGUMENT = \
+ Das Argument mit Index {0} ist mehr als einmal verwendet
+
+MULTIPLE_USE_OF_OPTION = \
+ Die Option '{0}' ist mehr als einmal verwendet
+
+UNKNOWN_HANDLER = \
+ Es ist kein OptionHandler für '{0}' registriert
+
+NO_OPTIONHANDLER = \
+ Ist keine OptionHandler Klasse
+
+NO_CONSTRUCTOR_ON_HANDLER = \
+ {0} hat nicht den notwendigen Konstruktor
+
+FORMAT_ERROR_FOR_MAP = \
+ Ein Argument für eine Map muss ein "=" enthalten
+
+MAP_HAS_NO_KEY = \
+ A Schl\u00fcssel muss gesetzt sein \ No newline at end of file
diff --git a/args4j/args4j/src/org/kohsuke/args4j/Messages_ru_RU.properties b/args4j/args4j/src/org/kohsuke/args4j/Messages_ru_RU.properties
new file mode 100644
index 0000000..1e6f8d0
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/Messages_ru_RU.properties
@@ -0,0 +1,22 @@
+MISSING_OPERAND = \u041E\u043F\u0446\u0438\u044F "{0}" \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u043D\u0434
+UNDEFINED_OPTION = "{0}" \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u043E\u043F\u0446\u0438\u044F
+NO_ARGUMENT_ALLOWED = \u041D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0439 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\: {0}
+REQUIRED_OPTION_MISSING = \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u043E\u043F\u0446\u0438\u044F "{0}"
+REQUIRED_ARGUMENT_MISSING = \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442 "{0}"
+TOO_MANY_ARGUMENTS = \u0421\u043B\u0438\u0448\u043A\u043E\u043C \u043C\u043D\u043E\u0433\u043E \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u0432\: {0}
+
+
+# For translation
+#------------------
+# METADATA_ERROR = Problems while reading the args-confguration.
+# MULTIPLE_USE_OF_ARGUMENT = Argument with index {0} is used more than once
+# MULTIPLE_USE_OF_OPTION = Option name {0} is used more than once
+# UNKNOWN_HANDLER = No OptionHandler is registered to handle {0}
+# NO_OPTIONHANDLER = Not an OptionHandler class
+# NO_CONSTRUCTOR_ON_HANDLER = {0} does not have the proper constructor
+# FORMAT_ERROR_FOR_MAP = An argument for setting a Map must contain a '='
+# MAP_HAS_NO_KEY = A key must be set.
+
+
+
+
diff --git a/args4j/args4j/src/org/kohsuke/args4j/NamedOptionDef.java b/args4j/args4j/src/org/kohsuke/args4j/NamedOptionDef.java
new file mode 100644
index 0000000..5ad895a
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/NamedOptionDef.java
@@ -0,0 +1,44 @@
+package org.kohsuke.args4j;
+
+/**
+ * Run-time copy of the Option or Argument annotation.
+ */
+public final class NamedOptionDef extends OptionDef {
+ private final String name;
+ private final String[] aliases;
+
+ public NamedOptionDef(Option o, boolean forceMultiValued) {
+ super(o.usage(),o.metaVar(),o.required(),o.handler(),o.multiValued() || forceMultiValued);
+
+ this.name = o.name();
+ this.aliases = o.aliases();
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public String[] aliases() {
+ return aliases;
+ }
+
+ @Override
+ public String toString() {
+ if (aliases.length > 0) {
+ String str = "";
+ for (String alias : aliases) {
+ if (str.length() > 0) {
+ str += ", ";
+ }
+ str += alias;
+ }
+ return name() + " (" + str + ")";
+ }
+ return name();
+ }
+
+ @Override
+ public boolean isArgument() {
+ return false;
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/Option.java b/args4j/args4j/src/org/kohsuke/args4j/Option.java
new file mode 100644
index 0000000..7ddf979
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/Option.java
@@ -0,0 +1,169 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.spi.OptionHandler;
+
+import java.io.File;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.reflect.AccessibleObject;
+import java.util.ResourceBundle;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Marks a field/setter that receives a command line switch value.
+ *
+ * <p>
+ * This annotation can be placed on a field of type T or the method
+ * of the form <tt>void <i>methodName</i>(T value)</tt>. Its access
+ * modified can be anything, but if it's not public, your application
+ * needs to run in a security context that allows args4j to access
+ * the field/method (see {@link AccessibleObject#setAccessible(boolean)}.
+ *
+ * <p>
+ * The behavior of the annotation differs depending on T --- the type
+ * of the field or the parameter of the method.
+ *
+ * <h2>Boolean Switch</h2>
+ * <p>
+ * When T is boolean , it represents
+ * a boolean option that takes the form of "-OPT". When this option is set,
+ * the property will be set to true.
+ *
+ * <h2>String Switch</h2>
+ * <p>
+ * When T is {@link String}, it represents
+ * an option that takes one operand. The value of the operand is set
+ * to the property.
+ *
+ * <h2>Enum Switch</h2>
+ * <p>
+ * When T is derived from {@link Enum}, it represents an option that takes
+ * an operand, which must be one of the enum constant. The comparion between
+ * the operand and the enum constant name is done in a case insensitive fashion.
+ * <p>
+ * For example, the following definition will represent command line options
+ * like "-coin penny" or "-coin DIME" but things like "-coin" or "-coin abc" are
+ * errors.
+ *
+ * <pre>
+ * enum Coin { PENNY,NICKEL,DIME,QUARTER }
+ *
+ * class Option {
+ * &#64;Option(name="-coin")
+ * public Coin coin;
+ * }
+ * </pre>
+ *
+ * <h2>File Switch</h2>
+ * <p>
+ * When T is a {@link File}, it represents an option that takes a file/directory
+ * name as an operand.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+@Retention(RUNTIME)
+@Target({FIELD,METHOD,PARAMETER})
+public @interface Option {
+ /**
+ * Name of the option, such as "-foo" or "-bar".
+ */
+ String name();
+
+ /**
+ * Aliases for the options, such as "--long-option-name".
+ */
+ String[] aliases() default { };
+
+ /**
+ * Help string used to display the usage screen.
+ *
+ * <p>
+ * This parameter works in two ways. For a simple use,
+ * you can just encode the human-readable help string directly,
+ * and that will be used as the message. This is easier,
+ * but it doesn't support localization.
+ *
+ * <p>
+ * For more advanced use, this property is set to a key of a
+ * {@link ResourceBundle}. The actual message is obtained
+ * by querying a {@link ResourceBundle} instance supplied to
+ * {@link CmdLineParser} by this key. This allows the usage
+ * screen to be properly localized.
+ *
+ * <p>
+ * If this value is empty, the option will not be displayed
+ * in the usage screen.
+ */
+ String usage() default "";
+
+ /**
+ * When the option takes an operand, the usage screen will show something like this:
+ * <pre>
+ * -x FOO : blah blah blah
+ * </pre>
+ * You can replace the 'FOO' token by using this parameter.
+ *
+ * <p>
+ * If left unspecifiied, this value is infered from the type of the option.
+ *
+ * <p>
+ * Just like {@link #usage()}, normally, this value is printed as is.
+ * But if a {@link ResourceBundle} is given to the {@link CmdLineParser},
+ * it will be used to obtain the locale-specific value.
+ */
+ String metaVar() default "";
+
+ /**
+ * Specify that the option is mandatory.
+ *
+ * <p>
+ * At the end of {@link CmdLineParser#parseArgument(String...)},
+ * a {@link CmdLineException} will be thrown if a required option
+ * is not present.
+ *
+ * <p>
+ * Note that in most of the command line interface design principles,
+ * options should be really optional. So use caution when using this
+ * flag.
+ */
+ boolean required() default false;
+
+ /**
+ * Specify the {@link OptionHandler} that processes the command line arguments.
+ *
+ * <p>
+ * The default value {@link OptionHandler} indicates that
+ * the {@link OptionHandler} will be infered from
+ * the type of the field/method where a {@link Option} annotation
+ * is placed.
+ *
+ * <p>
+ * If this annotation element is used, it overrides the inference
+ * and determines the handler to be used. This is convenient for
+ * defining a non-standard option parsing semantics.
+ *
+ * <h3>Example</h3>
+ * <pre>
+ * // this is a normal "-r" option
+ * &#64;Option(name="-r")
+ * boolean value;
+ *
+ * // this causes arg4j to use MyHandler, not the default
+ * // handler provided for boolean
+ * &#64;Option(name="-b",handler=MyHandler.class)
+ * boolean value;
+ * </pre>
+ */
+ Class<? extends OptionHandler> handler() default OptionHandler.class;
+
+ /**
+ * Whether the option is multi-valued.
+ * For mappings to List<...>, this defaults to true, otherwise false
+ */
+ boolean multiValued() default false;
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/OptionDef.java b/args4j/args4j/src/org/kohsuke/args4j/OptionDef.java
new file mode 100644
index 0000000..5601a41
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/OptionDef.java
@@ -0,0 +1,59 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.spi.OptionHandler;
+
+/**
+ * Run-time copy of the Option or Argument annotation. By definition, unnamed options
+ * are arguments (and instances of this class). Named options are actually a subclass.
+ *
+ * @author Mark Sinke
+ */
+public class OptionDef {
+ private final String usage;
+ private final String metaVar;
+ private final boolean required;
+ private final boolean multiValued;
+ private final Class<? extends OptionHandler> handler;
+
+ public OptionDef(Argument a, boolean forceMultiValued) {
+ this(a.usage(), a.metaVar(), a.required(), a.handler(), a.multiValued() || forceMultiValued);
+ }
+
+ protected OptionDef(String usage, String metaVar, boolean required,
+ Class<? extends OptionHandler> handler, boolean multiValued) {
+ this.usage = usage;
+ this.metaVar = metaVar;
+ this.required = required;
+ this.handler = handler;
+ this.multiValued = multiValued;
+ }
+
+ public String usage() {
+ return usage;
+ }
+
+ public String metaVar() {
+ return metaVar;
+ }
+
+ public boolean required() {
+ return required;
+ }
+
+ public Class<? extends OptionHandler> handler() {
+ return handler;
+ }
+
+ public boolean isMultiValued() {
+ return multiValued;
+ }
+
+ public boolean isArgument() {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return metaVar() != null ? metaVar() : "ARG";
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/Starter.java b/args4j/args4j/src/org/kohsuke/args4j/Starter.java
new file mode 100644
index 0000000..25de6a3
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/Starter.java
@@ -0,0 +1,109 @@
+package org.kohsuke.args4j;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Starter class which uses reflection to instantiate the business
+ * class, parse the command line parameters, sets the fields of the
+ * business class and doing the help message handling.
+ *
+ * @author Jan Materne
+ */
+public class Starter {
+
+ /**
+ * The name of the JavaVM property which stores the class name of
+ * the business class.
+ * {@value}
+ */
+ public static final String PARAMETER_NAME = "mainclass";
+
+ public static void main(String[] args) {
+ String classname = System.getProperty(PARAMETER_NAME);
+ CmdLineParser parser = null;
+ boolean classHasArgument = false;
+ boolean classHasOptions = false;
+
+ // Check the requirement: must specify the class to start
+ if (classname == null || "".equals(classname)) {
+ System.err.println("The system property '"
+ + PARAMETER_NAME
+ + "' must contain the classname to start.");
+ System.exit(-1);
+ }
+
+ try {
+ Class clazz = Class.forName(classname);
+ Object bean = clazz.newInstance();
+ parser = new CmdLineParser(bean);
+
+ // for help output
+ classHasArgument = hasAnnotation(clazz, Argument.class);
+ classHasOptions = hasAnnotation(clazz, Option.class);
+
+ parser.parseArgument(args);
+
+ // try starting run()
+ Method m;
+ boolean couldInvoke = false;
+ try {
+ m = clazz.getMethod("run", (Class[]) null);
+ m.invoke(bean, (Object[]) null);
+ couldInvoke = true;
+ } catch (SecurityException e) {
+ } catch (IllegalArgumentException e) {
+ } catch (NoSuchMethodException e) {
+ } catch (IllegalAccessException e) {
+ } catch (InvocationTargetException e) {
+ }
+
+ // try starting run(String[])
+ if (!couldInvoke) try {
+ m = clazz.getMethod("run", String[].class);
+ m.invoke(bean, new Object[]{args});
+ couldInvoke = true;
+ } catch (SecurityException e) {
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ } catch (IllegalAccessException e) {
+ } catch (InvocationTargetException e) {
+ }
+ } catch (ClassNotFoundException e) {
+ // wrong classpath setting
+ System.err.println("Cant find the class '"
+ + classname
+ + "' as specified in the system property '"
+ + PARAMETER_NAME + "'.");
+ } catch (CmdLineException e) {
+ // wrong argument enteres, so print the usage message as
+ // supplied by args4j
+ System.err.println(e.getMessage());
+ System.err.print(classname);
+ if (classHasOptions) System.err.print(" [options]");
+ if (classHasArgument) System.err.print(" arguments");
+ System.err.println();
+ if (parser != null)
+ parser.printUsage(System.err);
+ } catch (Exception e) {
+ // Must be an unhandled business exception, so we can only
+ // print stacktraces.
+ e.printStackTrace();
+ }
+ }
+
+ public static boolean hasAnnotation(Class clazz, Class<? extends Annotation> annotation) {
+ if (clazz.getAnnotation(annotation)!=null) return true;
+ for (Field f : clazz.getFields()) {
+ if (f.getAnnotation(annotation)!=null) return true;
+ }
+ for (Method m : clazz.getMethods()) {
+ if (m.getAnnotation(annotation)!=null) return true;
+ }
+ return false;
+ }
+
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/XmlParser.java b/args4j/args4j/src/org/kohsuke/args4j/XmlParser.java
new file mode 100644
index 0000000..8f71c5d
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/XmlParser.java
@@ -0,0 +1,91 @@
+package org.kohsuke.args4j;
+
+import java.lang.reflect.AccessibleObject;
+import java.net.URL;
+
+import org.kohsuke.args4j.spi.ArgumentImpl;
+import org.kohsuke.args4j.spi.ConfigElement;
+import org.kohsuke.args4j.spi.OptionImpl;
+import org.kohsuke.args4j.spi.Setters;
+import org.xml.sax.InputSource;
+
+/**
+ * Parses an XML-file specifying the 'annotations'.
+ * The XML must have the structure:
+ * <pre>
+ * &lt;args>
+ * &lt;option field="" method="" name="" usage="" metavar="" handler=""/>
+ * &lt;argument field="" method="" usage="" metavar="" handler=""/>
+ * &lt;/args>
+ * </pre>
+ * Exactly one of the attributes 'field' or 'method' must be set.
+ * The 'handler' value specifies a full qualified class name.
+ *
+ * <h3>Example</h3>
+ * <pre>
+ * &lt;args>
+ * &lt;option field="recursive" name="-r" usage="recursively run something"/>
+ * &lt;option field="out" name="-o" usage="output to this file" metavar="OUTPUT"/>
+ * &lt;option method="setStr(String)" name="-str"/>
+ * &lt;option field="data" name="-custom" handler="org.kohsuke.args4j.spi.BooleanOptionHandler" usage="boolean value for checking the custom handler"/>
+ * &lt;argument field="arguments"/>
+ * &lt;args>
+ * </pre>
+ *
+ * @author Jan Materne
+ */
+public class XmlParser {
+ public void parse(URL xml, CmdLineParser parser, Object bean) {
+ parse(new InputSource(xml.toExternalForm()),parser,bean);
+ }
+
+ public void parse(InputSource xml, CmdLineParser parser, Object bean) {
+ try {
+ Config config = Config.parse(xml);
+ for(ConfigElement ce : config.options) {
+ Option option = new OptionImpl(ce);
+ parser.addOption(Setters.create(parser, findMethodOrField(bean, ce.field, ce.method),bean), option);
+ }
+ for (ConfigElement ce : config.arguments) {
+ Argument argument = new ArgumentImpl(ce);
+ parser.addArgument(Setters.create(parser, findMethodOrField(bean, ce.field, ce.method),bean), argument);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(Messages.METADATA_ERROR.format(), e);
+ }
+ }
+
+
+ /**
+ * Finds a {@link java.lang.reflect.Method} or {@link java.lang.reflect.Method} in the bean
+ * instance with the requested name.
+ * @param bean bean instance
+ * @param field name of the field (field XOR method must be specified)
+ * @param method name of the method (field XOR method must be specified)
+ * @return the reflection reference
+ * @throws SecurityException
+ * @throws NoSuchFieldException
+ * @throws NoSuchMethodException
+ * @throws ClassNotFoundException
+ */
+ private AccessibleObject findMethodOrField(Object bean, String field, String method) throws SecurityException, NoSuchFieldException, NoSuchMethodException, ClassNotFoundException {
+ AccessibleObject rv;
+ if (field != null) {
+ rv = bean.getClass().getDeclaredField(field);
+ } else {
+ String methodName = method.substring(0, method.indexOf("("));
+ String[] params = method.substring(method.indexOf("(")+1, method.indexOf(")")).split(",");
+ Class[] paramTypes = new Class[params.length];
+ for(int i=0; i<params.length; i++) {
+ String className = params[i];
+ if (className.indexOf('.') < 0) {
+ className = "java.lang." + className;
+ }
+ paramTypes[i] = Class.forName(className);
+ }
+ rv = bean.getClass().getMethod(methodName, paramTypes);
+ }
+ return rv;
+ }
+
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/package.html b/args4j/args4j/src/org/kohsuke/args4j/package.html
new file mode 100644
index 0000000..bac7614
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/package.html
@@ -0,0 +1,84 @@
+<html><body>
+<p>Core classes of the Args4J command line parser.</p>
+
+<h1>What is Args4J</h1>
+<p>Args4J is a command line parser. As such a parser its job is to parse the String-array passed to the main() method
+and transfer the values to a java object, which includes type conversion. The entry point into this parsing is
+the CmdLineParser class with its parse() Method.</p>
+<p>Args4J must know the mapping between the flag from the command line and the target for the value.
+There are multiple ways for Args4J: <ul>
+ <li>place an @Option or @Argument annotation at a setter or on a field</li>
+ <li>provide a XML configuration file</li>
+ <li>make all fields public available</li>
+</ul>
+depending on what you want, you have to do a configuration step before starting the parsing.</p>
+
+<h1>Examples</h1>
+
+<p><tt>java Main -text newText</tt></p>
+
+<p>The standard use case is having a bean class and providing the annotations.
+This feature is available since the first Args4J release:
+<!-- TODO:
+Javadoc stops when reaching the at-sign. When I load the package.html directly into Firefox,
+all is fine. But when creating the javadoc it stops copying the content at that sign.
+(a) is a compromise here ...
+Does anyone know how to handle that?
+-->
+<pre>
+public class Bean {
+ (a)Option(name="-text")
+ String text;
+}
+public class Main {
+ public static void main(String[] args) throws CmdLineException {
+ Object bean = new Bean();
+ CmdLineParser parser = new CmdLineParser(bean);
+ parser.parse(args);
+ }
+}
+</pre>
+
+<p>An easy way for initializing fields and not touching the bean source code
+is using the FieldParser. The FieldParser scans all fields of the bean class
+(including inheritance) and makes them public available as options with
+a '-' prefix in the name.
+This feature is available since Args4J release 2.0.16:
+<pre>
+public class Bean {
+ String text;
+}
+public class Main {
+ public static void main(String[] args) throws CmdLineException {
+ Object bean = new Bean();
+ CmdLineParser parser = new CmdLineParser(null);
+ new FieldParser().parse(parser, bean);
+ parser.parse(args);
+ }
+}
+</pre>
+
+<p>While the FieldParser is easier to use, the XmlParser supports more features.
+That said it supports all features which are available via annotations: usage text, specifying handlers and more.
+You have to provide an XML InputSource or an URL to the XML file.
+This feature is available since Args4J release 2.0.16:
+<pre>
+public class Bean {
+ String text;
+}
+public class Main {
+ public static void main(String[] args) throws CmdLineException {
+ Object bean = new Bean();
+ CmdLineParser parser = new CmdLineParser(null);
+ new XmlParser().parse(getClass().getResource(bean.getClass().getName() + ".xml"), parser, bean);
+ parser.parse(args);
+ }
+}
+&lt;args>
+ &lt;option field="text" name="-text" usage="Output text"/>
+&lt;/args>
+</pre>
+</p>
+
+
+</body></html> \ No newline at end of file
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/AnnotationImpl.java b/args4j/args4j/src/org/kohsuke/args4j/spi/AnnotationImpl.java
new file mode 100644
index 0000000..bd1a2ec
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/AnnotationImpl.java
@@ -0,0 +1,63 @@
+package org.kohsuke.args4j.spi;
+
+import java.lang.annotation.Annotation;
+
+
+/**
+ * Base class for the @Option and @Argument implementation classes.
+ * @author Jan Materne
+ */
+public abstract class AnnotationImpl implements Annotation {
+ private final Class<? extends Annotation> annotationType;
+
+ protected AnnotationImpl(Class<? extends Annotation> annotationType) {
+ this.annotationType = annotationType;
+ }
+
+ protected AnnotationImpl(Class<? extends Annotation> annotationType, ConfigElement ce) throws ClassNotFoundException {
+ this(annotationType);
+
+ aliases = ce.aliases != null ? ce.aliases : new String[0];
+ if (ce.handler != null) {
+ handler = (Class<? extends OptionHandler>) Class.forName(ce.handler);
+ } else {
+ handler = OptionHandler.class;
+ }
+ metaVar = ce.metavar != null ? ce.metavar : "";
+ multiValued = ce.multiValued;
+ required = ce.required;
+ usage = ce.usage != null ? ce.usage : "";
+ }
+
+ public String[] aliases;
+ public String[] aliases() {
+ return aliases;
+ }
+ public Class<? extends OptionHandler> handler;
+ public Class<? extends OptionHandler> handler() {
+ return handler;
+ }
+ public String metaVar;
+ public String metaVar() {
+ return metaVar;
+ }
+ public boolean multiValued;
+ public boolean multiValued() {
+ return multiValued;
+ }
+ public boolean required;
+ public boolean required() {
+ return required;
+ }
+ public String usage;
+ public String usage() {
+ return usage;
+ }
+ public Class<? extends Annotation> annotationType() {
+ return annotationType;
+ }
+ public int index;
+ public int index() {
+ return index;
+ }
+} \ No newline at end of file
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/ArgumentImpl.java b/args4j/args4j/src/org/kohsuke/args4j/spi/ArgumentImpl.java
new file mode 100644
index 0000000..b2c3927
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/ArgumentImpl.java
@@ -0,0 +1,13 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.Argument;
+
+/**
+ * Implementation of @Argument so we can instantiate it.
+ * @author Jan Materne
+ */
+public class ArgumentImpl extends AnnotationImpl implements Argument {
+ public ArgumentImpl(ConfigElement ce) throws ClassNotFoundException {
+ super(Argument.class,ce);
+ }
+} \ No newline at end of file
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/BooleanOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/BooleanOptionHandler.java
new file mode 100644
index 0000000..5382fed
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/BooleanOptionHandler.java
@@ -0,0 +1,43 @@
+package org.kohsuke.args4j.spi;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+/**
+ * Boolean {@link OptionHandler}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class BooleanOptionHandler extends OptionHandler<Boolean> {
+ private static final List<String> ACCEPTABLE_VALUES = Arrays.asList(new String[] { "true", "on", "yes", "1",
+ "false", "off", "no", "0" });
+
+ public BooleanOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super Boolean> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ public int parseArguments(Parameters params) throws CmdLineException {
+ if (option.isArgument()) {
+ String valueStr = params.getParameter(0).toLowerCase();
+ int index = ACCEPTABLE_VALUES.indexOf(valueStr);
+ if (index == -1) {
+ throw new CmdLineException(owner, Messages.ILLEGAL_BOOLEAN.format(valueStr));
+ }
+ setter.addValue(index < ACCEPTABLE_VALUES.size() / 2);
+ return 1;
+ } else {
+ setter.addValue(true);
+ return 0;
+ }
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return null;
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/ByteOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/ByteOptionHandler.java
new file mode 100644
index 0000000..4bff552
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/ByteOptionHandler.java
@@ -0,0 +1,24 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+/**
+ * {@link Byte}
+ * {@link OptionHandler}
+ * {@link OneArgumentOptionHandler}
+ * @author Jan Materne
+ * @since 2.0.9
+ */
+public class ByteOptionHandler extends OneArgumentOptionHandler<Byte> {
+
+ public ByteOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super Byte> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ protected Byte parse(String argument) throws NumberFormatException {
+ return Byte.parseByte(argument);
+ }
+
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/CharOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/CharOptionHandler.java
new file mode 100644
index 0000000..f2089d8
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/CharOptionHandler.java
@@ -0,0 +1,28 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.CmdLineException;
+
+import java.text.MessageFormat;
+
+/**
+ * {@link Char}
+ * {@link OptionHandler}
+ * {@link OneArgumentOptionHandler}
+ * @author Jan Materne
+ * @since 2.0.9
+ */
+public class CharOptionHandler extends OneArgumentOptionHandler<Character> {
+
+ public CharOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super Character> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ protected Character parse(String argument) throws NumberFormatException, CmdLineException {
+ if (argument.length() != 1)
+ throw new CmdLineException(owner, Messages.ILLEGAL_CHAR.format(argument));
+ return argument.charAt(0);
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/ConfigElement.java b/args4j/args4j/src/org/kohsuke/args4j/spi/ConfigElement.java
new file mode 100644
index 0000000..474c943
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/ConfigElement.java
@@ -0,0 +1,25 @@
+package org.kohsuke.args4j.spi;
+
+/**
+ * The ConfigElement is an <tt>&lt;option></tt> or <tt>&lt;argument></tt> tag
+ * in the xml configuration file.
+ * @author Jan Materne
+ */
+public class ConfigElement {
+ public String field;
+ public String method;
+ public String name;
+ public String usage = "";
+ public String handler;
+ public String metavar = "";
+ public String[] aliases = {};
+ public boolean multiValued = false;
+ public boolean required = false;
+ /**
+ * Ensures that only a field XOR a method is set.
+ * @return
+ */
+ public boolean isInvalid() {
+ return field == null && method == null || field != null && method != null;
+ }
+} \ No newline at end of file
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/DoubleOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/DoubleOptionHandler.java
new file mode 100644
index 0000000..10f0dcc
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/DoubleOptionHandler.java
@@ -0,0 +1,21 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+/**
+ * {@link Double}
+ * {@link OptionHandler}.
+ * {@link OneArgumentOptionHandler}
+ * @author Leif Wickland
+ */
+public class DoubleOptionHandler extends OneArgumentOptionHandler<Double> {
+ public DoubleOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super Double> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ protected Double parse(String argument) throws NumberFormatException {
+ return Double.parseDouble(argument);
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/EnumOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/EnumOptionHandler.java
new file mode 100644
index 0000000..a6447ea
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/EnumOptionHandler.java
@@ -0,0 +1,58 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+/**
+ * {@link Enum} {@link OptionHandler}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class EnumOptionHandler<T extends Enum<T>> extends OptionHandler<T> {
+
+ private final Class<T> enumType;
+
+ public EnumOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super T> setter, Class<T> enumType) {
+ super(parser, option, setter);
+ this.enumType = enumType;
+ }
+
+ @Override
+ public int parseArguments(Parameters params) throws CmdLineException {
+ String s = params.getParameter(0).replaceAll("-", "_");
+ T value = null;
+ for( T o : enumType.getEnumConstants() )
+ if(o.name().equalsIgnoreCase(s)) {
+ value = o;
+ break;
+ }
+
+ if(value==null) {
+ if (option.isArgument()) {
+ throw new CmdLineException(owner, Messages.ILLEGAL_OPERAND.format(option.toString(),s));
+ } else {
+ throw new CmdLineException(owner, Messages.ILLEGAL_OPERAND.format(params.getParameter(-1),s));
+ }
+ }
+ setter.addValue(value);
+ return 1;
+ }
+
+ /*
+ * Returns all values of an enum type split by pipe.
+ * <tt>[ one | two | three]</tt>
+ * @see org.kohsuke.args4j.spi.OptionHandler#getDefaultMetaVariable()
+ */
+ @Override
+ public String getDefaultMetaVariable() {
+ StringBuffer rv = new StringBuffer();
+ rv.append("[");
+ for (T t : enumType.getEnumConstants()) {
+ rv.append(t).append(" | ");
+ }
+ rv.delete(rv.length()-3, rv.length());
+ rv.append("]");
+ return rv.toString();
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/ExplicitBooleanOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/ExplicitBooleanOptionHandler.java
new file mode 100644
index 0000000..e2fb837
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/ExplicitBooleanOptionHandler.java
@@ -0,0 +1,64 @@
+package org.kohsuke.args4j.spi;
+
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+/**
+ * Boolean {@link OptionHandler} that (unlike the standard {@link BooleanOptionHandler}
+ * allows values to be set to false explicitly (using e.g. '-myOpt false') rather
+ * than only returning false when the option is <em>omitted</em>.
+ */
+public class ExplicitBooleanOptionHandler extends OptionHandler<Boolean> {
+ // same values as BooleanOptionHandler
+ private static final Map<String, Boolean> ACCEPTABLE_VALUES;
+
+ static {
+ // I like the trick in BooleanOptionHandler but find this explicit map more readable
+ ACCEPTABLE_VALUES = new HashMap<String, Boolean>();
+ ACCEPTABLE_VALUES.put("true", TRUE);
+ ACCEPTABLE_VALUES.put("on", TRUE);
+ ACCEPTABLE_VALUES.put("yes", TRUE);
+ ACCEPTABLE_VALUES.put("1", TRUE);
+ ACCEPTABLE_VALUES.put("false", FALSE);
+ ACCEPTABLE_VALUES.put("off", FALSE);
+ ACCEPTABLE_VALUES.put("no", FALSE);
+ ACCEPTABLE_VALUES.put("0", FALSE);
+ }
+
+ public ExplicitBooleanOptionHandler(CmdLineParser parser,
+ OptionDef option, Setter<? super Boolean> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ public int parseArguments(Parameters params) throws CmdLineException {
+ // end of arg list or next arg is another option
+ if ((params.size() == 0) || params.getParameter(0).startsWith("-")) {
+ setter.addValue(TRUE);
+ return 0;
+ } else {
+ setter.addValue(getBoolean(params.getParameter(0)));
+ return 1;
+ }
+ }
+
+ private Boolean getBoolean(String parameter) throws CmdLineException {
+ String valueStr = parameter.toLowerCase();
+ if (!ACCEPTABLE_VALUES.containsKey(valueStr)) {
+ throw new CmdLineException(owner, Messages.ILLEGAL_BOOLEAN.format(valueStr));
+ }
+ return ACCEPTABLE_VALUES.get(valueStr);
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "[VAL]";
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/FieldSetter.java b/args4j/args4j/src/org/kohsuke/args4j/spi/FieldSetter.java
new file mode 100644
index 0000000..af946a7
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/FieldSetter.java
@@ -0,0 +1,42 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.spi.Setter;
+
+import java.lang.reflect.Field;
+
+/**
+ * {@link Setter} that sets to a {@link Field}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+final class FieldSetter implements Setter {
+ private final Field f;
+ private final Object bean;
+
+ public FieldSetter(Object bean, Field f) {
+ this.bean = bean;
+ this.f = f;
+ }
+
+ public Class getType() {
+ return f.getType();
+ }
+
+ public boolean isMultiValued() {
+ return false;
+ }
+
+ public void addValue(Object value) {
+ try {
+ f.set(bean,value);
+ } catch (IllegalAccessException _) {
+ // try again
+ f.setAccessible(true);
+ try {
+ f.set(bean,value);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAccessError(e.getMessage());
+ }
+ }
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/FileOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/FileOptionHandler.java
new file mode 100644
index 0000000..e1c23ab
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/FileOptionHandler.java
@@ -0,0 +1,29 @@
+package org.kohsuke.args4j.spi;
+
+import java.io.File;
+
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+
+/**
+ * {@link File} {@link OptionHandler}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class FileOptionHandler extends OptionHandler<File> {
+ public FileOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super File> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ public int parseArguments(Parameters params) throws CmdLineException {
+ setter.addValue(new File(params.getParameter(0)));
+ return 1;
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "FILE";
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/FloatOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/FloatOptionHandler.java
new file mode 100644
index 0000000..6442328
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/FloatOptionHandler.java
@@ -0,0 +1,26 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+/**
+ * {@link Float}
+ * {@link OptionHandler}
+ * {@link OneArgumentOptionHandler}
+ *
+ * @author Jan Materne
+ * @since 2.0.9
+ */
+public class FloatOptionHandler extends OneArgumentOptionHandler<Float> {
+
+ public FloatOptionHandler(CmdLineParser parser, OptionDef option,
+ Setter<? super Float> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ protected Float parse(String argument) throws NumberFormatException {
+ return Float.parseFloat(argument);
+ }
+
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/IntOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/IntOptionHandler.java
new file mode 100644
index 0000000..d26ffe6
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/IntOptionHandler.java
@@ -0,0 +1,22 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+/**
+ * {@link Integer}
+ * {@link OptionHandler}.
+ * {@link OneArgumentOptionHandler}
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class IntOptionHandler extends OneArgumentOptionHandler<Integer> {
+ public IntOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super Integer> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ protected Integer parse(String argument) throws NumberFormatException {
+ return Integer.parseInt(argument);
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/LongOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/LongOptionHandler.java
new file mode 100644
index 0000000..e139996
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/LongOptionHandler.java
@@ -0,0 +1,24 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+/**
+ * {@link Long}
+ * {@link OptionHandler}
+ * {@link OneArgumentOptionHandler}
+ * @author Jan Materne
+ * @since 2.0.9
+ */
+public class LongOptionHandler extends OneArgumentOptionHandler<Long> {
+
+ public LongOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super Long> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ protected Long parse(String argument) throws NumberFormatException {
+ return Long.parseLong(argument);
+ }
+
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/MapOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/MapOptionHandler.java
new file mode 100644
index 0000000..4502f78
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/MapOptionHandler.java
@@ -0,0 +1,32 @@
+package org.kohsuke.args4j.spi;
+
+import java.util.Map;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.MapSetter;
+import org.kohsuke.args4j.OptionDef;
+
+public class MapOptionHandler extends OptionHandler<Map<?,?>> {
+
+ public MapOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super Map<?,?>> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return null;
+ }
+
+ @Override
+ public int parseArguments(Parameters params) throws CmdLineException {
+ MapSetter mapSetter = (MapSetter)setter;
+ try {
+ mapSetter.addValue(params.getParameter(0));
+ } catch (RuntimeException e) {
+ throw new CmdLineException(owner, e.getMessage());
+ }
+ return 1;
+ }
+
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/Messages.java b/args4j/args4j/src/org/kohsuke/args4j/spi/Messages.java
new file mode 100644
index 0000000..a49ae96
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/Messages.java
@@ -0,0 +1,27 @@
+package org.kohsuke.args4j.spi;
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+/**
+ * @author Kohsuke Kawaguchi
+ */
+enum Messages {
+ ILLEGAL_OPERAND,
+ ILLEGAL_CHAR,
+ ILLEGAL_BOOLEAN,
+ ILLEGAL_METHOD_SIGNATURE,
+ ILLEGAL_FIELD_SIGNATURE,
+ ILLEGAL_LIST
+ ;
+
+ private static ResourceBundle rb;
+
+ public String format( Object... args ) {
+ synchronized(Messages.class) {
+ if(rb==null)
+ rb = ResourceBundle.getBundle(Messages.class.getName());
+ return MessageFormat.format(rb.getString(name()),args);
+ }
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/Messages.properties b/args4j/args4j/src/org/kohsuke/args4j/spi/Messages.properties
new file mode 100644
index 0000000..d98e0ae
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/Messages.properties
@@ -0,0 +1,12 @@
+ILLEGAL_OPERAND = \
+ "{1}" is not a valid value for "{0}"
+ILLEGAL_BOOLEAN = \
+ "{0}" is not a legal boolean value
+ILLEGAL_CHAR = \
+ "{0}" must be a single character
+ILLEGAL_METHOD_SIGNATURE = \
+ Method {0} takes more than one parameter
+ILLEGAL_FIELD_SIGNATURE = \
+ Field of type {0} isn't supported by args4j
+ILLEGAL_LIST = \
+ type of {0} is not a List \ No newline at end of file
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/Messages_de.properties b/args4j/args4j/src/org/kohsuke/args4j/spi/Messages_de.properties
new file mode 100644
index 0000000..c99dc83
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/Messages_de.properties
@@ -0,0 +1,20 @@
+# Unicode for Umlauts
+# Ae, ae \u00c4, \u00e4
+# Oe, oe \u00d6, \u00f6
+# Ue, ue \u00dc, \u00fc
+# ss \u00df
+
+
+
+ILLEGAL_METHOD_SIGNATURE = \
+ Methode {0} ben\u00f6tigt mehr als einen Parameter
+ILLEGAL_FIELD_SIGNATURE = \
+ Der Datentyp {0} wird von args4j nicht unterst\u00fctzt
+ILLEGAL_OPERAND = \
+ "{1}" ist kein g\u00fcltiger Wert f\u00fcr "{0}"
+ILLEGAL_BOOLEAN = \
+ "{0}" ist kein g\u00fcltiger Boolscher Wert
+ILLEGAL_CHAR = \
+ "{0}" muss ein einzelnes Zeichen sein
+ILLEGAL_LIST = \
+ Der Typ von {0} ist keine List \ No newline at end of file
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/Messages_ru.properties b/args4j/args4j/src/org/kohsuke/args4j/spi/Messages_ru.properties
new file mode 100644
index 0000000..3c6b9f5
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/Messages_ru.properties
@@ -0,0 +1,12 @@
+
+ILLEGAL_METHOD_SIGNATURE = \u041C\u0435\u0442\u043E\u0434 {0} \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0431\u043E\u043B\u0435\u0435 \u043E\u0434\u043D\u043E\u0433\u043E \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0430
+
+ILLEGAL_FIELD_SIGNATURE = \u041F\u043E\u043B\u0435 \u0442\u0438\u043F\u0430 {0} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F args4j
+
+
+# For Translation
+#-------------------
+# ILLEGAL_OPERAND = "{1}" is not a valid value for "{0}"
+# ILLEGAL_BOOLEAN = "{0}" is not a legal boolean value
+# ILLEGAL_CHAR = "{0}" must be a single character
+# ILLEGAL_LIST = type of {0} is not a List \ No newline at end of file
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/MethodSetter.java b/args4j/args4j/src/org/kohsuke/args4j/spi/MethodSetter.java
new file mode 100644
index 0000000..e6454f5
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/MethodSetter.java
@@ -0,0 +1,64 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.spi.Setter;
+import org.kohsuke.args4j.*;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * {@link Setter} that sets to a {@link Method}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public final class MethodSetter implements Setter {
+ private final CmdLineParser parser;
+ private final Object bean;
+ private final Method m;
+
+ public MethodSetter(CmdLineParser parser, Object bean, Method m) {
+ this.parser = parser;
+ this.bean = bean;
+ this.m = m;
+ if(m.getParameterTypes().length!=1)
+ throw new IllegalAnnotationError(Messages.ILLEGAL_METHOD_SIGNATURE.format(m));
+ }
+
+ public Class getType() {
+ return m.getParameterTypes()[0];
+ }
+
+ public boolean isMultiValued() {
+ return false;
+ }
+
+ public void addValue(Object value) throws CmdLineException {
+ try {
+ try {
+ m.invoke(bean,value);
+ } catch (IllegalAccessException _) {
+ // try again
+ m.setAccessible(true);
+ try {
+ m.invoke(bean,value);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAccessError(e.getMessage());
+ }
+ }
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getTargetException();
+ if(t instanceof RuntimeException)
+ throw (RuntimeException)t;
+ if(t instanceof Error)
+ throw (Error)t;
+ if(t instanceof CmdLineException)
+ throw (CmdLineException)t;
+
+ // otherwise wrap
+ if(t!=null)
+ throw new CmdLineException(parser, t);
+ else
+ throw new CmdLineException(parser, e);
+ }
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/MultiValueFieldSetter.java b/args4j/args4j/src/org/kohsuke/args4j/spi/MultiValueFieldSetter.java
new file mode 100644
index 0000000..7457070
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/MultiValueFieldSetter.java
@@ -0,0 +1,70 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.spi.Setter;
+import org.kohsuke.args4j.*;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link Setter} that sets multiple values to a collection {@link Field}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+final class MultiValueFieldSetter implements Setter {
+ private final Object bean;
+ private final Field f;
+
+ public MultiValueFieldSetter(Object bean, Field f) {
+ this.bean = bean;
+ this.f = f;
+
+ if(!List.class.isAssignableFrom(f.getType()))
+ throw new IllegalAnnotationError(Messages.ILLEGAL_FIELD_SIGNATURE.format(f.getType()));
+ }
+
+ public boolean isMultiValued() {
+ return true;
+ }
+
+ public Class getType() {
+ // TODO: compute this correctly
+ Type t = f.getGenericType();
+ if(t instanceof ParameterizedType) {
+ ParameterizedType pt = (ParameterizedType)t;
+ t = pt.getActualTypeArguments()[0];
+ if(t instanceof Class)
+ return (Class)t;
+ }
+ return Object.class;
+ }
+
+ public void addValue(Object value) {
+ try {
+ doAddValue(bean, value);
+ } catch (IllegalAccessException _) {
+ // try again
+ f.setAccessible(true);
+ try {
+ doAddValue(bean,value);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAccessError(e.getMessage());
+ }
+ }
+ }
+
+ private void doAddValue(Object bean, Object value) throws IllegalAccessException {
+ Object o = f.get(bean);
+ if(o==null) {
+ o = new ArrayList();
+ f.set(bean,o);
+ }
+ if(!(o instanceof List))
+ throw new IllegalAnnotationError(Messages.ILLEGAL_LIST.format(f));
+
+ ((List)o).add(value);
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/OneArgumentOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/OneArgumentOptionHandler.java
new file mode 100644
index 0000000..6501f8f
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/OneArgumentOptionHandler.java
@@ -0,0 +1,47 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+/**
+ * OptionHandler which handles an option with exactly one argument, like "-foo bar".
+ * @author Jan Materne
+ * @since 2.0.9
+ * @param <T> Type of the Setter-class
+ */
+public abstract class OneArgumentOptionHandler<T> extends OptionHandler<T> {
+
+ public OneArgumentOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super T> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "N";
+ }
+
+ @Override
+ public int parseArguments(Parameters params) throws CmdLineException {
+ String token = params.getParameter(0);
+ try {
+ T value = parse(token);
+ setter.addValue(value);
+ }
+ catch (NumberFormatException ex) {
+ throw new CmdLineException(owner, Messages.ILLEGAL_OPERAND.format(params.getParameter(-1),token));
+ }
+ return 1;
+ }
+
+ /**
+ * Parses a string to a real value of Type &lt;T&gt;.
+ * @param argument String value to parse
+ * @return the parsed value
+ * @throws NumberFormatException if parsing is not possible
+ * @throws CmdLineException
+ * if the parsing encounters a failure that should be reported to the user.
+ */
+ protected abstract T parse(String argument) throws NumberFormatException, CmdLineException;
+
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/OptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/OptionHandler.java
new file mode 100644
index 0000000..3697c5c
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/OptionHandler.java
@@ -0,0 +1,94 @@
+package org.kohsuke.args4j.spi;
+
+import java.util.ResourceBundle;
+
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.NamedOptionDef;
+
+
+/**
+ * Code that parses operands of an option into Java.
+ *
+ * <p>
+ * This class can be extended by application to support additional Java datatypes in option operands.
+ *
+ * <p>
+ * Implementation of this class needs to be registered to args4j by using
+ * {@link CmdLineParser#registerHandler(Class,Class)}
+ *
+ * @param <T>
+ * The type of the field that this {@link OptionHandler} works with.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public abstract class OptionHandler<T> {
+ /**
+ * The annotation.
+ */
+ public final OptionDef option;
+ /**
+ * Object to be used for setting value.
+ */
+ public final Setter<? super T> setter;
+ /**
+ * The owner to which this handler belongs to.
+ */
+ public final CmdLineParser owner;
+
+ protected OptionHandler(CmdLineParser parser, OptionDef option, Setter<? super T> setter) {
+ this.owner = parser;
+ this.option = option;
+ this.setter = setter;
+ }
+
+ /**
+ * Called if the option that this owner recognizes is found.
+ *
+ * @param params
+ * The rest of the arguments. This method can use this
+ * object to access the arguments of the option if necessary.
+ *
+ * The object is valid only during the method call.
+ *
+ * @return
+ * The number of arguments consumed. For example, return 0
+ * if this option doesn't take any parameter.
+ */
+ public abstract int parseArguments( Parameters params ) throws CmdLineException;
+
+ /**
+ * Gets the default meta variable name used to print the usage screen.
+ *
+ * @return null to hide a meta variable.
+ */
+ public abstract String getDefaultMetaVariable();
+
+ public final String getMetaVariable(ResourceBundle rb) {
+ String token = option.metaVar();
+ if(token.length()==0)
+ token = getDefaultMetaVariable();
+ if(token==null) return null;
+
+ if(rb!=null) {
+ String localized = rb.getString(token);
+ if(localized!=null)
+ token = localized;
+ }
+
+ return token;
+ }
+
+ public final String getNameAndMeta(ResourceBundle rb) {
+ String str = option.isArgument() ? "" : option.toString();
+ String meta = getMetaVariable(rb);
+ if (meta != null) {
+ if (str.length() > 0) {
+ str += " ";
+ }
+ str += meta;
+ }
+ return str;
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/OptionImpl.java b/args4j/args4j/src/org/kohsuke/args4j/spi/OptionImpl.java
new file mode 100644
index 0000000..e390fbc
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/OptionImpl.java
@@ -0,0 +1,18 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.Option;
+
+/**
+ * Implementation of @Option so we can instantiate it.
+ * @author Jan Materne
+ */
+public class OptionImpl extends AnnotationImpl implements Option {
+ public OptionImpl(ConfigElement ce) throws ClassNotFoundException {
+ super(Option.class,ce);
+ name = ce.name;
+ }
+ public String name;
+ public String name() {
+ return name;
+ }
+} \ No newline at end of file
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/Parameters.java b/args4j/args4j/src/org/kohsuke/args4j/spi/Parameters.java
new file mode 100644
index 0000000..9fc2e6b
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/Parameters.java
@@ -0,0 +1,34 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineException;
+
+/**
+ * List of arguments.
+ *
+ * <p>
+ * Object of this interface is passed to
+ * {@link OptionHandler}s to make it easy/safe to parse
+ * additional parameters for options.
+ */
+public interface Parameters {
+ /**
+ * Gets the additional parameter to this option.
+ *
+ * @param idx
+ * specifying 0 will retrieve the token next to the option.
+ * For example, if the command line looks like "-o abc -d x",
+ * then <code>getParameter(0)</code> for "-o" returns "abc"
+ * and <code>getParameter(1)</code> will return "-d".
+ *
+ * @return
+ * Always return non-null valid String. If an attempt is
+ * made to access a non-existent index, this method throws
+ * appropriate {@link org.kohsuke.args4j.CmdLineException}.
+ */
+ String getParameter(int idx) throws CmdLineException;
+
+ /**
+ * Number of remaining tokens.
+ */
+ int size();
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/RestOfArgumentsHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/RestOfArgumentsHandler.java
new file mode 100644
index 0000000..6cfdd7b
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/RestOfArgumentsHandler.java
@@ -0,0 +1,33 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.CmdLineException;
+
+/**
+ * Eagerly grabs all the arguments.
+ *
+ * <p>
+ * Used with {@link Argument}, this implements a semantics where
+ * non-option token causes the option parsing to terminate.
+ * An example of this is ssh(1), where "ssh -p 222 abc" will treat "-p" as an option
+ * to ssh but "ssh abc -p 222" is considered to have no option for ssh.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class RestOfArgumentsHandler extends OptionHandler<String> {
+ public RestOfArgumentsHandler(CmdLineParser cmdLineParser, OptionDef optionDef, Setter<String> setter) {
+ super(cmdLineParser, optionDef, setter);
+ }
+
+ public int parseArguments(Parameters parameters) throws CmdLineException {
+ for (int i=0; i<parameters.size(); i++)
+ setter.addValue(parameters.getParameter(i));
+ return parameters.size();
+ }
+
+ public String getDefaultMetaVariable() {
+ return "ARGS";
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/Setter.java b/args4j/args4j/src/org/kohsuke/args4j/spi/Setter.java
new file mode 100644
index 0000000..ac256d4
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/Setter.java
@@ -0,0 +1,29 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineException;
+
+/**
+ * Abstraction of the value setter.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public interface Setter<T> {
+ /**
+ * Adds/sets a value to the property of the option bean.
+ *
+ * <p>
+ * A {@link Setter} object has an implicit knowledge about the property it's setting,
+ * and the instance of the option bean.
+ */
+ void addValue(T value) throws CmdLineException;
+
+ /**
+ * Gets the type of the underlying method/field.
+ */
+ Class<T> getType();
+
+ /**
+ * Whether this setter is instrinsically multi-valued.
+ */
+ boolean isMultiValued();
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/Setters.java b/args4j/args4j/src/org/kohsuke/args4j/spi/Setters.java
new file mode 100644
index 0000000..0300053
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/Setters.java
@@ -0,0 +1,34 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.MapSetter;
+import org.kohsuke.args4j.CmdLineParser;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Factory of {@link Setter}s.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class Setters {
+ public static Setter create(CmdLineParser parser, AccessibleObject fieldOrMethod, Object bean) {
+ if (fieldOrMethod instanceof Method) {
+ return new MethodSetter(parser,bean,(Method) fieldOrMethod);
+ } else {
+ return create((Field)fieldOrMethod,bean);
+ }
+ }
+
+ public static Setter create(Field f, Object bean) {
+ if(List.class.isAssignableFrom(f.getType()))
+ return new MultiValueFieldSetter(bean,f);
+ else if(Map.class.isAssignableFrom(f.getType()))
+ return new MapSetter(bean,f);
+ else
+ return new FieldSetter(bean,f);
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/ShortOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/ShortOptionHandler.java
new file mode 100644
index 0000000..e459732
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/ShortOptionHandler.java
@@ -0,0 +1,24 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+/**
+ * {@link Short}
+ * {@link OptionHandler}
+ * {@link OneArgumentOptionHandler}
+ * @author Jan Materne
+ * @since 2.0.9
+ */
+public class ShortOptionHandler extends OneArgumentOptionHandler<Short> {
+
+ public ShortOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super Short> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ protected Short parse(String argument) throws NumberFormatException {
+ return Short.parseShort(argument);
+ }
+
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/StopOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/StopOptionHandler.java
new file mode 100644
index 0000000..16be42f
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/StopOptionHandler.java
@@ -0,0 +1,49 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+/**
+ * {@link OptionHandler} for the option terminator "--".
+ *
+ * <p>
+ * This {@link OptionHandler} can be used to implement the special token
+ * "--" that indicates that the rest of tokens are not options, but arguments.
+ *
+ * <p>
+ * For example, if you have the following class:
+ *
+ * <pre>
+ * class Foo {
+ * &#64;Argument
+ * &#64;Option(name="--",handler={@link StopOptionHandler}.class)
+ * List&lt;String> args;
+ *
+ * &#64;Option(name="-n")
+ * int n;
+ * }
+ * </pre>
+ *
+ * <p>
+ * The command line {@code -n 5 abc def} would parse into n=5, args={"abc",def"},
+ * but {@code -- -n 5 abc def} would parse into n=0, args={"-n","5","abc","def"}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class StopOptionHandler extends OptionHandler<String> {
+ public StopOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super String> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ public int parseArguments(Parameters params) throws CmdLineException {
+ owner.stopOptionParsing();
+ return 0;
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "ARGUMENTS";
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/StringArrayOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/StringArrayOptionHandler.java
new file mode 100644
index 0000000..2ae31ae
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/StringArrayOptionHandler.java
@@ -0,0 +1,79 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+import java.util.ArrayList;
+
+/**
+ * <p>
+ * An {@link OptionHandler} for handling {@link String[]} types. Can handle arrays of strings.
+ * </p>
+ * <p>
+ * <h1>How it works:</h1>
+ * Example for parameter -s, which is String[] type:<br>
+ * java -jar aaa.jar -s banan hruska jablko<br>
+ * java -jar aaa.jar -s banan "hruska jablko"<br>
+ * java -jar aaa.jar -s "banan hruska jablko"<br>
+ * java -jar aaa.jar -s banan hruska jablko -l 4 -r<br>
+ * java -jar aaa.jar -t 222 -s banan hruska jablko -r<br><br>
+ * It will handle all of these posibilites. This OptionHandler scans for parameter which begins
+ * with "-". If it found it, it will stop.
+ * </p>
+ *
+ * @author PlainText,LuVar
+ *
+ */
+public class StringArrayOptionHandler extends OptionHandler<String[]> {
+
+ public StringArrayOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super String[]> setter) {
+ super(parser, option, setter);
+ }
+
+ /**
+ * <p>
+ * Returns "STRING[]".
+ * </p>
+ *
+ * @return return "STRING[]";
+ */
+ @Override
+ public String getDefaultMetaVariable() {
+ return "STRING[]";
+ }
+
+ /**
+ * <p>
+ * Tryies to parse String[] argument from {@link Parameters}.
+ * </p>
+ */
+ @Override
+ public int parseArguments(Parameters params) throws CmdLineException {
+ int counter = 0;
+ ArrayList<String> values = new ArrayList<String>();
+ while(true) {
+ String param;
+ try {
+ param = params.getParameter(counter);
+ } catch (CmdLineException ex) {
+ break;
+ }
+ if(param.startsWith("-")) {
+ break;
+ }
+
+ for (String str : param.split(" ")) {
+ values.add(str);
+ }
+ counter++;
+ }//while true
+
+ // to work around a javac bug in Java1.5, we need to first assign this to
+ // the raw type.
+ Setter s = this.setter;
+ s.addValue(values.toArray(new String[values.size()]));
+ return counter;
+ }
+
+} \ No newline at end of file
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/StringOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/StringOptionHandler.java
new file mode 100644
index 0000000..0a9ff09
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/StringOptionHandler.java
@@ -0,0 +1,27 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+
+/**
+ * String {@link OptionHandler}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class StringOptionHandler extends OptionHandler<String> {
+ public StringOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super String> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ public int parseArguments(Parameters params) throws CmdLineException {
+ setter.addValue(params.getParameter(0));
+ return 1;
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "VAL";
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/URIOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/URIOptionHandler.java
new file mode 100644
index 0000000..3249b93
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/URIOptionHandler.java
@@ -0,0 +1,37 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * {@link URI} {@link OptionHandler}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class URIOptionHandler extends OptionHandler<URI> {
+ public URIOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super URI> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ public int parseArguments(Parameters params) throws CmdLineException {
+ String param = params.getParameter(0);
+ try {
+ setter.addValue(new URI(param));
+ return 1;
+ } catch (URISyntaxException e) {
+ throw new CmdLineException(owner, Messages.ILLEGAL_OPERAND.format(params.getParameter(-1),param));
+ }
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "URI";
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/URLOptionHandler.java b/args4j/args4j/src/org/kohsuke/args4j/spi/URLOptionHandler.java
new file mode 100644
index 0000000..64cd28a
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/URLOptionHandler.java
@@ -0,0 +1,36 @@
+package org.kohsuke.args4j.spi;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * {@link URL} {@link OptionHandler}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class URLOptionHandler extends OptionHandler<URL> {
+ public URLOptionHandler(CmdLineParser parser, OptionDef option, Setter<? super URL> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ public int parseArguments(Parameters params) throws CmdLineException {
+ String param = params.getParameter(0);
+ try {
+ setter.addValue(new URL(param));
+ return 1;
+ } catch (MalformedURLException e) {
+ throw new CmdLineException(owner, Messages.ILLEGAL_OPERAND.format(
+ params.getParameter(-1),param));
+ }
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "URL";
+ }
+}
diff --git a/args4j/args4j/src/org/kohsuke/args4j/spi/package.html b/args4j/args4j/src/org/kohsuke/args4j/spi/package.html
new file mode 100644
index 0000000..604f188
--- /dev/null
+++ b/args4j/args4j/src/org/kohsuke/args4j/spi/package.html
@@ -0,0 +1,5 @@
+<html><body>
+<p>
+Classes for extending the behavior of args4j.
+</p>
+</body></html> \ No newline at end of file
diff --git a/args4j/args4j/test/ExampleTest.java b/args4j/args4j/test/ExampleTest.java
new file mode 100644
index 0000000..85df342
--- /dev/null
+++ b/args4j/args4j/test/ExampleTest.java
@@ -0,0 +1,56 @@
+import java.io.File;
+
+import junit.framework.TestCase;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.ExampleMode;
+import org.kohsuke.args4j.Option;
+
+/**
+ * Tests {@link CmdLineParser#printExample(ExampleMode)}
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class ExampleTest extends TestCase {
+ @Option(required = true, name = "-a", usage = "this is X")
+ int x;
+
+ @Option(name = "-b", usage = "this is Y", metaVar = "<output>")
+ File y;
+
+ public void testPrintExampleModeAll() {
+ String s = new CmdLineParser(this).printExample(ExampleMode.ALL);
+ assertEquals(" -a N -b <output>", s);
+ }
+
+ public void testPrintExampleModeRequired() {
+ String s = new CmdLineParser(this).printExample(ExampleMode.REQUIRED);
+ assertEquals(" -a N", s);
+ }
+
+ public void testParsingAllArgs() throws Exception {
+ CmdLineParser parser = new CmdLineParser(this);
+ parser.parseArgument("-a", "1", "-b", "foo");
+ assertEquals(1, x);
+ assertEquals(new File("foo"), y);
+ }
+
+ public void testParsingOnlyRequiredArgs() throws Exception {
+ CmdLineParser parser = new CmdLineParser(this);
+ parser.parseArgument("-a", "1");
+ assertEquals(1, x);
+ assertNull(y);
+ }
+
+ public void testParsingMissingRequiredArgs() throws Exception {
+ CmdLineParser parser = new CmdLineParser(this);
+ try {
+ parser.parseArgument("-b", "foo");
+ fail("Should have thrown an exception because"
+ + " required arg 'a' is missing");
+ } catch (CmdLineException e) {
+ assertEquals("Option \"-a\" is required", e.getMessage());
+ }
+ }
+}
diff --git a/args4j/args4j/test/MandatoryOptionTest.java b/args4j/args4j/test/MandatoryOptionTest.java
new file mode 100644
index 0000000..6264166
--- /dev/null
+++ b/args4j/args4j/test/MandatoryOptionTest.java
@@ -0,0 +1,33 @@
+import junit.framework.TestCase;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.Option;
+
+/**
+ * Tests mandatory options.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class MandatoryOptionTest extends TestCase {
+ @Option(required=true,name="-a")
+ int x;
+
+ @Option(name="-b")
+ int y;
+
+ public void test1() throws Exception {
+ CmdLineParser p = new CmdLineParser(this);
+ p.parseArgument("-a","3","-b","2");
+ assertEquals(x,3);
+ assertEquals(y,2);
+
+ p = new CmdLineParser(this);
+ try {
+ p.parseArgument("-b","2");
+ fail();
+ } catch(CmdLineException e) {
+ System.out.println(e.getMessage());
+ assertTrue(e.getMessage().contains("-a"));
+ }
+ }
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/Aliased.java b/args4j/args4j/test/org/kohsuke/args4j/Aliased.java
new file mode 100644
index 0000000..34f2488
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/Aliased.java
@@ -0,0 +1,8 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.Option;
+
+public class Aliased {
+ @Option(name="-str",aliases={ "--long-str" },usage="set a string",metaVar="METAVAR")
+ public String str;
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/AliasedTest.java b/args4j/args4j/test/org/kohsuke/args4j/AliasedTest.java
new file mode 100644
index 0000000..2dbc6f0
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/AliasedTest.java
@@ -0,0 +1,30 @@
+package org.kohsuke.args4j;
+
+public class AliasedTest extends Args4JTestBase<Aliased> {
+ @Override
+ public Aliased getTestObject() {
+ return new Aliased();
+ }
+
+ public void testMissingParameter() {
+ setArgs("-str");
+ try {
+ parser.parseArgument(args);
+ fail("Should miss one parameter.");
+ } catch (CmdLineException e) {
+ String expectedError = "Option \"-str (--long-str)\" takes an operand";
+ String expectedUsage = " -str (--long-str) METAVAR : set a string";
+ String errorMessage = e.getMessage();
+ String[] usageLines = getUsageMessage();
+ assertUsageLength(1);
+ assertTrue("Got wrong error message: " + errorMessage, errorMessage.startsWith(expectedError));
+ assertEquals("Got wrong usage message", expectedUsage, usageLines[0]);
+ }
+ }
+
+ public void testAlias() throws Exception {
+ setArgs("--long-str", "something");
+ parser.parseArgument(args);
+ assertEquals("something", testObject.str);
+ }
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/Args4JTestBase.java b/args4j/args4j/test/org/kohsuke/args4j/Args4JTestBase.java
new file mode 100644
index 0000000..61ef0fd
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/Args4JTestBase.java
@@ -0,0 +1,130 @@
+package org.kohsuke.args4j;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+
+/**
+ * Base class for Args4J Tests.
+ * It instantiates the test object, the CmdLineParser for
+ * that test object and provides a String array for passing
+ * to the parser.
+ *
+ * @author Jan Materne
+ */
+public abstract class Args4JTestBase<T> extends TestCase {
+
+ CmdLineParser parser;
+ String[] args;
+ T testObject;
+
+ private Locale defaultLocale;
+
+ /**
+ * Specifies which concrete object to return as test object.
+ * @return the test object
+ */
+ public abstract T getTestObject();
+
+ /**
+ * Setter for args in a vararg manner.
+ * @param args
+ */
+ public void setArgs(String... args) {
+ this.args = args;
+ }
+
+ /**
+ * Returns the Locale to use for the tests.
+ * Defaults to use the US-Locale but should be overwritten by classes
+ * which tests I18N.
+ */
+ public Locale getLocale() {
+ return Locale.US;
+ }
+
+ /**
+ * Initializes the testObject and the parser for that object.
+ * @see junit.framework.TestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ defaultLocale = Locale.getDefault();
+ Locale.setDefault(getLocale());
+ testObject = getTestObject();
+ parser = createParser();
+ }
+
+ protected CmdLineParser createParser() {
+ return new CmdLineParser(testObject);
+ }
+
+ /**
+ * Restores the environment, namely the default Locale.
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ Locale.setDefault(defaultLocale);
+ }
+
+ /**
+ * Checks the number of lines of the parsers usage message.
+ * @param expectedLength
+ * @see TestCase#assertEquals(String, int, int)
+ * @see Args4JTestBase#getUsageMessage()
+ */
+ public void assertUsageLength(int expectedLength) {
+ assertEquals("Wrong amount of lines in usage message", expectedLength, getUsageMessage().length);
+ }
+
+ /**
+ * Asserts that a given text is part of the usage message.
+ * @param message Error message if the text is not found.
+ * @param containingText Text to search for.
+ */
+ public void assertUsageContains(String message, String containingText) {
+ boolean contains = false;
+ for (String line : getUsageMessage()) {
+ if (line.contains(containingText)) {
+ contains = true;
+ break;
+ }
+ }
+ if (!contains) {
+ throw new AssertionError(message);
+ }
+ }
+
+ /**
+ * Extracts the usage message from the parser as String array.
+ * @return the usage message
+ * @see CmdLineParser#printUsage(OutputStream)
+ */
+ public String[] getUsageMessage() {
+ Stream2String s2s = new Stream2String();
+ parser.printUsage(s2s);
+ return s2s.getString().split(System.getProperty("line.separator"));
+ }
+
+ /**
+ * Utility class for capturing an OutputStream into a String.
+ * @author Jan Materne
+ */
+ private class Stream2String extends OutputStream {
+ private StringBuffer sb = new StringBuffer();
+
+ @Override
+ public void write(int b) throws IOException {
+ sb.append((char)b);
+ }
+
+ public String getString() {
+ return sb.toString();
+ }
+ }
+
+} \ No newline at end of file
diff --git a/args4j/args4j/test/org/kohsuke/args4j/ArgumentTest.java b/args4j/args4j/test/org/kohsuke/args4j/ArgumentTest.java
new file mode 100644
index 0000000..6417dbf
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/ArgumentTest.java
@@ -0,0 +1,82 @@
+package org.kohsuke.args4j;
+
+import java.util.List;
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+public class ArgumentTest extends TestCase {
+ private Locale defaultLocale;
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ defaultLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ }
+ @Override
+ protected void tearDown() throws Exception {
+ Locale.setDefault(defaultLocale);
+ }
+
+
+
+ protected static class MultiValueHolder {
+ @Argument
+ public List<String> things;
+ }
+
+ protected static class SingleValueHolder {
+ @Argument(metaVar = "thing", required = true)
+ public String thing;
+ }
+
+ protected static class BooleanValueHolder {
+ @Argument(metaVar = "thing", required = true)
+ public boolean b;
+ }
+
+ public void testMultiValue() throws Exception {
+ MultiValueHolder holder = new MultiValueHolder();
+ CmdLineParser parser = new CmdLineParser(holder);
+ parser.parseArgument(new String[] { "one", "two" });
+
+ assertEquals(2, holder.things.size());
+ assertEquals("one", holder.things.get(0));
+ assertEquals("two", holder.things.get(1));
+ }
+
+ public void testTooFew() throws Exception {
+ SingleValueHolder holder = new SingleValueHolder();
+ CmdLineParser parser = new CmdLineParser(holder);
+
+ try {
+ parser.parseArgument(new String[] {});
+ } catch (CmdLineException e) {
+ assertEquals("Argument \"thing\" is required", e.getMessage());
+ return;
+ }
+ fail("expected " + CmdLineException.class);
+ }
+
+ public void testBoolean() throws Exception {
+ BooleanValueHolder holder = new BooleanValueHolder();
+ CmdLineParser parser = new CmdLineParser(holder);
+
+ parser.parseArgument(new String[] { "true" });
+
+ assertTrue(holder.b);
+ }
+
+ public void testIllegalBoolean() throws Exception {
+ BooleanValueHolder holder = new BooleanValueHolder();
+ CmdLineParser parser = new CmdLineParser(holder);
+
+ try {
+ parser.parseArgument(new String[] { "xyz" });
+ } catch (CmdLineException e) {
+ assertEquals("\"xyz\" is not a legal boolean value", e.getMessage());
+ return;
+ }
+ fail("expected " + CmdLineException.class);
+ }
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/Bean.java b/args4j/args4j/test/org/kohsuke/args4j/Bean.java
new file mode 100644
index 0000000..d2c4aaa
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/Bean.java
@@ -0,0 +1,9 @@
+/**
+ *
+ */
+package org.kohsuke.args4j;
+
+public class Bean {
+ String text = "default";
+ int number = -1;
+} \ No newline at end of file
diff --git a/args4j/args4j/test/org/kohsuke/args4j/CustomExceptionTest.java b/args4j/args4j/test/org/kohsuke/args4j/CustomExceptionTest.java
new file mode 100644
index 0000000..e7835de
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/CustomExceptionTest.java
@@ -0,0 +1,55 @@
+package org.kohsuke.args4j;
+
+// a 'custom' exception
+import javax.management.InvalidAttributeValueException;
+
+
+public class CustomExceptionTest extends Args4JTestBase<CustomExceptionTest> {
+
+ private String errMsgX = "this is a usual CLI exception";
+ private String errMsgY = "this is a 'custom' exception";
+
+
+ @Option(name="-x")
+ public void setX(String x) {
+ throw new IllegalArgumentException(errMsgX);
+ }
+
+ @Option(name="-y")
+ public void setY(String y) throws InvalidAttributeValueException {
+ throw new InvalidAttributeValueException(errMsgX);
+ }
+
+
+ @Override
+ public CustomExceptionTest getTestObject() {
+ return this;
+ }
+
+
+ protected void assertException(String expected, Class expectedExceptionClass, String... parserArgs) {
+ String expMsg = expectedExceptionClass.getName() + ": " + expected;
+ try {
+ parser.parseArgument(parserArgs);
+ fail("Exception expected.");
+ } catch (RuntimeException e) {
+ // RuntimeExceptions are passed through the parser to the caller.
+ assertEquals("Lost exception message.", expMsg, e.toString());
+ } catch (CmdLineException e) {
+ // Other Exceptions are wrapped into a CLE so we must ensure not to loose the
+ // message.
+ assertEquals("Lost exception message.", expMsg, e.getMessage());
+ } catch (Exception e) {
+ fail("Wrong exception type thrown.");
+ }
+ }
+
+ public void testRuntimeException() throws Exception {
+ assertException(errMsgX, IllegalArgumentException.class, "-x", "value");
+ }
+
+ public void testCustomException() throws Exception {
+ assertException(errMsgX, InvalidAttributeValueException.class, "-y", "value");
+ }
+
+} \ No newline at end of file
diff --git a/args4j/args4j/test/org/kohsuke/args4j/EnumArgument.java b/args4j/args4j/test/org/kohsuke/args4j/EnumArgument.java
new file mode 100644
index 0000000..5207adc
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/EnumArgument.java
@@ -0,0 +1,6 @@
+package org.kohsuke.args4j;
+
+class EnumArgument {
+ @Argument(required = true, metaVar="ANIMAL")
+ EnumAttribute.Animal myAnimal;
+} \ No newline at end of file
diff --git a/args4j/args4j/test/org/kohsuke/args4j/EnumArgumentTest.java b/args4j/args4j/test/org/kohsuke/args4j/EnumArgumentTest.java
new file mode 100644
index 0000000..917b96c
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/EnumArgumentTest.java
@@ -0,0 +1,43 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.EnumAttribute.Animal;
+
+import junit.framework.Assert;
+
+
+public class EnumArgumentTest extends Args4JTestBase<EnumArgument> {
+
+ @Override
+ public EnumArgument getTestObject() {
+ return new EnumArgument();
+ }
+
+ public void testSetEnum() throws CmdLineException {
+ args = new String[]{"HORSE"};
+ assertEquals(null, testObject.myAnimal);
+ parser.parseArgument(args);
+ assertEquals(Animal.HORSE, testObject.myAnimal);
+ }
+
+ public void testSetEnumCaseInsensitive() throws CmdLineException {
+ args = new String[]{"horse"};
+ assertEquals(null, testObject.myAnimal);
+ parser.parseArgument(args);
+ assertEquals(Animal.HORSE, testObject.myAnimal);
+ }
+
+ public void testIllegalArgumentOption() {
+ args = new String[] { "ILLEGAL_ANIMAL" };
+ try {
+ parser.parseArgument(args);
+ Assert.fail();
+ } catch (CmdLineException e) {
+ Assert.assertTrue(
+ "Illegal exception message: " + e.getMessage(),
+ e.getMessage().startsWith(
+ String.format("\"%s\" is not a valid value for \"", args[args.length - 1])
+ ));
+ }
+ }
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/EnumAttribute.java b/args4j/args4j/test/org/kohsuke/args4j/EnumAttribute.java
new file mode 100644
index 0000000..c219eee
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/EnumAttribute.java
@@ -0,0 +1,10 @@
+package org.kohsuke.args4j;
+
+public class EnumAttribute {
+
+ enum Animal { HORSE, DUCK }
+
+ @Option(name="-animal", usage="Give your favorite animal.")
+ Animal myAnimal;
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/EnumAttributeTest.java b/args4j/args4j/test/org/kohsuke/args4j/EnumAttributeTest.java
new file mode 100644
index 0000000..ccc9786
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/EnumAttributeTest.java
@@ -0,0 +1,44 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.EnumAttribute.Animal;
+
+public class EnumAttributeTest extends Args4JTestBase<EnumAttribute> {
+
+ @Override
+ public EnumAttribute getTestObject() {
+ return new EnumAttribute();
+ }
+
+ public void testSetEnum() throws CmdLineException {
+ args = new String[]{"-animal", "HORSE"};
+ parser.parseArgument(args);
+ assertEquals(Animal.HORSE, testObject.myAnimal);
+ }
+
+ public void testSetEnumCaseInsensitive() throws CmdLineException {
+ args = new String[]{"-animal", "horse"};
+ parser.parseArgument(args);
+ assertEquals(Animal.HORSE, testObject.myAnimal);
+ }
+
+ public void testIllegalEnum() {
+ args = new String[]{"-animal", "ILLEGAL_ANIMAL"};
+ try {
+ parser.parseArgument(args);
+ fail("Can't set ILLEGAL_ANIMAL as value.");
+ } catch (CmdLineException e) {
+ // exptected
+ }
+ }
+
+ public void testUsage() {
+ args = new String[]{"-wrong"};
+ try {
+ parser.parseArgument(args);
+ } catch (CmdLineException e) {
+ assertUsageContains("Usage message should contain the enum VALUES", "HORSE");
+ assertUsageContains("Usage message should contain the enum VALUES", "DUCK");
+ }
+ }
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/ExplicitBooleanArgumentTest.java b/args4j/args4j/test/org/kohsuke/args4j/ExplicitBooleanArgumentTest.java
new file mode 100644
index 0000000..94ff3b4
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/ExplicitBooleanArgumentTest.java
@@ -0,0 +1,101 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.ExplicitBooleanArgumentTest.BooleanArgumentHolder;
+import org.kohsuke.args4j.spi.ExplicitBooleanOptionHandler;
+
+public class ExplicitBooleanArgumentTest extends Args4JTestBase<BooleanArgumentHolder> {
+
+ public static class BooleanArgumentHolder {
+ @Argument(index = 0, handler = ExplicitBooleanOptionHandler.class, usage = "Set a boolean value")
+ boolean booleanArg;
+ }
+
+ @Override
+ public BooleanArgumentHolder getTestObject() {
+ return new BooleanArgumentHolder();
+ }
+
+ public void testSetBooleanTrue() throws CmdLineException {
+ args = new String[] { "true" };
+ parser.parseArgument(args);
+ assertTrue(testObject.booleanArg);
+ }
+
+ public void testSetBooleanOn() throws CmdLineException {
+ args = new String[] { "on" };
+ parser.parseArgument(args);
+ assertTrue(testObject.booleanArg);
+ }
+
+ public void testSetBooleanYes() throws CmdLineException {
+ args = new String[] { "yes" };
+ parser.parseArgument(args);
+ assertTrue(testObject.booleanArg);
+ }
+
+ public void testSetBooleanTrueCaseInsensitive() throws CmdLineException {
+ args = new String[] { "tRuE" };
+ parser.parseArgument(args);
+ assertTrue(testObject.booleanArg);
+ }
+
+ public void testSetBoolean1() throws CmdLineException {
+ args = new String[] { "1" };
+ parser.parseArgument(args);
+ assertTrue(testObject.booleanArg);
+ }
+
+ public void testSetBooleanFalse() throws CmdLineException {
+ args = new String[] { "false" };
+ parser.parseArgument(args);
+ assertFalse(testObject.booleanArg);
+ }
+
+ public void testSetBooleanOff() throws CmdLineException {
+ args = new String[] { "off" };
+ parser.parseArgument(args);
+ assertFalse(testObject.booleanArg);
+ }
+
+ public void testSetBooleanNo() throws CmdLineException {
+ args = new String[] { "no" };
+ parser.parseArgument(args);
+ assertFalse(testObject.booleanArg);
+ }
+
+ public void testSetBoolean0() throws CmdLineException {
+ args = new String[] { "0" };
+ parser.parseArgument(args);
+ assertFalse(testObject.booleanArg);
+ }
+
+ public void testSetBooleanFalseCaseInsensitive() throws CmdLineException {
+ args = new String[] { "FaLsE" };
+ parser.parseArgument(args);
+ assertFalse(testObject.booleanArg);
+ }
+
+ public void testSetBooleanNoValueIsFalse() throws CmdLineException {
+ args = new String[0];
+ parser.parseArgument(args);
+ assertFalse(testObject.booleanArg);
+ }
+
+ public void testIllegalBoolean() {
+ args = new String[] { "ILLEGAL_BOOLEAN" };
+ try {
+ parser.parseArgument(args);
+ fail("Can't set ILLEGAL_BOOLEAN as value.");
+ } catch (CmdLineException expected) {}
+ }
+
+ public void testUsage() {
+ args = new String[] { "-wrong" };
+ try {
+ parser.parseArgument(args);
+ } catch (CmdLineException e) {
+ assertUsageContains("Usage message should contain '[VAL]'", "[VAL]");
+ }
+ }
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/ExplicitBooleanOptionTest.java b/args4j/args4j/test/org/kohsuke/args4j/ExplicitBooleanOptionTest.java
new file mode 100644
index 0000000..85b710b
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/ExplicitBooleanOptionTest.java
@@ -0,0 +1,110 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.ExplicitBooleanOptionTest.BooleanOptionHolder;
+import org.kohsuke.args4j.spi.ExplicitBooleanOptionHandler;
+
+public class ExplicitBooleanOptionTest extends Args4JTestBase<BooleanOptionHolder> {
+
+ public static class BooleanOptionHolder {
+ @Option(name = "-booleanOpt", handler = ExplicitBooleanOptionHandler.class, usage = "Set a boolean value")
+ boolean booleanOpt;
+
+ @Option(name = "-nextArg")
+ boolean nextArg;
+ }
+
+ @Override
+ public BooleanOptionHolder getTestObject() {
+ return new BooleanOptionHolder();
+ }
+
+ public void testSetBooleanTrue() throws CmdLineException {
+ args = new String[] { "-booleanOpt", "true" };
+ parser.parseArgument(args);
+ assertTrue(testObject.booleanOpt);
+ }
+
+ public void testSetBooleanOn() throws CmdLineException {
+ args = new String[] { "-booleanOpt", "on" };
+ parser.parseArgument(args);
+ assertTrue(testObject.booleanOpt);
+ }
+
+ public void testSetBooleanYes() throws CmdLineException {
+ args = new String[] { "-booleanOpt", "yes" };
+ parser.parseArgument(args);
+ assertTrue(testObject.booleanOpt);
+ }
+
+ public void testSetBooleanTrueCaseInsensitive() throws CmdLineException {
+ args = new String[] { "-booleanOpt", "tRuE" };
+ parser.parseArgument(args);
+ assertTrue(testObject.booleanOpt);
+ }
+
+ public void testSetBoolean1() throws CmdLineException {
+ args = new String[] { "-booleanOpt", "1" };
+ parser.parseArgument(args);
+ assertTrue(testObject.booleanOpt);
+ }
+
+ public void testSetBooleanFalse() throws CmdLineException {
+ args = new String[] { "-booleanOpt", "false" };
+ parser.parseArgument(args);
+ assertFalse(testObject.booleanOpt);
+ }
+
+ public void testSetBooleanOff() throws CmdLineException {
+ args = new String[] { "-booleanOpt", "off" };
+ parser.parseArgument(args);
+ assertFalse(testObject.booleanOpt);
+ }
+
+ public void testSetBooleanNo() throws CmdLineException {
+ args = new String[] { "-booleanOpt", "no" };
+ parser.parseArgument(args);
+ assertFalse(testObject.booleanOpt);
+ }
+
+ public void testSetBoolean0() throws CmdLineException {
+ args = new String[] { "-booleanOpt", "0" };
+ parser.parseArgument(args);
+ assertFalse(testObject.booleanOpt);
+ }
+
+ public void testSetBooleanFalseCaseInsensitive() throws CmdLineException {
+ args = new String[] { "-booleanOpt", "FaLsE" };
+ parser.parseArgument(args);
+ assertFalse(testObject.booleanOpt);
+ }
+
+ public void testSetBooleanLastArgIsTrue() throws CmdLineException {
+ args = new String[] { "-booleanOpt" };
+ parser.parseArgument(args);
+ assertTrue(testObject.booleanOpt);
+ }
+
+ public void testSetBooleanWithoutParamIsTrue() throws CmdLineException {
+ args = new String[] { "-booleanOpt", "-nextArg" };
+ parser.parseArgument(args);
+ assertTrue(testObject.booleanOpt);
+ }
+
+ public void testIllegalBoolean() {
+ args = new String[] { "-booleanOpt", "ILLEGAL_BOOLEAN" };
+ try {
+ parser.parseArgument(args);
+ fail("Can't set ILLEGAL_BOOLEAN as value.");
+ } catch (CmdLineException expected) {}
+ }
+
+ public void testUsage() {
+ args = new String[] { "-wrong" };
+ try {
+ parser.parseArgument(args);
+ } catch (CmdLineException e) {
+ assertUsageContains("Usage message should contain '[VAL]'", "[VAL]");
+ }
+ }
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/ExternalConfiguredTest.java b/args4j/args4j/test/org/kohsuke/args4j/ExternalConfiguredTest.java
new file mode 100644
index 0000000..5d09d9b
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/ExternalConfiguredTest.java
@@ -0,0 +1,68 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.XmlParser;
+import org.xml.sax.InputSource;
+
+import java.io.File;
+import java.util.List;
+
+public class ExternalConfiguredTest extends Args4JTestBase<ExternalConfiguredTest> {
+
+ boolean recursive = false;
+ File out;
+ String str = "default";
+ public void setStr(String s) {
+ str = s.toUpperCase();
+ }
+ boolean data = false;
+ List<String> arguments;
+
+ @Override
+ public ExternalConfiguredTest getTestObject() {
+ return this;
+ }
+
+ @Override
+ protected CmdLineParser createParser() {
+ CmdLineParser p = new CmdLineParser(new Object());
+ new XmlParser().parse(getClass().getResource("ExternalConfiguredTest.xml"),p,this);
+ return p;
+ }
+
+ public void testNoArgsGiven() throws CmdLineException {
+ args = new String[] {};
+ parser.parseArgument(args);
+ assertTrue("Default value for 'str'.", "default".equals(str));
+ assertFalse("Default for 'recursive'.", recursive);
+ assertFalse("Default for 'data'.", data);
+ }
+
+ public void testFieldSetter() throws CmdLineException {
+ args = new String[] { "-o", "myfile.txt" };
+ parser.parseArgument(args);
+ assertTrue("Default value for 'str'.", "default".equals(str));
+ assertFalse("Default for 'recursive'.", recursive);
+ assertFalse("Default for 'data'.", data);
+ assertEquals("myfile.txt", out.getName());
+ }
+
+ public void testMethodSetter() throws CmdLineException {
+ args = new String[] { "-str", "myvalue" };
+ parser.parseArgument(args);
+ assertFalse("Default for 'recursive'.", recursive);
+ assertFalse("Default for 'data'.", data);
+ assertTrue("Method setter for '-str' doesnt work.", "MYVALUE".equals(str));
+ }
+
+ public void testCustomHandler() throws CmdLineException {
+ args = new String[] { "-custom" };
+ parser.parseArgument(args);
+ assertTrue("Default value set.", "default".equals(str));
+ assertFalse("Default for 'recursive'.", recursive);
+ assertTrue("Value per custom handler on 'data' not set.", data);
+ }
+
+ public void testUsage() {
+ assertUsageContains("'usage' is not evaluated", "recursively run something");
+ }
+} \ No newline at end of file
diff --git a/args4j/args4j/test/org/kohsuke/args4j/ExternalConfiguredTest.xml b/args4j/args4j/test/org/kohsuke/args4j/ExternalConfiguredTest.xml
new file mode 100644
index 0000000..8b1923d
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/ExternalConfiguredTest.xml
@@ -0,0 +1,8 @@
+<!-- for example\SampleMain -->
+<args>
+ <option field="recursive" name="-r" usage="recursively run something"/>
+ <option field="out" name="-o" usage="output to this file" metavar="OUTPUT"/>
+ <option method="setStr(String)" name="-str"/>
+ <option field="data" name="-custom" handler="org.kohsuke.args4j.spi.BooleanOptionHandler" usage="boolean value for checking the custom handler"/>
+ <argument field="arguments"/>
+</args> \ No newline at end of file
diff --git a/args4j/args4j/test/org/kohsuke/args4j/FieldParserTest.java b/args4j/args4j/test/org/kohsuke/args4j/FieldParserTest.java
new file mode 100644
index 0000000..9268e9f
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/FieldParserTest.java
@@ -0,0 +1,35 @@
+package org.kohsuke.args4j;
+
+import junit.framework.TestCase;
+
+public class FieldParserTest extends TestCase {
+
+ private void parse(Object bean, String... args) throws CmdLineException, ClassNotFoundException {
+ CmdLineParser p = new CmdLineParser(new Object());
+ new FieldParser().parse(p, bean);
+ p.parseArgument(args);
+ }
+
+ public void testNoArgs() throws CmdLineException, ClassNotFoundException {
+ Bean bean = new Bean();
+ parse(bean);
+ assertEquals("default", bean.text);
+ assertEquals(-1, bean.number);
+ }
+
+ public void testFields() throws CmdLineException, ClassNotFoundException {
+ Bean bean = new Bean();
+ parse(bean, "-text", "newText", "-number", "42");
+ assertEquals("newText", bean.text);
+ assertEquals(42, bean.number);
+ }
+
+ public void testInheritedFields() throws CmdLineException, ClassNotFoundException {
+ InheritedBean bean = new InheritedBean();
+ parse(bean, "-text", "newText", "-number", "42", "-text2", "newText");
+ assertEquals("newText", bean.text2);
+ assertEquals("newText", bean.text);
+ assertEquals(42, bean.number);
+ }
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/Inheritance.java b/args4j/args4j/test/org/kohsuke/args4j/Inheritance.java
new file mode 100644
index 0000000..4ba4476
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/Inheritance.java
@@ -0,0 +1,13 @@
+package org.kohsuke.args4j;
+
+public class Inheritance extends InheritanceFather implements InheritanceMother {
+ @Option(name="-m")
+ public String me;
+
+ public String mom;
+ public void setMom(String m) {
+ mom = m;
+ }
+
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/InheritanceFather.java b/args4j/args4j/test/org/kohsuke/args4j/InheritanceFather.java
new file mode 100644
index 0000000..7ce38e6
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/InheritanceFather.java
@@ -0,0 +1,6 @@
+package org.kohsuke.args4j;
+
+public class InheritanceFather extends InheritanceGrandfather {
+ @Option(name="-f")
+ public String father;
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/InheritanceGrandfather.java b/args4j/args4j/test/org/kohsuke/args4j/InheritanceGrandfather.java
new file mode 100644
index 0000000..9d68e4f
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/InheritanceGrandfather.java
@@ -0,0 +1,6 @@
+package org.kohsuke.args4j;
+
+public class InheritanceGrandfather {
+ @Option(name="-g")
+ public String grandpa;
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/InheritanceMother.java b/args4j/args4j/test/org/kohsuke/args4j/InheritanceMother.java
new file mode 100644
index 0000000..2e57f46
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/InheritanceMother.java
@@ -0,0 +1,6 @@
+package org.kohsuke.args4j;
+
+public interface InheritanceMother {
+ @Option(name="-mom")
+ public void setMom(String m);
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/InheritanceTest.java b/args4j/args4j/test/org/kohsuke/args4j/InheritanceTest.java
new file mode 100644
index 0000000..1bc43ed
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/InheritanceTest.java
@@ -0,0 +1,54 @@
+package org.kohsuke.args4j;
+
+public class InheritanceTest extends Args4JTestBase<Inheritance> {
+
+ @Override
+ public Inheritance getTestObject() {
+ return new Inheritance();
+ }
+
+ public void testMyself() {
+ args = new String[]{"-m","Thats me"};
+ Inheritance bo = testObject;
+ try {
+ parser.parseArgument(args);
+ assertEquals("Value for class itself not arrived", "Thats me", bo.me);
+ } catch (CmdLineException e) {
+ fail("This exception should not occur");
+ }
+ }
+
+ public void testFather() {
+ args = new String[]{"-f","My father"};
+ Inheritance bo = testObject;
+ try {
+ parser.parseArgument(args);
+ assertEquals("Value for class itself not arrived", "My father", bo.father);
+ } catch (CmdLineException e) {
+ fail("This exception should not occur");
+ }
+ }
+
+ public void testGrandfather() {
+ args = new String[]{"-g","My fathers father"};
+ Inheritance bo = testObject;
+ try {
+ parser.parseArgument(args);
+ assertEquals("Value for class itself not arrived", "My fathers father", bo.grandpa);
+ } catch (CmdLineException e) {
+ fail("This exception should not occur");
+ }
+ }
+
+ public void testMother() {
+ args = new String[]{"-mom","Hi Mom"};
+ Inheritance bo = testObject;
+ try {
+ parser.parseArgument(args);
+ assertNull("Annotations are not designed for use in interfaces", bo.mom);
+ } catch (CmdLineException e) {
+ //no-op
+ }
+ }
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/InheritedBean.java b/args4j/args4j/test/org/kohsuke/args4j/InheritedBean.java
new file mode 100644
index 0000000..e71bb11
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/InheritedBean.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+package org.kohsuke.args4j;
+
+public class InheritedBean extends Bean{
+ String text2 = "default";
+} \ No newline at end of file
diff --git a/args4j/args4j/test/org/kohsuke/args4j/Issue10Test.java b/args4j/args4j/test/org/kohsuke/args4j/Issue10Test.java
new file mode 100644
index 0000000..fa6acd8
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/Issue10Test.java
@@ -0,0 +1,29 @@
+package org.kohsuke.args4j;
+
+import java.io.ByteArrayOutputStream;
+
+import junit.framework.TestCase;
+
+/**
+ * @see https://args4j.dev.java.net/issues/show_bug.cgi?id=10
+ */
+@SuppressWarnings("unused")
+public class Issue10Test extends TestCase {
+ @Option(name="-enum", required=false, usage="Enum2")
+ private Enum crash;
+
+ enum Enum {
+ THIS, ENUM, HAS, A, VERY, LONG, USAGE, LINE,
+ BECAUSE, OF, ITS, HUGE, LIST, Of, VALUES,
+ SO, IT, WILL, CRASH
+ }
+
+ // The bug should be fixed with changing from manual printing to printf.
+ public void testIssue10() {
+ CmdLineParser parser = new CmdLineParser(this);
+ parser.printUsage(new ByteArrayOutputStream());
+ // occurred error: StringIndexOutOfBoundsException with index < 0
+
+ }
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/LongUsage.java b/args4j/args4j/test/org/kohsuke/args4j/LongUsage.java
new file mode 100644
index 0000000..173a0da
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/LongUsage.java
@@ -0,0 +1,18 @@
+package org.kohsuke.args4j;
+
+/**
+ * Test object for long option names.
+ * One short and one long name to 'see' the differences.
+ *
+ * @author Jan Materne
+ */
+@SuppressWarnings("unused")
+public class LongUsage {
+
+ @Option(name="-LongNamedStringOption",usage="set a string",metaVar="USE_A_NICE_STRING")
+ private String s;
+
+ @Option(name="-i",usage="set an int")
+ private int i;
+
+} \ No newline at end of file
diff --git a/args4j/args4j/test/org/kohsuke/args4j/LongUsageTest.java b/args4j/args4j/test/org/kohsuke/args4j/LongUsageTest.java
new file mode 100644
index 0000000..8c25f72
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/LongUsageTest.java
@@ -0,0 +1,26 @@
+package org.kohsuke.args4j;
+
+public class LongUsageTest extends Args4JTestBase<LongUsage> {
+ @Override
+ public LongUsage getTestObject() {
+ return new LongUsage();
+ }
+
+ public void testUsageMessage() {
+ args = new String[]{"-wrong-usage"};
+ try {
+ // set Widescreen otherwise a line wrapping must occur
+ parser.setUsageWidth(120);
+ // start parsing
+ parser.parseArgument(args);
+ } catch (CmdLineException e) {
+ String expectedLine1 = " -LongNamedStringOption USE_A_NICE_STRING : set a string";
+ String expectedLine2 = " -i N : set an int";
+ String[] usageLines = getUsageMessage();
+ assertUsageLength(2);
+ assertEquals("First line wrong", expectedLine1, usageLines[0]);
+ assertEquals("Second line wrong", expectedLine2, usageLines[1]);
+ }
+ }
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/MultivaluedTest.java b/args4j/args4j/test/org/kohsuke/args4j/MultivaluedTest.java
new file mode 100644
index 0000000..a4ce79d
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/MultivaluedTest.java
@@ -0,0 +1,64 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.spi.StopOptionHandler;
+
+import java.util.List;
+
+public class MultivaluedTest extends Args4JTestBase<MultivaluedTest> {
+
+ // The JavaBean part of this class as test object.
+
+ // On Lists the @Option(multiValued) defaults to 'true'
+ @Option(name="-list")
+ List<String> list;
+
+ @Option(name="-string", multiValued=true)
+ String string;
+
+ // There is no OptionHandler for Arrays
+ //@Option(name="-array", multiValued=true)
+ String[] array;
+
+ // The JUnit part of this class as tester.
+
+ @Override
+ public MultivaluedTest getTestObject() {
+ return this;
+ }
+
+ public void testOnList() throws Exception {
+ // The 'command line invocation'.
+ setArgs(
+ "-list", "one",
+ "-list", "two",
+ "-list", "three"
+ );
+ parser.parseArgument(args);
+ // Check the results.
+ assertEquals("Should got three values", 3, list.size());
+ assertTrue(list.contains("one"));
+ assertTrue(list.contains("two"));
+ assertTrue(list.contains("three"));
+ }
+
+ //TODO: How to use 'multiValued' on plain fields?
+ // We have to option for Strings or CharacterSequence's to specify a separator
+ // and concating all values.
+ // @Option(... multiValued=true, seperator=",") String s; --> "one,two,three"
+ // As the use of 'separator' (new!) implies multiValued this would be more user friendly:
+ // @Option(... seperator=",") String s; --> "one,two,three"
+ // But how to handle other types like int,MyClass? Concatinating is not an option here...
+ public void t_estOnString() throws Exception {
+ // The 'command line invocation'.
+ parser.parseArgument("-string","one","-string","two","-string","three");
+ }
+
+ //TODO: How to use 'multiValued' on arrays?
+ // There should be no difference to use on lists (from the user point of view).
+ public void t_estOnArray() throws Exception {
+ // The 'command line invocation'.
+ parser.parseArgument("-array","one","-array","two","-array","three");
+ // Check the results.
+ assertEquals("Should got three values", 3, array.length);
+ }
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/NativeTypes.java b/args4j/args4j/test/org/kohsuke/args4j/NativeTypes.java
new file mode 100644
index 0000000..a7fbc29
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/NativeTypes.java
@@ -0,0 +1,29 @@
+package org.kohsuke.args4j;
+
+@SuppressWarnings("unused")
+public class NativeTypes {
+
+ @Option(name="-boolean")
+ public boolean _boolean;
+
+ @Option(name="-byte")
+ public byte _byte;
+
+ @Option(name="-char")
+ public char _char;
+
+ @Option(name="-double")
+ public double _double;
+
+ @Option(name="-float")
+ public float _float;
+
+ @Option(name="-int")
+ public int _int;
+
+ @Option(name="-long")
+ public long _long;
+
+ @Option(name="-short")
+ public short _short;
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/NativeTypesTest.java b/args4j/args4j/test/org/kohsuke/args4j/NativeTypesTest.java
new file mode 100644
index 0000000..9d2f280
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/NativeTypesTest.java
@@ -0,0 +1,63 @@
+package org.kohsuke.args4j;
+
+public class NativeTypesTest extends Args4JTestBase<NativeTypes> {
+
+ @Override
+ public NativeTypes getTestObject() {
+ return new NativeTypes();
+ }
+
+ public void testBooleanTrue() throws CmdLineException {
+ args = new String[]{"-boolean"};
+ parser.parseArgument(args);
+ assertTrue(testObject._boolean);
+ }
+
+ public void testBooleanFalse() throws CmdLineException {
+ args = new String[]{};
+ parser.parseArgument(args);
+ assertFalse(testObject._boolean);
+ }
+
+ public void testByte() throws CmdLineException {
+ args = new String[]{"-byte", "42"};
+ parser.parseArgument(args);
+ assertEquals(42, testObject._byte);
+ }
+
+ public void testChar() throws CmdLineException {
+ args = new String[]{"-char", "a"};
+ parser.parseArgument(args);
+ assertEquals('a', testObject._char);
+ }
+
+ public void testDouble() throws CmdLineException {
+ args = new String[]{"-double", "42"};
+ parser.parseArgument(args);
+ assertEquals(42, testObject._double, 0);
+ }
+
+ public void testFloat() throws CmdLineException {
+ args = new String[]{"-float", "42"};
+ parser.parseArgument(args);
+ assertEquals(42, testObject._float, 0);
+ }
+
+ public void testInt() throws CmdLineException {
+ args = new String[]{"-int", "42"};
+ parser.parseArgument(args);
+ assertEquals(42, testObject._int);
+ }
+
+ public void testLong() throws CmdLineException {
+ args = new String[]{"-long", "42"};
+ parser.parseArgument(args);
+ assertEquals(42, testObject._long);
+ }
+
+ public void testShort() throws CmdLineException {
+ args = new String[]{"-short", "42"};
+ parser.parseArgument(args);
+ assertEquals(42, testObject._short);
+ }
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/PrintUsageTest.java b/args4j/args4j/test/org/kohsuke/args4j/PrintUsageTest.java
new file mode 100644
index 0000000..1ce74aa
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/PrintUsageTest.java
@@ -0,0 +1,36 @@
+package org.kohsuke.args4j;
+
+public class PrintUsageTest extends Args4JTestBase {
+
+ private class Bean {
+ @Option(name = "s", usage = "1234567890123456789012345678901234567890")
+ public String s;
+ }
+
+ @Override
+ public Object getTestObject() {
+ return new Bean();
+ }
+
+ public void testEnoughLength() {
+ String[] args = { "-wrong" };
+ try {
+ parser.parseArgument(args);
+ } catch (CmdLineException e) {
+ String[] usageMessage = getUsageMessage();
+ assertEquals("Shouldn't split the lines.", 1, usageMessage.length);
+ }
+ }
+
+ public void testTooSmallLength() {
+ String[] args = { "-wrong" };
+ try {
+ parser.setUsageWidth(30);
+ parser.parseArgument(args);
+ } catch (CmdLineException e) {
+ String[] usageMessage = getUsageMessage();
+ assertEquals("Should split the lines.", 2, usageMessage.length);
+ }
+ }
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/Props.java b/args4j/args4j/test/org/kohsuke/args4j/Props.java
new file mode 100644
index 0000000..66b83ea
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/Props.java
@@ -0,0 +1,16 @@
+package org.kohsuke.args4j;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Test object for setting name-value pairs.
+ * @author Jan Materne
+ * @since 2.0.9
+ */
+public class Props {
+
+ @Option(name="-T",usage="sets a key-value-pair")
+ public Map<String,String> props = new HashMap<String, String>();
+
+} \ No newline at end of file
diff --git a/args4j/args4j/test/org/kohsuke/args4j/PropsTest.java b/args4j/args4j/test/org/kohsuke/args4j/PropsTest.java
new file mode 100644
index 0000000..06889d9
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/PropsTest.java
@@ -0,0 +1,119 @@
+package org.kohsuke.args4j;
+
+import java.util.Map;
+
+public class PropsTest extends Args4JTestBase<Props> {
+
+ @Override
+ public Props getTestObject() {
+ return new Props();
+ }
+
+ public void testDoNothing() {
+ // ignore, that the other test cases are commented out
+ // JUnit doesnt like TestCases without a test-method.
+ }
+
+ public void testNoValues() {
+ args = new String[]{};
+ try {
+ parser.parseArgument(args);
+ Map<String,String> map = testObject.props;
+ if (map == null) {
+ // as expected
+ return;
+ }
+ assertTrue("Values illegally arrived.", map.size()==0);
+ } catch (CmdLineException e) {
+ fail("Call without parameters is valid! " + e.getMessage());
+ }
+ }
+
+ public void testSinglePair() {
+ args = new String[]{"-T", "key1=value1"};
+ try {
+ parser.parseArgument(args);
+ Map<String,String> map = testObject.props;
+ assertTrue("The key was not set.", map.containsKey("key1"));
+ assertEquals("More keys than expected.", map.size(), 1);
+ assertEquals("Key has wrong value", map.get("key1"), "value1");
+ } catch (CmdLineException e) {
+ fail("Cought an invalid exception: " + e.getMessage());
+ }
+ }
+
+ public void testMultiplePairs() {
+ args = new String[]{"-T", "key1=value1", "-T", "key2=value2", "-T", "key3=value3"};
+ try {
+ parser.parseArgument(args);
+ Map<String,String> map = testObject.props;
+ assertTrue("A key was not set.", map.containsKey("key1"));
+ assertTrue("A key was not set.", map.containsKey("key2"));
+ assertTrue("A key was not set.", map.containsKey("key3"));
+ assertEquals("Wrong number of keys.", map.size(), 3);
+ assertEquals("Key has wrong value", map.get("key1"), "value1");
+ assertEquals("Key has wrong value", map.get("key2"), "value2");
+ assertEquals("Key has wrong value", map.get("key3"), "value3");
+ } catch (CmdLineException e) {
+ fail("Cought an invalid exception: " + e.getMessage());
+ }
+ }
+
+ public void testDuplicateKey() {
+ args = new String[]{"-T", "key1=one", "-T", "key1=two"};
+ try {
+ parser.parseArgument(args);
+ Map<String,String> map = testObject.props;
+ assertTrue("A key was not set.", map.containsKey("key1"));
+ assertEquals("Wrong number of keys.", map.size(), 1);
+ assertEquals("As Map.put() defines: last put wins.", map.get("key1"), "two");
+ } catch (CmdLineException e) {
+ fail("Cought an invalid exception: " + e.getMessage());
+ }
+ }
+
+ public void testInitialisation() {
+ args = new String[]{"-T", "key1=value1"};
+ try {
+ testObject.props = null;
+ parser.parseArgument(args);
+ Map<String,String> map = testObject.props;
+ assertNotNull("Map should have been initialized with a new HashMap", map);
+ assertEquals("Key has wrong value", map.get("key1"), "value1");
+ } catch (CmdLineException e) {
+ fail("Cought an invalid exception: " + e.getMessage());
+ }
+ }
+
+ public void testNoValue() {
+ args = new String[]{"-T", "key="};
+ try {
+ parser.parseArgument(args);
+ Map<String,String> map = testObject.props;
+ assertNull("Key has wrong value", map.get("key"));
+ } catch (CmdLineException e) {
+ fail("Cought an invalid exception: " + e.getMessage());
+ }
+ }
+
+ public void testNoKey() {
+ args = new String[]{"-T", "=value"};
+ try {
+ parser.parseArgument(args);
+ fail("An exception should have been thrown.");
+ } catch (CmdLineException e) {
+ assertEquals("Wrong error message.", "A key must be set.", e.getMessage());
+ }
+ }
+
+ public void testNoSplitCharacter() {
+ args = new String[]{"-T", "keyvalue"};
+ try {
+ parser.parseArgument(args);
+ fail("An exception should have been thrown.");
+ } catch (CmdLineException e) {
+ assertEquals("Wrong error message.", "An argument for setting a Map must contain a \"=\"", e.getMessage());
+ }
+ }
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/Setter.java b/args4j/args4j/test/org/kohsuke/args4j/Setter.java
new file mode 100644
index 0000000..e85d39f
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/Setter.java
@@ -0,0 +1,12 @@
+package org.kohsuke.args4j;
+
+public class Setter {
+
+ public String str = "default";
+
+ @Option(name="-str",usage="set a string")
+ public void setStr(String str) {
+ this.str = str.toUpperCase();
+ }
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/SetterTest.java b/args4j/args4j/test/org/kohsuke/args4j/SetterTest.java
new file mode 100644
index 0000000..54ce2e9
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/SetterTest.java
@@ -0,0 +1,64 @@
+package org.kohsuke.args4j;
+
+public class SetterTest extends Args4JTestBase<Setter> {
+ @Override
+ public Setter getTestObject() {
+ return new Setter();
+ }
+
+ public void testSettingStringNoValues() {
+ Setter bo = testObject;
+ args = new String[]{};
+ try {
+ parser.parseArgument(args);
+ assertTrue("Default value set.", "default".equals(bo.str));
+ } catch (CmdLineException e) {
+ fail("Call without parameters is valid!");
+ }
+ }
+
+ public void testSettingString() {
+ Setter bo = testObject;
+ args = new String[]{"-str","test"};
+ try {
+ parser.parseArgument(args);
+ assertTrue("Given value set.", "TEST".equals(bo.str));
+ } catch (CmdLineException e) {
+ fail("Setting a string value should be possible");
+ }
+ }
+
+ public void testSettingUsage() {
+ args = new String[]{"-wrong-usage"};
+ try {
+ parser.parseArgument(args);
+ fail("Doesnt detect wrong parameters.");
+ } catch (CmdLineException e) {
+ String expectedError = "\"-wrong-usage\" is not a valid option";
+ String expectedUsage = " -str VAL : set a string";
+ String errorMessage = e.getMessage();
+ String[] usageLines = getUsageMessage();
+ assertUsageLength(1);
+ assertTrue("Got wrong error message", errorMessage.startsWith(expectedError));
+ assertEquals(expectedUsage, usageLines[0]);
+ }
+ }
+
+ public void testMissingParameter() {
+ args = new String[]{"-str"};
+ try {
+ parser.parseArgument(args);
+ fail("Should miss one parameter.");
+ } catch (CmdLineException e) {
+ String expectedError = "Option \"-str\" takes an operand";
+ String expectedUsage = " -str VAL : set a string";
+
+ String[] usageLines = getUsageMessage();
+ String errorMessage = e.getMessage();
+ assertUsageLength(1);
+ assertTrue("Got wrong error message: " + errorMessage, errorMessage.startsWith(expectedError));
+ assertEquals("Got wrong usage message", expectedUsage, usageLines[0]);
+ }
+ }
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/SimpleString.java b/args4j/args4j/test/org/kohsuke/args4j/SimpleString.java
new file mode 100644
index 0000000..e098df1
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/SimpleString.java
@@ -0,0 +1,12 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.Option;
+
+@SuppressWarnings("unused")
+public class SimpleString {
+ @Option(name="-str",usage="set a string")
+ public String str = "default";
+
+ @Option(name="-nu")
+ public String noUsage;
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/SimpleStringTest.java b/args4j/args4j/test/org/kohsuke/args4j/SimpleStringTest.java
new file mode 100644
index 0000000..800e7dc
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/SimpleStringTest.java
@@ -0,0 +1,82 @@
+package org.kohsuke.args4j;
+
+
+public class SimpleStringTest extends Args4JTestBase<SimpleString> {
+
+ @Override
+ public SimpleString getTestObject() {
+ return new SimpleString();
+ }
+
+ public void testSettingStringNoValues() {
+ SimpleString bo = testObject;
+ args = new String[]{};
+ try {
+ parser.parseArgument(args);
+ assertTrue("Default value set.", "default".equals(bo.str));
+ } catch (CmdLineException e) {
+ fail("Call without parameters is valid!");
+ }
+ }
+
+ public void testSettingString() {
+ SimpleString bo = testObject;
+ args = new String[]{"-str","test"};
+ try {
+ parser.parseArgument(args);
+ assertTrue("Given value set.", "test".equals(bo.str));
+ } catch (CmdLineException e) {
+ fail("Setting a string value should be possible");
+ }
+ }
+
+ public void testSettingUsage() {
+ args = new String[]{"-wrong-usage"};
+ try {
+ parser.parseArgument(args);
+ fail("Doesnt detect wrong parameters.");
+ } catch (CmdLineException e) {
+ String expectedError = "\"-wrong-usage\" is not a valid option";
+ String expectedUsage = " -str VAL : set a string";
+ String[] usageLines = getUsageMessage();
+ String errorMessage = e.getMessage();
+ assertTrue("Got wrong error message", errorMessage.startsWith(expectedError));
+ assertUsageLength(1);
+ assertEquals("Got wrong usage message", expectedUsage, usageLines[0]);
+ }
+ }
+
+ public void testMissingParameter() {
+ args = new String[]{"-str"};
+ try {
+ parser.parseArgument(args);
+ fail("Should miss one parameter.");
+ } catch (CmdLineException e) {
+ String expectedError = "Option \"-str\" takes an operand";
+ String expectedUsage = " -str VAL : set a string";
+ String[] usageLines = getUsageMessage();
+ String errorMessage = e.getMessage();
+ assertUsageLength(1);
+ assertTrue("Got wrong error message: " + errorMessage, errorMessage.startsWith(expectedError));
+ assertEquals("Got wrong usage message", expectedUsage, usageLines[0]);
+ }
+ }
+
+ /*
+ * Bug 5: Option without "usage" are hidden.
+ * TODO: it seems that this is intended:
+ * http://weblogs.java.net/blog/kohsuke/archive/2005/05/parsing_command.html
+ * An @option without "usage" should not be displayed?
+ * If there is no usage information, the CmdLineParser.printOption()
+ * methods do explitely nothing.
+ */
+ public void _testUsage() {
+ args = new String[]{"-wrong"};
+ try {
+ parser.parseArgument(args);
+ } catch (CmdLineException e) {
+ assertUsageContains("Usage does not contain -nu option", "-nu");
+ }
+ }
+
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/StopOptionTest.java b/args4j/args4j/test/org/kohsuke/args4j/StopOptionTest.java
new file mode 100644
index 0000000..488a844
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/StopOptionTest.java
@@ -0,0 +1,43 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.spi.StopOptionHandler;
+
+import java.util.List;
+
+/**
+ * Tests {@link StopOptionHandler}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class StopOptionTest extends Args4JTestBase<StopOptionTest> {
+
+ @Argument
+ @Option(name="--",handler= StopOptionHandler.class)
+ List<String> args;
+
+ @Option(name="-n")
+ int n;
+
+ @Override
+ public StopOptionTest getTestObject() {
+ return this;
+ }
+
+ public void test1() throws Exception {
+ parser.parseArgument("-n","5","abc","def");
+
+ assertEquals(5,n);
+ assertEquals(2,args.size());
+ assertEquals("abc",args.get(0));
+ assertEquals("def",args.get(1));
+ }
+
+ public void test2() throws Exception {
+ parser.parseArgument("--","-n","5","abc","def");
+
+ assertEquals(0,n);
+ assertEquals(4,args.size());
+ assertEquals("-n",args.get(0));
+ assertEquals("5",args.get(1));
+ }
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/StringWithMetavar.java b/args4j/args4j/test/org/kohsuke/args4j/StringWithMetavar.java
new file mode 100644
index 0000000..3b9738b
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/StringWithMetavar.java
@@ -0,0 +1,8 @@
+package org.kohsuke.args4j;
+
+import org.kohsuke.args4j.Option;
+
+public class StringWithMetavar {
+ @Option(name="-str",usage="set a string",metaVar="METAVAR")
+ public String str;
+}
diff --git a/args4j/args4j/test/org/kohsuke/args4j/StringWithMetavarTest.java b/args4j/args4j/test/org/kohsuke/args4j/StringWithMetavarTest.java
new file mode 100644
index 0000000..afeb393
--- /dev/null
+++ b/args4j/args4j/test/org/kohsuke/args4j/StringWithMetavarTest.java
@@ -0,0 +1,41 @@
+package org.kohsuke.args4j;
+
+public class StringWithMetavarTest extends Args4JTestBase<StringWithMetavar> {
+ @Override
+ public StringWithMetavar getTestObject() {
+ return new StringWithMetavar();
+ }
+
+ public void testSettingUsage() {
+ args = new String[]{"-wrong-usage"};
+ try {
+ parser.parseArgument(args);
+ fail("Doesnt detect wrong parameters.");
+ } catch (CmdLineException e) {
+ String expectedError = "\"-wrong-usage\" is not a valid option";
+ String expectedUsage = " -str METAVAR : set a string";
+ String[] usageLines = getUsageMessage();
+ String errorMessage = e.getMessage();
+ assertUsageLength(1);
+ assertTrue("Got wrong error message", errorMessage.startsWith(expectedError));
+ assertEquals("Got wrong usage message", expectedUsage, usageLines[0]);
+ }
+ }
+
+ public void testMissingParameter() {
+ args = new String[]{"-str"};
+ try {
+ parser.parseArgument(args);
+ fail("Should miss one parameter.");
+ } catch (CmdLineException e) {
+ String expectedError = "Option \"-str\" takes an operand";
+ String expectedUsage = " -str METAVAR : set a string";
+ String errorMessage = e.getMessage();
+ String[] usageLines = getUsageMessage();
+ assertUsageLength(1);
+ assertTrue("Got wrong error message", errorMessage.startsWith(expectedError));
+ assertEquals("Got wrong usage message", expectedUsage, usageLines[0]);
+ }
+ }
+
+}
diff --git a/args4j/pom.xml b/args4j/pom.xml
new file mode 100644
index 0000000..e43638a
--- /dev/null
+++ b/args4j/pom.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.kohsuke</groupId>
+ <artifactId>pom</artifactId>
+ <version>3</version>
+ </parent>
+
+ <groupId>args4j</groupId>
+ <artifactId>args4j-site</artifactId>
+ <name>args4j parent</name>
+ <version>2.0.22</version>
+ <packaging>pom</packaging>
+ <description>args4j : Java command line arguments parser</description>
+ <url>http://args4j.dev.java.net/</url>
+ <issueManagement>
+ <url>https://args4j.dev.java.net/issues</url>
+ </issueManagement>
+ <inceptionYear>2003</inceptionYear>
+
+ <ciManagement>
+ <notifiers>
+ <notifier>
+ <configuration>
+ <address>kk@kohsuke.org</address>
+ </configuration>
+ </notifier>
+ </notifiers>
+ </ciManagement>
+ <mailingLists>
+ <mailingList>
+ <name>discussion list</name>
+ <subscribe>users-subscribe@args4j.dev.java.net</subscribe>
+ <unsubscribe>users-ubsubscribe@args4j.dev.java.net</unsubscribe>
+ <archive>https://args4j.dev.java.net/servlets/SummarizeList?listName=users</archive>
+ </mailingList>
+ </mailingLists>
+
+ <developers>
+ <developer>
+ <id>kohsuke</id>
+ <name>Kohsuke Kawaguchi</name>
+ <email>kk@kohsuke.org</email>
+ <organization>Sun Microsystems</organization>
+ </developer>
+ <developer>
+ <id>jhm</id>
+ <name>Jan Materne</name>
+ <email>jhm@apache.org</email>
+ </developer>
+ <developer>
+ <id>marksinke</id>
+ <name>Mark Sinke</name>
+ <email>marksinke@dev.java.net</email>
+ </developer>
+ <developer>
+ <id>lacostej</id>
+ <name>Jerome Lacoste</name>
+ <email>jerome@coffeebreaks.org</email>
+ </developer>
+ </developers>
+
+ <scm>
+ <connection>scm:git:git@github.com/kohsuke/args4j.git</connection>
+ <developerConnection>scm:git:ssh://git@github.com/kohsuke/args4j.git</developerConnection>
+ <url>http://args4j.kohsuke.org/</url>
+ </scm>
+
+ <distributionManagement>
+ <site>
+ <id>github-pages</id>
+ <url>gitsite:git@github.com/kohsuke/args4j.git</url>
+ </site>
+ </distributionManagement>
+
+ <organization>
+ <name>Kohsuke Kawaguchi</name>
+ <url>http://www.kohsuke.org/</url>
+ </organization>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.2</version>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.3.1</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>3.0-beta-3</version>
+ </plugin>
+ </plugins>
+ </build>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <licenses>
+ <license>
+ <name>MIT License</name>
+ <url>http://www.opensource.org/licenses/mit-license.php</url>
+ </license>
+ </licenses>
+
+ <modules>
+ <module>args4j</module>
+ <module>args4j-tools</module>
+ <module>args4j-maven-plugin</module>
+ <module>args4j-maven-plugin-example</module>
+ </modules>
+</project>
diff --git a/args4j/project.properties b/args4j/project.properties
new file mode 100644
index 0000000..bc1988a
--- /dev/null
+++ b/args4j/project.properties
@@ -0,0 +1,44 @@
+# -------------------------------------------------------------------
+# P R O J E C T P R O P E R T I E S
+# -------------------------------------------------------------------
+maven.repo.remote=http://www.ibiblio.org/maven
+# use the lib directory as the repository
+
+maven.junit.fork=true
+
+compile.debug = on
+compile.optimize = off
+compile.deprecation = off
+maven.compile.source=1.5
+maven.compile.target=1.5
+
+maven.jarResources.basedir = ${basedir}/src
+
+maven.changes.issue.template=https://args4j.dev.java.net/issues/show_bug.cgi?id=%ISSUE%
+
+# -------------------------------------------------------------------
+# J A V A D O C P R O P E R T I E S
+# -------------------------------------------------------------------
+
+# Display the date on the Maven web site
+maven.xdoc.date = left
+
+# Display the project version the web site is documenting
+maven.xdoc.version = ${pom.currentVersion}
+
+maven.javadoc.links = \
+ http://java.sun.com/j2se/5.0/docs/api/
+
+maven.javadoc.locale = en_US
+maven.javadoc.public = true
+
+# java.net setting
+maven.javanet.project=args4j
+
+maven.multiproject.basedir=${basedir}
+
+
+
+# load tools jar from JDK
+maven.jar.override = true
+maven.jar.tools = ${java.home}/../lib/tools.jar
diff --git a/args4j/project.xml b/args4j/project.xml
new file mode 100644
index 0000000..29d041d
--- /dev/null
+++ b/args4j/project.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+ <pomVersion>3</pomVersion>
+ <name>args4j</name>
+ <groupId>args4j</groupId>
+ <artifactId>args4j-site</artifactId>
+ <currentVersion>2.0.16</currentVersion>
+
+ <organization>
+ <name>Kohsuke Kawaguchi</name>
+ <url>http://www.kohsuke.org/</url>
+ </organization>
+
+ <logo>/images/args4j.png</logo>
+ <inceptionYear>2003</inceptionYear>
+
+ <package>org.kohsuke.args4j</package>
+
+
+ <shortDescription>args4j : Java command line arguments parser</shortDescription>
+
+ <description>args4j : Java command line arguments parser</description>
+
+ <url>http://args4j.dev.java.net/</url>
+
+ <reports>
+ <report>maven-changes-plugin</report>
+ </reports>
+
+ <repository>
+ <connection>scm:cvs:pserver:guest@cvs.dev.java.net:/cvsroot:args4j</connection>
+ <developerConnection>scm:cvs:ext:${maven.username}@cvs.dev.java.net:/cvsroot:args4j</developerConnection>
+ <url>https://args4j.dev.java.net/source/browse/args4j/</url>
+ </repository>
+
+ <issueTrackingUrl>https://args4j.dev.java.net/issues</issueTrackingUrl>
+
+ <mailingLists>
+ <mailingList>
+ <name>discussion list</name>
+ <subscribe>users-subscribe@args4j.dev.java.net</subscribe>
+ <unsubscribe>users-ubsubscribe@args4j.dev.java.net</unsubscribe>
+ <archive>https://args4j.dev.java.net/servlets/SummarizeList?listName=users</archive>
+ </mailingList>
+ </mailingLists>
+
+
+ <developers>
+ <developer>
+ <name>Kohsuke Kawaguchi</name>
+ <id>kohsuke</id>
+ <email>kk@kohsuke.org</email>
+ <organization>Sun Microsystems</organization>
+ </developer>
+ <developer>
+ <name>Jan Materne</name>
+ <id>jhm</id>
+ <email>jhm@apache.org</email>
+ </developer>
+ <developer>
+ <name>Mark Sinke</name>
+ <id>marksinke</id>
+ <email>marksinke@dev.java.net</email>
+ </developer>
+ </developers>
+</project>
diff --git a/args4j/release.sh b/args4j/release.sh
new file mode 100644
index 0000000..bedbac2
--- /dev/null
+++ b/args4j/release.sh
@@ -0,0 +1,10 @@
+#!/bin/sh -xe
+# run this after manually updating project.xml and xdocs/changes.xml
+# to point to the next release version
+mvn -B release:prepare release:perform
+cd args4j
+maven clean:clean javanet:dist javanet:site jar:install
+cd ../args4j-tools
+maven clean:clean javanet:dist jar:install
+cd ..
+maven javanet:site
diff --git a/args4j/src/site/apt/apt.apt b/args4j/src/site/apt/apt.apt
new file mode 100644
index 0000000..fbde596
--- /dev/null
+++ b/args4j/src/site/apt/apt.apt
@@ -0,0 +1,9 @@
+ args4j can examine your annotated source code and generate HTML table or XML for the list of command line options. You can use this in the build process to generate your documentation, so that it will be always in sync with your code.
+
+ To do so, download {{{http://maven.jenkins-ci.org/content/repositories/releases/args4j/args4j-tools/}args4j-tools}} and run it as follows:
+
+----------------------------------------
+$ java -jar args4j-tools.jar path/to/my/OptionBean.java
+----------------------------------------
+
+ To see all the options, run it withouy any parameter.
diff --git a/args4j/src/site/apt/implementOptionhandler.apt b/args4j/src/site/apt/implementOptionhandler.apt
new file mode 100644
index 0000000..be08376
--- /dev/null
+++ b/args4j/src/site/apt/implementOptionhandler.apt
@@ -0,0 +1,3 @@
+ args4j comes with a built-in support for parsing options into several Java datatypes, such as <<<int>>>, <<<String>>>, and <<<Enum>>>. This support can be extended by writing {{{apidocs/org/kohsuke/args4j/spi/OptionHandler.html}OptionHandler}} implementation in an application and registering it to the <<<CmdLineParser>>> class.
+
+ In fact most of the built-in suppor is implemented as using this mechanism. See the source code for some of the OptionHandler class for details of how to do this.
diff --git a/args4j/src/site/apt/index.apt b/args4j/src/site/apt/index.apt
new file mode 100644
index 0000000..46a187e
--- /dev/null
+++ b/args4j/src/site/apt/index.apt
@@ -0,0 +1,51 @@
+ -----
+ Args4j
+ -----
+ -----
+
+
+ args4j is a small Java class library that makes it easy to parse command line options/arguments in your CUI application.
+
+Why should I use it?
+
+ See {{{http://weblogs.java.net/blog/kohsuke/archive/2005/05/parsing_command.html}my quick intro}}.
+
+ * It makes the command line parsing very easy by using annotations.
+
+ * You can generate the usage screen very easily.
+
+ * You can generate HTML/XML that lists all options for your documentation.
+
+ * Fully supports localization.
+
+ * It is designed to parse <<<javac>>> like options (as opposed to GNU-style where ls <<<-lR>>> is considered to have two options <<<l>>> and <<<R>>>.)
+
+ * It is licensed under {{{http://www.opensource.org/licenses/mit-license.php}the MIT license}}.
+
+ []
+
+How can I use it?
+
+ [[1]] Check {{{https://github.com/kohsuke/args4j/blob/master/args4j/examples/SampleMain.java}the sample}}. This is how your code will look like.
+
+ [[1]] {{{http://maven.glassfish.org/content/groups/public/args4j/}Download}} the distribution or include the library from the Maven Repository at java.net.
+
+ [[1]] Write your code.
+
+ []
+
+More Resource
+
+ [[1]] {{{./sample.html}A small tutorial}} for the use of the Starter and Args4J
+
+ [[1]] {{{./args4j/apidocs/}javadoc}}
+
+ [[1]] {{{./apt.html}How to generate a documentation for your CLI}}
+
+ [[1]] {{{./implementOptionhandler.html}Extend args4j to handle other Java types}}
+
+ [[1]] {{{http://weblogs.java.net/blog/kohsuke/archive/2005/05/parsing_command.html}Kohsuke's Blog: Parsing command line options in JDK 5.0 style}}
+
+ [[1]] {{{http://hikage.developpez.com/java/articles/api/cli-vs-args4j/}A comparison between Commons CLI and Args4j}} in French
+
+ []
diff --git a/args4j/src/site/apt/sample.apt b/args4j/src/site/apt/sample.apt
new file mode 100644
index 0000000..0c2a9be
--- /dev/null
+++ b/args4j/src/site/apt/sample.apt
@@ -0,0 +1,185 @@
+ -----
+ How to use Args4J
+ -----
+
+Prepare your environment
+
+ Because we only want to have a very small example, we use only one single directory containing all the stuff - sources, class files and the args4j jarfile. You need a JDK 1.5 or higher.
+
+ [[1]] Create a directory args4j-sample this will be our project directory.
+
+ [[1]] Download the latest args4j version from the download page
+
+ [[1]] Extract the args4j-{version}.jar from the archive into the project directory
+
+ []
+
+Implementing pure business logic
+
+ Create the business bean Business.java. At this step it contains only the business logic. To run this logic, we want to have a run() method.
+
+------------------------------
+import java.io.File;
+
+public class Business {
+
+ public String name;
+ public File file;
+
+ public void setFile(File f) {
+ if (f.exists()) file = f;
+ }
+
+ public void run() {
+ System.out.println("Business-Logic");
+ System.out.println("- name: " + name);
+ System.out.println("- file: " + ((file!=null)
+ ? file.getAbsolutePath()
+ : "null"));
+ }
+
+}
+------------------------------
+
+ Compile the sources
+
+------------------------------
+javac -classpath .;args4j-2.0.5.jar Business.java
+------------------------------
+
+Start the class
+
+ Now we have three options for setting the field from the command line:
+
+ [[1]] implement a main-method and the command line parsing for our own
+
+ [[1]] implement a main-method and use args4j for parsing
+
+ [[1]] use the starter class
+
+ []
+
+ Ok, because this is a args4j sample, the first method is not the right solution here ;-) In the first step we just use the Starter.
+
+ Start the class
+
+------------------------------
+java -classpath .;args4j-2.0.5.jar -Dmainclass=Business org.kohsuke.args4j.Starter
+------------------------------
+
+ and we will get
+
+------------------------------
+Business-Logic
+- name: null
+- file: null
+------------------------------
+
+ What happened? The starter class had a look into the java system property <<<mainclass>>> loads that class, instantiates it and executes their run() method. We provide the classpath so the Java VM could find the starter class and our business class.
+
+ Next we try to start the class with arguments:
+
+------------------------------
+java -classpath .;args4j-2.0.5.jar -Dmainclass=Business org.kohsuke.args4j.Starter -name "Hrld" -file args4j-2.0.5.jar
+------------------------------
+
+ which results in
+
+------------------------------
+"-name" is not a valid option
+Business
+------------------------------
+
+Adding Args4J Annotations
+
+ Ok, we don't have any annotations for handling the command line parameters yet. So we modify to the source:
+
+------------------------------
+ ...
+ import org.kohsuke.args4j.Option;
+ ...
+ @Option(name="-name",usage="Sets a name")
+ public String name;
+ ...
+ @Option(name="-file",usage="Sets a file if that is present")
+ public void setFile(File f) {
+ ...
+------------------------------
+
+ recompile it and try the start again
+
+------------------------------
+Business-Logic
+- name: Hello World
+- file: C:\temp\args4j-sample\args4j-2.0.5.jar
+------------------------------
+
+ Ok, so far so good. What is with wrong parameters? We will type a
+
+------------------------------
+java -classpath .;args4j-2.0.5.jar -Dmainclass=Business org.kohsuke.args4j.Starter -wrong
+------------------------------
+
+ and the output is
+
+------------------------------
+"-wrong" is not a valid option
+Business [options]
+ -file FILE : Sets a file if that is present
+ -name VAL : Sets a name
+------------------------------
+
+ Again - what happened? args4j throws a CmdLineException when we type an incorrect parameter (<<<-wrong>>>). The starter class catches this and prints out a help message: the classname and an <<<[Option]>>> because we have some @Option's in the code. (We dont have an @Argument so that line is not <<<Business [options] arguments>>>). After that it shows the possible options, as given by the parsers printUsage() method.
+
+ As you can see we added an @Option to an attribute and to a setter method. Adding to an attribute is the simplest thing. If we want to do some checks (like our file existance check) you could add the annotation to a setter.
+
+Enhancing the parsing
+
+ If you want to have more control about the parsing and error handling - dont use the starter. Use the CmdLineParser directly. Base steps are shown below:
+
+------------------------------
+ import org.kohsuke.args4j.CmdLineParser;
+ import org.kohsuke.args4j.CmdLineException;
+ ...
+ public static void main(String[] args) {
+ Business bean = new Business();
+ CmdLineParser parser = new CmdLineParser(bean);
+ try {
+ parser.parseArgument(args);
+ bean.run();
+ } catch (CmdLineException e) {
+ // handling of wrong arguments
+ System.err.println(e.getMessage());
+ parser.printUsage(System.err);
+ }
+ }
+------------------------------
+
+ Because we dont use the Starter we also have to supply the main method and start this. So after compiling we could start that with
+
+------------------------------
+java -classpath .;args4j-2.0.5.jar Business -name "Hello World" -file args4j-2.0.5.jar
+------------------------------
+
+ and we will get
+
+------------------------------
+Business-Logic
+- name: Hello World
+- file: C:\temp\args4j-sample\args4j-2.0.5.jar
+------------------------------
+
+ The error case from above
+
+------------------------------
+java -classpath .;args4j-2.0.5.jar Business -wrong
+------------------------------
+
+will result in
+
+------------------------------
+"-wrong" is not a valid option
+ -file FILE : Sets a file if that is present
+ -name VAL : Sets a name
+------------------------------
+
diff --git a/args4j/src/site/site.xml b/args4j/src/site/site.xml
new file mode 100644
index 0000000..1a59aed
--- /dev/null
+++ b/args4j/src/site/site.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.name}">
+ <skin>
+ <groupId>org.kohsuke</groupId>
+ <artifactId>maven-skin</artifactId>
+ <version>1.2</version>
+ </skin>
+
+ <body>
+ <menu name="Overview">
+ <item name="Home" href="/index.html"/>
+ <item name="Download" href="http://maven.jenkins-ci.org/content/repositories/releases/args4j/"/>
+ <item name="Javadoc" href="/args4j/apidocs/"/>
+ <item name="Source code" href="https://github.com/kohsuke/args4j"/>
+ <item name="Issues" href="http://java.net/jira/browse/ARGS4J"/>
+ </menu>
+ ${reports}
+ </body>
+</project>
+
diff --git a/args4j/xdocs/changes.xml b/args4j/xdocs/changes.xml
new file mode 100644
index 0000000..29b0543
--- /dev/null
+++ b/args4j/xdocs/changes.xml
@@ -0,0 +1,78 @@
+<document>
+ <properties>
+ <title>Args4J changes</title>
+ <author email="kk@kohsuke.org">Kohsuke Kawaguchi</author>
+ <author email="jhm@apache.org">Jan Materne</author>
+ <author email="marksinke@dev.java.net">Mark Sinke</author>
+ </properties>
+ <body>
+ <release version="2.0.16">
+ <action dev="jhm" type="add">New MetadataParser (FieldParser) which makes all fields available by their name</action>
+ <action dev="jhm" type="add">'annotate' a class via XML instead of Java5</action>
+ <action dev="jhm" type="add">Prepare for alternative 'markup' (instead of Annotations)</action>
+ <action dev="jhm" type="add">Make CmdLineParser.addOption / addArgument public for alternatives to parsing class files.</action>
+ </release>
+ <release version="2.0.10">
+ <action dev="jhm" type="fix" issue="10">
+ Enum with many/long values result in StringIndexOutOfBoundsException CmdLineParser.printUsage / printOption
+ </action>
+ <action dev="jhm">Rewrite the printOptions with a hook for line wrapping on word borders</action>
+ </release>
+ <release version="2.0.9" date="2008-06-16" description="Next version after a long time">
+ <action dev="jhm" type="add">Support of all Java native types</action>
+ <action dev="jhm" type="add">Support of java.util.Map</action>
+ </release>
+ <release version="2.0.8" date="2007-05-28" description="Bug-Fixes and Clean-up">
+ <!--
+ <action dev="jhm" type="fix" issue="5">Option without "usage" are hidden.</action>
+ -->
+ <action dev="jhm" type="fix" issue="4">Better usage output for Java5 enums.</action>
+ </release>
+ <release version="2.0.7" date="2006-08-15" description="fixed a packaging problem">
+ <action dev="kohsuke" type="fix">Fixed a packaging error where APT service entry was in args4j.jar</action>
+ </release>
+ <release version="2.0.6" date="2006-04-05" description="document improvements and few more features">
+ <action dev="jhm" type="add">add a changes document (this)</action>
+ <action dev="jhm" type="add">add a starter class</action>
+ <action dev="jhm" type="add">a short manual</action>
+ <action dev="jhm" type="add">args4j is running on Gump</action>
+ <action dev="jhm" type="fix" issue="3">allow to specify the console width for wrapping the usage message</action>
+ </release>
+ <release version="2.0.5" date="2006-02-15" description="tests, few more features">
+ <action dev="kohsuke" type="add">implemented the stop option <code>--</code> </action>
+ <action dev="kohsuke" type="update">modified test cases to use generics to avoid casting</action>
+ <action dev="jhm" type="add">check the usage messages in the test cases</action>
+ <action dev="jhm" type="add">test the inheritance of annotations</action>
+
+ <action dev="jhm" type="update">usage info for the -custom option and use of that data inside the SampleMain</action>
+ </release>
+ <release version="2.0.4" date="2006-01-29" description="tests, few more features">
+ <action dev="jhm" type="add">more test cases</action>
+ <action dev="jhm" type="add">tried to rebuild the Apache Ant command line interface in SampleAnt</action>
+ <action dev="kohsuke" type="add">expanded @Option to allow a Handler to be explicitly specified</action>
+ </release>
+
+ <release version="2.0.3" date="2006-01-13" description="tests, few more features">
+ <action dev="kohsuke" type="add">add DoubleOptionHandler</action>
+ <action dev="kohsuke" type="add">a few test cases</action>
+ <action dev="kohsuke" type="fix" issue="2">printExample provides the ability to generate list of available parameters with usage samples</action>
+ <action dev="kohsuke" type="fix" issue="1">handle mandatory options</action>
+ <action dev="kohsuke" type="add">fully supports localization</action>
+
+ </release>
+ <release version="2.0.1" date="2005-05-12" description="few more features">
+ <action dev="kohsuke" type="add">implemented metavariable support</action>
+ <action dev="kohsuke" type="update">split out args4j-tools</action>
+ <action dev="kohsuke" type="add">implemented a case-insensitive search</action>
+ </release>
+ <release version="2.0.0" date="2005-05-11" description="Move to dev.java.net">
+
+ <action dev="kohsuke" type="add">moving the repository from SourceForge <code>http://sourceforge.net/projects/args4j</code> </action>
+ <action dev="kohsuke" type="add">implemented args4j 2.0</action>
+ </release>
+ <release version="1.0-RC" datei="2003-10-01" description="Initial release">
+ <action dev="kohsuke" type="add">initial release</action>
+ </release>
+
+ </body>
+</document>