A worked example: the Cat command.

(This example is based on material provided by gchii)

The cat command is a JNode file system command for the concatenation of files.
The alternative command line syntaxes for the command are as follows:

 cat 
 cat -u | -urls <url> ... |
 cat <file> ... 

The simplest use of cat is to copy a file to standard output displaying the contents of a file; for example.

 cat d.txt

The following example displays a.txt, followed by b.txt and then c.txt.

 cat a.txt b.txt c.txt

The following example concatenates a.txt, b.txt and c.txt, writing the resulting file to d.txt.

 cat a.txt b.txt c.txt > d.txt

In fact, the > output redirection in the example above is performed by the command shell and interpreter, and the "> d.txt" arguments are removed before the command arguments are processed. As far the command class is concerned, this is equivalent to the previous example.

Finally, the following example displays the raw HTML for the JNode home page:
cat --urls http ://www.jnode.org/

Syntax specification
The syntax for the cat command is defined in fs/descriptors/org.jnode.fs.command.xml.

The relevant section of the document is as follows:

   39   <extension point="org.jnode.shell.syntaxes">
   40     <syntax alias="cat">
   41       <empty description="copy standard input to standard output"/>
   42       <sequence description="fetch and concatenate urls to standard output">
   43         <option argLabel="urls" shortName="u" longName="urls"/>
   44         <repeat minCount="1">
   45           <argument argLabel="url"/>
   46         </repeat>
   47       </sequence>
   48       <repeat minCount="1" description="concatenate files to standard output">
   49         <argument argLabel="file"/>
   50       </repeat>
   51     </syntax>

Line 39: "org.jnode.shell.syntaxes" is an extension point for command syntax.

Line 40: The syntax entity represents the entire syntax for a command. The alias attribute is required and associates a syntax with a command.

Line 41: When parsing a command line, the empty tag does not consume arguments. This is a description of the cat command.

Line 42: A sequence tag represents a group of options and arguments, and others.

Line 43: An option tag is a command line option, such as -u and --urls. Since -u and --urls are actually one and the same option, the argLable attribute identifies an option internally.

Line 44: An option might be used more than once on a command line. When minCount is one or more, an option is required.

Line 45: An argument tag consumes one command line argument.

Line 48: When minCount is 1, an option is required.

Line 49: An argument tag consumes one command line argument.

The cat command is implemented in CatCommand.java. The salient parts of the command's implementation are as follows.

   54     private final FileArgument ARG_FILE =
   55         new FileArgument("file", Argument.OPTIONAL | Argument.MULTIPLE,
   56                 "the files to be concatenated");

This declares a formal argument to capture JNode file/directory pathnames from the command line; see the specification of the org.jnode.shell.syntax.FileArgument. The "Argument.OPTIONAL | Argument.MULTIPLE" parameter gives the argument flags. Argument.OPTIONAL means that this argument may be optional in the syntax. The Argument.MULTIPLE means that the argument may be repeated in the syntax. Finally, the "file" label matches the "file" attribute in the XML above at line 49.

   58     private final URLArgument ARG_URL =
   59         new URLArgument("url", Argument.OPTIONAL | Argument.MULTIPLE,
   60                 "the urls to be concatenated");

This declares a formal argument to capture URLs from the command line. This matches the "url" attribute in the XML above at line 45.

   62     private final FlagArgument FLAG_URLS =
   63         new FlagArgument("urls", Argument.OPTIONAL, "If set, arguments will be urls");

This declares a formal flag that matches the "urls" attribute in the XML above at line 43.

   67     public CatCommand() {
   68         super("Concatenate the contents of files, urls or standard input to standard output");
   69         registerArguments(ARG_FILE, ARG_URL, FLAG_URLS);
   70     }

The constructor for the CatCommand registers the three formal arguments, ARG_FILE, ARG_URL and FLAG_URLS. The registerArguments() method is implemented in AbstractCommand.java. It simply adds the formal arguments to the command's ArgumentBundle, making them available to the syntax mechanism.

   79     public void execute() throws IOException {
   80         this.err = getError().getPrintWriter();
   81         OutputStream out = getOutput().getOutputStream();
   82         File[] files = ARG_FILE.getValues();
   83         URL[] urls = ARG_URL.getValues();
   84 
   85         boolean ok = true;
   86         if (urls != null && urls.length > 0) {
   87             for (URL url : urls) {
   ...
  107         } else if (files != null && files.length > 0) {
  108             for (File file : files) {
   ...
  127         } else {
  128             process(getInput().getInputStream(), out);
  129         }
  130         out.flush();
  131         if (!ok) {
  132             exit(1);
  133         }
  134     }

The "execute" method is called after the syntax processing has occurred, and after the command argument values have been converted to the relevant Java types and bound to the formals. As the code above shows, the method uses a method on the formal argument to retrieve the actual values. Other methods implemented by AbstractCommand allow the "execute" to access the command's standard input, output and error streams as Stream objects or Reader/Writer objects, and to set the command's return code.

Note: ideally the syntax of the JNode cat command should include this alternative:

 cat ( ( -u | -urls <url> ) | <file> ) ...

or even this:

 cat ( <url> | <file> ) ...

allowing <file> and <url&gt arguments to be interspersed. The problem with the first alternative syntax above is that the Argument objects do not allow the syntax to capture the complete order of the interspersed <file> and <url> arguments. In order to support this, we would need to replace ARG_FILE and ARG_URL with a suitably defined ARG_FILE_OR_URL. The problem with the second alternative syntax above is some legal <url> values are also legal <file> values, and the syntax does not allow the user to control the disambiguation.

For more information, see also org.jnode.fs.command.xml - http://jnode.svn.sourceforge.net/viewvc/jnode/trunk/fs/descriptors/org.j... .

CatCommand.java - http://jnode.svn.sourceforge.net/viewvc/jnode/trunk/fs/src/fs/org/jnode/...