// Copyright 2018 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.runfiles;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.ref.SoftReference;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Runfiles lookup library for Bazel-built Java binaries and tests.
 *
 * <p>USAGE:
 *
 * <p>1. Depend on this runfiles library from your build rule:
 *
 * <pre>
 *   java_binary(
 *       name = "my_binary",
 *       ...
 *       deps = ["@bazel_tools//tools/java/runfiles"],
 *   )
 * </pre>
 *
 * <p>2. Import the runfiles library.
 *
 * <pre>
 *   import com.google.devtools.build.runfiles.Runfiles;
 * </pre>
 *
 * <p>3. Create a {@link Preloaded} object:
 *
 * <pre>
 *   public void myFunction() {
 *     Runfiles.Preloaded runfiles = Runfiles.preload();
 *     ...
 * </pre>
 *
 * <p>4. To look up a runfile, use either of the following approaches:
 *
 * <p>4a. Annotate the class from which runfiles should be looked up with {@link
 * AutoBazelRepository} and obtain the name of the Bazel repository containing the class from a
 * constant generated by this annotation:
 *
 * <pre>
 *   import com.google.devtools.build.runfiles.AutoBazelRepository;
 *   &#64;AutoBazelRepository
 *   public class MyClass {
 *     public void myFunction() {
 *       Runfiles.Preloaded runfiles = Runfiles.preload();
 *       String path = runfiles.withSourceRepository(AutoBazelRepository_MyClass.NAME)
 *                             .rlocation("my_workspace/path/to/my/data.txt");
 *       ...
 *
 * </pre>
 *
 * <p>4b. Let Bazel compute the path passed to rlocation and pass it into a <code>java_binary</code>
 * via an argument or an environment variable:
 *
 * <pre>
 *   java_binary(
 *       name = "my_binary",
 *       srcs = ["MyClass.java"],
 *       data = ["@my_workspace//path/to/my:data.txt"],
 *       env = {"MY_RUNFILE": "$(rlocationpath @my_workspace//path/to/my:data.txt)"},
 *   )
 * </pre>
 *
 * <pre>
 *   public class MyClass {
 *     public void myFunction() {
 *       Runfiles.Preloaded runfiles = Runfiles.preload();
 *       String path = runfiles.unmapped().rlocation(System.getenv("MY_RUNFILE"));
 *       ...
 *
 * </pre>
 *
 * For more details on why it is required to pass in the current repository name, see {@see
 * https://bazel.build/build/bzlmod#repository-names}.
 *
 * <h3>Subprocesses</h3>
 *
 * <p>If you want to start subprocesses that also need runfiles, you need to set the right
 * environment variables for them:
 *
 * <pre>
 *   String path = r.rlocation("path/to/binary");
 *   ProcessBuilder pb = new ProcessBuilder(path);
 *   pb.environment().putAll(r.getEnvVars());
 *   ...
 *   Process p = pb.start();
 * </pre>
 *
 * <h3>{@link Preloaded} vs. {@link Runfiles}</h3>
 *
 * <p>Instances of {@link Preloaded} are meant to be stored and passed around to other components
 * that need to access runfiles. They are created by calling {@link Runfiles#preload()} {@link
 * Runfiles#preload(Map)} and immutably encapsulate all data required to look up runfiles with the
 * repository mapping of any Bazel repository specified at a later time.
 *
 * <p>Creating {@link Preloaded} instances can be costly, so applications should try to create as
 * few instances as possible. {@link Runfiles#preload()}, but not {@link Runfiles#preload(Map)},
 * returns a single global, softly cached instance of {@link Preloaded} that is constructed based on
 * the JVM's environment variables.
 *
 * <p>Instance of {@link Runfiles} are only meant to be used by code located in a single Bazel
 * repository and should not be passed around. They are created by calling {@link
 * Preloaded#withSourceRepository(String)} or {@link Preloaded#unmapped()} and in addition to the
 * data in {@link Preloaded} also fix a source repository relative to which apparent repository
 * names are resolved.
 *
 * <p>Creating {@link Preloaded} instances is cheap.
 */
public final class Runfiles {

  /**
   * A class that encapsulates all data required to look up runfiles relative to any Bazel
   * repository fixed at a later time.
   *
   * <p>This class is immutable.
   */
  public abstract static class Preloaded {

    /** See {@link com.google.devtools.build.lib.analysis.RepoMappingManifestAction.Entry}. */
    static class RepoMappingKey {

      public final String sourceRepo;
      public final String targetRepoApparentName;

      public RepoMappingKey(String sourceRepo, String targetRepoApparentName) {
        this.sourceRepo = sourceRepo;
        this.targetRepoApparentName = targetRepoApparentName;
      }

      @Override
      public boolean equals(Object o) {
        if (this == o) {
          return true;
        }
        if (o == null || !(o instanceof RepoMappingKey)) {
          return false;
        }
        RepoMappingKey that = (RepoMappingKey) o;
        return sourceRepo.equals(that.sourceRepo)
            && targetRepoApparentName.equals(that.targetRepoApparentName);
      }

      @Override
      public int hashCode() {
        return Objects.hash(sourceRepo, targetRepoApparentName);
      }
    }

    /**
     * Returns a {@link Runfiles} instance that uses the provided source repository's repository
     * mapping to translate apparent into canonical repository names.
     *
     * <p>{@see https://bazel.build/build/bzlmod#repository-names}
     *
     * @param sourceRepository the canonical name of the Bazel repository relative to which apparent
     *     repository names should be resolved. Should generally coincide with the Bazel repository
     *     that contains the caller of this method, which can be obtained via {@link
     *     AutoBazelRepository}.
     * @return a {@link Runfiles} instance that looks up runfiles relative to the provided source
     *     repository and shares all other data with this {@link Preloaded} instance.
     */
    public final Runfiles withSourceRepository(String sourceRepository) {
      Util.checkArgument(sourceRepository != null);
      return new Runfiles(this, sourceRepository);
    }

    /**
     * Returns a {@link Runfiles} instance backed by the preloaded runfiles data that can be used to
     * look up runfiles paths with canonical repository names only.
     *
     * @return a {@link Runfiles} instance that can only look up paths with canonical repository
     *     names and shared all data with this {@link Preloaded} instance.
     */
    public final Runfiles unmapped() {
      return new Runfiles(this, null);
    }

    protected abstract Map<String, String> getEnvVars();

    protected abstract String rlocationChecked(String path);

    protected abstract Map<RepoMappingKey, String> getRepoMapping();

    // Private constructor, so only nested classes may extend it.
    private Preloaded() {}
  }

  private static final String MAIN_REPOSITORY = "";

  private static SoftReference<Preloaded> defaultInstance = new SoftReference<>(null);

  private final Preloaded preloadedRunfiles;
  private final String sourceRepository;

  private Runfiles(Preloaded preloadedRunfiles, String sourceRepository) {
    this.preloadedRunfiles = preloadedRunfiles;
    this.sourceRepository = sourceRepository;
  }

  /**
   * Returns the softly cached global {@link Runfiles.Preloaded} instance, creating it if needed.
   *
   * <p>This method passes the JVM's environment variable map to {@link #create(Map)}.
   */
  public static synchronized Preloaded preload() throws IOException {
    Preloaded instance = defaultInstance.get();
    if (instance != null) {
      return instance;
    }
    instance = preload(System.getenv());
    defaultInstance = new SoftReference<>(instance);
    return instance;
  }

  /**
   * Returns a new {@link Runfiles.Preloaded} instance.
   *
   * <p>The returned object is either:
   *
   * <ul>
   *   <li>manifest-based, meaning it looks up runfile paths from a manifest file, or
   *   <li>directory-based, meaning it looks up runfile paths under a given directory path
   * </ul>
   *
   * <p>If {@code env} contains "RUNFILES_MANIFEST_ONLY" with value "1", this method returns a
   * manifest-based implementation. The manifest's path is defined by the "RUNFILES_MANIFEST_FILE"
   * key's value in {@code env}.
   *
   * <p>Otherwise this method returns a directory-based implementation. The directory's path is
   * defined by the value in {@code env} under the "RUNFILES_DIR" key, or if absent, then under the
   * "JAVA_RUNFILES" key.
   *
   * <p>Note about performance: the manifest-based implementation eagerly reads and caches the whole
   * manifest file upon instantiation.
   *
   * @throws IOException if RUNFILES_MANIFEST_ONLY=1 is in {@code env} but there's no
   *     "RUNFILES_MANIFEST_FILE", "RUNFILES_DIR", or "JAVA_RUNFILES" key in {@code env} or their
   *     values are empty, or some IO error occurs
   */
  public static Preloaded preload(Map<String, String> env) throws IOException {
    if (isManifestOnly(env)) {
      // On Windows, Bazel sets RUNFILES_MANIFEST_ONLY=1.
      // On every platform, Bazel also sets RUNFILES_MANIFEST_FILE, but on Linux and macOS it's
      // faster to use RUNFILES_DIR.
      return new ManifestBased(getManifestPath(env));
    } else {
      return new DirectoryBased(getRunfilesDir(env));
    }
  }

  /**
   * Returns a new {@link Runfiles} instance.
   *
   * <p>This method passes the JVM's environment variable map to {@link #create(Map)}.
   *
   * @deprecated Use {@link #preload()} instead. With {@code --enable_bzlmod}, this function does
   *     not work correctly.
   */
  @Deprecated
  public static Runfiles create() throws IOException {
    return preload().withSourceRepository(MAIN_REPOSITORY);
  }

  /**
   * Returns a new {@link Runfiles} instance.
   *
   * <p>The returned object is either:
   *
   * <ul>
   *   <li>manifest-based, meaning it looks up runfile paths from a manifest file, or
   *   <li>directory-based, meaning it looks up runfile paths under a given directory path
   * </ul>
   *
   * <p>If {@code env} contains "RUNFILES_MANIFEST_ONLY" with value "1", this method returns a
   * manifest-based implementation. The manifest's path is defined by the "RUNFILES_MANIFEST_FILE"
   * key's value in {@code env}.
   *
   * <p>Otherwise this method returns a directory-based implementation. The directory's path is
   * defined by the value in {@code env} under the "RUNFILES_DIR" key, or if absent, then under the
   * "JAVA_RUNFILES" key.
   *
   * <p>Note about performance: the manifest-based implementation eagerly reads and caches the whole
   * manifest file upon instantiation.
   *
   * @throws IOException if RUNFILES_MANIFEST_ONLY=1 is in {@code env} but there's no
   *     "RUNFILES_MANIFEST_FILE", "RUNFILES_DIR", or "JAVA_RUNFILES" key in {@code env} or their
   *     values are empty, or some IO error occurs
   * @deprecated Use {@link #preload(Map)} instead. With {@code --enable_bzlmod}, this function does
   *     not work correctly.
   */
  @Deprecated
  public static Runfiles create(Map<String, String> env) throws IOException {
    return preload(env).withSourceRepository(MAIN_REPOSITORY);
  }

  /**
   * Returns the runtime path of a runfile (a Bazel-built binary's/test's data-dependency).
   *
   * <p>The returned path may not be valid. The caller should check the path's validity and that the
   * path exists.
   *
   * <p>The function may return null. In that case the caller can be sure that the rule does not
   * know about this data-dependency.
   *
   * @param path runfiles-root-relative path of the runfile
   * @throws IllegalArgumentException if {@code path} fails validation, for example if it's null or
   *     empty, or not normalized (contains "./", "../", or "//")
   */
  public String rlocation(String path) {
    Util.checkArgument(path != null);
    Util.checkArgument(!path.isEmpty());
    Util.checkArgument(
        !path.startsWith("../")
            && !path.contains("/..")
            && !path.startsWith("./")
            && !path.contains("/./")
            && !path.endsWith("/.")
            && !path.contains("//"),
        "path is not normalized: \"%s\"",
        path);
    Util.checkArgument(
        !path.startsWith("\\"), "path is absolute without a drive letter: \"%s\"", path);
    if (new File(path).isAbsolute()) {
      return path;
    }

    if (sourceRepository == null) {
      return preloadedRunfiles.rlocationChecked(path);
    }
    String[] apparentTargetAndRemainder = path.split("/", 2);
    if (apparentTargetAndRemainder.length < 2) {
      return preloadedRunfiles.rlocationChecked(path);
    }
    String targetCanonical = getCanonicalRepositoryName(apparentTargetAndRemainder[0]);
    return preloadedRunfiles.rlocationChecked(
        targetCanonical + "/" + apparentTargetAndRemainder[1]);
  }

  /**
   * Returns environment variables for subprocesses.
   *
   * <p>The caller should add the returned key-value pairs to the environment of subprocesses in
   * case those subprocesses are also Bazel-built binaries that need to use runfiles.
   */
  public Map<String, String> getEnvVars() {
    return preloadedRunfiles.getEnvVars();
  }

  String getCanonicalRepositoryName(String apparentRepositoryName) {
    return preloadedRunfiles
        .getRepoMapping()
        .getOrDefault(
            new Preloaded.RepoMappingKey(sourceRepository, apparentRepositoryName),
            apparentRepositoryName);
  }

  /** Returns true if the platform supports runfiles only via manifests. */
  private static boolean isManifestOnly(Map<String, String> env) {
    return "1".equals(env.get("RUNFILES_MANIFEST_ONLY"));
  }

  private static String getManifestPath(Map<String, String> env) throws IOException {
    String value = env.get("RUNFILES_MANIFEST_FILE");
    if (Util.isNullOrEmpty(value)) {
      throw new IOException(
          "Cannot load runfiles manifest: $RUNFILES_MANIFEST_ONLY is 1 but"
              + " $RUNFILES_MANIFEST_FILE is empty or undefined");
    }
    return value;
  }

  private static String getRunfilesDir(Map<String, String> env) throws IOException {
    String value = env.get("RUNFILES_DIR");
    if (Util.isNullOrEmpty(value)) {
      value = env.get("JAVA_RUNFILES");
    }
    if (Util.isNullOrEmpty(value)) {
      throw new IOException(
          "Cannot find runfiles: $RUNFILES_DIR and $JAVA_RUNFILES are both unset or empty");
    }
    return value;
  }

  private static Map<Preloaded.RepoMappingKey, String> loadRepositoryMapping(String path)
      throws IOException {
    if (path == null || !new File(path).exists()) {
      return Collections.emptyMap();
    }

    try (BufferedReader r =
        new BufferedReader(
            new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8))) {
      return Collections.unmodifiableMap(
          r.lines()
              .filter(line -> !line.isEmpty())
              .map(
                  line -> {
                    String[] split = line.split(",");
                    if (split.length != 3) {
                      throw new IllegalArgumentException(
                          "Invalid line in repository mapping: '" + line + "'");
                    }
                    return split;
                  })
              .collect(
                  Collectors.toMap(
                      split -> new Preloaded.RepoMappingKey(split[0], split[1]),
                      split -> split[2])));
    }
  }

  /** {@link Runfiles} implementation that parses a runfiles-manifest file to look up runfiles. */
  private static final class ManifestBased extends Runfiles.Preloaded {

    private final Map<String, String> runfiles;
    private final String manifestPath;
    private final Map<RepoMappingKey, String> repoMapping;

    ManifestBased(String manifestPath) throws IOException {
      Util.checkArgument(manifestPath != null);
      Util.checkArgument(!manifestPath.isEmpty());
      this.manifestPath = manifestPath;
      this.runfiles = loadRunfiles(manifestPath);
      this.repoMapping = loadRepositoryMapping(rlocationChecked("_repo_mapping"));
    }

    @Override
    protected String rlocationChecked(String path) {
      String exactMatch = runfiles.get(path);
      if (exactMatch != null) {
        return exactMatch;
      }
      // If path references a runfile that lies under a directory that itself is a runfile, then
      // only the directory is listed in the manifest. Look up all prefixes of path in the manifest
      // and append the relative path from the prefix if there is a match.
      int prefixEnd = path.length();
      while ((prefixEnd = path.lastIndexOf('/', prefixEnd - 1)) != -1) {
        String prefixMatch = runfiles.get(path.substring(0, prefixEnd));
        if (prefixMatch != null) {
          return prefixMatch + '/' + path.substring(prefixEnd + 1);
        }
      }
      return null;
    }

    @Override
    protected Map<String, String> getEnvVars() {
      HashMap<String, String> result = new HashMap<>(4);
      result.put("RUNFILES_MANIFEST_ONLY", "1");
      result.put("RUNFILES_MANIFEST_FILE", manifestPath);
      String runfilesDir = findRunfilesDir(manifestPath);
      result.put("RUNFILES_DIR", runfilesDir);
      // TODO(laszlocsomor): remove JAVA_RUNFILES once the Java launcher can pick up RUNFILES_DIR.
      result.put("JAVA_RUNFILES", runfilesDir);
      return result;
    }

    @Override
    protected Map<RepoMappingKey, String> getRepoMapping() {
      return repoMapping;
    }

    private static Map<String, String> loadRunfiles(String path) throws IOException {
      HashMap<String, String> result = new HashMap<>();
      try (BufferedReader r =
          new BufferedReader(
              new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8))) {
        String line = null;
        while ((line = r.readLine()) != null) {
          int index = line.indexOf(' ');
          String runfile = (index == -1) ? line : line.substring(0, index);
          String realPath = (index == -1) ? line : line.substring(index + 1);
          result.put(runfile, realPath);
        }
      }
      return Collections.unmodifiableMap(result);
    }

    private static String findRunfilesDir(String manifest) {
      if (manifest.endsWith("/MANIFEST")
          || manifest.endsWith("\\MANIFEST")
          || manifest.endsWith(".runfiles_manifest")) {
        String path = manifest.substring(0, manifest.length() - 9);
        if (new File(path).isDirectory()) {
          return path;
        }
      }
      return "";
    }
  }

  /** {@link Runfiles} implementation that appends runfiles paths to the runfiles root. */
  private static final class DirectoryBased extends Preloaded {

    private final String runfilesRoot;
    private final Map<RepoMappingKey, String> repoMapping;

    DirectoryBased(String runfilesDir) throws IOException {
      Util.checkArgument(!Util.isNullOrEmpty(runfilesDir));
      Util.checkArgument(new File(runfilesDir).isDirectory());
      this.runfilesRoot = runfilesDir;
      this.repoMapping = loadRepositoryMapping(rlocationChecked("_repo_mapping"));
    }

    @Override
    protected String rlocationChecked(String path) {
      return runfilesRoot + "/" + path;
    }

    @Override
    protected Map<RepoMappingKey, String> getRepoMapping() {
      return repoMapping;
    }

    @Override
    protected Map<String, String> getEnvVars() {
      HashMap<String, String> result = new HashMap<>(2);
      result.put("RUNFILES_DIR", runfilesRoot);
      // TODO(laszlocsomor): remove JAVA_RUNFILES once the Java launcher can pick up RUNFILES_DIR.
      result.put("JAVA_RUNFILES", runfilesRoot);
      return result;
    }
  }

  static Preloaded createManifestBasedForTesting(String manifestPath) throws IOException {
    return new ManifestBased(manifestPath);
  }

  static Preloaded createDirectoryBasedForTesting(String runfilesDir) throws IOException {
    return new DirectoryBased(runfilesDir);
  }
}
