Skip to content

CommandLineOptions

Jordan Samhi edited this page Oct 25, 2026 · 3 revisions

CommandLineOptions

com.jordansamhi.androspecter.commandlineoptions.CommandLineOptions wraps Apache Commons CLI with caller-owned parser instances and immutable results. In the 2.0.0 API, parsing does not print help or exit the JVM. The executable decides how to display errors and help and what exit status to use.

This is an optional utility for applications built with AndroSpecter. It does not define a built-in analyzer command or make the library JAR executable.

Parse and handle the result

This complete utility class declares one required path option and one optional flag. Its run method returns a status to its caller; it does not terminate the process or launch an analysis.

import com.jordansamhi.androspecter.commandlineoptions.CommandLineOption;
import com.jordansamhi.androspecter.commandlineoptions.CommandLineOptions;
import java.io.PrintStream;

public final class CommandLineExample {
    /**
     * Parses an application's arguments and reports the selected input.
     * @param args command-line arguments supplied by the application
     * @param out destination for help and accepted input
     * @param err destination for validation errors
     * @return 0 for help or valid input, 2 for invalid input
     */
    public static int run(String[] args, PrintStream out, PrintStream err) {
        CommandLineOptions options = new CommandLineOptions("my-analysis-tool");
        options.addOption(new CommandLineOption(
            "apk", "a", "APK file to analyze", true, true));
        options.addOption(new CommandLineOption(
            "verbose", "v", "Enable application verbosity", false, false));

        try {
            CommandLineOptions.ParseResult parsed = options.parse(args);
            if (parsed.helpRequested()) {
                out.print(parsed.helpText());
                return 0;
            }
            if (!parsed.arguments().isEmpty()) {
                err.println("Unexpected positional arguments: " + parsed.arguments());
                err.print(parsed.helpText());
                return 2;
            }
            out.println("APK: " + parsed.getOptionValue("apk"));
            out.println("Verbose: " + parsed.hasOption("verbose"));
            return 0;
        } catch (CommandLineOptions.ValidationException ex) {
            err.println(ex.getMessage());
            err.print(options.helpText());
            return 2;
        }
    }
}

The caller can invoke CommandLineExample.run(args, System.out, System.err) from its own entry point. Successful parsing validates the argument structure, not the file's existence or the APK's contents. A verbosity flag is only parsed data; the application must decide what it changes.

The parser already includes -h / --help. Do not register another help option: the aliases h and help are reserved.

Parsing rules

  • Required options must be present unless a genuine help flag was parsed. --help alone is therefore valid even with required options.
  • Unknown options and missing argument values still produce ValidationException, including alongside help.
  • Long-option abbreviations are disabled: use the complete registered alias.
  • Tokens after -- are positional arguments. -- --help does not request help. An option value such as --input=--help is also a value, not a help request, when input is a registered value-taking option.
  • parse(...) rejects a null argument array and null elements with ValidationException.
  • Positional arguments are returned rather than rejected automatically. The example above chooses to reject them in application code.

Read immutable results

ParseResult method Meaning
helpRequested() Whether the help option was present
helpText() Formatted help captured at parse time
hasOption(alias) Presence of a short or long alias, without leading hyphens
getOptionValue(alias) The argument, or null for a flag, absent option, or unknown alias
arguments() Immutable positional arguments in input order

Use hasOption(...) for flags; their value is null even when present. Repeated value options retain the first value. Later parses, parser resets, and descriptor edits do not change an already returned ParseResult.

Configure an instance

new CommandLineOptions("tool-name") is ready for option registration and parsing. The no-argument constructor requires setAppName(...) before parse(...) or helpText(); missing names produce IllegalStateException, and null or blank names are rejected.

addOption(...) copies a CommandLineOption declaration and rejects duplicate or reserved aliases. Subsequent descriptor changes do not reconfigure the registered option. Each parser is independent; configure and use it on one thread.

reset() removes registered options, clears the latest parsed state, and unsets the application name. The built-in help option remains. Set the name again before parsing.

Legacy migration

CommandLineOptions.v(), parseArgs(...), and parser-level value getters remain deprecated compatibility APIs. The singleton shares mutable state. parseArgs(...) now behaves like parse(...): help does not print, and errors throw instead of exiting. If retaining it temporarily, inspect isHelpRequested() and helpText() and catch ValidationException explicitly.

Each parse attempt clears legacy values, even when parsing fails. Successful parses also update the original descriptors' legacy value fields. New code should keep the immutable result instead of reading shared parser or descriptor state.

See Cancellation and logging for the rest of the caller-owned execution policy. Runnable APK examples have their own entry points and argument contracts in the examples README.

Clone this wiki locally