// 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.rules.java;

import static com.google.devtools.build.lib.packages.Type.STRING_LIST;

import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.Allowlist;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.Runfiles;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.rules.java.JavaConfiguration.ImportDepsCheckingLevel;
import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider.JavaOutput;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.annotation.Nullable;

/** An implementation for the "java_import" rule. */
public class JavaImport implements RuleConfiguredTargetFactory {
  private final JavaSemantics semantics;

  protected JavaImport(JavaSemantics semantics) {
    this.semantics = semantics;
  }

  @Override
  @Nullable
  public ConfiguredTarget create(RuleContext ruleContext)
      throws InterruptedException, RuleErrorException, ActionConflictException {
    ImmutableList<Artifact> srcJars = ImmutableList.of();
    ImmutableList<Artifact> jars = collectJars(ruleContext);
    Artifact srcJar = ruleContext.getPrerequisiteArtifact("srcjar");

    if (ruleContext.hasErrors()) {
      return null;
    }

    checkJarsAttributeEmpty(ruleContext);

    if (exportError(ruleContext)) {
      ruleContext.ruleError(
          "java_import.exports is no longer supported; use java_import.deps instead");
    }

    ImmutableList<TransitiveInfoCollection> targets =
        ImmutableList.<TransitiveInfoCollection>builder()
            .addAll(ruleContext.getPrerequisites("deps"))
            .addAll(ruleContext.getPrerequisites("exports"))
            .build();
    final JavaCommon common =
        new JavaCommon(
            ruleContext,
            semantics,
            /* sources= */ ImmutableList.<Artifact>of(),
            targets,
            targets,
            targets);
    semantics.checkRule(ruleContext, common);

    // No need for javac options - no compilation happening here.
    ImmutableBiMap.Builder<Artifact, Artifact> compilationToRuntimeJarMapBuilder =
        ImmutableBiMap.builder();
    ImmutableList<Artifact> interfaceJars =
        processWithIjarIfNeeded(jars, ruleContext, compilationToRuntimeJarMapBuilder);

    JavaCompilationArtifacts javaArtifacts = collectJavaArtifacts(jars, interfaceJars);
    common.setJavaCompilationArtifacts(javaArtifacts);

    boolean neverLink = JavaCommon.isNeverLink(ruleContext);
    JavaCompilationArgsProvider javaCompilationArgs =
        common.collectJavaCompilationArgs(neverLink, false);
    NestedSet<Artifact> transitiveJavaSourceJars =
        collectTransitiveJavaSourceJars(ruleContext, srcJar);
    if (srcJar != null) {
      srcJars = ImmutableList.of(srcJar);
    }

    Artifact jdepsArtifact = null;
    JavaToolchainProvider toolchain = JavaToolchainProvider.from(ruleContext);
    Artifact depsChecker = toolchain.depsChecker();
    if (Allowlist.hasAllowlist(ruleContext, "java_import_deps_checking")
        && !Allowlist.isAvailable(ruleContext, "java_import_deps_checking")
        && !ruleContext.attributes().get("tags", STRING_LIST).contains("incomplete-deps")
        && !jars.isEmpty()
        && depsChecker != null) {
      jdepsArtifact =
          ruleContext.getUniqueDirectoryArtifact(
              "_java_import", "jdeps.proto", ruleContext.getBinOrGenfilesDirectory());
      JavaCompilationArgsProvider provider = JavaCompilationArgsProvider.legacyFromTargets(targets);
      JavaTargetAttributes attributes =
          new JavaTargetAttributes.Builder(semantics)
              .merge(provider)
              .addDirectJars(provider.getDirectCompileTimeJars())
              .build();
      ImportDepsCheckActionBuilder.newBuilder()
          .importDepsChecker(depsChecker)
          .bootclasspath(toolchain.getBootclasspath().bootclasspath())
          .declareDeps(attributes.getDirectJars())
          .transitiveDeps(attributes.getCompileTimeClassPath())
          .checkJars(NestedSetBuilder.wrap(Order.STABLE_ORDER, jars))
          .importDepsCheckingLevel(ImportDepsCheckingLevel.ERROR)
          .jdepsOutputArtifact(jdepsArtifact)
          .ruleLabel(ruleContext.getLabel())
          .buildAndRegister(ruleContext);
    }

    // The "neverlink" attribute is transitive, so if it is enabled, we don't add any
    // runfiles from this target or its dependencies.
    Runfiles runfiles =
        neverLink
            ? Runfiles.EMPTY
            : new Runfiles.Builder(
                    ruleContext.getWorkspaceName(),
                    ruleContext.getConfiguration().legacyExternalRunfiles())
                // add the jars to the runfiles
                .addArtifacts(javaArtifacts.getRuntimeJars())
                .addTargets(
                    targets,
                    RunfilesProvider.DEFAULT_RUNFILES,
                    ruleContext.getConfiguration().alwaysIncludeFilesToBuildInData())
                .addRunfiles(ruleContext, RunfilesProvider.DEFAULT_RUNFILES)
                .build();

    RuleConfiguredTargetBuilder ruleBuilder = new RuleConfiguredTargetBuilder(ruleContext);
    NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder();
    filesBuilder.addAll(jars);

    ImmutableBiMap<Artifact, Artifact> compilationToRuntimeJarMap =
        compilationToRuntimeJarMapBuilder.buildOrThrow();

    NestedSet<Artifact> filesToBuild = filesBuilder.build();

    JavaRuleOutputJarsProvider.Builder ruleOutputJarsProviderBuilder =
        JavaRuleOutputJarsProvider.builder();
    for (Artifact jar : jars) {
      ruleOutputJarsProviderBuilder.addJavaOutput(
          JavaOutput.builder()
              .setClassJar(jar)
              .setCompileJar(compilationToRuntimeJarMap.inverse().get(jar))
              .addSourceJar(srcJar)
              .build());
    }

    NestedSet<Artifact> proguardSpecs = new ProguardLibrary(ruleContext).collectProguardSpecs();

    JavaRuleOutputJarsProvider ruleOutputJarsProvider = ruleOutputJarsProviderBuilder.build();
    JavaSourceJarsProvider sourceJarsProvider =
        JavaSourceJarsProvider.create(transitiveJavaSourceJars, srcJars);
    JavaCompilationArgsProvider compilationArgsProvider = javaCompilationArgs;

    JavaInfo.Builder javaInfoBuilder = JavaInfo.Builder.create();
    common.addTransitiveInfoProviders(ruleBuilder, javaInfoBuilder, filesToBuild, null);

    JavaInfo javaInfo =
        javaInfoBuilder
            .addProvider(JavaCompilationArgsProvider.class, compilationArgsProvider)
            .addProvider(JavaRuleOutputJarsProvider.class, ruleOutputJarsProvider)
            .addProvider(JavaSourceJarsProvider.class, sourceJarsProvider)
            .setRuntimeJars(javaArtifacts.getRuntimeJars())
            .setJavaConstraints(JavaCommon.getConstraints(ruleContext))
            .setNeverlink(neverLink)
            .build();

    if (jdepsArtifact != null) {
      ruleBuilder.addOutputGroup(OutputGroupInfo.VALIDATION, jdepsArtifact);
    }

    return ruleBuilder
        .setFilesToBuild(filesToBuild)
        .addNativeDeclaredProvider(javaInfo)
        .add(RunfilesProvider.class, RunfilesProvider.simple(runfiles))
        .addNativeDeclaredProvider(new ProguardSpecProvider(proguardSpecs))
        .addOutputGroup(JavaSemantics.SOURCE_JARS_OUTPUT_GROUP, transitiveJavaSourceJars)
        .addOutputGroup(
            JavaSemantics.DIRECT_SOURCE_JARS_OUTPUT_GROUP,
            NestedSetBuilder.wrap(Order.STABLE_ORDER, sourceJarsProvider.getSourceJars()))
        .addOutputGroup(OutputGroupInfo.HIDDEN_TOP_LEVEL, proguardSpecs)
        .build();
  }

