View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *  http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package org.apache.any23.cli;
    19
    20  import com.beust.jcommander.JCommander;
    21  import com.beust.jcommander.Parameter;
    22  import com.beust.jcommander.converters.FileConverter;
    23  import org.apache.any23.Any23;
    24  import org.apache.any23.plugin.Any23PluginManager;
    25
    26  import java.io.File;
    27  import java.io.IOException;
    28  import java.io.InputStream;
    29  import java.io.PrintStream;
    30  import java.util.Date;
    31  import java.util.Iterator;
    32  import java.util.Locale;
    33  import java.util.Map;
    34  import java.util.Properties;
    35
    36  import static java.lang.System.currentTimeMillis;
    37  import static java.lang.System.exit;
    38
    39  /**
    40   * This class is the main class responsible to provide a uniform command-line access points to all the others tools like
    41   * {@link Rover}.
    42   *
    43   * @see ExtractorDocumentation
    44   * @see Rover
    45   */
    46  public final class ToolRunner {
    47
    48      public static final File DEFAULT_PLUGIN_DIR = new File(new File(System.getProperty("user.home")), ".any23/plugins");
    49
    50      private static final PrintStream infoStream = System.err;
    51
    52      @Parameter(names = { "-h", "--help" }, description = "Display help information.")
    53      private boolean printHelp;
    54
    55      @Parameter(names = { "-v", "--version" }, description = "Display version information.")
    56      private boolean showVersion;
    57
    58      @Parameter(names = { "-X", "--verbose" }, description = "Produce execution verbose output.")
    59      private boolean verbose;
    60
    61      @Parameter(names = {
    62              "--plugins-dir" }, description = "The Any23 plugins directory.", converter = FileConverter.class)
    63      private File pluginsDir = DEFAULT_PLUGIN_DIR;
    64
    65      public static void main(String[] args) throws Exception {
    66          exit(new ToolRunner().execute(args));
    67      }
    68
    69      public int execute(String... args) throws Exception {
    70          return execute(false, args);
    71      }
    72
    73      int execute(boolean concise, String... args) throws Exception {
    74          JCommander commander = new JCommander(this);
    75          commander.setProgramName(System.getProperty("app.name"));
    76
    77          // TODO (low) : this dirty solution has been introduced because it is not possible to
    78          // parse arguments ( commander.parse() ) twice.
    79          final File pluginsDirOption;
    80          try {
    81              pluginsDirOption = parsePluginDirOption(args);
    82          } catch (Exception e) {
    83              System.err.println(e.getMessage());
    84              return 1;
    85          }
    86          if (pluginsDirOption != null) {
    87              pluginsDir = pluginsDirOption;
    88          }
    89
    90          // add all plugins first
    91          final Iterator<Tool> tools = getToolsInClasspath();
    92          while (tools.hasNext()) {
    93              Tool tool = tools.next();
    94              commander.addCommand(tool);
    95          }
    96
    97          commander.parse(args);
    98
    99          Map<String, JCommander> commands = commander.getCommands();
    100         String parsedCommand = commander.getParsedCommand();
    101
    102         if (printHelp) {
    103             commander.usage();
    104             return 0;
    105         }
    106
    107         if (showVersion) {
    108             printVersionInfo();
    109             return 0;
    110         }
    111
    112         if (parsedCommand == null) {
    113             infoStream.println("A command must be specified.");
    114             commander.usage();
    115             return 1;
    116         }
    117
    118         long start = currentTimeMillis();
    119         int exit = 0;
    120
    121         Throwable error = null;
    122
    123         // execute the parsed command
    124         infoStream.println();
    125         infoStream.println("------------------------------------------------------------------------");
    126         infoStream.printf(Locale.ROOT, "Apache Any23 :: %s%n", parsedCommand);
    127         infoStream.println("------------------------------------------------------------------------");
    128         infoStream.println();
    129
    130         try {
    131             Tool tool = Tool.class.cast(commands.get(parsedCommand).getObjects().get(0));
    132             if (tool instanceof BaseTool) {
    133                 ((BaseTool) tool).run(concise);
    134             } else {
    135                 tool.run();
    136             }
    137         } catch (Throwable t) {
    138             exit = 1;
    139             error = t;
    140         } finally {
    141             infoStream.println();
    142             infoStream.println("------------------------------------------------------------------------");
    143             infoStream.printf(Locale.ROOT, "Apache Any23 %s%n", (exit != 0) ? "FAILURE" : "SUCCESS");
    144
    145             if (exit != 0) {
    146                 infoStream.println();
    147
    148                 if (verbose) {
    149                     System.err.println("Execution terminated with errors:");
    150                     error.printStackTrace(infoStream);
    151                 } else {
    152                     infoStream.printf(Locale.ROOT, "Execution terminated with errors: %s%n", error.getMessage());
    153                 }
    154
    155                 infoStream.println();
    156             }
    157
    158             infoStream.printf(Locale.ROOT, "Total time: %ss%n", ((currentTimeMillis() - start) / 1000));
    159             infoStream.printf(Locale.ROOT, "Finished at: %s%n", new Date());
    160
    161             final Runtime runtime = Runtime.getRuntime();
    162             final int megaUnit = 1024 * 1024;
    163             infoStream.printf(Locale.ROOT, "Final Memory: %sM/%sM%n",
    164                     (runtime.totalMemory() - runtime.freeMemory()) / megaUnit, runtime.totalMemory() / megaUnit);
    165
    166             infoStream.println("------------------------------------------------------------------------");
    167         }
    168
    169         return exit;
    170     }
    171
    172     Iterator<Tool> getToolsInClasspath() throws IOException {
    173         final Any23PluginManager pluginManager = Any23PluginManager.getInstance();
    174         if (pluginsDir.exists() && pluginsDir.isDirectory()) {
    175             pluginManager.loadJARDir(pluginsDir);
    176         }
    177         return pluginManager.getTools();
    178     }
    179
    180     private static void printVersionInfo() {
    181         Properties properties = new Properties();
    182         InputStream input = ToolRunner.class.getClassLoader()
    183                 .getResourceAsStream("META-INF/maven/org.apache.any23/any23-core/pom.properties");
    184
    185         if (input != null) {
    186             try {
    187                 properties.load(input);
    188             } catch (IOException e) {
    189                 // ignore, just don't load the properties
    190             } finally {
    191                 try {
    192                     input.close();
    193                 } catch (IOException e) {
    194                     // close quietly
    195                 }
    196             }
    197         }
    198
    199         infoStream.printf(Locale.ROOT, "Apache Any23 %s%n", Any23.VERSION);
    200         infoStream.printf(Locale.ROOT, "Java version: %s, vendor: %s%n", System.getProperty("java.version"),
    201                 System.getProperty("java.vendor"));
    202         infoStream.printf(Locale.ROOT, "Java home: %s%n", System.getProperty("java.home"));
    203         infoStream.printf(Locale.ROOT, "Default locale: %s_%s, platform encoding: %s%n",
    204                 System.getProperty("user.language"), System.getProperty("user.country"),
    205                 System.getProperty("sun.jnu.encoding"));
    206         infoStream.printf(Locale.ROOT, "OS name: \"%s\", version: \"%s\", arch: \"%s\", family: \"%s\"%n",
    207                 System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch"),
    208                 getOsFamily());
    209     }
    210
    211     private static final String getOsFamily() {
    212         String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT);
    213         String pathSep = System.getProperty("path.separator");
    214
    215         if (osName.contains("windows")) {
    216             return "windows";
    217         } else if (osName.contains("os/2")) {
    218             return "os/2";
    219         } else if (osName.contains("z/os") || osName.contains("os/390")) {
    220             return "z/os";
    221         } else if (osName.contains("os/400")) {
    222             return "os/400";
    223         } else if (";".equals(pathSep)) {
    224             return "dos";
    225         } else if (osName.contains("mac")) {
    226             if (osName.endsWith("x")) {
    227                 return "mac"; // MACOSX
    228             }
    229             return "unix";
    230         } else if (osName.contains("nonstop_kernel")) {
    231             return "tandem";
    232         } else if (osName.contains("openvms")) {
    233             return "openvms";
    234         } else if (":".equals(pathSep)) {
    235             return "unix";
    236         }
    237
    238         return "undefined";
    239     }
    240
    241     private static File parsePluginDirOption(String[] args) {
    242         int optionIndex = -1;
    243         for (int i = 0; i < args.length; i++) {
    244             if ("--plugins-dir".equals(args[i])) {
    245                 optionIndex = i;
    246             }
    247         }
    248         if (optionIndex == -1)
    249             return null;
    250
    251         if (optionIndex == args.length - 1) {
    252             throw new IllegalArgumentException("Missing argument for --plugins-dir option.");
    253         }
    254         final File pluginsDir = new File(args[optionIndex + 1]);
    255         if (!pluginsDir.isDirectory()) {
    256             throw new IllegalArgumentException("Expected a directory for --plugins-dir option value.");
    257         }
    258         return pluginsDir;
    259     }
    260
    261 }