// 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 static com.google.devtools.build.lib.profiler.AutoProfiler.profiledAndLogged;
import static java.nio.charset.StandardCharsets.ISO_8859_1;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Range;
import com.google.common.collect.Sets;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.SubscriberExceptionContext;
import com.google.common.eventbus.SubscriberExceptionHandler;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.devtools.build.lib.actions.cache.ActionCache;
import com.google.devtools.build.lib.actions.cache.CompactPersistentActionCache;
import com.google.devtools.build.lib.actions.cache.NullActionCache;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.WorkspaceStatusAction;
import com.google.devtools.build.lib.analysis.config.BinTools;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.ConfigurationFactory;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.OutputFilter;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.packages.PackageFactory;
import com.google.devtools.build.lib.packages.Preprocessor;
import com.google.devtools.build.lib.packages.RuleClassProvider;
import com.google.devtools.build.lib.pkgcache.PackageManager;
import com.google.devtools.build.lib.profiler.AutoProfiler;
import com.google.devtools.build.lib.profiler.MemoryProfiler;
import com.google.devtools.build.lib.profiler.ProfilePhase;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.Profiler.ProfiledTaskKinds;
import com.google.devtools.build.lib.profiler.ProfilerTask;
import com.google.devtools.build.lib.query2.AbstractBlazeQueryEnvironment;
import com.google.devtools.build.lib.query2.QueryEnvironmentFactory;
import com.google.devtools.build.lib.query2.output.OutputFormatter;
import com.google.devtools.build.lib.rules.test.CoverageReportActionFactory;
import com.google.devtools.build.lib.runtime.commands.BuildCommand;
import com.google.devtools.build.lib.runtime.commands.CanonicalizeCommand;
import com.google.devtools.build.lib.runtime.commands.CleanCommand;
import com.google.devtools.build.lib.runtime.commands.DumpCommand;
import com.google.devtools.build.lib.runtime.commands.HelpCommand;
import com.google.devtools.build.lib.runtime.commands.InfoCommand;
import com.google.devtools.build.lib.runtime.commands.MobileInstallCommand;
import com.google.devtools.build.lib.runtime.commands.ProfileCommand;
import com.google.devtools.build.lib.runtime.commands.QueryCommand;
import com.google.devtools.build.lib.runtime.commands.RunCommand;
import com.google.devtools.build.lib.runtime.commands.ShutdownCommand;
import com.google.devtools.build.lib.runtime.commands.TestCommand;
import com.google.devtools.build.lib.runtime.commands.VersionCommand;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy;
import com.google.devtools.build.lib.server.RPCServer;
import com.google.devtools.build.lib.server.ServerCommand;
import com.google.devtools.build.lib.server.signal.InterruptSignalHandler;
import com.google.devtools.build.lib.skyframe.DiffAwareness;
import com.google.devtools.build.lib.skyframe.PrecomputedValue;
import com.google.devtools.build.lib.skyframe.SequencedSkyframeExecutorFactory;
import com.google.devtools.build.lib.skyframe.SkyValueDirtinessChecker;
import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
import com.google.devtools.build.lib.skyframe.SkyframeExecutorFactory;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.BlazeClock;
import com.google.devtools.build.lib.util.Clock;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.util.LoggingUtil;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.util.OsUtils;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.util.ThreadUtils;
import com.google.devtools.build.lib.util.io.OutErr;
import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.JavaIoFileSystem;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.UnixFileSystem;
import com.google.devtools.build.lib.vfs.WindowsFileSystem;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionPriority;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsClassProvider;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingException;
import com.google.devtools.common.options.OptionsProvider;
import com.google.devtools.common.options.TriState;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import javax.annotation.Nullable;

/**
 * The BlazeRuntime class encapsulates the immutable configuration of the current instance. These
 * runtime settings and services are available to most parts of any Blaze application for the
 * duration of the batch run or server lifetime.
 *
 * <p>The parts specific to the current command are stored in {@link CommandEnvironment}.
 */
public final class BlazeRuntime {
  public static final String DO_NOT_BUILD_FILE_NAME = "DO_NOT_BUILD_HERE";

  private static final Pattern suppressFromLog = Pattern.compile(".*(auth|pass|cookie).*",
      Pattern.CASE_INSENSITIVE);

  private static final Logger LOG = Logger.getLogger(BlazeRuntime.class.getName());

  private final Iterable<BlazeModule> blazeModules;
  private final Map<String, BlazeCommand> commandMap = new LinkedHashMap<>();
  private final Clock clock;

  private final PackageFactory packageFactory;
  private final ConfigurationFactory configurationFactory;
  private final ConfiguredRuleClassProvider ruleClassProvider;
  private final TimestampGranularityMonitor timestampGranularityMonitor;

  private final AtomicInteger storedExitCode = new AtomicInteger();

  // We pass this through here to make it available to the MasterLogWriter.
  private final OptionsProvider startupOptionsProvider;

  private final SubscriberExceptionHandler eventBusExceptionHandler;
  private final BinTools binTools;
  private final WorkspaceStatusAction.Factory workspaceStatusActionFactory;
  private final ProjectFile.Provider projectFileProvider;
  @Nullable
  private final InvocationPolicy invocationPolicy;

  // Workspace state (currently exactly one workspace per server)
  private final BlazeDirectories directories;
  private final SkyframeExecutor skyframeExecutor;
  private final QueryEnvironmentFactory queryEnvironmentFactory;
  /** The action cache is loaded lazily on the first build command. */
  private ActionCache actionCache;
  /** The execution time range of the previous build command in this server, if any. */
  @Nullable
  private Range<Long> lastExecutionRange = null;

  private BlazeRuntime(BlazeDirectories directories,
      WorkspaceStatusAction.Factory workspaceStatusActionFactory,
      final SkyframeExecutor skyframeExecutor,
      QueryEnvironmentFactory queryEnvironmentFactory,
      PackageFactory pkgFactory, ConfiguredRuleClassProvider ruleClassProvider,
      ConfigurationFactory configurationFactory, Clock clock,
      OptionsProvider startupOptionsProvider, Iterable<BlazeModule> blazeModules,
      TimestampGranularityMonitor timestampGranularityMonitor,
      SubscriberExceptionHandler eventBusExceptionHandler,
      BinTools binTools, ProjectFile.Provider projectFileProvider,
      InvocationPolicy invocationPolicy, Iterable<BlazeCommand> commands) {
    // Server state
    this.blazeModules = blazeModules;
    overrideCommands(commands);

    this.workspaceStatusActionFactory = workspaceStatusActionFactory;
    this.packageFactory = pkgFactory;
    this.binTools = binTools;
    this.projectFileProvider = projectFileProvider;
    this.invocationPolicy = invocationPolicy;

    this.ruleClassProvider = ruleClassProvider;
    this.configurationFactory = configurationFactory;
    this.clock = clock;
    this.timestampGranularityMonitor = Preconditions.checkNotNull(timestampGranularityMonitor);
    this.startupOptionsProvider = startupOptionsProvider;
    this.eventBusExceptionHandler = eventBusExceptionHandler;
    this.queryEnvironmentFactory = queryEnvironmentFactory;

    // Workspace state
    this.directories = directories;
    this.skyframeExecutor = skyframeExecutor;

    if (inWorkspace()) {
      writeOutputBaseReadmeFile();
      writeDoNotBuildHereFile();
    }
    setupExecRoot();
  }

