View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.creadur.whisker.cli;
20  
21  import org.apache.commons.cli.*;
22  import org.apache.creadur.whisker.app.Act;
23  import org.apache.creadur.whisker.app.Whisker;
24  import org.apache.creadur.whisker.app.load.StreamableResourceFactory;
25  import org.apache.creadur.whisker.app.out.WriteResultsToSystemOutFactory;
26  import org.apache.creadur.whisker.out.velocity.VelocityEngine;
27  
28  /**
29   * Command line interface for whisker.
30   */
31  public final class Main {
32  
33      /**
34       * Prepended to help.
35       */
36      private static final String HELP_HEADER = "\nPass " +
37      		"the descriptor containing license meta-data " +
38      		"and the act to be done.\n";
39  
40      /**
41       * Appended to help.
42       */
43      private static final String HELP_FOOTER =
44          "\nApache Whisker assists assembled applications " +
45          "maintain correct legal documentation. " +
46          "Whisker is part of the " +
47          "Apache Creadur suite of tools for " +
48          "auditing and comprehending software distributions, " +
49          "and is open source community developed software. " +
50          "Get involved at http://www.apache.org.\n\n";
51  
52      /**
53       * Names the application.
54       */
55      private static final String APP_NAME = "apache-whisker-cli";
56  
57      /**
58       * Returns okay to system.
59       */
60      private static final int SYSTEM_EXIT_OK = 0;
61      /** Error code returned to system when parameters cannot be parsed. */
62      private static final int SYSTEM_EXIT_CLI_PARSE_FAILED = 1;
63  
64      /**
65       * Bootstraps application.
66       * @param args not null
67       * @throws Exception when application fails unexpectedly
68       */
69      public static void main(final String[] args) throws Exception {
70          System.exit(new Main(app()).run(args));
71      }
72  
73      /**
74       * Creates an instance of the application.
75       * @return not null
76       */
77      private static Whisker app() {
78          return new Whisker();
79      }
80  
81      /** The application run. */
82      private final Whisker whisker;
83  
84      /**
85       * Constructs a wrapper for the given application.
86       * @param whisker not null
87       */
88      public Main(final Whisker whisker) {
89          super();
90          this.whisker = whisker;
91      }
92  
93      /**
94       * Creates a parser for command line parameters.
95       * Use GNU-style/default style.
96       * @return not null
97       */
98      private CommandLineParser parser() {
99          return new DefaultParser();
100     }
101 
102     /**
103      * Parses a line of arguments.
104      * @param args not null
105      * @return not null
106      * @throws ParseException when parsing fails
107      */
108     public CommandLine parse(final String[] args) throws ParseException {
109         return parser().parse(options(), args);
110     }
111 
112     /**
113      * Parses arguments and configures the application.
114      * @param args not null
115      * @return not null
116      * @throws ParseException when arguments cannot be parsed
117      */
118     public Whisker configure(final String[] args) throws ParseException {
119         return configure(parse(args));
120     }
121 
122     /**
123      * Configures the application from the command line given.
124      * @param commandLine not null
125      * @return not null
126      * @throws MissingOptionException when a mandatory option
127      * has not been supplied
128      */
129     private Whisker configure(
130             final CommandLine commandLine) throws MissingOptionException {
131         whisker.setEngine(new VelocityEngine(new SystemLog()));
132         whisker.setSource(CommandLineOption.SOURCE.getOptionValue(commandLine));
133         whisker.setLicenseDescriptor(
134                 new StreamableResourceFactory().streamFromResource(
135                         licenseDescriptorName(commandLine)));
136         whisker.setWriterFactory(new WriteResultsToSystemOutFactory());
137         if (CommandLineOption.ACT_TO_AUDIT.isSetOn(commandLine)) {
138             whisker.setAct(Act.AUDIT);
139         } else if (CommandLineOption.ACT_TO_GENERATE.isSetOn(commandLine)) {
140             whisker.setAct(Act.GENERATE);
141         } else if (CommandLineOption.ACT_TO_SKELETON.isSetOn(commandLine)) {
142             whisker.setAct(Act.SKELETON);
143         }
144 
145         if (whisker.getSource() == null
146                 && whisker.getAct().isSourceRequired()) {
147             throw new MissingOptionException("-"
148                     + CommandLineOption.SOURCE.getShortName() + " "
149                     + CommandLineOption.SOURCE.getDescription());
150         }
151         return whisker;
152     }
153 
154     /**
155      * Extracts the license descriptor name value,
156      * @param commandLine not null
157      * @return the value for the license descriptor name
158      * passed from the command line
159      */
160     private String licenseDescriptorName(final CommandLine commandLine) {
161         return CommandLineOption.LICENSE_DESCRIPTION
162             .getOptionValue(commandLine);
163     }
164 
165     /**
166      * Runs Whisker.
167      * @param args not null
168      * @return system return code
169      * @throws Exception when application unexpectedly fails
170      */
171     public int run(final String[] args) throws Exception {
172         try {
173             if (printHelp(args)) {
174                 help();
175             } else {
176                 configure(args).act();
177             }
178             return SYSTEM_EXIT_OK;
179         } catch (ParseException e) {
180             System.out.println();
181             System.out.println(e.getMessage());
182             System.out.println();
183             help();
184             return SYSTEM_EXIT_CLI_PARSE_FAILED;
185         }
186     }
187 
188     /**
189      * Do these command line arguments ask for help?
190      * @param args not null
191      * @return true when command line contains option for help,
192      * false otherwise
193      * @throws ParseException in case options could not be read properly.
194      */
195     public boolean printHelp(String[] args) throws ParseException {
196         final CommandLineOption help = CommandLineOption.PRINT_HELP;
197         try {
198             return help.isSetOn(
199                 parser().parse(new Options().addOption(
200                         help.create()), args));
201         } catch (ParseException e) {
202             return false;
203         }
204     }
205 
206     /**
207      * Prints out help.
208      */
209     private void help() {
210         final HelpFormatter formatter = new HelpFormatter();
211         formatter.printHelp(APP_NAME, HELP_HEADER, options(), HELP_FOOTER, true);
212     }
213 
214     /**
215      * Builds options for the command line.
216      * @return not null
217      */
218     private Options options() {
219         return CommandLineOption.options();
220     }
221 }