  private static boolean exportError(RuleContext ruleContext) {
    if (!ruleContext.attributes().isAttributeValueExplicitlySpecified("exports")) {
      return false;
    }
    if (ruleContext.getFragment(JavaConfiguration.class).disallowJavaImportExports()) {
      return true;
    }
    return Allowlist.hasAllowlist(ruleContext, "java_import_exports")
        && !Allowlist.isAvailable(ruleContext, "java_import_exports");
  }

  private static void checkJarsAttributeEmpty(RuleContext ruleContext) {
    if (ruleContext.getPrerequisites("jars").isEmpty()
        && ruleContext.getFragment(JavaConfiguration.class).disallowJavaImportEmptyJars()
        && Allowlist.hasAllowlist(ruleContext, "java_import_empty_jars")
        && !Allowlist.isAvailable(ruleContext, "java_import_empty_jars")) {
      ruleContext.ruleError(
          "empty java_import.jars is no longer supported " + ruleContext.getLabel());
    }
  }

  private NestedSet<Artifact> collectTransitiveJavaSourceJars(
      RuleContext ruleContext, Artifact srcJar) {
    NestedSetBuilder<Artifact> transitiveJavaSourceJarBuilder = NestedSetBuilder.stableOrder();
    if (srcJar != null) {
      transitiveJavaSourceJarBuilder.add(srcJar);
    }
    for (JavaSourceJarsProvider other :
        JavaInfo.getProvidersFromListOfTargets(
            JavaSourceJarsProvider.class, ruleContext.getPrerequisites("exports"))) {
      transitiveJavaSourceJarBuilder.addTransitive(other.getTransitiveSourceJars());
    }
    return transitiveJavaSourceJarBuilder.build();
  }