  private static InvocationPolicy createInvocationPolicyFromModules(
      InvocationPolicy initialInvocationPolicy,
      Iterable<BlazeModule> modules) {
    InvocationPolicy.Builder builder = InvocationPolicy.newBuilder();
    builder.mergeFrom(initialInvocationPolicy);
    // Merge the policies from the modules
    for (BlazeModule module : modules) {
      InvocationPolicy modulePolicy = module.getInvocationPolicy();
      if (modulePolicy != null) {
        builder.mergeFrom(module.getInvocationPolicy());
      }
    }
    return builder.build();
  }

  @Nullable CoverageReportActionFactory getCoverageReportActionFactory() {
    CoverageReportActionFactory firstFactory = null;
    for (BlazeModule module : blazeModules) {
      CoverageReportActionFactory factory = module.getCoverageReportFactory();
      if (factory != null) {
        Preconditions.checkState(firstFactory == null,
            "only one Blaze Module can have a Coverage Report Factory");
        firstFactory = factory;
      }
    }
    return firstFactory;
  }

  /**
   * Adds the given command under the given name to the map of commands.
   *
   * @throws AssertionError if the name is already used by another command.
   */
  private void addCommand(BlazeCommand command) {
    String name = command.getClass().getAnnotation(Command.class).name();
    if (commandMap.containsKey(name)) {
      throw new IllegalStateException("Command name or alias " + name + " is already used.");
    }
    commandMap.put(name, command);
  }

  final void overrideCommands(Iterable<BlazeCommand> commands) {
    commandMap.clear();
    for (BlazeCommand command : commands) {
      addCommand(command);
    }
    for (BlazeModule module : blazeModules) {
      for (BlazeCommand command : module.getCommands()) {
        addCommand(command);
      }
    }
  }

  public CommandEnvironment initCommand() {
    EventBus eventBus = new EventBus(eventBusExceptionHandler);
    skyframeExecutor.setEventBus(eventBus);
    UUID commandId = UUID.randomUUID();
    return new CommandEnvironment(this, commandId, eventBus);
  }

  private void clearEventBus() {
    // EventBus does not have an unregister() method, so this is how we release memory associated
    // with handlers.
    skyframeExecutor.setEventBus(null);
  }

  @Nullable
  public InvocationPolicy getInvocationPolicy() {
    return invocationPolicy;
  }

  /**
   * Conditionally enable profiling.
   */
  private final boolean initProfiler(CommandEnvironment env, CommonCommandOptions options,
      UUID buildID, long execStartTimeNanos) {
    OutputStream out = null;
    boolean recordFullProfilerData = false;
    ProfiledTaskKinds profiledTasks = ProfiledTaskKinds.NONE;

    try {
      if (options.profilePath != null) {
        Path profilePath = getWorkspace().getRelative(options.profilePath);

        recordFullProfilerData = options.recordFullProfilerData;
        out = new BufferedOutputStream(profilePath.getOutputStream(), 1024 * 1024);
        env.getReporter().handle(Event.info("Writing profile data to '" + profilePath + "'"));
        profiledTasks = ProfiledTaskKinds.ALL;
      } else if (options.alwaysProfileSlowOperations) {
        recordFullProfilerData = false;
        out = null;
        profiledTasks = ProfiledTaskKinds.SLOWEST;
      }
      if (profiledTasks != ProfiledTaskKinds.NONE) {
        Profiler.instance().start(profiledTasks, out,
            "Blaze profile for " + getOutputBase() + " at " + new Date()
            + ", build ID: " + buildID,
            recordFullProfilerData, clock, execStartTimeNanos);
        return true;
      }
    } catch (IOException e) {
      env.getReporter().handle(Event.error("Error while creating profile file: " + e.getMessage()));
    }
    return false;
  }

  /**
   * Generates a README file in the output base directory. This README file
   * contains the name of the workspace directory, so that users can figure out
   * which output base directory corresponds to which workspace.
   */
  private void writeOutputBaseReadmeFile() {
    Preconditions.checkNotNull(getWorkspace());
    Path outputBaseReadmeFile = getOutputBase().getRelative("README");
    try {
      FileSystemUtils.writeIsoLatin1(outputBaseReadmeFile, "WORKSPACE: " + getWorkspace(), "",
          "The first line of this file is intentionally easy to parse for various",
          "interactive scripting and debugging purposes.  But please DO NOT write programs",
          "that exploit it, as they will be broken by design: it is not possible to",
          "reverse engineer the set of source trees or the --package_path from the output",
          "tree, and if you attempt it, you will fail, creating subtle and",
          "hard-to-diagnose bugs, that will no doubt get blamed on changes made by the",
          "Blaze team.", "", "This directory was generated by Blaze.",
          "Do not attempt to modify or delete any files in this directory.",
          "Among other issues, Blaze's file system caching assumes that",
          "only Blaze will modify this directory and the files in it,",
          "so if you change anything here you may mess up Blaze's cache.");
    } catch (IOException e) {
      LOG.warning("Couldn't write to '" + outputBaseReadmeFile + "': " + e.getMessage());
    }
  }

  private void writeDoNotBuildHereFile(Path filePath) {
    try {
      FileSystemUtils.createDirectoryAndParents(filePath.getParentDirectory());
      FileSystemUtils.writeContent(filePath, ISO_8859_1, getWorkspace().toString());
    } catch (IOException e) {
      LOG.warning("Couldn't write to '" + filePath + "': " + e.getMessage());
    }
  }

  private void writeDoNotBuildHereFile() {
    Preconditions.checkNotNull(getWorkspace());
    writeDoNotBuildHereFile(getOutputBase().getRelative(DO_NOT_BUILD_FILE_NAME));
    if (startupOptionsProvider.getOptions(BlazeServerStartupOptions.class).deepExecRoot) {
      writeDoNotBuildHereFile(getOutputBase().getRelative("execroot").getRelative(
          DO_NOT_BUILD_FILE_NAME));
    }
  }

  /**
   * Creates the execRoot dir under outputBase.
   */
  private void setupExecRoot() {
    try {
      FileSystemUtils.createDirectoryAndParents(directories.getExecRoot());
    } catch (IOException e) {
      LOG.warning("failed to create execution root '" + directories.getExecRoot() + "': "
          + e.getMessage());
    }
  }

  void recordLastExecutionTime(long commandStartTime) {
    long currentTimeMillis = clock.currentTimeMillis();
    lastExecutionRange = currentTimeMillis >= commandStartTime
        ? Range.closed(commandStartTime, currentTimeMillis)
        : null;
  }

