├── .classpath ├── .gitignore ├── .settings └── org.eclipse.jdt.core.prefs ├── LICENSE ├── README.md ├── args4j-maven-plugin-example ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── kohsuke │ └── args4j │ └── maven │ └── Example.java ├── args4j-maven-plugin ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── kohsuke │ └── args4j │ └── maven │ └── Args4jUsageMojo.java ├── args4j-tools ├── LICENSE.txt ├── pom.xml ├── src │ ├── META-INF │ │ └── services │ │ │ └── javax.annotation.processing.Processor │ └── org │ │ └── kohsuke │ │ └── args4j │ │ └── apt │ │ ├── AnnotationProcessorImpl.java │ │ ├── AnnotationVisitor.java │ │ ├── AnnotationVisitorReorderer.java │ │ ├── HtmlWriter.java │ │ ├── IsolatingClassLoader.java │ │ ├── Main.java │ │ ├── Mode.java │ │ ├── OptionWithUsage.java │ │ ├── ReloadingClassLoader.java │ │ ├── TxtWriter.java │ │ └── XmlWriter.java └── test │ └── org │ └── kohsuke │ └── args4j │ └── apt │ └── AnnotationVisitorReordererTest.java ├── args4j ├── LICENSE.txt ├── examples │ ├── SampleAnt.java │ ├── SampleMain.java │ ├── SampleStarter.bat │ └── SampleStarter.java ├── pom.xml ├── src │ └── org │ │ └── kohsuke │ │ └── args4j │ │ ├── Argument.java │ │ ├── ClassParser.java │ │ ├── CmdLineException.java │ │ ├── CmdLineParser.java │ │ ├── Config.java │ │ ├── ExampleMode.java │ │ ├── FieldParser.java │ │ ├── IllegalAnnotationError.java │ │ ├── Localizable.java │ │ ├── Messages.java │ │ ├── Messages.properties │ │ ├── Messages_de.properties │ │ ├── Messages_en.properties │ │ ├── Messages_ru.properties │ │ ├── NamedOptionDef.java │ │ ├── Option.java │ │ ├── OptionDef.java │ │ ├── OptionHandlerFilter.java │ │ ├── OptionHandlerRegistry.java │ │ ├── ParserProperties.java │ │ ├── Starter.java │ │ ├── Utilities.java │ │ ├── XmlParser.java │ │ ├── package.html │ │ └── spi │ │ ├── AnnotationImpl.java │ │ ├── ArgumentImpl.java │ │ ├── ArrayFieldSetter.java │ │ ├── BooleanOptionHandler.java │ │ ├── ByteOptionHandler.java │ │ ├── CharOptionHandler.java │ │ ├── ConfigElement.java │ │ ├── DelimitedOptionHandler.java │ │ ├── DoubleOptionHandler.java │ │ ├── EnumOptionHandler.java │ │ ├── ExplicitBooleanOptionHandler.java │ │ ├── FieldSetter.java │ │ ├── FileOptionHandler.java │ │ ├── FloatOptionHandler.java │ │ ├── Getter.java │ │ ├── InetAddressOptionHandler.java │ │ ├── IntOptionHandler.java │ │ ├── LongOptionHandler.java │ │ ├── MacAddressOptionHandler.java │ │ ├── MapOptionHandler.java │ │ ├── Messages.java │ │ ├── Messages.properties │ │ ├── Messages_de.properties │ │ ├── Messages_en.properties │ │ ├── Messages_ru.properties │ │ ├── MethodSetter.java │ │ ├── MultiFileOptionHandler.java │ │ ├── MultiPathOptionHandler.java │ │ ├── MultiValueFieldSetter.java │ │ ├── OneArgumentOptionHandler.java │ │ ├── OptionHandler.java │ │ ├── OptionImpl.java │ │ ├── Parameters.java │ │ ├── PathOptionHandler.java │ │ ├── PatternOptionHandler.java │ │ ├── RestOfArgumentsHandler.java │ │ ├── Setter.java │ │ ├── Setters.java │ │ ├── ShortOptionHandler.java │ │ ├── StopOptionHandler.java │ │ ├── StringArrayOptionHandler.java │ │ ├── StringOptionHandler.java │ │ ├── SubCommand.java │ │ ├── SubCommandHandler.java │ │ ├── SubCommands.java │ │ ├── URIOptionHandler.java │ │ ├── URLOptionHandler.java │ │ ├── UuidOptionHandler.java │ │ └── package.html └── test │ ├── ExampleTest.java │ ├── MandatoryOptionTest.java │ └── org │ └── kohsuke │ └── args4j │ ├── Aliased.java │ ├── AliasedTest.java │ ├── Args4JTestBase.java │ ├── ArgumentTest.java │ ├── AtOption.java │ ├── AtOptionTest.java │ ├── Bean.java │ ├── CmdLineExceptionTest.java │ ├── CustomExceptionTest.java │ ├── DefaultOption.java │ ├── DefaultOptionTest.java │ ├── DependencyOptions.java │ ├── DependencyOptionsTest.java │ ├── EnumArgument.java │ ├── EnumArgumentTest.java │ ├── EnumAttribute.java │ ├── EnumAttributeTest.java │ ├── ExplicitBooleanArgumentTest.java │ ├── ExplicitBooleanOptionTest.java │ ├── ExternalConfiguredTest.java │ ├── ExternalConfiguredTest.xml │ ├── FieldParserTest.java │ ├── HelpOption.java │ ├── HelpOptionTest.java │ ├── HiddenOption.java │ ├── HiddenOptionTest.java │ ├── Inheritance.java │ ├── InheritanceFather.java │ ├── InheritanceGrandfather.java │ ├── InheritanceMother.java │ ├── InheritanceTest.java │ ├── InheritedBean.java │ ├── Issue10Test.java │ ├── KeyValue.java │ ├── KeyValueTest.java │ ├── LongUsage.java │ ├── LongUsageTest.java │ ├── MultivaluedTest.java │ ├── NativeTypes.java │ ├── NativeTypesTest.java │ ├── OptionHandlerRegistryTest.java │ ├── ParserPropertiesUnitTest.java │ ├── PrintUsageTest.java │ ├── Props.java │ ├── PropsTest.java │ ├── Setter.java │ ├── SetterTest.java │ ├── SimpleString.java │ ├── SimpleStringTest.java │ ├── StopOptionTest.java │ ├── StringWithMetavar.java │ ├── StringWithMetavarTest.java │ ├── SubCommandTest.java │ └── spi │ ├── InetAddressOptionHandlerTest.java │ ├── MacAddressOptionHandlerTest.java │ ├── MultiPathOptionHandlerTest.java │ ├── PathOptionHandlerTest.java │ ├── PatternOptionHandlerTest.java │ ├── SettersTest.java │ └── StringArrayOptionHandlerTest.java ├── pom.xml ├── release.sh ├── src └── site │ ├── apt │ ├── apt.apt │ ├── implementOptionhandler.apt │ ├── index.apt │ └── sample.apt │ └── site.xml └── xdocs └── changes.xml /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.ipr 3 | *.iws 4 | target 5 | .* 6 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.8 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 12 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 13 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning 14 | org.eclipse.jdt.core.compiler.release=enabled 15 | org.eclipse.jdt.core.compiler.source=1.8 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Kohsuke Kawaguchi and other contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | args4j 2 | ====== 3 | args4j is a small Java class library that makes it easy to parse command line options/arguments in your CUI 4 | application. See more info at https://args4j.kohsuke.org/ 5 | 6 | Why should I use it? 7 | -------------------- 8 | 9 | See [the quick intro](https://web.archive.org/web/20120605024439/http://weblogs.java.net/blog/kohsuke/archive/2005/05/parsing_command.html) 10 | 11 | - It makes command line parsing very easy by using annotations 12 | - Generate usage text very easily 13 | - Generate HTML/XML documentation listing all options 14 | - Full localization support 15 | - Designed to parse javac like options, as opposed to GNU-style (where ls -lR is considered to have two options l and 16 | R). 17 | - Licensed under [the MIT license](https://opensource.org/license/mit/). 18 | 19 | How can I use it? 20 | ----------------- 21 | 22 | 1. Check [the sample](https://github.com/kohsuke/args4j/blob/master/args4j/examples/SampleMain.java). This is how your 23 | code will look like. 24 | 2. [Download](https://search.maven.org/search?q=g:args4j%20AND%20a:args4j) the distribution or include the library from 25 | the Maven Repository. 26 | 3. Write your code. 27 | 28 | More Resources 29 | -------------- 30 | 31 | 1. [A small tutorial](https://args4j.kohsuke.org/sample.html) for the use of the Starter and Args4J 32 | 2. [javadoc](https://args4j.kohsuke.org/args4j/apidocs/) 33 | 3. [How to generate a documentation for your CLI](https://args4j.kohsuke.org/apt.html) 34 | 4. [Extend args4j to handle other Java types](https://args4j.kohsuke.org/implementOptionhandler.html) 35 | 5. [Kohsuke's Blog: Parsing command line options in JDK 5.0 style](https://web.archive.org/web/20120605024439/http://weblogs.java.net/blog/kohsuke/archive/2005/05/parsing_command.html) 36 | 6. [A comparison between Commons CLI and Args4j](https://hikage.developpez.com/java/articles/api/cli-vs-args4j/) in 37 | French 38 | -------------------------------------------------------------------------------- /args4j-maven-plugin-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | args4j 6 | args4j-site 7 | 2.38-SNAPSHOT 8 | ../pom.xml 9 | 10 | args4j-maven-plugin-example 11 | jar 12 | Args4j Maven Plugin Example 13 | 14 | Example of running the maven plugin 15 | 16 | 2011 17 | 18 | 19 | 20 | 21 | org.kohsuke.args4j 22 | args4j-maven-plugin 23 | ${project.version} 24 | 25 | 26 | package 27 | 28 | usage 29 | 30 | 31 | 32 | org/kohsuke/args4j/maven/Example.java 33 | ../../../../args4j-tools/src/org/kohsuke/args4j/apt/Main.java 34 | ../../../../args4j/examples/SampleAnt.java 35 | ../../../../args4j/examples/SampleMain.java 36 | ../../../../args4j/examples/SampleStarter.java 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-jar-plugin 45 | 46 | 47 | 48 | args4j.maven.plugin.example 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | args4j 58 | args4j 59 | ${project.version} 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /args4j-maven-plugin-example/src/main/java/org/kohsuke/args4j/maven/Example.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.maven; 2 | 3 | import org.kohsuke.args4j.CmdLineException; 4 | import org.kohsuke.args4j.CmdLineParser; 5 | import org.kohsuke.args4j.Option; 6 | 7 | public class Example { 8 | @Option(name = "-o", usage="Option") 9 | public String option; 10 | 11 | @Option(name = "-r", required = true, usage="Required") 12 | public String required; 13 | 14 | public static void main(String[] args) { 15 | System.exit(new Example().run(args)); 16 | } 17 | 18 | private int run(String[] args) { 19 | CmdLineParser p = new CmdLineParser(this); 20 | try { 21 | p.parseArgument(args); 22 | run(); 23 | return 0; 24 | } catch (CmdLineException e) { 25 | System.err.println(e.getMessage()); 26 | p.printUsage(System.err); 27 | return 1; 28 | } 29 | } 30 | 31 | private void run() { 32 | System.out.format("Option %s Required %s\n", option, required); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /args4j-maven-plugin/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | args4j 6 | args4j-site 7 | 2.38-SNAPSHOT 8 | ../pom.xml 9 | 10 | org.kohsuke.args4j 11 | args4j-maven-plugin 12 | maven-plugin 13 | Args4j Maven Plugin 14 | Automate the generation of 15 | 16 | 17 | 2.0 18 | 19 | 2011 20 | 21 | 22 | args4j 23 | args4j-tools 24 | ${project.version} 25 | jar-with-dependencies 26 | 27 | 28 | org.apache.maven 29 | maven-plugin-api 30 | 3.8.1 31 | 32 | 33 | org.apache.maven.plugin-tools 34 | maven-plugin-annotations 35 | 3.8.1 36 | provided 37 | 38 | 39 | 40 | 41 | 42 | org.apache.maven.plugins 43 | maven-jar-plugin 44 | 45 | 46 | 47 | args4j.maven.plugin 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /args4j-tools/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2003, Kohsuke Kawaguchi 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /args4j-tools/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | args4j 6 | args4j-site 7 | 2.38-SNAPSHOT 8 | ../pom.xml 9 | 10 | args4j-tools 11 | args4j-tools 12 | development-time tool for generating additional artifacits 13 | 14 | bundle 15 | 16 | 17 | org.kohsuke.args4j.apt.Main 18 | 19 | 20 | 21 | src 22 | test 23 | 24 | 25 | src 26 | 27 | **/*.properties 28 | META-INF/services/* 29 | 30 | 31 | 32 | 33 | 34 | maven-jar-plugin 35 | 36 | 37 | 38 | true 39 | ${mainClass} 40 | 41 | 42 | args4j.tools 43 | 44 | 45 | 46 | 47 | 48 | org.apache.maven.plugins 49 | maven-assembly-plugin 50 | 3.3.0 51 | 52 | 53 | 54 | ${mainClass} 55 | 56 | 57 | 58 | jar-with-dependencies 59 | 60 | 61 | 62 | 63 | make-assembly 64 | package 65 | 66 | single 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | args4j 76 | args4j 77 | ${project.version} 78 | 79 | 80 | junit 81 | junit 82 | 4.13.2 83 | test 84 | 85 | 86 | org.mockito 87 | mockito-core 88 | 3.11.2 89 | test 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /args4j-tools/src/META-INF/services/javax.annotation.processing.Processor: -------------------------------------------------------------------------------- 1 | org.kohsuke.args4j.apt.AnnotationProcessorImpl 2 | -------------------------------------------------------------------------------- /args4j-tools/src/org/kohsuke/args4j/apt/AnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.apt; 2 | 3 | 4 | import org.kohsuke.args4j.Option; 5 | 6 | /** 7 | * @author Kohsuke Kawaguchi 8 | */ 9 | interface AnnotationVisitor { 10 | /** 11 | * @deprecated as of 2.0.17 use {@link #onOption(OptionWithUsage)} 12 | */ 13 | @Deprecated 14 | void onOption( String name, String usage ); 15 | void onOption( OptionWithUsage optionWithUsage ); 16 | void done(); 17 | } 18 | -------------------------------------------------------------------------------- /args4j-tools/src/org/kohsuke/args4j/apt/AnnotationVisitorReorderer.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.apt; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * Reorders the annotation according to their canonical name 7 | */ 8 | public class AnnotationVisitorReorderer implements AnnotationVisitor { 9 | private AnnotationVisitor target; 10 | 11 | private List arguments = new ArrayList(); 12 | 13 | public AnnotationVisitorReorderer(AnnotationVisitor target) { 14 | this.target = target; 15 | } 16 | 17 | public void onOption(String name, String usage) { 18 | throw new UnsupportedOperationException("method not used"); 19 | } 20 | 21 | public void onOption(OptionWithUsage optionWithUsage) { 22 | arguments.add(optionWithUsage); 23 | } 24 | 25 | public void done() { 26 | reorderArguments(); 27 | for (OptionWithUsage argument : arguments) { 28 | target.onOption(argument); 29 | } 30 | target.done(); 31 | } 32 | 33 | private void reorderArguments() { 34 | Collections.sort(arguments, new NaturalOrderOptionsComparator()); 35 | } 36 | 37 | private static class NaturalOrderOptionsComparator implements Comparator { 38 | public int compare(OptionWithUsage o1, OptionWithUsage o2) { 39 | return o1.option.name().compareTo(o2.option.name()); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /args4j-tools/src/org/kohsuke/args4j/apt/HtmlWriter.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.apt; 2 | 3 | import java.io.PrintWriter; 4 | import java.io.Writer; 5 | 6 | /** 7 | * Writes the option list as HTML to a {@link Writer}. 8 | * 9 | * @author Kohsuke Kawaguchi 10 | */ 11 | class HtmlWriter implements AnnotationVisitor { 12 | private final PrintWriter out; 13 | 14 | public HtmlWriter(Writer out) { 15 | this.out = new PrintWriter(out); 16 | this.out.println(""); 17 | } 18 | 19 | public void onOption(String name, String usage) { 20 | out.println(" "); 21 | writeTag("td","args4j-option",name); 22 | writeTag("td","args4j-usage",usage); 23 | out.println(" "); 24 | } 25 | 26 | public void onOption( OptionWithUsage optionWithUsage ) { 27 | out.println(" "); 28 | writeTag("td","args4j-option",optionWithUsage.option.name()); 29 | writeTag("td","args4j-usage",optionWithUsage.usage); 30 | out.println(" "); 31 | } 32 | 33 | private void writeTag(String tag, String cssClass, String value) { 34 | out.println(" <"+tag+" class='"+cssClass+"'>"); 35 | } 36 | 37 | public void done() { 38 | out.println("
"); 39 | out.close(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /args4j-tools/src/org/kohsuke/args4j/apt/IsolatingClassLoader.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.apt; 2 | 3 | /** 4 | * @author Kohsuke Kawaguchi 5 | */ 6 | public class IsolatingClassLoader extends ClassLoader { 7 | public IsolatingClassLoader(ClassLoader parent) { 8 | super(parent); 9 | } 10 | 11 | public Class loadClass(String name) throws ClassNotFoundException { 12 | throw new ClassNotFoundException(name); 13 | } 14 | 15 | protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { 16 | if(!name.startsWith("org.kohsuke")) 17 | return super.loadClass(name,resolve); 18 | throw new ClassNotFoundException(name); 19 | } 20 | 21 | protected Class findClass(String name) throws ClassNotFoundException { 22 | throw new ClassNotFoundException(name); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /args4j-tools/src/org/kohsuke/args4j/apt/Mode.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.apt; 2 | 3 | /** 4 | * @author Kohsuke Kawaguchi 5 | */ 6 | public enum Mode { 7 | XML, HTML, TXT 8 | } 9 | -------------------------------------------------------------------------------- /args4j-tools/src/org/kohsuke/args4j/apt/OptionWithUsage.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.apt; 2 | 3 | import org.kohsuke.args4j.Option; 4 | 5 | /** 6 | * @author Jerome Lacoste 7 | */ 8 | public class OptionWithUsage { 9 | final Option option; 10 | final String usage; 11 | 12 | OptionWithUsage(Option option, String usage) { 13 | this.option = option; 14 | this.usage = usage; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /args4j-tools/src/org/kohsuke/args4j/apt/ReloadingClassLoader.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.apt; 2 | 3 | import java.io.InputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.IOException; 6 | 7 | /** 8 | * Used to isolate a child class loader from the parent classloader. 9 | * 10 | * @author Kohsuke Kawaguchi 11 | */ 12 | public class ReloadingClassLoader extends ClassLoader { 13 | protected ReloadingClassLoader(ClassLoader parent) { 14 | super(parent); 15 | } 16 | 17 | protected Class findClass(String name) throws ClassNotFoundException { 18 | String pathName = name.replace('.','/')+".class"; 19 | 20 | InputStream is = getParent().getResourceAsStream(pathName); 21 | if (is==null) 22 | throw new ClassNotFoundException(name); 23 | 24 | try { 25 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 26 | byte[] buf = new byte[1024]; 27 | int len; 28 | while((len=is.read(buf))>=0) 29 | baos.write(buf,0,len); 30 | 31 | buf = baos.toByteArray(); 32 | return defineClass(name,buf,0,buf.length); 33 | } catch (IOException e) { 34 | throw new ClassNotFoundException(name,e); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /args4j-tools/src/org/kohsuke/args4j/apt/TxtWriter.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.apt; 2 | 3 | import javax.lang.model.element.TypeElement; 4 | import org.kohsuke.args4j.Option; 5 | 6 | import java.io.PrintWriter; 7 | import java.io.Writer; 8 | 9 | /** 10 | * Writes the option list as TXT to a {@link java.io.Writer}. 11 | * 12 | * @author Jerome Lacoste 13 | */ 14 | class TxtWriter implements AnnotationVisitor { 15 | private final PrintWriter out; 16 | 17 | public TxtWriter(Writer out, TypeElement d) { 18 | this.out = new PrintWriter(out); 19 | this.out.println("Usage: " + d.getQualifiedName()); 20 | } 21 | 22 | public void onOption(String name, String usage) { 23 | throw new UnsupportedOperationException("never used"); 24 | } 25 | 26 | public void onOption( OptionWithUsage optionWithUsage) { 27 | out.println("\t" + optionWithUsage.option.name() + ": " + required(optionWithUsage.option) + optionWithUsage.usage); 28 | } 29 | 30 | private String required(Option option) { 31 | if (option.required()) { 32 | return "[required] "; 33 | } 34 | return "[optional] "; 35 | } 36 | 37 | public void done() { 38 | out.close(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /args4j-tools/src/org/kohsuke/args4j/apt/XmlWriter.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.apt; 2 | 3 | import javax.lang.model.element.TypeElement; 4 | 5 | import java.io.PrintWriter; 6 | import java.io.Writer; 7 | 8 | /** 9 | * Writes the option list as XML to a {@link Writer}. 10 | * 11 | * @author Kohsuke Kawaguchi 12 | */ 13 | class XmlWriter implements AnnotationVisitor { 14 | private final PrintWriter out; 15 | 16 | public XmlWriter(Writer out, TypeElement d) { 17 | this.out = new PrintWriter(out); 18 | this.out.println(""); 19 | } 20 | 21 | public void onOption( String name, String usage ) { 22 | out.println(" "); 26 | } 27 | 28 | public void onOption( OptionWithUsage optionWithUsage ) { 29 | out.println(" "); 33 | } 34 | 35 | private void writeTag(String tag, String value) { 36 | out.println(" <"+tag+">"); 37 | } 38 | 39 | public void done() { 40 | out.println(""); 41 | out.close(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /args4j-tools/test/org/kohsuke/args4j/apt/AnnotationVisitorReordererTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.apt; 2 | 3 | import junit.framework.TestCase; 4 | import org.kohsuke.args4j.Option; 5 | 6 | import static org.mockito.Mockito.mock; 7 | import static org.mockito.Mockito.verify; 8 | import static org.mockito.Mockito.when; 9 | 10 | public class AnnotationVisitorReordererTest extends TestCase { 11 | 12 | private AnnotationVisitor target; 13 | private AnnotationVisitorReorderer reorderer; 14 | 15 | final OptionWithUsage optionb = new OptionWithUsage(mockOption("-b"), "optionb"); 16 | final OptionWithUsage optiona = new OptionWithUsage(mockOption("-a"), "optiona"); 17 | 18 | protected void setUp() throws Exception { 19 | super.setUp(); 20 | target = mock(AnnotationVisitor.class); 21 | reorderer = new AnnotationVisitorReorderer(target); 22 | } 23 | 24 | public void testReorderWithUnorderedAnnotations() throws Exception { 25 | simulateOnOptionsThenDone(optionb, optiona); 26 | verifyOptionsThenDone(optiona, optionb); 27 | } 28 | 29 | public void testReorderWithAlreadyOrderedAnnotations() throws Exception { 30 | simulateOnOptionsThenDone(optiona, optionb); 31 | verifyOptionsThenDone(optiona, optionb); 32 | } 33 | 34 | private void simulateOnOptionsThenDone(OptionWithUsage... options) { 35 | for (OptionWithUsage option : options) { 36 | reorderer.onOption(option); 37 | } 38 | reorderer.done(); 39 | } 40 | 41 | private void verifyOptionsThenDone(OptionWithUsage... options) { 42 | for (OptionWithUsage option : options) { 43 | verify(target).onOption(option); 44 | } 45 | verify(target).done(); 46 | } 47 | 48 | private Option mockOption(String name) { 49 | Option option1 = mock(Option.class); 50 | when(option1.name()).thenReturn(name); 51 | return option1; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /args4j/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2003, Kohsuke Kawaguchi 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /args4j/examples/SampleStarter.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem This shows how to use the Args4J-Starter class 3 | set EXE=java -classpath ../target/classes;../target/examples -Dmainclass=SampleStarter org.kohsuke.args4j.Starter 4 | 5 | 6 | rem Error: The system property 'mainclass' must contain the classname to start. 7 | echo java -classpath ../target/classes;../target/examples org.kohsuke.args4j.Starter 8 | java -classpath ../target/classes;../target/examples org.kohsuke.args4j.Starter 9 | echo -------------------------------------------------------------------------- 10 | 11 | 12 | rem SampleStarter.run(String[]) 13 | rem - args.length: 0 14 | rem SampleStarter: name='null' file='null' 15 | echo %EXE% 16 | %EXE% 17 | echo -------------------------------------------------------------------------- 18 | 19 | 20 | rem "-wrong" is not a valid option 21 | rem mainclass [options] 22 | rem -file FILE : Sets the file 23 | rem -name VAL : Sets the name 24 | echo %EXE% -wrong 25 | %EXE% -wrong 26 | echo -------------------------------------------------------------------------- 27 | 28 | 29 | rem SampleStarter.run(String[]) 30 | rem - args.length: 2 31 | rem - -name 32 | rem - Test 33 | rem SampleStarter: name='Test' file='null' 34 | echo %EXE% -name Test 35 | %EXE% -name Test 36 | echo -------------------------------------------------------------------------- 37 | 38 | 39 | rem SampleStarter.run(String[]) 40 | rem - args.length: 4 41 | rem - -file 42 | rem - . 43 | rem - -name 44 | rem - Hello World 45 | rem SampleStarter: name='Hello World' file='C:\cvs-repository\args4j\args4j\examples\.' 46 | echo %EXE% -file . -name "Hello World" 47 | %EXE% -file . -name "Hello World" -------------------------------------------------------------------------------- /args4j/examples/SampleStarter.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | 3 | import org.kohsuke.args4j.Option; 4 | 5 | /** 6 | * Show the use of the args4j Starter class. 7 | * @author Jan Materne 8 | * @see SampleStarter.bat 9 | */ 10 | public class SampleStarter { 11 | 12 | @Option(name = "-name",usage="Sets the name") 13 | public String name; 14 | 15 | @Option(name = "-file",usage="Sets the file") 16 | public File file; 17 | 18 | /* 19 | * Just do something ... 20 | */ 21 | public String toString() { 22 | StringBuffer buffer = new StringBuffer(); 23 | buffer.append("SampleStarter:"); 24 | buffer.append(" name='"); 25 | buffer.append(name); 26 | buffer.append("' file='"); 27 | buffer.append( (file!=null) ? file.getAbsoluteFile() : "null" ); 28 | buffer.append("'"); 29 | return buffer.toString(); 30 | } 31 | 32 | /** 33 | * First try is to run this run() method. 34 | */ 35 | public void xrun() { 36 | System.out.println("SampleStarter.run()"); 37 | System.out.println(this); 38 | } 39 | 40 | /** 41 | * If you want to get the args-Array from the command line 42 | * use the signature run(String[] args). But then there must 43 | * not be a run() because that is executed prior to this. 44 | * @param args The arguments as specified on the command line 45 | */ 46 | public void run(String[] args) { 47 | System.out.println("SampleStarter.run(String[])"); 48 | System.out.println("- args.length: " + args.length); 49 | for (String arg : args) System.out.println(" - " + arg); 50 | System.out.println(this); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /args4j/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | args4j 5 | args4j-site 6 | 2.38-SNAPSHOT 7 | ../pom.xml 8 | 9 | args4j 10 | args4j 11 | 12 | bundle 13 | 14 | 15 | src 16 | test 17 | 18 | 19 | src 20 | 21 | **/*.properties 22 | META-INF/services/* 23 | 24 | 25 | 26 | 27 | 28 | test 29 | 30 | **/*.xml 31 | 32 | 33 | 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-jar-plugin 38 | 39 | 40 | 41 | args4j 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | junit 51 | junit 52 | 4.13.2 53 | test 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/Argument.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.Target; 5 | 6 | import org.kohsuke.args4j.spi.OptionHandler; 7 | 8 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 9 | import static java.lang.annotation.ElementType.FIELD; 10 | import static java.lang.annotation.ElementType.METHOD; 11 | import static java.lang.annotation.ElementType.PARAMETER; 12 | 13 | /** 14 | * Argument of the command line. 15 | * 16 | * This works mostly like {@link Option} except the following differences. 17 | * 18 | *
    19 | *
  1. Arguments have an index about their relative position on the command line. 20 | *
