Example #1
0
  public void verify(PrintStream out) {
    List<String> errors = new ArrayList<>();

    if (!missing.isEmpty()) {
      StringBuilder missingMessage = new StringBuilder(80);
      List<String> missingSwitches = new ArrayList<>(missing.size());

      for (CliOption option : missing) {
        missingSwitches.add(last(option.getSwitchNames()));
      }

      missingMessage.append("Missing required option");

      if (missing.size() > 1) {
        missingMessage.append('s');
      }

      missingMessage.append(": ").append(join(", ", missingSwitches));
      errors.add(missingMessage.toString());
    }

    if (!unexpected.isEmpty()) {
      String unexpectedMessage = "Unexpected parameters: " + join(" ", unexpected);

      errors.add(unexpectedMessage);
    }

    if (!duplicates.isEmpty()) {
      StringBuilder duplicatesMessage = new StringBuilder(80);
      List<String> duplicateSwitches = new ArrayList<>(duplicates.size());

      for (Map.Entry<String, String> duplicate : duplicates) {
        duplicateSwitches.add(duplicate.getKey() + "=" + duplicate.getValue());
      }

      duplicatesMessage.append("Duplicate options: ").append(join(", ", duplicateSwitches));
      errors.add(duplicatesMessage.toString());
    }

    if (!errors.isEmpty()) {
      out.println(command.getDocumentation());
      out.println();
      out.flush();

      throw new ErrorMessage(join("\n", errors));
    }
  }
Example #2
0
 /**
  * Add a <code>CliCommand</code>.
  *
  * <p>Called by the extending application class to add their custom commands.
  *
  * <p>if the given <code>CliCommand.commandName</code> is null then a non-command simple switch
  * only application is declared. Otherwise a command driven application is declared.
  *
  * <p>Commands added here are the first level commands expected at <code>args[0]</code>.
  *
  * <p>Nested commands are supported to any level.
  */
 protected void addCommand(CliCommand command) {
   if (nonCommandCli != null) {
     if (nonCommandCli.get() && command.getCommandName() != null)
       throw new RuntimeException("Trying to add a command when already in non-command mode");
     if (nonCommandCli.get() && command.getCommandName() == null)
       throw new RuntimeException("Trying to add two non-commands");
     if (!nonCommandCli.get() && command.getCommandName() == null)
       throw new RuntimeException("Trying to add a non-command when already set to command mode");
   }
   if (command.getCommandName() != null) nonCommandCli = new AtomicBoolean(false);
   else nonCommandCli = new AtomicBoolean(true);
   commands.put(command.getCommandName(), command);
   command.cliSetup();
 }
Example #3
0
  public CliParser(CliCommand command, List<String> arguments) {
    this.command = command;

    // getOption removes options as it parses them
    ArgumentList argumentList = new ArgumentList(arguments);

    for (CliOption option : command.getOptions()) {
      switches.addAll(option.getSwitchNames());

      List<Map.Entry<String, String>> parsedValues = getOption(option, argumentList);

      if (parsedValues.isEmpty()) {
        if (option.isRequired()) {
          missing.add(option);
        }
      } else if (parsedValues.size() > 1) {
        if (option.isUnique()) {
          duplicates.addAll(parsedValues);
        } else {
          for (String switchName : option.getSwitchNames()) {
            for (Map.Entry<String, String> parsedValue : parsedValues) {
              List<String> switchValues = multiValues.get(switchName);

              if (switchValues == null) {
                switchValues = new ArrayList<>();
                multiValues.put(switchName, switchValues);
              }

              switchValues.add(parsedValue.getValue());
            }
          }
        }
      } else {
        String value = parsedValues.get(0).getValue();

        for (String switchName : option.getSwitchNames()) {
          values.put(switchName, value);
        }
      }
    }

    Iterator<CliParameter> parameters = command.getParameters().iterator();
    Iterator<String> trailingArguments = argumentList.trailing();

    while (parameters.hasNext() && trailingArguments.hasNext()) {
      String name = parameters.next().getName();

      values.put(name, trailingArguments.next());
      trailingArguments.remove();
      switches.add(name);
    }

    while (parameters.hasNext()) {
      CliParameter parameter = parameters.next();

      switches.add(parameter.getName());

      if (parameter.isRequired()) {
        CliOption option = new CliOption.SwitchBuilder().withSwitch(parameter.getName()).build();

        missing.add(option);
      }
    }

    if (command.allowsTrailingParameter()) {
      while (trailingArguments.hasNext()) {
        trailing.add(trailingArguments.next());
        trailingArguments.remove();
      }
    }

    Iterator<String> unexpected = argumentList.remaining();

    while (unexpected.hasNext()) {
      this.unexpected.add(unexpected.next());
    }
  }