  /**
   * Range that represents the last execution time of a build in millis since epoch.
   */
  @Nullable
  public Range<Long> getLastExecutionTimeRange() {
    return lastExecutionRange;
  }

  public String getWorkspaceName() {
    Path workspace = directories.getWorkspace();
    if (workspace == null) {
      return "";
    }
    return workspace.getBaseName();
  }

  /**
   * Returns the Blaze directories object for this runtime.
   */
  public BlazeDirectories getDirectories() {
    return directories;
  }

  /**
   * Returns the working directory of the server.
   *
   * <p>This is often the first entry on the {@code --package_path}, but not always.
   * Callers should certainly not make this assumption. The Path returned may be null.
   */
  public Path getWorkspace() {
    return directories.getWorkspace();
  }

  /**
   * Returns if the client passed a valid workspace to be used for the build.
   */
  public boolean inWorkspace() {
    return directories.inWorkspace();
  }

  /**
   * Returns the output base directory associated with this Blaze server
   * process. This is the base directory for shared Blaze state as well as tool
   * and strategy specific subdirectories.
   */
  public Path getOutputBase() {
    return directories.getOutputBase();
  }

  /**
   * Returns the output path associated with this Blaze server process..
   */
  public Path getOutputPath() {
    return directories.getOutputPath();
  }

  /**
   * The directory in which blaze stores the server state - that is, the socket
   * file and a log.
   */
  public Path getServerDirectory() {
    return getOutputBase().getChild("server");
  }

  /**
   * Returns the execution root directory associated with this Blaze server
   * process. This is where all input and output files visible to the actual
   * build reside.
   */
  public Path getExecRoot() {
    return directories.getExecRoot();
  }

  public BinTools getBinTools() {
    return binTools;
  }

  /**
   * Returns the skyframe executor.
   */
  public SkyframeExecutor getSkyframeExecutor() {
    return skyframeExecutor;
  }

  /**
   * Returns the {@link QueryEnvironmentFactory} that should be used to create a
   * {@link AbstractBlazeQueryEnvironment}, whenever one is needed.
   */
  public QueryEnvironmentFactory getQueryEnvironmentFactory() {
    return queryEnvironmentFactory;
  }

  /**
   * Returns the package factory.
   */
  public PackageFactory getPackageFactory() {
    return packageFactory;
  }

  public ImmutableList<OutputFormatter> getQueryOutputFormatters() {
    ImmutableList.Builder<OutputFormatter> result = ImmutableList.builder();
    result.addAll(OutputFormatter.getDefaultFormatters());
    for (BlazeModule module : blazeModules) {
      result.addAll(module.getQueryOutputFormatters());
    }

    return result.build();
  }

  /**
   * Returns the package manager.
   */
  public PackageManager getPackageManager() {
    return skyframeExecutor.getPackageManager();
  }

  public WorkspaceStatusAction.Factory getworkspaceStatusActionFactory() {
    return workspaceStatusActionFactory;
  }

  /**
   * Returns the rule class provider.
   */
  public ConfiguredRuleClassProvider getRuleClassProvider() {
    return ruleClassProvider;
  }

  public Iterable<BlazeModule> getBlazeModules() {
    return blazeModules;
  }

  @SuppressWarnings("unchecked")
  public <T extends BlazeModule> T getBlazeModule(Class<T> moduleClass) {
    for (BlazeModule module : blazeModules) {
      if (module.getClass() == moduleClass) {
        return (T) module;
      }
    }

    return null;
  }

  public ConfigurationFactory getConfigurationFactory() {
    return configurationFactory;
  }

  /**
   * Returns reference to the lazily instantiated persistent action cache
   * instance. Note, that method may recreate instance between different build
   * requests, so return value should not be cached.
   */
  public ActionCache getPersistentActionCache(Reporter reporter) throws IOException {
    if (actionCache == null) {
      if (OS.getCurrent() == OS.WINDOWS) {
        // TODO(bazel-team): Add support for a persistent action cache on Windows.
        actionCache = new NullActionCache();
        return actionCache;
      }
      try (AutoProfiler p = profiledAndLogged("Loading action cache", ProfilerTask.INFO, LOG)) {
        try {
          actionCache = new CompactPersistentActionCache(getCacheDirectory(), clock);
        } catch (IOException e) {
          LOG.log(Level.WARNING, "Failed to load action cache: " + e.getMessage(), e);
          LoggingUtil.logToRemote(Level.WARNING, "Failed to load action cache: "
              + e.getMessage(), e);
          reporter.handle(
              Event.error("Error during action cache initialization: " + e.getMessage()
              + ". Corrupted files were renamed to '" + getCacheDirectory() + "/*.bad'. "
              + "Blaze will now reset action cache data, causing a full rebuild"));
          actionCache = new CompactPersistentActionCache(getCacheDirectory(), clock);
        }
      }
    }
    return actionCache;
  }

  /**
   * Removes in-memory caches.
   */
  public void clearCaches() throws IOException {
    skyframeExecutor.resetEvaluator();
    actionCache = null;
    FileSystemUtils.deleteTree(getCacheDirectory());
  }

  /**
   * Returns the TimestampGranularityMonitor. The same monitor object is used
   * across multiple Blaze commands, but it doesn't hold any persistent state
   * across different commands.
   */
  public TimestampGranularityMonitor getTimestampGranularityMonitor() {
    return timestampGranularityMonitor;
  }

  /**
   * Returns path to the cache directory. Path must be inside output base to
   * ensure that users can run concurrent instances of blaze in different
   * clients without attempting to concurrently write to the same action cache
   * on disk, which might not be safe.
   */
  private Path getCacheDirectory() {
    return getOutputBase().getChild("action_cache");
  }

  /**
   * Returns a provider for project file objects. Can be null if no such provider was set by any of
   * the modules.
   */
  @Nullable
  public ProjectFile.Provider getProjectFileProvider() {
    return projectFileProvider;
  }

  /**
   * Hook method called by the BlazeCommandDispatcher prior to the dispatch of
   * each command.
   *
   * @param options The CommonCommandOptions used by every command.
   * @throws AbruptExitException if this command is unsuitable to be run as specified
   */
  void beforeCommand(CommandEnvironment env, CommonCommandOptions options, long execStartTimeNanos)
      throws AbruptExitException {
    // Conditionally enable profiling
    // We need to compensate for launchTimeNanos (measurements taken outside of the jvm).
    long startupTimeNanos = options.startupTime * 1000000L;
    if (initProfiler(env, options, env.getCommandId(), execStartTimeNanos - startupTimeNanos)) {
      Profiler profiler = Profiler.instance();

      // Instead of logEvent() we're calling the low level function to pass the timings we took in
      // the launcher. We're setting the INIT phase marker so that it follows immediately the LAUNCH
      // phase.
      profiler.logSimpleTaskDuration(execStartTimeNanos - startupTimeNanos, 0, ProfilerTask.PHASE,
          ProfilePhase.LAUNCH.description);
      profiler.logSimpleTaskDuration(execStartTimeNanos, 0, ProfilerTask.PHASE,
          ProfilePhase.INIT.description);
    }

    if (options.memoryProfilePath != null) {
      Path memoryProfilePath = env.getWorkingDirectory().getRelative(options.memoryProfilePath);
      try {
        MemoryProfiler.instance().start(memoryProfilePath.getOutputStream());
      } catch (IOException e) {
        env.getReporter().handle(
            Event.error("Error while creating memory profile file: " + e.getMessage()));
      }
    }

    // Initialize exit code to dummy value for afterCommand.
    storedExitCode.set(ExitCode.RESERVED.getNumericExitCode());
  }

