// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.runtime;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Predicates;
import com.google.common.base.Verify;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.io.Flushables;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.flags.InvocationPolicyEnforcer;
import com.google.devtools.build.lib.runtime.commands.ProjectFileSupport;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.AnsiStrippingOutputStream;
import com.google.devtools.build.lib.util.BlazeClock;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.util.LoggingUtil;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.util.io.DelegatingOutErr;
import com.google.devtools.build.lib.util.io.OutErr;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.common.options.OpaqueOptionsData;
import com.google.devtools.common.options.OptionPriority;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import javax.annotation.Nullable;

/**
 * Dispatches to the Blaze commands; that is, given a command line, this
 * abstraction looks up the appropriate command object, parses the options
 * required by the object, and calls its exec method. Also, this object provides
 * the runtime state (BlazeRuntime) to the commands.
 */
public class BlazeCommandDispatcher {

  /**
   * What to do if the command lock is not available.
   */
  public enum LockingMode {
    WAIT,  // Wait until it is available
    ERROR_OUT,  // Return with an error
  }
  // Keep in sync with options added in OptionProcessor::AddRcfileArgsAndOptions()
  private static final Set<String> INTERNAL_COMMAND_OPTIONS = ImmutableSet.of(
      "rc_source", "default_override", "isatty", "terminal_columns", "ignore_client_env",
      "client_env", "client_cwd");

  private static final ImmutableList<String> HELP_COMMAND = ImmutableList.of("help");

  private static final Set<String> ALL_HELP_OPTIONS = ImmutableSet.of("--help", "-help", "-h");

  /**
   * If the server needs to be shut down and how.
   */
  public enum ShutdownMethod {
    /** The server doesn't need to be shut down. */
    NONE,

    /** The server is to be shut down cleanly, e.g. as a result of "blaze shutdown". */
    CLEAN,

    /**
     * The server is shut down as a result of a "blaze clean --expunge.
     *
     * <p>In this case, no files should be deleted on shutdown hooks, since clean also deletes the
     * lock file, and there is a small possibility of the following sequence of events:
     *
     * <ol>
     *   <li> Client 1 runs "blaze clean --expunge"
     *   <li> Client 2 runs a command and waits for client 1 to finish
     *   <li> The clean command deletes everything including the lock file
     *   <li> Client 2 starts running and since the output base is empty, starts up a new server,
     *     which creates its own socket and PID files
     *   <li> The server used by client runs its shutdown hooks, deleting the PID files created by
     *     the new server
     * </ol>
     */
    EXPUNGE,
  }

  /**
   * By throwing this exception, a command indicates that it wants to shutdown
   * the Blaze server process.
   * See {@link BlazeCommandDispatcher#exec(List, OutErr, long)}.
   */
  public static class ShutdownBlazeServerException extends Exception {
    private final int exitStatus;
    private final ShutdownMethod method;

    public ShutdownBlazeServerException(int exitStatus, ShutdownMethod method, Throwable cause) {
      super(cause);
      this.exitStatus = exitStatus;
      this.method = method;
    }

    public ShutdownBlazeServerException(int exitStatus, ShutdownMethod method) {
      Preconditions.checkState(method != ShutdownMethod.NONE);
      this.exitStatus = exitStatus;
      this.method = method;
    }

    public int getExitStatus() {
      return exitStatus;
    }

    public ShutdownMethod getMethod() {
      return method;
    }
  }

  private final BlazeRuntime runtime;
  private final Object commandLock;
  private String currentClientDescription = null;
  private String shutdownReason = null;
  private OutputStream logOutputStream = null;
  private Level lastLogVerbosityLevel = null;
  private final LoadingCache<BlazeCommand, OpaqueOptionsData> optionsDataCache =
      CacheBuilder.newBuilder().build(
          new CacheLoader<BlazeCommand, OpaqueOptionsData>() {
            @Override
            public OpaqueOptionsData load(BlazeCommand command) {
              return OptionsParser.getOptionsData(BlazeCommandUtils.getOptions(
                  command.getClass(),
                  runtime.getBlazeModules(),
                  runtime.getRuleClassProvider()));
            }
          });

  /**
   * Create a Blaze dispatcher that uses the specified {@code BlazeRuntime} instance, but overrides
   * the command map with the given commands (plus any commands from modules).
   */
  @VisibleForTesting
  public BlazeCommandDispatcher(BlazeRuntime runtime, BlazeCommand... commands) {
    this(runtime);
    runtime.overrideCommands(Arrays.asList(commands));
  }

