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

import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.packages.BuildType.TRISTATE;
import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fromFunctions;
import static com.google.devtools.build.lib.packages.Type.BOOLEAN;
import static com.google.devtools.build.lib.packages.Type.STRING;
import static com.google.devtools.build.lib.packages.Type.STRING_LIST;
import static com.google.devtools.build.lib.rules.java.JavaRuleClasses.CONTAINS_JAVA_PROVIDER;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.analysis.config.HostTransition;
import com.google.devtools.build.lib.bazel.rules.cpp.BazelCppRuleClasses.CcToolchainRequiringRule;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction;
import com.google.devtools.build.lib.packages.PredicateWithMessage;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
import com.google.devtools.build.lib.packages.RuleClass.PackageNameConstraint;
import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
import com.google.devtools.build.lib.packages.TriState;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.rules.cpp.CcBinary.CcLauncherInfo;
import com.google.devtools.build.lib.rules.cpp.CcInfo;
import com.google.devtools.build.lib.rules.java.JavaInfo;
import com.google.devtools.build.lib.rules.java.JavaRuleClasses.IjarBaseRule;
import com.google.devtools.build.lib.rules.java.JavaRuleClasses.JavaRuntimeBaseRule;
import com.google.devtools.build.lib.rules.java.JavaSemantics;
import com.google.devtools.build.lib.util.FileTypeSet;

/**
 * Rule class definitions for Java rules.
 */
public class BazelJavaRuleClasses {

  public static final PredicateWithMessage<Rule> JAVA_PACKAGE_NAMES = new PackageNameConstraint(
      PackageNameConstraint.ANY_SEGMENT, "java", "javatests");

  protected static final String JUNIT_TESTRUNNER = "//tools/jdk:TestRunner";

  public static final ImplicitOutputsFunction JAVA_BINARY_IMPLICIT_OUTPUTS =
      fromFunctions(
          JavaSemantics.JAVA_BINARY_CLASS_JAR,
          JavaSemantics.JAVA_BINARY_SOURCE_JAR,
          JavaSemantics.JAVA_BINARY_DEPLOY_JAR,
          JavaSemantics.JAVA_BINARY_DEPLOY_SOURCE_JAR);

  static final ImplicitOutputsFunction JAVA_LIBRARY_IMPLICIT_OUTPUTS =
      fromFunctions(
          JavaSemantics.JAVA_LIBRARY_CLASS_JAR,
          JavaSemantics.JAVA_LIBRARY_SOURCE_JAR);

  public static final ImmutableList<SkylarkProviderIdentifier> CONTAINS_CC_LINK_PARAMS =
      ImmutableList.of(SkylarkProviderIdentifier.forKey(CcInfo.PROVIDER.getKey()));

  /**
   * Meant to be the value of {@code mandatoryProvidersLists} in order for the rule to provide only
   * a {@link JavaInfo} through an attribute.
   */
  public static final ImmutableList<ImmutableList<SkylarkProviderIdentifier>>
      MANDATORY_JAVA_PROVIDER_ONLY = ImmutableList.of(CONTAINS_JAVA_PROVIDER);

