# 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,
        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.
""",
)