  /**
   * Create a Blaze dispatcher that uses the specified {@code BlazeRuntime} instance.
   */
  @VisibleForTesting
  public BlazeCommandDispatcher(BlazeRuntime runtime) {
    this.runtime = runtime;
    this.commandLock = new Object();
  }

  /**
   * Only some commands work if cwd != workspaceSuffix in Blaze. In that case, also check if Blaze
   * was called from the output directory and fail if it was.
   */
  private ExitCode checkCwdInWorkspace(CommandEnvironment env, Command commandAnnotation,
      String commandName, OutErr outErr) {
    if (!commandAnnotation.mustRunInWorkspace()) {
      return ExitCode.SUCCESS;
    }

    if (!env.inWorkspace()) {
      outErr.printErrLn(
          "The '" + commandName + "' command is only supported from within a workspace.");
      return ExitCode.COMMAND_LINE_ERROR;
    }

    Path workspace = env.getWorkspace();
    // TODO(kchodorow): Remove this once spaces are supported.
    if (workspace.getPathString().contains(" ")) {
      outErr.printErrLn(runtime.getProductName() + " does not currently work properly from paths "
          + "containing spaces (" + workspace + ").");
      return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
    }

    Path doNotBuild = workspace.getParentDirectory().getRelative(
        BlazeWorkspace.DO_NOT_BUILD_FILE_NAME);

    if (doNotBuild.exists()) {
      if (!commandAnnotation.canRunInOutputDirectory()) {
        outErr.printErrLn(getNotInRealWorkspaceError(doNotBuild));
        return ExitCode.COMMAND_LINE_ERROR;
      } else {
        outErr.printErrLn("WARNING: Blaze is run from output directory. This is unsound.");
      }
    }
    return ExitCode.SUCCESS;
  }

  private void parseArgsAndConfigs(CommandEnvironment env, OptionsParser optionsParser,
      Command commandAnnotation, List<String> args, List<String> rcfileNotes, OutErr outErr)
      throws OptionsParsingException {

    Function<String, String> commandOptionSourceFunction = new Function<String, String>() {
      @Override
      public String apply(String input) {
        if (INTERNAL_COMMAND_OPTIONS.contains(input)) {
          return "options generated by Blaze launcher";
        } else {
          return "command line options";
        }
      }
    };

    // Explicit command-line options:
    List<String> cmdLineAfterCommand = args.subList(1, args.size());
    optionsParser.parseWithSourceFunction(OptionPriority.COMMAND_LINE,
        commandOptionSourceFunction, cmdLineAfterCommand);

    // Command-specific options from .blazerc passed in via --default_override
    // and --rc_source. A no-op if none are provided.
    CommonCommandOptions rcFileOptions = optionsParser.getOptions(CommonCommandOptions.class);
    List<Pair<String, ListMultimap<String, String>>> optionsMap =
        getOptionsMap(outErr, rcFileOptions.rcSource, rcFileOptions.optionsOverrides,
            runtime.getCommandMap().keySet());

    parseOptionsForCommand(rcfileNotes, commandAnnotation, optionsParser, optionsMap, null, null);
    if (commandAnnotation.builds()) {
      ProjectFileSupport.handleProjectFiles(env, optionsParser, commandAnnotation.name());
    }

    // Fix-point iteration until all configs are loaded.
    List<String> configsLoaded = ImmutableList.of();
    Set<String> unknownConfigs = new LinkedHashSet<>();
    CommonCommandOptions commonOptions = optionsParser.getOptions(CommonCommandOptions.class);
    while (!commonOptions.configs.equals(configsLoaded)) {
      Set<String> missingConfigs = new LinkedHashSet<>(commonOptions.configs);
      missingConfigs.removeAll(configsLoaded);
      parseOptionsForCommand(rcfileNotes, commandAnnotation, optionsParser, optionsMap,
          missingConfigs, unknownConfigs);
      configsLoaded = commonOptions.configs;
      commonOptions = optionsParser.getOptions(CommonCommandOptions.class);
    }
    if (!unknownConfigs.isEmpty()) {
      outErr.printErrLn("WARNING: Config values are not defined in any .rc file: "
          + Joiner.on(", ").join(unknownConfigs));
    }
  }

