# Copyright 2026 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.
"""Definition of the java_single_jar rule."""

load("//java/common:java_common.bzl", "java_common")
load("//java/common:java_info.bzl", "JavaInfo")
load("//java/common:java_semantics.bzl", "semantics")
load("//java/common/rules/impl:java_helper.bzl", "helper")

# copybara: default visibility

def _single_jar_inputs(deps, deploy_env):
    transitive_inputs = []
    for dep in deps:
        if JavaInfo in dep:
            info = dep[JavaInfo]
            transitive_inputs.append(info.transitive_runtime_jars)
            if hasattr(info, "compilation_info"):
                compilation_info = info.compilation_info
                if hasattr(compilation_info, "runtime_classpath"):
                    transitive_inputs.append(compilation_info.runtime_classpath)
        else:
            files = []
            for f in dep[DefaultInfo].files.to_list():
                if not f.extension == "jar":
                    fail("unexpected file type in java_single_jar.deps: %s" % f.path)
                files.append(f)
            transitive_inputs.append(depset(files))
    all_inputs = depset(transitive = transitive_inputs)
    inputs = all_inputs

    if hasattr(java_common, "JavaRuntimeClasspathInfo"):
        deploy_env_jars = depset(transitive = [
            dep[java_common.JavaRuntimeClasspathInfo].runtime_classpath
            for dep in deploy_env
        ])
        excluded_jars = {jar: None for jar in deploy_env_jars.to_list()}
        if excluded_jars:
            inputs = depset([jar for jar in inputs.to_list() if jar not in excluded_jars])
    return inputs, all_inputs

def _bazel_java_single_jar_impl(ctx):
    inputs, all_inputs = _single_jar_inputs(ctx.attr.deps, ctx.attr.deploy_env)

    args = ctx.actions.args()
    args.add_all("--sources", inputs)
    args.use_param_file("@%s")
    args.set_param_file_format("shell")
    args.add_all("--deploy_manifest_lines", ctx.attr.deploy_manifest_lines)
    args.add("--output", ctx.outputs.output)
    args.add("--normalize")

    # Deal with limitation of singlejar flags: tool's default behavior is
    # "no", but you get that behavior only by absence of compression flags.
    if ctx.attr.compress == "preserve":
        args.add("--dont_change_compression")
    elif ctx.attr.compress == "yes":
        args.add("--compression")
    elif ctx.attr.compress == "no":
        pass
    else:
        fail("\"compress\" attribute (%s) must be: yes, no, preserve." % ctx.attr.compress)

    if ctx.attr.exclude_build_data and ctx.attr.stamp == 1:
        fail("Enabling stamping has not effect with exclude_build_data enabled")

    build_info_files = []
    if ctx.attr.exclude_build_data:
        args.add("--exclude_build_data")
    else:
        build_info_files = helper.get_build_info(ctx, ctx.attr.stamp)
        args.add_all(build_info_files, before_each = "--build_info_file")
    if ctx.attr.multi_release:
        args.add("--multi_release")

    if ctx.attr.exclude_pattern:
        args.add("--exclude_pattern", ctx.attr.exclude_pattern)

    ctx.actions.run(
        inputs = depset(build_info_files, transitive = [inputs]),
        outputs = [ctx.outputs.output],
        arguments = [args],
        progress_message = "Merging into %s" % ctx.outputs.output.short_path,
        mnemonic = "JavaSingleJar",
        executable = ctx.executable._singlejar,
        execution_requirements = {
            "supports-path-mapping": "1",
        },
        use_default_shell_env = True,
    )

    files = depset([ctx.outputs.output])
    providers = [DefaultInfo(
        files = files,
        runfiles = ctx.runfiles(transitive_files = files),
    )]
    if hasattr(java_common, "JavaRuntimeClasspathInfo"):
        providers.append(java_common.JavaRuntimeClasspathInfo(runtime_classpath = all_inputs))
    return providers

bazel_java_single_jar = rule(
    attrs = {
        "deps": attr.label_list(
            allow_files = True,
            doc = """
                The Java targets (including java_import and java_library) to collect
                transitive dependencies from. Runtime dependencies are collected via
                deps, exports, and runtime_deps. Resources are also collected.
                Native cc_library or java_wrap_cc dependencies are not.""",
        ),
        "deploy_manifest_lines": attr.string_list(doc = """
          A list of lines to add to the <code>META-INF/manifest.mf</code> file."""),
        "deploy_env": attr.label_list(
            providers = [java_common.JavaRuntimeClasspathInfo] if hasattr(java_common, "JavaRuntimeClasspathInfo") else [],
            allow_files = False,
            doc = """
            A list of `java_binary` or `java_single_jar` targets which represent
            the deployment environment for this binary.

            Set this attribute when building a plugin which will be loaded by another
            `java_binary`.

            `deploy_env` dependencies are excluded from the jar built by this rule.""",
        ),
        "compress": attr.string(default = "preserve", doc = """
            Whether to always deflate ("yes"), always store ("no"), or pass
            through unmodified ("preserve"). The default is "preserve", and is the
            most efficient option -- no extra work is done to inflate or deflate."""),
        "exclude_build_data": attr.bool(default = True, doc = """
            Whether to omit the build-data.properties file generated
            by default."""),
        "multi_release": attr.bool(default = True, doc = """Whether to enable Multi-Release output jars."""),
        "exclude_pattern": attr.string(default = "", doc = """
            A regex pattern of files to exclude from the jar.
        """),
        "_singlejar": attr.label(
            default = Label("//toolchains:singlejar"),
            cfg = "exec",
            allow_single_file = True,
            executable = True,
        ),
        "output": attr.output(),
        "stamp": attr.int(
            doc = """
              Whether to embed extra Bazel build information into the build_data.properties file:
                * `stamp = 1`: Always embed Bazel build information, even in `--nostamp` builds.
                * `stamp = 0`: Embed Bazel build information with constant values, even in `--stamp` builds.
                * `stamp = -1`: Embedding of Bazel build information is controlled by the `--[no]stamp` flag.

                Note: whether the output contains the build_data.properties file is controlled
                 by the `exclude_build_data` attribute.
                """,
            default = 0,
            values = [-1, 0, 1],
        ),
        "_build_info_translator": attr.label(default = semantics.BUILD_INFO_TRANSLATOR_LABEL),
    },
    implementation = _bazel_java_single_jar_impl,
    doc = """
Collects Java dependencies and jar files into a single jar

`java_single_jar` collects Java dependencies and jar files into a single jar.
This is similar to java_binary with everything related to executables disabled,
and provides an alternative to the java_binary "deploy jar hack".

## Example

```skylark
load("//tools/build_defs/java_single_jar:java_single_jar.bzl", "java_single_jar")

java_single_jar(
    name = "my_single_jar",
    deps = [
        "//java/com/google/foo",
        "//java/com/google/bar",
    ],
)
```

Outputs:
  {name}.jar: A single jar containing all of the inputs.
""",
)