  /**
   * Posts the {@link CommandCompleteEvent}, so that listeners can tidy up. Called by {@link
   * #afterCommand}, and by BugReport when crashing from an exception in an async thread.
   */
  public void notifyCommandComplete(int exitCode) {
    if (!storedExitCode.compareAndSet(ExitCode.RESERVED.getNumericExitCode(), exitCode)) {
      // This command has already been called, presumably because there is a race between the main
      // thread and a worker thread that crashed. Don't try to arbitrate the dispute. If the main
      // thread won the race (unlikely, but possible), this may be incorrectly logged as a success.
      return;
    }
    skyframeExecutor.getEventBus().post(new CommandCompleteEvent(exitCode));
  }

  /**
   * Hook method called by the BlazeCommandDispatcher after the dispatch of each
   * command.
   */
  @VisibleForTesting
  public void afterCommand(CommandEnvironment env, int exitCode) {
    // Remove any filters that the command might have added to the reporter.
    env.getReporter().setOutputFilter(OutputFilter.OUTPUT_EVERYTHING);

    notifyCommandComplete(exitCode);

    for (BlazeModule module : blazeModules) {
      module.afterCommand();
    }

    clearEventBus();

    try {
      Profiler.instance().stop();
      MemoryProfiler.instance().stop();
    } catch (IOException e) {
      env.getReporter().handle(Event.error("Error while writing profile file: " + e.getMessage()));
    }
  }

  // Make sure we keep a strong reference to this logger, so that the
  // configuration isn't lost when the gc kicks in.
  private static Logger templateLogger = Logger.getLogger("com.google.devtools.build");

  /**
   * Configures "com.google.devtools.build.*" loggers to the given
   *  {@code level}. Note: This code relies on static state.
   */
  public static void setupLogging(Level level) {
    templateLogger.setLevel(level);
    templateLogger.info("Log level: " + templateLogger.getLevel());
  }

  /**
   * Returns the Clock-instance used for the entire build. Before,
   * individual classes (such as Profiler) used to specify the type
   * of clock (e.g. EpochClock) they wanted to use. This made it
   * difficult to get Blaze working on Windows as some of the clocks
   * available for Linux aren't (directly) available on Windows.
   * Setting the Blaze-wide clock upon construction of BlazeRuntime
   * allows injecting whatever Clock instance should be used from
   * BlazeMain.
   *
   * @return The Blaze-wide clock
   */
  public Clock getClock() {
    return clock;
  }

  public OptionsProvider getStartupOptionsProvider() {
    return startupOptionsProvider;
  }

  /**
   * An array of String values useful if Blaze crashes.
   * For now, just returns the size of the action cache and the build id.
   */
  public String[] getCrashData(CommandEnvironment env) {
    return new String[]{
        getFileSizeString(CompactPersistentActionCache.cacheFile(getCacheDirectory()),
                          "action cache"),
        env.getCommandId() + " (build id)",
    };
  }

  private String getFileSizeString(Path path, String type) {
    try {
      return String.format("%d bytes (%s)", path.getFileSize(), type);
    } catch (IOException e) {
      return String.format("unknown file size (%s)", type);
    }
  }

  public Map<String, BlazeCommand> getCommandMap() {
    return commandMap;
  }

  public void shutdown() {
    for (BlazeModule module : blazeModules) {
      module.blazeShutdown();
    }
  }

  /**
   * Returns the defaults package for the default settings. Should only be called by commands that
   * do <i>not</i> process {@link BuildOptions}, since build options can alter the contents of the
   * defaults package, which will not be reflected here.
   */
  public String getDefaultsPackageContent() {
    return ruleClassProvider.getDefaultsPackageContent();
  }

  /**
   * Returns the defaults package for the given options taken from an optionsProvider.
   */
  public String getDefaultsPackageContent(OptionsClassProvider optionsProvider) {
    return ruleClassProvider.getDefaultsPackageContent(optionsProvider);
  }

  /**
   * Creates a BuildOptions class for the given options taken from an optionsProvider.
   */
  public BuildOptions createBuildOptions(OptionsClassProvider optionsProvider) {
    return ruleClassProvider.createBuildOptions(optionsProvider);
  }

  /**
   * An EventBus exception handler that will report the exception to a remote server, if a
   * handler is registered.
   */
  public static final class RemoteExceptionHandler implements SubscriberExceptionHandler {
    @Override
    public void handleException(Throwable exception, SubscriberExceptionContext context) {
      LOG.log(Level.SEVERE, "Failure in EventBus subscriber", exception);
      LoggingUtil.logToRemote(Level.SEVERE, "Failure in EventBus subscriber.", exception);
    }
  }

  /**
   * An EventBus exception handler that will call BugReport.handleCrash exiting
   * the current thread.
   */
  public static final class BugReportingExceptionHandler implements SubscriberExceptionHandler {
    @Override
    public void handleException(Throwable exception, SubscriberExceptionContext context) {
      BugReport.handleCrash(exception);
    }
  }

  /**
   * Main method for the Blaze server startup. Note: This method logs
   * exceptions to remote servers. Do not add this to a unittest.
   */
  public static void main(Iterable<Class<? extends BlazeModule>> moduleClasses, String[] args) {
    setupUncaughtHandler(args);
    List<BlazeModule> modules = createModules(moduleClasses);
    // blaze.cc will put --batch first if the user set it.
    if (args.length >= 1 && args[0].equals("--batch")) {
      // Run Blaze in batch mode.
      System.exit(batchMain(modules, args));
    }
    LOG.info("Starting Blaze server with args " + Arrays.toString(args));
    try {
      // Run Blaze in server mode.
      System.exit(serverMain(modules, OutErr.SYSTEM_OUT_ERR, args));
    } catch (RuntimeException | Error e) { // A definite bug...
      BugReport.printBug(OutErr.SYSTEM_OUT_ERR, e);
      BugReport.sendBugReport(e, Arrays.asList(args));
      System.exit(ExitCode.BLAZE_INTERNAL_ERROR.getNumericExitCode());
      throw e; // Shouldn't get here.
    }
  }

