/*
 * Copyright 2012-present Facebook, Inc.
 *
 * 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.facebook.buck.java;

import com.facebook.buck.android.HasAndroidResourceDeps;
import com.facebook.buck.android.UberRDotJavaUtil;
import com.facebook.buck.graph.TopologicalSort;
import com.facebook.buck.java.abi.AbiWriterProtocol;
import com.facebook.buck.model.AnnotationProcessingData;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.rules.AbiRule;
import com.facebook.buck.rules.AbstractBuildRuleBuilder;
import com.facebook.buck.rules.AbstractBuildRuleBuilderParams;
import com.facebook.buck.rules.AbstractCachingBuildRule;
import com.facebook.buck.rules.ArtifactCache;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildDependencies;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.JavaPackageFinder;
import com.facebook.buck.rules.ResourcesAttributeBuilder;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.Sha1HashCode;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePaths;
import com.facebook.buck.rules.SrcsAttributeBuilder;
import com.facebook.buck.step.AbstractExecutionStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.facebook.buck.step.fs.MkdirAndSymlinkFileStep;
import com.facebook.buck.step.fs.WriteFileStep;
import com.facebook.buck.util.BuckConstant;
import com.facebook.buck.util.ProjectFilesystem;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import com.google.common.reflect.ClassPath;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;

import javax.annotation.Nullable;

/**
 * Suppose this were a rule defined in <code>src/com/facebook/feed/BUILD</code>:
 * <pre>
 * java_library(
 *   name = 'feed',
 *   srcs = [
 *     'FeedStoryRenderer.java',
 *   ],
 *   deps = [
 *     '//src/com/facebook/feed/model:model',
 *     '//third-party/java/guava:guava',
 *   ],
 * )
 * </pre>
 * Then this would compile {@code FeedStoryRenderer.java} against Guava and the classes generated
 * from the {@code //src/com/facebook/feed/model:model} rule.
 */