  /**
   * Executes a single command. Returns the Unix exit status for the Blaze
   * client process, or throws {@link ShutdownBlazeServerException} to
   * indicate that a command wants to shutdown the Blaze server.
   */
  int exec(List<String> args, OutErr outErr, LockingMode lockingMode, String clientDescription,
      long firstContactTime) throws ShutdownBlazeServerException, InterruptedException {
    Preconditions.checkNotNull(clientDescription);
    if (args.isEmpty()) { // Default to help command if no arguments specified.
      args = HELP_COMMAND;
    }

    String commandName = args.get(0);

    // Be gentle to users who want to find out about Blaze invocation.
    if (ALL_HELP_OPTIONS.contains(commandName)) {
      commandName = "help";
    }

    BlazeCommand command = runtime.getCommandMap().get(commandName);
    if (command == null) {
      outErr.printErrLn(String.format(
          "Command '%s' not found. Try '%s help'.", commandName, runtime.getProductName()));
      return ExitCode.COMMAND_LINE_ERROR.getNumericExitCode();
    }


    long waitTimeInMs = 0;
    synchronized (commandLock) {
      boolean warningPrinted = false;
      while (currentClientDescription != null) {
        switch (lockingMode) {
          case WAIT:
            if (!warningPrinted) {
              outErr.printErrLn("Another command (" + currentClientDescription + ") is running. "
                  + " Waiting for it to complete...");
              warningPrinted = true;
            }
            long clockBefore = BlazeClock.nanoTime();
            commandLock.wait();
            waitTimeInMs = (BlazeClock.nanoTime() - clockBefore) / (1000L * 1000L);
            break;

          case ERROR_OUT:
            outErr.printErrLn(String.format("Another command (" + currentClientDescription + ") is "
                + "running. Exiting immediately."));
            return ExitCode.COMMAND_LINE_ERROR.getNumericExitCode();

          default:
            throw new IllegalStateException();
        }
      }
      Verify.verify(currentClientDescription == null);
      currentClientDescription = clientDescription;
    }

    try {
      if (shutdownReason != null) {
        outErr.printErrLn("Server shut down " + shutdownReason);
        return ExitCode.LOCAL_ENVIRONMENTAL_ERROR.getNumericExitCode();
      }
      return execExclusively(args, outErr, firstContactTime, commandName, command, waitTimeInMs);
    } catch (ShutdownBlazeServerException e) {
      shutdownReason = "explicitly by client " + currentClientDescription;
      throw e;
    } finally {
      synchronized (commandLock) {
        currentClientDescription = null;
        commandLock.notify();
      }
    }
  }

