// 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.collect.nestedset.Order.STABLE_ORDER;
import static com.google.devtools.build.lib.packages.Type.BOOLEAN;
import static com.google.devtools.build.lib.rules.cpp.CppRuleClasses.JAVA_LAUNCHER_LINK;
import static com.google.devtools.build.lib.rules.cpp.CppRuleClasses.STATIC_LINKING_MODE;
import static com.google.devtools.build.lib.rules.java.DeployArchiveBuilder.Compression.COMPRESSED;
import static java.util.Objects.requireNonNull;

import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ExecutionRequirements;
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.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.PrerequisiteArtifacts;
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.RunfilesSupport;
import com.google.devtools.build.lib.analysis.SourceManifestAction;
import com.google.devtools.build.lib.analysis.SourceManifestAction.ManifestType;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.FileWriteAction;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.config.CompilationMode;
import com.google.devtools.build.lib.analysis.test.ExecutionInfo;
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.BuildType;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.rules.apple.ApplePlatform;
import com.google.devtools.build.lib.rules.cpp.CcCommon;
import com.google.devtools.build.lib.rules.cpp.CcCommon.Language;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppHelper;
import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider.ClasspathType;
import com.google.devtools.build.lib.rules.java.JavaConfiguration.OneVersionEnforcementLevel;
import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider.JavaOutput;
import com.google.devtools.build.lib.rules.java.proto.GeneratedExtensionRegistryProvider;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.util.StringCanonicalizer;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
import net.starlark.java.eval.EvalException;

/** An implementation of java_binary. */
public class JavaBinary implements RuleConfiguredTargetFactory {
  private static final PathFragment CPP_RUNTIMES = PathFragment.create("_cpp_runtimes");

  private final JavaSemantics semantics;

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