  @VisibleForTesting
  public static List<BlazeModule> createModules(
      Iterable<Class<? extends BlazeModule>> moduleClasses) {
    ImmutableList.Builder<BlazeModule> result = ImmutableList.builder();
    for (Class<? extends BlazeModule> moduleClass : moduleClasses) {
      try {
        BlazeModule module = moduleClass.newInstance();
        result.add(module);
      } catch (Throwable e) {
        throw new IllegalStateException("Cannot instantiate module " + moduleClass.getName(), e);
      }
    }

    return result.build();
  }

  /**
   * Generates a string form of a request to be written to the logs,
   * filtering the user environment to remove anything that looks private.
   * The current filter criteria removes any variable whose name includes
   * "auth", "pass", or "cookie".
   *
   * @param requestStrings
   * @return the filtered request to write to the log.
   */
  @VisibleForTesting
  public static String getRequestLogString(List<String> requestStrings) {
    StringBuilder buf = new StringBuilder();
    buf.append('[');
    String sep = "";
    for (String s : requestStrings) {
      buf.append(sep);
      if (s.startsWith("--client_env")) {
        int varStart = "--client_env=".length();
        int varEnd = s.indexOf('=', varStart);
        String varName = s.substring(varStart, varEnd);
        if (suppressFromLog.matcher(varName).matches()) {
          buf.append("--client_env=");
          buf.append(varName);
          buf.append("=__private_value_removed__");
        } else {
          buf.append(s);
        }
      } else {
        buf.append(s);
      }
      sep = ", ";
    }
    buf.append(']');
    return buf.toString();
  }

  /**
   * Command line options split in to two parts: startup options and everything else.
   */
  @VisibleForTesting
  static class CommandLineOptions {
    private final List<String> startupArgs;
    private final List<String> otherArgs;

    CommandLineOptions(List<String> startupArgs, List<String> otherArgs) {
      this.startupArgs = ImmutableList.copyOf(startupArgs);
      this.otherArgs = ImmutableList.copyOf(otherArgs);
    }

    public List<String> getStartupArgs() {
      return startupArgs;
    }

    public List<String> getOtherArgs() {
      return otherArgs;
    }
  }

  /**
   * Splits given arguments into two lists - arguments matching options defined in this class
   * and everything else, while preserving order in each list.
   */
  static CommandLineOptions splitStartupOptions(
      Iterable<BlazeModule> modules, String... args) {
    List<String> prefixes = new ArrayList<>();
    List<Field> startupFields = Lists.newArrayList();
    for (Class<? extends OptionsBase> defaultOptions
      : BlazeCommandUtils.getStartupOptions(modules)) {
      startupFields.addAll(ImmutableList.copyOf(defaultOptions.getFields()));
    }

    for (Field field : startupFields) {
      if (field.isAnnotationPresent(Option.class)) {
        prefixes.add("--" + field.getAnnotation(Option.class).name());
        if (field.getType() == boolean.class || field.getType() == TriState.class) {
          prefixes.add("--no" + field.getAnnotation(Option.class).name());
        }
      }
    }

    List<String> startupArgs = new ArrayList<>();
    List<String> otherArgs = Lists.newArrayList(args);

    for (Iterator<String> argi = otherArgs.iterator(); argi.hasNext(); ) {
      String arg = argi.next();
      if (!arg.startsWith("--")) {
        break;  // stop at command - all startup options would be specified before it.
      }
      for (String prefix : prefixes) {
        if (arg.startsWith(prefix)) {
          startupArgs.add(arg);
          argi.remove();
          break;
        }
      }
    }
    return new CommandLineOptions(startupArgs, otherArgs);
  }

  private static void captureSigint() {
    final Thread mainThread = Thread.currentThread();
    final AtomicInteger numInterrupts = new AtomicInteger();

    final Runnable interruptWatcher = new Runnable() {
      @Override
      public void run() {
        int count = 0;
        // Not an actual infinite loop because it's run in a daemon thread.
        while (true) {
          count++;
          Uninterruptibles.sleepUninterruptibly(10, TimeUnit.SECONDS);
          LOG.warning("Slow interrupt number " + count + " in batch mode");
          ThreadUtils.warnAboutSlowInterrupt();
        }
      }
    };

    new InterruptSignalHandler() {
      @Override
      protected void onSignal() {
        LOG.info("User interrupt");
        OutErr.SYSTEM_OUT_ERR.printErrLn("Blaze received an interrupt");
        mainThread.interrupt();

        int curNumInterrupts = numInterrupts.incrementAndGet();
        if (curNumInterrupts == 1) {
          Thread interruptWatcherThread = new Thread(interruptWatcher, "interrupt-watcher");
          interruptWatcherThread.setDaemon(true);
          interruptWatcherThread.start();
        } else if (curNumInterrupts == 2) {
          LOG.warning("Second --batch interrupt: Reverting to JVM SIGINT handler");
          uninstall();
        }
      }
    };
  }

  /**
   * A main method that runs blaze commands in batch mode. The return value indicates the desired
   * exit status of the program.
   */
  private static int batchMain(Iterable<BlazeModule> modules, String[] args) {
    captureSigint();
    CommandLineOptions commandLineOptions = splitStartupOptions(modules, args);
    LOG.info("Running Blaze in batch mode with startup args "
        + commandLineOptions.getStartupArgs());

    BlazeRuntime runtime;
    try {
      runtime = newRuntime(modules, parseOptions(modules, commandLineOptions.getStartupArgs()));
    } catch (OptionsParsingException e) {
      OutErr.SYSTEM_OUT_ERR.printErr(e.getMessage());
      return ExitCode.COMMAND_LINE_ERROR.getNumericExitCode();
    } catch (AbruptExitException e) {
      OutErr.SYSTEM_OUT_ERR.printErr(e.getMessage());
      return e.getExitCode().getNumericExitCode();
    }

    BlazeCommandDispatcher dispatcher = new BlazeCommandDispatcher(runtime);

    try {
      LOG.info(getRequestLogString(commandLineOptions.getOtherArgs()));
      return dispatcher.exec(commandLineOptions.getOtherArgs(), OutErr.SYSTEM_OUT_ERR,
          runtime.getClock().currentTimeMillis());
    } catch (BlazeCommandDispatcher.ShutdownBlazeServerException e) {
      return e.getExitStatus();
    } finally {
      runtime.shutdown();
      dispatcher.shutdown();
    }
  }

  /**
   * A main method that does not send email. The return value indicates the desired exit status of
   * the program.
   */
  private static int serverMain(Iterable<BlazeModule> modules, OutErr outErr, String[] args) {
    try {
      createBlazeRPCServer(modules, Arrays.asList(args)).serve();
      return ExitCode.SUCCESS.getNumericExitCode();
    } catch (OptionsParsingException e) {
      outErr.printErr(e.getMessage());
      return ExitCode.COMMAND_LINE_ERROR.getNumericExitCode();
    } catch (IOException e) {
      outErr.printErr("I/O Error: " + e.getMessage());
      return ExitCode.BUILD_FAILURE.getNumericExitCode();
    } catch (AbruptExitException e) {
      outErr.printErr(e.getMessage());
      return e.getExitCode().getNumericExitCode();
    }
  }