  private int execExclusively(List<String> args, OutErr outErr, long firstContactTime,
      String commandName, BlazeCommand command, long waitTimeInMs)
      throws ShutdownBlazeServerException {
    Command commandAnnotation = command.getClass().getAnnotation(Command.class);

    // Record the start time for the profiler. Do not put anything before this!
    long execStartTimeNanos = runtime.getClock().nanoTime();

    // The initCommand call also records the start time for the timestamp granularity monitor.
    CommandEnvironment env = runtime.getWorkspace().initCommand();
    // Record the command's starting time for use by the commands themselves.
    env.recordCommandStartTime(firstContactTime);

    AbruptExitException exitCausingException = null;
    for (BlazeModule module : runtime.getBlazeModules()) {
      try {
        module.beforeCommand(commandAnnotation, env);
      } catch (AbruptExitException e) {
        // Don't let one module's complaints prevent the other modules from doing necessary
        // setup. We promised to call beforeCommand exactly once per-module before each command
        // and will be calling afterCommand soon in the future - a module's afterCommand might
        // rightfully assume its beforeCommand has already been called.
        outErr.printErrLn(e.getMessage());
        // It's not ideal but we can only return one exit code, so we just pick the code of the
        // last exception.
        exitCausingException = e;
      }
    }
    if (exitCausingException != null) {
      return exitCausingException.getExitCode().getNumericExitCode();
    }

    try {
      Path commandLog = getCommandLogPath(env.getOutputBase());

      // Unlink old command log from previous build, if present, so scripts
      // reading it don't conflate it with the command log we're about to write.
      closeSilently(logOutputStream);
      logOutputStream = null;
      commandLog.delete();

      if (env.getRuntime().writeCommandLog() && commandAnnotation.writeCommandLog()) {
        logOutputStream = commandLog.getOutputStream();
        outErr = tee(outErr, OutErr.create(logOutputStream, logOutputStream));
      }
    } catch (IOException ioException) {
      LoggingUtil.logToRemote(Level.WARNING, "Unable to delete or open command.log", ioException);
    }

    ExitCode result = checkCwdInWorkspace(env, commandAnnotation, commandName, outErr);
    if (!result.equals(ExitCode.SUCCESS)) {
      return result.getNumericExitCode();
    }

    OptionsParser optionsParser;
    // Delay output of notes regarding the parsed rc file, so it's possible to disable this in the
    // rc file.
    List<String> rcfileNotes = new ArrayList<>();
    try {
      optionsParser = createOptionsParser(command);
      parseArgsAndConfigs(env, optionsParser, commandAnnotation, args, rcfileNotes, outErr);

      InvocationPolicyEnforcer optionsPolicyEnforcer =
          new InvocationPolicyEnforcer(runtime.getInvocationPolicy());
      optionsPolicyEnforcer.enforce(optionsParser, commandName);
      optionsPolicyEnforcer =
          InvocationPolicyEnforcer.create(
              getRuntime()
                  .getStartupOptionsProvider()
                  .getOptions(BlazeServerStartupOptions.class)
                  .invocationPolicy);
      optionsPolicyEnforcer.enforce(optionsParser, commandName);
    } catch (OptionsParsingException e) {
      for (String note : rcfileNotes) {
        outErr.printErrLn("INFO: " + note);
      }
      outErr.printErrLn(e.getMessage());
      return ExitCode.COMMAND_LINE_ERROR.getNumericExitCode();
    }

    // Setup log filtering
    BlazeCommandEventHandler.Options eventHandlerOptions =
        optionsParser.getOptions(BlazeCommandEventHandler.Options.class);
    OutErr colorfulOutErr = outErr;

    if (!eventHandlerOptions.useColor()) {
      outErr = ansiStripOut(ansiStripErr(outErr));
      if (!commandAnnotation.binaryStdOut()) {
        colorfulOutErr = ansiStripOut(colorfulOutErr);
      }
      if (!commandAnnotation.binaryStdErr()) {
        colorfulOutErr = ansiStripErr(colorfulOutErr);
      }
    }

    if (!commandAnnotation.binaryStdOut()) {
      outErr = lineBufferOut(outErr);
    }

    if (!commandAnnotation.binaryStdErr()) {
      outErr = lineBufferErr(outErr);
    }

    CommonCommandOptions commonOptions = optionsParser.getOptions(CommonCommandOptions.class);
    if (!commonOptions.verbosity.equals(lastLogVerbosityLevel)) {
      BlazeRuntime.setupLogging(commonOptions.verbosity);
      lastLogVerbosityLevel = commonOptions.verbosity;
    }

    // Do this before an actual crash so we don't have to worry about
    // allocating memory post-crash.
    String[] crashData = env.getCrashData();
    int numericExitCode = ExitCode.BLAZE_INTERNAL_ERROR.getNumericExitCode();
    PrintStream savedOut = System.out;
    PrintStream savedErr = System.err;

    EventHandler handler = createEventHandler(outErr, eventHandlerOptions);
    Reporter reporter = env.getReporter();
    reporter.addHandler(handler);
    env.getEventBus().register(handler);

    // We register an ANSI-allowing handler associated with {@code handler} so that ANSI control
    // codes can be re-introduced later even if blaze is invoked with --color=no. This is useful
    // for commands such as 'blaze run' where the output of the final executable shouldn't be
    // modified.
    EventHandler ansiAllowingHandler = null;
    if (!eventHandlerOptions.useColor()) {
      ansiAllowingHandler = createEventHandler(colorfulOutErr, eventHandlerOptions);
      reporter.registerAnsiAllowingHandler(handler, ansiAllowingHandler);
      if (ansiAllowingHandler instanceof ExperimentalEventHandler) {
        env.getEventBus()
            .register(
                new PassiveExperimentalEventHandler(
                    (ExperimentalEventHandler) ansiAllowingHandler));
      }
    }

    try {
      // While a Blaze command is active, direct all errors to the client's
      // event handler (and out/err streams).
      OutErr reporterOutErr = reporter.getOutErr();
      System.setOut(new PrintStream(reporterOutErr.getOutputStream(), /*autoflush=*/true));
      System.setErr(new PrintStream(reporterOutErr.getErrorStream(), /*autoflush=*/true));

      for (BlazeModule module : runtime.getBlazeModules()) {
        module.checkEnvironment(env);
      }

      if (commonOptions.announceRcOptions) {
        for (String note : rcfileNotes) {
          reporter.handle(Event.info(note));
        }
      }

      try {
        // Notify the BlazeRuntime, so it can do some initial setup.
        env.beforeCommand(commandAnnotation, optionsParser, commonOptions, execStartTimeNanos,
            waitTimeInMs);
        // Allow the command to edit options after parsing:
        command.editOptions(env, optionsParser);
      } catch (AbruptExitException e) {
        reporter.handle(Event.error(e.getMessage()));
        return e.getExitCode().getNumericExitCode();
      }
      for (BlazeModule module : runtime.getBlazeModules()) {
        module.handleOptions(optionsParser);
      }

      // Print warnings for odd options usage
      for (String warning : optionsParser.getWarnings()) {
        reporter.handle(Event.warn(warning));
      }

      ExitCode outcome = command.exec(env, optionsParser);
      outcome = env.precompleteCommand(outcome);
      numericExitCode = outcome.getNumericExitCode();
      return numericExitCode;
    } catch (ShutdownBlazeServerException e) {
      numericExitCode = e.getExitStatus();
      throw e;
    } catch (Throwable e) {
      e.printStackTrace();
      BugReport.printBug(outErr, e);
      BugReport.sendBugReport(e, args, crashData);
      numericExitCode = BugReport.getExitCodeForThrowable(e);
      throw new ShutdownBlazeServerException(numericExitCode, ShutdownMethod.CLEAN, e);
    } finally {
      env.getEventBus().post(new AfterCommandEvent());
      runtime.afterCommand(env, numericExitCode);
      // Swallow IOException, as we are already in a finally clause
      Flushables.flushQuietly(outErr.getOutputStream());
      Flushables.flushQuietly(outErr.getErrorStream());

      System.setOut(savedOut);
      System.setErr(savedErr);
      reporter.removeHandler(handler);
      releaseHandler(handler);
      if (!eventHandlerOptions.useColor()) {
        reporter.removeHandler(ansiAllowingHandler);
        releaseHandler(ansiAllowingHandler);
      }
      env.getTimestampGranularityMonitor().waitForTimestampGranularity(outErr);
    }
  }