  /**
   * Common attributes for Java rules.
   */
  public static final class JavaBaseRule implements RuleDefinition {
    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder.build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$java_base_rule")
          .type(RuleClassType.ABSTRACT)
          .ancestors(IjarBaseRule.class, JavaRuntimeBaseRule.class)
          .build();
    }
  }

  static final ImmutableSet<String> ALLOWED_RULES_IN_DEPS =
      ImmutableSet.of(
          "cc_binary", // NB: linkshared=1
          "cc_library",
          "genrule",
          "genproto", // TODO(bazel-team): we should filter using providers instead (skylark rule).
          "java_import",
          "java_library",
          "java_proto_library",
          "java_lite_proto_library",
          "proto_library",
          "sh_binary",
          "sh_library");

  /**
   * Common attributes for Java rules.
   */
  public static final class JavaRule implements RuleDefinition {
    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          /* <!-- #BLAZE_RULE($java_rule).ATTRIBUTE(deps) -->
          The list of other libraries to be linked in to the target.
          See general comments about <code>deps</code> at
          <a href="common-definitions.html#common-attributes">Attributes common to all build rules
          </a>.
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .override(
              builder
                  .copy("deps")
                  .allowedFileTypes(JavaSemantics.JAR)
                  .allowedRuleClasses(ALLOWED_RULES_IN_DEPS)
                  .mandatoryProvidersList(
                      ImmutableList.of(CONTAINS_CC_LINK_PARAMS, CONTAINS_JAVA_PROVIDER))
                  .skipAnalysisTimeFileTypeCheck())
          /* <!-- #BLAZE_RULE($java_rule).ATTRIBUTE(runtime_deps) -->
          Libraries to make available to the final binary or test at runtime only.
          Like ordinary <code>deps</code>, these will appear on the runtime classpath, but unlike
          them, not on the compile-time classpath. Dependencies needed only at runtime should be
          listed here. Dependency-analysis tools should ignore targets that appear in both
          <code>runtime_deps</code> and <code>deps</code>.
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(
              attr("runtime_deps", LABEL_LIST)
                  .allowedFileTypes(JavaSemantics.JAR)
                  .allowedRuleClasses(ALLOWED_RULES_IN_DEPS)
                  .mandatoryProvidersList(MANDATORY_JAVA_PROVIDER_ONLY)
                  .skipAnalysisTimeFileTypeCheck())

          /* <!-- #BLAZE_RULE($java_rule).ATTRIBUTE(srcs) -->
          The list of source files that are processed to create the target.
          This attribute is almost always required; see exceptions below.
          <p>
            Source files of type <code>.java</code> are compiled. In case of generated
            <code>.java</code> files it is generally advisable to put the generating rule's name
            here instead of the name of the file itself. This not only improves readability but
            makes the rule more resilient to future changes: if the generating rule generates
            different files in the future, you only need to fix one place: the <code>outs</code> of
            the generating rule. You should not list the generating rule in <code>deps</code>
            because it is a no-op.
          </p>
          <p>
            Source files of type <code>.srcjar</code> are unpacked and compiled. (This is useful if
            you need to generate a set of <code>.java</code> files with a genrule.)
          </p>
          <p>
            Rules: if the rule (typically <code>genrule</code> or <code>filegroup</code>) generates
            any of the files listed above, they will be used the same way as described for source
            files.
          </p>

          <p>
            This argument is almost always required, except if a
            <a href="#java_binary.main_class"><code>main_class</code></a> attribute specifies a
            class on the runtime classpath or you specify the <code>runtime_deps</code> argument.
          </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(
              attr("srcs", LABEL_LIST)
                  .orderIndependent()
                  .direct_compile_time_input()
                  .allowedFileTypes(
                      JavaSemantics.JAVA_SOURCE,
                      JavaSemantics.SOURCE_JAR,
                      JavaSemantics.PROPERTIES))
          /* <!-- #BLAZE_RULE($java_rule).ATTRIBUTE(resources) -->
          A list of data files to include in a Java jar.
          <p>
            If resources are specified, they will be bundled in the jar along with the usual
            <code>.class</code> files produced by compilation. The location of the resources inside
            of the jar file is determined by the project structure. Bazel first looks for Maven's
            <a href="https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html">standard directory layout</a>,
            (a "src" directory followed by a "resources" directory grandchild). If that is not
            found, Bazel then looks for the topmost directory named "java" or "javatests" (so, for
            example, if a resource is at <code>&lt;workspace root&gt;/x/java/y/java/z</code>, the
            path of the resource will be <code>y/java/z</code>. This heuristic cannot be overridden.
          </p>

          <p>
            Resources may be source files or generated files.
          </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(
              attr("resources", LABEL_LIST)
                  .orderIndependent()
                  .allowedFileTypes(FileTypeSet.ANY_FILE)
                  .dontCheckConstraints())
          /* <!-- #BLAZE_RULE($java_rule).ATTRIBUTE(resource_strip_prefix) -->
          The path prefix to strip from Java resources.
          <p>
            If specified, this path prefix is stripped from every file in the <code>resources</code>
            attribute. It is an error for a resource file not to be under this directory. If not
            specified (the default), the path of resource file is determined according to the same
            logic as the Java package of source files. For example, a source file at
            <code>stuff/java/foo/bar/a.txt</code> will be located at <code>foo/bar/a.txt</code>.
          </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(attr("resource_strip_prefix", STRING))
          /* <!-- #BLAZE_RULE($java_rule).ATTRIBUTE(resource_jars) -->
          Set of archives containing Java resources.
          <p>
            If specified, the contents of these jars are merged into the output jar.
          </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(
              attr("resource_jars", LABEL_LIST)
                  .orderIndependent()
                  .allowedFileTypes(JavaSemantics.JAR))
          /* <!-- #BLAZE_RULE($java_rule).ATTRIBUTE(plugins) -->
          Java compiler plugins to run at compile-time.
          Every <code>java_plugin</code> specified in this attribute will be run whenever this rule
          is built. A library may also inherit plugins from dependencies that use
          <code><a href="#java_library.exported_plugins">exported_plugins</a></code>. Resources
          generated by the plugin will be included in the resulting jar of this rule.
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(
              attr("plugins", LABEL_LIST)
                  .cfg(HostTransition.createFactory())
                  .allowedRuleClasses("java_plugin")
                  .legacyAllowAnyFileType())
          .add(
              attr(":java_plugins", LABEL_LIST)
                  .cfg(HostTransition.createFactory())
                  .allowedRuleClasses("java_plugin")
                  .silentRuleClassFilter()
                  .value(JavaSemantics.JAVA_PLUGINS))
          /* <!-- #BLAZE_RULE($java_rule).ATTRIBUTE(javacopts) -->
          Extra compiler options for this library.
          Subject to <a href="make-variables.html">"Make variable"</a> substitution and
          <a href="common-definitions.html#sh-tokenization">Bourne shell tokenization</a>.
          <p>These compiler options are passed to javac after the global compiler options.</p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(attr("javacopts", STRING_LIST))
          .build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$java_rule")
          .type(RuleClassType.ABSTRACT)
          .ancestors(BaseRuleClasses.RuleBase.class, JavaBaseRule.class)
          .build();
    }
  }

  /**
   * Base class for rule definitions producing Java binaries.
   */
  public static final class BaseJavaBinaryRule implements RuleDefinition {

    @Override
    public RuleClass build(RuleClass.Builder builder, final RuleDefinitionEnvironment env) {
      return builder
          /* <!-- #BLAZE_RULE($base_java_binary).ATTRIBUTE(classpath_resources) -->
          <em class="harmful">DO NOT USE THIS OPTION UNLESS THERE IS NO OTHER WAY)</em>
          <p>
            A list of resources that must be located at the root of the java tree. This attribute's
            only purpose is to support third-party libraries that require that their resources be
            found on the classpath as exactly <code>"myconfig.xml"</code>. It is only allowed on
            binaries and not libraries, due to the danger of namespace conflicts.
          </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(attr("classpath_resources", LABEL_LIST).legacyAllowAnyFileType())
          /* <!-- #BLAZE_RULE($base_java_binary).ATTRIBUTE(jvm_flags) -->
          A list of flags to embed in the wrapper script generated for running this binary.
          Subject to <a href="${link make-variables#location}">$(location)</a> and
          <a href="make-variables.html">"Make variable"</a> substitution, and
          <a href="common-definitions.html#sh-tokenization">Bourne shell tokenization</a>.

          <p>The wrapper script for a Java binary includes a CLASSPATH definition
          (to find all the dependent jars) and invokes the right Java interpreter.
          The command line generated by the wrapper script includes the name of
          the main class followed by a <code>"$@"</code> so you can pass along other
          arguments after the classname.  However, arguments intended for parsing
          by the JVM must be specified <i>before</i> the classname on the command
          line.  The contents of <code>jvm_flags</code> are added to the wrapper
          script before the classname is listed.</p>

          <p>Note that this attribute has <em>no effect</em> on <code>*_deploy.jar</code>
          outputs.</p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(attr("jvm_flags", STRING_LIST))
          /* <!-- #BLAZE_RULE($base_java_binary).ATTRIBUTE(use_testrunner) -->
          Use the test runner (by default
          <code>com.google.testing.junit.runner.BazelTestRunner</code>) class as the
          main entry point for a Java program, and provide the test class
          to the test runner as a value of <code>bazel.test_suite</code>
          system property.

          You can use this to override the default
          behavior, which is to use test runner for
          <code>java_test</code> rules,
          and not use it for <code>java_binary</code> rules.  It is unlikely
          you will want to do this.  One use is for <code>AllTest</code>
          rules that are invoked by another rule (to set up a database
          before running the tests, for example).  The <code>AllTest</code>
          rule must be declared as a <code>java_binary</code>, but should
          still use the test runner as its main entry point.

          The name of a test runner class can be overridden with <code>main_class</code> attribute.
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(attr("use_testrunner", BOOLEAN).value(false))
          /* <!-- #BLAZE_RULE($base_java_binary).ATTRIBUTE(main_class) -->
          Name of class with <code>main()</code> method to use as entry point.
          If a rule uses this option, it does not need a <code>srcs=[...]</code> list.
          Thus, with this attribute one can make an executable from a Java library that already
          contains one or more <code>main()</code> methods.
          <p>
            The value of this attribute is a class name, not a source file. The class must be
            available at runtime: it may be compiled by this rule (from <code>srcs</code>) or
            provided by direct or transitive dependencies (through <code>runtime_deps</code> or
            <code>deps</code>). If the class is unavailable, the binary will fail at runtime; there
            is no build-time check.
          </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(attr("main_class", STRING))
          /* <!-- #BLAZE_RULE($base_java_binary).ATTRIBUTE(create_executable) -->
          Whether the binary is executable. Non-executable binaries collect transitive
          runtime Java dependencies into a deploy jar, but cannot be executed directly.

          No wrapper script is created if this attribute is set. It is an error to set
          this to 0 if the <code>launcher</code> or <code>main_class</code> attributes
          are set.
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(attr("create_executable", BOOLEAN).nonconfigurable("internal").value(true))
          .add(
              attr("$testsupport", LABEL)
                  .value(
                      new Attribute.ComputedDefault("use_testrunner") {
                        @Override
                        public Object getDefault(AttributeMap rule) {
                          return rule.get("use_testrunner", Type.BOOLEAN)
                              ? env.getToolsLabel(JUNIT_TESTRUNNER)
                              : null;
                        }
                      }))
          /* <!-- #BLAZE_RULE($base_java_binary).ATTRIBUTE(deploy_manifest_lines) -->
          A list of lines to add to the <code>META-INF/manifest.mf</code> file generated for the
          <code>*_deploy.jar</code> target. The contents of this attribute are <em>not</em> subject
          to <a href="make-variables.html">"Make variable"</a> substitution.
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(attr("deploy_manifest_lines", STRING_LIST))
          /* <!-- #BLAZE_RULE($base_java_binary).ATTRIBUTE(stamp) -->
          Enable link stamping.
          Whether to encode build information into the binary. Possible values:
          <ul>
            <li><code>stamp = 1</code>: Stamp the build information into the binary. Stamped
              binaries are only rebuilt when their dependencies change. Use this if there are tests
              that depend on the build information.</li>
            <li><code>stamp = 0</code>: Always replace build information by constant values. This
              gives good build result caching.</li>
            <li><code>stamp = -1</code>: Embedding of build information is controlled by the
              <a href="../user-manual.html#flag--stamp">--[no]stamp</a> flag.</li>
          </ul>
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          // TODO(bazel-team): describe how to access this data at runtime
          .add(attr("stamp", TRISTATE).value(TriState.AUTO))
          /* <!-- #BLAZE_RULE($base_java_binary).ATTRIBUTE(launcher) -->
          Specify a binary that will be used to run your Java program instead of the
          normal <code>bin/java</code> program included with the JDK.
          The target must be a <code>cc_binary</code>. Any <code>cc_binary</code> that
          implements the
          <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/invocation.html">
          Java Invocation API</a> can be specified as a value for this attribute.

          <p>By default, Bazel will use the normal JDK launcher (bin/java or java.exe).</p>

          <p>The related <a href="../user-manual.html#flag--java_launcher"><code>
          --java_launcher</code></a> Bazel flag affects only those
          <code>java_binary</code> and <code>java_test</code> targets that have
          <i>not</i> specified a <code>launcher</code> attribute.</p>

          <p>Note that your native (C++, SWIG, JNI) dependencies will be built differently
          depending on whether you are using the JDK launcher or another launcher:</p>

          <ul>
            <li>If you are using the normal JDK launcher (the default), native dependencies are
            built as a shared library named <code>{name}_nativedeps.so</code>, where
            <code>{name}</code> is the <code>name</code> attribute of this java_binary rule.
            Unused code is <em>not</em> removed by the linker in this configuration.</li>

            <li>If you are using any other launcher, native (C++) dependencies are statically
            linked into a binary named <code>{name}_nativedeps</code>, where <code>{name}</code>
            is the <code>name</code> attribute of this java_binary rule. In this case,
            the linker will remove any code it thinks is unused from the resulting binary,
            which means any C++ code accessed only via JNI may not be linked in unless
            that <code>cc_library</code> target specifies <code>alwayslink = 1</code>.</li>
          </ul>

          <p>When using any launcher other than the default JDK launcher, the format
          of the <code>*_deploy.jar</code> output changes. See the main
          <a href="#java_binary">java_binary</a> docs for details.</p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(
              attr("launcher", LABEL)
                  .allowedFileTypes(FileTypeSet.NO_FILE)
                  .mandatoryProviders(
                      SkylarkProviderIdentifier.forKey(CcLauncherInfo.PROVIDER.getKey())))
          .add(attr(":java_launcher", LABEL).value(JavaSemantics.JAVA_LAUNCHER)) // blaze flag
          .add(
              attr("$launcher", LABEL)
                  .cfg(HostTransition.createFactory())
                  .value(env.getToolsLabel("//tools/launcher:launcher")))
          .build();
    }
    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$base_java_binary")
          .type(RuleClassType.ABSTRACT)
          .ancestors(
              JavaRule.class,
              // java_binary and java_test require the crosstool C++ runtime
              // libraries (libstdc++.so, libgcc_s.so).
              // TODO(bazel-team): Add tests for Java+dynamic runtime.
              CcToolchainRequiringRule.class)
          .build();
    }
  }
}