  @Override
  @Nullable
  public ConfiguredTarget create(RuleContext ruleContext)
      throws InterruptedException, RuleErrorException, ActionConflictException {
    final JavaCommon common = new JavaCommon(ruleContext, semantics);
    DeployArchiveBuilder deployArchiveBuilder = new DeployArchiveBuilder(semantics, ruleContext);
    Runfiles.Builder runfilesBuilder =
        new Runfiles.Builder(
            ruleContext.getWorkspaceName(),
            ruleContext.getConfiguration().legacyExternalRunfiles());
    List<String> jvmFlags = new ArrayList<>();

    JavaTargetAttributes.Builder attributesBuilder = common.initCommon();
    attributesBuilder.addClassPathResources(
        ruleContext.getPrerequisiteArtifacts("classpath_resources").list());

    // Add Java8 timezone resource data
    addTimezoneResourceForJavaBinaries(ruleContext, attributesBuilder);

    List<String> userJvmFlags = JavaCommon.getJvmFlags(ruleContext);

    ruleContext.checkSrcsSamePackage(true);
    boolean createExecutable = ruleContext.attributes().get("create_executable", Type.BOOLEAN);

    if (!createExecutable
        && ruleContext.attributes().isAttributeValueExplicitlySpecified("launcher")) {
      ruleContext.ruleError("launcher specified but create_executable is false");
    }

    if (!ruleContext.attributes().get("use_launcher", Type.BOOLEAN)
        && ruleContext.attributes().isAttributeValueExplicitlySpecified("launcher")) {
      ruleContext.ruleError("launcher specified but use_launcher is false");
    }

    if (ruleContext.attributes().isAttributeValueExplicitlySpecified("add_exports")
        && Allowlist.hasAllowlist(ruleContext, "java_add_exports_allowlist")
        && !Allowlist.isAvailable(ruleContext, "java_add_exports_allowlist")) {
      ruleContext.ruleError("setting add_exports is not permitted");
    }
    if (ruleContext.attributes().isAttributeValueExplicitlySpecified("add_opens")
        && Allowlist.hasAllowlist(ruleContext, "java_add_opens_allowlist")
        && !Allowlist.isAvailable(ruleContext, "java_add_opens_allowlist")) {
      ruleContext.ruleError("setting add_opens is not permitted");
    }

    semantics.checkRule(ruleContext, common);
    semantics.checkForProtoLibraryAndJavaProtoLibraryOnSameProto(ruleContext, common);
    String mainClass = semantics.getMainClass(ruleContext, common.getSrcsArtifacts());
    String originalMainClass = mainClass;
    if (ruleContext.hasErrors()) {
      return null;
    }

    // Collect the transitive dependencies.
    JavaCompilationHelper helper =
        new JavaCompilationHelper(ruleContext, semantics, common.getJavacOpts(), attributesBuilder);
    List<TransitiveInfoCollection> deps =
        Lists.newArrayList(common.targetsTreatedAsDeps(ClasspathType.COMPILE_ONLY));
    helper.addLibrariesToAttributes(deps);
    attributesBuilder.addNativeLibraries(
        JavaCommon.collectNativeLibraries(common.targetsTreatedAsDeps(ClasspathType.BOTH)));

    // deploy_env is valid for java_binary, but not for java_test.
    if (ruleContext.getRule().isAttrDefined("deploy_env", BuildType.LABEL_LIST)) {
      for (JavaRuntimeClasspathProvider envTarget :
          ruleContext.getPrerequisites("deploy_env", JavaRuntimeClasspathProvider.class)) {
        attributesBuilder.addExcludedArtifacts(envTarget.getRuntimeClasspathNestedSet());
      }
    }

    Artifact srcJar = ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_SOURCE_JAR);
    JavaSourceJarsProvider.Builder javaSourceJarsProviderBuilder =
        JavaSourceJarsProvider.builder()
            .addSourceJar(srcJar)
            .addAllTransitiveSourceJars(common.collectTransitiveSourceJars(srcJar));
    Artifact classJar = ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_CLASS_JAR);

    CppConfiguration cppConfiguration =
        ruleContext.getConfiguration().getFragment(CppConfiguration.class);
    CcToolchainProvider ccToolchain =
        CppHelper.getToolchainUsingDefaultCcToolchainAttribute(ruleContext);
    FeatureConfiguration featureConfiguration = null;
    try {
      featureConfiguration =
          CcCommon.configureFeaturesOrThrowEvalException(
              /* requestedFeatures= */ ImmutableSet.<String>builder()
                  .addAll(ruleContext.getFeatures())
                  .add(STATIC_LINKING_MODE)
                  .add(JAVA_LAUNCHER_LINK)
                  .build(),
              /* unsupportedFeatures= */ ruleContext.getDisabledFeatures(),
              Language.CPP,
              ccToolchain,
              cppConfiguration);
    } catch (EvalException e) {
      ruleContext.ruleError(e.getMessage());
    }
    boolean stripAsDefault =
        ccToolchain.shouldCreatePerObjectDebugInfo(featureConfiguration, cppConfiguration)
            && cppConfiguration.getCompilationMode() == CompilationMode.OPT;
    DeployArchiveBuilder unstrippedDeployArchiveBuilder = null;
    if (stripAsDefault) {
      unstrippedDeployArchiveBuilder = new DeployArchiveBuilder(semantics, ruleContext);
    }
    Pair<Artifact, Artifact> launcherAndUnstrippedLauncher =
        semantics.getLauncher(
            ruleContext,
            common,
            deployArchiveBuilder,
            unstrippedDeployArchiveBuilder,
            runfilesBuilder,
            jvmFlags,
            attributesBuilder,
            stripAsDefault,
            ccToolchain,
            featureConfiguration);
    Artifact launcher = launcherAndUnstrippedLauncher.first;
    Artifact unstrippedLauncher = launcherAndUnstrippedLauncher.second;

    JavaCompilationArtifacts.Builder javaArtifactsBuilder = new JavaCompilationArtifacts.Builder();

    NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder();
    Artifact executableForRunfiles = null;
    if (createExecutable) {
      // This artifact is named as the rule itself, e.g. //foo:bar_bin -> bazel-bin/foo/bar_bin
      // On Windows, it's going to be bazel-bin/foo/bar_bin.exe
      if (OS.getCurrent() == OS.WINDOWS) {
        executableForRunfiles =
            ruleContext.getImplicitOutputArtifact(ruleContext.getTarget().getName() + ".exe");
      } else {
        executableForRunfiles = ruleContext.createOutputArtifact();
      }
      filesBuilder.add(classJar).add(executableForRunfiles);

      if (ruleContext.getConfiguration().isCodeCoverageEnabled()) {
        mainClass = semantics.addCoverageSupport(helper, executableForRunfiles);
      }
    } else {
      filesBuilder.add(classJar);
    }

    JavaCompileOutputs<Artifact> outputs = helper.createOutputs(classJar);
    JavaRuleOutputJarsProvider.Builder ruleOutputJarsProviderBuilder =
        JavaRuleOutputJarsProvider.builder()
            .addJavaOutput(
                JavaOutput.builder().fromJavaCompileOutputs(outputs).addSourceJar(srcJar).build());

    JavaTargetAttributes attributes = attributesBuilder.build();
    List<Artifact> nativeLibraries = attributes.getNativeLibraries();
    if (!nativeLibraries.isEmpty()) {
      jvmFlags.add(
          "-Djava.library.path="
              + JavaCommon.javaLibraryPath(
                  nativeLibraries, ruleContext.getRule().getPackage().getWorkspaceName()));
    }

    JavaConfiguration javaConfig = ruleContext.getFragment(JavaConfiguration.class);
    if (attributes.hasMessages()) {
      helper.setTranslations(semantics.translate(ruleContext, attributes.getMessages()));
    }

    if (attributes.hasSources() || attributes.hasResources()) {
      // We only want to add a jar to the classpath of a dependent rule if it has content.
      javaArtifactsBuilder.addRuntimeJar(classJar);
    }

    GeneratedExtensionRegistryProvider generatedExtensionRegistryProvider =
        semantics.createGeneratedExtensionRegistry(
            ruleContext,
            common,
            filesBuilder,
            javaArtifactsBuilder,
            ruleOutputJarsProviderBuilder,
            javaSourceJarsProviderBuilder);
    javaArtifactsBuilder.setCompileTimeDependencies(outputs.depsProto());

    JavaCompilationArtifacts javaArtifacts = javaArtifactsBuilder.build();
    common.setJavaCompilationArtifacts(javaArtifacts);

    helper.createCompileAction(outputs);
    helper.createSourceJarAction(srcJar, outputs.genSource());

    common.setClassPathFragment(
        new ClasspathConfiguredFragment(
            javaArtifacts, attributes, false, helper.getBootclasspathOrDefault()));

    Iterables.addAll(
        jvmFlags, semantics.getJvmFlags(ruleContext, common.getSrcsArtifacts(), userJvmFlags));

    JavaModuleFlagsProvider javaModuleFlagsProvider =
        JavaModuleFlagsProvider.create(
            ruleContext,
            JavaInfo.getProvidersFromListOfTargets(
                JavaModuleFlagsProvider.class, common.targetsTreatedAsDeps(ClasspathType.BOTH))
                .stream());

    javaModuleFlagsProvider.toFlags().stream()
        // Share strings in the heap with the equivalent javacopt flags, which are also interned
        .map(StringCanonicalizer::intern)
        .forEach(jvmFlags::add);

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

    Artifact executableToRun = executableForRunfiles;
    if (createExecutable) {
      String javaExecutable;
      if (semantics.isJavaExecutableSubstitution()) {
        javaExecutable = JavaCommon.getJavaBinSubstitution(ruleContext, launcher);
      } else {
        javaExecutable = JavaCommon.getJavaExecutableForStub(ruleContext, launcher);
      }
      // Create a shell stub for a Java application
      executableToRun =
          semantics.createStubAction(
              ruleContext,
              common,
              jvmFlags,
              executableForRunfiles,
              mainClass,
              originalMainClass,
              filesBuilder,
              javaExecutable,
              /* createCoverageMetadataJar= */ false);
      if (!executableToRun.equals(executableForRunfiles)) {
        filesBuilder.add(executableToRun);
        runfilesBuilder.addArtifact(executableToRun);
      }
    }

    JavaSourceJarsProvider sourceJarsProvider = javaSourceJarsProviderBuilder.build();
    NestedSet<Artifact> transitiveSourceJars = sourceJarsProvider.getTransitiveSourceJars();

    // TODO(bazel-team): if (getOptions().sourceJars) then make this a dummy prerequisite for the
    // DeployArchiveAction ? Needs a few changes there as we can't pass inputs
    SingleJarActionBuilder.createSourceJarAction(
        ruleContext,
        semantics,
        NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER),
        transitiveSourceJars,
        ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_DEPLOY_SOURCE_JAR));

    RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext);
    builder.add(
        JavaPrimaryClassProvider.class,
        new JavaPrimaryClassProvider(
            semantics.getPrimaryClass(ruleContext, common.getSrcsArtifacts())));
    if (generatedExtensionRegistryProvider != null) {
      builder.addNativeDeclaredProvider(generatedExtensionRegistryProvider);
    }

    Artifact deployJar =
        ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_DEPLOY_JAR);

    if (javaConfig.oneVersionEnforcementLevel() != OneVersionEnforcementLevel.OFF) {
      // This JavaBinary class is also the implementation for java_test targets (via the
      // {Google,Bazel}JavaTest subclass). java_test targets can have their one version enforcement
      // disabled with a second flag (to avoid the incremental build performance cost at the expense
      // of safety.)
      if (javaConfig.enforceOneVersionOnJavaTests() || !isJavaTestRule(ruleContext)) {
        Artifact oneVersionOutputArtifact =
            OneVersionCheckActionBuilder.newBuilder()
                .withEnforcementLevel(javaConfig.oneVersionEnforcementLevel())
                .useToolchain(JavaToolchainProvider.from(ruleContext))
                .checkJars(
                    NestedSetBuilder.fromNestedSet(attributes.getRuntimeClassPath())
                        .add(classJar)
                        .build())
                .build(ruleContext);
        if (oneVersionOutputArtifact != null) {
          builder.addOutputGroup(OutputGroupInfo.VALIDATION, oneVersionOutputArtifact);
        }
      }
    }
    NestedSet<Artifact> filesToBuild = filesBuilder.build();

    NestedSet<Artifact> dynamicRuntimeActionInputs;
    try {
      dynamicRuntimeActionInputs = ccToolchain.getDynamicRuntimeLinkInputs(featureConfiguration);
    } catch (EvalException e) {
      throw ruleContext.throwWithRuleError(e);
    }

    collectDefaultRunfiles(
        runfilesBuilder,
        ruleContext,
        common,
        javaArtifacts,
        filesToBuild,
        launcher,
        dynamicRuntimeActionInputs);
    Runfiles defaultRunfiles = runfilesBuilder.build();

    RunfilesSupport runfilesSupport = null;
    NestedSetBuilder<Artifact> extraFilesToRunBuilder = NestedSetBuilder.stableOrder();
    if (createExecutable) {
      List<String> extraArgs =
          new ArrayList<>(semantics.getExtraArguments(ruleContext, common.getSrcsArtifacts()));
      // The executable we pass here will be used when creating the runfiles directory. E.g. for the
      // stub script called bazel-bin/foo/bar_bin, the runfiles directory will be created under
      // bazel-bin/foo/bar_bin.runfiles . On platforms where there's an extra stub script (Windows)
      // which dispatches to this one, we still create the runfiles directory for the shell script,
      // but use the dispatcher script (a batch file) as the RunfilesProvider's executable.
      runfilesSupport =
          RunfilesSupport.withExecutable(
              ruleContext, defaultRunfiles, executableForRunfiles, extraArgs);
      extraFilesToRunBuilder.add(runfilesSupport.getRunfilesMiddleman());
    }

    RunfilesProvider runfilesProvider =
        RunfilesProvider.withData(
            defaultRunfiles,
            new Runfiles.Builder(
                    ruleContext.getWorkspaceName(),
                    ruleContext.getConfiguration().legacyExternalRunfiles())
                .merge(runfilesSupport)
                .build());

    ImmutableList<String> deployManifestLines =
        getDeployManifestLines(ruleContext, originalMainClass);

    Artifact jsa = createSharedArchive(ruleContext, javaArtifacts, attributes);

    if (ruleContext.isAttrDefined("hermetic", BOOLEAN)
        && ruleContext.attributes().get("hermetic", BOOLEAN)) {
      if (!createExecutable) {
        ruleContext.ruleError("hermetic specified but create_executable is false");
      }
      JavaRuntimeInfo javaRuntime = JavaRuntimeInfo.from(ruleContext);
      if (javaRuntime.libModules() == null) {
        ruleContext.attributeError(
            "hermetic", "hermetic specified but java_runtime.lib_modules is absent");
      }
      deployArchiveBuilder
          .setJavaHome(javaRuntime.javaHomePathFragment())
          .setLibModules(javaRuntime.libModules())
          .setHermeticInputs(javaRuntime.hermeticInputs());
    }

    deployArchiveBuilder
        .setOutputJar(deployJar)
        .setJavaStartClass(mainClass)
        .setDeployManifestLines(deployManifestLines)
        .setAttributes(attributes)
        .addRuntimeJars(javaArtifacts.getRuntimeJars())
        .setIncludeBuildData(true)
        .setRunfilesMiddleman(
            runfilesSupport == null ? null : runfilesSupport.getRunfilesMiddleman())
        .setCompression(COMPRESSED)
        .setLauncher(launcher)
        .setOneVersionEnforcementLevel(
            javaConfig.oneVersionEnforcementLevel(),
            JavaToolchainProvider.from(ruleContext).getOneVersionAllowlist())
        .setMultiReleaseDeployJars(javaConfig.multiReleaseDeployJars())
        .setSharedArchive(jsa)
        .setAddExports(javaModuleFlagsProvider.addExports())
        .setAddOpens(javaModuleFlagsProvider.addOpens())
        .build();

    Artifact unstrippedDeployJar =
        ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_UNSTRIPPED_BINARY_DEPLOY_JAR);
    if (stripAsDefault) {
      requireNonNull(unstrippedDeployArchiveBuilder); // guarded by stripAsDefault
      unstrippedDeployArchiveBuilder
          .setOutputJar(unstrippedDeployJar)
          .setJavaStartClass(mainClass)
          .setDeployManifestLines(deployManifestLines)
          .setAttributes(attributes)
          .addRuntimeJars(javaArtifacts.getRuntimeJars())
          .setIncludeBuildData(true)
          .setRunfilesMiddleman(
              runfilesSupport == null ? null : runfilesSupport.getRunfilesMiddleman())
          .setCompression(COMPRESSED)
          .setLauncher(unstrippedLauncher);

      unstrippedDeployArchiveBuilder.build();
    } else {
      // Write an empty file as the name_deploy.jar.unstripped when the default output jar is not
      // stripped.
      ruleContext.registerAction(
          FileWriteAction.create(ruleContext, unstrippedDeployJar, "", false));
    }

    JavaRuleOutputJarsProvider ruleOutputJarsProvider = ruleOutputJarsProviderBuilder.build();

    JavaInfo.Builder javaInfoBuilder = JavaInfo.Builder.create();

    NestedSetBuilder<Pair<String, String>> coverageEnvironment = NestedSetBuilder.stableOrder();
    NestedSetBuilder<Artifact> coverageSupportFiles = NestedSetBuilder.stableOrder();
    if (ruleContext.getConfiguration().isCodeCoverageEnabled()) {

      // Create an artifact that contains the runfiles relative paths of the jars on the runtime
      // classpath. Using SourceManifestAction is the only reliable way to match the runfiles
      // creation code.
      Artifact runtimeClasspathArtifact =
          ruleContext.getUniqueDirectoryArtifact(
              "runtime_classpath_for_coverage",
              "runtime_classpath.txt",
              ruleContext.getBinOrGenfilesDirectory());
      ruleContext.registerAction(
          new SourceManifestAction(
              ManifestType.SOURCES_ONLY,
              ruleContext.getActionOwner(),
              runtimeClasspathArtifact,
              new Runfiles.Builder(
                      ruleContext.getWorkspaceName(),
                      ruleContext.getConfiguration().legacyExternalRunfiles())
                  // This matches the code below in collectDefaultRunfiles.
                  .addTransitiveArtifactsWrappedInStableOrder(common.getRuntimeClasspath())
                  .build(),
              null,
              true));
      filesBuilder.add(runtimeClasspathArtifact);

      // Pass the artifact through an environment variable in the coverage environment so it
      // can be read by the coverage collection script.
      coverageEnvironment.add(
          new Pair<>(
              "JAVA_RUNTIME_CLASSPATH_FOR_COVERAGE", runtimeClasspathArtifact.getExecPathString()));
      // Add the file to coverageSupportFiles so it ends up as an input for the test action
      // when coverage is enabled.
      coverageSupportFiles.add(runtimeClasspathArtifact);

      // Make single jar reachable from the coverage environment because it needs to be executed
      // by the coverage collection script.
      Artifact singleJar = JavaToolchainProvider.from(ruleContext).getSingleJar();
      coverageEnvironment.add(new Pair<>("SINGLE_JAR_TOOL", singleJar.getExecPathString()));
      coverageSupportFiles.add(singleJar);
    }

    common.addTransitiveInfoProviders(
        builder,
        javaInfoBuilder,
        filesToBuild,
        classJar,
        coverageEnvironment.build(),
        coverageSupportFiles.build());
    common.addGenJarsProvider(builder, javaInfoBuilder, outputs.genClass(), outputs.genSource());

    // This rule specifically _won't_ build deploy_env, so we selectively propagate validations to
    // filter out deploy_env's if there are any (and otherwise rely on automatic validation
    // propagation). Note that any validations not propagated here will still be built if and when
    // deploy_env is built.
    if (ruleContext.getRule().isAttrDefined("deploy_env", BuildType.LABEL_LIST)) {
      NestedSetBuilder<Artifact> excluded = NestedSetBuilder.stableOrder();
      for (OutputGroupInfo outputGroup :
          ruleContext.getPrerequisites("deploy_env", OutputGroupInfo.STARLARK_CONSTRUCTOR)) {
        NestedSet<Artifact> toExclude = outputGroup.getOutputGroup(OutputGroupInfo.VALIDATION);
        if (!toExclude.isEmpty()) {
          excluded.addTransitive(toExclude);
        }
      }
      if (!excluded.isEmpty()) {
        NestedSetBuilder<Artifact> validations = NestedSetBuilder.stableOrder();
        RuleConfiguredTargetBuilder.collectTransitiveValidationOutputGroups(
            ruleContext,
            attributeName -> !"deploy_env".equals(attributeName),
            validations::addTransitive);

        // Likely, deploy_env will overlap with deps/runtime_deps. Unless we're building an
        // executable (which is rare and somewhat questionable when deploy_env is specified), we can
        // exclude validations from deploy_env entirely from this rule, since this rule specifically
        // never builds the referenced code.
        if (createExecutable) {
          // Executable classpath isn't affected by deploy_env, so build all collected validations.
          builder.addOutputGroup(OutputGroupInfo.VALIDATION_TRANSITIVE, validations.build());
        } else {
          // Filter validations similar to JavaTargetAttributes.getRuntimeClassPathForArchive().
          builder.addOutputGroup(
              OutputGroupInfo.VALIDATION_TRANSITIVE,
              NestedSetBuilder.wrap(
                  Order.STABLE_ORDER,
                  Iterables.filter(
                      validations.build().toList(),
                      Predicates.not(Predicates.in(excluded.build().toSet())))));
        }
      }
    }

    Artifact validation =
        AndroidLintActionBuilder.create(
            ruleContext,
            javaConfig,
            attributes,
            helper.getBootclasspathOrDefault(),
            common,
            semantics,
            outputs);
    if (validation != null) {
      builder.addOutputGroup(
          OutputGroupInfo.VALIDATION, NestedSetBuilder.create(STABLE_ORDER, validation));
    }

    // Support test execution on darwin.
    if (ApplePlatform.isApplePlatform(ruleContext.getConfiguration().getCpu())
        && TargetUtils.isTestRule(ruleContext.getRule())) {
      builder.addNativeDeclaredProvider(
          new ExecutionInfo(ImmutableMap.of(ExecutionRequirements.REQUIRES_DARWIN, "")));
    }

    JavaInfo javaInfo =
        javaInfoBuilder
            .addProvider(JavaSourceJarsProvider.class, sourceJarsProvider)
            .addProvider(JavaRuleOutputJarsProvider.class, ruleOutputJarsProvider)
            .build();

    return builder
        .setFilesToBuild(filesToBuild)
        .addNativeDeclaredProvider(javaInfo)
        .add(RunfilesProvider.class, runfilesProvider)
        // The executable to run (below) may be different from the executable for runfiles (the one
        // we create the runfiles support object with). On Linux they are the same (it's the same
        // shell script), on Windows they are different (the executable to run is a batch file, the
        // executable for runfiles is the shell script).
        .setRunfilesSupport(runfilesSupport, executableToRun)
        // Add the native libraries as test action tools. Useful for the persistent test runner
        // to include them in the worker's key and re-build a worker if the native dependencies
        // have changed.
        .addTestActionTools(nativeLibraries)
        .addFilesToRun(extraFilesToRunBuilder.build())
        .add(
            JavaRuntimeClasspathProvider.class,
            new JavaRuntimeClasspathProvider(common.getRuntimeClasspath()))
        .addOutputGroup(JavaSemantics.SOURCE_JARS_OUTPUT_GROUP, transitiveSourceJars)
        .addOutputGroup(
            JavaSemantics.DIRECT_SOURCE_JARS_OUTPUT_GROUP,
            NestedSetBuilder.wrap(Order.STABLE_ORDER, sourceJarsProvider.getSourceJars()))
        .build();
  }

  @Nullable
  private static Artifact createSharedArchive(
      RuleContext ruleContext,
      JavaCompilationArtifacts javaArtifacts,
      JavaTargetAttributes attributes)
      throws InterruptedException {
    if (!ruleContext.getRule().isAttrDefined("classlist", BuildType.LABEL)) {
      return null;
    }
    Artifact classlist = ruleContext.getPrerequisiteArtifact("classlist");
    if (classlist == null) {
      return null;
    }
    NestedSet<Artifact> classpath =
        NestedSetBuilder.<Artifact>stableOrder()
            .addAll(javaArtifacts.getRuntimeJars())
            .addTransitive(attributes.getRuntimeClassPathForArchive())
            .build();
    Artifact jsa = ruleContext.getImplicitOutputArtifact(JavaSemantics.SHARED_ARCHIVE_ARTIFACT);
    Artifact merged =
        ruleContext.getDerivedArtifact(
            jsa.getOutputDirRelativePath(ruleContext.getConfiguration().isSiblingRepositoryLayout())
                .replaceName(
                    FileSystemUtils.removeExtension(jsa.getRootRelativePath().getBaseName())
                        + "-merged.jar"),
            jsa.getRoot());
    SingleJarActionBuilder.createSingleJarAction(ruleContext, classpath, merged);
    JavaRuntimeInfo javaRuntime = JavaRuntimeInfo.from(ruleContext);
    Artifact configFile = ruleContext.getPrerequisiteArtifact("cds_config_file");

    CustomCommandLine.Builder commandLine =
        CustomCommandLine.builder()
            .add("-Xshare:dump")
            .addFormatted("-XX:SharedArchiveFile=%s", jsa.getExecPath())
            .addFormatted("-XX:SharedClassListFile=%s", classlist.getExecPath());
    if (configFile != null) {
      commandLine.addFormatted("-XX:SharedArchiveConfigFile=%s", configFile.getExecPath());
    }
    commandLine.add("-cp").addExecPath(merged);
    SpawnAction.Builder spawnAction = new SpawnAction.Builder();
    if (ruleContext.getRule().isAttrDefined("jvm_flags_for_cds_image_creation", Type.STRING_LIST)) {
      commandLine.addAll(
          ruleContext
              .getExpander()
              .withDataExecLocations()
              .list("jvm_flags_for_cds_image_creation"));
      spawnAction.addTransitiveInputs(PrerequisiteArtifacts.nestedSet(ruleContext, "data"));
    }
    spawnAction
        .setExecutable(javaRuntime.javaBinaryExecPathFragment())
        .addCommandLine(commandLine.build())
        .setMnemonic("JavaJSA")
        .setProgressMessage("Dumping Java Shared Archive %s", jsa.prettyPrint())
        .addOutput(jsa)
        .addInput(classlist)
        .addInput(merged)
        .addTransitiveInputs(javaRuntime.javaBaseInputs());
    if (configFile != null) {
      spawnAction.addInput(configFile);
    }
    ruleContext.registerAction(spawnAction.build(ruleContext));
    return jsa;
  }

  // Create the deploy jar and make it dependent on the runfiles middleman if an executable is
  // created. Do not add the deploy jar to files to build, so we will only build it when it gets
  // requested.
  private static ImmutableList<String> getDeployManifestLines(
      RuleContext ruleContext, String originalMainClass) {
    ImmutableList.Builder<String> builder =
        ImmutableList.<String>builder()
            .addAll(ruleContext.attributes().get("deploy_manifest_lines", Type.STRING_LIST));
    if (ruleContext.getConfiguration().isCodeCoverageEnabled()) {
      builder.add("Coverage-Main-Class: " + originalMainClass);
    }
    return builder.build();
  }

  /** Add Java8 timezone resource jar to java binary, if specified in tool chain. */
  private static void addTimezoneResourceForJavaBinaries(
      RuleContext ruleContext, JavaTargetAttributes.Builder attributesBuilder) {
    JavaToolchainProvider toolchainProvider = JavaToolchainProvider.from(ruleContext);
    if (toolchainProvider.getTimezoneData() != null) {
      attributesBuilder.addResourceJars(
          NestedSetBuilder.create(Order.STABLE_ORDER, toolchainProvider.getTimezoneData()));
    }
  }

  private void collectDefaultRunfiles(
      Runfiles.Builder builder,
      RuleContext ruleContext,
      JavaCommon common,
      JavaCompilationArtifacts javaArtifacts,
      NestedSet<Artifact> filesToBuild,
      Artifact launcher,
      NestedSet<Artifact> dynamicRuntimeActionInputs) {
    builder.addTransitiveArtifactsWrappedInStableOrder(filesToBuild);
    builder.addArtifacts(javaArtifacts.getRuntimeJars());
    if (launcher != null) {
      final TransitiveInfoCollection defaultLauncher =
          JavaHelper.launcherForTarget(semantics, ruleContext);
      final Artifact defaultLauncherArtifact =
          JavaHelper.launcherArtifactForTarget(semantics, ruleContext);
      if (!defaultLauncherArtifact.equals(launcher)) {
        builder.addArtifact(launcher);

        // N.B. The "default launcher" referred to here is the launcher target specified through
        // an attribute or flag. We wish to retain the runfiles of the default launcher, *except*
        // for the original cc_binary artifact, because we've swapped it out with our custom
        // launcher. Hence, instead of calling builder.addTarget(), or adding an odd method
        // to Runfiles.Builder, we "unravel" the call and manually add things to the builder.
        // Because the NestedSet representing each target's launcher runfiles is re-built here,
        // we may see increased memory consumption for representing the target's runfiles.
        Runfiles runfiles =
            defaultLauncher.getProvider(RunfilesProvider.class).getDefaultRunfiles();
        NestedSetBuilder<Artifact> unconditionalArtifacts = NestedSetBuilder.compileOrder();
        for (Artifact a : runfiles.getArtifacts().toList()) {
          if (!a.equals(defaultLauncherArtifact)) {
            unconditionalArtifacts.add(a);
          }
        }
        builder.addTransitiveArtifacts(unconditionalArtifacts.build());
        builder.addSymlinks(runfiles.getSymlinks());
        builder.addRootSymlinks(runfiles.getRootSymlinks());
      } else {
        builder.addTarget(
            defaultLauncher,
            RunfilesProvider.DEFAULT_RUNFILES,
            ruleContext.getConfiguration().alwaysIncludeFilesToBuildInData());
      }
    }

    semantics.addRunfilesForBinary(ruleContext, launcher, builder);
    builder.addRunfiles(ruleContext, RunfilesProvider.DEFAULT_RUNFILES);

    List<? extends TransitiveInfoCollection> runtimeDeps =
        ruleContext.getPrerequisites("runtime_deps");
    builder.addTargets(
        runtimeDeps,
        RunfilesProvider.DEFAULT_RUNFILES,
        ruleContext.getConfiguration().alwaysIncludeFilesToBuildInData());

    builder.addTransitiveArtifactsWrappedInStableOrder(common.getRuntimeClasspath());

    // Add the JDK files if it comes from the source repository (see java_stub_template.txt).
    JavaRuntimeInfo javaRuntime = JavaRuntimeInfo.from(ruleContext);
    if (javaRuntime != null) {
      builder.addTransitiveArtifacts(javaRuntime.javaBaseInputs());

      if (!javaRuntime.javaHomePathFragment().isAbsolute()) {
        // Add symlinks to the C++ runtime libraries under a path that can be built
        // into the Java binary without having to embed the crosstool, gcc, and grte
        // version information contained within the libraries' package paths.
        for (Artifact lib : dynamicRuntimeActionInputs.toList()) {
          PathFragment path = CPP_RUNTIMES.getRelative(lib.getExecPath().getBaseName());
          builder.addSymlink(path, lib);
        }
      }
    }
  }

  private static boolean isJavaTestRule(RuleContext ruleContext) {
    return ruleContext.getRule().getRuleClass().endsWith("_test");
  }
}
