# 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))
    inputs = depset(transitive = transitive_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

def _bazel_java_single_jar_impl(ctx):
    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("multiline")
    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,
        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 = 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.
""",
)