21 | * 22 | * @author Kohsuke Kawaguchi 23 | * @author Mark Sinke 24 | */ 25 | @Retention(RUNTIME) 26 | @Target({FIELD,METHOD,PARAMETER}) 27 | public @interface Argument { 28 | /** 29 | * See {@link Option#usage()}. 30 | */ 31 | String usage() default ""; 32 | /** 33 | * See {@link Option#metaVar()}. 34 | */ 35 | String metaVar() default ""; 36 | /** 37 | * See {@link Option#required()}. 38 | */ 39 | boolean required() default false; 40 | 41 | /** 42 | * See {@link Option#hidden()}. 43 | */ 44 | boolean hidden() default false; 45 | 46 | /** 47 | * See {@link Option#handler()}. 48 | */ 49 | Class handler() default OptionHandler.class; 50 | 51 | /** 52 | * Position of the argument. 53 | * 54 | *

55 | * If you define multiple single value properties to bind to arguments, 56 | * they should have {@code index=0, index=1, index=2}, ... and so on. 57 | * 58 | *

59 | * Multi value properties bound to arguments must be always the last entry. 60 | */ 61 | int index() default 0; 62 | 63 | /** 64 | * 65 | */ 66 | boolean multiValued() default false; 67 | } 68 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/ClassParser.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import org.kohsuke.args4j.spi.MethodSetter; 4 | import org.kohsuke.args4j.spi.Setters; 5 | 6 | import java.lang.reflect.Field; 7 | import java.lang.reflect.Method; 8 | 9 | /** 10 | * Parser for analyzing Args4J annotations in the class hierarchy. 11 | * 12 | * This can be used to feed option bindings that span across multiple instances. 13 | * 14 | * @author Jan Materne 15 | */ 16 | public class ClassParser { 17 | public void parse(Object bean, CmdLineParser parser) { 18 | // recursively process all the methods/fields. 19 | for( Class c=bean.getClass(); c!=null; c=c.getSuperclass()) { 20 | for( Method m : c.getDeclaredMethods() ) { 21 | Option o = m.getAnnotation(Option.class); 22 | if(o!=null) { 23 | parser.addOption(new MethodSetter(parser,bean,m), o); 24 | } 25 | Argument a = m.getAnnotation(Argument.class); 26 | if(a!=null) { 27 | parser.addArgument(new MethodSetter(parser,bean,m), a); 28 | } 29 | } 30 | 31 | for( Field f : c.getDeclaredFields() ) { 32 | Option o = f.getAnnotation(Option.class); 33 | if(o!=null) { 34 | parser.addOption(Setters.create(f,bean),o); 35 | } 36 | Argument a = f.getAnnotation(Argument.class); 37 | if(a!=null) { 38 | parser.addArgument(Setters.create(f,bean), a); 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/CmdLineException.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.util.Locale; 4 | import org.kohsuke.args4j.spi.OptionHandler; 5 | 6 | /** 7 | * Signals an error in the user input. 8 | * 9 | * @author Kohsuke Kawaguchi 10 | */ 11 | public class CmdLineException extends Exception { 12 | private static final long serialVersionUID = -8574071211991372980L; 13 | 14 | private CmdLineParser parser = null; 15 | 16 | /** 17 | * The optional localized message. 18 | * @see Throwable#getLocalizedMessage() 19 | */ 20 | private String localizedMessage = null; 21 | 22 | /** 23 | * @deprecated 24 | * Use {@link #CmdLineException(CmdLineParser, String)} 25 | */ 26 | public CmdLineException(String message) { 27 | super(message); 28 | } 29 | 30 | /** 31 | * @deprecated 32 | * Use {@link #CmdLineException(CmdLineParser, String, Throwable)} 33 | */ 34 | public CmdLineException(String message, Throwable cause) { 35 | super(message, cause); 36 | } 37 | 38 | /** 39 | * @deprecated 40 | * Use {@link #CmdLineException(CmdLineParser, Throwable)} 41 | */ 42 | public CmdLineException(Throwable cause) { 43 | super(cause); 44 | } 45 | 46 | public CmdLineException(CmdLineParser parser, Localizable message, String... args) { 47 | super(message.formatWithLocale(Locale.ENGLISH, (Object[])args)); 48 | this.localizedMessage = message.format((Object[])args); 49 | this.parser = parser; 50 | } 51 | 52 | /** 53 | * @deprecated 54 | * Use {@link #CmdLineException(org.kohsuke.args4j.CmdLineParser, Localizable, java.lang.String...) } 55 | */ 56 | public CmdLineException(CmdLineParser parser, String message) { 57 | super(message); 58 | this.parser = parser; 59 | } 60 | 61 | public CmdLineException(CmdLineParser parser, String message, Throwable cause) { 62 | super(message, cause); 63 | this.parser = parser; 64 | } 65 | 66 | public CmdLineException(CmdLineParser parser, Throwable cause) { 67 | super(cause); 68 | this.parser = parser; 69 | } 70 | 71 | @Override 72 | public String getLocalizedMessage() { 73 | if (localizedMessage != null) { 74 | return localizedMessage; 75 | } else { 76 | return getMessage(); 77 | } 78 | } 79 | 80 | /** 81 | * Obtains the {@link CmdLineParser} that triggered an exception. 82 | * 83 | *

84 | * Unless you have legacy {@link OptionHandler} that doesn't pass in this information 85 | * when it throws an exception, this method should always return a non-null value. 86 | */ 87 | public CmdLineParser getParser() { 88 | return parser; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/Config.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import org.kohsuke.args4j.spi.ConfigElement; 8 | import org.xml.sax.Attributes; 9 | import org.xml.sax.InputSource; 10 | import org.xml.sax.SAXException; 11 | import org.xml.sax.XMLReader; 12 | import org.xml.sax.helpers.DefaultHandler; 13 | import org.xml.sax.helpers.XMLReaderFactory; 14 | 15 | 16 | /** 17 | * Metadataconfiguration. 18 | * This class holds all metadata for a class, mainly a list of @Options and @Arguments. 19 | * 20 | * @author Jan Materne 21 | */ 22 | public class Config { 23 | 24 | /** All @Options. */ 25 | public List options = new ArrayList();; 26 | 27 | /** All @Arguments. */ 28 | public List arguments = new ArrayList(); 29 | 30 | 31 | /** 32 | * SAX-Handler for reading the configuration file. 33 | * @author Jan Materne 34 | */ 35 | public class ConfigHandler extends DefaultHandler { 36 | public ConfigHandler(Config config) { 37 | super(); 38 | this.config = config; 39 | } 40 | 41 | Config config; 42 | ConfigElement currentCE; 43 | 44 | @Override 45 | public void startElement(String uri, String localName, String qName, 46 | Attributes attributes) throws SAXException { 47 | if (qName.equals("option") || qName.equals("argument")) { 48 | currentCE = new ConfigElement(); 49 | currentCE.field = attributes.getValue("field"); 50 | currentCE.handler = attributes.getValue("handler"); 51 | currentCE.metavar = attributes.getValue("metavar"); 52 | currentCE.method = attributes.getValue("method"); 53 | currentCE.name = attributes.getValue("name"); 54 | currentCE.usage = attributes.getValue("usage"); 55 | currentCE.multiValued = Boolean.getBoolean(attributes.getValue("multiValued")); 56 | currentCE.required = Boolean.getBoolean(attributes.getValue("required")); 57 | if (attributes.getValue("aliases") != null) { 58 | currentCE.aliases = attributes.getValue("aliases").split(","); 59 | } else { 60 | currentCE.aliases = new String[]{}; 61 | } 62 | (qName.equals("option") ? config.options : config.arguments).add(currentCE); 63 | } 64 | } 65 | } 66 | 67 | /** 68 | * Parses a XML file and returns a Config object holding the information. 69 | * @param xml source of the xml data 70 | * @return The parsed configuration. 71 | * @throws IOException 72 | * @throws SAXException 73 | */ 74 | public static Config parse(InputSource xml) throws IOException, SAXException { 75 | Config rv = new Config(); 76 | XMLReader reader = XMLReaderFactory.createXMLReader(); 77 | ConfigHandler handler = rv.new ConfigHandler(rv); 78 | reader.setContentHandler(handler); 79 | reader.parse(xml); 80 | return rv; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/ExampleMode.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import org.kohsuke.args4j.spi.OptionHandler; 4 | 5 | /** 6 | * Used with {@link CmdLineParser#printExample(ExampleMode)}. 7 | * 8 | * @author Kohsuke Kawaguchi 9 | * 10 | * @deprecated use {@link OptionHandlerFilter} 11 | */ 12 | public enum ExampleMode implements OptionHandlerFilter { 13 | /** 14 | * Print all defined options in the example. 15 | * 16 | *

17 | * This would only be useful with small numbers of options. 18 | */ 19 | ALL() { 20 | public boolean select(OptionHandler o) { 21 | return true; 22 | } 23 | }, 24 | 25 | /** 26 | * Print all {@linkplain Option#required() required} option. 27 | */ 28 | REQUIRED() { 29 | public boolean select(OptionHandler o) { 30 | return o.option.required(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/FieldParser.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | import org.kohsuke.args4j.spi.ConfigElement; 6 | import org.kohsuke.args4j.spi.OptionImpl; 7 | import org.kohsuke.args4j.spi.Setters; 8 | 9 | /** 10 | * This metadata parser makes all field available to the CmdLineParser. 11 | * @author Jan Materne 12 | * 13 | */ 14 | public class FieldParser { 15 | 16 | public void parse(CmdLineParser parser, Object bean) throws ClassNotFoundException { 17 | for(Class c=bean.getClass(); c!=null; c=c.getSuperclass()) { 18 | System.out.println("Class: " + c); 19 | for( Field f : c.getDeclaredFields() ) { 20 | Option o = new OptionImpl(createConfigElement(f)); 21 | parser.addOption(Setters.create(f, bean), o ); 22 | } 23 | } 24 | } 25 | 26 | private ConfigElement createConfigElement(Field f) { 27 | ConfigElement rv = new ConfigElement(); 28 | rv.field = f.getName(); 29 | rv.name = "-" + f.getName(); 30 | return rv; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/IllegalAnnotationError.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | /** 4 | * Signals an incorrect use of args4j annotations. 5 | * 6 | *

7 | * This only happens when there's something wrong with the way you use 8 | * args4j in your code--not when the user's arguments are wrong. 9 | * Therefore, this class is an {@link Error}. 10 | * 11 | * @author Kohsuke Kawaguchi 12 | */ 13 | public class IllegalAnnotationError extends Error { 14 | private static final long serialVersionUID = 2397757838147693218L; 15 | 16 | public IllegalAnnotationError(String message) { 17 | super(message); 18 | } 19 | 20 | public IllegalAnnotationError(String message, Throwable cause) { 21 | super(message, cause); 22 | } 23 | 24 | public IllegalAnnotationError(Throwable cause) { 25 | super(cause); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/Localizable.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.text.MessageFormat; 4 | import java.util.Locale; 5 | 6 | /** 7 | * A message that can be formatted with arguments and locale. 8 | *

9 | * The message is implicitly given by {@code this} object and can 10 | * contain formatting similar to the {@link MessageFormat} class. 11 | * 12 | * @see Messages 13 | * @see org.kohsuke.args4j.spi.Messages 14 | * @author Stephan Fuhrmann 15 | */ 16 | public interface Localizable { 17 | 18 | /** 19 | * Format the implicitly given message by {@code this} object with the given locale. 20 | * @param locale the locale to use for formatting . 21 | * @param args the arguments to use for formatting. See {@link MessageFormat#format(java.lang.String, java.lang.Object...)}. 22 | * @return the formatted string. 23 | */ 24 | public String formatWithLocale( Locale locale, Object... args ); 25 | 26 | /** 27 | * Format the implicitly given message by {@code this} object with the default locale. 28 | * @param args the arguments to use for formatting. See {@link MessageFormat#format(java.lang.String, java.lang.Object...)}. 29 | * @return the formatted string. 30 | */ 31 | public String format( Object... args ); 32 | } 33 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/Messages.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.text.MessageFormat; 4 | import java.util.Locale; 5 | import java.util.ResourceBundle; 6 | 7 | /** 8 | * @author Kohsuke Kawaguchi 9 | */ 10 | enum Messages implements Localizable { 11 | MISSING_OPERAND, 12 | UNDEFINED_OPTION, 13 | NO_ARGUMENT_ALLOWED, 14 | REQUIRED_OPTION_MISSING, 15 | TOO_MANY_ARGUMENTS, 16 | REQUIRED_ARGUMENT_MISSING, 17 | METADATA_ERROR, 18 | MULTIPLE_USE_OF_ARGUMENT, 19 | MULTIPLE_USE_OF_OPTION, 20 | UNKNOWN_HANDLER, 21 | NO_OPTIONHANDLER, 22 | NO_CONSTRUCTOR_ON_HANDLER, 23 | REQUIRES_OPTION_MISSING, 24 | FORBIDDEN_OPTION_PRESENT, 25 | NO_SUCH_FILE, 26 | DEFAULT_VALUE 27 | ; 28 | 29 | public String formatWithLocale( Locale locale, Object... args ) { 30 | ResourceBundle localized = ResourceBundle.getBundle(Messages.class.getName(), locale); 31 | return MessageFormat.format(localized.getString(name()),args); 32 | } 33 | 34 | public String format( Object... args ) { 35 | return formatWithLocale(Locale.getDefault(),args); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/Messages.properties: -------------------------------------------------------------------------------- 1 | MISSING_OPERAND = \ 2 | Option "{0}" takes an operand 3 | 4 | UNDEFINED_OPTION = \ 5 | "{0}" is not a valid option 6 | 7 | NO_ARGUMENT_ALLOWED = \ 8 | No argument is allowed: {0} 9 | 10 | REQUIRED_OPTION_MISSING = \ 11 | Option "{0}" is required 12 | 13 | REQUIRED_ARGUMENT_MISSING = \ 14 | Argument "{0}" is required 15 | 16 | TOO_MANY_ARGUMENTS = \ 17 | Too many arguments: {0} 18 | 19 | METADATA_ERROR = \ 20 | Problems while reading the args-confguration. 21 | 22 | MULTIPLE_USE_OF_ARGUMENT = \ 23 | Argument with index {0} is used more than once 24 | 25 | MULTIPLE_USE_OF_OPTION = \ 26 | Option name {0} is used more than once 27 | 28 | UNKNOWN_HANDLER = \ 29 | No OptionHandler is registered to handle {0} 30 | 31 | NO_OPTIONHANDLER = \ 32 | Not an OptionHandler class 33 | 34 | NO_CONSTRUCTOR_ON_HANDLER = \ 35 | {0} does not have the proper constructor 36 | 37 | REQUIRES_OPTION_MISSING = \ 38 | option "{0}" requires the option(s) {1} 39 | 40 | FORBIDDEN_OPTION_PRESENT = \ 41 | option "{0}" cannot be used with the option(s) {1} 42 | 43 | NO_SUCH_FILE = \ 44 | No such file: {0} 45 | 46 | DEFAULT_VALUE = \ 47 | (default: {0}) 48 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/Messages_de.properties: -------------------------------------------------------------------------------- 1 | # Unicode for Umlauts 2 | # Ae, ae \u00c4, \u00e4 3 | # Oe, oe \u00d6, \u00f6 4 | # Ue, ue \u00dc, \u00fc 5 | # ss \u00df 6 | 7 | 8 | 9 | MISSING_OPERAND = \ 10 | Option "{0}" ben\u00f6tigt einen Operanden 11 | 12 | UNDEFINED_OPTION = \ 13 | "{0}" ist keine g\u00fcltige Option 14 | 15 | NO_ARGUMENT_ALLOWED = \ 16 | Kein Argument erlaubt: {0} 17 | 18 | REQUIRED_OPTION_MISSING = \ 19 | Option "{0}" wird ben\u00f6tigt 20 | 21 | REQUIRED_ARGUMENT_MISSING = \ 22 | Argument "{0}" wird ben\u00f6tigt 23 | 24 | TOO_MANY_ARGUMENTS = \ 25 | Zu viele Argumente: {0} 26 | 27 | METADATA_ERROR = \ 28 | Kann die Args4J-Metadaten nicht lesen 29 | 30 | MULTIPLE_USE_OF_ARGUMENT = \ 31 | Das Argument mit Index {0} ist mehr als einmal verwendet 32 | 33 | MULTIPLE_USE_OF_OPTION = \ 34 | Die Option ''{0}'' ist mehr als einmal verwendet 35 | 36 | UNKNOWN_HANDLER = \ 37 | Es ist kein OptionHandler f\u00fcr ''{0}'' registriert 38 | 39 | NO_OPTIONHANDLER = \ 40 | Ist keine OptionHandler Klasse 41 | 42 | NO_CONSTRUCTOR_ON_HANDLER = \ 43 | {0} hat nicht den notwendigen Konstruktor 44 | 45 | REQUIRES_OPTION_MISSING = \ 46 | Option "{0}" ben\u00f6tigt die Option(en) {1} 47 | 48 | DEFAULT_VALUE = \ 49 | (Vorgabe: {0}) 50 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/Messages_en.properties: -------------------------------------------------------------------------------- 1 | # this file is intentionally empty to fall back to the default 2 | # which is the English locale 3 | 4 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/Messages_ru.properties: -------------------------------------------------------------------------------- 1 | MISSING_OPERAND = \u041E\u043F\u0446\u0438\u044F "{0}" \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u043D\u0434 2 | UNDEFINED_OPTION = "{0}" \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u043E\u043F\u0446\u0438\u044F 3 | 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} 4 | REQUIRED_OPTION_MISSING = \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u043E\u043F\u0446\u0438\u044F "{0}" 5 | REQUIRED_ARGUMENT_MISSING = \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442 "{0}" 6 | 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} 7 | 8 | 9 | # For translation 10 | #------------------ 11 | # METADATA_ERROR = Problems while reading the args-confguration. 12 | # MULTIPLE_USE_OF_ARGUMENT = Argument with index {0} is used more than once 13 | # MULTIPLE_USE_OF_OPTION = Option name {0} is used more than once 14 | # UNKNOWN_HANDLER = No OptionHandler is registered to handle {0} 15 | # NO_OPTIONHANDLER = Not an OptionHandler class 16 | # NO_CONSTRUCTOR_ON_HANDLER = {0} does not have the proper constructor 17 | # FORMAT_ERROR_FOR_MAP = An argument for setting a Map must contain a '=' 18 | # MAP_HAS_NO_KEY = A key must be set. 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/NamedOptionDef.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Immutable run-time copy of {@link Option} annotation. 7 | */ 8 | public final class NamedOptionDef extends OptionDef { 9 | private final String name; 10 | private final String[] aliases; 11 | private final String[] depends; 12 | private final String[] forbids; 13 | 14 | /** 15 | * @deprecated 16 | * multi-valuedness as option definition does not make sense. It's driven by the setter. 17 | */ 18 | public NamedOptionDef(Option o, boolean forceMultiValued) { 19 | this(o); 20 | } 21 | 22 | public NamedOptionDef(Option o) { 23 | super(o.usage(),o.metaVar(),o.required(),o.help(),o.hidden(),o.handler(),false); 24 | 25 | this.name = o.name(); 26 | this.aliases = createZeroSizedArrayIfNull(o.aliases()); 27 | this.depends = createZeroSizedArrayIfNull(o.depends()); 28 | this.forbids = createZeroSizedArrayIfNull(o.forbids()); 29 | } 30 | 31 | private static String[] createZeroSizedArrayIfNull(String in[]) { 32 | if (in == null) { 33 | return new String[0]; 34 | } else { 35 | return in; 36 | } 37 | } 38 | 39 | public String name() { 40 | return name; 41 | } 42 | 43 | public String[] aliases() { 44 | return Arrays.copyOf(aliases, aliases.length); 45 | } 46 | 47 | public String[] depends() { 48 | return Arrays.copyOf(depends, depends.length); 49 | } 50 | 51 | public String[] forbids() { 52 | return Arrays.copyOf(forbids, forbids.length); 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | if (aliases.length > 0) { 58 | String str = ""; 59 | for (String alias : aliases) { 60 | if (str.length() > 0) { 61 | str += ", "; 62 | } 63 | str += alias; 64 | } 65 | return name() + " (" + str + ")"; 66 | } 67 | return name(); 68 | } 69 | 70 | @Override 71 | public boolean isArgument() { 72 | return false; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/OptionDef.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import org.kohsuke.args4j.spi.OptionHandler; 4 | 5 | /** 6 | * Run-time copy of the Option or Argument annotation. By definition, unnamed options 7 | * are arguments (and instances of this class). Named options are actually a subclass. 8 | * 9 | * @author Mark Sinke 10 | */ 11 | public class OptionDef { 12 | private final String usage; 13 | private final String metaVar; 14 | private final boolean required; 15 | private final boolean help; 16 | private final boolean hidden; 17 | private final boolean multiValued; 18 | private final Class handler; 19 | 20 | public OptionDef(Argument a, boolean forceMultiValued) { 21 | this(a.usage(), a.metaVar(), a.required(), false, a.hidden(), a.handler(), a.multiValued() || forceMultiValued); 22 | } 23 | 24 | protected OptionDef(String usage, String metaVar, boolean required, 25 | boolean help, boolean hidden, 26 | Class handler, 27 | boolean multiValued) { 28 | this.usage = usage; 29 | this.metaVar = metaVar; 30 | this.required = required; 31 | this.help = help; 32 | this.hidden = hidden; 33 | this.handler = handler; 34 | this.multiValued = multiValued; 35 | } 36 | 37 | public String usage() { 38 | return usage; 39 | } 40 | 41 | public String metaVar() { 42 | return metaVar; 43 | } 44 | 45 | public boolean required() { 46 | return required; 47 | } 48 | 49 | public boolean help() { 50 | return help; 51 | } 52 | 53 | /** 54 | * Value from {@link Option#hidden()} or {@link Argument#hidden()} 55 | */ 56 | public boolean hidden() { 57 | return hidden; 58 | } 59 | 60 | public Class handler() { 61 | return handler; 62 | } 63 | 64 | public boolean isMultiValued() { 65 | return multiValued; 66 | } 67 | 68 | public boolean isArgument() { 69 | return true; 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | return metaVar() != null ? metaVar() : "ARG"; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/OptionHandlerFilter.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import org.kohsuke.args4j.spi.OptionHandler; 4 | 5 | import java.io.Writer; 6 | import java.util.ResourceBundle; 7 | 8 | /** 9 | * Selects {@link OptionHandler}. 10 | * 11 | *

12 | * For example, we use this to let the caller specify which 13 | * options are printed, and which ones aren't. 14 | * 15 | * @author Kohsuke Kawaguchi 16 | * @see CmdLineParser#printExample(OptionHandlerFilter) 17 | * @see CmdLineParser#printUsage(Writer, ResourceBundle, OptionHandlerFilter) 18 | */ 19 | public interface OptionHandlerFilter { 20 | /** 21 | * 22 | * @param o 23 | * Never {@code null}. Internally options (like -r) and arguments (others) 24 | * are treated uniformly as {@link OptionHandler}. 25 | * See {@link OptionDef#isArgument()} to distinguish them. 26 | * @return 27 | * true to choose this option, false to ignore/discard/disregard it. 28 | */ 29 | boolean select(OptionHandler o); 30 | 31 | /** 32 | * Print all defined options in the example. 33 | */ 34 | OptionHandlerFilter ALL = new OptionHandlerFilter() { 35 | public boolean select(OptionHandler o) { 36 | return true; 37 | } 38 | }; 39 | 40 | /** 41 | * Print all {@linkplain Option#hidden() non-hidden} options. 42 | * 43 | *

44 | * This would only be useful with a small number of options. 45 | */ 46 | OptionHandlerFilter PUBLIC = new OptionHandlerFilter() { 47 | public boolean select(OptionHandler o) { 48 | return !o.option.hidden(); 49 | } 50 | }; 51 | 52 | /** 53 | * Print all {@linkplain Option#required() required} options. 54 | */ 55 | OptionHandlerFilter REQUIRED = new OptionHandlerFilter() { 56 | public boolean select(OptionHandler o) { 57 | return o.option.required(); 58 | } 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/Starter.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.lang.reflect.Field; 5 | import java.lang.reflect.InvocationTargetException; 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * Starter class which uses reflection to instantiate the business 10 | * class, parse the command line parameters, sets the fields of the 11 | * business class and doing the help message handling. 12 | * 13 | * @author Jan Materne 14 | */ 15 | public class Starter { 16 | 17 | /** 18 | * The name of the JavaVM property which stores the class name of 19 | * the business class. 20 | * {@value} 21 | */ 22 | public static final String PARAMETER_NAME = "mainclass"; 23 | 24 | public static void main(String[] args) { 25 | String classname = System.getProperty(PARAMETER_NAME); 26 | CmdLineParser parser = null; 27 | boolean classHasArgument = false; 28 | boolean classHasOptions = false; 29 | 30 | // Check the requirement: must specify the class to start 31 | if (classname == null || "".equals(classname)) { 32 | System.err.println("The system property '" 33 | + PARAMETER_NAME 34 | + "' must contain the classname to start."); 35 | System.exit(-1); 36 | } 37 | 38 | try { 39 | Class clazz = Class.forName(classname); 40 | Object bean = clazz.newInstance(); 41 | parser = new CmdLineParser(bean); 42 | 43 | // for help output 44 | classHasArgument = hasAnnotation(clazz, Argument.class); 45 | classHasOptions = hasAnnotation(clazz, Option.class); 46 | 47 | parser.parseArgument(args); 48 | 49 | // try starting run() 50 | Method m; 51 | boolean couldInvoke = false; 52 | try { 53 | m = clazz.getMethod("run", (Class[]) null); 54 | m.invoke(bean, (Object[]) null); 55 | couldInvoke = true; 56 | } catch (SecurityException e) { 57 | } catch (IllegalArgumentException e) { 58 | } catch (NoSuchMethodException e) { 59 | } catch (IllegalAccessException e) { 60 | } catch (InvocationTargetException e) { 61 | } 62 | 63 | // try starting run(String[]) 64 | if (!couldInvoke) try { 65 | m = clazz.getMethod("run", String[].class); 66 | m.invoke(bean, new Object[]{args}); 67 | couldInvoke = true; 68 | } catch (SecurityException e) { 69 | } catch (IllegalArgumentException e) { 70 | e.printStackTrace(); 71 | } catch (NoSuchMethodException e) { 72 | } catch (IllegalAccessException e) { 73 | } catch (InvocationTargetException e) { 74 | } 75 | } catch (ClassNotFoundException e) { 76 | // wrong classpath setting 77 | System.err.println("Cant find the class '" 78 | + classname 79 | + "' as specified in the system property '" 80 | + PARAMETER_NAME + "'."); 81 | } catch (CmdLineException e) { 82 | // wrong argument enteres, so print the usage message as 83 | // supplied by args4j 84 | System.err.println(e.getMessage()); 85 | System.err.print(classname); 86 | if (classHasOptions) System.err.print(" [options]"); 87 | if (classHasArgument) System.err.print(" arguments"); 88 | System.err.println(); 89 | if (parser != null) 90 | parser.printUsage(System.err); 91 | } catch (Exception e) { 92 | // Must be an unhandled business exception, so we can only 93 | // print stacktraces. 94 | e.printStackTrace(); 95 | } 96 | } 97 | 98 | public static boolean hasAnnotation(Class clazz, Class annotation) { 99 | if (clazz.getAnnotation(annotation)!=null) return true; 100 | for (Field f : clazz.getFields()) { 101 | if (f.getAnnotation(annotation)!=null) return true; 102 | } 103 | for (Method m : clazz.getMethods()) { 104 | if (m.getAnnotation(annotation)!=null) return true; 105 | } 106 | return false; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/Utilities.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | /** 4 | * Misc utility methods. Don't make this 5 | * class visible to the outside world. 6 | * When we switch to JDK 1.7, re-check the sense 7 | * of this class. 8 | */ 9 | class Utilities { 10 | 11 | private Utilities() { 12 | // no instance 13 | } 14 | 15 | /** This method is similar to {@code Objects.requireNonNull()}. 16 | * But this one is available for JDK 1.6 which is the 17 | * current target of args4j. 18 | * I didn't want to break compatibility with JDK 1.6. 19 | * @param obj the object to check for {@code null} value. 20 | * @param name the object name. If {@code obj} is {@code null}, then 21 | * an exception is constructed from this name. 22 | */ 23 | static void checkNonNull(Object obj, String name) { 24 | if (obj == null) { 25 | throw new NullPointerException(name+" is null"); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/XmlParser.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.lang.reflect.AccessibleObject; 4 | import java.net.URL; 5 | 6 | import org.kohsuke.args4j.spi.ArgumentImpl; 7 | import org.kohsuke.args4j.spi.ConfigElement; 8 | import org.kohsuke.args4j.spi.OptionImpl; 9 | import org.kohsuke.args4j.spi.Setters; 10 | import org.xml.sax.InputSource; 11 | 12 | /** 13 | * Parses an XML-file specifying the 'annotations'. 14 | * The XML must have the structure: 15 | *

16 |  * <args>
17 |  *     <option field="" method="" name="" usage="" metavar="" handler=""/>
18 |  *     <argument field="" method="" usage="" metavar="" handler=""/>
19 |  * </args>
20 |  * 
21 | * Exactly one of the attributes 'field' or 'method' must be set. 22 | * The 'handler' value specifies a full qualified class name. 23 | * 24 | *

Example

25 | *
26 |  * <args>
27 |  *     <option field="recursive" name="-r" usage="recursively run something"/>
28 |  *     <option field="out" name="-o" usage="output to this file" metavar="OUTPUT"/>
29 |  *     <option method="setStr(String)" name="-str"/>
30 |  *     <option field="data" name="-custom" handler="org.kohsuke.args4j.spi.BooleanOptionHandler" usage="boolean value for checking the custom handler"/>
31 |  *     <argument field="arguments"/>
32 |  * <args>
33 |  * 
34 | * 35 | * @author Jan Materne 36 | */ 37 | public class XmlParser { 38 | public void parse(URL xml, CmdLineParser parser, Object bean) { 39 | parse(new InputSource(xml.toExternalForm()),parser,bean); 40 | } 41 | 42 | public void parse(InputSource xml, CmdLineParser parser, Object bean) { 43 | try { 44 | Config config = Config.parse(xml); 45 | for(ConfigElement ce : config.options) { 46 | Option option = new OptionImpl(ce); 47 | parser.addOption(Setters.create(parser, findMethodOrField(bean, ce.field, ce.method),bean), option); 48 | } 49 | for (ConfigElement ce : config.arguments) { 50 | Argument argument = new ArgumentImpl(ce); 51 | parser.addArgument(Setters.create(parser, findMethodOrField(bean, ce.field, ce.method),bean), argument); 52 | } 53 | } catch (Exception e) { 54 | throw new RuntimeException(Messages.METADATA_ERROR.format(), e); 55 | } 56 | } 57 | 58 | 59 | /** 60 | * Finds a {@link java.lang.reflect.Method} or {@link java.lang.reflect.Method} in the bean 61 | * instance with the requested name. 62 | * @param bean bean instance 63 | * @param field name of the field (field XOR method must be specified) 64 | * @param method name of the method (field XOR method must be specified) 65 | * @return the reflection reference 66 | * @throws SecurityException 67 | * @throws NoSuchFieldException 68 | * @throws NoSuchMethodException 69 | * @throws ClassNotFoundException 70 | */ 71 | private AccessibleObject findMethodOrField(Object bean, String field, String method) throws SecurityException, NoSuchFieldException, NoSuchMethodException, ClassNotFoundException { 72 | AccessibleObject rv; 73 | if (field != null) { 74 | rv = bean.getClass().getDeclaredField(field); 75 | } else { 76 | String methodName = method.substring(0, method.indexOf("(")); 77 | String[] params = method.substring(method.indexOf("(")+1, method.indexOf(")")).split(","); 78 | Class[] paramTypes = new Class[params.length]; 79 | for(int i=0; i 2 | 3 | 4 |

Core classes of the Args4J command line parser.

5 | 6 |

What is Args4J?

7 | 8 |

9 | Args4J is a command line parser. 10 | As such, its job is to parse the String-array passed to the main() method and 11 | transfer the values to a Java object, which includes type conversion. 12 | The entry point into this parsing is the CmdLineParser class, 13 | with its parse() method. 14 |

15 | 16 |

Args4J must know the mapping between the flag from the command line and the target for the value. 17 | There are many ways to use Args4J:

18 | 19 |
    20 |
  • place an @Option or @Argument annotation at a setter or on a field
  • 21 |
  • provide a XML configuration file
  • 22 |
  • make all fields publicly available
  • 23 |
24 | 25 |

Depending on what you want, you may have perform a configuration step before parsing.

26 | 27 | 28 |

Examples

29 | 30 |

java Main -text newText

31 | 32 |

The typical use involves writing a small bean class and providing the annotations.

33 |

This feature is available since the first Args4J release:

34 | 35 |
36 | public class Bean {
37 |    {@literal @}Option(name="-text")
38 |     String text;
39 | }
40 | public class Main {
41 |     public static void main(String[] args) throws CmdLineException {
42 |         Object bean = new Bean();
43 |         CmdLineParser parser = new CmdLineParser(bean);
44 |         parser.parse(args);
45 |     }
46 | }
47 | 
48 | 49 | 50 |

An easy way to initialize fields without touching the bean source code is to use the FieldParser.

51 | 52 |

The FieldParser scans all fields of bean class (including inheritance), and makes them publicly available as options with a - prefix in the name.

53 | 54 |

This feature is available since Args4J release 2.0.16:

55 | 56 |
57 | public class Bean {
58 |     String text;
59 | }
60 | public class Main {
61 |     public static void main(String[] args) throws CmdLineException {
62 |         Object bean = new Bean();
63 |         CmdLineParser parser = new CmdLineParser(null);
64 |         new FieldParser().parse(parser, bean);
65 |         parser.parse(args);
66 |     }
67 | }
68 | 
69 | 70 |

While the FieldParser is easier to use, the XmlParser supports more features.

71 |

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 a URL to the XML file.

72 | 73 |

This feature is available since Args4J release 2.0.16:

74 | 75 |
76 | public class Bean {
77 |     String text;
78 | }
79 | public class Main {
80 |     public static void main(String[] args) throws CmdLineException {
81 |         Object bean = new Bean();
82 |         CmdLineParser parser = new CmdLineParser(null);
83 |         new XmlParser().parse(getClass().getResource(bean.getClass().getName() + ".xml"), parser, bean);
84 |         parser.parse(args);
85 |     }
86 | }
87 | <args>
88 |   <option field="text" name="-text" usage="Output text"/>
89 | </args>
90 | 
91 | 92 | 93 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/AnnotationImpl.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.util.Arrays; 5 | 6 | 7 | /** 8 | * Base class for the @Option and @Argument implementation classes. 9 | * @author Jan Materne 10 | */ 11 | public abstract class AnnotationImpl implements Annotation { 12 | private final Class annotationType; 13 | 14 | protected AnnotationImpl(Class annotationType) { 15 | this.annotationType = annotationType; 16 | } 17 | 18 | protected AnnotationImpl(Class annotationType, ConfigElement ce) throws ClassNotFoundException { 19 | this(annotationType); 20 | 21 | aliases = ce.aliases != null ? ce.aliases : new String[0]; 22 | if (ce.handler != null) { 23 | handler = (Class) Class.forName(ce.handler); 24 | } else { 25 | handler = OptionHandler.class; 26 | } 27 | metaVar = ce.metavar != null ? ce.metavar : ""; 28 | multiValued = ce.multiValued; 29 | required = ce.required; 30 | hidden = ce.hidden; 31 | usage = ce.usage != null ? ce.usage : ""; 32 | } 33 | 34 | public String[] aliases; 35 | public String[] aliases() { 36 | return Arrays.copyOf(aliases, aliases.length); 37 | } 38 | public Class handler; 39 | public Class handler() { 40 | return handler; 41 | } 42 | public String metaVar; 43 | public String metaVar() { 44 | return metaVar; 45 | } 46 | public boolean multiValued; 47 | public boolean multiValued() { 48 | return multiValued; 49 | } 50 | public boolean required; 51 | public boolean required() { 52 | return required; 53 | } 54 | public boolean help; 55 | public boolean help() { 56 | return help; 57 | } 58 | public boolean hidden; 59 | public boolean hidden() { 60 | return hidden; 61 | } 62 | public String usage; 63 | public String usage() { 64 | return usage; 65 | } 66 | public Class annotationType() { 67 | return annotationType; 68 | } 69 | public int index; 70 | public int index() { 71 | return index; 72 | } 73 | } -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/ArgumentImpl.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.Argument; 4 | 5 | /** 6 | * Implementation of @Argument so we can instantiate it. 7 | * @author Jan Materne 8 | */ 9 | public class ArgumentImpl extends AnnotationImpl implements Argument { 10 | public ArgumentImpl(ConfigElement ce) throws ClassNotFoundException { 11 | super(Argument.class,ce); 12 | } 13 | } -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/BooleanOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import org.kohsuke.args4j.CmdLineException; 7 | import org.kohsuke.args4j.CmdLineParser; 8 | import org.kohsuke.args4j.OptionDef; 9 | 10 | /** 11 | * Boolean {@link OptionHandler}. 12 | * 13 | * @author Kohsuke Kawaguchi 14 | */ 15 | public class BooleanOptionHandler extends OptionHandler { 16 | private static final List ACCEPTABLE_VALUES = Arrays.asList(new String[] { "true", "on", "yes", "1", 17 | "false", "off", "no", "0" }); 18 | 19 | public BooleanOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 20 | super(parser, option, setter); 21 | } 22 | 23 | @Override 24 | public int parseArguments(Parameters params) throws CmdLineException { 25 | if (option.isArgument()) { 26 | String valueStr = params.getParameter(0).toLowerCase(); 27 | int index = ACCEPTABLE_VALUES.indexOf(valueStr); 28 | if (index == -1) { 29 | throw new CmdLineException(owner, Messages.ILLEGAL_BOOLEAN, valueStr); 30 | } 31 | setter.addValue(index < ACCEPTABLE_VALUES.size() / 2); 32 | return 1; 33 | } else { 34 | setter.addValue(true); 35 | return 0; 36 | } 37 | } 38 | 39 | @Override 40 | public String getDefaultMetaVariable() { 41 | return null; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/ByteOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineParser; 4 | import org.kohsuke.args4j.OptionDef; 5 | 6 | /** 7 | * {@link Byte} 8 | * {@link OptionHandler} 9 | * {@link OneArgumentOptionHandler} 10 | * @author Jan Materne 11 | * @since 2.0.9 12 | */ 13 | public class ByteOptionHandler extends OneArgumentOptionHandler { 14 | 15 | public ByteOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 16 | super(parser, option, setter); 17 | } 18 | 19 | @Override 20 | protected Byte parse(String argument) throws NumberFormatException { 21 | return Byte.parseByte(argument); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/CharOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineParser; 4 | import org.kohsuke.args4j.OptionDef; 5 | import org.kohsuke.args4j.CmdLineException; 6 | 7 | 8 | /** 9 | * {@link Character} 10 | * {@link OptionHandler} 11 | * {@link OneArgumentOptionHandler} 12 | * @author Jan Materne 13 | * @since 2.0.9 14 | */ 15 | public class CharOptionHandler extends OneArgumentOptionHandler { 16 | 17 | public CharOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 18 | super(parser, option, setter); 19 | } 20 | 21 | @Override 22 | protected Character parse(String argument) throws NumberFormatException, CmdLineException { 23 | if (argument.length() != 1) 24 | throw new CmdLineException(owner, Messages.ILLEGAL_CHAR, argument); 25 | return argument.charAt(0); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/ConfigElement.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | /** 4 | * The ConfigElement is an <option> or <argument> tag 5 | * in the xml configuration file. 6 | * @author Jan Materne 7 | */ 8 | public class ConfigElement { 9 | public String field; 10 | public String method; 11 | public String name; 12 | public String usage = ""; 13 | public String handler; 14 | public String metavar = ""; 15 | public String[] aliases = {}; 16 | public boolean multiValued = false; 17 | public boolean required = false; 18 | public boolean hidden = false; 19 | /** 20 | * Ensures that only a field XOR a method is set. 21 | * @return Whether this element has invalid settings. 22 | */ 23 | public boolean isInvalid() { 24 | return field == null && method == null || field != null && method != null; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/DelimitedOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineException; 4 | import org.kohsuke.args4j.CmdLineParser; 5 | import org.kohsuke.args4j.Option; 6 | import org.kohsuke.args4j.OptionDef; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Partial {@link OptionHandler} implementation that takes a single value to the option, 12 | * which is then gets split into individual tokens using fixed delimiter. 13 | * 14 | *

15 | * This class is marked as {@code abstract} even though it has no abstract methods 16 | * to indicate that the class cannot be used by itself in {@link Option#handler()}, 17 | * due to the extra argument that it takes. 18 | * 19 | * @author kmahoney 20 | */ 21 | public abstract class DelimitedOptionHandler extends OptionHandler { 22 | 23 | protected final String delimiter; 24 | protected final OneArgumentOptionHandler individualOptionHandler; 25 | 26 | public DelimitedOptionHandler(CmdLineParser parser, OptionDef option, Setter setter, String delimiter, OneArgumentOptionHandler individualOptionHandler) { 27 | super(parser, option, setter); 28 | this.delimiter = delimiter; 29 | this.individualOptionHandler = individualOptionHandler; 30 | } 31 | 32 | @Override 33 | public int parseArguments(Parameters params) throws CmdLineException { 34 | String full = params.getParameter(0); 35 | String[] delimitedStrs = full.split(delimiter); 36 | for (String delimitedStr : delimitedStrs) { 37 | setter.addValue(individualOptionHandler.parse(delimitedStr)); 38 | } 39 | 40 | // The number of Parameters consumed (not the number set) 41 | return 1; 42 | } 43 | 44 | @Override 45 | public String getDefaultMetaVariable() { 46 | final String tMetaVar = individualOptionHandler.getDefaultMetaVariable(); 47 | if (tMetaVar == null || tMetaVar.trim().isEmpty()) return tMetaVar; 48 | return "<" + tMetaVar + delimiter + tMetaVar + delimiter + "...>"; 49 | } 50 | 51 | /** 52 | * Prints the default value by introspecting the current setter as {@link Getter}. 53 | * 54 | * @return null if the current value of the setter isn't available. 55 | */ 56 | public String printDefaultValue() { 57 | if (setter instanceof Getter) { 58 | Getter getter = (Getter)setter; 59 | List defaultValues = getter.getValueList(); 60 | 61 | StringBuilder buf = new StringBuilder(); 62 | for (T v : defaultValues) { 63 | if (buf.length()>0) buf.append(delimiter); 64 | buf.append(print(v)); 65 | } 66 | return buf.toString(); 67 | } 68 | return null; 69 | } 70 | } -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/DoubleOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineParser; 4 | import org.kohsuke.args4j.OptionDef; 5 | 6 | /** 7 | * {@link Double} 8 | * {@link OptionHandler}. 9 | * {@link OneArgumentOptionHandler} 10 | * @author Leif Wickland 11 | */ 12 | public class DoubleOptionHandler extends OneArgumentOptionHandler { 13 | public DoubleOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 14 | super(parser, option, setter); 15 | } 16 | 17 | @Override 18 | protected Double parse(String argument) throws NumberFormatException { 19 | return Double.parseDouble(argument); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/EnumOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.util.ResourceBundle; 4 | 5 | import org.kohsuke.args4j.CmdLineException; 6 | import org.kohsuke.args4j.CmdLineParser; 7 | import org.kohsuke.args4j.OptionDef; 8 | 9 | /** 10 | * {@link Enum} {@link OptionHandler}. 11 | * 12 | * @author Kohsuke Kawaguchi 13 | */ 14 | public class EnumOptionHandler> extends OptionHandler { 15 | 16 | private final Class enumType; 17 | 18 | public EnumOptionHandler(CmdLineParser parser, OptionDef option, Setter setter, Class enumType) { 19 | super(parser, option, setter); 20 | this.enumType = enumType; 21 | } 22 | 23 | @Override 24 | public int parseArguments(Parameters params) throws CmdLineException { 25 | String s = params.getParameter(0).replaceAll("-", "_"); 26 | T value = null; 27 | for( T o : enumType.getEnumConstants() ) 28 | if(o.name().equalsIgnoreCase(s)) { 29 | value = o; 30 | break; 31 | } 32 | 33 | if(value==null) { 34 | if (option.isArgument()) { 35 | throw new CmdLineException(owner, Messages.ILLEGAL_OPERAND, option.toString(), s); 36 | } else { 37 | throw new CmdLineException(owner, Messages.ILLEGAL_OPERAND, params.getParameter(-1),s); 38 | } 39 | } 40 | setter.addValue(value); 41 | return 1; 42 | } 43 | 44 | /* 45 | * Returns all values of an enum type split by pipe. 46 | * [ one | two | three] 47 | * @see org.kohsuke.args4j.spi.OptionHandler#getDefaultMetaVariable() 48 | */ 49 | @Override 50 | public String getDefaultMetaVariable() { 51 | StringBuffer rv = new StringBuffer(); 52 | rv.append("["); 53 | for (T t : enumType.getEnumConstants()) { 54 | rv.append(t).append(" | "); 55 | } 56 | rv.delete(rv.length()-3, rv.length()); 57 | rv.append("]"); 58 | return rv.toString(); 59 | } 60 | 61 | @Override 62 | public String getMetaVariable(ResourceBundle rb) { 63 | return getDefaultMetaVariable(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/ExplicitBooleanOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import static java.lang.Boolean.FALSE; 4 | import static java.lang.Boolean.TRUE; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | import org.kohsuke.args4j.CmdLineException; 10 | import org.kohsuke.args4j.CmdLineParser; 11 | import org.kohsuke.args4j.OptionDef; 12 | 13 | /** 14 | * Boolean {@link OptionHandler} that (unlike the standard {@link BooleanOptionHandler} 15 | * allows values to be set to false explicitly (using e.g. '-myOpt false') rather 16 | * than only returning false when the option is omitted. 17 | */ 18 | public class ExplicitBooleanOptionHandler extends OptionHandler { 19 | // same values as BooleanOptionHandler 20 | private static final Map ACCEPTABLE_VALUES; 21 | 22 | static { 23 | // I like the trick in BooleanOptionHandler but find this explicit map more readable 24 | ACCEPTABLE_VALUES = new HashMap(); 25 | ACCEPTABLE_VALUES.put("true", TRUE); 26 | ACCEPTABLE_VALUES.put("on", TRUE); 27 | ACCEPTABLE_VALUES.put("yes", TRUE); 28 | ACCEPTABLE_VALUES.put("1", TRUE); 29 | ACCEPTABLE_VALUES.put("false", FALSE); 30 | ACCEPTABLE_VALUES.put("off", FALSE); 31 | ACCEPTABLE_VALUES.put("no", FALSE); 32 | ACCEPTABLE_VALUES.put("0", FALSE); 33 | } 34 | 35 | public ExplicitBooleanOptionHandler(CmdLineParser parser, 36 | OptionDef option, Setter setter) { 37 | super(parser, option, setter); 38 | } 39 | 40 | @Override 41 | public int parseArguments(Parameters params) throws CmdLineException { 42 | // end of arg list or next arg is another option 43 | if ((params.size() == 0) || params.getParameter(0).startsWith("-")) { 44 | setter.addValue(TRUE); 45 | return 0; 46 | } else { 47 | setter.addValue(getBoolean(params.getParameter(0))); 48 | return 1; 49 | } 50 | } 51 | 52 | private Boolean getBoolean(String parameter) throws CmdLineException { 53 | String valueStr = parameter.toLowerCase(); 54 | if (!ACCEPTABLE_VALUES.containsKey(valueStr)) { 55 | throw new CmdLineException(owner, Messages.ILLEGAL_BOOLEAN, valueStr); 56 | } 57 | return ACCEPTABLE_VALUES.get(valueStr); 58 | } 59 | 60 | @Override 61 | public String getDefaultMetaVariable() { 62 | return Messages.DEFAULT_META_EXPLICIT_BOOLEAN_OPTION_HANDLER.format(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/FieldSetter.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.lang.reflect.AnnotatedElement; 4 | import java.lang.reflect.Field; 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | /** 9 | * {@link Setter} that sets to a {@link Field}. 10 | * 11 | * @author Kohsuke Kawaguchi 12 | */ 13 | public final class FieldSetter implements Getter, Setter { 14 | private final Field f; 15 | private final Object bean; 16 | 17 | public FieldSetter(Object bean, Field f) { 18 | this.bean = bean; 19 | this.f = f; 20 | } 21 | 22 | public Class getType() { 23 | return f.getType(); 24 | } 25 | 26 | public boolean isMultiValued() { 27 | // a field can only store one value. a collection field is handled via MultiValueFieldSetter 28 | return false; 29 | } 30 | 31 | public FieldSetter asFieldSetter() { 32 | return new FieldSetter(bean,f); 33 | } 34 | 35 | public AnnotatedElement asAnnotatedElement() { 36 | return f; 37 | } 38 | 39 | public void addValue(Object value) { 40 | try { 41 | f.set(bean,value); 42 | } catch (IllegalAccessException ex) { 43 | // try again 44 | f.setAccessible(true); 45 | try { 46 | f.set(bean,value); 47 | } catch (IllegalAccessException e) { 48 | throw new IllegalAccessError(e.getMessage()); 49 | } 50 | } 51 | } 52 | 53 | public Object getValue() { 54 | try { 55 | return f.get(bean); 56 | } catch (IllegalAccessException ex) { 57 | // try again 58 | f.setAccessible(true); 59 | try { 60 | return f.get(bean); 61 | } catch (IllegalAccessException e) { 62 | throw new IllegalAccessError(e.getMessage()); 63 | } 64 | } 65 | } 66 | 67 | public List getValueList() { 68 | return asList(getValue()); 69 | } 70 | 71 | private List asList(Object o) { 72 | if (o!=null) return Collections.singletonList(o); 73 | return Collections.emptyList(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/FileOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.io.File; 4 | 5 | import org.kohsuke.args4j.OptionDef; 6 | import org.kohsuke.args4j.CmdLineException; 7 | import org.kohsuke.args4j.CmdLineParser; 8 | 9 | /** 10 | * {@link File} {@link OptionHandler}. 11 | * 12 | * @author Kohsuke Kawaguchi 13 | */ 14 | public class FileOptionHandler extends OneArgumentOptionHandler { 15 | public FileOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 16 | super(parser, option, setter); 17 | } 18 | 19 | @Override 20 | protected File parse(String argument) throws CmdLineException { 21 | return new File(argument); 22 | } 23 | 24 | @Override 25 | public String getDefaultMetaVariable() { 26 | return Messages.DEFAULT_META_FILE_OPTION_HANDLER.format(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/FloatOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineParser; 4 | import org.kohsuke.args4j.OptionDef; 5 | 6 | /** 7 | * {@link Float} 8 | * {@link OptionHandler} 9 | * {@link OneArgumentOptionHandler} 10 | * 11 | * @author Jan Materne 12 | * @since 2.0.9 13 | */ 14 | public class FloatOptionHandler extends OneArgumentOptionHandler { 15 | 16 | public FloatOptionHandler(CmdLineParser parser, OptionDef option, 17 | Setter setter) { 18 | super(parser, option, setter); 19 | } 20 | 21 | @Override 22 | protected Float parse(String argument) throws NumberFormatException { 23 | return Float.parseFloat(argument); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/Getter.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Interface that can be instantiated to get default values. 7 | * @see Setter 8 | * @author Stephan Fuhrmann 9 | */ 10 | public interface Getter { 11 | /** 12 | * Gets the current value of the property. 13 | * 14 | *

15 | * A {@link Getter} object has an implicit knowledge about the property it's getting, 16 | * and the instance of the option bean. 17 | * 18 | * @return 19 | * empty list or null if there's no current value. 20 | */ 21 | List getValueList(); 22 | } 23 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/InetAddressOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.net.InetAddress; 4 | import java.net.UnknownHostException; 5 | 6 | import org.kohsuke.args4j.CmdLineException; 7 | import org.kohsuke.args4j.CmdLineParser; 8 | import org.kohsuke.args4j.OptionDef; 9 | 10 | /** 11 | * {@link InetAddress} {@link OptionHandler}. 12 | * 13 | * @author Dipen Lad 14 | */ 15 | public class InetAddressOptionHandler extends 16 | OneArgumentOptionHandler { 17 | public InetAddressOptionHandler(CmdLineParser parser, OptionDef option, 18 | Setter setter) { 19 | super(parser, option, setter); 20 | } 21 | 22 | @Override 23 | protected InetAddress parse(String argument) throws CmdLineException { 24 | try { 25 | return InetAddress.getByName(argument); 26 | } catch (UnknownHostException e) { 27 | throw new CmdLineException(owner, 28 | Messages.ILLEGAL_IP_ADDRESS, argument); 29 | } 30 | } 31 | 32 | @Override 33 | public String getDefaultMetaVariable() { 34 | return Messages.DEFAULT_META_INET_ADDRESS_OPTION_HANDLER.format(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/IntOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineParser; 4 | import org.kohsuke.args4j.OptionDef; 5 | 6 | /** 7 | * {@link Integer} 8 | * {@link OptionHandler}. 9 | * {@link OneArgumentOptionHandler} 10 | * 11 | * @author Kohsuke Kawaguchi 12 | */ 13 | public class IntOptionHandler extends OneArgumentOptionHandler { 14 | public IntOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 15 | super(parser, option, setter); 16 | } 17 | 18 | @Override 19 | protected Integer parse(String argument) throws NumberFormatException { 20 | return Integer.parseInt(argument); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/LongOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineParser; 4 | import org.kohsuke.args4j.OptionDef; 5 | 6 | /** 7 | * {@link Long} 8 | * {@link OptionHandler} 9 | * {@link OneArgumentOptionHandler} 10 | * @author Jan Materne 11 | * @since 2.0.9 12 | */ 13 | public class LongOptionHandler extends OneArgumentOptionHandler { 14 | 15 | public LongOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 16 | super(parser, option, setter); 17 | } 18 | 19 | @Override 20 | protected Long parse(String argument) throws NumberFormatException { 21 | return Long.parseLong(argument); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/MacAddressOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineException; 4 | import org.kohsuke.args4j.CmdLineParser; 5 | import org.kohsuke.args4j.OptionDef; 6 | 7 | /** 8 | * {@link OptionHandler} that parses MAC address to byte[] of length 6. 9 | * 10 | *

11 | * The string representation of a MAC address can be of different forms, e.g. 12 | * 13 | *

14 |  * XXXXXXXXXXXX
15 |  * XX XX XX XX XX XX
16 |  * XX-XX-XX-XX-XX-XX
17 |  * XX:XX:XX:XX:XX:XX
18 |  * 
19 | * 20 | * @author Tobias Stolzmann 21 | */ 22 | public class MacAddressOptionHandler extends OptionHandler { 23 | public MacAddressOptionHandler(CmdLineParser parser, OptionDef option, 24 | Setter setter) { 25 | super(parser, option, setter); 26 | } 27 | 28 | @Override 29 | public int parseArguments(Parameters params) throws CmdLineException { 30 | String macString = params.getParameter(0); 31 | String[] macStringArray = null; 32 | 33 | if (macString.matches("[0-9a-fA-F]{12}")) 34 | /* 35 | * When entering this clause our MAC address is a hexadecimal string 36 | * with 12 digit. Hence we have no delimiter to split. So we simply 37 | * split after each two characters. 38 | */ 39 | macStringArray = macString.split("(?<=\\G.{2})"); 40 | else if (macString.matches("([0-9a-fA-F]{1,2}[^0-9a-fA-F]+){5}[0-9a-fA-F]{1,2}")) 41 | /* 42 | * When entering this clause our MAC address is a in the form 43 | * XX#XX#XX#XX#XX#XX where XX is a hexadecimal string with one or two 44 | * digits and # is a delimiter which contains no hexadecimal digit. 45 | * In most cases # is a dash (-), a colon (:) or a space ( ). 46 | * We just need to split by our delimiter. 47 | */ 48 | macStringArray = macString.split("[^0-9a-fA-F]+"); 49 | else 50 | throw new CmdLineException(owner, 51 | Messages.ILLEGAL_MAC_ADDRESS, macString); 52 | 53 | byte[] mac = new byte[6]; 54 | for (int i = 0; i < 6; i++) 55 | /* 56 | * Yes, we really need to parse a short here... ;-) 57 | * Explanation: All six MAC address parts are unsigned bytes in 58 | * hexadecimal representation. They lay between 0x00 and 0xff 59 | * respectively 0 and 255. The Java data type byte is signed. It 60 | * lays between -128 and 127. Therefore we need to "convert" the 61 | * upper half of our unsigned values to negative to obtain the 62 | * correct bit representation (think of the two's complement). This 63 | * is done best by parsing short (or int or long) and casting to 64 | * byte. 65 | */ 66 | mac[i] = (byte) Short.parseShort(macStringArray[i], 16); 67 | 68 | setter.asFieldSetter().addValue(mac); 69 | return 1; 70 | } 71 | 72 | @Override 73 | public String getDefaultMetaVariable() { 74 | return Messages.DEFAULT_META_MAC_ADDRESS_OPTION_HANDLER.format(); 75 | } 76 | 77 | @Override 78 | public String print(byte[] v) { 79 | StringBuilder buf = new StringBuilder(); 80 | for (byte b : v) { 81 | if (buf.length()>0) buf.append(':'); 82 | buf.append(Integer.toHexString(((int)b)&0xFF)); 83 | } 84 | return buf.toString(); 85 | } 86 | } -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/MapOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import org.kohsuke.args4j.*; 7 | 8 | /** 9 | * Parses options into a {@link Map}. 10 | * 11 | *

12 |  * class Foo {
13 |  *  {@literal @}Option(name="-P",handler={@link MapOptionHandler}.class)
14 |  *   Map<String,String> args;
15 |  * }
16 |  * 
17 | * 18 | *

19 | * With this, -P x=1 -P y=2 parses to map of size {@code 2}. 20 | * This option handler can be subtyped if you want to convert values to different types 21 | * or to handle key=value in other formats, like key:=value. 22 | * */ 23 | public class MapOptionHandler extends OptionHandler> { 24 | 25 | public MapOptionHandler(CmdLineParser parser, OptionDef option, Setter> setter) { 26 | super(parser, option, setter); 27 | if (setter.asFieldSetter()==null) 28 | throw new IllegalArgumentException("MapOptionHandler can only work with fields"); 29 | } 30 | 31 | @Override 32 | public String getDefaultMetaVariable() { 33 | return null; 34 | } 35 | 36 | @Override 37 | public int parseArguments(Parameters params) throws CmdLineException { 38 | FieldSetter fs = setter.asFieldSetter(); 39 | Map v = (Map)fs.getValue(); 40 | if (v==null) { 41 | v = createNewCollection(fs.getType()); 42 | fs.addValue(v); 43 | } 44 | 45 | addToMap(params.getParameter(0),v); 46 | 47 | return 1; 48 | } 49 | 50 | /** 51 | * Creates a new instance of the collection. 52 | */ 53 | protected Map createNewCollection(Class type) { 54 | return new HashMap(); 55 | } 56 | 57 | /** 58 | * Encapsulates how a single string argument gets converted into key and value. 59 | */ 60 | protected void addToMap(String argument, Map m) throws CmdLineException { 61 | if (String.valueOf(argument).indexOf('=') == -1) { 62 | throw new CmdLineException(owner,Messages.FORMAT_ERROR_FOR_MAP); 63 | } 64 | 65 | String mapKey; 66 | String mapValue; 67 | 68 | //Splitting off the key from the value 69 | int idx = argument.indexOf('='); 70 | if (idx>=0) { 71 | mapKey = argument.substring(0, idx); 72 | mapValue = argument.substring(idx + 1); 73 | if (mapValue.length()==0) 74 | // Kohsuke: I think this is a bad choice, but this is needed to remain backward compatible 75 | mapValue = null; 76 | } else { 77 | mapKey = argument; 78 | mapValue = null; 79 | } 80 | 81 | if (mapKey.length()==0) { 82 | throw new CmdLineException(owner,Messages.MAP_HAS_NO_KEY); 83 | } 84 | 85 | addToMap(m, mapKey, mapValue); 86 | } 87 | 88 | /** 89 | * This is the opportunity to convert values to some typed objects. 90 | */ 91 | protected void addToMap(Map m, String key, String value) { 92 | m.put(key,value); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/Messages.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.text.MessageFormat; 4 | import java.util.Locale; 5 | import java.util.ResourceBundle; 6 | 7 | import org.kohsuke.args4j.Localizable; 8 | 9 | /** 10 | * @author Kohsuke Kawaguchi 11 | */ 12 | public enum Messages implements Localizable { 13 | ILLEGAL_OPERAND, 14 | ILLEGAL_CHAR, 15 | ILLEGAL_BOOLEAN, 16 | ILLEGAL_METHOD_SIGNATURE, 17 | ILLEGAL_FIELD_SIGNATURE, 18 | ILLEGAL_LIST, 19 | FORMAT_ERROR_FOR_MAP, 20 | MAP_HAS_NO_KEY, 21 | ILLEGAL_IP_ADDRESS, 22 | ILLEGAL_PATTERN, 23 | ILLEGAL_MAC_ADDRESS, 24 | ILLEGAL_UUID, 25 | ILLEGAL_PATH, 26 | DEFAULT_META_EXPLICIT_BOOLEAN_OPTION_HANDLER, 27 | DEFAULT_META_FILE_OPTION_HANDLER, 28 | DEFAULT_META_INET_ADDRESS_OPTION_HANDLER, 29 | DEFAULT_META_MAC_ADDRESS_OPTION_HANDLER, 30 | DEFAULT_META_PATH_OPTION_HANDLER, 31 | DEFAULT_META_PATTERN_OPTION_HANDLER, 32 | DEFAULT_META_REST_OF_ARGUMENTS_HANDLER, 33 | DEFAULT_META_STRING_ARRAY_OPTION_HANDLER, 34 | DEFAULT_META_STRING_OPTION_HANDLER, 35 | DEFAULT_META_SUB_COMMAND_HANDLER, 36 | DEFAULT_META_URI_OPTION_HANDLER, 37 | DEFAULT_META_URL_OPTION_HANDLER, 38 | DEFAULT_META_UUID_OPTION_HANDLER 39 | ; 40 | 41 | public String formatWithLocale( Locale locale, Object... args ) { 42 | ResourceBundle localized = ResourceBundle.getBundle(Messages.class.getName(), locale); 43 | return MessageFormat.format(localized.getString(name()),args); 44 | } 45 | 46 | 47 | public String format( Object... args ) { 48 | return formatWithLocale(Locale.getDefault(),args); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/Messages.properties: -------------------------------------------------------------------------------- 1 | ILLEGAL_OPERAND = \ 2 | "{1}" is not a valid value for "{0}" 3 | ILLEGAL_BOOLEAN = \ 4 | "{0}" is not a legal boolean value 5 | ILLEGAL_CHAR = \ 6 | "{0}" must be a single character 7 | ILLEGAL_METHOD_SIGNATURE = \ 8 | Method {0} takes more than one parameter 9 | ILLEGAL_FIELD_SIGNATURE = \ 10 | Field of type {0} isn't supported by args4j 11 | ILLEGAL_LIST = \ 12 | type of {0} is not a List 13 | FORMAT_ERROR_FOR_MAP = \ 14 | An argument for setting a Map must contain a "=" 15 | MAP_HAS_NO_KEY = \ 16 | A key must be set. 17 | ILLEGAL_IP_ADDRESS = \ 18 | "{0}" must be an IP address 19 | ILLEGAL_PATTERN = \ 20 | "{0}" must be a regular expression 21 | ILLEGAL_MAC_ADDRESS = \ 22 | "{0}" must be an MAC address 23 | ILLEGAL_UUID = \ 24 | "{0}" must be a UUID 25 | ILLEGAL_PATH = \ 26 | Failed to parse path "{0}" 27 | DEFAULT_META_EXPLICIT_BOOLEAN_OPTION_HANDLER = \ 28 | VALUE 29 | DEFAULT_META_FILE_OPTION_HANDLER = \ 30 | FILE 31 | DEFAULT_META_INET_ADDRESS_OPTION_HANDLER = \ 32 | IP ADDRESS 33 | DEFAULT_META_MAC_ADDRESS_OPTION_HANDLER = \ 34 | MAC ADDRESS 35 | DEFAULT_META_PATH_OPTION_HANDLER = \ 36 | PATH 37 | DEFAULT_META_PATTERN_OPTION_HANDLER = \ 38 | REGEX 39 | DEFAULT_META_REST_OF_ARGUMENTS_HANDLER = \ 40 | ARGS 41 | DEFAULT_META_STRING_ARRAY_OPTION_HANDLER = \ 42 | STRING[] 43 | DEFAULT_META_STRING_OPTION_HANDLER = \ 44 | VAL 45 | DEFAULT_META_SUB_COMMAND_HANDLER = \ 46 | CMD ARGS... 47 | DEFAULT_META_URI_OPTION_HANDLER = \ 48 | URI 49 | DEFAULT_META_URL_OPTION_HANDLER = \ 50 | URL 51 | DEFAULT_META_UUID_OPTION_HANDLER = \ 52 | UUID 53 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/Messages_de.properties: -------------------------------------------------------------------------------- 1 | # Unicode for Umlauts 2 | # Ae, ae \u00c4, \u00e4 3 | # Oe, oe \u00d6, \u00f6 4 | # Ue, ue \u00dc, \u00fc 5 | # ss \u00df 6 | 7 | 8 | 9 | ILLEGAL_METHOD_SIGNATURE = \ 10 | Methode {0} ben\u00f6tigt mehr als einen Parameter 11 | ILLEGAL_FIELD_SIGNATURE = \ 12 | Der Datentyp {0} wird von args4j nicht unterst\u00fctzt 13 | ILLEGAL_OPERAND = \ 14 | "{1}" ist kein g\u00fcltiger Wert f\u00fcr "{0}" 15 | ILLEGAL_BOOLEAN = \ 16 | "{0}" ist kein g\u00fcltiger Boolescher Wert 17 | ILLEGAL_CHAR = \ 18 | "{0}" muss ein einzelnes Zeichen sein 19 | ILLEGAL_LIST = \ 20 | Der Typ von {0} ist keine List 21 | FORMAT_ERROR_FOR_MAP = \ 22 | Ein Argument f\u00fcr eine Map muss ein "=" enthalten 23 | MAP_HAS_NO_KEY = \ 24 | A Schl\u00fcssel muss gesetzt sein 25 | ILLEGAL_PATTERN = \ 26 | "{0}" muss ein regul\u00e4rer Ausdruck sein 27 | ILLEGAL_IP_ADDRESS = \ 28 | "{0}" ist keine g\u00fcltige IP-Adresse 29 | ILLEGAL_MAC_ADDRESS = \ 30 | "{0}" ist keine g\u00fcltige MAC-Adresse 31 | ILLEGAL_UUID = \ 32 | "{0}" ist keine g\u00fcltige UUID 33 | ILLEGAL_PATH = \ 34 | Pfad "{0}" ist nicht g\u00fcltig 35 | DEFAULT_META_EXPLICIT_BOOLEAN_OPTION_HANDLER = \ 36 | WERT 37 | DEFAULT_META_FILE_OPTION_HANDLER = \ 38 | DATEI 39 | DEFAULT_META_INET_ADDRESS_OPTION_HANDLER = \ 40 | IP ADRESSE 41 | DEFAULT_META_MAC_ADDRESS_OPTION_HANDLER = \ 42 | MAC ADRESSE 43 | DEFAULT_META_PATH_OPTION_HANDLER = \ 44 | PFAD 45 | DEFAULT_META_PATTERN_OPTION_HANDLER = \ 46 | REGEX 47 | DEFAULT_META_STRING_OPTION_HANDLER = \ 48 | WERT 49 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/Messages_en.properties: -------------------------------------------------------------------------------- 1 | # this file is intentionally empty to fall back to the default 2 | # which is the English locale 3 | 4 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/Messages_ru.properties: -------------------------------------------------------------------------------- 1 | 2 | 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 3 | 4 | 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 5 | 6 | 7 | # For Translation 8 | #------------------- 9 | # ILLEGAL_OPERAND = "{1}" is not a valid value for "{0}" 10 | # ILLEGAL_BOOLEAN = "{0}" is not a legal boolean value 11 | # ILLEGAL_CHAR = "{0}" must be a single character 12 | # ILLEGAL_LIST = type of {0} is not a List -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/MethodSetter.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.*; 4 | 5 | import java.lang.reflect.AnnotatedElement; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.lang.reflect.Method; 8 | 9 | /** 10 | * {@link Setter} that sets to a {@link Method}. 11 | * 12 | * @author Kohsuke Kawaguchi 13 | */ 14 | public final class MethodSetter implements Setter { 15 | private final CmdLineParser parser; 16 | private final Object bean; 17 | private final Method m; 18 | 19 | public MethodSetter(CmdLineParser parser, Object bean, Method m) { 20 | this.parser = parser; 21 | this.bean = bean; 22 | this.m = m; 23 | if(m.getParameterTypes().length!=1) 24 | throw new IllegalAnnotationError(Messages.ILLEGAL_METHOD_SIGNATURE.format(m)); 25 | } 26 | 27 | public Class getType() { 28 | return m.getParameterTypes()[0]; 29 | } 30 | 31 | public boolean isMultiValued() { 32 | // multiple values can be handled by calling methods repeatedly 33 | return true; 34 | } 35 | 36 | public FieldSetter asFieldSetter() { 37 | return null; 38 | } 39 | 40 | public AnnotatedElement asAnnotatedElement() { 41 | return m; 42 | } 43 | 44 | public void addValue(Object value) throws CmdLineException { 45 | try { 46 | try { 47 | m.invoke(bean,value); 48 | } catch (IllegalAccessException ex) { 49 | // try again 50 | m.setAccessible(true); 51 | try { 52 | m.invoke(bean,value); 53 | } catch (IllegalAccessException e) { 54 | throw new IllegalAccessError(e.getMessage()); 55 | } 56 | } 57 | } catch (InvocationTargetException e) { 58 | Throwable t = e.getTargetException(); 59 | if(t instanceof RuntimeException) 60 | throw (RuntimeException)t; 61 | if(t instanceof Error) 62 | throw (Error)t; 63 | if(t instanceof CmdLineException) 64 | throw (CmdLineException)t; 65 | 66 | // otherwise wrap 67 | if(t!=null) 68 | throw new CmdLineException(parser, t); 69 | else 70 | throw new CmdLineException(parser, e); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/MultiFileOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineParser; 4 | import org.kohsuke.args4j.OptionDef; 5 | 6 | import java.io.File; 7 | 8 | /** 9 | * Takes a classpath like option ("-cp a.jar;b.jar;c") and maps them to a collection of {@link File}. 10 | * 11 | * @author kmahoney 12 | */ 13 | public class MultiFileOptionHandler extends DelimitedOptionHandler { 14 | protected static String sysPathSeperator = System.getProperty("path.separator"); 15 | public MultiFileOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 16 | super(parser, option, setter, sysPathSeperator, new FileOptionHandler(parser, option, setter)); 17 | } 18 | } -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/MultiPathOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineParser; 4 | import org.kohsuke.args4j.OptionDef; 5 | 6 | import java.nio.file.Path; 7 | 8 | /** 9 | * Takes a classpath like option ("-cp a.jar;b.jar;c") and maps them to a collection of {@link Path}. 10 | * 11 | * @author kmahoney 12 | */ 13 | public class MultiPathOptionHandler extends DelimitedOptionHandler { 14 | protected static String sysPathSeperator = System.getProperty("path.separator"); 15 | public MultiPathOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 16 | super(parser, option, setter, sysPathSeperator, new PathOptionHandler(parser, option, setter)); 17 | } 18 | } -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/MultiValueFieldSetter.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.*; 4 | 5 | import java.lang.reflect.AnnotatedElement; 6 | import java.lang.reflect.Field; 7 | import java.lang.reflect.ParameterizedType; 8 | import java.lang.reflect.Type; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * {@link Setter} that sets multiple values to a collection {@link Field}. 14 | * 15 | * @author Kohsuke Kawaguchi 16 | */ 17 | final class MultiValueFieldSetter implements Getter, Setter { 18 | private final Object bean; 19 | private final Field f; 20 | 21 | public MultiValueFieldSetter(Object bean, Field f) { 22 | this.bean = bean; 23 | this.f = f; 24 | 25 | if(!List.class.isAssignableFrom(f.getType())) 26 | throw new IllegalAnnotationError(Messages.ILLEGAL_FIELD_SIGNATURE.format(f.getType())); 27 | } 28 | 29 | public boolean isMultiValued() { 30 | return true; 31 | } 32 | 33 | public FieldSetter asFieldSetter() { 34 | return new FieldSetter(bean,f); 35 | } 36 | 37 | public AnnotatedElement asAnnotatedElement() { 38 | return f; 39 | } 40 | 41 | public Class getType() { 42 | // TODO: compute this correctly 43 | Type t = f.getGenericType(); 44 | if(t instanceof ParameterizedType) { 45 | ParameterizedType pt = (ParameterizedType)t; 46 | t = pt.getActualTypeArguments()[0]; 47 | if(t instanceof Class) 48 | return (Class)t; 49 | } 50 | return Object.class; 51 | } 52 | 53 | public void addValue(Object value) { 54 | try { 55 | doAddValue(bean, value); 56 | } catch (IllegalAccessException ex) { 57 | // try again 58 | f.setAccessible(true); 59 | try { 60 | doAddValue(bean,value); 61 | } catch (IllegalAccessException e) { 62 | throw new IllegalAccessError(e.getMessage()); 63 | } 64 | } 65 | } 66 | 67 | private void doAddValue(Object bean, Object value) throws IllegalAccessException { 68 | Object o = f.get(bean); 69 | if(o==null) { 70 | o = new ArrayList(); 71 | f.set(bean,o); 72 | } 73 | if(!(o instanceof List)) 74 | throw new IllegalAnnotationError(Messages.ILLEGAL_LIST.format(f)); 75 | 76 | ((List)o).add(value); 77 | } 78 | 79 | public List getValueList() { 80 | try { 81 | f.setAccessible(true); 82 | return (List)f.get(bean); 83 | } 84 | catch (IllegalAccessException ex) { 85 | throw new IllegalAccessError(ex.getMessage()); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/OneArgumentOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineException; 4 | import org.kohsuke.args4j.CmdLineParser; 5 | import org.kohsuke.args4j.OptionDef; 6 | 7 | /** 8 | * OptionHandler which handles an option with exactly one argument, like "-foo bar". 9 | * @author Jan Materne 10 | * @since 2.0.9 11 | * @param Type of the Setter-class 12 | */ 13 | public abstract class OneArgumentOptionHandler extends OptionHandler { 14 | 15 | public OneArgumentOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 16 | super(parser, option, setter); 17 | } 18 | 19 | @Override 20 | public String getDefaultMetaVariable() { 21 | return "N"; 22 | } 23 | 24 | @Override 25 | public int parseArguments(Parameters params) throws CmdLineException { 26 | String token = params.getParameter(0); 27 | try { 28 | T value = parse(token); 29 | setter.addValue(value); 30 | } 31 | catch (NumberFormatException ex) { 32 | throw new CmdLineException(owner, Messages.ILLEGAL_OPERAND, params.getParameter(-1), token); 33 | } 34 | return 1; 35 | } 36 | 37 | /** 38 | * Parses a string to a real value of Type <T>. 39 | * @param argument String value to parse 40 | * @return the parsed value 41 | * @throws NumberFormatException if parsing is not possible 42 | * @throws CmdLineException 43 | * if the parsing encounters a failure that should be reported to the user. 44 | */ 45 | protected abstract T parse(String argument) throws NumberFormatException, CmdLineException; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/OptionImpl.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.Option; 4 | 5 | /** 6 | * Implementation of @Option so we can instantiate it. 7 | * @author Jan Materne 8 | */ 9 | public class OptionImpl extends AnnotationImpl implements Option { 10 | public OptionImpl(ConfigElement ce) throws ClassNotFoundException { 11 | super(Option.class, ce); 12 | name = ce.name; 13 | } 14 | 15 | public String name; 16 | public String name() { 17 | return name; 18 | } 19 | 20 | public String[] depends; 21 | public String[] depends() { 22 | return depends; 23 | } 24 | 25 | public String[] forbids; 26 | public String[] forbids() { 27 | return forbids; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/Parameters.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineException; 4 | 5 | /** 6 | * List of arguments. 7 | * 8 | *

9 | * Object of this interface is passed to 10 | * {@link OptionHandler}s to make it easy/safe to parse 11 | * additional parameters for options. 12 | */ 13 | public interface Parameters { 14 | /** 15 | * Gets the additional parameter to this option. 16 | * 17 | * @param idx 18 | * specifying 0 will retrieve the token next to the option. 19 | * For example, if the command line looks like -o abc -d x, 20 | * then {@code getParameter(0)} for -o returns {@code abc} 21 | * and {@code getParameter(1)} will return -d. 22 | * 23 | * @return 24 | * Always return non-{@code null} valid {@code String}. If an attempt is 25 | * made to access a non-existent index, this method throws 26 | * appropriate {@link org.kohsuke.args4j.CmdLineException}. 27 | */ 28 | String getParameter(int idx) throws CmdLineException; 29 | 30 | /** 31 | * Number of remaining tokens. 32 | */ 33 | int size(); 34 | } 35 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/PathOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineException; 4 | import org.kohsuke.args4j.CmdLineParser; 5 | import org.kohsuke.args4j.OptionDef; 6 | 7 | import java.nio.file.Path; 8 | import java.nio.file.Paths; 9 | 10 | /** 11 | * Takes a single argument to the option and maps that to {@link Path}. 12 | * 13 | * @author kmahoney 14 | */ 15 | public class PathOptionHandler extends OneArgumentOptionHandler { 16 | public PathOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 17 | super(parser, option, setter); 18 | } 19 | 20 | @Override 21 | protected Path parse(String argument) throws NumberFormatException, CmdLineException { 22 | try { 23 | return Paths.get(argument); 24 | } 25 | catch (Exception e) { 26 | throw new CmdLineException(owner, Messages.ILLEGAL_PATH, argument); 27 | } 28 | } 29 | 30 | @Override 31 | public String getDefaultMetaVariable() { 32 | return Messages.DEFAULT_META_PATH_OPTION_HANDLER.format(); 33 | } 34 | } -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/PatternOptionHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | package org.kohsuke.args4j.spi; 8 | 9 | import java.util.regex.Pattern; 10 | import java.util.regex.PatternSyntaxException; 11 | import org.kohsuke.args4j.CmdLineException; 12 | import org.kohsuke.args4j.CmdLineParser; 13 | import org.kohsuke.args4j.OptionDef; 14 | 15 | /** 16 | * A regex option handler. 17 | * @author Stephan Fuhrmann 18 | */ 19 | public class PatternOptionHandler extends OptionHandler { 20 | 21 | public PatternOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 22 | super(parser, option, setter); 23 | } 24 | 25 | @Override 26 | public int parseArguments(Parameters params) throws CmdLineException { 27 | String s = params.getParameter(0); 28 | Pattern p; 29 | try { 30 | p = Pattern.compile(s); 31 | } 32 | catch (PatternSyntaxException x) { 33 | throw new CmdLineException(owner, Messages.ILLEGAL_PATTERN.format(option.toString(), s)); 34 | } 35 | setter.addValue(p); 36 | return 1; 37 | } 38 | 39 | @Override 40 | public String getDefaultMetaVariable() { 41 | return Messages.DEFAULT_META_PATTERN_OPTION_HANDLER.format(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/RestOfArgumentsHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.Argument; 4 | import org.kohsuke.args4j.CmdLineParser; 5 | import org.kohsuke.args4j.OptionDef; 6 | import org.kohsuke.args4j.CmdLineException; 7 | 8 | /** 9 | * Eagerly grabs all the arguments. 10 | * 11 | *

12 | * Used with {@link Argument}, this implements a semantics where 13 | * non-option token causes the option parsing to terminate. 14 | * An example of this is ssh(1), where ssh -p 222 abc will treat 15 | * -p as an option to ssh, but ssh abc -p 222 is 16 | * considered to have no option for ssh. 17 | * 18 | * @author Kohsuke Kawaguchi 19 | */ 20 | public class RestOfArgumentsHandler extends OptionHandler { 21 | public RestOfArgumentsHandler(CmdLineParser cmdLineParser, OptionDef optionDef, Setter setter) { 22 | super(cmdLineParser, optionDef, setter); 23 | } 24 | 25 | public int parseArguments(Parameters parameters) throws CmdLineException { 26 | for (int i=0; i 13 | * This abstracts away the difference between a field and a setter method, 14 | * which object we are setting the value to, 15 | * and/or how we handle collection fields differently. 16 | * @see Getter 17 | * @author Kohsuke Kawaguchi 18 | */ 19 | public interface Setter { 20 | /** 21 | * Adds/sets a value to the property of the option bean. 22 | * 23 | *

24 | * A {@link Setter} object has an implicit knowledge about the property it's setting, 25 | * and the instance of the option bean. 26 | */ 27 | void addValue(T value) throws CmdLineException; 28 | 29 | /** 30 | * Gets the type of the underlying method/field. 31 | */ 32 | Class getType(); 33 | 34 | /** 35 | * Whether this setter is intrinsically multi-valued. 36 | * 37 | *

38 | * When parsing arguments (instead of options), intrinsically multi-valued setters consume 39 | * all the remaining arguments. So, if the setter can store multiple values, 40 | * this method should return {@code true}. 41 | * 42 | *

43 | * This characteristics of a setter doesn't affect option parsing at all; any options can be 44 | * specified multiple times. In many cases, this is a no-op--but when your shell script expands 45 | * multiple environment variables (each of which may contain options), tolerating such 46 | * redundant options can be useful. 47 | */ 48 | boolean isMultiValued(); 49 | 50 | /** 51 | * If this setter encapsulates a field, return the direct access to that field as 52 | * {@link FieldSetter}. This method serves two purposes: 53 | * 54 | *

    55 | *
  1. This lets {@link OptionHandler}s bypass the collection/array handling of fields. 56 | * This is useful if you're defining an option handler that produces array or collection 57 | * from a single argument.
  2. 58 | *
  3. The other is to retrieve the current value of the field (via {@link FieldSetter#getValueList()}).
  4. 59 | *
60 | * 61 | * @return 62 | * {@code null} if this setter wraps a method. 63 | */ 64 | FieldSetter asFieldSetter(); 65 | 66 | /** 67 | * Returns the {@link AnnotatedElement} by which you can access annotations written on this setter. 68 | * 69 | * This is the same {@link AnnotatedElement} that had {@link Option}/{@link Argument}. 70 | * 71 | *

72 | * This enables {@link OptionHandler} to further tweak its behavior based on additional annotations. 73 | */ 74 | AnnotatedElement asAnnotatedElement(); 75 | } 76 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/Setters.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.lang.reflect.AccessibleObject; 4 | import java.lang.reflect.Field; 5 | import java.lang.reflect.Method; 6 | import java.lang.reflect.Modifier; 7 | import java.util.List; 8 | 9 | import org.kohsuke.args4j.CmdLineParser; 10 | 11 | /** 12 | * Factory of {@link Setter}s. 13 | * 14 | * @author Kohsuke Kawaguchi 15 | */ 16 | public class Setters { 17 | 18 | private Setters() { 19 | // no instance allowed 20 | } 21 | 22 | public static Setter create(CmdLineParser parser, AccessibleObject fieldOrMethod, Object bean) { 23 | if (fieldOrMethod instanceof Method) { 24 | return new MethodSetter(parser,bean,(Method) fieldOrMethod); 25 | } else { 26 | return create((Field)fieldOrMethod,bean); 27 | } 28 | } 29 | 30 | public static Setter create(Field f, Object bean) { 31 | if (Modifier.isFinal(f.getModifiers())) 32 | throw new IllegalStateException(String.format("Cannot set value to a final field '%s'.", f.getDeclaringClass().getName()+"."+f.getName())); 33 | if(f.getType().isArray()) 34 | return new ArrayFieldSetter(bean,f); 35 | if(List.class.isAssignableFrom(f.getType())) 36 | return new MultiValueFieldSetter(bean,f); 37 | else 38 | return new FieldSetter(bean,f); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/ShortOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineParser; 4 | import org.kohsuke.args4j.OptionDef; 5 | 6 | /** 7 | * {@link Short} 8 | * {@link OptionHandler} 9 | * {@link OneArgumentOptionHandler} 10 | * @author Jan Materne 11 | * @since 2.0.9 12 | */ 13 | public class ShortOptionHandler extends OneArgumentOptionHandler { 14 | 15 | public ShortOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 16 | super(parser, option, setter); 17 | } 18 | 19 | @Override 20 | protected Short parse(String argument) throws NumberFormatException { 21 | return Short.parseShort(argument); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/StopOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineException; 4 | import org.kohsuke.args4j.CmdLineParser; 5 | import org.kohsuke.args4j.OptionDef; 6 | 7 | /** 8 | * {@link OptionHandler} for the option terminator --. 9 | * 10 | *

11 | * This {@link OptionHandler} can be used to implement the special token 12 | * -- that indicates that the rest of tokens are not options, but arguments. 13 | * 14 | *

15 | * For example, if you have the following class: 16 | * 17 | *

18 |  *  
19 |  * class Foo {
20 |  *  {@literal @}Argument
21 |  *  {@literal @}Option(name="--",handler={@link StopOptionHandler}.class)
22 |  *   List<String> args;
23 |  *
24 |  *  {@literal @}Option(name="-n")
25 |  *   int n;
26 |  * }
27 |  * 
28 | * 29 | *

30 | * The command line -n 5 abc def would parse into {@code n=5, args={"abc",def"}}, 31 | * but -- -n 5 abc def would parse into {@code n=0, args={"-n","5","abc","def"}}. 32 | * 33 | * @author Kohsuke Kawaguchi 34 | */ 35 | public class StopOptionHandler extends OptionHandler { 36 | public StopOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 37 | super(parser, option, setter); 38 | } 39 | 40 | @Override 41 | public int parseArguments(Parameters params) throws CmdLineException { 42 | owner.stopOptionParsing(); 43 | return 0; 44 | } 45 | 46 | @Override 47 | public String getDefaultMetaVariable() { 48 | return Messages.DEFAULT_META_REST_OF_ARGUMENTS_HANDLER.format(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/StringArrayOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineException; 4 | import org.kohsuke.args4j.CmdLineParser; 5 | import org.kohsuke.args4j.OptionDef; 6 | 7 | /** 8 | *

9 | * An {@link OptionHandler} for greedily mapping a list of tokens into a collection of {@link String}s 10 | * (such as {@code String[]}, {@code List}, etc.). 11 | *

12 | * 13 | *

How it works:

14 | * 15 | *

16 | * Example for parameter {@code -s}, which is type {@code String[]}:

17 | * 18 | *
{@code
19 |  * java -jar aaa.jar -s banan hruska jablko
20 |  * java -jar aaa.jar -s banan "hruska jablko"
21 |  * java -jar aaa.jar -s "banan hruska jablko"
22 |  * java -jar aaa.jar -s banan hruska jablko -l 4 -r
23 |  * java -jar aaa.jar -t 222 -s banan hruska jablko -r
24 |  * }
25 | * 26 | *

27 | * All of them result in a single string array that contains three tokens: 28 | * banan, hruska, and jablko.

29 | * 30 | *

31 | * This {@code OptionHandler} scans for parameter which begins with -. If found, it will stop.

32 | * 33 | * @author PlainText,LuVar 34 | */ 35 | public class StringArrayOptionHandler extends OptionHandler { 36 | 37 | public StringArrayOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 38 | super(parser, option, setter); 39 | } 40 | 41 | /** 42 | * Returns {@code "STRING[]"}. 43 | * 44 | * @return return "STRING[]"; 45 | */ 46 | @Override 47 | public String getDefaultMetaVariable() { 48 | return Messages.DEFAULT_META_STRING_ARRAY_OPTION_HANDLER.format(); 49 | } 50 | 51 | /** 52 | * Tries to parse {@code String[]} argument from {@link Parameters}. 53 | */ 54 | @Override 55 | public int parseArguments(Parameters params) throws CmdLineException { 56 | int counter=0; 57 | for (; counter { 13 | public StringOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 14 | super(parser, option, setter); 15 | } 16 | 17 | @Override 18 | public int parseArguments(Parameters params) throws CmdLineException { 19 | setter.addValue(params.getParameter(0)); 20 | return 1; 21 | } 22 | 23 | @Override 24 | public String getDefaultMetaVariable() { 25 | return Messages.DEFAULT_META_STRING_OPTION_HANDLER.format(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/SubCommand.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | /** 7 | * Specifies a single sub-command. 8 | * 9 | * @see SubCommandHandler 10 | * @author Kohsuke Kawaguchi 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface SubCommand { 14 | /** 15 | * Name of the sub-command. 16 | * This must appear as-is in the command line for this sub-command to be activated. 17 | */ 18 | String name(); 19 | 20 | /** 21 | * The implementation class of this sub command. 22 | * 23 | * When a sub-command is selected, this class is instantiated and the rest of the arguments 24 | * will be parsed against this new instance. 25 | */ 26 | Class impl(); 27 | } 28 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/SubCommands.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Collection of {@link SubCommand}s that define possible sub-commands. 10 | * 11 | * @see SubCommandHandler 12 | * @author Kohsuke Kawaguchi 13 | */ 14 | @Target({ElementType.FIELD,ElementType.METHOD}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | public @interface SubCommands { 17 | SubCommand[] value(); 18 | } 19 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/URIOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineException; 4 | import org.kohsuke.args4j.CmdLineParser; 5 | import org.kohsuke.args4j.OptionDef; 6 | 7 | import java.net.URI; 8 | import java.net.URISyntaxException; 9 | 10 | /** 11 | * {@link URI} {@link OptionHandler}. 12 | * 13 | * @author Kohsuke Kawaguchi 14 | */ 15 | public class URIOptionHandler extends OptionHandler { 16 | public URIOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 17 | super(parser, option, setter); 18 | } 19 | 20 | @Override 21 | public int parseArguments(Parameters params) throws CmdLineException { 22 | String param = params.getParameter(0); 23 | try { 24 | setter.addValue(new URI(param)); 25 | return 1; 26 | } catch (URISyntaxException e) { 27 | throw new CmdLineException(owner, Messages.ILLEGAL_OPERAND, params.getParameter(-1), param); 28 | } 29 | } 30 | 31 | @Override 32 | public String getDefaultMetaVariable() { 33 | return Messages.DEFAULT_META_URI_OPTION_HANDLER.format(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/URLOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import org.kohsuke.args4j.CmdLineException; 4 | import org.kohsuke.args4j.CmdLineParser; 5 | import org.kohsuke.args4j.OptionDef; 6 | 7 | import java.net.MalformedURLException; 8 | import java.net.URL; 9 | 10 | /** 11 | * {@link URL} {@link OptionHandler}. 12 | * 13 | * @author Kohsuke Kawaguchi 14 | */ 15 | public class URLOptionHandler extends OptionHandler { 16 | public URLOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { 17 | super(parser, option, setter); 18 | } 19 | 20 | @Override 21 | public int parseArguments(Parameters params) throws CmdLineException { 22 | String param = params.getParameter(0); 23 | try { 24 | setter.addValue(new URL(param)); 25 | return 1; 26 | } catch (MalformedURLException e) { 27 | throw new CmdLineException(owner, Messages.ILLEGAL_OPERAND, 28 | params.getParameter(-1), param); 29 | } 30 | } 31 | 32 | @Override 33 | public String getDefaultMetaVariable() { 34 | return Messages.DEFAULT_META_URL_OPTION_HANDLER.format(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/UuidOptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.util.UUID; 4 | 5 | import org.kohsuke.args4j.CmdLineException; 6 | import org.kohsuke.args4j.CmdLineParser; 7 | import org.kohsuke.args4j.OptionDef; 8 | 9 | /** 10 | * {@link UUID} {@link OptionHandler}. 11 | * 12 | * @author Tobias Stolzmann 13 | * @see UUID#fromString(String) 14 | */ 15 | public class UuidOptionHandler extends 16 | OneArgumentOptionHandler { 17 | public UuidOptionHandler(CmdLineParser parser, OptionDef option, 18 | Setter setter) { 19 | super(parser, option, setter); 20 | } 21 | 22 | @Override 23 | protected UUID parse(String argument) throws CmdLineException { 24 | try { 25 | if (argument.startsWith("{")) argument=argument.substring(1); 26 | if (argument.endsWith("}")) argument=argument.substring(0,argument.length()-1); 27 | return UUID.fromString(argument); 28 | } catch (IllegalArgumentException e) { 29 | throw new CmdLineException(owner, 30 | Messages.ILLEGAL_UUID, argument); 31 | } 32 | } 33 | 34 | @Override 35 | public String getDefaultMetaVariable() { 36 | return Messages.DEFAULT_META_UUID_OPTION_HANDLER.format(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /args4j/src/org/kohsuke/args4j/spi/package.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | Classes for extending the behavior of args4j. 4 |

5 | -------------------------------------------------------------------------------- /args4j/test/ExampleTest.java: -------------------------------------------------------------------------------- 1 | import junit.framework.TestCase; 2 | import org.kohsuke.args4j.*; 3 | 4 | import java.io.File; 5 | import java.net.InetAddress; 6 | import java.util.Locale; 7 | 8 | /** 9 | * Tests {@link CmdLineParser#printExample(ExampleMode)} 10 | * 11 | * @author Kohsuke Kawaguchi 12 | */ 13 | public class ExampleTest extends TestCase { 14 | // DOr sort test, start with these not in alphabetical order 15 | 16 | @Option(name = "-h", usage = "this is H", forbids={"-b", "-c"}) 17 | boolean h; 18 | 19 | @Option(required = true, name = "-a", usage = "this is X") 20 | int x; 21 | 22 | @Option(name = "-b", usage = "this is Y", metaVar = "") 23 | File y; 24 | 25 | @Option(name = "-c", usage = "this is Z") 26 | InetAddress z; 27 | 28 | private Locale oldDefault; 29 | 30 | @Override 31 | public void setUp() { 32 | oldDefault = Locale.getDefault(); 33 | Locale.setDefault(Locale.ENGLISH); 34 | } 35 | 36 | @Override 37 | protected void tearDown() throws Exception { 38 | Locale.setDefault(oldDefault); 39 | } 40 | 41 | public void testPrintExampleModeAll() { 42 | String s = new CmdLineParser(this).printExample(ExampleMode.ALL); 43 | assertEquals(" -a N -b -c IP ADDRESS -h", s); 44 | } 45 | 46 | public void testPrintExampleModeRequired() { 47 | String s = new CmdLineParser(this).printExample(ExampleMode.REQUIRED); 48 | assertEquals(" -a N", s); 49 | } 50 | 51 | public void testParsingAllArgs() throws Exception { 52 | CmdLineParser parser = new CmdLineParser(this); 53 | parser.parseArgument("-a", "1", "-b", "foo", "-c", "1.2.3.4"); 54 | assertEquals(1, x); 55 | assertEquals(new File("foo"), y); 56 | assertEquals(InetAddress.getByName("1.2.3.4"), z); 57 | } 58 | 59 | public void testParsingOnlyRequiredArgs() throws Exception { 60 | CmdLineParser parser = new CmdLineParser(this); 61 | parser.parseArgument("-a", "1"); 62 | assertEquals(1, x); 63 | assertNull(y); 64 | assertNull(z); 65 | } 66 | 67 | public void testParsingMissingRequiredArgs() throws Exception { 68 | CmdLineParser parser = new CmdLineParser(this); 69 | try { 70 | parser.parseArgument("-b", "foo"); 71 | fail("Should have thrown an exception because" 72 | + " required arg 'a' is missing"); 73 | } catch (CmdLineException e) { 74 | assertEquals("Option \"-a\" is required", e.getMessage()); 75 | } 76 | } 77 | 78 | public void testForbidArgs() throws Exception { 79 | CmdLineParser parser = new CmdLineParser(this); 80 | try { 81 | parser.parseArgument("-h", "-a", "2", "-b", "1"); 82 | fail("Should have thrown an exception because" 83 | + " arg 'h' forbids 'b'"); 84 | } catch (CmdLineException e) { 85 | assertEquals("option \"-h\" cannot be used with the option(s) [-b, -c]", e.getMessage()); 86 | } 87 | } 88 | 89 | public void testNoOptionsSort() { 90 | ParserProperties properties = ParserProperties.defaults().withOptionSorter(null); 91 | String s = new CmdLineParser(this, properties).printExample(ExampleMode.ALL); 92 | assertEquals(" -h -a N -b -c IP ADDRESS", s); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /args4j/test/MandatoryOptionTest.java: -------------------------------------------------------------------------------- 1 | import junit.framework.TestCase; 2 | import org.kohsuke.args4j.CmdLineException; 3 | import org.kohsuke.args4j.CmdLineParser; 4 | import org.kohsuke.args4j.Option; 5 | 6 | /** 7 | * Tests mandatory options. 8 | * 9 | * @author Kohsuke Kawaguchi 10 | */ 11 | public class MandatoryOptionTest extends TestCase { 12 | @Option(required=true,name="-a") 13 | int x; 14 | 15 | @Option(name="-b") 16 | int y; 17 | 18 | public void test1() throws Exception { 19 | CmdLineParser p = new CmdLineParser(this); 20 | p.parseArgument("-a","3","-b","2"); 21 | assertEquals(x,3); 22 | assertEquals(y,2); 23 | 24 | p = new CmdLineParser(this); 25 | try { 26 | p.parseArgument("-b","2"); 27 | fail(); 28 | } catch(CmdLineException e) { 29 | System.out.println(e.getMessage()); 30 | assertTrue(e.getMessage().contains("-a")); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/Aliased.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class Aliased { 4 | @Option(name="-str",aliases={ "--long-str" },usage="set a string",metaVar="METAVAR") 5 | public String str; 6 | } 7 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/AliasedTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class AliasedTest extends Args4JTestBase { 4 | @Override 5 | public Aliased getTestObject() { 6 | return new Aliased(); 7 | } 8 | 9 | public void testMissingParameter() { 10 | setArgs("-str"); 11 | try { 12 | parser.parseArgument(args); 13 | fail("Should miss one parameter."); 14 | } catch (CmdLineException e) { 15 | String expectedError = "Option \"-str (--long-str)\" takes an operand"; 16 | String expectedUsage = " -str (--long-str) METAVAR : set a string"; 17 | String[] usageLines = getUsageMessage(); 18 | assertUsageLength(1); 19 | assertErrorMessagePrefix(expectedError, e); 20 | assertEquals("Got wrong usage message", expectedUsage, usageLines[0]); 21 | } 22 | } 23 | 24 | public void testAlias() throws Exception { 25 | setArgs("--long-str", "something"); 26 | parser.parseArgument(args); 27 | assertEquals("something", testObject.str); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/ArgumentTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import junit.framework.TestCase; 4 | 5 | import java.util.List; 6 | 7 | public class ArgumentTest extends TestCase { 8 | protected static class MultiValueHolder { 9 | @Argument 10 | public List things; 11 | } 12 | 13 | protected static class SingleValueHolder { 14 | @Argument(metaVar = "thing", required = true) 15 | public String thing; 16 | } 17 | 18 | protected static class BooleanValueHolder { 19 | @Argument(metaVar = "thing", required = true) 20 | public boolean b; 21 | } 22 | 23 | public void testMultiValue() throws Exception { 24 | MultiValueHolder holder = new MultiValueHolder(); 25 | CmdLineParser parser = new CmdLineParser(holder); 26 | parser.parseArgument(new String[] { "one", "two" }); 27 | 28 | assertEquals(2, holder.things.size()); 29 | assertEquals("one", holder.things.get(0)); 30 | assertEquals("two", holder.things.get(1)); 31 | } 32 | 33 | public void testTooFew() throws Exception { 34 | SingleValueHolder holder = new SingleValueHolder(); 35 | CmdLineParser parser = new CmdLineParser(holder); 36 | 37 | try { 38 | parser.parseArgument(new String[] {}); 39 | } catch (CmdLineException e) { 40 | assertEquals("Argument \"thing\" is required", e.getMessage()); 41 | return; 42 | } 43 | fail("expected " + CmdLineException.class); 44 | } 45 | 46 | public void testBoolean() throws Exception { 47 | BooleanValueHolder holder = new BooleanValueHolder(); 48 | CmdLineParser parser = new CmdLineParser(holder); 49 | 50 | parser.parseArgument(new String[] { "true" }); 51 | 52 | assertTrue(holder.b); 53 | } 54 | 55 | public void testIllegalBoolean() throws Exception { 56 | BooleanValueHolder holder = new BooleanValueHolder(); 57 | CmdLineParser parser = new CmdLineParser(holder); 58 | 59 | try { 60 | parser.parseArgument(new String[] { "xyz" }); 61 | } catch (CmdLineException e) { 62 | assertEquals("\"xyz\" is not a legal boolean value", e.getMessage()); 63 | return; 64 | } 65 | fail("expected " + CmdLineException.class); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/AtOption.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | @SuppressWarnings("unused") 4 | public class AtOption { 5 | @Option(name="-string",usage="set a string") 6 | public String str = "default"; 7 | 8 | @Option(name="-noUsage") 9 | public String noUsage; 10 | 11 | @Argument 12 | public String arguments[]; 13 | } 14 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/AtOptionTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.PrintWriter; 6 | import java.util.Arrays; 7 | 8 | /** 9 | * Tests the AT sign that reads options from an external file. 10 | * @author Stephan Fuhrmann 11 | */ 12 | public class AtOptionTest extends Args4JTestBase { 13 | @Override 14 | public AtOption getTestObject() { 15 | return new AtOption(); 16 | } 17 | 18 | public void testSimpleAt() throws IOException, CmdLineException { 19 | 20 | File tmp = File.createTempFile("atoption", null); 21 | PrintWriter printWriter = new PrintWriter(tmp); 22 | printWriter.println("-string\nfoo"); 23 | printWriter.close(); 24 | 25 | args = new String[]{"@"+tmp.getAbsolutePath()}; 26 | parser.parseArgument(args); 27 | 28 | assertEquals("foo", testObject.str); 29 | assertNull(testObject.noUsage); 30 | assertNull(testObject.arguments); 31 | 32 | tmp.delete(); 33 | } 34 | 35 | public void testAtAfterOpts() throws IOException, CmdLineException { 36 | 37 | File tmp = File.createTempFile("atoption", null); 38 | PrintWriter printWriter = new PrintWriter(tmp); 39 | printWriter.println("-string\nfoo"); 40 | printWriter.close(); 41 | 42 | args = new String[]{"-noUsage","lala", "@"+tmp.getAbsolutePath()}; 43 | parser.parseArgument(args); 44 | 45 | assertEquals("foo", testObject.str); 46 | assertEquals("lala", testObject.noUsage); 47 | assertNull(testObject.arguments); 48 | 49 | tmp.delete(); 50 | } 51 | 52 | public void testAtBeforeOpts() throws IOException, CmdLineException { 53 | 54 | File tmp = File.createTempFile("atoption", null); 55 | PrintWriter printWriter = new PrintWriter(tmp); 56 | printWriter.println("-string\nfoo"); 57 | printWriter.close(); 58 | 59 | args = new String[]{"@"+tmp.getAbsolutePath(), "-noUsage","lala"}; 60 | parser.parseArgument(args); 61 | 62 | assertEquals("foo", testObject.str); 63 | assertEquals("lala", testObject.noUsage); 64 | assertNull(testObject.arguments); 65 | 66 | tmp.delete(); 67 | } 68 | 69 | public void testAtOptsWithBeingDisabled() throws IOException, CmdLineException { 70 | 71 | parser.getProperties().withAtSyntax(false); 72 | 73 | File tmp = File.createTempFile("atoption", null); 74 | PrintWriter printWriter = new PrintWriter(tmp); 75 | printWriter.println("-string\nfoo"); 76 | printWriter.close(); 77 | 78 | // this time the @-option gets not interpreted because 79 | // it's disabled 80 | args = new String[]{"-noUsage", "foo", "@"+tmp.getAbsolutePath()}; 81 | parser.parseArgument(args); 82 | 83 | assertEquals("default", testObject.str); 84 | assertEquals("foo", testObject.noUsage); 85 | assertEquals(Arrays.asList(new String[] {"@"+tmp.getAbsolutePath()}), 86 | Arrays.asList(testObject.arguments)); 87 | 88 | tmp.delete(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/Bean.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.kohsuke.args4j; 5 | 6 | public class Bean { 7 | String text = "default"; 8 | int number = -1; 9 | } -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/CmdLineExceptionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2014 Kohsuke Kawaguchi. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.kohsuke.args4j; 26 | 27 | import java.util.Locale; 28 | import junit.framework.TestCase; 29 | 30 | /** 31 | * Test case for {@link CmdLineException}. 32 | * @author Stephan Fuhrmann 33 | */ 34 | public class CmdLineExceptionTest extends TestCase { 35 | 36 | private static class TestBean { 37 | @Option(name = "-foo") 38 | String foo; 39 | } 40 | 41 | /*** 42 | * Test for {@link CmdLineException#CmdLineException(org.kohsuke.args4j.CmdLineParser, Localizable, java.lang.String...) } 43 | * and {@link CmdLineException#getLocalizedMessage() }. 44 | */ 45 | public void testGetLocalizedMessage() { 46 | TestBean testBean = new TestBean(); 47 | 48 | Locale cur = Locale.getDefault(); 49 | Locale.setDefault(Locale.GERMANY); 50 | try { 51 | CmdLineParser parser = new CmdLineParser(testBean); 52 | CmdLineException e = new CmdLineException(parser, Messages.NO_ARGUMENT_ALLOWED, "foofoo"); 53 | 54 | assertEquals("No argument is allowed: foofoo", e.getMessage()); 55 | assertEquals("Kein Argument erlaubt: foofoo", e.getLocalizedMessage()); 56 | assertSame(parser, e.getParser()); 57 | } catch (Exception e1) { 58 | Locale.setDefault(cur); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/CustomExceptionTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | // a 'custom' exception 4 | import javax.management.InvalidAttributeValueException; 5 | 6 | 7 | public class CustomExceptionTest extends Args4JTestBase { 8 | 9 | private final String errMsgX = "this is a usual CLI exception"; 10 | private final String errMsgY = "this is a 'custom' exception"; 11 | 12 | 13 | @Option(name="-x") 14 | public void setX(String x) { 15 | throw new IllegalArgumentException(errMsgX); 16 | } 17 | 18 | @Option(name="-y") 19 | public void setY(String y) throws InvalidAttributeValueException { 20 | throw new InvalidAttributeValueException(errMsgX); 21 | } 22 | 23 | 24 | @Override 25 | public CustomExceptionTest getTestObject() { 26 | return this; 27 | } 28 | 29 | 30 | protected void assertException(String expected, Class expectedExceptionClass, String... parserArgs) { 31 | String expMsg = expectedExceptionClass.getName() + ": " + expected; 32 | try { 33 | parser.parseArgument(parserArgs); 34 | fail("Exception expected."); 35 | } catch (RuntimeException e) { 36 | // RuntimeExceptions are passed through the parser to the caller. 37 | assertEquals("Lost exception message.", expMsg, e.toString()); 38 | } catch (CmdLineException e) { 39 | // Other Exceptions are wrapped into a CLE so we must ensure not to loose the 40 | // message. 41 | assertEquals("Lost exception message.", expMsg, e.getMessage()); 42 | } catch (Exception e) { 43 | fail("Wrong exception type thrown."); 44 | } 45 | } 46 | 47 | public void testRuntimeException() throws Exception { 48 | assertException(errMsgX, IllegalArgumentException.class, "-x", "value"); 49 | } 50 | 51 | public void testCustomException() throws Exception { 52 | assertException(errMsgX, InvalidAttributeValueException.class, "-y", "value"); 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/DefaultOption.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | @SuppressWarnings("unused") 7 | public class DefaultOption { 8 | @Option(name="-str",usage="set a string") 9 | public String str = "pretty string"; 10 | 11 | @Option(name="-req",usage="set a string", required = true) 12 | public String req = "required"; 13 | 14 | @Option(name="-noDefault") 15 | public String noDefault; 16 | 17 | @Option(name="-noDefaultReq", required = true) 18 | public String noDefaultReq; 19 | 20 | @Option(name="-byteVal", usage = "my favorite byte") 21 | public byte byteVal; 22 | 23 | @Option(name="-strArray", usage="my favorite strarr") 24 | public String strArray[] = new String[] { "san", "dra", "chen"}; 25 | 26 | public enum DrinkName { 27 | BEER, 28 | WHISKEY, 29 | SCOTCH, 30 | BOURBON, 31 | BRANDY 32 | }; 33 | 34 | @Option(name="-drinkArray", usage="my favorite drinks") 35 | public DrinkName drinkArray[] = new DrinkName[] { DrinkName.BEER, DrinkName.BOURBON }; 36 | 37 | @Option(name="-drink", usage="my favorite drink") 38 | public DrinkName drink = DrinkName.BEER; 39 | 40 | @Option(name="-drinkList", usage="my favorite drinks") 41 | public List drinkList = Arrays.asList(DrinkName.BEER, DrinkName.BRANDY); 42 | 43 | @Argument 44 | public String arguments[] = new String[] { "foo", "bar" }; 45 | } 46 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/DefaultOptionTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * Tests the default option value outputs in many ways. 7 | * @author Stephan Fuhrmann 8 | */ 9 | public class DefaultOptionTest extends Args4JTestBase { 10 | 11 | @Override 12 | public DefaultOption getTestObject() { 13 | return new DefaultOption(); 14 | } 15 | 16 | public void testParseArgumentWithEmptyArgs() throws IOException, CmdLineException { 17 | 18 | String usageMessage[] = getUsageMessage(); 19 | 20 | String testMessageExpected[] = new String[] { 21 | " -byteVal N : my favorite byte (default: 0)", 22 | " -drink [BEER | WHISKEY | SCOTCH | : my favorite drink (default: BEER)", 23 | " BOURBON | BRANDY] ", 24 | " -drinkArray [BEER | WHISKEY | SCOTCH : my favorite drinks (default:", 25 | " | BOURBON | BRANDY] [BEER,BOURBON])", 26 | " -drinkList [BEER | WHISKEY | SCOTCH | : my favorite drinks (default:", 27 | " BOURBON | BRANDY] [BEER,BRANDY])", 28 | " -req VAL : set a string", 29 | " -str VAL : set a string (default: pretty string)", 30 | " -strArray VAL : my favorite strarr (default:", 31 | " [san,dra,chen])" 32 | }; 33 | 34 | for (int i=0; i < usageMessage.length; i++) { 35 | assertEquals("Line "+(i+1)+" wrong", testMessageExpected[i], usageMessage[i]); 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/DependencyOptions.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | /** 4 | * @author Nicolas Geraud 5 | */ 6 | public class DependencyOptions { 7 | @Option(name = "-z", depends ={"-y"}) 8 | int a; 9 | 10 | @Option(name = "-y", depends ={"-z"}) 11 | int b; 12 | 13 | @Option(name = "-a", aliases="--alpha") 14 | int w; 15 | 16 | @Option(name = "-b", aliases="--bravo") 17 | int x; 18 | 19 | @Option(name = "-c", depends ={"--alpha"}) 20 | int y; 21 | 22 | @Option(name = "-d", depends ={"-b", "-c"}) 23 | int z; 24 | 25 | @Option(name = "-h", forbids ={"-a", "-b"}) 26 | int o; 27 | } 28 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/EnumArgument.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | class EnumArgument { 4 | @Argument(required = true, metaVar="ANIMAL") 5 | EnumAttribute.Animal myAnimal; 6 | } -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/EnumArgumentTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import org.kohsuke.args4j.EnumAttribute.Animal; 4 | 5 | import org.junit.Assert; 6 | 7 | 8 | public class EnumArgumentTest extends Args4JTestBase { 9 | 10 | @Override 11 | public EnumArgument getTestObject() { 12 | return new EnumArgument(); 13 | } 14 | 15 | public void testSetEnum() throws CmdLineException { 16 | args = new String[]{"HORSE"}; 17 | assertEquals(null, testObject.myAnimal); 18 | parser.parseArgument(args); 19 | assertEquals(Animal.HORSE, testObject.myAnimal); 20 | } 21 | 22 | public void testSetEnumCaseInsensitive() throws CmdLineException { 23 | args = new String[]{"horse"}; 24 | assertEquals(null, testObject.myAnimal); 25 | parser.parseArgument(args); 26 | assertEquals(Animal.HORSE, testObject.myAnimal); 27 | } 28 | 29 | public void testIllegalArgumentOption() { 30 | args = new String[] { "ILLEGAL_ANIMAL" }; 31 | try { 32 | parser.parseArgument(args); 33 | Assert.fail(); 34 | } catch (CmdLineException e) { 35 | Assert.assertTrue( 36 | "Illegal exception message: " + e.getMessage(), 37 | e.getMessage().startsWith( 38 | String.format("\"%s\" is not a valid value for \"", args[args.length - 1]) 39 | )); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/EnumAttribute.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class EnumAttribute { 4 | 5 | enum Animal { HORSE, DUCK } 6 | 7 | @Option(name="-animal", usage="Give your favorite animal.") 8 | Animal myAnimal; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/EnumAttributeTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import org.kohsuke.args4j.EnumAttribute.Animal; 4 | 5 | public class EnumAttributeTest extends Args4JTestBase { 6 | 7 | @Override 8 | public EnumAttribute getTestObject() { 9 | return new EnumAttribute(); 10 | } 11 | 12 | public void testSetEnum() throws CmdLineException { 13 | args = new String[]{"-animal", "HORSE"}; 14 | parser.parseArgument(args); 15 | assertEquals(Animal.HORSE, testObject.myAnimal); 16 | } 17 | 18 | public void testSetEnumCaseInsensitive() throws CmdLineException { 19 | args = new String[]{"-animal", "horse"}; 20 | parser.parseArgument(args); 21 | assertEquals(Animal.HORSE, testObject.myAnimal); 22 | } 23 | 24 | public void testIllegalEnum() { 25 | args = new String[]{"-animal", "ILLEGAL_ANIMAL"}; 26 | try { 27 | parser.parseArgument(args); 28 | fail("Can't set ILLEGAL_ANIMAL as value."); 29 | } catch (CmdLineException e) { 30 | // exptected 31 | } 32 | } 33 | 34 | public void testUsage() { 35 | args = new String[]{"-wrong"}; 36 | try { 37 | parser.parseArgument(args); 38 | } catch (CmdLineException e) { 39 | assertUsageContains("Usage message should contain the enum VALUES", "HORSE"); 40 | assertUsageContains("Usage message should contain the enum VALUES", "DUCK"); 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/ExplicitBooleanArgumentTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import org.kohsuke.args4j.ExplicitBooleanArgumentTest.BooleanArgumentHolder; 4 | import org.kohsuke.args4j.spi.ExplicitBooleanOptionHandler; 5 | 6 | public class ExplicitBooleanArgumentTest extends Args4JTestBase { 7 | 8 | public static class BooleanArgumentHolder { 9 | @Argument(index = 0, handler = ExplicitBooleanOptionHandler.class, usage = "Set a boolean value") 10 | boolean booleanArg; 11 | } 12 | 13 | @Override 14 | public BooleanArgumentHolder getTestObject() { 15 | return new BooleanArgumentHolder(); 16 | } 17 | 18 | public void testSetBooleanTrue() throws CmdLineException { 19 | args = new String[] { "true" }; 20 | parser.parseArgument(args); 21 | assertTrue(testObject.booleanArg); 22 | } 23 | 24 | public void testSetBooleanOn() throws CmdLineException { 25 | args = new String[] { "on" }; 26 | parser.parseArgument(args); 27 | assertTrue(testObject.booleanArg); 28 | } 29 | 30 | public void testSetBooleanYes() throws CmdLineException { 31 | args = new String[] { "yes" }; 32 | parser.parseArgument(args); 33 | assertTrue(testObject.booleanArg); 34 | } 35 | 36 | public void testSetBooleanTrueCaseInsensitive() throws CmdLineException { 37 | args = new String[] { "tRuE" }; 38 | parser.parseArgument(args); 39 | assertTrue(testObject.booleanArg); 40 | } 41 | 42 | public void testSetBoolean1() throws CmdLineException { 43 | args = new String[] { "1" }; 44 | parser.parseArgument(args); 45 | assertTrue(testObject.booleanArg); 46 | } 47 | 48 | public void testSetBooleanFalse() throws CmdLineException { 49 | args = new String[] { "false" }; 50 | parser.parseArgument(args); 51 | assertFalse(testObject.booleanArg); 52 | } 53 | 54 | public void testSetBooleanOff() throws CmdLineException { 55 | args = new String[] { "off" }; 56 | parser.parseArgument(args); 57 | assertFalse(testObject.booleanArg); 58 | } 59 | 60 | public void testSetBooleanNo() throws CmdLineException { 61 | args = new String[] { "no" }; 62 | parser.parseArgument(args); 63 | assertFalse(testObject.booleanArg); 64 | } 65 | 66 | public void testSetBoolean0() throws CmdLineException { 67 | args = new String[] { "0" }; 68 | parser.parseArgument(args); 69 | assertFalse(testObject.booleanArg); 70 | } 71 | 72 | public void testSetBooleanFalseCaseInsensitive() throws CmdLineException { 73 | args = new String[] { "FaLsE" }; 74 | parser.parseArgument(args); 75 | assertFalse(testObject.booleanArg); 76 | } 77 | 78 | public void testSetBooleanNoValueIsFalse() throws CmdLineException { 79 | args = new String[0]; 80 | parser.parseArgument(args); 81 | assertFalse(testObject.booleanArg); 82 | } 83 | 84 | public void testIllegalBoolean() { 85 | args = new String[] { "ILLEGAL_BOOLEAN" }; 86 | try { 87 | parser.parseArgument(args); 88 | fail("Can't set ILLEGAL_BOOLEAN as value."); 89 | } catch (CmdLineException expected) {} 90 | } 91 | 92 | public void testUsage() { 93 | args = new String[] { "-wrong" }; 94 | try { 95 | parser.parseArgument(args); 96 | } catch (CmdLineException e) { 97 | assertUsageContains("Usage message should contain 'VAL'", "VAL"); 98 | } 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/ExternalConfiguredTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | 4 | import java.io.File; 5 | import java.util.List; 6 | 7 | public class ExternalConfiguredTest extends Args4JTestBase { 8 | 9 | boolean recursive = false; 10 | File out; 11 | String str = "default"; 12 | public void setStr(String s) { 13 | str = s.toUpperCase(); 14 | } 15 | boolean data = false; 16 | List arguments; 17 | 18 | @Override 19 | public ExternalConfiguredTest getTestObject() { 20 | return this; 21 | } 22 | 23 | @Override 24 | protected CmdLineParser createParser() { 25 | CmdLineParser p = new CmdLineParser(new Object()); 26 | new XmlParser().parse(getClass().getResource("ExternalConfiguredTest.xml"),p,this); 27 | return p; 28 | } 29 | 30 | public void testNoArgsGiven() throws CmdLineException { 31 | args = new String[] {}; 32 | parser.parseArgument(args); 33 | assertTrue("Default value for 'str'.", "default".equals(str)); 34 | assertFalse("Default for 'recursive'.", recursive); 35 | assertFalse("Default for 'data'.", data); 36 | } 37 | 38 | public void testFieldSetter() throws CmdLineException { 39 | args = new String[] { "-o", "myfile.txt" }; 40 | parser.parseArgument(args); 41 | assertTrue("Default value for 'str'.", "default".equals(str)); 42 | assertFalse("Default for 'recursive'.", recursive); 43 | assertFalse("Default for 'data'.", data); 44 | assertEquals("myfile.txt", out.getName()); 45 | } 46 | 47 | public void testMethodSetter() throws CmdLineException { 48 | args = new String[] { "-str", "myvalue" }; 49 | parser.parseArgument(args); 50 | assertFalse("Default for 'recursive'.", recursive); 51 | assertFalse("Default for 'data'.", data); 52 | assertTrue("Method setter for '-str' doesnt work.", "MYVALUE".equals(str)); 53 | } 54 | 55 | public void testCustomHandler() throws CmdLineException { 56 | args = new String[] { "-custom" }; 57 | parser.parseArgument(args); 58 | assertTrue("Default value set.", "default".equals(str)); 59 | assertFalse("Default for 'recursive'.", recursive); 60 | assertTrue("Value per custom handler on 'data' not set.", data); 61 | } 62 | 63 | public void testUsage() { 64 | assertUsageContains("'usage' is not evaluated", "recursively run something"); 65 | } 66 | } -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/ExternalConfiguredTest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/FieldParserTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class FieldParserTest extends TestCase { 6 | 7 | private void parse(Object bean, String... args) throws CmdLineException, ClassNotFoundException { 8 | CmdLineParser p = new CmdLineParser(new Object()); 9 | new FieldParser().parse(p, bean); 10 | p.parseArgument(args); 11 | } 12 | 13 | public void testNoArgs() throws CmdLineException, ClassNotFoundException { 14 | Bean bean = new Bean(); 15 | parse(bean); 16 | assertEquals("default", bean.text); 17 | assertEquals(-1, bean.number); 18 | } 19 | 20 | public void testFields() throws CmdLineException, ClassNotFoundException { 21 | Bean bean = new Bean(); 22 | parse(bean, "-text", "newText", "-number", "42"); 23 | assertEquals("newText", bean.text); 24 | assertEquals(42, bean.number); 25 | } 26 | 27 | public void testInheritedFields() throws CmdLineException, ClassNotFoundException { 28 | InheritedBean bean = new InheritedBean(); 29 | parse(bean, "-text", "newText", "-number", "42", "-text2", "newText"); 30 | assertEquals("newText", bean.text2); 31 | assertEquals("newText", bean.text); 32 | assertEquals(42, bean.number); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/HelpOption.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class HelpOption { 4 | @Option(name="-req",usage="required option",required = true) 5 | public String req1; 6 | 7 | @Option(name="-opt",usage="optional option") 8 | public String optional1; 9 | 10 | @Option(name="-help",help = true) 11 | public boolean help; 12 | } 13 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/HelpOptionTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | /** 4 | * JUnit test for checking whether {@link Option#help() works}. 5 | * @author Stephan Fuhrmann 6 | */ 7 | public class HelpOptionTest extends Args4JTestBase { 8 | @Override 9 | public HelpOption getTestObject() { 10 | return new HelpOption(); 11 | } 12 | 13 | public void testWithRequiredOptionMissing() { 14 | args = new String[]{"-opt", "operand"}; 15 | try { 16 | parser.parseArgument(args); 17 | fail("Doesnt detect missing parameters."); 18 | } catch (CmdLineException e) { 19 | String expectedError = "Option \"-req\" is required"; 20 | String[] usageLines = getUsageMessage(); 21 | String errorMessage = e.getMessage(); 22 | assertUsageLength(2); 23 | assertTrue("Got wrong error message", errorMessage.startsWith(expectedError)); 24 | } 25 | } 26 | 27 | public void testWithRequiredOptionExisting() throws CmdLineException { 28 | args = new String[]{"-req", "operand"}; 29 | parser.parseArgument(args); 30 | 31 | assertFalse(testObject.help); 32 | assertNull(testObject.optional1); 33 | assertEquals("operand", testObject.req1); 34 | } 35 | 36 | public void testWithHelpExistingButRequiredOptionMissing() throws CmdLineException { 37 | args = new String[]{"-help"}; 38 | parser.parseArgument(args); 39 | 40 | assertTrue(testObject.help); 41 | assertNull(testObject.optional1); 42 | assertNull(testObject.req1); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/HiddenOption.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class HiddenOption { 4 | @Option(name="-str",usage="set a string",metaVar="METAVAR",hidden=true) 5 | public String str; 6 | } 7 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/HiddenOptionTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class HiddenOptionTest extends Args4JTestBase { 4 | @Override 5 | public HiddenOption getTestObject() { 6 | return new HiddenOption(); 7 | } 8 | 9 | public void testSettingUsage() { 10 | args = new String[]{"-wrong-usage"}; 11 | try { 12 | parser.parseArgument(args); 13 | fail("Doesnt detect wrong parameters."); 14 | } catch (CmdLineException e) { 15 | String expectedError = "\"-wrong-usage\" is not a valid option"; 16 | String expectedUsage = ""; 17 | String[] usageLines = getUsageMessage(); 18 | assertUsageLength(1); 19 | assertErrorMessagePrefix(expectedError, e); 20 | assertEquals("Got wrong usage message", expectedUsage, usageLines[0]); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/Inheritance.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class Inheritance extends InheritanceFather implements InheritanceMother { 4 | @Option(name="-m") 5 | public String me; 6 | 7 | public String mom; 8 | public void setMom(String m) { 9 | mom = m; 10 | } 11 | 12 | 13 | } 14 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/InheritanceFather.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class InheritanceFather extends InheritanceGrandfather { 4 | @Option(name="-f") 5 | public String father; 6 | } 7 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/InheritanceGrandfather.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class InheritanceGrandfather { 4 | @Option(name="-g") 5 | public String grandpa; 6 | } 7 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/InheritanceMother.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public interface InheritanceMother { 4 | @Option(name="-mom") 5 | public void setMom(String m); 6 | } 7 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/InheritanceTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class InheritanceTest extends Args4JTestBase { 4 | 5 | @Override 6 | public Inheritance getTestObject() { 7 | return new Inheritance(); 8 | } 9 | 10 | public void testMyself() { 11 | args = new String[]{"-m","Thats me"}; 12 | Inheritance bo = testObject; 13 | try { 14 | parser.parseArgument(args); 15 | assertEquals("Value for class itself not arrived", "Thats me", bo.me); 16 | } catch (CmdLineException e) { 17 | fail("This exception should not occur"); 18 | } 19 | } 20 | 21 | public void testFather() { 22 | args = new String[]{"-f","My father"}; 23 | Inheritance bo = testObject; 24 | try { 25 | parser.parseArgument(args); 26 | assertEquals("Value for class itself not arrived", "My father", bo.father); 27 | } catch (CmdLineException e) { 28 | fail("This exception should not occur"); 29 | } 30 | } 31 | 32 | public void testGrandfather() { 33 | args = new String[]{"-g","My fathers father"}; 34 | Inheritance bo = testObject; 35 | try { 36 | parser.parseArgument(args); 37 | assertEquals("Value for class itself not arrived", "My fathers father", bo.grandpa); 38 | } catch (CmdLineException e) { 39 | fail("This exception should not occur"); 40 | } 41 | } 42 | 43 | public void testMother() { 44 | args = new String[]{"-mom","Hi Mom"}; 45 | Inheritance bo = testObject; 46 | try { 47 | parser.parseArgument(args); 48 | assertNull("Annotations are not designed for use in interfaces", bo.mom); 49 | } catch (CmdLineException e) { 50 | //no-op 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/InheritedBean.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package org.kohsuke.args4j; 5 | 6 | public class InheritedBean extends Bean{ 7 | String text2 = "default"; 8 | } -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/Issue10Test.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | 5 | import junit.framework.TestCase; 6 | 7 | /** 8 | * @see https://args4j.dev.java.net/issues/show_bug.cgi?id=10 9 | */ 10 | @SuppressWarnings("unused") 11 | public class Issue10Test extends TestCase { 12 | @Option(name="-enum", required=false, usage="Enum2") 13 | private Enum crash; 14 | 15 | enum Enum { 16 | THIS, ENUM, HAS, A, VERY, LONG, USAGE, LINE, 17 | BECAUSE, OF, ITS, HUGE, LIST, Of, VALUES, 18 | SO, IT, WILL, CRASH 19 | } 20 | 21 | // The bug should be fixed with changing from manual printing to printf. 22 | public void testIssue10() { 23 | CmdLineParser parser = new CmdLineParser(this); 24 | parser.printUsage(new ByteArrayOutputStream()); 25 | // occurred error: StringIndexOutOfBoundsException with index < 0 26 | 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/KeyValue.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | @SuppressWarnings("unused") 4 | public class KeyValue { 5 | 6 | @Option(name="-s", aliases="--string") 7 | public String _string; 8 | 9 | @Option(name="-d", aliases="--double") 10 | public double _double; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/KeyValueTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class KeyValueTest extends Args4JTestBase { 4 | 5 | @Override 6 | public KeyValue getTestObject() { 7 | return new KeyValue(); 8 | } 9 | 10 | public void testDouble() throws CmdLineException { 11 | args = new String[]{"--double=42.54"}; 12 | parser.parseArgument(args); 13 | assertEquals(42.54, testObject._double, 0); 14 | } 15 | 16 | public void testDoubleShort() throws CmdLineException { 17 | args = new String[]{"-d=42.54"}; 18 | parser.parseArgument(args); 19 | assertEquals(42.54, testObject._double, 0); 20 | } 21 | 22 | 23 | public void testChar() throws CmdLineException { 24 | args = new String[]{"--string=stringValue"}; 25 | parser.parseArgument(args); 26 | assertEquals("stringValue", testObject._string); 27 | } 28 | 29 | public void testCharShort() throws CmdLineException { 30 | args = new String[]{"-s=stringValue"}; 31 | parser.parseArgument(args); 32 | assertEquals("stringValue", testObject._string); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/LongUsage.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | /** 4 | * Test object for long option names. 5 | * One short and one long name to 'see' the differences. 6 | * 7 | * @author Jan Materne 8 | */ 9 | @SuppressWarnings("unused") 10 | public class LongUsage { 11 | 12 | @Option(name="-LongNamedStringOption",usage="set a string",metaVar="USE_A_NICE_STRING") 13 | private String s; 14 | 15 | @Option(name="-i",usage="set an int") 16 | private int i; 17 | 18 | } -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/LongUsageTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class LongUsageTest extends Args4JTestBase { 4 | @Override 5 | public LongUsage getTestObject() { 6 | return new LongUsage(); 7 | } 8 | 9 | public void testUsageMessage() { 10 | args = new String[]{"-wrong-usage"}; 11 | try { 12 | // set Widescreen otherwise a line wrapping must occur 13 | parser.setUsageWidth(120); 14 | // start parsing 15 | parser.parseArgument(args); 16 | } catch (CmdLineException e) { 17 | String expectedLine1 = " -LongNamedStringOption USE_A_NICE_STRING : set a string"; 18 | String expectedLine2 = " -i N : set an int (default: 0)"; 19 | String[] usageLines = getUsageMessage(); 20 | assertUsageLength(2); 21 | assertEquals("First line wrong", expectedLine1, usageLines[0]); 22 | assertEquals("Second line wrong", expectedLine2, usageLines[1]); 23 | } 24 | } 25 | 26 | public void testUsageMessageWithNewWayToSet() { 27 | args = new String[]{"-wrong-usage"}; 28 | // set Widescreen otherwise a line wrapping must occur 29 | parser = new CmdLineParser(testObject, 30 | ParserProperties.defaults().withUsageWidth(120)); 31 | try { 32 | // start parsing 33 | parser.parseArgument(args); 34 | } catch (CmdLineException e) { 35 | String expectedLine1 = " -LongNamedStringOption USE_A_NICE_STRING : set a string"; 36 | String expectedLine2 = " -i N : set an int (default: 0)"; 37 | String[] usageLines = getUsageMessage(); 38 | assertUsageLength(2); 39 | assertEquals("First line wrong", expectedLine1, usageLines[0]); 40 | assertEquals("Second line wrong", expectedLine2, usageLines[1]); 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/MultivaluedTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import org.kohsuke.args4j.spi.StringArrayOptionHandler; 4 | 5 | import java.util.List; 6 | 7 | public class MultivaluedTest extends Args4JTestBase { 8 | 9 | // The JavaBean part of this class as test object. 10 | 11 | @Option(name="-list") 12 | List list; 13 | 14 | @Option(name="-string") 15 | String string; 16 | 17 | @Option(name="-array") 18 | String[] array; 19 | 20 | @Option(name="-multivalued-array", handler = StringArrayOptionHandler.class) 21 | String[] multiValuedArray; 22 | 23 | // The JUnit part of this class as tester. 24 | 25 | @Override 26 | public MultivaluedTest getTestObject() { 27 | return this; 28 | } 29 | 30 | public void testOnList() throws Exception { 31 | // The 'command line invocation'. 32 | setArgs( 33 | "-list", "one", 34 | "-list", "two", 35 | "-list", "three" 36 | ); 37 | parser.parseArgument(args); 38 | // Check the results. 39 | assertEquals("Should got three values", 3, list.size()); 40 | assertTrue(list.contains("one")); 41 | assertTrue(list.contains("two")); 42 | assertTrue(list.contains("three")); 43 | } 44 | 45 | /** 46 | * Specifying an option multiple times can get no-op, such as in the case when the field can only retain one value. 47 | */ 48 | public void testOnString() throws Exception { 49 | // The 'command line invocation'. 50 | parser.parseArgument("-string","one","-string","two","-string","three"); 51 | assertEquals("three",string); 52 | } 53 | 54 | public void testOnArray() throws Exception { 55 | // The 'command line invocation'. 56 | parser.parseArgument("-array","one","-array","two","-array","three"); 57 | // Check the results. 58 | assertEquals("Should got three values", 3, array.length); 59 | assertEquals("one",array[0]); 60 | assertEquals("two",array[1]); 61 | assertEquals("three",array[2]); 62 | } 63 | 64 | public void testOnMultiValuedArray() throws Exception { 65 | // The 'command line invocation'. 66 | parser.parseArgument("-multivalued-array","one", "two","-multivalued-array","three"); 67 | // Check the results. 68 | assertEquals("Should got three values", 3, multiValuedArray.length); 69 | assertEquals("one",multiValuedArray[0]); 70 | assertEquals("two",multiValuedArray[1]); 71 | assertEquals("three",multiValuedArray[2]); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/NativeTypes.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | @SuppressWarnings("unused") 4 | public class NativeTypes { 5 | 6 | @Option(name="-boolean") 7 | public boolean _boolean; 8 | 9 | @Option(name="-byte") 10 | public byte _byte; 11 | 12 | @Option(name="-char") 13 | public char _char; 14 | 15 | @Option(name="-double") 16 | public double _double; 17 | 18 | @Option(name="-float") 19 | public float _float; 20 | 21 | @Option(name="-int") 22 | public int _int; 23 | 24 | @Option(name="-long") 25 | public long _long; 26 | 27 | @Option(name="-short") 28 | public short _short; 29 | } 30 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/NativeTypesTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class NativeTypesTest extends Args4JTestBase { 4 | 5 | @Override 6 | public NativeTypes getTestObject() { 7 | return new NativeTypes(); 8 | } 9 | 10 | public void testBooleanTrue() throws CmdLineException { 11 | args = new String[]{"-boolean"}; 12 | parser.parseArgument(args); 13 | assertTrue(testObject._boolean); 14 | } 15 | 16 | public void testBooleanFalse() throws CmdLineException { 17 | args = new String[]{}; 18 | parser.parseArgument(args); 19 | assertFalse(testObject._boolean); 20 | } 21 | 22 | public void testByte() throws CmdLineException { 23 | args = new String[]{"-byte", "42"}; 24 | parser.parseArgument(args); 25 | assertEquals(42, testObject._byte); 26 | } 27 | 28 | public void testChar() throws CmdLineException { 29 | args = new String[]{"-char", "a"}; 30 | parser.parseArgument(args); 31 | assertEquals('a', testObject._char); 32 | } 33 | 34 | public void testDouble() throws CmdLineException { 35 | args = new String[]{"-double", "42"}; 36 | parser.parseArgument(args); 37 | assertEquals(42, testObject._double, 0); 38 | } 39 | 40 | public void testFloat() throws CmdLineException { 41 | args = new String[]{"-float", "42"}; 42 | parser.parseArgument(args); 43 | assertEquals(42, testObject._float, 0); 44 | } 45 | 46 | public void testInt() throws CmdLineException { 47 | args = new String[]{"-int", "42"}; 48 | parser.parseArgument(args); 49 | assertEquals(42, testObject._int); 50 | } 51 | 52 | public void testLong() throws CmdLineException { 53 | args = new String[]{"-long", "42"}; 54 | parser.parseArgument(args); 55 | assertEquals(42, testObject._long); 56 | } 57 | 58 | public void testShort() throws CmdLineException { 59 | args = new String[]{"-short", "42"}; 60 | parser.parseArgument(args); 61 | assertEquals(42, testObject._short); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/ParserPropertiesUnitTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class ParserPropertiesUnitTest extends TestCase { 6 | public void testDefaults() { 7 | ParserProperties props = ParserProperties.defaults(); 8 | assertEquals(80, props.getUsageWidth()); 9 | assertEquals(ParserProperties.DEFAULT_COMPARATOR, props.getOptionSorter()); 10 | } 11 | 12 | public void testSetToSame() { 13 | ParserProperties props = ParserProperties.defaults().withUsageWidth(80); 14 | assertEquals(80, props.getUsageWidth()); 15 | assertEquals(ParserProperties.DEFAULT_COMPARATOR, props.getOptionSorter()); 16 | } 17 | 18 | public void testSetToDifferent() { 19 | ParserProperties props = ParserProperties.defaults().withUsageWidth(90).withOptionSorter(null); 20 | assertEquals(90, props.getUsageWidth()); 21 | assertEquals(null, props.getOptionSorter()); 22 | } 23 | 24 | public void testSetOnlyOne() { 25 | ParserProperties props = ParserProperties.defaults().withOptionSorter(null); 26 | assertEquals(80, props.getUsageWidth()); 27 | assertEquals(null, props.getOptionSorter()); 28 | } 29 | 30 | public void testFailOnNegativeWidth() { 31 | try { 32 | ParserProperties.defaults().withUsageWidth(-1); 33 | fail("accepted negative width"); 34 | } catch (IllegalArgumentException x) { 35 | // OK 36 | } 37 | } 38 | 39 | public void testAcceptPositiveWidth() { 40 | try { 41 | ParserProperties.defaults().withUsageWidth(0); 42 | } catch (IllegalArgumentException x) { 43 | fail("rejected zero width"); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/PrintUsageTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class PrintUsageTest extends Args4JTestBase { 4 | 5 | private class Bean { 6 | @Option(name = "s", usage = "1234567890123456789012345678901234567890") 7 | public String s; 8 | } 9 | 10 | @Override 11 | public Object getTestObject() { 12 | return new Bean(); 13 | } 14 | 15 | public void testEnoughLength() { 16 | String[] args = { "-wrong" }; 17 | try { 18 | parser.parseArgument(args); 19 | } catch (CmdLineException e) { 20 | String[] usageMessage = getUsageMessage(); 21 | assertEquals("Shouldn't split the lines.", 1, usageMessage.length); 22 | } 23 | } 24 | 25 | public void testTooSmallLength() { 26 | String[] args = { "-wrong" }; 27 | try { 28 | parser.setUsageWidth(30); 29 | parser.parseArgument(args); 30 | } catch (CmdLineException e) { 31 | String[] usageMessage = getUsageMessage(); 32 | assertEquals("Should split the lines.", 2, usageMessage.length); 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/Props.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * Test object for setting name-value pairs. 8 | * @author Jan Materne 9 | * @since 2.0.9 10 | */ 11 | public class Props { 12 | 13 | @Option(name="-T",usage="sets a key-value-pair") 14 | public Map props = new HashMap(); 15 | 16 | } -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/Setter.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class Setter { 4 | 5 | public String str = "default"; 6 | 7 | @Option(name="-str",usage="set a string") 8 | public void setStr(String str) { 9 | this.str = str.toUpperCase(); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/SetterTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class SetterTest extends Args4JTestBase { 4 | @Override 5 | public Setter getTestObject() { 6 | return new Setter(); 7 | } 8 | 9 | public void testSettingStringNoValues() { 10 | Setter bo = testObject; 11 | args = new String[]{}; 12 | try { 13 | parser.parseArgument(args); 14 | assertTrue("Default value set.", "default".equals(bo.str)); 15 | } catch (CmdLineException e) { 16 | fail("Call without parameters is valid!"); 17 | } 18 | } 19 | 20 | public void testSettingString() { 21 | Setter bo = testObject; 22 | args = new String[]{"-str","test"}; 23 | try { 24 | parser.parseArgument(args); 25 | assertTrue("Given value set.", "TEST".equals(bo.str)); 26 | } catch (CmdLineException e) { 27 | fail("Setting a string value should be possible"); 28 | } 29 | } 30 | 31 | public void testSettingUsage() { 32 | args = new String[]{"-wrong-usage"}; 33 | try { 34 | parser.parseArgument(args); 35 | fail("Doesnt detect wrong parameters."); 36 | } catch (CmdLineException e) { 37 | String expectedError = "\"-wrong-usage\" is not a valid option"; 38 | String expectedUsage = " -str VAL : set a string"; 39 | String errorMessage = e.getMessage(); 40 | String[] usageLines = getUsageMessage(); 41 | assertUsageLength(1); 42 | assertTrue("Got wrong error message", errorMessage.startsWith(expectedError)); 43 | assertEquals(expectedUsage, usageLines[0]); 44 | } 45 | } 46 | 47 | public void testMissingParameter() { 48 | args = new String[]{"-str"}; 49 | try { 50 | parser.parseArgument(args); 51 | fail("Should miss one parameter."); 52 | } catch (CmdLineException e) { 53 | String expectedError = "Option \"-str\" takes an operand"; 54 | String expectedUsage = " -str VAL : set a string"; 55 | 56 | String[] usageLines = getUsageMessage(); 57 | String errorMessage = e.getMessage(); 58 | assertUsageLength(1); 59 | assertTrue("Got wrong error message: " + errorMessage, errorMessage.startsWith(expectedError)); 60 | assertEquals("Got wrong usage message", expectedUsage, usageLines[0]); 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/SimpleString.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | @SuppressWarnings("unused") 4 | public class SimpleString { 5 | @Option(name="-str",usage="set a string") 6 | public String str = "default"; 7 | 8 | @Option(name="-nu") 9 | public String noUsage; 10 | } 11 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/SimpleStringTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | 4 | public class SimpleStringTest extends Args4JTestBase { 5 | 6 | @Override 7 | public SimpleString getTestObject() { 8 | return new SimpleString(); 9 | } 10 | 11 | public void testSettingStringNoValues() { 12 | SimpleString bo = testObject; 13 | args = new String[]{}; 14 | try { 15 | parser.parseArgument(args); 16 | assertTrue("Default value set.", "default".equals(bo.str)); 17 | } catch (CmdLineException e) { 18 | fail("Call without parameters is valid!"); 19 | } 20 | } 21 | 22 | public void testSettingString() { 23 | SimpleString bo = testObject; 24 | args = new String[]{"-str","test"}; 25 | try { 26 | parser.parseArgument(args); 27 | assertTrue("Given value set.", "test".equals(bo.str)); 28 | } catch (CmdLineException e) { 29 | fail("Setting a string value should be possible"); 30 | } 31 | } 32 | 33 | public void testSettingUsage() { 34 | args = new String[]{"-wrong-usage"}; 35 | try { 36 | parser.parseArgument(args); 37 | fail("Doesnt detect wrong parameters."); 38 | } catch (CmdLineException e) { 39 | String expectedError = "\"-wrong-usage\" is not a valid option"; 40 | String expectedUsage = " -str VAL : set a string (default: default)"; 41 | String[] usageLines = getUsageMessage(); 42 | assertErrorMessagePrefix(expectedError, e); 43 | assertUsageLength(1); 44 | assertEquals("Got wrong usage message", expectedUsage, usageLines[0]); 45 | } 46 | } 47 | 48 | public void testMissingParameter() { 49 | args = new String[]{"-str"}; 50 | try { 51 | parser.parseArgument(args); 52 | fail("Should miss one parameter."); 53 | } catch (CmdLineException e) { 54 | String expectedError = "Option \"-str\" takes an operand"; 55 | String expectedUsage = " -str VAL : set a string (default: default)"; 56 | String[] usageLines = getUsageMessage(); 57 | String errorMessage = e.getMessage(); 58 | assertUsageLength(1); 59 | assertTrue("Got wrong error message: " + errorMessage, errorMessage.startsWith(expectedError)); 60 | assertEquals("Got wrong usage message", expectedUsage, usageLines[0]); 61 | } 62 | } 63 | 64 | /* 65 | * Bug 5: Option without "usage" are hidden. 66 | * TODO: it seems that this is intended: 67 | * http://weblogs.java.net/blog/kohsuke/archive/2005/05/parsing_command.html 68 | * An @option without "usage" should not be displayed? 69 | * If there is no usage information, the CmdLineParser.printOption() 70 | * methods do explitely nothing. 71 | */ 72 | public void _testUsage() { 73 | args = new String[]{"-wrong"}; 74 | try { 75 | parser.parseArgument(args); 76 | } catch (CmdLineException e) { 77 | assertUsageContains("Usage does not contain -nu option", "-nu"); 78 | } 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/StopOptionTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import org.kohsuke.args4j.spi.StopOptionHandler; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Tests {@link StopOptionHandler}. 9 | * 10 | * @author Kohsuke Kawaguchi 11 | */ 12 | public class StopOptionTest extends Args4JTestBase { 13 | 14 | @Argument 15 | @Option(name="--",handler= StopOptionHandler.class) 16 | List args; 17 | 18 | @Option(name="-n") 19 | int n; 20 | 21 | @Override 22 | public StopOptionTest getTestObject() { 23 | return this; 24 | } 25 | 26 | public void test1() throws Exception { 27 | parser.parseArgument("-n","5","abc","def"); 28 | 29 | assertEquals(5,n); 30 | assertEquals(2,args.size()); 31 | assertEquals("abc",args.get(0)); 32 | assertEquals("def",args.get(1)); 33 | } 34 | 35 | public void test2() throws Exception { 36 | parser.parseArgument("--","-n","5","abc","def"); 37 | 38 | assertEquals(0,n); 39 | assertEquals(4,args.size()); 40 | assertEquals("-n",args.get(0)); 41 | assertEquals("5",args.get(1)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/StringWithMetavar.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | public class StringWithMetavar { 4 | @Option(name="-str",usage="set a string",metaVar="METAVAR") 5 | public String str; 6 | } 7 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/StringWithMetavarTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import java.io.StringWriter; 4 | 5 | public class StringWithMetavarTest extends Args4JTestBase { 6 | @Override 7 | public StringWithMetavar getTestObject() { 8 | return new StringWithMetavar(); 9 | } 10 | 11 | public void testSettingUsage() { 12 | args = new String[]{"-wrong-usage"}; 13 | try { 14 | parser.parseArgument(args); 15 | fail("Doesn't detect wrong parameters."); 16 | } catch (CmdLineException e) { 17 | String expectedError = "\"-wrong-usage\" is not a valid option"; 18 | String expectedUsage = " -str METAVAR : set a string"; 19 | String expectedSingleLineUsage = " [-str METAVAR]"; 20 | String[] usageLines = getUsageMessage(); 21 | String singleLineUsage = getSingleLineUsage(); 22 | assertUsageLength(1); 23 | assertErrorMessagePrefix(expectedError, e); 24 | assertEquals("Got wrong usage message", expectedUsage, usageLines[0]); 25 | assertEquals("Got wrong usage summary", expectedSingleLineUsage, singleLineUsage); 26 | } 27 | } 28 | 29 | public void testMissingParameter() { 30 | args = new String[]{"-str"}; 31 | try { 32 | parser.parseArgument(args); 33 | fail("Should miss one parameter."); 34 | } catch (CmdLineException e) { 35 | String expectedError = "Option \"-str\" takes an operand"; 36 | String expectedUsage = " -str METAVAR : set a string"; 37 | String[] usageLines = getUsageMessage(); 38 | assertUsageLength(1); 39 | assertErrorMessagePrefix(expectedError, e); 40 | assertEquals("Got wrong usage message", expectedUsage, usageLines[0]); 41 | } 42 | } 43 | 44 | private String getSingleLineUsage() { 45 | StringWriter buffer = new StringWriter(); 46 | parser.printSingleLineUsage(buffer, null); 47 | buffer.flush(); 48 | return buffer.toString(); 49 | } 50 | 51 | public void testEqualsSeparator() { 52 | args = new String[]{"-wrong-usage"}; 53 | parser.getProperties().withOptionValueDelimiter("="); 54 | try { 55 | parser.parseArgument(args); 56 | fail("Doesn't detect wrong parameters."); 57 | } catch (CmdLineException e) { 58 | String expectedUsage = " -str=METAVAR : set a string"; 59 | String expectedSingleLineUsage = " [-str=METAVAR]"; 60 | String[] usageLines = getUsageMessage(); 61 | String singleLineUsage = getSingleLineUsage(); 62 | assertUsageLength(1); 63 | assertEquals("Got wrong usage message", expectedUsage, usageLines[0]); 64 | assertEquals("Got wrong usage summary", expectedSingleLineUsage, singleLineUsage); 65 | } 66 | } 67 | 68 | public void testExplicitNoEqualsSeparator() { 69 | args = new String[]{"-wrong-usage"}; 70 | parser.getProperties().withOptionValueDelimiter(" "); 71 | try { 72 | parser.parseArgument(args); 73 | fail("Doesn't detect wrong parameters."); 74 | } catch (CmdLineException e) { 75 | String expectedUsage = " -str METAVAR : set a string"; 76 | String expectedSingleLineUsage = " [-str METAVAR]"; 77 | String[] usageLines = getUsageMessage(); 78 | String singleLineUsage = getSingleLineUsage(); 79 | assertUsageLength(1); 80 | assertEquals("Got wrong usage message", expectedUsage, usageLines[0]); 81 | assertEquals("Got wrong usage summary", expectedSingleLineUsage, singleLineUsage); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/SubCommandTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j; 2 | 3 | import org.kohsuke.args4j.spi.SubCommand; 4 | import org.kohsuke.args4j.spi.SubCommandHandler; 5 | import org.kohsuke.args4j.spi.SubCommands; 6 | 7 | /** 8 | * @author Kohsuke Kawaguchi 9 | */ 10 | public class SubCommandTest extends Args4JTestBase { 11 | 12 | public static class Foo { 13 | @Argument(handler= SubCommandHandler.class) 14 | @SubCommands({ 15 | @SubCommand(name="cmd1",impl=Cmd1.class), 16 | @SubCommand(name="cmd2",impl=Cmd2.class) 17 | }) 18 | SubCmd value; 19 | 20 | @Option(name="-r") 21 | String globalOption1; 22 | } 23 | 24 | public static abstract class SubCmd {} 25 | 26 | public static class Cmd1 extends SubCmd { 27 | @Option(name="-r") 28 | String localOption; 29 | } 30 | public static class Cmd2 extends SubCmd {} 31 | 32 | 33 | 34 | @Override 35 | public Foo getTestObject() { 36 | return new Foo(); 37 | } 38 | 39 | public void testCmd1() throws Exception { 40 | parser.parseArgument("-r","a","cmd1","-r","b"); 41 | assertEquals("a",testObject.globalOption1); 42 | assertEquals("b",((Cmd1)testObject.value).localOption); 43 | } 44 | 45 | public void testCmd2() throws Exception { 46 | parser.parseArgument("cmd2"); 47 | assertTrue(testObject.value instanceof Cmd2); 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/spi/InetAddressOptionHandlerTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.net.InetAddress; 4 | 5 | import junit.framework.TestCase; 6 | 7 | import org.kohsuke.args4j.CmdLineException; 8 | 9 | public class InetAddressOptionHandlerTest extends TestCase { 10 | 11 | private InetAddressOptionHandler handler; 12 | 13 | @Override 14 | public void setUp() { 15 | handler = new InetAddressOptionHandler(null, null, null); 16 | } 17 | 18 | public void testParseSuccess() throws Exception { 19 | InetAddress expectedIp = InetAddress.getByAddress(new byte[] { (byte) 1, 20 | (byte) 2, (byte) 3, (byte) 4 }); 21 | InetAddress ip = handler.parse("1.2.3.4"); 22 | 23 | assertEquals(expectedIp, ip); 24 | } 25 | 26 | public void testParseFailure() throws Exception { 27 | try { 28 | handler.parse("bogus.ip.address.nosuch."); 29 | } catch (CmdLineException e) { 30 | assertEquals("\"bogus.ip.address.nosuch.\" must be an IP address", e.getMessage()); 31 | return; 32 | } 33 | fail("We should not reach here"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/spi/MacAddressOptionHandlerTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.util.Arrays; 4 | import java.util.Locale; 5 | import static org.junit.Assert.assertEquals; 6 | import static org.junit.Assert.fail; 7 | 8 | import junit.framework.TestCase; 9 | import org.kohsuke.args4j.CmdLineException; 10 | 11 | import org.kohsuke.args4j.CmdLineParser; 12 | import org.kohsuke.args4j.Option; 13 | 14 | /** 15 | * Simple test for the {@link MacAddressOptionHandler}. 16 | * 17 | * @author Stephan Fuhrmann 18 | */ 19 | public class MacAddressOptionHandlerTest extends TestCase { 20 | 21 | private class TestBean { 22 | 23 | @Option(name = "-mac", handler = MacAddressOptionHandler.class) 24 | private byte addr[]; 25 | } 26 | 27 | public void testParseSuccessWithoutSixPartFormatUnsigned() throws Exception { 28 | TestBean bean = new TestBean(); 29 | CmdLineParser parser = new CmdLineParser(bean); 30 | parser.parseArgument("-mac", "00:11:22:33:44:55"); 31 | 32 | assertEquals(Arrays.toString(new byte[]{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}), Arrays.toString(bean.addr)); 33 | } 34 | 35 | public void testParseSuccessWithSixPartFormatSign() throws Exception { 36 | TestBean bean = new TestBean(); 37 | CmdLineParser parser = new CmdLineParser(bean); 38 | parser.parseArgument("-mac", "80:f1:72:33:c4:d5"); 39 | 40 | assertEquals(Arrays.toString(new byte[]{(byte)0x80, (byte)0xf1, 0x72, 0x33, (byte)0xc4, (byte)0xd5}), Arrays.toString(bean.addr)); 41 | } 42 | 43 | public void testParseSuccessWithContinuousFormat() throws Exception { 44 | TestBean bean = new TestBean(); 45 | CmdLineParser parser = new CmdLineParser(bean); 46 | parser.parseArgument("-mac", "80f17233c4d5"); 47 | 48 | assertEquals(Arrays.toString(new byte[]{(byte)0x80, (byte)0xf1, 0x72, 0x33, (byte)0xc4, (byte)0xd5}), Arrays.toString(bean.addr)); 49 | } 50 | 51 | public void testParseSuccessWithSpacedFormat() throws Exception { 52 | TestBean bean = new TestBean(); 53 | CmdLineParser parser = new CmdLineParser(bean); 54 | parser.parseArgument("-mac", "80 f1 72 33 c4 d5"); 55 | 56 | assertEquals(Arrays.toString(new byte[]{(byte)0x80, (byte)0xf1, 0x72, 0x33, (byte)0xc4, (byte)0xd5}), Arrays.toString(bean.addr)); 57 | } 58 | 59 | public void testParseSuccessWithMinusFormat() throws Exception { 60 | TestBean bean = new TestBean(); 61 | CmdLineParser parser = new CmdLineParser(bean); 62 | parser.parseArgument("-mac", "80-f1-72-33-c4-d5"); 63 | 64 | assertEquals(Arrays.toString(new byte[]{(byte)0x80, (byte)0xf1, 0x72, 0x33, (byte)0xc4, (byte)0xd5}), Arrays.toString(bean.addr)); 65 | } 66 | 67 | public void testParseFail() throws Exception { 68 | 69 | Locale old = Locale.getDefault(); 70 | Locale.setDefault(Locale.ENGLISH); 71 | TestBean bean = new TestBean(); 72 | CmdLineParser parser = new CmdLineParser(bean); 73 | try { 74 | parser.parseArgument("-mac", "00:11:22:33:44:55:ff"); 75 | fail("Expecting exception"); 76 | } catch (CmdLineException e) { 77 | assertEquals("\"00:11:22:33:44:55:ff\" must be an MAC address", e.getMessage()); 78 | } finally { 79 | Locale.setDefault(old); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/spi/PathOptionHandlerTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import junit.framework.TestCase; 4 | import org.kohsuke.args4j.CmdLineException; 5 | 6 | import java.nio.file.Path; 7 | import java.nio.file.Paths; 8 | 9 | /** 10 | * Created with IntelliJ IDEA. 11 | * User: kmahoney 12 | * Date: 6/7/13 13 | * Time: 6:09 AM 14 | */ 15 | 16 | public class PathOptionHandlerTest extends TestCase { 17 | static final String TEST_1 = "/path/test"; 18 | static final String TEST_2 = "bad/path/\0"; 19 | 20 | private PathOptionHandler handler; 21 | 22 | @Override 23 | public void setUp() { 24 | handler = new PathOptionHandler(null, null, null); 25 | } 26 | 27 | public void testParseSuccess() throws Exception { 28 | Path expectedPath = Paths.get(TEST_1); 29 | Path path = handler.parse(TEST_1); 30 | 31 | assertEquals(expectedPath, path); 32 | } 33 | 34 | public void testParseFailure() throws Exception { 35 | try { 36 | handler.parse(TEST_2); 37 | } catch (CmdLineException e) { 38 | return; 39 | } 40 | fail("Invalid Path Should Have Thrown Exception"); 41 | } 42 | 43 | public void testNullParseFailure() throws Exception { 44 | try { 45 | handler.parse(null); 46 | } catch (CmdLineException e) { 47 | return; 48 | } 49 | fail("Null Path Should Have Thrown Exception"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/spi/PatternOptionHandlerTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.util.Locale; 4 | import java.util.regex.Pattern; 5 | 6 | import junit.framework.TestCase; 7 | import org.kohsuke.args4j.CmdLineException; 8 | 9 | import org.kohsuke.args4j.CmdLineParser; 10 | import org.kohsuke.args4j.Option; 11 | 12 | /** Simple test for the {@link PatternOptionHandler}. 13 | * @author Stephan Fuhrmann 14 | */ 15 | public class PatternOptionHandlerTest extends TestCase { 16 | 17 | private class TestBean { 18 | @Option(name="-pattern") 19 | private Pattern pattern; 20 | } 21 | 22 | public void testParseSuccess() throws Exception { 23 | 24 | TestBean bean = new TestBean(); 25 | CmdLineParser parser = new CmdLineParser(bean); 26 | parser.parseArgument("-pattern", ".*"); 27 | 28 | assertEquals(Pattern.compile(".*").toString(), bean.pattern.toString()); 29 | } 30 | 31 | 32 | public void testParseFail() throws Exception { 33 | 34 | Locale old = Locale.getDefault(); 35 | Locale.setDefault(Locale.ENGLISH); 36 | TestBean bean = new TestBean(); 37 | CmdLineParser parser = new CmdLineParser(bean); 38 | try { 39 | parser.parseArgument("-pattern", "*"); 40 | fail("Expecting exception"); 41 | } 42 | catch (CmdLineException e) { 43 | assertEquals("\"-pattern\" must be a regular expression", e.getMessage()); 44 | } 45 | finally { 46 | Locale.setDefault(old); 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/spi/SettersTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | import org.junit.Assert; 6 | import junit.framework.TestCase; 7 | 8 | /** 9 | * @author dantuch 10 | */ 11 | @SuppressWarnings({"static-method", "unused"}) 12 | public class SettersTest extends TestCase { 13 | 14 | private final String finalField = "thisValueMakesItFinal"; 15 | private String mutableField; 16 | 17 | public void testSNotCreateSetterForFinalField() throws Exception { 18 | // given 19 | Field f = SettersTest.class.getDeclaredField("finalField"); 20 | // when 21 | try { 22 | Setters.create(f, null); 23 | fail(); 24 | } catch (IllegalStateException e) { 25 | // expected 26 | } 27 | } 28 | 29 | public void testSCreateSetterForMutableField() throws Exception { 30 | // given 31 | Field f = SettersTest.class.getDeclaredField("mutableField"); 32 | // when 33 | @SuppressWarnings("rawtypes") 34 | Setter created = Setters.create(f, null); 35 | // then 36 | Assert.assertNotNull(created); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /args4j/test/org/kohsuke/args4j/spi/StringArrayOptionHandlerTest.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.args4j.spi; 2 | 3 | import java.util.Arrays; 4 | import org.junit.Assert; 5 | import junit.framework.TestCase; 6 | import org.kohsuke.args4j.Argument; 7 | 8 | import org.kohsuke.args4j.CmdLineParser; 9 | import org.kohsuke.args4j.Option; 10 | 11 | /** 12 | * Test for {@link StringArrayOptionHandler}. 13 | * 14 | * This test is for a possible design problem in the old version of {@link ArrayFieldSetter} 15 | * that I discovered today. The fix could break existing code, I think it will need 16 | * some discussion. 17 | * 18 | * @author Stephan Fuhrmann 19 | */ 20 | public class StringArrayOptionHandlerTest extends TestCase { 21 | 22 | private static class TestBean { 23 | 24 | @Option(name = "-opt") 25 | private String stringArray[] = new String[]{"def1", "def2", "def3"}; 26 | 27 | @Argument 28 | private String rest[]; 29 | } 30 | 31 | public void testParseWithDefault() throws Exception { 32 | 33 | TestBean bean = new TestBean(); 34 | 35 | CmdLineParser parser = new CmdLineParser(bean); 36 | parser.parseArgument("test1", "test2", "test3"); 37 | 38 | Assert.assertEquals(Arrays.asList("def1", "def2", "def3"), Arrays.asList(bean.stringArray)); 39 | Assert.assertEquals(Arrays.asList("test1", "test2", "test3"), Arrays.asList(bean.rest)); 40 | } 41 | 42 | public void testParseWithOneParam() throws Exception { 43 | 44 | TestBean bean = new TestBean(); 45 | 46 | CmdLineParser parser = new CmdLineParser(bean); 47 | parser.parseArgument("test1", "test2", "-opt", "test3"); 48 | 49 | Assert.assertEquals(Arrays.asList("test3"), Arrays.asList(bean.stringArray)); 50 | Assert.assertEquals(Arrays.asList("test1", "test2"), Arrays.asList(bean.rest)); 51 | } 52 | 53 | public void testParseWithTwoParams() throws Exception { 54 | 55 | TestBean bean = new TestBean(); 56 | 57 | CmdLineParser parser = new CmdLineParser(bean); 58 | parser.parseArgument("test1", "test2", "-opt", "test3", "-opt", "test4"); 59 | 60 | Assert.assertEquals(Arrays.asList("test3", "test4"), Arrays.asList(bean.stringArray)); 61 | Assert.assertEquals(Arrays.asList("test1", "test2"), Arrays.asList(bean.rest)); 62 | } 63 | 64 | public void testParseWithNoDefault() throws Exception { 65 | 66 | TestBean bean = new TestBean(); 67 | bean.stringArray = null; // remove 68 | 69 | CmdLineParser parser = new CmdLineParser(bean); 70 | parser.parseArgument("test1", "test2", "-opt", "test3", "-opt", "test4"); 71 | 72 | Assert.assertEquals(Arrays.asList("test3", "test4"), Arrays.asList(bean.stringArray)); 73 | Assert.assertEquals(Arrays.asList("test1", "test2"), Arrays.asList(bean.rest)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -xe 2 | # run this after manually updating project.xml and xdocs/changes.xml 3 | # to point to the next release version 4 | mvn -B release:prepare release:perform 5 | -------------------------------------------------------------------------------- /src/site/apt/apt.apt: -------------------------------------------------------------------------------- 1 | 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 your build process to generate your documentation, so it's always in sync with your code. 2 | 3 | To do so, download {{{http://maven.jenkins-ci.org/content/repositories/releases/args4j/args4j-tools/}args4j-tools}} and run it as follows: 4 | 5 | ---------------------------------------- 6 | $ java -jar args4j-tools.jar path/to/my/OptionBean.java 7 | ---------------------------------------- 8 | 9 | To see all the options, run it without any parameters. 10 | -------------------------------------------------------------------------------- /src/site/apt/implementOptionhandler.apt: -------------------------------------------------------------------------------- 1 | args4j comes with a built-in support for parsing options into several Java datatypes (such as <<>>, <<>>, and <<>>). You can extend this further by writing your own {{{apidocs/org/kohsuke/args4j/spi/OptionHandler.html}OptionHandler}} implementation, then registering it to the <<>> class. 2 | 3 | In fact, most of the built-in support is implemented using this mechanism. The <<>> class's source code details how to do this. 4 | -------------------------------------------------------------------------------- /src/site/apt/index.apt: -------------------------------------------------------------------------------- 1 | ----- 2 | Args4j 3 | ----- 4 | ----- 5 | 6 | 7 | args4j is a small Java class library that makes it easy to parse command line options/arguments in your CUI application. 8 | 9 | Why should I use it? 10 | 11 | See {{{http://weblogs.java.net/blog/kohsuke/archive/2005/05/parsing_command.html}my quick intro}}. 12 | 13 | * It makes command line parsing very easy by using annotations 14 | 15 | * Generate usage text very easily 16 | 17 | * Generate HTML/XML documentation listing all options 18 | 19 | * Full localization support 20 | 21 | * Designed to parse <<>> like options, as opposed to GNU-style (where <<>> is considered to have two options <<>> and <<>>). 22 | 23 | * Licensed under {{{http://www.opensource.org/licenses/mit-license.php}the MIT license}}. 24 | 25 | [] 26 | 27 | How can I use it? 28 | 29 | [[1]] Check {{{https://github.com/kohsuke/args4j/blob/master/args4j/examples/SampleMain.java}the sample}}. This is how your code will look like. 30 | 31 | [[1]] {{{http://maven.glassfish.org/content/groups/public/args4j/}Download}} the distribution or include the library from the Maven Repository at java.net. 32 | 33 | [[1]] Write your code. 34 | 35 | [] 36 | 37 | More Resources 38 | 39 | [[1]] {{{./sample.html}A small tutorial}} for the use of the Starter and Args4J 40 | 41 | [[1]] {{{./args4j/apidocs/}javadoc}} 42 | 43 | [[1]] {{{./apt.html}How to generate a documentation for your CLI}} 44 | 45 | [[1]] {{{./implementOptionhandler.html}Extend args4j to handle other Java types}} 46 | 47 | [[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}} 48 | 49 | [[1]] {{{http://hikage.developpez.com/java/articles/api/cli-vs-args4j/}A comparison between Commons CLI and Args4j}} in French 50 | 51 | [] 52 | -------------------------------------------------------------------------------- /src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.kohsuke 5 | maven-skin 6 | 1.2 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ${reports} 18 | 19 | 20 | 21 | --------------------------------------------------------------------------------