Why default parser (using commons-cli) does not throw exception when option is not recognized?

丶灬走出姿态 提交于 2019-12-24 10:38:14

问题


I would like to have a printed usage help message, when option which is specified as an program argument is not valid (not available in predefined options list).

      CommandLineParser parser = new BasicParser();
    try {
        CommandLine line = parser.parse(getOptions(), args);
    }
    catch( ParseException exp ) {
        getLogger().info("Invalid command line option name. "+exp.getMessage());
        HelpFormatter hf = new HelpFormatter();
        hf.printHelp("destDir", getOptions());
        return false;
    }       
    return true;

I type as an parameter 'Test' string. I was thinking, that invalid options cause parser to throw ParseException, however it's not. How can I achieve that behaviour ? Is it possible with this library at all ? Now it just ommit paremeters which are not valid.

UPDATE Actually it throws exception when option has a '-' prefix. So '-Test' cause throwing exception, but 'Test' not. My question anyway is still valid, how to force parser to throw exception on invalid parameter


回答1:


Command lines have two types of entry other than the program name, Options (which are specified with a - or --) and what I will call parameters (which probably have a better name but I don't know what it is!) which don't have a prefix. For example, for ls:

ls -la foo

The options are -l and -a, and parameter is foo (the directory to list). When you parse a command line with commons-cli it only cares about the options, it ignores everything else. Which is why it doesn't fail if you add Test (not an option) but does if you add -Test.




回答2:


Although answer provided by adamreeve is really fine and I accept it, I've decided to extend default parser capabilities to prevent typing invalid option even without '-' or '--' symbols. I made my own custom parser :

public class StrictParser extends Parser {

    @Override
    protected String[] flatten(Options opts, String[] arguments, boolean stopAtNonOption) {
        return arguments;
    }

    @Override
    public CommandLine parse(Options options, String[] arguments, boolean stopAtNonOption) throws ParseException {

        CommandLine cmd = null;
        List<String> tokenList = Arrays.asList(flatten(getOptions(), arguments, stopAtNonOption));
        ListIterator<String> iterator = tokenList.listIterator();

        boolean eatTheRest = false;
        setOptions(options);
        cmd = super.parse(options, arguments, stopAtNonOption);

        while (iterator.hasNext()) {
            String token = (String) iterator.next();
            if (!token.startsWith("--") && !token.startsWith("-")) {
                if (stopAtNonOption) {
                        throw new UnrecognizedOptionException("Unrecognized option: " + token +". Every option must start with '--' or '-'", token);
                }
            } else {
                eatTheRest = true;
            }

            if (eatTheRest) {
                iterator.next();
            }
        }
        return cmd;
    }
}

In this solution any cli parameters typed without '--' or '-' throw UnrecognizedOptionException. This is no perfect solution, but it show how it can be done, and can be a good starting point to other solutions. For instance we could accept options without '--' and '-' but check if that option is correct. Then we need to change

        if (stopAtNonOption) {
                throw new UnrecognizedOptionException("Unrecognized option: " + token +". Every option must start with '--' or '-'", token);
        }

to

        if (stopAtNonOption) {                  
            if(!getOptions().hasOption(token)){                     
                throw new UnrecognizedOptionException(
                        "Unrecognized option: " + token, token);
            }
        }

(ignore this ugly three nested ifs ;)) This also accepts only one argument per option,but as I've mentioned it's only starting point to implement other modifications to default parser




回答3:


Yes you can , you have to create custom Exception like:

public class ParseException extends Exception{
        ParseException(String msg){
             super(msg);  
        }
}

And into code :

CommandLineParser parser = new BasicParser();
    try {
        CommandLine line = parser.parse(getOptions(), args);
    }
    catch( Exception exp ) {
       throw new ParseException("Invalid Arguments");
    }       
    return true;

And above method should throw

throws ParseException

So its caller if pass invalid argument will get ParseException



来源:https://stackoverflow.com/questions/40082191/why-default-parser-using-commons-cli-does-not-throw-exception-when-option-is-n

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!