  /**
   * For testing ONLY. Same as {@link #exec(List, OutErr, boolean, String, long)}, but automatically
   * uses the current time.
   */
  @VisibleForTesting
  public int exec(List<String> args, LockingMode lockingMode, String clientDescription,
      OutErr originalOutErr) throws ShutdownBlazeServerException, InterruptedException {
    return exec(args, originalOutErr, LockingMode.ERROR_OUT, clientDescription,
        runtime.getClock().currentTimeMillis());
  }

  /**
   * Parses the options from .rc files for a command invocation. It works in one of two modes;
   * either it loads the non-config options, or the config options that are specified in the {@code
   * configs} parameter.
   *
   * <p>This method adds every option pertaining to the specified command to the options parser. To
   * do that, it needs the command -> option mapping that is generated from the .rc files.
   *
   * <p>It is not as trivial as simply taking the list of options for the specified command because
   * commands can inherit arguments from each other, and we have to respect that (e.g. if an option
   * is specified for 'build', it needs to take effect for the 'test' command, too).
   *
   * <p>Note that the order in which the options are parsed is well-defined: all options from the
   * same rc file are parsed at the same time, and the rc files are handled in the order in which
   * they were passed in from the client.
   *
   * @param rcfileNotes note message that would be printed during parsing
   * @param commandAnnotation the command for which options should be parsed.
   * @param optionsParser parser to receive parsed options.
   * @param optionsMap .rc files in structured format: a list of pairs, where the first part is the
   *     name of the rc file, and the second part is a multimap of command name (plus config, if
   *     present) to the list of options for that command
   * @param configs the configs for which to parse options; if {@code null}, non-config options are
   *     parsed
   * @param unknownConfigs optional; a collection that the method will populate with the config
   *     values in {@code configs} that none of the .rc files had entries for
   * @throws OptionsParsingException
   */
  protected static void parseOptionsForCommand(List<String> rcfileNotes, Command commandAnnotation,
      OptionsParser optionsParser, List<Pair<String, ListMultimap<String, String>>> optionsMap,
      @Nullable Collection<String> configs, @Nullable Collection<String> unknownConfigs)
      throws OptionsParsingException {
    Set<String> knownConfigs = new HashSet<>();
    for (String commandToParse : getCommandNamesToParse(commandAnnotation)) {
      for (Pair<String, ListMultimap<String, String>> entry : optionsMap) {
        List<String> allOptions = new ArrayList<>();
        if (configs == null) {
          allOptions.addAll(entry.second.get(commandToParse));
        } else {
          for (String config : configs) {
            Collection<String> values = entry.second.get(commandToParse + ":" + config);
            if (!values.isEmpty()) {
              allOptions.addAll(values);
              knownConfigs.add(config);
            }
          }
        }
        processOptionList(optionsParser, commandToParse,
            commandAnnotation.name(), rcfileNotes, entry.first, allOptions);
      }
    }
    if (unknownConfigs != null && configs != null && configs.size() > knownConfigs.size()) {
      Iterables.addAll(
          unknownConfigs,
          Iterables.filter(configs, Predicates.not(Predicates.in(knownConfigs))));
    }
  }