  private JavaCompilationArtifacts collectJavaArtifacts(
      ImmutableList<Artifact> jars, ImmutableList<Artifact> interfaceJars) {
    return new JavaCompilationArtifacts.Builder()
        .addRuntimeJars(jars)
        // interfaceJars Artifacts have proper owner labels
        .addInterfaceJarsWithFullJars(interfaceJars, jars)
        .build();
  }

  private ImmutableList<Artifact> collectJars(RuleContext ruleContext) {
    Set<Artifact> jars = new LinkedHashSet<>();
    for (TransitiveInfoCollection info : ruleContext.getPrerequisites("jars")) {
      if (JavaInfo.getProvider(JavaCompilationArgsProvider.class, info) != null) {
        ruleContext.attributeError("jars", "should not refer to Java rules");
      }
      for (Artifact jar : info.getProvider(FileProvider.class).getFilesToBuild().toList()) {
        if (!JavaSemantics.JAR.matches(jar.getFilename())) {
          ruleContext.attributeError("jars", jar.getFilename() + " is not a .jar file");
        } else {
          if (!jars.add(jar)) {
            ruleContext.attributeError("jars", jar.getFilename() + " is a duplicate");
          }
        }
      }
    }
    return ImmutableList.copyOf(jars);
  }

  private ImmutableList<Artifact> processWithIjarIfNeeded(
      ImmutableList<Artifact> jars,
      RuleContext ruleContext,
      ImmutableMap.Builder<Artifact, Artifact> compilationToRuntimeJarMap) {
    ImmutableList.Builder<Artifact> interfaceJarsBuilder = ImmutableList.builder();
    boolean useIjar = ruleContext.getFragment(JavaConfiguration.class).getUseIjars();
    for (Artifact jar : jars) {
      Artifact interfaceJar =
          useIjar
              ? JavaCompilationHelper.createIjarAction(
                  ruleContext,
                  JavaToolchainProvider.from(ruleContext),
                  jar,
                  ruleContext.getLabel(),
                  /* injectingRuleKind */ null,
                  true)
              : jar;
      interfaceJarsBuilder.add(interfaceJar);
      compilationToRuntimeJarMap.put(interfaceJar, jar);
    }
    return interfaceJarsBuilder.build();
  }
}
