View Javadoc

1   package fr.in2p3.jsaga.command;
2   
3   import org.apache.commons.cli.*;
4   
5   import java.io.ByteArrayOutputStream;
6   import java.io.PrintWriter;
7   import java.util.ArrayList;
8   import java.util.List;
9   
10  /* ***************************************************
11  * *** Centre de Calcul de l'IN2P3 - Lyon (France) ***
12  * ***             http://cc.in2p3.fr/             ***
13  * ***************************************************
14  * File:   AbstractCommand
15  * Author: Sylvain Reynaud (sreynaud@in2p3.fr)
16  * Date:   12 ao�t 2007
17  * ***************************************************
18  * Description:                                      */
19  /**
20   *
21   */
22  public abstract class AbstractCommand {
23      private String m_appName;
24      private Options m_options;
25      private String[] m_nonOptionNames;
26      private String[] m_standaloneOptionNames;
27      private Parser m_parser;
28      protected String[] m_nonOptionValues;
29  
30      protected abstract Options createOptions();
31  
32      /**
33       * @param appName the application name
34       * @param nonOptionNames the names of non-options (required if <code>standaloneOptionNames</code> not null)
35       * @param standaloneOptionNames the names of standalone options (i.e. options that do not require non-options)
36       * @param parser the command line parser
37       */
38      protected AbstractCommand(String appName, String[] nonOptionNames, String[] standaloneOptionNames, Parser parser) {
39          m_appName = appName;
40          m_options = this.createOptions();
41          m_nonOptionNames = nonOptionNames;
42          m_standaloneOptionNames = standaloneOptionNames;
43          m_parser = (parser!=null ? parser : new PosixParser());
44          m_nonOptionValues = null;
45      }
46  
47      protected AbstractCommand(String appName, String[] nonOptionNames, String[] standaloneOptionNames) {
48          this(appName, nonOptionNames, standaloneOptionNames, null);
49      }
50  
51      protected AbstractCommand(String appName) {
52          this(appName, null, null, null);
53      }
54  
55      protected CommandLine parse(String[] args) {
56          // update args
57          List list = new ArrayList();
58          for (int i=0; args!=null && i<args.length; i++) {
59              String[] array;
60              if (args[i]!=null && args[i].startsWith("-D") && (array=args[i].split("=")).length<=2) {
61                  String name = array[0].substring(2);
62                  String value = array.length==2 ? array[1] : "";
63                  System.setProperty(name, value);
64              } else {
65                  list.add(args[i]);
66              }
67          }
68          String[] newArgs = (args!=null && list.size()!=args.length
69                  ? (String[]) list.toArray(new String[list.size()])
70                  : args);
71  
72          // parse
73          try {
74              boolean stopAtNonOption = (m_nonOptionNames==null || m_nonOptionNames.length==0);
75              CommandLine line = m_parser.parse(m_options, newArgs, stopAtNonOption);
76              m_nonOptionValues = line.getArgs();
77              if (m_nonOptionNames!=null && m_nonOptionValues.length>m_nonOptionNames.length) {
78                  throw new UnrecognizedOptionException("Unexpected option: "+ m_nonOptionValues[m_nonOptionNames.length]);
79              } else if (m_standaloneOptionNames!=null && m_nonOptionValues.length<m_nonOptionNames.length && !this.hasStandaloneOption(line)) {
80                  throw new MissingOptionException("Missing option: "+m_nonOptionNames[m_nonOptionValues.length]);
81              } else {
82                  return line;
83              }
84          } catch(ParseException e) {
85              printHelpAndExit(e.getMessage());
86              return null;
87          }
88      }
89      private boolean hasStandaloneOption(CommandLine line) {
90          for (int i=0; m_standaloneOptionNames!=null && i<m_standaloneOptionNames.length; i++) {
91              if (line.hasOption(m_standaloneOptionNames[i])) {
92                  return true;
93              }
94          }
95          return false;
96      }
97  
98      protected void printHelpAndExit(String errorMessage) {
99          if (errorMessage != null) {
100             System.err.println(errorMessage);
101             System.err.println();
102             this.printHelp();
103             System.exit(1);
104         } else {
105             this.printHelp();
106             System.exit(0);
107         }
108     }
109     private void printHelp() {
110         HelpFormatter help = new HelpFormatter();
111 
112         // build usage
113         ByteArrayOutputStream usage = new ByteArrayOutputStream();
114         PrintWriter writer = new PrintWriter(usage);
115         help.printUsage(
116                 writer,
117                 HelpFormatter.DEFAULT_WIDTH,
118                 m_appName,
119                 m_options);
120         writer.flush();
121 
122         // print usage and help
123         writer = new PrintWriter(System.out);
124         writer.write(usage.toString(), 0, usage.size()-2);
125         printNonOptionNames(writer, 0);
126         writer.println();
127         writer.println();
128         writer.println("where:");
129         help.printOptions(
130                 writer,
131                 HelpFormatter.DEFAULT_WIDTH,
132                 m_options,
133                 HelpFormatter.DEFAULT_LEFT_PAD,
134                 HelpFormatter.DEFAULT_DESC_PAD);
135         writer.flush();
136     }
137     private void printNonOptionNames(PrintWriter writer, int current) {
138         if (m_nonOptionNames!=null && current<m_nonOptionNames.length) {
139             if (m_standaloneOptionNames != null) {
140                 writer.print(" <"+m_nonOptionNames[current]+">");
141             } else {
142                 writer.print(" [<"+m_nonOptionNames[current]+">");
143                 printNonOptionNames(writer, current+1);
144                 writer.print("]");
145             }
146         }
147     }
148 }