diff --git a/.gitignore b/.gitignore index 08d3e3d..da72d7c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /classes /doc -/lib/jargs*.jar \ No newline at end of file +/lib/jargs*.jar +*~ diff --git a/LICENCE b/LICENCE index 509c1b7..f79cc31 100644 --- a/LICENCE +++ b/LICENCE @@ -2,6 +2,7 @@ Copyright (c) 2001-2003 Steve Purcell. Copyright (c) 2002 Vidar Holen. Copyright (c) 2002 Michal Ceresna. Copyright (c) 2005 Ewan Mellor. +Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). All rights reserved. diff --git a/README.md b/README.md index 12b75a6..0f8175a 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ JArgs command-line argument parsing library - Copyright (c) 2002 Vidar Holen. - Copyright (c) 2002 Michal Ceresna. - Copyright (c) 2005 Ewan Mellor. +- Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). All rights reserved. @@ -21,7 +22,7 @@ in parentheses. Any version equal to or later than this should work. Apache Ant (1.4.1), by The Apache Software Foundation, from http://ant.apache.org/. Ant is used to build JArgs, and to run its tests. -JUnit (3.7), by Eric Gamma, et al, from http://sourceforge.net/projects/junit. +JUnit (3.7 & 4.3.1), by Eric Gamma, et al, from http://www.junit.org/. JUnit is used to run the unit tests, and is not needed to run the library itself. @@ -45,8 +46,9 @@ Documentation ------------- The main documentation is the detailed worked example in -`src/jargs/examples/gnu/OptionTest.java`, plus the generated API documentation -in `doc/api/`. +`src/jargs/examples/gnu/OptionTest.java` (old Java 1.1 API), +`src/jargs/examples/gnu/OptionTest5.java` (new Java 1.5 API), plus the generated +API documentation in `doc/api/`. Package contents diff --git a/build.xml b/build.xml index 3697ec9..7631198 100644 --- a/build.xml +++ b/build.xml @@ -3,15 +3,15 @@ - - + + - + - + + @@ -30,7 +30,7 @@ Purcell. Copyright &copy; 2002 Vidar Holen. Copyright &copy; 2002 Micha - + @@ -62,9 +62,13 @@ Purcell. Copyright &copy; 2002 Vidar Holen. Copyright &copy; 2002 Micha + classpath="${build.classes}:${junit3.jar}:${java.class.path}"> + + + @@ -98,7 +102,7 @@ Purcell. Copyright &copy; 2002 Vidar Holen. Copyright &copy; 2002 Micha footer="${javadoc.header}" bottom="${javadoc.bottom}"> - + diff --git a/src/jargs/examples/gnu/AutoHelpParser.java b/src/jargs/examples/gnu/AutoHelpParser.java index f42ec5f..f008450 100644 --- a/src/jargs/examples/gnu/AutoHelpParser.java +++ b/src/jargs/examples/gnu/AutoHelpParser.java @@ -1,3 +1,35 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + package jargs.examples.gnu; import jargs.gnu.CmdLineParser; diff --git a/src/jargs/examples/gnu/AutoHelpParser5.java b/src/jargs/examples/gnu/AutoHelpParser5.java new file mode 100644 index 0000000..1b85c5e --- /dev/null +++ b/src/jargs/examples/gnu/AutoHelpParser5.java @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package jargs.examples.gnu; + +import jargs.gnu.CmdLineParser; + +import java.util.ArrayList; +import java.util.List; + +/** + * This example shows how to dynamically create basic output for a --help option. + */ +public class AutoHelpParser5 extends CmdLineParser { + + List optionHelpStrings = new ArrayList(); + + public Option addHelp(Option option, String helpString) { + optionHelpStrings.add(" -" + option.shortForm() + "/--" + option.longForm() + ": " + helpString); + return option; + } + + public void printUsage() { + System.err.println("usage: prog [options]"); + for (String help : optionHelpStrings) { + System.err.println(help); + } + } + + public static void main(String[] args) { + AutoHelpParser5 parser = new AutoHelpParser5(); + CmdLineParser.Option verbose = parser.addHelp( + parser.addBooleanOption('v', "verbose"), + "Print extra information"); + CmdLineParser.Option size = parser.addHelp( + parser.addIntegerOption('s', "size"), + "The extent of the thing"); + CmdLineParser.Option name = parser.addHelp( + parser.addStringOption('n', "name"), + "Name given to the widget"); + CmdLineParser.Option fraction = parser.addHelp( + parser.addDoubleOption('f', "fraction"), + "What percentage should be discarded"); + CmdLineParser.Option help = parser.addHelp( + parser.addBooleanOption('h', "help"), + "Show this help message"); + + try { + parser.parse(args); + } catch (CmdLineParser.OptionException e) { + System.err.println(e.getMessage()); + parser.printUsage(); + System.exit(2); + } + + if (Boolean.TRUE.equals(parser.getOptionValue(help))) { + parser.printUsage(); + System.exit(0); + } + + // Extract the values entered for the various options -- if the + // options were not specified, the corresponding values will be + // null. + Boolean verboseValue = parser.getOptionValue(verbose); + Integer sizeValue = parser.getOptionValue(size); + String nameValue = parser.getOptionValue(name); + Double fractionValue = parser.getOptionValue(fraction); + + // For testing purposes, we just print out the option values + System.out.println("verbose: " + verboseValue); + System.out.println("size: " + sizeValue); + System.out.println("name: " + nameValue); + System.out.println("fraction: " + fractionValue); + + // Extract the trailing command-line arguments ('a_nother') in the + // usage string above. + String[] otherArgs = parser.getRemainingArgs(); + System.out.println("remaining args: "); + for (int i = 0; i < otherArgs.length; ++i) { + System.out.println(otherArgs[i]); + } + + // In a real program, one would pass the option values and other + // arguments to a function that does something more useful. + + System.exit(0); + } +} diff --git a/src/jargs/examples/gnu/CustomOptionTest.java b/src/jargs/examples/gnu/CustomOptionTest.java index 2a1c45f..5b6bd8a 100644 --- a/src/jargs/examples/gnu/CustomOptionTest.java +++ b/src/jargs/examples/gnu/CustomOptionTest.java @@ -1,3 +1,35 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + package jargs.examples.gnu; import jargs.gnu.CmdLineParser; diff --git a/src/jargs/examples/gnu/CustomOptionTest5.java b/src/jargs/examples/gnu/CustomOptionTest5.java new file mode 100644 index 0000000..a088d49 --- /dev/null +++ b/src/jargs/examples/gnu/CustomOptionTest5.java @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package jargs.examples.gnu; + +import jargs.gnu.CmdLineParser; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Locale; +import java.util.Date; + +public class CustomOptionTest5 { + + private static void printUsage() { + System.err.println("usage: prog [{-d,--date} date]"); + } + + /** + * A custom type of command line option corresponding to a short + * date value, e.g. . + */ + public static class ShortDateOption extends CmdLineParser.Option { + + public ShortDateOption(char shortForm, String longForm) { + super(shortForm, longForm, true); + } + + @Override + protected Date parseValue(String arg, Locale locale) + throws CmdLineParser.IllegalOptionValueException { + try { + DateFormat dateFormat = + DateFormat.getDateInstance(DateFormat.SHORT, locale); + return dateFormat.parse(arg); + } catch (ParseException e) { + throw new CmdLineParser.IllegalOptionValueException(this, arg); + } + } + } + + public static void main(String[] args) { + CmdLineParser parser = new CmdLineParser(); + CmdLineParser.Option date = + parser.addOption(new ShortDateOption('d', "date")); + + try { + parser.parse(args); + } catch (CmdLineParser.OptionException e) { + System.err.println(e.getMessage()); + printUsage(); + System.exit(2); + } + + // Extract the values entered for the various options -- if the + // options were not specified, the corresponding values will be + // null. + Date dateValue = parser.getOptionValue(date); + + // For testing purposes, we just print out the option values + System.out.println("date: " + dateValue); + + // Extract the trailing command-line arguments ('a_number') in the + // usage string above. + String[] otherArgs = parser.getRemainingArgs(); + System.out.println("remaining args: "); + for (int i = 0; i < otherArgs.length; ++i) { + System.out.println(otherArgs[i]); + } + + // In a real program, one would pass the option values and other + // arguments to a function that does something more useful. + + System.exit(0); + } +} diff --git a/src/jargs/examples/gnu/OptionParserSubclassTest.java b/src/jargs/examples/gnu/OptionParserSubclassTest.java index 551abf1..9b10dd1 100644 --- a/src/jargs/examples/gnu/OptionParserSubclassTest.java +++ b/src/jargs/examples/gnu/OptionParserSubclassTest.java @@ -1,3 +1,35 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + package jargs.examples.gnu; import jargs.gnu.CmdLineParser; diff --git a/src/jargs/examples/gnu/OptionParserSubclassTest5.java b/src/jargs/examples/gnu/OptionParserSubclassTest5.java new file mode 100644 index 0000000..4d5c543 --- /dev/null +++ b/src/jargs/examples/gnu/OptionParserSubclassTest5.java @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package jargs.examples.gnu; + +import jargs.gnu.CmdLineParser; + +public class OptionParserSubclassTest5 { + + private static class MyOptionsParser extends CmdLineParser { + + public static final Option VERBOSE = new CmdLineParser.Option.BooleanOption('v', "verbose"); + public static final Option SIZE = new CmdLineParser.Option.IntegerOption('s', "size"); + public static final Option NAME = new CmdLineParser.Option.StringOption('n', "name"); + public static final Option FRACTION = new CmdLineParser.Option.DoubleOption('f', "fraction"); + + public MyOptionsParser() { + super(); + addOption(VERBOSE); + addOption(SIZE); + addOption(NAME); + addOption(FRACTION); + } + } + + private static void printUsage() { + System.err.println("usage: prog [{-v,--verbose}] [{-n,--name} a_name]" + + "[{-s,--size} a_number] [{-f,--fraction} a_float]"); + } + + public static void main(String[] args) { + MyOptionsParser myOptions = new MyOptionsParser(); + + try { + myOptions.parse(args); + } catch (CmdLineParser.UnknownOptionException e) { + System.err.println(e.getMessage()); + printUsage(); + System.exit(2); + } catch (CmdLineParser.IllegalOptionValueException e) { + System.err.println(e.getMessage()); + printUsage(); + System.exit(2); + } + + CmdLineParser.Option[] allOptions = new CmdLineParser.Option[]{ + MyOptionsParser.VERBOSE, + MyOptionsParser.NAME, + MyOptionsParser.SIZE, + MyOptionsParser.FRACTION + }; + + for (int j = 0; j < allOptions.length; ++j) { + System.out.println(allOptions[j].longForm() + ": " + + myOptions.getOptionValue(allOptions[j])); + } + + String[] otherArgs = myOptions.getRemainingArgs(); + System.out.println("remaining args: "); + for (int i = 0; i < otherArgs.length; ++i) { + System.out.println(otherArgs[i]); + } + System.exit(0); + } +} diff --git a/src/jargs/examples/gnu/OptionTest.java b/src/jargs/examples/gnu/OptionTest.java index f09f6be..c84bafa 100644 --- a/src/jargs/examples/gnu/OptionTest.java +++ b/src/jargs/examples/gnu/OptionTest.java @@ -1,10 +1,41 @@ -package jargs.examples.gnu; +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ -import java.util.Enumeration; -import java.util.Vector; +package jargs.examples.gnu; import jargs.gnu.CmdLineParser; +import java.util.Collection; +import java.util.Iterator; public class OptionTest { @@ -91,7 +122,7 @@ public static void main( String[] args ) { // once. In this case, you may get all the values specified by the // user, as a Vector: - Vector fractionValues = parser.getOptionValues(fraction); + Collection fractionValues = parser.getOptionValues(fraction); // Alternatively, you may make the loop explicit: @@ -124,9 +155,9 @@ public static void main( String[] args ) { System.out.println("verbosity: " + verbosity); - Enumeration e = fractionValues.elements(); - while (e.hasMoreElements()) { - System.out.println("fraction: " + (Double)e.nextElement()); + Iterator it = fractionValues.iterator(); + while (it.hasNext()) { + System.out.println("fraction: " + (Double)it.next()); } System.out.println("remaining args: "); diff --git a/src/jargs/examples/gnu/OptionTest5.java b/src/jargs/examples/gnu/OptionTest5.java new file mode 100644 index 0000000..b18599d --- /dev/null +++ b/src/jargs/examples/gnu/OptionTest5.java @@ -0,0 +1,167 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package jargs.examples.gnu; + +import jargs.gnu.CmdLineParser; +import jargs.gnu.CmdLineParser.Option; + +import java.util.Collection; +import java.util.Iterator; + +public class OptionTest5 { + + private static void printUsage() { + System.err.println( + "Usage: OptionTest [-d,--debug] [{-v,--verbose}] [{--alt}] [{--name} a_name]\n" + + " [{-s,--size} a_number] [{-f,--fraction} a_float] [a_nother]"); + } + + public static void main(String[] args) { + + // First, you must create a CmdLineParser, and add to it the + // appropriate Options. + + // To start with, we add the Options -d, -v, -s, and -f, with aliases + // --debug, --verbose, --size, and --fraction respectively. + + // The -d and -v options have no associated value -- they are either + // present, or they are not. The -s and -f options take integer and + // double-precision floating-point values respectively. + + CmdLineParser parser = new CmdLineParser(); + Option debug = parser.addBooleanOption('d', "debug"); + Option verbose = parser.addBooleanOption('v', "verbose"); + Option size = parser.addIntegerOption('s', "size"); + Option fraction = parser.addDoubleOption('f', "fraction"); + + // Options may have just a long form with no corresponding short form. + // Here, we add --alt and --name options. + + Option alt = parser.addBooleanOption("alt"); + Option name = parser.addStringOption('n', "name"); + + + // Next, you must parse the user-provided command line arguments, and + // catch any errors therein. + + // Options may appear on the command line in any order, and may even + // appear after some or all of the non-option arguments. + + // If the user needs to specify non-option arguments that start with a + // minus, then they may indicate the end of the parsable options with + // -- , like this: + + // prog -f 20 -- -10 -fred + + // The -f 20 will be parsed as the fraction option, with the value 20. + // The -10 and -fred arguments will be regarded as non-option + // arguments, and passed through getRemainingArgs as unparsed Strings. + + // Short boolean options may be specified separately (-d -v) or + // together (-dv). + + // Options with values may be given on the command line as -f 1.0 or + // --fraction=1.0. + + try { + parser.parse(args); + } catch (CmdLineParser.OptionException e) { + System.err.println(e.getMessage()); + printUsage(); + System.exit(2); + } + + + // For options that may be specified only zero or one time, the value + // of that option may be extracted as shown below. If the options + // were not specified, the corresponding values will be null. + + Boolean debugValue = parser.getOptionValue(debug); + String nameValue = parser.getOptionValue(name); + + // Alternatively, you may specify a default value. This will be + // returned (instead of null) when the command line argument is + // missing. + + Boolean altValue = parser.getOptionValue(alt, Boolean.FALSE); + Integer sizeValue = parser.getOptionValue(size, new Integer(42)); + + // If your application requires it, options may be specified more than + // once. In this case, you may get all the values specified by the + // user, as a Vector: + + Collection fractionValues = parser.getOptionValues(fraction); + + // Alternatively, you may make the loop explicit: + + int verbosity = 0; + while (true) { + Boolean verboseValue = parser.getOptionValue(verbose); + + if (verboseValue == null) { + break; + } else { + verbosity++; + } + } + + // The remaining command-line arguments -- those that do not start + // with a minus sign -- can be captured like this: + + String[] otherArgs = parser.getRemainingArgs(); + + + // For testing purposes, we just print out the option values and + // remaining command-line arguments. In a real program, of course, + // one would pass them to a function that does something more useful. + + System.out.println("debug: " + debugValue); + System.out.println("alt: " + altValue); + System.out.println("size: " + sizeValue); + System.out.println("name: " + nameValue); + + System.out.println("verbosity: " + verbosity); + + Iterator it = fractionValues.iterator(); + while (it.hasNext()) { + System.out.println("fraction: " + it.next()); + } + + System.out.println("remaining args: "); + for (int i = 0; i < otherArgs.length; ++i) { + System.out.println(otherArgs[i]); + } + + System.exit(0); + } +} diff --git a/src/jargs/gnu/CmdLineParser.java b/src/jargs/gnu/CmdLineParser.java index 12d1836..f858d0e 100644 --- a/src/jargs/gnu/CmdLineParser.java +++ b/src/jargs/gnu/CmdLineParser.java @@ -1,10 +1,46 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + package jargs.gnu; import java.text.NumberFormat; import java.text.ParseException; -import java.util.Hashtable; -import java.util.Vector; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; import java.util.Locale; +import java.util.Map; +import java.util.Vector; /** * Largely GNU-compatible command-line options parser. Has short (-v) and @@ -13,6 +49,8 @@ * can be explicitly terminated by the argument '--'. * * @author Steve Purcell + * @author penSec.IT UG (haftungsbeschränkt) + * * @version $Revision$ * @see jargs.examples.gnu.OptionTest */ @@ -44,8 +82,11 @@ public static class UnknownOptionException extends OptionException { /** * @return the name of the option that was unknown (e.g. "-u") */ - public String getOptionName() { return this.optionName; } - private String optionName = null; + public String getOptionName() { + return this.optionName; + } + + private final String optionName; } /** @@ -63,7 +104,9 @@ public static class UnknownSuboptionException super(option, "Illegal option: '"+suboption+"' in '"+option+"'"); this.suboption=suboption; } - public char getSuboption() { return suboption; } + public char getSuboption() { + return suboption; + } } /** @@ -85,7 +128,9 @@ public static class NotFlagException extends UnknownOptionException { /** * @return the first character which wasn't a boolean (e.g 'c') */ - public char getOptionChar() { return notflag; } + public char getOptionChar() { + return notflag; + } } /** @@ -93,9 +138,13 @@ public static class NotFlagException extends UnknownOptionException { * an option that takes a value. getMessage() returns * an error string suitable for reporting the error to the user (in * English). + * + * No generic class can ever extend java.lang.Throwable, so we + * have to return Option<?> instead of + * Option<T>. */ public static class IllegalOptionValueException extends OptionException { - public IllegalOptionValueException( Option opt, String value ) { + public IllegalOptionValueException( Option opt, String value ) { super("Illegal value '" + value + "' for option " + (opt.shortForm() != null ? "-" + opt.shortForm() + "/" : "") + "--" + opt.longForm()); @@ -106,20 +155,26 @@ public IllegalOptionValueException( Option opt, String value ) { /** * @return the name of the option whose value was illegal (e.g. "-u") */ - public Option getOption() { return this.option; } + public Option getOption() { + return this.option; + } /** * @return the illegal value */ - public String getValue() { return this.value; } - private Option option; - private String value; + public String getValue() { + return this.value; + } + private final Option option; + private final String value; } /** * Representation of a command-line option + * + * @param T Type of data configured by this option */ - public static abstract class Option { + public static abstract class Option { protected Option( String longForm, boolean wantsValue ) { this(null, longForm, wantsValue); @@ -131,32 +186,38 @@ protected Option( char shortForm, String longForm, } private Option( String shortForm, String longForm, boolean wantsValue ) { - if ( longForm == null ) + if ( longForm == null ) { throw new IllegalArgumentException("Null longForm not allowed"); + } this.shortForm = shortForm; this.longForm = longForm; this.wantsValue = wantsValue; } - public String shortForm() { return this.shortForm; } + public String shortForm() { + return this.shortForm; + } - public String longForm() { return this.longForm; } + public String longForm() { + return this.longForm; + } /** * Tells whether or not this option wants a value */ - public boolean wantsValue() { return this.wantsValue; } + public boolean wantsValue() { + return this.wantsValue; + } - public final Object getValue( String arg, Locale locale ) + public final T getValue( String arg, Locale locale ) throws IllegalOptionValueException { if ( this.wantsValue ) { if ( arg == null ) { throw new IllegalOptionValueException(this, ""); } return this.parseValue(arg, locale); - } - else { - return Boolean.TRUE; + } else { + return this.getDefaultValue(); } } @@ -164,40 +225,65 @@ public final Object getValue( String arg, Locale locale ) * Override to extract and convert an option value passed on the * command-line */ - protected Object parseValue( String arg, Locale locale ) - throws IllegalOptionValueException { + protected T parseValue(String arg, Locale locale) + throws IllegalOptionValueException { + return null; } + + /** + * Override to define default value returned by getValue if option does + * not want a value + */ + protected T getDefaultValue() { + return null; + } + + private final String shortForm; + private final String longForm; + private final boolean wantsValue; - private String shortForm = null; - private String longForm = null; - private boolean wantsValue = false; - public static class BooleanOption extends Option { + + /** + * An option that expects a boolean value + */ + public static class BooleanOption extends Option { public BooleanOption( char shortForm, String longForm ) { super(shortForm, longForm, false); } public BooleanOption( String longForm ) { super(longForm, false); } + + @Override + public Boolean parseValue(String arg, Locale lcoale) { + return Boolean.TRUE; + } + + @Override + public Boolean getDefaultValue() { + return Boolean.TRUE; + } } /** * An option that expects an integer value */ - public static class IntegerOption extends Option { + public static class IntegerOption extends Option { public IntegerOption( char shortForm, String longForm ) { super(shortForm, longForm, true); } public IntegerOption( String longForm ) { super(longForm, true); } - protected Object parseValue( String arg, Locale locale ) + + @Override + protected Integer parseValue( String arg, Locale locale ) throws IllegalOptionValueException { try { return new Integer(arg); - } - catch (NumberFormatException e) { + } catch (NumberFormatException e) { throw new IllegalOptionValueException(this, arg); } } @@ -206,19 +292,20 @@ protected Object parseValue( String arg, Locale locale ) /** * An option that expects a long integer value */ - public static class LongOption extends Option { + public static class LongOption extends Option { public LongOption( char shortForm, String longForm ) { super(shortForm, longForm, true); } public LongOption( String longForm ) { super(longForm, true); } - protected Object parseValue( String arg, Locale locale ) + + @Override + protected Long parseValue( String arg, Locale locale ) throws IllegalOptionValueException { try { return new Long(arg); - } - catch (NumberFormatException e) { + } catch (NumberFormatException e) { throw new IllegalOptionValueException(this, arg); } } @@ -227,21 +314,22 @@ protected Object parseValue( String arg, Locale locale ) /** * An option that expects a floating-point value */ - public static class DoubleOption extends Option { + public static class DoubleOption extends Option { public DoubleOption( char shortForm, String longForm ) { super(shortForm, longForm, true); } public DoubleOption( String longForm ) { super(longForm, true); } - protected Object parseValue( String arg, Locale locale ) + + @Override + protected Double parseValue( String arg, Locale locale ) throws IllegalOptionValueException { try { NumberFormat format = NumberFormat.getNumberInstance(locale); Number num = (Number)format.parse(arg); return new Double(num.doubleValue()); - } - catch (ParseException e) { + } catch (ParseException e) { throw new IllegalOptionValueException(this, arg); } } @@ -250,14 +338,16 @@ protected Object parseValue( String arg, Locale locale ) /** * An option that expects a string value */ - public static class StringOption extends Option { + public static class StringOption extends Option { public StringOption( char shortForm, String longForm ) { super(shortForm, longForm, true); } public StringOption( String longForm ) { super(longForm, true); } - protected Object parseValue( String arg, Locale locale ) { + + @Override + protected String parseValue( String arg, Locale locale ) { return arg; } } @@ -266,9 +356,10 @@ protected Object parseValue( String arg, Locale locale ) { /** * Add the specified Option to the list of accepted options */ - public final Option addOption( Option opt ) { - if ( opt.shortForm() != null ) + public final Option addOption( Option opt ) { + if ( opt.shortForm() != null ) { this.options.put("-" + opt.shortForm(), opt); + } this.options.put("--" + opt.longForm(), opt); return opt; } @@ -277,7 +368,7 @@ public final Option addOption( Option opt ) { * Convenience method for adding a string option. * @return the new Option */ - public final Option addStringOption( char shortForm, String longForm ) { + public final Option addStringOption( char shortForm, String longForm ) { return addOption(new Option.StringOption(shortForm, longForm)); } @@ -285,7 +376,7 @@ public final Option addStringOption( char shortForm, String longForm ) { * Convenience method for adding a string option. * @return the new Option */ - public final Option addStringOption( String longForm ) { + public final Option addStringOption( String longForm ) { return addOption(new Option.StringOption(longForm)); } @@ -293,7 +384,7 @@ public final Option addStringOption( String longForm ) { * Convenience method for adding an integer option. * @return the new Option */ - public final Option addIntegerOption( char shortForm, String longForm ) { + public final Option addIntegerOption( char shortForm, String longForm ) { return addOption(new Option.IntegerOption(shortForm, longForm)); } @@ -301,7 +392,7 @@ public final Option addIntegerOption( char shortForm, String longForm ) { * Convenience method for adding an integer option. * @return the new Option */ - public final Option addIntegerOption( String longForm ) { + public final Option addIntegerOption( String longForm ) { return addOption(new Option.IntegerOption(longForm)); } @@ -309,7 +400,7 @@ public final Option addIntegerOption( String longForm ) { * Convenience method for adding a long integer option. * @return the new Option */ - public final Option addLongOption( char shortForm, String longForm ) { + public final Option addLongOption( char shortForm, String longForm ) { return addOption(new Option.LongOption(shortForm, longForm)); } @@ -317,7 +408,7 @@ public final Option addLongOption( char shortForm, String longForm ) { * Convenience method for adding a long integer option. * @return the new Option */ - public final Option addLongOption( String longForm ) { + public final Option addLongOption( String longForm ) { return addOption(new Option.LongOption(longForm)); } @@ -325,7 +416,7 @@ public final Option addLongOption( String longForm ) { * Convenience method for adding a double option. * @return the new Option */ - public final Option addDoubleOption( char shortForm, String longForm ) { + public final Option addDoubleOption( char shortForm, String longForm ) { return addOption(new Option.DoubleOption(shortForm, longForm)); } @@ -333,7 +424,7 @@ public final Option addDoubleOption( char shortForm, String longForm ) { * Convenience method for adding a double option. * @return the new Option */ - public final Option addDoubleOption( String longForm ) { + public final Option addDoubleOption( String longForm ) { return addOption(new Option.DoubleOption(longForm)); } @@ -341,7 +432,7 @@ public final Option addDoubleOption( String longForm ) { * Convenience method for adding a boolean option. * @return the new Option */ - public final Option addBooleanOption( char shortForm, String longForm ) { + public final Option addBooleanOption( char shortForm, String longForm ) { return addOption(new Option.BooleanOption(shortForm, longForm)); } @@ -349,7 +440,7 @@ public final Option addBooleanOption( char shortForm, String longForm ) { * Convenience method for adding a boolean option. * @return the new Option */ - public final Option addBooleanOption( String longForm ) { + public final Option addBooleanOption( String longForm ) { return addOption(new Option.BooleanOption(longForm)); } @@ -357,7 +448,7 @@ public final Option addBooleanOption( String longForm ) { * Equivalent to {@link #getOptionValue(Option, Object) getOptionValue(o, * null)}. */ - public final Object getOptionValue( Option o ) { + public final T getOptionValue( Option o ) { return getOptionValue(o, null); } @@ -366,18 +457,20 @@ public final Object getOptionValue( Option o ) { * @return the parsed value of the given Option, or the given default 'def' * if the option was not set */ - public final Object getOptionValue( Option o, Object def ) { - Vector v = (Vector)values.get(o.longForm()); + public final T getOptionValue( Option o, T def ) { + List v = values.get(o.longForm()); if (v == null) { return def; - } - else if (v.isEmpty()) { + } else if (v.isEmpty()) { return null; - } - else { - Object result = v.elementAt(0); - v.removeElementAt(0); + } else { + + /* Cast should be safe because Option.parseValue has to return an + * instance of type T or null + */ + @SuppressWarnings("unchecked") + T result = (T)v.remove(0); return result; } } @@ -387,16 +480,15 @@ else if (v.isEmpty()) { * @return A Vector giving the parsed values of all the occurrences of the * given Option, or an empty Vector if the option was not set. */ - public final Vector getOptionValues( Option option ) { - Vector result = new Vector(); + public final Vector getOptionValues( Option option ) { + Vector result = new Vector(); while (true) { - Object o = getOptionValue(option, null); + T o = getOptionValue(option, null); if (o == null) { return result; - } - else { + } else { result.addElement(o); } } @@ -437,9 +529,9 @@ public final void parse( String[] argv, Locale locale ) // backwards compatibility with old user code we throw the two // exceptions above instead. - Vector otherArgs = new Vector(); + ArrayList otherArgs = new ArrayList(); int position = 0; - this.values = new Hashtable(10); + this.values = new HashMap>(10); while ( position < argv.length ) { String curArg = argv[position]; if ( curArg.startsWith("-") ) { @@ -456,24 +548,25 @@ public final void parse( String[] argv, Locale locale ) } } else if(curArg.length() > 2) { // handle -abcd for(int i=1; i opt=this.options.get("-"+curArg.charAt(i)); + if(opt==null) { + throw new UnknownSuboptionException(curArg,curArg.charAt(i)); + } + if(opt.wantsValue()) { + throw new NotFlagException(curArg,curArg.charAt(i)); + } + addValue(opt, null, locale); } position++; continue; } - Option opt = (Option)this.options.get(curArg); + Option opt = this.options.get(curArg); if ( opt == null ) { throw new UnknownOptionException(curArg); } - Object value = null; + if ( opt.wantsValue() ) { if ( valueArg == null ) { position += 1; @@ -481,45 +574,49 @@ public final void parse( String[] argv, Locale locale ) valueArg = argv[position]; } } - value = opt.getValue(valueArg, locale); - } - else { - value = opt.getValue(null, locale); + addValue(opt, valueArg, locale); + } else { + addValue(opt, null, locale); } - addValue(opt, value); - position += 1; } else { - otherArgs.addElement(curArg); + otherArgs.add(curArg); position += 1; } } for ( ; position < argv.length; ++position ) { - otherArgs.addElement(argv[position]); + otherArgs.add(argv[position]); } this.remainingArgs = new String[otherArgs.size()]; - otherArgs.copyInto(remainingArgs); + remainingArgs = otherArgs.toArray(remainingArgs); } - private void addValue(Option opt, Object value) { + private void addValue(Option opt, String valueArg, Locale locale) + throws IllegalOptionValueException { + + T value = opt.getValue(valueArg, locale); String lf = opt.longForm(); - Vector v = (Vector)values.get(lf); + /* Cast is typesafe because the only location we add elements to the + * values map is in this method. + */ + @SuppressWarnings("unchecked") + List v = (List) values.get(lf); if (v == null) { - v = new Vector(); + v = new ArrayList(); values.put(lf, v); } - v.addElement(value); + v.add(value); } private String[] remainingArgs = null; - private Hashtable options = new Hashtable(10); - private Hashtable values = new Hashtable(10); + private Map> options = new HashMap>(10); + private Map> values = new HashMap>(10); } diff --git a/src/jargs/test/gnu/AllTests.java b/src/jargs/test/gnu/AllTests.java index 09aadb9..eda1138 100644 --- a/src/jargs/test/gnu/AllTests.java +++ b/src/jargs/test/gnu/AllTests.java @@ -1,3 +1,35 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + package jargs.test.gnu; import junit.framework.TestSuite; diff --git a/src/jargs/test/gnu/AllTests5.java b/src/jargs/test/gnu/AllTests5.java new file mode 100644 index 0000000..8255542 --- /dev/null +++ b/src/jargs/test/gnu/AllTests5.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package jargs.test.gnu; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({ + CmdLineParserTestCase5.class, + CustomOptionTestCase5.class, +}) +public class AllTests5 { +} diff --git a/src/jargs/test/gnu/CmdLineParserTestCase.java b/src/jargs/test/gnu/CmdLineParserTestCase.java index 2217959..785666d 100644 --- a/src/jargs/test/gnu/CmdLineParserTestCase.java +++ b/src/jargs/test/gnu/CmdLineParserTestCase.java @@ -1,10 +1,42 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + package jargs.test.gnu; import jargs.gnu.CmdLineParser; -import java.util.Enumeration; +import java.util.Collection; +import java.util.Iterator; import java.util.Locale; -import java.util.Vector; import junit.framework.TestCase; @@ -166,15 +198,14 @@ public void testGetOptionValues() throws Exception { }); int verbosity = 0; - Vector v = parser.getOptionValues(verbose); - Enumeration e = v.elements(); - while (e.hasMoreElements()) { - Boolean b = (Boolean)e.nextElement(); + Collection v = parser.getOptionValues(verbose); + Iterator it = v.iterator(); + while (it.hasNext()) { + Boolean b = (Boolean)it.next(); if (b == Boolean.TRUE) { verbosity++; - } - else { + } else { assertEquals(Boolean.FALSE, b); verbosity--; } diff --git a/src/jargs/test/gnu/CmdLineParserTestCase5.java b/src/jargs/test/gnu/CmdLineParserTestCase5.java new file mode 100644 index 0000000..c3b5181 --- /dev/null +++ b/src/jargs/test/gnu/CmdLineParserTestCase5.java @@ -0,0 +1,290 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package jargs.test.gnu; + +import jargs.gnu.CmdLineParser; +import jargs.gnu.CmdLineParser.Option; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Locale; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; +import org.junit.Test; + +public class CmdLineParserTestCase5 { + + @Test + public void testStandardOptions() throws Exception { + CmdLineParser parser = new CmdLineParser(); + Option verbose = parser.addBooleanOption('v', "verbose"); + Option size = parser.addIntegerOption('s', "size"); + Option name = parser.addStringOption('n', "name"); + Option fraction = parser.addDoubleOption('f', "fraction"); + Option missing = parser.addBooleanOption('m', "missing"); + Option careful = parser.addBooleanOption("careful"); + Option bignum = parser.addLongOption('b', "bignum"); + assertEquals(null, parser.getOptionValue(size)); + Long longValue = new Long(new Long(Integer.MAX_VALUE).longValue() + 1); + parser.parse(new String[]{"-v", "--size=100", "-b", + longValue.toString(), "-n", "foo", "-f", "0.1", "rest"}, + Locale.US); + assertEquals(null, parser.getOptionValue(missing)); + assertEquals(Boolean.TRUE, parser.getOptionValue(verbose)); + assertEquals(100, parser.getOptionValue(size).intValue()); + assertEquals("foo", parser.getOptionValue(name)); + assertEquals(longValue, parser.getOptionValue(bignum)); + assertEquals(0.1, parser.getOptionValue(fraction).doubleValue(), 0.1e-6); + assertArrayEquals(new String[]{"rest"}, parser.getRemainingArgs()); + } + + @Test + public void testDefaults() throws Exception { + CmdLineParser parser = new CmdLineParser(); + Option boolean1 = parser.addBooleanOption("boolean1"); + Option boolean2 = parser.addBooleanOption("boolean2"); + Option boolean3 = parser.addBooleanOption("boolean3"); + Option boolean4 = parser.addBooleanOption("boolean4"); + Option boolean5 = parser.addBooleanOption("boolean5"); + + Option int1 = parser.addIntegerOption("int1"); + Option int2 = parser.addIntegerOption("int2"); + Option int3 = parser.addIntegerOption("int3"); + Option int4 = parser.addIntegerOption("int4"); + + Option string1 = parser.addStringOption("string1"); + Option string2 = parser.addStringOption("string2"); + Option string3 = parser.addStringOption("string3"); + Option string4 = parser.addStringOption("string4"); + + parser.parse(new String[]{ + "--boolean1", "--boolean2", + "--int1=42", "--int2=42", + "--string1=Hello", "--string2=Hello",}); + + assertEquals(Boolean.TRUE, parser.getOptionValue(boolean1)); + assertEquals(Boolean.TRUE, + parser.getOptionValue(boolean2, Boolean.FALSE)); + assertEquals(null, parser.getOptionValue(boolean3)); + assertEquals(Boolean.FALSE, + parser.getOptionValue(boolean4, Boolean.FALSE)); + assertEquals(Boolean.TRUE, + parser.getOptionValue(boolean5, Boolean.TRUE)); + + Integer forty_two = new Integer(42); + Integer thirty_six = new Integer(36); + + assertEquals(forty_two, parser.getOptionValue(int1)); + assertEquals(forty_two, parser.getOptionValue(int2, thirty_six)); + assertEquals(null, parser.getOptionValue(int3)); + assertEquals(thirty_six, parser.getOptionValue(int4, thirty_six)); + + assertEquals("Hello", parser.getOptionValue(string1)); + assertEquals("Hello", parser.getOptionValue(string2, "Goodbye")); + assertEquals(null, parser.getOptionValue(string3)); + assertEquals("Goodbye", parser.getOptionValue(string4, "Goodbye")); + } + + @Test + public void testMultipleUses() throws Exception { + CmdLineParser parser = new CmdLineParser(); + Option verbose = parser.addBooleanOption('v', "verbose"); + Option foo = parser.addBooleanOption('f', "foo"); + Option bar = parser.addBooleanOption('b', "bar"); + + parser.parse(new String[]{ + "--foo", "-v", "-v", "--verbose", "-v", "-b", "rest" + }); + + int verbosity = 0; + while (true) { + Boolean b = parser.getOptionValue(verbose); + + if (b == null) { + break; + } + + if (b == Boolean.TRUE) { + verbosity++; + } else { + assertEquals(Boolean.FALSE, b); + verbosity--; + } + } + + assertEquals(4, verbosity); + } + + @Test + public void testCombinedFlags() throws Exception { + CmdLineParser parser = new CmdLineParser(); + Option alt = parser.addBooleanOption('a', "alt"); + Option debug = parser.addBooleanOption('d', "debug"); + Option verbose = parser.addBooleanOption('v', "verbose"); + parser.parse(new String[]{ + "-dv" + }); + + assertEquals(null, parser.getOptionValue(alt)); + assertEquals(Boolean.TRUE, parser.getOptionValue(debug)); + assertEquals(Boolean.TRUE, parser.getOptionValue(verbose)); + } + + @Test + public void testExplictlyTerminatedOptions() throws Exception { + CmdLineParser parser = new CmdLineParser(); + Option alt = parser.addBooleanOption('a', "alt"); + Option debug = parser.addBooleanOption('d', "debug"); + Option verbose = parser.addBooleanOption('v', "verbose"); + Option fraction = parser.addDoubleOption('f', "fraction"); + parser.parse(new String[]{ + "-a", "hello", "-d", "-f", "10", "--", "goodbye", "-v", "welcome", + "-f", "-10" + }); + + assertEquals(Boolean.TRUE, parser.getOptionValue(alt)); + assertEquals(Boolean.TRUE, parser.getOptionValue(debug)); + assertEquals(null, parser.getOptionValue(verbose)); + assertEquals(new Double(10), parser.getOptionValue(fraction)); + + assertArrayEquals( + new String[]{"hello", "goodbye", "-v", "welcome", "-f", "-10"}, + parser.getRemainingArgs()); + } + + @Test + public void testGetOptionValues() throws Exception { + CmdLineParser parser = new CmdLineParser(); + Option verbose = parser.addBooleanOption('v', "verbose"); + Option foo = parser.addBooleanOption('f', "foo"); + Option bar = parser.addBooleanOption('b', "bar"); + + parser.parse(new String[]{ + "--foo", "-v", "-v", "--verbose", "-v", "-b", "rest" + }); + + int verbosity = 0; + Collection v = parser.getOptionValues(verbose); + Iterator it = v.iterator(); + while (it.hasNext()) { + Boolean b = it.next(); + + if (b == Boolean.TRUE) { + verbosity++; + } else { + assertEquals(Boolean.FALSE, b); + verbosity--; + } + } + + assertEquals(4, verbosity); + } + + @Test + public void testBadFormat() throws Exception { + CmdLineParser parser = new CmdLineParser(); + Option size = parser.addIntegerOption('s', "size"); + try { + parser.parse(new String[]{"--size=blah"}); + fail("Expected IllegalOptionValueException"); + } catch (CmdLineParser.IllegalOptionValueException e) { + // pass + } + } + + @Test + public void testResetBetweenParse() throws Exception { + CmdLineParser parser = new CmdLineParser(); + Option verbose = parser.addBooleanOption('v', "verbose"); + parser.parse(new String[]{"-v"}); + assertEquals(Boolean.TRUE, parser.getOptionValue(verbose)); + parser.parse(new String[]{}); + assertEquals(null, parser.getOptionValue(verbose)); + } + + @Test + public void testLocale() throws Exception { + CmdLineParser parser = new CmdLineParser(); + Option fraction = parser.addDoubleOption('f', "fraction"); + parser.parse(new String[]{"--fraction=0.2"}, Locale.US); + assertEquals(0.2, parser.getOptionValue(fraction).doubleValue(), 0.1e-6); + parser.parse(new String[]{"--fraction=0,2"}, Locale.GERMANY); + assertEquals(0.2, parser.getOptionValue(fraction).doubleValue(), 0.1e-6); + } + + @Test + public void testDetachedOption() throws Exception { + CmdLineParser parser = new CmdLineParser(); + Option detached = new CmdLineParser.Option.BooleanOption( + 'v', "verbose"); + assertEquals(null, parser.getOptionValue(detached)); + try { + parser.parse(new String[]{"-v"}); + fail("UnknownOptionException expected"); + } catch (CmdLineParser.UnknownOptionException e) { + // pass + } + assertEquals(null, parser.getOptionValue(detached)); + } + + @Test + public void testMissingValueForStringOption() throws Exception { + CmdLineParser parser = new CmdLineParser(); + parser.addBooleanOption('v', "verbose"); + parser.addStringOption('c', "config"); + + try { + parser.parse(new String[]{"-v", "-c"}); + fail(); + } catch (CmdLineParser.IllegalOptionValueException e) { + } + } + + @Test + public void testWhitespaceValueForStringOption() throws Exception { + CmdLineParser parser = new CmdLineParser(); + Option opt = parser.addStringOption('o', "option"); + parser.parse(new String[]{"-o", " "}); + assertEquals(" ", parser.getOptionValue(opt)); + } + + private void assertArrayEquals(Object[] expected, Object[] actual) { + assertNotNull(actual); + assertEquals(expected.length, actual.length); + for (int i = 0; i < expected.length; ++i) { + assertEquals(expected[i], actual[i]); + } + } +} diff --git a/src/jargs/test/gnu/CustomOptionTestCase.java b/src/jargs/test/gnu/CustomOptionTestCase.java index 92f0519..0d06744 100644 --- a/src/jargs/test/gnu/CustomOptionTestCase.java +++ b/src/jargs/test/gnu/CustomOptionTestCase.java @@ -1,3 +1,35 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + package jargs.test.gnu; import jargs.gnu.CmdLineParser; diff --git a/src/jargs/test/gnu/CustomOptionTestCase5.java b/src/jargs/test/gnu/CustomOptionTestCase5.java new file mode 100644 index 0000000..908ec35 --- /dev/null +++ b/src/jargs/test/gnu/CustomOptionTestCase5.java @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2001-2003 Steve Purcell. + * Copyright (c) 2002 Vidar Holen. + * Copyright (c) 2002 Michal Ceresna. + * Copyright (c) 2005 Ewan Mellor. + * Copyright (c) 2010-2012 penSec.IT UG (haftungsbeschränkt). + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package jargs.test.gnu; + +import jargs.gnu.CmdLineParser; +import jargs.gnu.CmdLineParser.Option; + +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import org.junit.Test; + +public class CustomOptionTestCase5 { + + @Test + public void testCustomOption() throws Exception { + Calendar calendar = Calendar.getInstance(); + CmdLineParser parser = new CmdLineParser(); + Option date = + parser.addOption(new ShortDateOption('d', "date")); + + parser.parse(new String[]{"-d", "11/03/2003"}, Locale.UK); + Date d = parser.getOptionValue(date); + calendar.setTime(d); + assertEquals(11, calendar.get(Calendar.DAY_OF_MONTH)); + assertEquals(Calendar.MARCH, calendar.get(Calendar.MONTH)); + assertEquals(2003, calendar.get(Calendar.YEAR)); + + parser.parse(new String[]{"-d", "11/03/2003"}, Locale.US); + d = parser.getOptionValue(date); + calendar.setTime(d); + assertEquals(3, calendar.get(Calendar.DAY_OF_MONTH)); + assertEquals(Calendar.NOVEMBER, calendar.get(Calendar.MONTH)); + assertEquals(2003, calendar.get(Calendar.YEAR)); + } + + @Test + public void testIllegalCustomOption() throws Exception { + CmdLineParser parser = new CmdLineParser(); + Option date = + parser.addOption(new ShortDateOption('d', "date")); + try { + parser.parse(new String[]{"-d", "foobar"}, Locale.US); + fail("Expected IllegalOptionValueException"); + } + catch (CmdLineParser.IllegalOptionValueException e) { + //pass + } + } + + public static class ShortDateOption extends CmdLineParser.Option { + + public ShortDateOption( char shortForm, String longForm ) { + super(shortForm, longForm, true); + } + + @Override + protected Date parseValue( String arg, Locale locale ) + throws CmdLineParser.IllegalOptionValueException { + try { + DateFormat dateFormat = + DateFormat.getDateInstance(DateFormat.SHORT, locale); + return dateFormat.parse(arg); + } + catch (ParseException e) { + throw new CmdLineParser.IllegalOptionValueException(this, arg); + } + } + } + + +}