diff --git a/args4j/src/org/kohsuke/args4j/CmdLineParser.java b/args4j/src/org/kohsuke/args4j/CmdLineParser.java
index f3a48947..35244561 100644
--- a/args4j/src/org/kohsuke/args4j/CmdLineParser.java
+++ b/args4j/src/org/kohsuke/args4j/CmdLineParser.java
@@ -16,6 +16,7 @@
import java.util.List;
import java.util.ResourceBundle;
import java.util.Set;
+
import org.kohsuke.args4j.spi.Getter;
import org.kohsuke.args4j.spi.OptionHandler;
@@ -26,635 +27,664 @@
/**
* Command line argument owner.
- *
*
- * For typical usage, see this example.
+ *
+ * For typical usage, see
+ * this
+ * example.
*
- * @author
- * Kohsuke Kawaguchi (kk@kohsuke.org)
+ * @author Kohsuke Kawaguchi (kk@kohsuke.org)
*/
public class CmdLineParser {
- /**
- * Discovered {@link OptionHandler}s for options.
- */
- private final List options = new ArrayList();
+ /**
+ * Discovered {@link OptionHandler}s for options.
+ */
+ private final List options = new ArrayList();
- /**
- * Discovered {@link OptionHandler}s for arguments.
- */
- private final List arguments = new ArrayList();
+ /**
+ * Discovered {@link OptionHandler}s for arguments.
+ */
+ private final List arguments = new ArrayList();
- private boolean parsingOptions = true;
- private OptionHandler currentOptionHandler = null;
+ private boolean parsingOptions = true;
+ private OptionHandler currentOptionHandler = null;
/**
- * settings for the parser
+ * settings for the parser
*/
private ParserProperties parserProperties;
- /**
- * Creates a new command line owner that
- * parses arguments/options and set them into
- * the given object.
- *
- * @param bean
- * instance of a class annotated by {@link Option} and {@link Argument}.
- * this object will receive values. If this is {@code null}, the processing will
- * be skipped, which is useful if you'd like to feed metadata from other sources.
- *
- * @throws IllegalAnnotationError
- * if the option bean class is using args4j annotations incorrectly.
- */
- public CmdLineParser(Object bean) {
- // for display purposes, we like the arguments in argument order, but the options in alphabetical order
- this(bean, ParserProperties.defaults());
- }
-
- /**
- * Creates a new command line owner that
- * parses arguments/options and set them into
- * the given object.
- *
- * @param bean
- * instance of a class annotated by {@link Option} and {@link Argument}.
- * this object will receive values. If this is {@code null}, the processing will
- * be skipped, which is useful if you'd like to feed metadata from other sources.
- *
- * @param parserProperties various settings for this class
- *
- * @throws IllegalAnnotationError
- * if the option bean class is using args4j annotations incorrectly.
- */
- public CmdLineParser(Object bean, ParserProperties parserProperties) {
- this.parserProperties = parserProperties;
- // A 'return' in the constructor just skips the rest of the implementation
- // and returns the new object directly.
- if (bean==null) return;
-
- // Parse the metadata and create the setters
- new ClassParser().parse(bean,this);
-
- if (parserProperties.getOptionSorter()!=null) {
- Collections.sort(options, parserProperties.getOptionSorter());
- }
- }
-
- public ParserProperties getProperties() {
- return parserProperties;
- }
-
- /**
- * Programmatically defines an argument (instead of reading it from annotations as normal).
- *
- * @param setter the setter for the type
- * @param a the Argument
- * @throws NullPointerException if {@code setter} or {@code a} is {@code null}.
- */
- public void addArgument(Setter setter, Argument a) {
- checkNonNull(setter, "Setter");
- checkNonNull(a, "Argument");
-
- OptionHandler h = createOptionHandler(new OptionDef(a,setter.isMultiValued()),setter);
- int index = a.index();
- // make sure the argument will fit in the list
- while (index >= arguments.size()) {
- arguments.add(null);
- }
- if(arguments.get(index)!=null) {
- throw new IllegalAnnotationError(Messages.MULTIPLE_USE_OF_ARGUMENT.format(index));
- }
- arguments.set(index, h);
- }
-
- /**
- * Programmatically defines an option (instead of reading it from annotations as normal).
- *
- * @param setter the setter for the type
- * @param o the {@code Option}
- * @throws NullPointerException if {@code setter} or {@code o} is {@code null}.
- * @throws IllegalAnnotationError if the option name or one of the aliases is already taken.
- */
- public void addOption(Setter setter, Option o) {
- checkNonNull(setter, "Setter");
- checkNonNull(o, "Option");
-
- checkOptionNotInMap(o.name());
- for (String alias : o.aliases()) {
- checkOptionNotInMap(alias);
- }
- options.add(createOptionHandler(new NamedOptionDef(o), setter));
- }
-
- /**
- * Lists up all the defined arguments in the order.
- */
- public List getArguments() {
- return arguments;
- }
-
- /**
- * Lists up all the defined options.
- */
- public List getOptions() {
- return options;
- }
+ /**
+ * Creates a new command line owner that
+ * parses arguments/options and set them into
+ * the given object.
+ *
+ * @param bean instance of a class annotated by {@link Option} and {@link Argument}.
+ * this object will receive values. If this is {@code null}, the processing will
+ * be skipped, which is useful if you'd like to feed metadata from other sources.
+ * @throws IllegalAnnotationError if the option bean class is using args4j annotations incorrectly.
+ */
+ public CmdLineParser(Object bean) {
+ // for display purposes, we like the arguments in argument order, but the options in alphabetical order
+ this(bean, ParserProperties.defaults());
+ }
+
+ /**
+ * Creates a new command line owner that
+ * parses arguments/options and set them into
+ * the given object.
+ *
+ * @param bean instance of a class annotated by {@link Option} and {@link Argument}.
+ * this object will receive values. If this is {@code null}, the processing will
+ * be skipped, which is useful if you'd like to feed metadata from other sources.
+ * @param parserProperties various settings for this class
+ * @throws IllegalAnnotationError if the option bean class is using args4j annotations incorrectly.
+ */
+ public CmdLineParser(Object bean, ParserProperties parserProperties) {
+ this.parserProperties = parserProperties;
+ // A 'return' in the constructor just skips the rest of the implementation
+ // and returns the new object directly.
+ if (bean == null) {
+ return;
+ }
+
+ // Parse the metadata and create the setters
+ new ClassParser().parse(bean, this);
+
+ if (parserProperties.getOptionSorter() != null) {
+ Collections.sort(options, parserProperties.getOptionSorter());
+ }
+ }
+
+ public ParserProperties getProperties() {
+ return parserProperties;
+ }
+
+ /**
+ * Programmatically defines an argument (instead of reading it from annotations as normal).
+ *
+ * @param setter the setter for the type
+ * @param a the Argument
+ * @throws NullPointerException if {@code setter} or {@code a} is {@code null}.
+ */
+ public void addArgument(Setter setter, Argument a) {
+ checkNonNull(setter, "Setter");
+ checkNonNull(a, "Argument");
+
+ OptionHandler h = createOptionHandler(new OptionDef(a, setter.isMultiValued()), setter);
+ int index = a.index();
+ // make sure the argument will fit in the list
+ while (index >= arguments.size()) {
+ arguments.add(null);
+ }
+ if (arguments.get(index) != null) {
+ throw new IllegalAnnotationError(Messages.MULTIPLE_USE_OF_ARGUMENT.format(index));
+ }
+ arguments.set(index, h);
+ }
+
+ /**
+ * Programmatically defines an option (instead of reading it from annotations as normal).
+ *
+ * @param setter the setter for the type
+ * @param o the {@code Option}
+ * @throws NullPointerException if {@code setter} or {@code o} is {@code null}.
+ * @throws IllegalAnnotationError if the option name or one of the aliases is already taken.
+ */
+ public void addOption(Setter setter, Option o) {
+ checkNonNull(setter, "Setter");
+ checkNonNull(o, "Option");
+
+ checkOptionNotInMap(o.name());
+ for (String alias : o.aliases()) {
+ checkOptionNotInMap(alias);
+ }
+ options.add(createOptionHandler(new NamedOptionDef(o), setter));
+ }
+
+ /**
+ * Lists up all the defined arguments in the order.
+ */
+ public List getArguments() {
+ return arguments;
+ }
+
+ /**
+ * Lists up all the defined options.
+ */
+ public List getOptions() {
+ return options;
+ }
private void checkOptionNotInMap(String name) throws IllegalAnnotationError {
- checkNonNull(name, "name");
-
- if(findOptionByName(name)!=null) {
- throw new IllegalAnnotationError(Messages.MULTIPLE_USE_OF_OPTION.format(name));
- }
- }
-
- /**
- * Creates an {@link OptionHandler} that handles the given {@link Option} annotation
- * and the {@link Setter} instance.
- */
- protected OptionHandler createOptionHandler(OptionDef o, Setter setter) {
- checkNonNull(o, "OptionDef");
- checkNonNull(setter, "Setter");
- return OptionHandlerRegistry.getRegistry().createOptionHandler(this, o, setter);
- }
-
- /**
- * Formats a command line example into a string.
- *
- * See {@link #printExample(OptionHandlerFilter, ResourceBundle)} for more details.
- *
- * @param filter
- * must not be {@code null}.
- * @return
- * always non-{@code null}.
- */
- public String printExample(OptionHandlerFilter filter) {
- return printExample(filter, null);
- }
-
- /**
- * @deprecated
- * Use {@link #printExample(OptionHandlerFilter)}
- */
- public String printExample(ExampleMode mode) {
- return printExample(mode, null);
- }
-
- /**
- * Formats a command line example into a string.
- *
- *
- * This method produces a string like -d <dir> -v -b
.
- * This is useful for printing a command line example (perhaps
- * as a part of the usage screen).
- *
- *
- * @param mode
- * Determines which options will be a part of the returned string.
- * Must not be {@code null}.
- * @param rb
- * If non-{@code null}, meta variables (<dir>
in the above example)
- * is treated as a key to this resource bundle, and the associated
- * value is printed. See {@link Option#metaVar()}. This is to support
- * localization.
- *
- * Passing {@code null} would print {@link Option#metaVar()} directly.
- * @return
- * always non-{@code null}. If there's no option, this method returns
- * just the empty string {@code ""}. Otherwise, this method returns a
- * string that contains a space at the beginning (but not at the end).
- * This allows you to do something like:
- * System.err.println("java -jar my.jar"+parser.printExample(REQUIRED)+" arg1 arg2");
- * @throws NullPointerException if {@code mode} is {@code null}.
- */
- public String printExample(OptionHandlerFilter mode, ResourceBundle rb) {
- StringBuilder buf = new StringBuilder();
-
- checkNonNull(mode, "mode");
-
- for (OptionHandler h : options) {
- OptionDef option = h.option;
- if(option.usage().length()==0) continue; // ignore
- if(!mode.select(h)) continue;
-
- buf.append(' ');
- buf.append(h.getNameAndMeta(rb, parserProperties));
- }
-
- return buf.toString();
- }
-
- /**
- * @deprecated
- * Use {@link #printExample(OptionHandlerFilter,ResourceBundle)}
- */
- public String printExample(ExampleMode mode, ResourceBundle rb) {
- return printExample((OptionHandlerFilter) mode, rb);
- }
-
- /**
- * Prints the list of options and their usages to the screen.
- *
- *
- * This is a convenience method for calling {@code printUsage(new OutputStreamWriter(out),null)}
- * so that you can do {@code printUsage(System.err)}.
- */
- public void printUsage(OutputStream out) {
- printUsage(new OutputStreamWriter(out),null);
- }
-
- /**
- * Prints the list of all the non-hidden options and their usages to the screen.
- *
- *
- * Short for {@code printUsage(out,rb,OptionHandlerFilter.PUBLIC)}
- */
- public void printUsage(Writer out, ResourceBundle rb) {
- printUsage(out, rb, OptionHandlerFilter.PUBLIC);
- }
-
- /**
- * Prints the list of all the non-hidden options and their usages to the screen.
- *
- * @param rb
- * If non-{@code null}, {@link Option#usage()} is treated
- * as a key to obtain the actual message from this resource bundle.
- * @param filter
- * Controls which options to be printed.
- */
- public void printUsage(Writer out, ResourceBundle rb, OptionHandlerFilter filter) {
- PrintWriter w = new PrintWriter(out);
- // determine the length of the option + metavar first
- int len = 0;
- for (OptionHandler h : arguments) {
- int curLen = getPrefixLen(h, rb);
- len = Math.max(len,curLen);
- }
- for (OptionHandler h: options) {
- int curLen = getPrefixLen(h, rb);
- len = Math.max(len,curLen);
- }
-
- // then print
- for (OptionHandler h : arguments) {
- printOption(w, h, len, rb, filter);
- }
- for (OptionHandler h : options) {
- printOption(w, h, len, rb, filter);
- }
-
- w.flush();
- }
-
- /**
- * Prints usage information for a given option.
- *
- *
- * Subtypes may override this method and determine which options get printed (or other things),
- * based on {@link OptionHandler} (perhaps by using {@code handler.setter.asAnnotatedElement()}).
- *
- * @param out Writer to write into
- * @param handler handler where to receive the information
- * @param len Maximum length of metadata column
- * @param rb {@code ResourceBundle} for I18N
- * @see Setter#asAnnotatedElement()
- */
- protected void printOption(PrintWriter out, OptionHandler handler, int len, ResourceBundle rb, OptionHandlerFilter filter) {
- // Hiding options without usage information
- if (handler.option.usage() == null ||
- handler.option.usage().length() == 0 ||
- !filter.select(handler)) {
- return;
- }
-
- // What is the width of the two data columns
- int totalUsageWidth = parserProperties.getUsageWidth();
- int widthMetadata = Math.min(len, (totalUsageWidth - 4) / 2);
- int widthUsage = totalUsageWidth - 4 - widthMetadata;
-
- String defaultValuePart = createDefaultValuePart(handler);
-
- // Line wrapping
- // the 'left' side
- List namesAndMetas = wrapLines(handler.getNameAndMeta(rb, parserProperties), widthMetadata);
- // the 'right' side
- List usages = wrapLines(localize(handler.option.usage(),rb) + defaultValuePart, widthUsage);
-
- // Output
- for(int i=0; i= namesAndMetas.size()) ? "" : namesAndMetas.get(i);
- String usage = (i >= usages.size()) ? "" : usages.get(i);
- String format = ((nameAndMeta.length() > 0) && (i == 0))
- ? " %1$-" + widthMetadata + "s : %2$-1s"
- : " %1$-" + widthMetadata + "s %2$-1s";
+ checkNonNull(name, "name");
+
+ if (findOptionByName(name) != null) {
+ throw new IllegalAnnotationError(Messages.MULTIPLE_USE_OF_OPTION.format(name));
+ }
+ }
+
+ /**
+ * Creates an {@link OptionHandler} that handles the given {@link Option} annotation
+ * and the {@link Setter} instance.
+ */
+ protected OptionHandler createOptionHandler(OptionDef o, Setter setter) {
+ checkNonNull(o, "OptionDef");
+ checkNonNull(setter, "Setter");
+ return OptionHandlerRegistry.getRegistry().createOptionHandler(this, o, setter);
+ }
+
+ /**
+ * Formats a command line example into a string.
+ *
+ * See {@link #printExample(OptionHandlerFilter, ResourceBundle)} for more details.
+ *
+ * @param filter must not be {@code null}.
+ * @return always non-{@code null}.
+ */
+ public String printExample(OptionHandlerFilter filter) {
+ return printExample(filter, null);
+ }
+
+ /**
+ * @deprecated Use {@link #printExample(OptionHandlerFilter)}
+ */
+ public String printExample(ExampleMode mode) {
+ return printExample(mode, null);
+ }
+
+ /**
+ * Formats a command line example into a string.
+ *
+ *
+ * This method produces a string like -d <dir> -v -b
.
+ * This is useful for printing a command line example (perhaps
+ * as a part of the usage screen).
+ *
+ * @param mode Determines which options will be a part of the returned string.
+ * Must not be {@code null}.
+ * @param rb If non-{@code null}, meta variables (<dir>
in the above example)
+ * is treated as a key to this resource bundle, and the associated
+ * value is printed. See {@link Option#metaVar()}. This is to support
+ * localization.
+ *
+ * Passing {@code null} would print {@link Option#metaVar()} directly.
+ * @return always non-{@code null}. If there's no option, this method returns
+ * just the empty string {@code ""}. Otherwise, this method returns a
+ * string that contains a space at the beginning (but not at the end).
+ * This allows you to do something like:
+ * System.err.println("java -jar my.jar"+parser.printExample(REQUIRED)+" arg1 arg2");
+ * @throws NullPointerException if {@code mode} is {@code null}.
+ */
+ public String printExample(OptionHandlerFilter mode, ResourceBundle rb) {
+ StringBuilder buf = new StringBuilder();
+
+ checkNonNull(mode, "mode");
+
+ for (OptionHandler h : options) {
+ OptionDef option = h.option;
+ if (option.usage().length() == 0) {
+ continue; // ignore
+ }
+ if (!mode.select(h)) {
+ continue;
+ }
+
+ buf.append(' ');
+ buf.append(h.getNameAndMeta(rb, parserProperties));
+ }
+
+ return buf.toString();
+ }
+
+ /**
+ * @deprecated Use {@link #printExample(OptionHandlerFilter, ResourceBundle)}
+ */
+ public String printExample(ExampleMode mode, ResourceBundle rb) {
+ return printExample((OptionHandlerFilter) mode, rb);
+ }
+
+ /**
+ * Prints the list of options and their usages to the screen.
+ *
+ *
+ * This is a convenience method for calling {@code printUsage(new OutputStreamWriter(out),null)}
+ * so that you can do {@code printUsage(System.err)}.
+ */
+ public void printUsage(OutputStream out) {
+ printUsage(new OutputStreamWriter(out), null);
+ }
+
+ /**
+ * Prints the list of all the non-hidden options and their usages to the screen.
+ *
+ *
+ * Short for {@code printUsage(out,rb,OptionHandlerFilter.PUBLIC)}
+ */
+ public void printUsage(Writer out, ResourceBundle rb) {
+ printUsage(out, rb, OptionHandlerFilter.PUBLIC);
+ }
+
+ /**
+ * Prints the list of all the non-hidden options and their usages to the screen.
+ *
+ * @param rb If non-{@code null}, {@link Option#usage()} is treated
+ * as a key to obtain the actual message from this resource bundle.
+ * @param filter Controls which options to be printed.
+ */
+ public void printUsage(Writer out, ResourceBundle rb, OptionHandlerFilter filter) {
+ PrintWriter w = new PrintWriter(out);
+ // determine the length of the option + metavar first
+ int len = 0;
+ for (OptionHandler h : arguments) {
+ int curLen = getPrefixLen(h, rb);
+ len = Math.max(len, curLen);
+ }
+ for (OptionHandler h : options) {
+ int curLen = getPrefixLen(h, rb);
+ len = Math.max(len, curLen);
+ }
+
+ // then print
+ for (OptionHandler h : arguments) {
+ printOption(w, h, len, rb, filter);
+ }
+ for (OptionHandler h : options) {
+ printOption(w, h, len, rb, filter);
+ }
+
+ w.flush();
+ }
+
+ /**
+ * Prints usage information for a given option.
+ *
+ *
+ * Subtypes may override this method and determine which options get printed (or other things),
+ * based on {@link OptionHandler} (perhaps by using {@code handler.setter.asAnnotatedElement()}).
+ *
+ * @param out Writer to write into
+ * @param handler handler where to receive the information
+ * @param len Maximum length of metadata column
+ * @param rb {@code ResourceBundle} for I18N
+ * @see Setter#asAnnotatedElement()
+ */
+ protected void printOption(PrintWriter out, OptionHandler handler, int len, ResourceBundle rb,
+ OptionHandlerFilter filter) {
+ // Hiding options without usage information
+ if (handler.option.usage() == null || handler.option.usage().length() == 0 || !filter.select(handler)) {
+ return;
+ }
+
+ // What is the width of the two data columns
+ int totalUsageWidth = parserProperties.getUsageWidth();
+ int widthMetadata = Math.min(len, (totalUsageWidth - 4) / 2);
+ int widthUsage = totalUsageWidth - 4 - widthMetadata;
+
+ String defaultValuePart = createDefaultValuePart(handler);
+
+ // Line wrapping
+ // the 'left' side
+ List namesAndMetas = wrapLines(handler.getNameAndMeta(rb, parserProperties), widthMetadata);
+ // the 'right' side
+ List usages = wrapLines(localize(handler.option.usage(), rb) + defaultValuePart, widthUsage);
+
+ // Output
+ for (int i = 0; i < Math.max(namesAndMetas.size(), usages.size()); i++) {
+ String nameAndMeta = (i >= namesAndMetas.size()) ? "" : namesAndMetas.get(i);
+ String usage = (i >= usages.size()) ? "" : usages.get(i);
+ String format = ((nameAndMeta.length() > 0) && (i == 0)) ? " %1$-" + widthMetadata + "s : %2$-1s" : " " +
+ "%1$-" + widthMetadata + "s %2$-1s";
String output = String.format(format, nameAndMeta, usage);
-
+
out.println(output);
- }
- }
-
- private String createDefaultValuePart(OptionHandler handler) {
- if (parserProperties.getShowDefaults() && !handler.option.required() && handler.setter instanceof Getter) {
- String v = handler.printDefaultValue();
- if (v!=null)
- return " " + Messages.DEFAULT_VALUE.format(v);
- }
- return "";
- }
-
- private String localize(String s, ResourceBundle rb) {
- if(rb!=null) return rb.getString(s);
- return s;
- }
-
- /**
- * Wraps a line so that the resulting parts are not longer than a given maximum length.
- *
- * @param line Line to wrap
- * @param maxLength maximum length for the resulting parts
- * @return list of all wrapped parts
- */
- private List wrapLines(String line, final int maxLength) {
- List rv = new ArrayList();
- for (String restOfLine : line.split("\\n")) {
- while (restOfLine.length() > maxLength) {
- // try to wrap at space, but don't try too hard as some languages don't even have whitespaces.
- int lineLength;
- String candidate = restOfLine.substring(0, maxLength);
- int sp=candidate.lastIndexOf(' ');
- if(sp>maxLength*3/5) lineLength=sp;
- else lineLength=maxLength;
- rv.add(restOfLine.substring(0, lineLength));
- restOfLine = restOfLine.substring(lineLength).trim();
- }
- rv.add(restOfLine);
- }
- return rv;
- }
+ }
+ }
+
+ private String createDefaultValuePart(OptionHandler handler) {
+ if (parserProperties.getShowDefaults() && !handler.option.required() && handler.setter instanceof Getter) {
+ String v = handler.printDefaultValue();
+ if (v != null) {
+ return " " + Messages.DEFAULT_VALUE.format(v);
+ }
+ }
+ return "";
+ }
+
+ private String localize(String s, ResourceBundle rb) {
+ if (rb != null) {
+ return rb.getString(s);
+ }
+ return s;
+ }
+
+ /**
+ * Wraps a line so that the resulting parts are not longer than a given maximum length.
+ *
+ * @param line Line to wrap
+ * @param maxLength maximum length for the resulting parts
+ * @return list of all wrapped parts
+ */
+ private List wrapLines(String line, final int maxLength) {
+ List rv = new ArrayList();
+ for (String restOfLine : line.split("\\n")) {
+ while (restOfLine.length() > maxLength) {
+ // try to wrap at space, but don't try too hard as some languages don't even have whitespaces.
+ int lineLength;
+ String candidate = restOfLine.substring(0, maxLength);
+ int sp = candidate.lastIndexOf(' ');
+ if (sp > maxLength * 3 / 5) {
+ lineLength = sp;
+ } else {
+ lineLength = maxLength;
+ }
+ rv.add(restOfLine.substring(0, lineLength));
+ restOfLine = restOfLine.substring(lineLength).trim();
+ }
+ rv.add(restOfLine);
+ }
+ return rv;
+ }
private int getPrefixLen(OptionHandler h, ResourceBundle rb) {
- if(h.option.usage().length()==0)
+ if (h.option.usage().length() == 0) {
return 0;
+ }
return h.getNameAndMeta(rb, parserProperties).length();
}
- /**
- * Essentially a pointer over a {@link String} array.
- * Can move forward; can look ahead.
- */
- private class CmdLineImpl implements Parameters {
- private final String[] args;
- private int pos;
-
- CmdLineImpl( String[] args ) {
- this.args = args;
- pos = 0;
- }
-
- protected boolean hasMore() {
- return pos=args.length || pos+idx<0 )
- throw new CmdLineException(CmdLineParser.this, Messages.MISSING_OPERAND, getOptionName());
- return args[pos+idx];
- }
-
- public int size() {
- return args.length-pos;
- }
-
- /**
- * Used when the current token is of the form "-option=value",
- * to replace the current token by "value", as if this was given as two tokens "-option value"
- */
- void splitToken() {
- if (pos < args.length && pos >= 0) {
- int idx = args[pos].indexOf("=");
- if (idx > 0) {
- args[pos] = args[pos].substring(idx + 1);
- }
- }
- }
- }
-
- private String getOptionName() {
- return currentOptionHandler.option.toString();
- }
-
- /**
- * Same as {@link #parseArgument(String[])}
- */
- public void parseArgument(Collection args) throws CmdLineException {
- parseArgument(args.toArray(new String[args.size()]));
- }
-
- /**
- * Parses the command line arguments and set them to the option bean
- * given in the constructor.
- *
- * @param args arguments to parse
- *
- * @throws CmdLineException
- * if there's any error parsing arguments, or if
- * {@link Option#required() required} option was not given.
- * @throws NullPointerException if {@code args} is {@code null}.
- */
- public void parseArgument(final String... args) throws CmdLineException {
-
- checkNonNull(args, "args");
-
- String expandedArgs[] = args;
- if (parserProperties.getAtSyntax()) {
- expandedArgs = expandAtFiles(args);
- }
- CmdLineImpl cmdLine = new CmdLineImpl(expandedArgs);
-
- Set present = new HashSet();
- int argIndex = 0;
-
- while( cmdLine.hasMore() ) {
- String arg = cmdLine.getCurrentToken();
- if( isOption(arg) ) {
- // '=' is for historical compatibility fallback
- boolean isKeyValuePair = arg.contains(parserProperties.getOptionValueDelimiter()) || arg.indexOf('=')!=-1;
-
- // parse this as an option.
- currentOptionHandler = isKeyValuePair ? findOptionHandler(arg) : findOptionByName(arg);
-
- if(currentOptionHandler==null) {
- // TODO: insert dynamic handler processing
- throw new CmdLineException(this, Messages.UNDEFINED_OPTION, arg);
- }
-
- // known option; skip its name
- if (isKeyValuePair) {
- cmdLine.splitToken();
- } else {
- cmdLine.proceed(1);
- }
- } else {
- if (argIndex >= arguments.size()) {
- Messages msg = arguments.size() == 0 ? Messages.NO_ARGUMENT_ALLOWED : Messages.TOO_MANY_ARGUMENTS;
- throw new CmdLineException(this, msg, arg);
- }
-
- // known argument
- currentOptionHandler = arguments.get(argIndex);
- if (currentOptionHandler==null) // this is a programmer error. arg index should be continuous
- throw new IllegalStateException("@Argument with index="+argIndex+" is undefined");
-
- if (!currentOptionHandler.option.isMultiValued())
- argIndex++;
- }
- int diff = currentOptionHandler.parseArguments(cmdLine);
- cmdLine.proceed(diff);
- present.add(currentOptionHandler);
- }
-
- // check whether a help option is set
- boolean helpSet = false;
- for (OptionHandler handler : options) {
- if(handler.option.help() && present.contains(handler)) {
- helpSet = true;
- }
- }
-
- if (!helpSet) {
- checkRequiredOptionsAndArguments(present);
- }
- }
-
- /**
- * Expands every entry prefixed with the AT sign by
- * reading the file. The AT sign is used to reference
- * another file that contains command line options separated
- * by line breaks.
- * @param args the command line arguments to be preprocessed.
- * @return args with the @ sequences replaced by the text files referenced
- * by the @ sequences, split around the line breaks.
- * @throws CmdLineException
- */
- private String[] expandAtFiles(String args[]) throws CmdLineException {
- List result = new ArrayList();
- for (String arg : args) {
- if (arg.startsWith("@")) {
- File file = new File(arg.substring(1));
- if (!file.exists())
- throw new CmdLineException(this,Messages.NO_SUCH_FILE,file.getPath());
- try {
- result.addAll(readAllLines(file));
- } catch (IOException ex) {
- throw new CmdLineException(this, "Failed to parse "+file,ex);
- }
- } else {
- result.add(arg);
- }
- }
- return result.toArray(new String[result.size()]);
- }
-
- /**
- * Reads all lines of a file with the platform encoding.
- */
- private static List readAllLines(File f) throws IOException {
- BufferedReader r = new BufferedReader(new FileReader(f));
- try {
- List result = new ArrayList();
- String line;
- while ((line = r.readLine()) != null) {
- result.add(line);
- }
- return result;
- } finally {
- r.close();
- }
- }
-
- private void checkRequiredOptionsAndArguments(Set present) throws CmdLineException {
- // make sure that all mandatory options are present
- for (OptionHandler handler : options) {
- if(handler.option.required() && !present.contains(handler)) {
- throw new CmdLineException(this, Messages.REQUIRED_OPTION_MISSING, handler.option.toString());
- }
- }
-
- // make sure that all mandatory arguments are present
- for (OptionHandler handler : arguments) {
- if(handler.option.required() && !present.contains(handler)) {
- throw new CmdLineException(this, Messages.REQUIRED_ARGUMENT_MISSING, handler.option.toString());
- }
- }
-
- //make sure that all requires arguments are present
- for (OptionHandler handler : present) {
- if (handler.option instanceof NamedOptionDef && !isHandlerHasHisOptions((NamedOptionDef)handler.option, present)) {
- throw new CmdLineException(this, Messages.REQUIRES_OPTION_MISSING,
- handler.option.toString(), Arrays.toString(((NamedOptionDef)handler.option).depends()));
- }
- }
-
- //make sure that all forbids arguments are not present
- for (OptionHandler handler : present) {
- if (handler.option instanceof NamedOptionDef && !isHandlerAllowOtherOptions((NamedOptionDef) handler.option, present)) {
- throw new CmdLineException(this, Messages.FORBIDDEN_OPTION_PRESENT,
- handler.option.toString(), Arrays.toString(((NamedOptionDef) handler.option).forbids()));
- }
- }
- }
-
- /**
- * @return {@code true} if all options required by {@code option} are present, {@code false} otherwise
- */
- private boolean isHandlerHasHisOptions(NamedOptionDef option, Set present) {
- for (String depend : option.depends()) {
- if (!present.contains(findOptionHandler(depend)))
- return false;
- }
- return true;
- }
-
- /**
- * @return {@code true} if all options forbid by {@code option} are not present, {@code false} otherwise
- */
- private boolean isHandlerAllowOtherOptions(NamedOptionDef option, Set present) {
- for (String forbid : option.forbids()) {
- if (present.contains(findOptionHandler(forbid)))
- return false;
- }
- return true;
- }
-
- private OptionHandler findOptionHandler(String name) {
- // Look for key/value pair first.
- int pos = name.indexOf(parserProperties.getOptionValueDelimiter());
- if (pos < 0) {
- pos = name.indexOf('='); // historical compatibility fallback
- }
- if (pos > 0) {
- name = name.substring(0, pos);
- }
+ /**
+ * Essentially a pointer over a {@link String} array.
+ * Can move forward; can look ahead.
+ */
+ private class CmdLineImpl implements Parameters {
+ private final String[] args;
+ private int pos;
+
+ CmdLineImpl(String[] args) {
+ this.args = args;
+ pos = 0;
+ }
+
+ protected boolean hasMore() {
+ return pos < args.length;
+ }
+
+ protected String getCurrentToken() {
+ return args[pos];
+ }
+
+ private void proceed(int n) {
+ pos += n;
+ }
+
+ public String getParameter(int idx) throws CmdLineException {
+ if (pos + idx >= args.length || pos + idx < 0) {
+ throw new CmdLineException(CmdLineParser.this, Messages.MISSING_OPERAND, getOptionName());
+ }
+ return args[pos + idx];
+ }
+
+ public int size() {
+ return args.length - pos;
+ }
+
+ /**
+ * Used when the current token is of the form "-option=value",
+ * to replace the current token by "value", as if this was given as two tokens "-option value"
+ */
+ void splitToken() {
+ if (pos < args.length && pos >= 0) {
+ int idx = args[pos].indexOf("=");
+ if (idx > 0) {
+ args[pos] = args[pos].substring(idx + 1);
+ }
+ }
+ }
+ }
+
+ private String getOptionName() {
+ return currentOptionHandler.option.toString();
+ }
+
+ /**
+ * Same as {@link #parseArgument(String[])}
+ */
+ public void parseArgument(Collection args) throws CmdLineException {
+ parseArgument(args.toArray(new String[args.size()]));
+ }
+
+ /**
+ * Parses the command line arguments and set them to the option bean
+ * given in the constructor.
+ *
+ * @param args arguments to parse
+ * @throws CmdLineException if there's any error parsing arguments, or if
+ * {@link Option#required() required} option was not given.
+ * @throws NullPointerException if {@code args} is {@code null}.
+ */
+ public void parseArgument(final String... args) throws CmdLineException {
+
+ checkNonNull(args, "args");
+
+ String expandedArgs[] = args;
+ if (parserProperties.getAtSyntax()) {
+ expandedArgs = expandAtFiles(args);
+ }
+ CmdLineImpl cmdLine = new CmdLineImpl(expandedArgs);
+
+ Set present = new HashSet();
+ int argIndex = 0;
+
+
+ List undefinedOptions = new ArrayList();
+ while (cmdLine.hasMore()) {
+ String arg = cmdLine.getCurrentToken();
+ if (isOption(arg)) {
+ // '=' is for historical compatibility fallback
+ boolean isKeyValuePair = arg.contains(parserProperties.getOptionValueDelimiter()) || arg.indexOf('=')
+ != -1;
+
+ // parse this as an option.
+ currentOptionHandler = isKeyValuePair ? findOptionHandler(arg) : findOptionByName(arg);
+
+ if (currentOptionHandler == null) {
+ if (!parserProperties.isIgnoreUndefinedOptions()) {
+ // TODO: insert dynamic handler processing
+ throw new CmdLineException(this, Messages.UNDEFINED_OPTION, arg);
+ } else {
+ undefinedOptions.add(arg);
+ cmdLine.proceed(2);
+ continue;
+ }
+ }
+
+ // known option; skip its name
+ if (isKeyValuePair) {
+ cmdLine.splitToken();
+ } else {
+ cmdLine.proceed(1);
+ }
+ } else {
+ if (argIndex >= arguments.size()) {
+ Messages msg = arguments.size() == 0 ? Messages.NO_ARGUMENT_ALLOWED : Messages.TOO_MANY_ARGUMENTS;
+ throw new CmdLineException(this, msg, arg);
+ }
+
+ // known argument
+ currentOptionHandler = arguments.get(argIndex);
+ if (currentOptionHandler == null) // this is a programmer error. arg index should be continuous
+ {
+ throw new IllegalStateException("@Argument with index=" + argIndex + " is undefined");
+ }
+
+ if (!currentOptionHandler.option.isMultiValued()) {
+ argIndex++;
+ }
+ }
+ int diff = currentOptionHandler.parseArguments(cmdLine);
+ cmdLine.proceed(diff);
+ present.add(currentOptionHandler);
+ }
+
+ // check whether a help option is set
+ boolean helpSet = false;
+ for (OptionHandler handler : options) {
+ if (handler.option.help() && present.contains(handler)) {
+ helpSet = true;
+ }
+ }
+
+ if (!helpSet) {
+ checkRequiredOptionsAndArguments(present);
+ }
+ if (parserProperties.isIgnoreUndefinedOptions() && !undefinedOptions.isEmpty()) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < undefinedOptions.size(); i++) {
+ sb.append(undefinedOptions.get(i));
+ if (i < undefinedOptions.size() - 1) {
+ sb.append(", ");
+ }
+ }
+
+ System.out.println("The following undefined options were ignored: " + sb.toString());
+ }
+ }
+
+ /**
+ * Expands every entry prefixed with the AT sign by
+ * reading the file. The AT sign is used to reference
+ * another file that contains command line options separated
+ * by line breaks.
+ *
+ * @param args the command line arguments to be preprocessed.
+ * @return args with the @ sequences replaced by the text files referenced
+ * by the @ sequences, split around the line breaks.
+ * @throws CmdLineException
+ */
+ private String[] expandAtFiles(String args[]) throws CmdLineException {
+ List result = new ArrayList();
+ for (String arg : args) {
+ if (arg.startsWith("@")) {
+ File file = new File(arg.substring(1));
+ if (!file.exists()) {
+ throw new CmdLineException(this, Messages.NO_SUCH_FILE, file.getPath());
+ }
+ try {
+ result.addAll(readAllLines(file));
+ } catch (IOException ex) {
+ throw new CmdLineException(this, "Failed to parse " + file, ex);
+ }
+ } else {
+ result.add(arg);
+ }
+ }
+ return result.toArray(new String[result.size()]);
+ }
+
+ /**
+ * Reads all lines of a file with the platform encoding.
+ */
+ private static List readAllLines(File f) throws IOException {
+ BufferedReader r = new BufferedReader(new FileReader(f));
+ try {
+ List result = new ArrayList();
+ String line;
+ while ((line = r.readLine()) != null) {
+ result.add(line);
+ }
+ return result;
+ } finally {
+ r.close();
+ }
+ }
+
+ private void checkRequiredOptionsAndArguments(Set present) throws CmdLineException {
+ // make sure that all mandatory options are present
+ for (OptionHandler handler : options) {
+ if (handler.option.required() && !present.contains(handler)) {
+ throw new CmdLineException(this, Messages.REQUIRED_OPTION_MISSING, handler.option.toString());
+ }
+ }
+
+ // make sure that all mandatory arguments are present
+ for (OptionHandler handler : arguments) {
+ if (handler.option.required() && !present.contains(handler)) {
+ throw new CmdLineException(this, Messages.REQUIRED_ARGUMENT_MISSING, handler.option.toString());
+ }
+ }
+
+ //make sure that all requires arguments are present
+ for (OptionHandler handler : present) {
+ if (handler.option instanceof NamedOptionDef && !isHandlerHasHisOptions((NamedOptionDef) handler.option,
+ present)) {
+ throw new CmdLineException(this,
+ Messages.REQUIRES_OPTION_MISSING,
+ handler.option.toString(),
+ Arrays.toString(((NamedOptionDef) handler.option).depends()));
+ }
+ }
+
+ //make sure that all forbids arguments are not present
+ for (OptionHandler handler : present) {
+ if (handler.option instanceof NamedOptionDef && !isHandlerAllowOtherOptions((NamedOptionDef) handler
+ .option,
+ present)) {
+ throw new CmdLineException(this,
+ Messages.FORBIDDEN_OPTION_PRESENT,
+ handler.option.toString(),
+ Arrays.toString(((NamedOptionDef) handler.option).forbids()));
+ }
+ }
+ }
+
+ /**
+ * @return {@code true} if all options required by {@code option} are present, {@code false} otherwise
+ */
+ private boolean isHandlerHasHisOptions(NamedOptionDef option, Set present) {
+ for (String depend : option.depends()) {
+ if (!present.contains(findOptionHandler(depend))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @return {@code true} if all options forbid by {@code option} are not present, {@code false} otherwise
+ */
+ private boolean isHandlerAllowOtherOptions(NamedOptionDef option, Set present) {
+ for (String forbid : option.forbids()) {
+ if (present.contains(findOptionHandler(forbid))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private OptionHandler findOptionHandler(String name) {
+ // Look for key/value pair first.
+ int pos = name.indexOf(parserProperties.getOptionValueDelimiter());
+ if (pos < 0) {
+ pos = name.indexOf('='); // historical compatibility fallback
+ }
+ if (pos > 0) {
+ name = name.substring(0, pos);
+ }
return findOptionByName(name);
- }
+ }
/**
* Finds a registered {@code OptionHandler} by its name or its alias.
+ *
* @param name name
* @return the {@code OptionHandler} or {@code null}
*/
private OptionHandler findOptionByName(String name) {
for (OptionHandler h : options) {
- NamedOptionDef option = (NamedOptionDef)h.option;
+ NamedOptionDef option = (NamedOptionDef) h.option;
if (name.equals(option.name())) {
return h;
}
@@ -667,89 +697,89 @@ private OptionHandler findOptionByName(String name) {
return null;
}
- /**
- * Returns {@code true} if the given token is an option
- * (as opposed to an argument).
- * @throws NullPointerException if {@code arg} is {@code null}.
- */
- protected boolean isOption(String arg) {
- checkNonNull(arg, "arg");
-
- return parsingOptions && arg.startsWith("-");
- }
-
- /**
- * Registers a user-defined {@link OptionHandler} class with args4j.
- *
- *
- * This method allows users to extend the behavior of args4j by writing
- * their own {@link OptionHandler} implementation.
- *
- * @param valueType
- * The specified handler is used when the field/method annotated by {@link Option}
- * is of this type.
- * @param handlerClass
- * This class must have the constructor that has the same signature as
- * {@link OptionHandler#OptionHandler(CmdLineParser, OptionDef, Setter)}
- * @throws NullPointerException if {@code valueType} or {@code handlerClass} is {@code null}.
- * @throws IllegalArgumentException if {@code handlerClass} is not a subtype of {@code OptionHandler}.
- * @deprecated You should use {@link OptionHandlerRegistry#registerHandler(java.lang.Class, java.lang.Class)} instead.
- */
- public static void registerHandler( Class valueType, Class extends OptionHandler> handlerClass ) {
- checkNonNull(valueType, "valueType");
- checkNonNull(handlerClass, "handlerClass");
-
- OptionHandlerRegistry.getRegistry().registerHandler(valueType, handlerClass);
- }
-
- /**
- * Sets the width of the usage output.
- * @param usageWidth the width of the usage output in columns.
- * @throws IllegalArgumentException if {@code usageWidth} is negative
- * @deprecated
- * Use {@link ParserProperties#withUsageWidth(int)} instead.
- */
+ /**
+ * Returns {@code true} if the given token is an option
+ * (as opposed to an argument).
+ *
+ * @throws NullPointerException if {@code arg} is {@code null}.
+ */
+ protected boolean isOption(String arg) {
+ checkNonNull(arg, "arg");
+
+ return parsingOptions && arg.startsWith("-");
+ }
+
+ /**
+ * Registers a user-defined {@link OptionHandler} class with args4j.
+ *
+ *
+ * This method allows users to extend the behavior of args4j by writing
+ * their own {@link OptionHandler} implementation.
+ *
+ * @param valueType The specified handler is used when the field/method annotated by {@link Option}
+ * is of this type.
+ * @param handlerClass This class must have the constructor that has the same signature as
+ * {@link OptionHandler#OptionHandler(CmdLineParser, OptionDef, Setter)}
+ * @throws NullPointerException if {@code valueType} or {@code handlerClass} is {@code null}.
+ * @throws IllegalArgumentException if {@code handlerClass} is not a subtype of {@code OptionHandler}.
+ * @deprecated You should use {@link OptionHandlerRegistry#registerHandler(java.lang.Class, java.lang.Class)}
+ * instead.
+ */
+ public static void registerHandler(Class valueType, Class extends OptionHandler> handlerClass) {
+ checkNonNull(valueType, "valueType");
+ checkNonNull(handlerClass, "handlerClass");
+
+ OptionHandlerRegistry.getRegistry().registerHandler(valueType, handlerClass);
+ }
+
+ /**
+ * Sets the width of the usage output.
+ *
+ * @param usageWidth the width of the usage output in columns.
+ * @throws IllegalArgumentException if {@code usageWidth} is negative
+ * @deprecated Use {@link ParserProperties#withUsageWidth(int)} instead.
+ */
public void setUsageWidth(int usageWidth) {
- parserProperties.withUsageWidth(usageWidth);
+ parserProperties.withUsageWidth(usageWidth);
}
- /**
- * Signals the parser that parsing the options has finished.
- *
- *
- * Everything seen after this call is treated as an argument
- * as opposed to an option.
- */
+ /**
+ * Signals the parser that parsing the options has finished.
+ *
+ *
+ * Everything seen after this call is treated as an argument
+ * as opposed to an option.
+ */
public void stopOptionParsing() {
parsingOptions = false;
}
- /**
- * Prints a single-line usage to the screen.
- *
- *
- * This is a convenience method for calling {@code printUsage(new OutputStreamWriter(out),null)}
- * so that you can do {@code printUsage(System.err)}.
- * @throws NullPointerException if {@code out} is {@code null}.
- */
+ /**
+ * Prints a single-line usage to the screen.
+ *
+ *
+ * This is a convenience method for calling {@code printUsage(new OutputStreamWriter(out),null)}
+ * so that you can do {@code printUsage(System.err)}.
+ *
+ * @throws NullPointerException if {@code out} is {@code null}.
+ */
public void printSingleLineUsage(OutputStream out) {
- checkNonNull(out, "OutputStream");
-
+ checkNonNull(out, "OutputStream");
+
printSingleLineUsage(new OutputStreamWriter(out), null);
}
- /**
- * Prints a single-line usage to the screen.
- *
- * @param rb
- * if this is non-{@code null}, {@link Option#usage()} is treated
- * as a key to obtain the actual message from this resource bundle.
- * @throws NullPointerException if {@code w} is {@code null}.
- */
- // TODO test this!
+ /**
+ * Prints a single-line usage to the screen.
+ *
+ * @param rb if this is non-{@code null}, {@link Option#usage()} is treated
+ * as a key to obtain the actual message from this resource bundle.
+ * @throws NullPointerException if {@code w} is {@code null}.
+ */
+ // TODO test this!
public void printSingleLineUsage(Writer w, ResourceBundle rb) {
- checkNonNull(w, "Writer");
-
+ checkNonNull(w, "Writer");
+
PrintWriter pw = new PrintWriter(w);
for (OptionHandler h : arguments) {
printSingleLineOption(pw, h, rb);
@@ -762,13 +792,15 @@ public void printSingleLineUsage(Writer w, ResourceBundle rb) {
private void printSingleLineOption(PrintWriter pw, OptionHandler h, ResourceBundle rb) {
pw.print(' ');
- if (!h.option.required())
+ if (!h.option.required()) {
pw.print('[');
+ }
pw.print(h.getNameAndMeta(rb, parserProperties));
if (h.option.isMultiValued()) {
pw.print(" ...");
}
- if (!h.option.required())
+ if (!h.option.required()) {
pw.print(']');
+ }
}
}
diff --git a/args4j/src/org/kohsuke/args4j/ParserProperties.java b/args4j/src/org/kohsuke/args4j/ParserProperties.java
index ec6669c6..cdd7c2cc 100644
--- a/args4j/src/org/kohsuke/args4j/ParserProperties.java
+++ b/args4j/src/org/kohsuke/args4j/ParserProperties.java
@@ -18,6 +18,7 @@ public class ParserProperties {
private String optionValueDelimiter=" ";
private boolean atSyntax = true;
private boolean showDefaults = true;
+ private boolean ignoreUndefinedOptions = false;
private ParserProperties() {
}
@@ -129,7 +130,19 @@ public ParserProperties withOptionValueDelimiter(String v) {
return this;
}
- public String getOptionValueDelimiter() {
+ public boolean isIgnoreUndefinedOptions() {
+ return ignoreUndefinedOptions;
+ }
+
+ public ParserProperties withIgnoreUndefinedOptions(boolean b){
+ this.ignoreUndefinedOptions = b;
+ return this;
+
+ }
+
+
+
+ public String getOptionValueDelimiter() {
return this.optionValueDelimiter;
}
diff --git a/args4j/test/org/kohsuke/args4j/IgnoreUndefinedOptionsDisabledTest.java b/args4j/test/org/kohsuke/args4j/IgnoreUndefinedOptionsDisabledTest.java
new file mode 100644
index 00000000..658c48ca
--- /dev/null
+++ b/args4j/test/org/kohsuke/args4j/IgnoreUndefinedOptionsDisabledTest.java
@@ -0,0 +1,41 @@
+package org.kohsuke.args4j;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+
+public class IgnoreUndefinedOptionsDisabledTest extends Args4JTestBase {
+
+ @Option(name = "-one")
+ public String one;
+
+ @Option(name = "-two")
+ public String two;
+
+
+ @Override
+ public IgnoreUndefinedOptionsDisabledTest getTestObject() {
+ return this;
+ }
+
+
+ protected CmdLineParser createParser() {
+ ParserProperties parserProperties = ParserProperties.defaults();
+ parserProperties.withIgnoreUndefinedOptions(false);
+ return new CmdLineParser(testObject, parserProperties);
+ }
+
+
+ public void test() {
+
+ try {
+ parser.parseArgument("-one", "value_one", "-two", "value_two", "-three", "value_three");
+ Assert.fail("Undefined option '-three' should cause CmdLineException");
+ } catch (CmdLineException e) {
+ //This exception is expected
+ }
+
+
+ }
+
+}
diff --git a/args4j/test/org/kohsuke/args4j/IgnoreUndefinedOptionsEnabledTest.java b/args4j/test/org/kohsuke/args4j/IgnoreUndefinedOptionsEnabledTest.java
new file mode 100644
index 00000000..b62ce257
--- /dev/null
+++ b/args4j/test/org/kohsuke/args4j/IgnoreUndefinedOptionsEnabledTest.java
@@ -0,0 +1,41 @@
+package org.kohsuke.args4j;
+
+import org.junit.Assert;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+
+
+public class IgnoreUndefinedOptionsEnabledTest extends Args4JTestBase{
+
+ @Option(name = "-one")
+ public String one;
+
+ @Option(name = "-two")
+ public String two;
+
+
+ @Override
+ public IgnoreUndefinedOptionsEnabledTest getTestObject() {
+ return this;
+ }
+
+
+ protected CmdLineParser createParser() {
+ ParserProperties parserProperties = ParserProperties.defaults();
+ parserProperties.withIgnoreUndefinedOptions(true);
+ return new CmdLineParser(testObject, parserProperties);
+ }
+
+
+ public void test(){
+
+
+ try {
+ parser.parseArgument("-one", "value_one", "-two", "value_two", "-three", "value_three");
+ } catch (CmdLineException e) {
+ Assert.fail(e.getMessage());
+ }
+
+ }
+
+}