Example #4
0
  /**
   * Validate command line <code>args</code>.
   * <p>The given command line <code>args</code> are validated against the
   * custom <code>CliCommand</code>'s added by the application.  Help is
   * displayed and the application exits if there are errors.  Otherwise, the
   * specified <code>activeCommand<code> is set, making its commons-cli
   * <code>CommandLine</code> available for the application.
   * @return the selected <code>CliCommand</code>
   */
  protected CliCommand validateCommands() {
    // check for no arguments help
    if (originalArgs.length == 0) {
      if (nonCommandCli.get()) commands.get(null).help(0, null);
      commandHelp(0, null);
    }

    // check for simple no commands command line
    if (nonCommandCli.get()) {
      CliCommand command = commands.get(null);
      command.parseCommandLine(originalArgs);
      boolean gotConfig = command.handleConfiguration();
      handleLogger(command.getCommandLine(), gotConfig);
      command.customInit();
      activeCommand = command;
      return command;
    }

    // check for -v --version at first argument
    if (originalArgs[0].equals("-" + VersionShortCl)
        || originalArgs[0].equals("--" + VersionLongCl)) version();
    if (originalArgs[0].equals("-" + CliBase.HelpShortCl)
        || originalArgs[0].equals("--" + CliBase.HelpLongCl)) commandHelp(0, null);

    // check if first command given is known
    CliCommand cmd = null;
    for (Entry<String, CliCommand> entry : commands.entrySet()) {
      if (entry.getKey().equals(originalArgs[0])) {
        cmd = entry.getValue();
        break;
      }
    }
    if (cmd == null) commandHelp(InvalidCommand, "Unknown command: " + originalArgs[0]);
    // check for first command given but no arguments help
    if (originalArgs.length == 1) {
      if (cmd.hasChildren()) cmd.commandHelp(0, null);
      if (cmd.hasOptions()) cmd.help(0, null);
      return cmd;
    }

    // must be more than 1 argument given, see if 2nd is another level command
    CliCommand command = null;
    for (Entry<String, CliCommand> entry : commands.entrySet()) {
      command = entry.getValue();
      activeCommand = command.validateCommands(0);
      if (activeCommand != null) break;
    }

    boolean gotConfig = command.handleConfiguration();
    handleLogger(command.getCommandLine(), gotConfig);
    if (log.isDebugEnabled()) {
      StrH.ttl(initsb, 1, "java.class.path:");
      String path = System.getProperty("java.class.path");
      do {
        int index = path.indexOf(';');
        if (index == -1) break;
        String element = path.substring(0, index);
        StrH.ttl(initsb, 2, element);
        path = path.substring(++index);
      } while (true);
      path = path.replace(';', '\n');
    }
    log.debug(initsb.toString());
    return activeCommand;
  }
Example #5
0
 /**
  * Return Command Line.
  *
  * @return the <code>CommandLine</code>from the active <code>CliCommand</code> specified in the
  *     given command line arguments. Will never be null.
  * @see CliCommand
  */
 public CommandLine getCommandLine() {
   return activeCommand.getCommandLine();
 }