jcmdline Package User Guide Release 2.0.0

Introduction
Obtaining this Document
Some Semantics
Quick Start
      Define The Parameters
      Create a CmdLineHandler
      Parse the Command Line
      Access the Processed Parameters
Parameters
      When Supplied Parameters Are Not Adequate
            Post-processing Parameters
            Creating Custom Parameter Classes
Command Line Handlers
      Parsers
            The PosixCmdLineParser
            Usage Formatters
      CmdLineHandler Decorators
      Writing CmdLineHandler Decorators
Best Practices Suggestions

[toc]

Introduction

The jcmdline package contains classes used to parse and process command line options and arguments from a Java program. This package was written with the following goals:

[toc]

Obtaining this Document

The most current version of this user guide is supplied in the doc-files directory for the jcmdline package. It is accessible from a link in the Description section of the package summary of the jcmdline API javadoc and/or may be downloaded with the source files.

[toc]

Some Semantics

Throughout this document, the following semantics are used.
option
A command line option is comprised of an identifying "tag", typically preceded by a dash or two, and optionally requires a value. A typical option might be "-outfile /tmp/myfile".
argument
A command line argument is specified on the command line after all of the options and their values.
parameter
A command line parameter is an option or an argument.
For instance:
    javadoc -d /home/html -sourcepath /home/src java.awt
            \__________          _____________/ \      /
                         options                arguments
            \______________             _______________/
                             parameters

[toc]

Quick Start

Using the jcmdline package requires the following steps:

[toc]

Define The Parameters

