// 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.Preconditions;
import com.google.common.base.Throwables;
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.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Flushables;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.devtools.build.lib.bugreport.BugReport;
import com.google.devtools.build.lib.buildtool.buildevent.ProfilerStartedEvent;
import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable;
import com.google.devtools.build.lib.events.PrintingEventHandler;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.events.StoredEventHandler;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.SilentCloseable;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.AnsiStrippingOutputStream;
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.io.DelegatingOutErr;
import com.google.devtools.build.lib.util.io.OutErr;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.common.options.OpaqueOptionsData;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingException;
import com.google.devtools.common.options.OptionsParsingResult;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 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 {
  private static final Logger logger = Logger.getLogger(BlazeCommandDispatcher.class.getName());

  /**
   * 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
  }

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

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

  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();
  }

  /**
   * Executes a single command. Returns a {@link BlazeCommandResult} to indicate either an exit
   * code, the desire to shut down the server, or that a given binary should be executed by the
   * client.
   */
  public BlazeCommandResult exec(
      InvocationPolicy invocationPolicy,
      List<String> args,
      OutErr outErr,
      LockingMode lockingMode,
      String clientDescription,
      long firstContactTimeMillis,
      Optional<List<Pair<String, String>>> startupOptionsTaggedWithBazelRc)
      throws InterruptedException {
    OriginalUnstructuredCommandLineEvent originalCommandLine =
        new OriginalUnstructuredCommandLineEvent(args);
    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 BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
    }

    // Take the exclusive server lock.  If we fail, we busy-wait until the lock becomes available.
    //
    // We used to rely on commandLock.wait() to lazy-wait for the lock to become available, which is
    // theoretically fine, but doing so prevents us from determining if the PID of the server
    // holding the lock has changed under the hood.  There have been multiple bug reports where
    // users (especially macOS ones) mention that the Blaze invocation hangs on a non-existent PID.
    // This should help troubleshoot those scenarios in case there really is a bug somewhere.
    boolean multipleAttempts = false;
    long clockBefore = BlazeClock.nanoTime();
    String otherClientDescription = "";
    // TODO(ulfjack): Add lock acquisition to the profiler.
    synchronized (commandLock) {
      while (currentClientDescription != null) {
        switch (lockingMode) {
          case WAIT:
            if (!otherClientDescription.equals(currentClientDescription)) {
              outErr.printErrLn("Another command (" + currentClientDescription + ") is running. "
                  + " Waiting for it to complete on the server...");
              otherClientDescription = currentClientDescription;
            }
            commandLock.wait(500);
            break;

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

          default:
            throw new IllegalStateException();
        }

        multipleAttempts = true;
      }
      Verify.verify(currentClientDescription == null);
      currentClientDescription = clientDescription;
    }
    // If we took the lock on the first try, force the reported wait time to 0 to avoid unnecessary
    // noise in the logs.  In this metric, we are only interested in knowing how long it took for
    // other commands to complete, not how fast acquiring a lock is.
    long waitTimeInMs =
        !multipleAttempts ? 0 : (BlazeClock.nanoTime() - clockBefore) / (1000L * 1000L);

    try {
      if (shutdownReason != null) {
        outErr.printErrLn("Server shut down " + shutdownReason);
        return BlazeCommandResult.exitCode(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
      }
      BlazeCommandResult result = execExclusively(
          originalCommandLine,
          invocationPolicy,
          args,
          outErr,
          firstContactTimeMillis,
          commandName,
          command,
          waitTimeInMs,
          startupOptionsTaggedWithBazelRc);
      if (result.shutdown()) {
        // TODO(lberki): This also handles the case where we catch an uncaught Throwable in
        // execExclusively() which is not an explicit shutdown.
        shutdownReason = "explicitly by client " + clientDescription;
      }
      return result;
    } finally {
      synchronized (commandLock) {
        currentClientDescription = null;
        commandLock.notify();
      }
    }
  }

  /**
   * For testing ONLY. Same as {@link #exec(InvocationPolicy, List, OutErr, LockingMode, String,
   * long, Optional<List<Pair<String, String>>>)}, but automatically uses the current time.
   */
  @VisibleForTesting
  public BlazeCommandResult exec(List<String> args, String clientDescription, OutErr originalOutErr)
      throws InterruptedException {
    return exec(
        InvocationPolicy.getDefaultInstance(),
        args,
        originalOutErr,
        LockingMode.ERROR_OUT,
        clientDescription,
        runtime.getClock().currentTimeMillis(),
        Optional.empty() /* startupOptionBundles */);
  }

  private BlazeCommandResult execExclusively(
      OriginalUnstructuredCommandLineEvent unstructuredServerCommandLineEvent,
      InvocationPolicy invocationPolicy,
      List<String> args,
      OutErr outErr,
      long firstContactTime,
      String commandName,
      BlazeCommand command,
      long waitTimeInMs,
      Optional<List<Pair<String, String>>> startupOptionsTaggedWithBazelRc) {
    // Record the start time for the profiler. Do not put anything before this!
    long execStartTimeNanos = runtime.getClock().nanoTime();

    Command commandAnnotation = command.getClass().getAnnotation(Command.class);
    BlazeWorkspace workspace = runtime.getWorkspace();

    StoredEventHandler storedEventHandler = new StoredEventHandler();
    BlazeOptionHandler optionHandler =
        new BlazeOptionHandler(
            runtime,
            workspace,
            command,
            commandAnnotation,
            // Provide the options parser so that we can cache OptionsData here.
            createOptionsParser(command),
            invocationPolicy);
    ExitCode earlyExitCode = optionHandler.parseOptions(args, storedEventHandler);
    OptionsParsingResult options = optionHandler.getOptionsResult();

    CommandLineEvent originalCommandLineEvent =
        new CommandLineEvent.OriginalCommandLineEvent(
            runtime, commandName, options, startupOptionsTaggedWithBazelRc);
    CommandLineEvent canonicalCommandLineEvent =
        new CommandLineEvent.CanonicalCommandLineEvent(runtime, commandName, options);

    // The initCommand call also records the start time for the timestamp granularity monitor.
    List<String> commandEnvWarnings = new ArrayList<>();
    CommandEnvironment env = workspace.initCommand(commandAnnotation, options, commandEnvWarnings);
    // Record the command's starting time for use by the commands themselves.
    env.recordCommandStartTime(firstContactTime);
    CommonCommandOptions commonOptions = options.getOptions(CommonCommandOptions.class);
    // TODO(ulfjack): Move the profiler initialization as early in the startup sequence as possible.
    // Profiler setup and shutdown must always happen in pairs. Shutdown is currently performed in
    // the afterCommand call in the finally block below.
    Path profilePath =
        runtime.initProfiler(
            storedEventHandler,
            workspace,
            commonOptions,
            env.getCommandId(),
            execStartTimeNanos,
            waitTimeInMs);
    if (commonOptions.postProfileStartedEvent) {
      storedEventHandler.post(new ProfilerStartedEvent(profilePath));
    }

    BlazeCommandResult result = BlazeCommandResult.exitCode(ExitCode.BLAZE_INTERNAL_ERROR);
    PrintStream savedOut = System.out;
    PrintStream savedErr = System.err;
    boolean afterCommandCalled = false;
    try {
      // Temporary: there are modules that output events during beforeCommand, but the reporter
      // isn't setup yet. Add the stored event handler to catch those events.
      env.getReporter().addHandler(storedEventHandler);
      for (BlazeModule module : runtime.getBlazeModules()) {
        try (SilentCloseable closeable = Profiler.instance().profile(module + ".beforeCommand")) {
          module.beforeCommand(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.
          storedEventHandler.handle(Event.error(e.getMessage()));
          // It's not ideal but we can only return one exit code, so we just pick the code of the
          // last exception.
          earlyExitCode = e.getExitCode();
        }
      }
      env.getReporter().removeHandler(storedEventHandler);

      // Setup stdout / stderr.
      outErr = tee(outErr, env.getOutputListeners());

      // Early exit. We need to guarantee that the ErrOut and Reporter setup below never error out,
      // so any invariants they need must be checked before this point.
      if (!earlyExitCode.equals(ExitCode.SUCCESS)) {
        return replayEarlyExitEvents(outErr, optionHandler, storedEventHandler, env, earlyExitCode);
      }

      Reporter reporter = env.getReporter();
      try (SilentCloseable closeable = Profiler.instance().profile("setup event handler")) {
        BlazeCommandEventHandler.Options eventHandlerOptions =
            options.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 = bufferOut(outErr, eventHandlerOptions.experimentalUi);
        }

        if (!commandAnnotation.binaryStdErr()) {
          outErr = bufferErr(outErr, eventHandlerOptions.experimentalUi);
        }

        if (!commonOptions.verbosity.equals(lastLogVerbosityLevel)) {
          BlazeRuntime.setupLogging(commonOptions.verbosity);
          lastLogVerbosityLevel = commonOptions.verbosity;
        }

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

        int oomMoreEagerlyThreshold = commonOptions.oomMoreEagerlyThreshold;
        if (oomMoreEagerlyThreshold == 100) {
          oomMoreEagerlyThreshold =
              runtime
                  .getStartupOptionsProvider()
                  .getOptions(BlazeServerStartupOptions.class)
                  .oomMoreEagerlyThreshold;
        }
        if (oomMoreEagerlyThreshold < 0 || oomMoreEagerlyThreshold > 100) {
          reporter.handle(Event.error("--oom_more_eagerly_threshold must be non-negative percent"));
          return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
        }
        if (oomMoreEagerlyThreshold != 100) {
          try {
            RetainedHeapLimiter.maybeInstallRetainedHeapLimiter(oomMoreEagerlyThreshold);
          } catch (OptionsParsingException e) {
            reporter.handle(Event.error(e.getMessage()));
            return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
          }
        }

        // 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 (SilentCloseable closeable = Profiler.instance().profile("replay stored events")) {
        // Now we're ready to replay the events.
        storedEventHandler.replayOn(reporter);
        for (String warning : commandEnvWarnings) {
          reporter.handle(Event.warn(warning));
        }
      }

      try (SilentCloseable closeable = Profiler.instance().profile("announce rc options")) {
        if (commonOptions.announceRcOptions) {
          if (startupOptionsTaggedWithBazelRc.isPresent()) {
            String lastBlazerc = "";
            List<String> accumulatedStartupOptions = new ArrayList<>();
            for (Pair<String, String> option : startupOptionsTaggedWithBazelRc.get()) {
              // Do not include the command line options, marked by the empty string.
              if (option.getFirst().isEmpty()) {
                continue;
              }

              // If we've moved to a new blazerc in the list, print out the info from the last one,
              // and clear the accumulated list.
              if (!lastBlazerc.isEmpty() && !option.getFirst().equals(lastBlazerc)) {
                String logMessage =
                    String.format(
                        "Reading 'startup' options from %s: %s",
                        lastBlazerc, String.join(", ", accumulatedStartupOptions));
                reporter.handle(Event.info(logMessage));
                accumulatedStartupOptions = new ArrayList<>();
              }

              lastBlazerc = option.getFirst();
              accumulatedStartupOptions.add(option.getSecond());
            }
            // Print out the final blazerc-grouped list, if any startup options were provided by
            // blazerc.
            if (!lastBlazerc.isEmpty()) {
              String logMessage =
                  String.format(
                      "Reading 'startup' options from %s: %s",
                      lastBlazerc, String.join(", ", accumulatedStartupOptions));
              reporter.handle(Event.info(logMessage));
            }
          }
          for (String note : optionHandler.getRcfileNotes()) {
            reporter.handle(Event.info(note));
          }
        }
      }

      // 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));

      try (SilentCloseable closeable = Profiler.instance().profile("CommandEnv.beforeCommand")) {
        // Notify the BlazeRuntime, so it can do some initial setup.
        env.beforeCommand(
            options,
            commonOptions,
            waitTimeInMs,
            invocationPolicy);
      } catch (AbruptExitException e) {
        reporter.handle(Event.error(e.getMessage()));
        return BlazeCommandResult.exitCode(e.getExitCode());
      }

      // Log the command line now that the modules have all had a change to register their listeners
      // to the event bus.
      env.getEventBus().post(unstructuredServerCommandLineEvent);
      env.getEventBus().post(originalCommandLineEvent);
      env.getEventBus().post(canonicalCommandLineEvent);
      env.getEventBus().post(commonOptions.toolCommandLine);

      for (BlazeModule module : runtime.getBlazeModules()) {
        try (SilentCloseable closeable =
            Profiler.instance().profile(module + ".injectExtraPrecomputedValues")) {
          env.getSkyframeExecutor().injectExtraPrecomputedValues(module.getPrecomputedValues());
        }
      }

      // Parse starlark options.
      earlyExitCode = optionHandler.parseStarlarkOptions(env, storedEventHandler);
      if (!earlyExitCode.equals(ExitCode.SUCCESS)) {
        return replayEarlyExitEvents(outErr, optionHandler, storedEventHandler, env, earlyExitCode);
      }
      options = optionHandler.getOptionsResult();

      result = command.exec(env, options);
      ExitCode moduleExitCode = env.precompleteCommand(result.getExitCode());
      // If Blaze did not suffer an infrastructure failure, check for errors in modules.
      if (!result.getExitCode().isInfrastructureFailure() && moduleExitCode != null) {
        result = BlazeCommandResult.exitCode(moduleExitCode);
      }

      afterCommandCalled = true;
      return runtime.afterCommand(env, result);
    } catch (Throwable e) {
      outErr.printErr(
          "Internal error thrown during build. Printing stack trace: "
              + Throwables.getStackTraceAsString(e));
      e.printStackTrace();
      BugReport.printBug(outErr, e);
      BugReport.sendBugReport(e, args, env.getCrashData());
      logger.log(Level.SEVERE, "Shutting down due to exception", e);
      return BlazeCommandResult.shutdown(BugReport.getExitCodeForThrowable(e));
    } finally {
      if (!afterCommandCalled) {
        runtime.afterCommand(env, result);
      }
      // Swallow IOException, as we are already in a finally clause
      Flushables.flushQuietly(outErr.getOutputStream());
      Flushables.flushQuietly(outErr.getErrorStream());

      System.setOut(savedOut);
      System.setErr(savedErr);
      env.getTimestampGranularityMonitor().waitForTimestampGranularity(outErr);
    }
  }

  private static BlazeCommandResult replayEarlyExitEvents(
      OutErr outErr,
      BlazeOptionHandler optionHandler,
      StoredEventHandler storedEventHandler,
      CommandEnvironment env,
      ExitCode earlyExitCode) {
    PrintingEventHandler printingEventHandler =
        new PrintingEventHandler(outErr, EventKind.ALL_EVENTS);
    for (String note : optionHandler.getRcfileNotes()) {
      printingEventHandler.handle(Event.info(note));
    }
    for (Event event : storedEventHandler.getEvents()) {
      printingEventHandler.handle(event);
    }
    for (Postable post : storedEventHandler.getPosts()) {
      env.getEventBus().post(post);
    }
    return BlazeCommandResult.exitCode(earlyExitCode);
  }

  private OutErr bufferOut(OutErr outErr, boolean fully) {
    OutputStream wrappedOut;
    if (fully) {
      wrappedOut = new BufferedOutputStream(outErr.getOutputStream());
    } else {
      wrappedOut = new LineBufferedOutputStream(outErr.getOutputStream());
    }
    return OutErr.create(wrappedOut, outErr.getErrorStream());
  }

  private OutErr bufferErr(OutErr outErr, boolean fully) {
    OutputStream wrappedErr;
    if (fully) {
      wrappedErr = new BufferedOutputStream(outErr.getErrorStream());
    } else {
      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 OutErr tee(OutErr outErr, List<OutErr> additionalOutErrs) {
    if (additionalOutErrs.isEmpty()) {
      return outErr;
    }
    DelegatingOutErr result = new DelegatingOutErr();
    result.addSink(outErr);
    for (OutErr additionalOutErr : additionalOutErrs) {
      result.addSink(additionalOutErr);
    }
    return result;
  }

  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 BlazeOptionHandler#parseOptions} for command-specific options.
   */
  private OptionsParser createOptionsParser(BlazeCommand command)
      throws OptionsParser.ConstructionException {
    OpaqueOptionsData optionsData;
    try {
      optionsData = optionsDataCache.getUnchecked(command);
    } catch (UncheckedExecutionException e) {
      Throwables.throwIfInstanceOf(e.getCause(), OptionsParser.ConstructionException.class);
      throw new IllegalStateException(e);
    }
    Command annotation = command.getClass().getAnnotation(Command.class);
    OptionsParser parser = OptionsParser.newOptionsParser(optionsData, "--//");
    parser.setAllowResidue(annotation.allowResidue());
    return parser;
  }

  /** Returns the event handler to use for this Blaze command. */
  private EventHandler createEventHandler(
      OutErr outErr, BlazeCommandEventHandler.Options eventOptions) {
    Path workspacePath = runtime.getWorkspace().getDirectories().getWorkspace();
    PathFragment workspacePathFragment = workspacePath == null ? null : workspacePath.asFragment();
    EventHandler eventHandler;
    if (eventOptions.experimentalUi) {
      // The experimental event handler is not to be rate limited, so don't wrap it in a
      // RateLimitingEventHandler.
      return new ExperimentalEventHandler(
          outErr, eventOptions, runtime.getClock(), workspacePathFragment);
    } else if ((eventOptions.useColor() || eventOptions.useCursorControl())) {
      eventHandler = new FancyTerminalEventHandler(outErr, eventOptions, workspacePathFragment);
    } else {
      eventHandler = new BlazeCommandEventHandler(outErr, eventOptions, workspacePathFragment);
    }

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

  /**
   * Returns the runtime instance shared by the commands that this dispatcher
   * dispatches to.
   */
  @VisibleForTesting
  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;
  }
}