  private static FileSystem fileSystemImplementation() {
    if ("0".equals(System.getProperty("io.bazel.UnixFileSystem"))) {
      // Ignore UnixFileSystem, to be used for bootstrapping.
      return OS.getCurrent() == OS.WINDOWS ? new WindowsFileSystem() : new JavaIoFileSystem();
    }
    // The JNI-based UnixFileSystem is faster, but on Windows it is not available.
    return OS.getCurrent() == OS.WINDOWS ? new WindowsFileSystem() : new UnixFileSystem();
  }

  /**
   * Creates and returns a new Blaze RPCServer. Call {@link RPCServer#serve()} to start the server.
   */
  private static RPCServer createBlazeRPCServer(Iterable<BlazeModule> modules, List<String> args)
      throws IOException, OptionsParsingException, AbruptExitException {
    OptionsProvider options = parseOptions(modules, args);
    BlazeServerStartupOptions startupOptions = options.getOptions(BlazeServerStartupOptions.class);

    final BlazeRuntime runtime = newRuntime(modules, options);
    final BlazeCommandDispatcher dispatcher = new BlazeCommandDispatcher(runtime);

    final ServerCommand blazeCommand;

    // Adaptor from RPC mechanism to BlazeCommandDispatcher:
    blazeCommand = new ServerCommand() {
      private boolean shutdown = false;

      @Override
      public int exec(List<String> args, OutErr outErr, long firstContactTime) {
        LOG.info(getRequestLogString(args));

        try {
          return dispatcher.exec(args, outErr, firstContactTime);
        } catch (BlazeCommandDispatcher.ShutdownBlazeServerException e) {
          if (e.getCause() != null) {
            StringWriter message = new StringWriter();
            message.write("Shutting down due to exception:\n");
            PrintWriter writer = new PrintWriter(message, true);
            e.printStackTrace(writer);
            writer.flush();
            LOG.severe(message.toString());
          }
          shutdown = true;
          runtime.shutdown();
          dispatcher.shutdown();
          return e.getExitStatus();
        }
      }

      @Override
      public boolean shutdown() {
        return shutdown;
      }
    };

    RPCServer server = RPCServer.newServerWith(runtime.getClock(), blazeCommand,
        runtime.getServerDirectory(), runtime.getWorkspace(), startupOptions.maxIdleSeconds);
    return server;
  }

  private static Function<String, String> sourceFunctionForMap(final Map<String, String> map) {
    return new Function<String, String>() {
      @Override
      public String apply(String input) {
        if (!map.containsKey(input)) {
          return "default";
        }

        if (map.get(input).isEmpty()) {
          return "command line";
        }

        return map.get(input);
      }
    };
  }

  /**
   * Parses the command line arguments into a {@link OptionsParser} object.
   *
   *  <p>This function needs to parse the --option_sources option manually so that the real option
   * parser can set the source for every option correctly. If that cannot be parsed or is missing,
   * we just report an unknown source for every startup option.
   */
  private static OptionsProvider parseOptions(
      Iterable<BlazeModule> modules, List<String> args) throws OptionsParsingException {
    Set<Class<? extends OptionsBase>> optionClasses = Sets.newHashSet();
    optionClasses.addAll(BlazeCommandUtils.getStartupOptions(modules));
    // First parse the command line so that we get the option_sources argument
    OptionsParser parser = OptionsParser.newOptionsParser(optionClasses);
    parser.setAllowResidue(false);
    parser.parse(OptionPriority.COMMAND_LINE, null, args);
    Function<? super String, String> sourceFunction =
        sourceFunctionForMap(parser.getOptions(BlazeServerStartupOptions.class).optionSources);

    // Then parse the command line again, this time with the correct option sources
    parser = OptionsParser.newOptionsParser(optionClasses);
    parser.setAllowResidue(false);
    parser.parseWithSourceFunction(OptionPriority.COMMAND_LINE, sourceFunction, args);
    return parser;
  }