  // Processes the option list for an .rc file - command pair.
  private static void processOptionList(OptionsParser optionsParser, String commandToParse,
      String originalCommand, List<String> rcfileNotes, String rcfile, List<String> rcfileOptions)
      throws OptionsParsingException {
    if (!rcfileOptions.isEmpty()) {
      String inherited = commandToParse.equals(originalCommand) ? "" : "Inherited ";
      String source = rcfile.equals("client") ? "Options provided by the client"
          : "Reading options for '" + originalCommand + "' from " + rcfile;
      rcfileNotes.add(source + ":\n"
          + "  " + inherited + "'" + commandToParse + "' options: "
        + Joiner.on(' ').join(rcfileOptions));
      optionsParser.parse(OptionPriority.RC_FILE, rcfile, rcfileOptions);
    }
  }

  private static List<String> getCommandNamesToParse(Command commandAnnotation) {
    List<String> result = new ArrayList<>();
    result.add("common");
    getCommandNamesToParseHelper(commandAnnotation, result);
    return result;
  }

  private static void getCommandNamesToParseHelper(Command commandAnnotation,
      List<String> accumulator) {
    for (Class<? extends BlazeCommand> base : commandAnnotation.inherits()) {
      getCommandNamesToParseHelper(base.getAnnotation(Command.class), accumulator);
    }
    accumulator.add(commandAnnotation.name());
  }

  private OutErr lineBufferOut(OutErr outErr) {
    OutputStream wrappedOut = new LineBufferedOutputStream(outErr.getOutputStream());
    return OutErr.create(wrappedOut, outErr.getErrorStream());
  }

  private OutErr lineBufferErr(OutErr outErr) {
    OutputStream wrappedErr = new LineBufferedOutputStream(outErr.getErrorStream());
    return OutErr.create(outErr.getOutputStream(), wrappedErr);
  }

  private OutErr ansiStripOut(OutErr outErr) {
    OutputStream wrappedOut = new AnsiStrippingOutputStream(outErr.getOutputStream());
    return OutErr.create(wrappedOut, outErr.getErrorStream());
  }

  private OutErr ansiStripErr(OutErr outErr) {
    OutputStream wrappedErr = new AnsiStrippingOutputStream(outErr.getErrorStream());
    return OutErr.create(outErr.getOutputStream(), wrappedErr);
  }

  private String getNotInRealWorkspaceError(Path doNotBuildFile) {
    String message = "Blaze should not be called from a Blaze output directory. ";
    try {
      String realWorkspace =
          new String(FileSystemUtils.readContentAsLatin1(doNotBuildFile));
      message += String.format("The pertinent workspace directory is: '%s'",
          realWorkspace);
    } catch (IOException e) {
      // We are exiting anyway.
    }

    return message;
  }

  /**
   * For a given output_base directory, returns the command log file path.
   */
  public static Path getCommandLogPath(Path outputBase) {
    return outputBase.getRelative("command.log");
  }

  private OutErr tee(OutErr outErr1, OutErr outErr2) {
    DelegatingOutErr outErr = new DelegatingOutErr();
    outErr.addSink(outErr1);
    outErr.addSink(outErr2);
    return outErr;
  }

