// Copyright 2016 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.sandbox;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
import com.google.devtools.build.lib.actions.ExecException;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.analysis.test.TestConfiguration;
import com.google.devtools.build.lib.exec.SpawnInputExpander;
import com.google.devtools.build.lib.exec.SpawnRunner.SpawnExecutionPolicy;
import com.google.devtools.build.lib.rules.fileset.FilesetActionContext;
import com.google.devtools.build.lib.standalone.StandaloneSpawnStrategy;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.common.options.OptionsProvider;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/** Helper methods that are shared by the different sandboxing strategies in this package. */
public final class SandboxHelpers {

  static void fallbackToNonSandboxedExecution(
      Spawn spawn, ActionExecutionContext actionExecutionContext)
      throws ExecException, InterruptedException {
    StandaloneSpawnStrategy standaloneStrategy =
        Preconditions.checkNotNull(
            actionExecutionContext.getContext(StandaloneSpawnStrategy.class));
    standaloneStrategy.exec(spawn, actionExecutionContext);
  }

  /**
   * Returns the inputs of a Spawn as a map of PathFragments relative to an execRoot to paths in the
   * host filesystem where the input files can be found.
   */
  public static Map<PathFragment, Path> getInputFiles(
      SpawnInputExpander spawnInputExpander,
      Path execRoot,
      Spawn spawn,
      ActionExecutionContext executionContext)
      throws IOException {
    Map<PathFragment, ActionInput> inputMap =
        spawnInputExpander.getInputMapping(
            spawn,
            executionContext.getArtifactExpander(),
            executionContext.getActionInputFileCache(),
            executionContext.getContext(FilesetActionContext.class));
    return postProcess(inputMap, spawn, executionContext.getArtifactExpander(), execRoot);
  }

  /**
   * Returns the inputs of a Spawn as a map of PathFragments relative to an execRoot to paths in the
   * host filesystem where the input files can be found.
   */
  public static Map<PathFragment, Path> getInputFiles(
      Spawn spawn,
      SpawnExecutionPolicy policy,
      Path execRoot)
          throws IOException {
    return postProcess(policy.getInputMapping(), spawn, policy.getArtifactExpander(), execRoot);
  }

  /**
   * Returns the inputs of a Spawn as a map of PathFragments relative to an execRoot to paths in the
   * host filesystem where the input files can be found.
   */
  private static Map<PathFragment, Path> postProcess(
      Map<PathFragment, ActionInput> inputMap,
      Spawn spawn, 
      ArtifactExpander artifactExpander,
      Path execRoot) {
    // SpawnInputExpander#getInputMapping uses ArtifactExpander#expandArtifacts to expand
    // middlemen and tree artifacts, which expands empty tree artifacts to no entry. However,
    // actions that accept TreeArtifacts as inputs generally expect that the empty directory is
    // created. So we add those explicitly here.
    // TODO(ulfjack): Move this code to SpawnInputExpander.
    for (ActionInput input : spawn.getInputFiles()) {
      if (input instanceof Artifact && ((Artifact) input).isTreeArtifact()) {
        List<Artifact> containedArtifacts = new ArrayList<>();
        artifactExpander.expand((Artifact) input, containedArtifacts);
        // Attempting to mount a non-empty directory results in ERR_DIRECTORY_NOT_EMPTY, so we
        // only mount empty TreeArtifacts as directories.
        if (containedArtifacts.isEmpty()) {
          inputMap.put(input.getExecPath(), input);
        }
      }
    }

    Map<PathFragment, Path> inputFiles = new TreeMap<>();
    for (Map.Entry<PathFragment, ActionInput> e : inputMap.entrySet()) {
      Path inputPath =
          e.getValue() == SpawnInputExpander.EMPTY_FILE
              ? null
              : execRoot.getRelative(e.getValue().getExecPath());
      inputFiles.put(e.getKey(), inputPath);
    }
    return inputFiles;
  }

  public static ImmutableSet<PathFragment> getOutputFiles(Spawn spawn) {
    Builder<PathFragment> outputFiles = ImmutableSet.builder();
    for (ActionInput output : spawn.getOutputFiles()) {
      outputFiles.add(PathFragment.create(output.getExecPathString()));
    }
    return outputFiles.build();
  }

  /**
   * Returns true if the build options are set in a way that requires network access for all
   * actions. This is separate from {@link #shouldAllowNetwork(Spawn)} to avoid having to keep a
   * reference to the full set of build options (and also for performance, since this only needs to
   * be checked once-per-build).
   */
  static boolean shouldAllowNetwork(OptionsProvider buildOptions) {
    // Allow network access, when --java_debug is specified, otherwise we can't connect to the
    // remote debug server of the test. This intentionally overrides the "block-network" execution
    // tag.
    return buildOptions
        .getOptions(TestConfiguration.TestOptions.class)
        .testArguments
        .contains("--wrapper_script_flag=--debug");
  }

  /** Returns true if this specific spawn requires network access. */
  static boolean shouldAllowNetwork(Spawn spawn) {
    // If the Spawn requests to block network access, do so.
    if (spawn.getExecutionInfo().containsKey("block-network")) {
      return false;
    }

    // Network access is allowed by default.
    return true;
  }
}