public class DefaultJavaLibraryRule extends AbstractCachingBuildRule
    implements JavaLibraryRule, AbiRule, HasJavaSrcs, HasClasspathEntries {

  private final ImmutableSortedSet<String> srcs;

  private final ImmutableSortedSet<SourcePath> resources;

  private final Optional<String> outputJar;

  private final List<String> inputsToConsiderForCachingPurposes;

  private final Optional<String> proguardConfig;


  private final boolean exportDeps;

  private final Supplier<ImmutableSetMultimap<JavaLibraryRule, String>> outputClasspathEntriesSupplier;

  private final Supplier<ImmutableSetMultimap<JavaLibraryRule, String>>
      transitiveClasspathEntriesSupplier;

  private final Supplier<ImmutableSetMultimap<JavaLibraryRule, String>>
      declaredClasspathEntriesSupplier;

  private final JavacOptions javacOptions;

  /**
   * This returns the ABI key for this rule. This will be set <em>EITHER</em> as part of
   * {@link #recordOutputFileDetailsAfterFetchedFromArtifactCache(ArtifactCache, ProjectFilesystem)}
   * or while the build steps (in particular, the javac step) for this rule are created. In the case
   * of the latter, the {@link Supplier} is guaranteed to be able to return (a possibly null) value
   * after the build steps have been executed.
   * <p>
   * This field should be set exclusively through {@link #setAbiKey(Supplier)}
   */
  @Nullable
  private Supplier<Sha1HashCode> abiKeySupplier;

  /**
   * Function for opening a JAR and returning all symbols that can be referenced from inside of that
   * jar.
   */
  @VisibleForTesting
  static interface JarResolver extends Function<String, ImmutableSet<String>> {}

  private final JarResolver JAR_RESOLVER =
      new JarResolver() {
    @Override
    public ImmutableSet<String> apply(String classPath) {
      ImmutableSet.Builder<String> topLevelSymbolsBuilder = ImmutableSet.builder();
      try {
        ClassLoader loader = URLClassLoader.newInstance(
            new URL[]{new File(classPath).toURI().toURL()},
          /* parent */ null);

        // For every class contained in that jar, check to see if the package name
        // (e.g. com.facebook.foo), the simple name (e.g. ImmutableSet) or the name
        // (e.g com.google.common.collect.ImmutableSet) is one of the missing symbols.
        for (ClassPath.ClassInfo classInfo : ClassPath.from(loader).getTopLevelClasses()) {
          topLevelSymbolsBuilder.add(classInfo.getPackageName(),
              classInfo.getSimpleName(),
              classInfo.getName());
        }
      } catch (IOException e) {
        // Since this simply is a heuristic, return an empty set if we fail to load a jar.
        return topLevelSymbolsBuilder.build();
      }
      return topLevelSymbolsBuilder.build();
    }
  };

  /**
   * This is set in {@link #buildInternal(com.facebook.buck.rules.BuildContext)} and is available to subclasses.
   */
  protected ImmutableList<HasAndroidResourceDeps> androidResourceDeps;

  protected DefaultJavaLibraryRule(BuildRuleParams buildRuleParams,
                                   Set<String> srcs,
                                   Set<? extends SourcePath> resources,
                                   Optional<String> proguardConfig,
                                   boolean exportDeps,
                                   JavacOptions javacOptions) {
    super(buildRuleParams);
    this.srcs = ImmutableSortedSet.copyOf(srcs);
    this.resources = ImmutableSortedSet.copyOf(resources);
    this.proguardConfig = Preconditions.checkNotNull(proguardConfig);
    this.exportDeps = exportDeps;
    this.javacOptions = Preconditions.checkNotNull(javacOptions);

    if (!srcs.isEmpty() || !resources.isEmpty()) {
      this.outputJar = Optional.of(getOutputJarPath(getBuildTarget()));
    } else {
      this.outputJar = Optional.absent();
    }

    // Note that both srcs and resources are sorted so that the list order is consistent even if
    // the iteration order of the sets passed to the constructor changes. See
    // AbstractBuildRule.getInputsToCompareToOutput() for details.
    ImmutableList.Builder<String> builder = ImmutableList.<String>builder().addAll(this.srcs);
    builder.addAll(SourcePaths.filterInputsToCompareToOutput(resources));
    inputsToConsiderForCachingPurposes = builder.build();

    outputClasspathEntriesSupplier =
        Suppliers.memoize(new Supplier<ImmutableSetMultimap<JavaLibraryRule, String>>() {
          @Override
          public ImmutableSetMultimap<JavaLibraryRule, String> get() {
            ImmutableSetMultimap<JavaLibraryRule, String> outputClasspathEntries;

            // If this java_library exports its dependencies then just return the transitive
            // dependencies.
            if (DefaultJavaLibraryRule.this.exportDeps) {
              outputClasspathEntries = getTransitiveClasspathEntries();
            } else if (outputJar.isPresent()) {
              outputClasspathEntries = ImmutableSetMultimap.<JavaLibraryRule, String>builder()
                  .put(DefaultJavaLibraryRule.this, getPathToOutputFile())
                  .build();
            } else {
              outputClasspathEntries = ImmutableSetMultimap.of();
            }

            return outputClasspathEntries;
          }
        });

    transitiveClasspathEntriesSupplier =
        Suppliers.memoize(new Supplier<ImmutableSetMultimap<JavaLibraryRule, String>>() {
          @Override
          public ImmutableSetMultimap<JavaLibraryRule, String> get() {
            final ImmutableSetMultimap.Builder<JavaLibraryRule, String> classpathEntries =
                ImmutableSetMultimap.builder();
            ImmutableSetMultimap<JavaLibraryRule, String> classpathEntriesForDeps =
                Classpaths.getClasspathEntries(getDeps());

            classpathEntries.putAll(classpathEntriesForDeps);

            if (DefaultJavaLibraryRule.this.exportDeps) {
              classpathEntries.putAll(DefaultJavaLibraryRule.this,
                  classpathEntriesForDeps.values());
            }

            // Only add ourselves to the classpath if there's a jar to be built.
            if (outputJar.isPresent()) {
              classpathEntries.putAll(DefaultJavaLibraryRule.this, getPathToOutputFile());
            }

            return classpathEntries.build();
          }
        });

    declaredClasspathEntriesSupplier =
        Suppliers.memoize(new Supplier<ImmutableSetMultimap<JavaLibraryRule, String>>() {
          @Override
          public ImmutableSetMultimap<JavaLibraryRule, String> get() {
            final ImmutableSetMultimap.Builder<JavaLibraryRule, String> classpathEntries =
               ImmutableSetMultimap.builder();

            Iterable<JavaLibraryRule> javaLibraryDeps = Iterables.filter(
                Sets.union(getDeps(), ImmutableSet.of(DefaultJavaLibraryRule.this)),
                JavaLibraryRule.class);

            for (JavaLibraryRule rule : javaLibraryDeps) {
              classpathEntries.putAll(rule, rule.getOutputClasspathEntries().values());
            }
            return classpathEntries.build();
          }
        });
  }

  /**
   * @param outputDirectory Directory to write class files to
   * @param transitiveClasspathEntries Classpaths of all transitive dependencies.
   * @param declaredClasspathEntries Classpaths of all declared dependencies.
   * @param javacOptions options to use when compiling code.
   * @param suggestBuildRules Function to convert from missing symbols to the suggested rules.
   * @param commands List of steps to add to.
   */
  private void createCommandsForJavac(
      String outputDirectory,
      ImmutableSet<String> transitiveClasspathEntries,
      ImmutableSet<String> declaredClasspathEntries,
      JavacOptions javacOptions,
      BuildDependencies buildDependencies,
      Optional<DependencyCheckingJavacStep.SuggestBuildRules> suggestBuildRules,
      ImmutableList.Builder<Step> commands) {
    // Make sure that this directory exists because ABI information will be written here.
    Step mkdir = new MakeCleanDirectoryStep(getPathToAbiOutputDir());
    commands.add(mkdir);

    // Only run javac if there are .java files to compile.
    if (!getJavaSrcs().isEmpty()) {
      final JavacInMemoryStep javac = new DependencyCheckingJavacStep(
          outputDirectory,
          getJavaSrcs(),
          transitiveClasspathEntries,
          declaredClasspathEntries,
          javacOptions,
          Optional.of(getPathToAbiOutputFile()),
          Optional.of(getFullyQualifiedName()),
          buildDependencies,
          suggestBuildRules);
      commands.add(javac);

      // Create a supplier that extracts the ABI key from javac after it executes.
      setAbiKey(Suppliers.memoize(new Supplier<Sha1HashCode>() {
        @Override
        public Sha1HashCode get() {
          return javac.getAbiKey();
        }
      }));
    } else {
      // When there are no .java files to compile, the ABI key should be a constant.
      setAbiKey(Suppliers.ofInstance(new Sha1HashCode(AbiWriterProtocol.EMPTY_ABI_KEY)));
    }
  }

  private String getPathToAbiOutputDir() {
    BuildTarget target = getBuildTarget();
    return String.format(
        "%s/%slib__%s__abi",
        BuckConstant.GEN_DIR,
        target.getBasePathWithSlash(),
        target.getShortName());

  }

  private String getPathToAbiOutputFile() {
    return String.format("%s/abi", getPathToAbiOutputDir());
  }

  private String getPathToAbiKeyForDepsFile() {
    return String.format("%s/abi_deps", getPathToAbiOutputDir());
  }

  private String getPathToRuleKeyNoDepsFile() {
    return String.format("%s/rule_key_no_deps", getPathToAbiOutputDir());
  }

  private static String getOutputJarDirPath(BuildTarget target) {
    return String.format(
        "%s/%slib__%s__output",
        BuckConstant.GEN_DIR,
        target.getBasePathWithSlash(),
        target.getShortName());
  }

  private static String getOutputJarPath(BuildTarget target) {
    return String.format(
        "%s/%s.jar",
        getOutputJarDirPath(target),
        target.getShortName());
  }

  /**
   * @return directory path relative to the project root where .class files will be generated.
   *     The return value does not end with a slash.
   */
  private static String getClassesDir(BuildTarget target) {
    return String.format(
        "%s/%slib__%s__classes",
        BuckConstant.BIN_DIR,
        target.getBasePathWithSlash(),
        target.getShortName());
  }

  @Override
  public boolean isAndroidRule() {
    return false;
  }

  @Override
  public boolean isLibrary() {
    return true;
  }

  @Override
  public Optional<RuleKey> getRuleKeyWithoutDeps() {
    return Optional.of(createRuleKeyWithoutDeps());
  }

  @Override
  public Optional<RuleKey> getRuleKeyWithoutDepsOnDisk(ProjectFilesystem projectFilesystem) {
    return projectFilesystem.readFirstLine(getPathToRuleKeyNoDepsFile())
        .transform(RuleKey.TO_RULE_KEY);
  }

  /**
   * Finds all deps that implement JavaLibraryRule and hash their ABI keys together. If any dep
   * lacks an ABI key, then returns {@link Optional#absent()}.
   */
  @Override
  public Optional<Sha1HashCode> getAbiKeyForDeps() {
    // Make sure to consider declared classpath entries and not just immediate deps because there
    // may be deps that use export_deps=True.
    SortedSet<JavaLibraryRule> rulesWithAbiToConsider = Sets.newTreeSet();
    for (BuildRule dep : getDeps()) {
      if (dep instanceof JavaLibraryRule) {
        JavaLibraryRule javaRule = (JavaLibraryRule)dep;
        rulesWithAbiToConsider.addAll(javaRule.getOutputClasspathEntries().keys());
      }
    }

    Hasher hasher = Hashing.sha1().newHasher();
    for (JavaLibraryRule ruleWithAbiToConsider : rulesWithAbiToConsider) {
      if (ruleWithAbiToConsider == this) {
        continue;
      }

      Optional<Sha1HashCode> abiKey = ruleWithAbiToConsider.getAbiKey();
      if (!abiKey.isPresent()) {
        return Optional.absent();
      }
      hasher.putString(abiKey.get().getHash());
    }

    return Optional.of(new Sha1HashCode(hasher.hash().toString()));
  }

  @Override
  public Optional<Sha1HashCode> getAbiKeyForDepsOnDisk(ProjectFilesystem projectFilesystem) {
    return projectFilesystem.readFirstLine(getPathToAbiKeyForDepsFile())
        .transform(Sha1HashCode.TO_SHA1);
  }

  @Override
  protected RuleKey.Builder appendToRuleKey(RuleKey.Builder builder) {
    super.appendToRuleKey(builder)
        .set("srcs", srcs)
        .setSourcePaths("resources", resources)
        .set("proguard", proguardConfig)
        .set("exportDeps", exportDeps);
    javacOptions.appendToRuleKey(builder);
    return builder;
  }

  @Override
  public BuildRuleType getType() {
    return BuildRuleType.JAVA_LIBRARY;
  }

  @Override
  public ImmutableSortedSet<String> getJavaSrcs() {
    return srcs;
  }

  @Override
  public ImmutableSetMultimap<JavaLibraryRule, String> getTransitiveClasspathEntries() {
    return transitiveClasspathEntriesSupplier.get();
  }

  @Override
  public ImmutableSetMultimap<JavaLibraryRule, String> getDeclaredClasspathEntries() {
    return declaredClasspathEntriesSupplier.get();
  }

  @Override
  public ImmutableSetMultimap<JavaLibraryRule, String> getOutputClasspathEntries() {
    return outputClasspathEntriesSupplier.get();
  }

  @Override
  public AnnotationProcessingData getAnnotationProcessingData() {
    return javacOptions.getAnnotationProcessingData();
  }

  public Optional<String> getProguardConfig() {
    return proguardConfig;
  }

  @Override
  @Nullable
  protected List<String> getInputsToCompareToOutput() {
    return inputsToConsiderForCachingPurposes;
  }

  @Override
  public boolean getExportDeps() {
    return exportDeps;
  }

  /**
   * Building a java_library() rule entails compiling the .java files specified in the srcs
   * attribute. They are compiled into a directory under {@link BuckConstant#BIN_DIR}.
   */
  @Override
  protected final List<Step> buildInternal(BuildContext context) throws IOException {
    ImmutableList.Builder<Step> commands = ImmutableList.builder();
    BuildTarget buildTarget = getBuildTarget();

    JavacOptions javacOptions = this.javacOptions;
    // Only override the bootclasspath if this rule is supposed to compile Android code.
    if (isAndroidRule()) {
      javacOptions = JavacOptions.builder(this.javacOptions)
          .setBootclasspath(context.getAndroidBootclasspathSupplier().get())
          .build();
    }

    // If this rule depends on AndroidResourceRules, then we need to generate the R.java files that
    // this rule needs in order to be able to compile itself.
    androidResourceDeps = UberRDotJavaUtil.getAndroidResourceDeps(this,
        context.getDependencyGraph());
    boolean dependsOnAndroidResourceRules = !androidResourceDeps.isEmpty();
    if (dependsOnAndroidResourceRules) {
      UberRDotJavaUtil.createDummyRDotJavaFiles(androidResourceDeps, buildTarget, commands);
    }

    ImmutableSetMultimap<JavaLibraryRule, String> transitiveClasspathEntries =
        getTransitiveClasspathEntries();
    ImmutableSetMultimap<JavaLibraryRule, String> declaredClasspathEntries =
        getDeclaredClasspathEntries();

    // If this rule depends on AndroidResourceRules, then we need to include the compiled R.java
    // files on the classpath when compiling this rule.
    if (dependsOnAndroidResourceRules) {
      ImmutableSetMultimap.Builder<JavaLibraryRule, String> transitiveClasspathEntriesWithRDotJava =
          ImmutableSetMultimap.builder();
      transitiveClasspathEntriesWithRDotJava.putAll(transitiveClasspathEntries);

      ImmutableSetMultimap.Builder<JavaLibraryRule, String> declaredClasspathEntriesWithRDotJava =
          ImmutableSetMultimap.builder();
      declaredClasspathEntriesWithRDotJava.putAll(declaredClasspathEntries);

      ImmutableSet<String> rDotJavaClasspath =
          ImmutableSet.of(UberRDotJavaUtil.getRDotJavaBinFolder(buildTarget));

      transitiveClasspathEntriesWithRDotJava.putAll(this, rDotJavaClasspath);
      declaredClasspathEntriesWithRDotJava.putAll(this, rDotJavaClasspath);

      declaredClasspathEntries = declaredClasspathEntriesWithRDotJava.build();
      transitiveClasspathEntries = transitiveClasspathEntriesWithRDotJava.build();
    }

    // Javac requires that the root directory for generated sources already exist.
    String annotationGenFolder =
        javacOptions.getAnnotationProcessingData().getGeneratedSourceFolderName();
    if (annotationGenFolder != null) {
      MakeCleanDirectoryStep mkdirGeneratedSources =
          new MakeCleanDirectoryStep(annotationGenFolder);
      commands.add(mkdirGeneratedSources);
    }

    // Always create the output directory, even if there are no .java files to compile because there
    // might be resources that need to be copied there.
    String outputDirectory = getClassesDir(getBuildTarget());
    commands.add(new MakeCleanDirectoryStep(outputDirectory));

    Optional<DependencyCheckingJavacStep.SuggestBuildRules> suggestBuildRule =
        createSuggestBuildFunction(context,
            transitiveClasspathEntries,
            declaredClasspathEntries,
            JAR_RESOLVER);

    // This adds the javac command, along with any supporting commands.
    createCommandsForJavac(
        outputDirectory,
        ImmutableSet.copyOf(transitiveClasspathEntries.values()),
        ImmutableSet.copyOf(declaredClasspathEntries.values()),
        javacOptions,
        context.getBuildDependencies(),
        suggestBuildRule,
        commands);


    // If there are resources, then link them to the appropriate place in the classes directory.
    addResourceCommands(context, commands, outputDirectory, context.getJavaPackageFinder());

    if (outputJar.isPresent()) {
      commands.add(new MakeCleanDirectoryStep(getOutputJarDirPath(getBuildTarget())));
      commands.add(new JarDirectoryStep(
          outputJar.get(),
          Collections.singleton(outputDirectory),
          /* mainClass */ null,
          /* manifestFile */ null));
    }

    Preconditions.checkNotNull(abiKeySupplier,
        "abiKeySupplier must be set so that getAbiKey() will " +
        "return a non-null value if this rule builds successfully.");

    addStepsToRecordAbiToDisk(commands);

    // Add a step that writes the ABI key to the ArtifactCache.
    final ArtifactCache artifactCache = context.getArtifactCache();
    Step recordAbiKey = new AbstractExecutionStep("record ABI key") {
      @Override
      public int execute(ExecutionContext context) {
        RuleKey ruleKey = createRuleKeyForAbiKeyProjection();
        ProjectFilesystem projectFilesystem = context.getProjectFilesystem();
        File abiKeyFile = projectFilesystem.getFileForRelativePath(getPathToAbiOutputFile());
        artifactCache.store(ruleKey, abiKeyFile);
        return 0;
      }
    };
    commands.add(recordAbiKey);

    return commands.build();
  }

  /**
   * Assuming the build has completed successfully, the ABI should have been computed, and it should
   * be stored for subsequent builds.
   */
  private void addStepsToRecordAbiToDisk(ImmutableList.Builder<Step> commands) {
    // Note that the parent directories for all of the files written by these steps should already
    // have been created by a previous step. Therefore, there is no reason to add a MkdrStep here.

    Supplier<String> abiKeyHash = Suppliers.compose(new Function<Sha1HashCode, String>() {
      @Override
      public String apply(Sha1HashCode abiKey) {
        return abiKey.getHash();
      }
    }, abiKeySupplier);
    commands.add(new WriteFileStep(abiKeyHash, getPathToAbiOutputFile()));

    Optional<Sha1HashCode> abiKeyForDeps = getAbiKeyForDeps();
    if (abiKeyForDeps.isPresent()) {
      commands.add(new WriteFileStep(abiKeyForDeps.get().getHash(), getPathToAbiKeyForDepsFile()));
    }

    Optional<RuleKey> ruleKeyNoDeps = getRuleKeyWithoutDeps();
    if (ruleKeyNoDeps.isPresent()) {
      commands.add(new WriteFileStep(ruleKeyNoDeps.get().toString(), getPathToRuleKeyNoDepsFile()));
    }
  }

  /**
   *  @param transitiveNotDeclaredDep A {@link BuildRule} that is contained in the transitive
   *      dependency list but is not declared as a dependency.
   *  @param failedImports A Set of remaining failed imports.  This function will mutate this set
   *      and remove any imports satisfied by {@code transitiveNotDeclaredDep}.
   *  @return whether or not adding {@code transitiveNotDeclaredDep} as a dependency to this build
   *      rule would have satisfied one of the {@code failedImports}.
   */
  private boolean isMissingBuildRule(BuildRule transitiveNotDeclaredDep,
      Set<String> failedImports,
      JarResolver jarResolver) {
    if (!(transitiveNotDeclaredDep instanceof JavaLibraryRule)) {
      return false;
    }

    ImmutableSet<String> classPaths = getTransitiveClasspathEntries()
        .get((JavaLibraryRule)transitiveNotDeclaredDep);
    boolean containsMissingBuildRule = false;
    // Open the output jar for every jar contained as the output of transitiveNotDeclaredDep.  With
    // the exception of rules that export their dependencies, this will result in a single
    // classpath.
    for (String classPath : classPaths) {
      ImmutableSet<String> topLevelSymbols;
      topLevelSymbols = jarResolver.apply(classPath);

      for (String symbolName : topLevelSymbols) {
        if (failedImports.contains(symbolName)) {
          failedImports.remove(symbolName);
          containsMissingBuildRule = true;

          // If we've found all of the missing imports, bail out early.
          if (failedImports.isEmpty()) {
            return true;
          }
        }
      }
    }
    return containsMissingBuildRule;
  }

  /**
   * @return A function that takes a list of failed imports from a javac invocation and returns a
   *    set of rules to suggest that the developer import to satisfy those imports.
   */
  @VisibleForTesting
  Optional<DependencyCheckingJavacStep.SuggestBuildRules> createSuggestBuildFunction(
      BuildContext context,
      ImmutableSetMultimap<JavaLibraryRule, String> transitiveClasspathEntries,
      ImmutableSetMultimap<JavaLibraryRule, String> declaredClasspathEntries,
      final JarResolver jarResolver) {
    if (context.getBuildDependencies() != BuildDependencies.WARN_ON_TRANSITIVE) {
      return Optional.absent();
    }
    final Set<JavaLibraryRule> transitiveNotDeclaredDeps = Sets.difference(
        transitiveClasspathEntries.keySet(),
        declaredClasspathEntries.keySet());

    final ImmutableList<BuildRule> sortedTransitiveNotDeclaredDeps = ImmutableList.copyOf(
        TopologicalSort.sort(context.getDependencyGraph(),
            new Predicate<BuildRule>() {
              @Override
              public boolean apply(BuildRule input) {
                return transitiveNotDeclaredDeps.contains(input);
              }
            })).reverse();

    DependencyCheckingJavacStep.SuggestBuildRules suggestBuildRuleFn =
        new DependencyCheckingJavacStep.SuggestBuildRules() {
      @Override
      public ImmutableSet<String> apply(ImmutableSet<String> failedImports) {
        ImmutableSet.Builder<String> suggestedDeps = ImmutableSet.builder();

        Set<String> remainingImports = Sets.newHashSet(failedImports);

        for (BuildRule transitiveNotDeclaredDep : sortedTransitiveNotDeclaredDeps) {
          boolean ruleCanSeeDep = transitiveNotDeclaredDep.isVisibleTo(
              DefaultJavaLibraryRule.this.getBuildTarget());
          if (ruleCanSeeDep &&
              isMissingBuildRule(transitiveNotDeclaredDep, remainingImports, jarResolver)) {
            suggestedDeps.add(transitiveNotDeclaredDep.getFullyQualifiedName());
          }
          // If we've wiped out all remaining imports, break the loop looking for them.
          if (remainingImports.isEmpty()) {
            break;
          }
        }
        return suggestedDeps.build();
      }
    };
    return Optional.of(suggestBuildRuleFn);
  }

  @Override
  protected void recordOutputFileDetailsAfterFetchFromArtifactCache(ArtifactCache cache,
      ProjectFilesystem projectFilesystem) throws IOException {
    RuleKey ruleKey = createRuleKeyForAbiKeyProjection();
    File abiKeyFile = projectFilesystem.getFileForRelativePath(getPathToAbiOutputFile());
    boolean isSuccess = cache.fetch(ruleKey, abiKeyFile);
    if (isSuccess) {
      String abiKey = Files.readFirstLine(abiKeyFile, Charsets.UTF_8);
      Sha1HashCode hash = abiKey != null ? new Sha1HashCode(abiKey) : null;
      setAbiKey(Suppliers.ofInstance(hash));
    } else {
      // It is possible that, for whatever reason, the code that uploaded the artifact failed to
      // upload the corresponding ABI key. When this happens, getAbiKey() should return null.
      setAbiKey(Suppliers.ofInstance((Sha1HashCode)null));
    }
  }

  /**
   * This returns a RuleKey that is a hash of this rule's ordinary RuleKey and a known value. (The
   * known value is {@code "namespace.abi_key"}, which includes a period to distinguish it from
   * an ordinary property name.) This new RuleKey is associated with the ABI for this rule in the
   * {@link ArtifactCache}. This enables us to query an {@link ArtifactCache} for an ABI for a build
   * rule when we know its RuleKey, because we can reproduce the RuleKey returned by this method
   * using the rule's RuleKey and the value {@code "namespace.abi_key"}.
   */
  private RuleKey createRuleKeyForAbiKeyProjection() {
    RuleKey.Builder builder = RuleKey.builder(this);
    appendToRuleKey(builder);
    builder.set("namespace.abi_key", (String)null);
    return builder.build();
  }

  @Override
  public boolean initializeFromDisk(ProjectFilesystem projectFilesystem) {
    Optional<String> abiKeyHash = projectFilesystem.readFirstLine(getPathToAbiOutputFile());
    if (abiKeyHash.isPresent()) {
      String hash = abiKeyHash.get();
      setAbiKey(Suppliers.ofInstance(new Sha1HashCode(hash)));
      return true;
    } else {
      return false;
    }
  }

  @Override
  public Optional<Sha1HashCode> getAbiKey() {
    Preconditions.checkState(isRuleBuilt(),
        "%s must be built before its ABI key can be returned.", this);
    return Optional.fromNullable(abiKeySupplier.get());
  }

  private void setAbiKey(Supplier<Sha1HashCode> abiKeySupplier) {
    Preconditions.checkState(this.abiKeySupplier == null, "abiKeySupplier should be set only once");
    this.abiKeySupplier = abiKeySupplier;
  }


  @VisibleForTesting
  void addResourceCommands(BuildContext context,
                           ImmutableList.Builder<Step> commands,
                           String outputDirectory,
                           JavaPackageFinder javaPackageFinder) {
    if (!resources.isEmpty()) {
      String targetPackageDir = javaPackageFinder.findJavaPackageForPath(
          getBuildTarget().getBasePathWithSlash())
          .replace('.', File.separatorChar);

      for (SourcePath rawResource : resources) {
        // If the path to the file defining this rule were:
        // "first-party/orca/lib-http/tests/com/facebook/orca/BUILD"
        //
        // And the value of resource were:
        // "first-party/orca/lib-http/tests/com/facebook/orca/protocol/base/batch_exception1.txt"
        //
        // Then javaPackageAsPath would be:
        // "com/facebook/orca/protocol/base/"
        //
        // And the path that we would want to copy to the classes directory would be:
        // "com/facebook/orca/protocol/base/batch_exception1.txt"
        //
        // Therefore, some path-wrangling is required to produce the correct string.

        String resource = rawResource.resolve(context).toString();
        String javaPackageAsPath = javaPackageFinder.findJavaPackageFolderForPath(resource);
        String relativeSymlinkPath;


        if (resource.startsWith(BuckConstant.BUCK_OUTPUT_DIRECTORY) ||
            resource.startsWith(BuckConstant.GEN_DIR) ||
            resource.startsWith(BuckConstant.BIN_DIR) ||
            resource.startsWith(BuckConstant.ANNOTATION_DIR)) {
          // Handle the case where we depend on the output of another BuildRule. In that case, just
          // grab the output and put in the same package as this target would be in.
          relativeSymlinkPath = String.format(
              "%s/%s", targetPackageDir, rawResource.resolve(context).getFileName());
        } else if ("".equals(javaPackageAsPath)) {
          // In this case, the project root is acting as the default package, so the resource path
          // works fine.
          relativeSymlinkPath = resource;
        } else {
          int lastIndex = resource.lastIndexOf(javaPackageAsPath);
          Preconditions.checkState(lastIndex >= 0,
              "Resource path %s must contain %s",
              resource,
              javaPackageAsPath);

          relativeSymlinkPath = resource.substring(lastIndex);
        }
        String target = outputDirectory + '/' + relativeSymlinkPath;
        MkdirAndSymlinkFileStep link = new MkdirAndSymlinkFileStep(resource, target);
        commands.add(link);
      }
    }
  }

  @Override
  public String getPathToOutputFile() {
    return outputJar.orNull();
  }

  public static Builder newJavaLibraryRuleBuilder(AbstractBuildRuleBuilderParams params) {
    return new Builder(params);
  }

  public static class Builder extends AbstractBuildRuleBuilder<DefaultJavaLibraryRule> implements
      SrcsAttributeBuilder, ResourcesAttributeBuilder {

    protected Set<String> srcs = Sets.newHashSet();
    protected Set<SourcePath> resources = Sets.newHashSet();
    protected final AnnotationProcessingParams.Builder annotationProcessingBuilder =
        new AnnotationProcessingParams.Builder();
    protected boolean exportDeps = false;
    protected JavacOptions.Builder javacOptions = JavacOptions.builder();
    protected Optional<String> proguardConfig = Optional.absent();

    protected Builder(AbstractBuildRuleBuilderParams params) {
      super(params);
    }

    @Override
    public DefaultJavaLibraryRule build(BuildRuleResolver ruleResolver) {
      BuildRuleParams buildRuleParams = createBuildRuleParams(ruleResolver);
      AnnotationProcessingParams processingParams =
          annotationProcessingBuilder.build(ruleResolver);
      javacOptions.setAnnotationProcessingData(processingParams);

      return new DefaultJavaLibraryRule(
          buildRuleParams,
          srcs,
          resources,
          proguardConfig,
          exportDeps,
          javacOptions.build());
    }

    public AnnotationProcessingParams.Builder getAnnotationProcessingBuilder() {
      return annotationProcessingBuilder;
    }

    @Override
    public Builder setBuildTarget(BuildTarget buildTarget) {
      super.setBuildTarget(buildTarget);
      annotationProcessingBuilder.setOwnerTarget(buildTarget);
      return this;
    }

    @Override
    public Builder addDep(BuildTarget dep) {
      super.addDep(dep);
      return this;
    }

    @Override
    public Builder addSrc(String src) {
      srcs.add(src);
      return this;
    }

    @Override
    public Builder addResource(SourcePath relativePathToResource) {
      resources.add(relativePathToResource);
      return this;
    }

    @Override
    public Builder addVisibilityPattern(BuildTargetPattern visibilityPattern) {
      super.addVisibilityPattern(visibilityPattern);
      return this;
    }

    public Builder setProguardConfig(Optional<String> proguardConfig) {
      this.proguardConfig = Preconditions.checkNotNull(proguardConfig);
      return this;
    }


    public Builder setSourceLevel(String sourceLevel) {
      javacOptions.setSourceLevel(sourceLevel);
      return this;
    }

    public Builder setTargetLevel(String targetLevel) {
      javacOptions.setTargetLevel(targetLevel);
      return this;
    }

    public Builder setExportDeps(boolean exportDeps) {
      this.exportDeps = exportDeps;
      return this;
    }
  }
}