  private void closeSilently(OutputStream logOutputStream) {
    if (logOutputStream != null) {
      try {
        logOutputStream.close();
      } catch (IOException e) {
        LoggingUtil.logToRemote(Level.WARNING, "Unable to close command.log", e);
      }
    }
  }

  /**
   * Creates an option parser using the common options classes and the
   * command-specific options classes.
   *
   * <p>An overriding method should first call this method and can then
   * override default values directly or by calling {@link
   * #parseOptionsForCommand} for command-specific options.
   *
   * @throws OptionsParsingException
   */
  protected OptionsParser createOptionsParser(BlazeCommand command)
      throws OptionsParsingException {
    Command annotation = command.getClass().getAnnotation(Command.class);
    OptionsParser parser = OptionsParser.newOptionsParser(optionsDataCache.getUnchecked(command));
    parser.setAllowResidue(annotation.allowResidue());
    return parser;
  }

  /**
   * Convert a list of option override specifications to a more easily digestible
   * form.
   *
   * @param overrides list of option override specifications
   */
  @VisibleForTesting
  static List<Pair<String, ListMultimap<String, String>>> getOptionsMap(
      OutErr outErr,
      List<String> rcFiles,
      List<CommonCommandOptions.OptionOverride> overrides,
      Set<String> validCommands) {
    List<Pair<String, ListMultimap<String, String>>> result = new ArrayList<>();

    String lastRcFile = null;
    ListMultimap<String, String> lastMap = null;
    for (CommonCommandOptions.OptionOverride override : overrides) {
      if (override.blazeRc < 0 || override.blazeRc >= rcFiles.size()) {
        outErr.printErrLn("WARNING: inconsistency in generated command line "
            + "args. Ignoring bogus argument\n");
        continue;
      }
      String rcFile = rcFiles.get(override.blazeRc);

      String command = override.command;
      int index = command.indexOf(':');
      if (index > 0) {
        command = command.substring(0, index);
      }
      if (!validCommands.contains(command) && !command.equals("common")) {
        outErr.printErrLn("WARNING: while reading option defaults file '"
            + rcFile + "':\n"
            + "  invalid command name '" + override.command + "'.");
        continue;
      }

      if (!rcFile.equals(lastRcFile)) {
        if (lastRcFile != null) {
          result.add(Pair.of(lastRcFile, lastMap));
        }
        lastRcFile = rcFile;
        lastMap = ArrayListMultimap.create();
      }
      lastMap.put(override.command, override.option);
    }
    if (lastRcFile != null) {
      result.add(Pair.of(lastRcFile, lastMap));
    }

    return result;
  }

  /**
   * Returns the event handler to use for this Blaze command.
   */
  private EventHandler createEventHandler(OutErr outErr,
      BlazeCommandEventHandler.Options eventOptions) {
    EventHandler eventHandler;
    if (eventOptions.experimentalUi) {
      // The experimental event handler is not to be rate limited.
      return new ExperimentalEventHandler(outErr, eventOptions, runtime.getClock());
    } else if ((eventOptions.useColor() || eventOptions.useCursorControl())) {
      eventHandler = new FancyTerminalEventHandler(outErr, eventOptions);
    } else {
      eventHandler = new BlazeCommandEventHandler(outErr, eventOptions);
    }

    return RateLimitingEventHandler.create(eventHandler, eventOptions.showProgressRateLimit);
  }

  /**
   * Unsets the event handler.
   */
  private void releaseHandler(EventHandler eventHandler) {
    if (eventHandler instanceof FancyTerminalEventHandler) {
      // Make sure that the terminal state of the old event handler is clear
      // before creating a new one.
      ((FancyTerminalEventHandler) eventHandler).resetTerminal();
    }
    if (eventHandler instanceof ExperimentalEventHandler) {
      ((ExperimentalEventHandler) eventHandler).resetTerminal();
    }
  }

  /**
   * Returns the runtime instance shared by the commands that this dispatcher
   * dispatches to.
   */
  public BlazeRuntime getRuntime() {
    return runtime;
  }

  /**
   * Shuts down all the registered commands to give them a chance to cleanup or
   * close resources. Should be called by the owner of this command dispatcher
   * in all termination cases.
   */
  public void shutdown() {
    closeSilently(logOutputStream);
    logOutputStream = null;
  }
}