For this example, set up some parameters for a program that will work sort of like the Unix "grep" command:
    public static void main(String[] args) {

        // command line arguments
        StringParam patternArg =
            new StringParam("pattern", "the pattern to match",
                            StringParam.REQUIRED);
        FileParam filesArg =
            new FileParam("file",
                          "a file to be processed - defaults to stdin",
                          FileParam.IS_FILE & FileParam.IS_READABLE,
                          FileParam.OPTIONAL,
                          FileParam.MULTI_VALUED);

        // command line options
        BooleanParam ignorecaseOpt =
            new BooleanParam("ignoreCase", "ignore case while matching");
        BooleanParam listfilesOpt = 
            new BooleanParam("listFiles", "list filenames containing pattern");

        // a help text because we will use a HelpCmdLineHandler so our
        // command will display verbose help with the -help option
        String helpText = "This command prints to stdout all lines within " +
                          "the specified files that contain the specified " +
                          "pattern.\n\n" + 
                          "Optionally, the matching may be done without " +
                          "regard to case (using the -ignorecase option).\n\n" +                          
                          "If the -listFiles option is specified, only the " + 
                          "names of the files containing the pattern will be " +                 
                          "listed.  In this case, files to process must be " +
                          "specified on the command line";

[toc]

Create a CmdLineHandler

Next a CmdLineHandler is instantiated to process the command line:
        CmdLineHandler cl =
            new VersionCmdLineHandler("V 5.2",
            new HelpCmdLineHandler(helpText,
                "kindagrep",
                "find lines in files containing a specified pattern",
                new Parameter[] { ignorecaseOpt, listfilesOpt },
                new Parameter[] { patternArg, filesArg } ));
The CmdLineHandler used here uses some supplied Decorators to provide some typical options. The options supported by this CmdLineHandler, in addition to those defined by the program itself are: -h, -?, -h!, -help, -help!, -version (see the information on hidden parameters for the h! and help! options)..

[toc]

Parse the Command Line

Now parse the command line:
        cl.parse(args);
The parse() method will not return if the command line does not validate - instead the command usage and an error message will be displayed and the program will exit with exit status = 1 (an option may be specified to the CmdLineHandler to modify this behavior to throw an exception instead, if desired).

The usage and error message displayed when a non-existent file is specified is:

kindagrep - find lines in files containing a specified pattern

Usage: kindagrep [options] pattern [file],[file]...

where:

pattern = the pattern to match (required)
file    = a file to be processed - defaults to stdin (optional)

and options are:

-?           prints usage to stdout; exits (optional)
-h           prints usage to stdout; exits (optional)
-help        displays verbose help information (optional)
-ignoreCase  ignore case while matching (optional)
-listFiles   list filenames containing pattern (optional)
-version     displays command's version (optional)

Option tags are not case sensitive, and may be truncated as long as they remain
unambiguous.  Option tags must be separated from their corresponding values by
whitespace, or by an equal sign.  Boolean options (options that require no
associated value) may be specified alone (=true), or as 'tag=value' where value
is 'true' or 'false'.

ERROR: Invalid name (nosuchfile) specified for <file>, must be an existing,
       readable, file.

[toc]

Access the Processed Parameters

Following the call to the CmdLineHandler, it can be assumed that: The program can now access the processed parameters and their values:
        // this can't be check by CmdLineHandler
        if (listfilesOpt.isTrue() && ! filesArg.isSet()) {
            cl.exitUsageError(
                "filename(s) must be specified with -listFiles option");
        }

        String pattern = patternArg.getValue();

        if (filesArg.isSet()) {
            for (File f : filesArg.getValues()) { 
                findPattern(pattern, new FileInputStream(f), listfilesOpt.isTrue());
            }
        } else {
            findPattern(pattern, System.in, false);
        }
Note that the relationship between the listfilesOpt and filesArg is not checked by the CmdLineHandler, but must be checked explicitly. The exitUsageError() method of the CmdLineHandler is then used to display the usage and error message in case of error.

[toc]

Parameters

All command line options and arguments are represented by Parameter objects. All parameters support the following characteristics:
tag The tag is used to identify the parameter.

For options, the tag indicates how the option is specified, for instance, a tag of "outfile" indicates an option specified like "-outfile /tmp/myfile".

For command line arguments, the tag is typically used by the usage display formatter to identify the argument.

description The description is used by the usage display formatter to describe a parameter.
optional indicator The optional indicator indicates whether a parameter is optional or required. If a parameter is configured to be required, the CmdLineHandler will reject the command line if the parameter is not specified.
multi-valued A parameter that is multi-valued can be specified more than once. This is frequently used with the final command line argument when the command accepts multiple instances. The above example demonstrates this type of usage.
acceptable values Most Parameter types allow the programmer to specify a set of values that the parameter will accept. The command line is rejected if a user attempts to set the parameter to any non-specified value.
hidden indicator The hidden indicator is used to indicate whether a parameter is hidden or public. By default, all paramters are public, meaning that they will be described in a regular usage statement.

Optionally, a parameter may be designated hidden, in which case it may still be specified by the user, but is not displayed in a normal usage statement. Who has not shipped code supporting "debug" or "trace" options that might be performance impacting and thus not be suitable for publication to the casual user? This indicator is for that type of option.

Both the DefaultCmdLineHandler and HelpCmdLineHandler support (hidden) command line options that will cause hidden options and help to be displayed.

The jcmdline package comes with Parameter classes to handle several types of common parameters. See the list of subclasses for AbstractParameter for a complete list. As of this writing, the following Parameter classes are available:

StringParam handles generic string parameters - can be used for any parameter for which a more specific class does not exist
FileParam handles filename parameters
IntParam handles numeric integer parameters
BooleanParam handles boolean parameters
DateTimeParam handles parameters consisting of a date and time
DateParam handles parameters consisting of a date only
TimeParam handles parameters consisting of a time only

If an application supports several different commands, more than one of which accepts a new and different type of Parameter, it is strongly suggested that a new subclass of AbstractParameter be written to handle that type. This will provide greater consistency amongst the commands in the application.

[toc]

When Supplied Parameters Are Not Adequate

It may sometimes be the case that the Parameter classes supplied by the jcmdline package cannot completely validate a parameter. For instance, perhaps a command line parameter must not only be a readable file, but it must also be a file whose name ends in ".html". For cases where the supplied parameters just don't quite do it, there are a couple of options:

[toc]

Post-processing Parameters

The CmdLineHandler interface supports a method, exitUsageError(), that can be used to exit the program, displaying the usage, just as it would have been exited if an error had been detected during the parse. This method should be called if there is an error when a parameter is post-processed.

The following code snippet demonstrates use of the exitUsageError() method when a filename parameter is validated to end with ".html" after the command line is parsed by the CmdLineHandler:

    cl.parse(args);
    if (! myfile.getFile().getPath().endsWith(".html")) {
        cl.exitUsageError("Filename specified for '" +
                          myfile.getTag() + "' must end with '.html'");
    }

[toc]

Creating Custom Parameter Classes

If an application requires custom parameter validation in more than one place, it would be better to create a custom Parameter class to handle the validation. A template type of class, AbstractParameter, has been provided to make this easier. Instructions for how to use this class to create a custom Parameter class are in the javadoc for the class.

[toc]

Command Line Handlers

The CmdLineHandler classes control the parsing and validation of command line parameters. This package comes with one basic CmdLineHandler, named, coincidentally, BasicCmdLineHandler .

Although the BasicCmdLineHandler is, technically, the only "real" command line handler supplied by this package, there are several "decorator" command line handlers that can be used to add functionality. Typically, a program will use one or more of these "decorator" classes when making use of this package.

The CmdLineHandler performs the following functions:

[toc]

Parsers

A CmdLineHandler uses a CmdLineParser to perform the actual parsing of the command line. There is only one CmdLineParser that comes with the jcmdline package - the PosixCmdLineParser, but the capability exists for a user to create and use their own parser.

[toc]

The PosixCmdLineParser

The PosixCmdLineParser, basically, accepts options preceded by either a '-', or a '--', that may, optionally, have an associated value separated from the option "tag" by a space or an '='. Command line options end with the first parameter that does not start with a '-' or a '--', or when a '--' appears by itself as a parameter. A '--' must be used alone to signal the end of options when the first command line argument starts with a '-'.

Option tags are parsed in a case insensitive manner. Truncated option tags are accepted as long as the tag remains un-ambiguous (execpt for hidden options, whose tags must be fully specified).

A BooleanParam may be specified either without a value (in which case it is set to true), or with an '=' followed by its value. If a BooleanParam is specified more than once, the final specification takes precedence.

Using the PosixCmdLineParser, the following command lines are all equivalent:

java Concat -delete -out myoutfile infile1 infile2
java Concat -d -o myoutfile infile1 infile2
java Concat -delete=true -o myoutfile infile1 infile2
java Concat -d=true -o=myoutfile infile1 infile2
java Concat -Delete -OUT myoutfile infile1 infile2
See the API for PosixCmdLineParser for a more complete description.

[toc]

Usage Formatters

A CmdLineParser is configured with a UsageFormatter that it uses to format command usage and error messages. The only UsageFormatter that comes with the jcmdline package is the TextUsageFormatter, but the option is there for a user to define their own.

[toc]

CmdLineHandler Decorators

A Decorator, or Wrapper, pattern has been set up to facilitate the implementation of options whose processing can take place entirely at option parse time. This pattern was chosen in order that programmers can mix and match options that seem useful to their particular applications. It works, basically, as follows:

Because each "decorator" class implements the CmdLineHandler interface, and each accepts a CmdLineHandler as its base handler at construction, "decorator" classes can be "nested".

CmdLineHandler decorator classes that are supplied with the jcmdline package include the following. All of these classes take their option tags from a resource bundle. The values defined for English are used in the descriptions.

DefaultCmdLineHandler A CmdLineHandler that implements options that will cause command usage to be displayed. The option tags are "-h" or "-?" to display regular usage, "-h!" to display a usage that includes hidden parameters.
HelpCmdLineHandler A CmdLineHandler that implements options that will cause command usage and a more verbose help message to be displayed. The option tags are "-help" to display regular help and "-help!" to display a help text that includes hidden parameters.
VersionCmdLineHandler A CmdLineHandler that implements an option that will cause the command version to be displayed. The option tag is "-version".
LoggerCmdLineHandler A CmdLineHandler that implements an option that supports setting the logging level for the root logger and adds a StreamHandler to the root logger to manage the messages. See the java.util.logging package for information on java logging. The option tag is "-log" and it requires a value that is a valid, localized, Level string.
These classes may be used separately, or together. For instance, to use a CmdLineHandler that supports the "-h", "-?", "-h!", "-help", "-help!", and "-version" command line options, as well as any command specific options and arguments, the following would work:
public static void main(String args) {
    // define options and arguments
    .
    CmdLineHandler clh = 
        new HelpCmdLineHandler(helpText,
        new VersionCmdLineHandler(myVersion,
        new DefaultCmdLineHandler(cmdName,
                                  cmdDescription,
                                  options,
                                  args)));
    clh.parse(args);
    .
    .

[toc]

Writing CmdLineHandler Decorators

The class AbstractHandlerDecorator is supplied with the jcmdline package to facilitate the writing of CmdLineHandler decorator classes. This class implements all methods of the CmdLineHandler interface by, for the most part, delegating to a "contained" CmdLineHandler object. Using this class, a new decorator class can be created by implementing a single method and the required constructors.

The best instructions for using this class are to be found in the javadoc for AbstractHandlerDecorator, so they will not be repeated here.

[toc]

Best Practices Suggestions

Following are suggestions from the author of this package for how to get the best results, particularly when your application includes multiple executables.
Last Updated on 10/29/02
Lynne Lawrence
lgl@visuallink.com