  /**
   * Creates a new blaze runtime, given the install and output base directories.
   *
   * <p>Note: This method can and should only be called once per startup, as it also creates the
   * filesystem object that will be used for the runtime. So it should only ever be called from the
   * main method of the Blaze program.
   *
   * @param options Blaze startup options.
   *
   * @return a new BlazeRuntime instance initialized with the given filesystem and directories, and
   *         an error string that, if not null, describes a fatal initialization failure that makes
   *         this runtime unsuitable for real commands
   */
  private static BlazeRuntime newRuntime(
      Iterable<BlazeModule> blazeModules, OptionsProvider options) throws AbruptExitException {
    for (BlazeModule module : blazeModules) {
      module.globalInit(options);
    }

    BlazeServerStartupOptions startupOptions = options.getOptions(BlazeServerStartupOptions.class);
    if (startupOptions.batch && startupOptions.oomMoreEagerly) {
      new OomSignalHandler();
    }
    PathFragment workspaceDirectory = startupOptions.workspaceDirectory;
    PathFragment installBase = startupOptions.installBase;
    PathFragment outputBase = startupOptions.outputBase;

    OsUtils.maybeForceJNI(installBase);  // Must be before first use of JNI.

    // From the point of view of the Java program --install_base and --output_base
    // are mandatory options, despite the comment in their declarations.
    if (installBase == null || !installBase.isAbsolute()) { // (includes "" default case)
      throw new IllegalArgumentException(
          "Bad --install_base option specified: '" + installBase + "'");
    }
    if (outputBase != null && !outputBase.isAbsolute()) { // (includes "" default case)
      throw new IllegalArgumentException(
          "Bad --output_base option specified: '" + outputBase + "'");
    }

    PathFragment outputPathFragment = BlazeDirectories.outputPathFromOutputBase(
        outputBase, workspaceDirectory, startupOptions.deepExecRoot);
    FileSystem fs = null;
    for (BlazeModule module : blazeModules) {
      FileSystem moduleFs = module.getFileSystem(options, outputPathFragment);
      if (moduleFs != null) {
        Preconditions.checkState(fs == null, "more than one module returns a file system");
        fs = moduleFs;
      }
    }

    if (fs == null) {
      fs = fileSystemImplementation();
    }
    Path.setFileSystemForSerialization(fs);

    Path installBasePath = fs.getPath(installBase);
    Path outputBasePath = fs.getPath(outputBase);
    Path workspaceDirectoryPath = null;
    if (!workspaceDirectory.equals(PathFragment.EMPTY_FRAGMENT)) {
      workspaceDirectoryPath = fs.getPath(workspaceDirectory);
    }

    if (fs instanceof UnixFileSystem) {
      ((UnixFileSystem) fs).setRootsWithAllowedHardlinks(
          // Some tests pass nulls for these paths, so remove these from the list
          Iterables.filter(
              Arrays.asList(installBasePath, outputBasePath, workspaceDirectoryPath),
              Predicates.notNull()));
    }

    BlazeDirectories directories =
        new BlazeDirectories(installBasePath, outputBasePath, workspaceDirectoryPath,
                             startupOptions.deepExecRoot, startupOptions.installMD5);

    Clock clock = BlazeClock.instance();

    BinTools binTools;
    try {
      binTools = BinTools.forProduction(directories);
    } catch (IOException e) {
      throw new AbruptExitException(
          "Cannot enumerate embedded binaries: " + e.getMessage(),
          ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
    }

    BlazeRuntime.Builder runtimeBuilder = new BlazeRuntime.Builder().setDirectories(directories)
        .setStartupOptionsProvider(options)
        .setBinTools(binTools)
        .setClock(clock)
        // TODO(bazel-team): Make BugReportingExceptionHandler the default.
        // See bug "Make exceptions in EventBus subscribers fatal"
        .setEventBusExceptionHandler(
            startupOptions.fatalEventBusExceptions || !BlazeVersionInfo.instance().isReleasedBlaze()
                ? new BlazeRuntime.BugReportingExceptionHandler()
                : new BlazeRuntime.RemoteExceptionHandler());

    if (System.getenv("TEST_TMPDIR") != null
        && System.getenv("NO_CRASH_ON_LOGGING_IN_TEST") == null) {
      LoggingUtil.installRemoteLogger(getTestCrashLogger());
    }

    for (BlazeModule blazeModule : blazeModules) {
      runtimeBuilder.addBlazeModule(blazeModule);
    }
    runtimeBuilder.addCommands(getBuiltinCommandList());

    BlazeRuntime runtime = runtimeBuilder.build();
    AutoProfiler.setClock(runtime.getClock());
    BugReport.setRuntime(runtime);
    return runtime;
  }

  /**
   * Returns a logger that crashes as soon as it's written to, since tests should not cause events
   * that would be logged.
   */
  @VisibleForTesting
  public static Future<Logger> getTestCrashLogger() {
    Logger crashLogger = Logger.getAnonymousLogger();
    crashLogger.addHandler(
        new Handler() {
          @Override
          public void publish(LogRecord record) {
            System.err.println("Remote logging disabled for testing, forcing abrupt shutdown.");
            System.err.printf("%s#%s: %s\n",
                record.getSourceClassName(),
                record.getSourceMethodName(),
                record.getMessage());

            Throwable e = record.getThrown();
            if (e != null) {
              e.printStackTrace();
            }

            Runtime.getRuntime().halt(ExitCode.BLAZE_INTERNAL_ERROR.getNumericExitCode());
          }

          @Override
          public void flush() {
            throw new IllegalStateException();
          }

          @Override
          public void close() {
            throw new IllegalStateException();
          }
        });
    return Futures.immediateFuture(crashLogger);
  }

  /**
   * Make sure async threads cannot be orphaned. This method makes sure bugs are reported to
   * telemetry and the proper exit code is reported.
   */
  private static void setupUncaughtHandler(final String[] args) {
    Thread.setDefaultUncaughtExceptionHandler(
        new Thread.UncaughtExceptionHandler() {
          @Override
          public void uncaughtException(Thread thread, Throwable throwable) {
            BugReport.handleCrash(throwable, args);
          }
        });
  }


  /**
   * Returns an immutable list containing new instances of each Blaze command.
   */
  @VisibleForTesting
  public static List<BlazeCommand> getBuiltinCommandList() {
    return ImmutableList.of(
        new BuildCommand(),
        new CanonicalizeCommand(),
        new CleanCommand(),
        new DumpCommand(),
        new HelpCommand(),
        new InfoCommand(),
        new MobileInstallCommand(),
        new ProfileCommand(),
        new QueryCommand(),
        new RunCommand(),
        new ShutdownCommand(),
        new TestCommand(),
        new VersionCommand());
  }

  /**
   * A builder for {@link BlazeRuntime} objects. The only required fields are the {@link
   * BlazeDirectories}, and the {@link RuleClassProvider} (except for testing). All other fields
   * have safe default values.
   *
   * <p>If a {@link ConfigurationFactory} is set, then the builder ignores the host system flag.
   * <p>The default behavior of the BlazeRuntime's EventBus is to exit when a subscriber throws
   * an exception. Please plan appropriately.
   */
  public static class Builder {

    private BlazeDirectories directories;
    private ConfigurationFactory configurationFactory;
    private Clock clock;
    private OptionsProvider startupOptionsProvider;
    private final List<BlazeModule> blazeModules = new ArrayList<>();
    private SubscriberExceptionHandler eventBusExceptionHandler =
        new RemoteExceptionHandler();
    private BinTools binTools;
    private UUID instanceId;
    private final List<BlazeCommand> commands = new ArrayList<>();
    private InvocationPolicy invocationPolicy = InvocationPolicy.getDefaultInstance();

    public BlazeRuntime build() throws AbruptExitException {
      Preconditions.checkNotNull(directories);
      Preconditions.checkNotNull(startupOptionsProvider);

      Clock clock = (this.clock == null) ? BlazeClock.instance() : this.clock;
      UUID instanceId =  (this.instanceId == null) ? UUID.randomUUID() : this.instanceId;

      Preconditions.checkNotNull(clock);
      TimestampGranularityMonitor timestampMonitor = new TimestampGranularityMonitor(clock);

      Preprocessor.Factory.Supplier preprocessorFactorySupplier = null;
      SkyframeExecutorFactory skyframeExecutorFactory = null;
      QueryEnvironmentFactory queryEnvironmentFactory = null;
      for (BlazeModule module : blazeModules) {
        module.blazeStartup(startupOptionsProvider,
            BlazeVersionInfo.instance(), instanceId, directories, clock);
        Preprocessor.Factory.Supplier modulePreprocessorFactorySupplier =
            module.getPreprocessorFactorySupplier();
        if (modulePreprocessorFactorySupplier != null) {
          Preconditions.checkState(preprocessorFactorySupplier == null,
              "more than one module defines a preprocessor factory supplier");
          preprocessorFactorySupplier = modulePreprocessorFactorySupplier;
        }
        SkyframeExecutorFactory skyFactory = module.getSkyframeExecutorFactory();
        if (skyFactory != null) {
          Preconditions.checkState(skyframeExecutorFactory == null,
              "At most one skyframe factory supported. But found two: %s and %s", skyFactory,
              skyframeExecutorFactory);
          skyframeExecutorFactory = skyFactory;
        }
        QueryEnvironmentFactory queryEnvFactory = module.getQueryEnvironmentFactory();
        if (queryEnvFactory != null) {
          Preconditions.checkState(queryEnvironmentFactory == null,
              "At most one query environment factory supported. But found two: %s and %s",
              queryEnvFactory,
              queryEnvironmentFactory);
          queryEnvironmentFactory = queryEnvFactory;
        }
      }
      if (skyframeExecutorFactory == null) {
        skyframeExecutorFactory = new SequencedSkyframeExecutorFactory();
      }
      if (queryEnvironmentFactory == null) {
        queryEnvironmentFactory = new QueryEnvironmentFactory();
      }
      if (preprocessorFactorySupplier == null) {
        preprocessorFactorySupplier = Preprocessor.Factory.Supplier.NullSupplier.INSTANCE;
      }

      ConfiguredRuleClassProvider.Builder ruleClassBuilder =
          new ConfiguredRuleClassProvider.Builder();
      for (BlazeModule module : blazeModules) {
        module.initializeRuleClasses(ruleClassBuilder);
      }

      Map<String, String> platformRegexps = null;
      {
        ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<>();
        for (BlazeModule module : blazeModules) {
          builder.putAll(module.getPlatformSetRegexps());
        }
        platformRegexps = builder.build();
        if (platformRegexps.isEmpty()) {
          platformRegexps = null; // Use the default.
        }
      }

      Iterable<DiffAwareness.Factory> diffAwarenessFactories;
      {
        ImmutableList.Builder<DiffAwareness.Factory> builder = new ImmutableList.Builder<>();
        boolean watchFS = startupOptionsProvider != null
            && startupOptionsProvider.getOptions(BlazeServerStartupOptions.class).watchFS;
        for (BlazeModule module : blazeModules) {
          builder.addAll(module.getDiffAwarenessFactories(watchFS));
        }
        diffAwarenessFactories = builder.build();
      }

      // Merge filters from Blaze modules that allow some action inputs to be missing.
      Predicate<PathFragment> allowedMissingInputs = null;
      for (BlazeModule module : blazeModules) {
        Predicate<PathFragment> modulePredicate = module.getAllowedMissingInputs();
        if (modulePredicate != null) {
          Preconditions.checkArgument(allowedMissingInputs == null,
              "More than one Blaze module allows missing inputs.");
          allowedMissingInputs = modulePredicate;
        }
      }
      if (allowedMissingInputs == null) {
        allowedMissingInputs = Predicates.alwaysFalse();
      }

      ConfiguredRuleClassProvider ruleClassProvider = ruleClassBuilder.build();
      WorkspaceStatusAction.Factory workspaceStatusActionFactory = null;
      for (BlazeModule module : blazeModules) {
        WorkspaceStatusAction.Factory candidate = module.getWorkspaceStatusActionFactory();
        if (candidate != null) {
          Preconditions.checkState(workspaceStatusActionFactory == null,
              "more than one module defines a workspace status action factory");
          workspaceStatusActionFactory = candidate;
        }
      }

      List<PackageFactory.EnvironmentExtension> extensions = new ArrayList<>();
      for (BlazeModule module : blazeModules) {
        extensions.add(module.getPackageEnvironmentExtension());
      }

      // We use an immutable map builder for the nice side effect that it throws if a duplicate key
      // is inserted.
      ImmutableMap.Builder<SkyFunctionName, SkyFunction> skyFunctions = ImmutableMap.builder();
      for (BlazeModule module : blazeModules) {
        skyFunctions.putAll(module.getSkyFunctions(directories));
      }

      ImmutableList.Builder<PrecomputedValue.Injected> precomputedValues = ImmutableList.builder();
      for (BlazeModule module : blazeModules) {
        precomputedValues.addAll(module.getPrecomputedSkyframeValues());
      }

      ImmutableList.Builder<SkyValueDirtinessChecker> customDirtinessCheckers =
          ImmutableList.builder();
      for (BlazeModule module : blazeModules) {
        customDirtinessCheckers.addAll(module.getCustomDirtinessCheckers());
      }

      final PackageFactory pkgFactory =
          new PackageFactory(ruleClassProvider, platformRegexps, extensions,
              BlazeVersionInfo.instance().getVersion());
      SkyframeExecutor skyframeExecutor =
          skyframeExecutorFactory.create(
              pkgFactory,
              timestampMonitor,
              directories,
              binTools,
              workspaceStatusActionFactory,
              ruleClassProvider.getBuildInfoFactories(),
              diffAwarenessFactories,
              allowedMissingInputs,
              preprocessorFactorySupplier,
              skyFunctions.build(),
              precomputedValues.build(),
              customDirtinessCheckers.build());

      if (configurationFactory == null) {
        configurationFactory = new ConfigurationFactory(
            ruleClassProvider.getConfigurationCollectionFactory(),
            ruleClassProvider.getConfigurationFragments());
      }

      ProjectFile.Provider projectFileProvider = null;
      for (BlazeModule module : blazeModules) {
        ProjectFile.Provider candidate = module.createProjectFileProvider();
        if (candidate != null) {
          Preconditions.checkState(projectFileProvider == null,
              "more than one module defines a project file provider");
          projectFileProvider = candidate;
        }
      }

      invocationPolicy = createInvocationPolicyFromModules(invocationPolicy, blazeModules);

      return new BlazeRuntime(directories, workspaceStatusActionFactory, skyframeExecutor,
          queryEnvironmentFactory, pkgFactory, ruleClassProvider, configurationFactory,
          clock, startupOptionsProvider, ImmutableList.copyOf(blazeModules),
          timestampMonitor, eventBusExceptionHandler, binTools, projectFileProvider,
          invocationPolicy, commands);
    }

    public Builder setBinTools(BinTools binTools) {
      this.binTools = binTools;
      return this;
    }

    public Builder setInvocationPolicy(InvocationPolicy invocationPolicy) {
      this.invocationPolicy = invocationPolicy;
      return this;
    }

    public Builder setDirectories(BlazeDirectories directories) {
      this.directories = directories;
      return this;
    }

    /**
     * Creates and sets a new {@link BlazeDirectories} instance with the given
     * parameters.
     */
    public Builder setDirectories(Path installBase, Path outputBase,
        Path workspace) {
      this.directories = new BlazeDirectories(installBase, outputBase, workspace);
      return this;
    }

    public Builder setConfigurationFactory(ConfigurationFactory configurationFactory) {
      this.configurationFactory = configurationFactory;
      return this;
    }

    public Builder setClock(Clock clock) {
      this.clock = clock;
      return this;
    }

    public Builder setStartupOptionsProvider(OptionsProvider startupOptionsProvider) {
      this.startupOptionsProvider = startupOptionsProvider;
      return this;
    }

    public Builder addBlazeModule(BlazeModule blazeModule) {
      blazeModules.add(blazeModule);
      return this;
    }

    public Builder setInstanceId(UUID id) {
      instanceId = id;
      return this;
    }

    @VisibleForTesting
    public Builder setEventBusExceptionHandler(
        SubscriberExceptionHandler eventBusExceptionHandler) {
      this.eventBusExceptionHandler = eventBusExceptionHandler;
      return this;
    }

    public Builder addCommands(BlazeCommand... commands) {
      this.commands.addAll(Arrays.asList(commands));
      return this;
    }

    public Builder addCommands(Iterable<BlazeCommand> commands) {
      Iterables.addAll(this.commands, commands);
      return this;
    }
  }
}
