java_grpc_library.bzl: workaround strict_deps

This is a sync from our internal copy, so has lots of small changes.
But the most important change is strict_deps issues are worked around
within the rule. This means there should be no longer any reason to
specify more than one dep.

Our Bazel CI is still on Bazel 0.20, so for the moment avoid requiring
Bazel 0.22 by staying on the old 'proto' provider instead of ProtoInfo.

Fixes #5314
diff --git a/BUILD.bazel b/BUILD.bazel
index e4175b0..a1b416e 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -24,3 +24,30 @@
     srcs = ["@com_google_protobuf//:api_proto"],
     deps = [":api_proto_java"],
 )
+
+java_library(
+    name = "java_grpc_library_deps__do_not_reference",
+    visibility = ["//visibility:public"],
+    exports = [
+        "//core",
+        "//protobuf",
+        "//stub",
+        "//stub:javax_annotation",
+        "@com_google_code_findbugs_jsr305//jar",
+        "@com_google_guava_guava//jar",
+        "@com_google_protobuf//:protobuf_java",
+    ],
+)
+
+java_library(
+    name = "java_lite_grpc_library_deps__do_not_reference",
+    visibility = ["//visibility:public"],
+    exports = [
+        "//core",
+        "//protobuf-lite",
+        "//stub",
+        "//stub:javax_annotation",
+        "@com_google_code_findbugs_jsr305//jar",
+        "@com_google_guava_guava//jar",
+    ],
+)
diff --git a/java_grpc_library.bzl b/java_grpc_library.bzl
index 5ea8386..76264a0 100644
--- a/java_grpc_library.bzl
+++ b/java_grpc_library.bzl
@@ -1,60 +1,74 @@
+# "repository" here is for Bazel builds that span multiple WORKSPACES.
 def _path_ignoring_repository(f):
-    if (len(f.owner.workspace_root) == 0):
+    if len(f.owner.workspace_root) == 0:
         return f.short_path
     return f.path[f.path.find(f.owner.workspace_root) + len(f.owner.workspace_root) + 1:]
 
-def _gensource_impl(ctx):
-    if len(ctx.attr.srcs) > 1:
-        fail("Only one src value supported", "srcs")
-    for s in ctx.attr.srcs:
-        if s.label.package != ctx.label.package:
-            print(("in srcs attribute of {0}: Proto source with label {1} should be in " +
-                   "same package as consuming rule").format(ctx.label, s.label))
+def _create_include_path(include):
+    return "-I{0}={1}".format(_path_ignoring_repository(include), include.path)
 
-    # Use .jar since .srcjar makes protoc think output will be a directory
-    srcdotjar = ctx.new_file(ctx.label.name + "_src.jar")
+def _java_rpc_library_impl(ctx):
+    if len(ctx.attr.srcs) != 1:
+        fail("Exactly one src value supported", "srcs")
+    if ctx.attr.srcs[0].label.package != ctx.label.package:
+        print(("in srcs attribute of {0}: Proto source with label {1} should be in " +
+               "same package as consuming rule").format(ctx.label, ctx.attr.srcs[0].label))
 
-    srcs = [f for dep in ctx.attr.srcs for f in dep.proto.direct_sources]
-    includes = [f for dep in ctx.attr.srcs for f in dep.proto.transitive_imports]
-
+    srcs = ctx.attr.srcs[0].proto.direct_sources
+    includes = ctx.attr.srcs[0].proto.transitive_imports
     flavor = ctx.attr.flavor
     if flavor == "normal":
         flavor = ""
+
+    args = ctx.actions.args()
+    args.add(ctx.executable._java_plugin.path, format = "--plugin=protoc-gen-grpc-java=%s")
+    args.add("--grpc-java_out={0}:{1}".format(flavor, ctx.outputs.srcjar.path))
+    args.add_all(includes, map_each = _create_include_path)
+    args.add_all(srcs, map_each = _path_ignoring_repository)
+
     ctx.action(
-        inputs = [ctx.executable._java_plugin] + srcs + includes,
-        outputs = [srcdotjar],
-        executable = ctx.executable._protoc,
-        arguments = [
-                        "--plugin=protoc-gen-grpc-java=" + ctx.executable._java_plugin.path,
-                        "--grpc-java_out={0},enable_deprecated={1}:{2}"
-                            .format(flavor, str(ctx.attr.enable_deprecated).lower(), srcdotjar.path),
-                    ] +
-                    ["-I{0}={1}".format(_path_ignoring_repository(include), include.path) for include in includes] +
-                    [_path_ignoring_repository(src) for src in srcs],
-    )
-    ctx.action(
-        command = "cp $1 $2",
-        inputs = [srcdotjar],
+        inputs = depset([ctx.executable._java_plugin] + srcs, transitive = [includes]),
         outputs = [ctx.outputs.srcjar],
-        arguments = [srcdotjar.path, ctx.outputs.srcjar.path],
+        executable = ctx.executable._protoc,
+        arguments = [args],
     )
 
-_gensource = rule(
+    deps_java_info = java_common.merge([dep[JavaInfo] for dep in ctx.attr.deps])
+
+    java_info = java_common.compile(
+        ctx,
+        java_toolchain = ctx.attr._java_toolchain,
+        host_javabase = ctx.attr._host_javabase,
+        source_jars = [ctx.outputs.srcjar],
+        output = ctx.outputs.jar,
+        deps = [
+            java_common.make_non_strict(deps_java_info),
+            ctx.attr.runtime[JavaInfo],
+        ],
+    )
+    return [java_info]
+
+_java_rpc_library = rule(
     attrs = {
         "srcs": attr.label_list(
             mandatory = True,
             non_empty = True,
             providers = ["proto"],
         ),
+        "deps": attr.label_list(
+            mandatory = True,
+            non_empty = True,
+            providers = [JavaInfo],
+        ),
         "flavor": attr.string(
             values = [
                 "normal",
-                "lite",  # Not currently supported
+                "lite",
             ],
             default = "normal",
         ),
-        "enable_deprecated": attr.bool(
-            default = False,
+        "runtime": attr.label(
+            mandatory = True,
         ),
         "_protoc": attr.label(
             default = Label("@com_google_protobuf//:protoc"),
@@ -66,11 +80,21 @@
             executable = True,
             cfg = "host",
         ),
+        "_java_toolchain": attr.label(
+            default = Label("@bazel_tools//tools/jdk:current_java_toolchain"),
+        ),
+        "_host_javabase": attr.label(
+            cfg = "host",
+            default = Label("@bazel_tools//tools/jdk:current_host_java_runtime"),
+        ),
     },
+    fragments = ["java"],
     outputs = {
-        "srcjar": "%{name}.srcjar",
+        "jar": "lib%{name}.jar",
+        "srcjar": "lib%{name}-src.jar",
     },
-    implementation = _gensource_impl,
+    provides = [JavaInfo],
+    implementation = _java_rpc_library_impl,
 )
 
 def java_grpc_library(
@@ -78,15 +102,17 @@
         srcs,
         deps,
         flavor = None,
-        enable_deprecated = None,
+        tags = None,
         visibility = None,
         **kwargs):
     """Generates and compiles gRPC Java sources for services defined in a proto
-    file. This rule is compatible with java_proto_library and java_lite_proto_library.
+    file. This rule is compatible with proto_library with java_api_version,
+    java_proto_library, and java_lite_proto_library.
 
     Do note that this rule only scans through the proto file for RPC services. It
     does not generate Java classes for proto messages. You will need a separate
-    java_proto_library or java_lite_proto_library rule.
+    proto_library with java_api_version, java_proto_library, or
+    java_lite_proto_library rule.
 
     Args:
       name: (str) A unique name for this rule. Required.
@@ -99,44 +125,42 @@
       visibility: (list) the visibility list
       **kwargs: Passed through to generated targets
     """
-    if flavor == None:
-        flavor = "normal"
 
     if len(deps) > 1:
         print("Multiple values in 'deps' is deprecated in " + name)
 
-    gensource_name = name + "__do_not_reference__srcjar"
-    _gensource(
-        name = gensource_name,
-        srcs = srcs,
-        flavor = flavor,
-        enable_deprecated = enable_deprecated,
-        visibility = ["//visibility:private"],
-        **kwargs
-    )
-
-    added_deps = [
-        "@io_grpc_grpc_java//core",
-        "@io_grpc_grpc_java//stub",
-        "@io_grpc_grpc_java//stub:javax_annotation",
-        "@com_google_guava_guava//jar",
-    ]
-    if flavor == "normal":
-        added_deps += [
-            "@com_google_protobuf//:protobuf_java",
-            "@io_grpc_grpc_java//protobuf",
-        ]
-    elif flavor == "lite":
-        added_deps += ["@io_grpc_grpc_java//protobuf-lite"]
+    if flavor == "lite":
+        inner_name = name + "__do_not_reference"
+        inner_visibility = ["//visibility:private"]
+        inner_tags = ["avoid_dep"]
+        runtime = "@io_grpc_grpc_java//:java_lite_grpc_library_deps__do_not_reference"
     else:
-        fail("Unknown flavor type", "flavor")
+        inner_name = name
+        inner_visibility = visibility
+        inner_tags = tags
+        runtime = "@io_grpc_grpc_java//:java_grpc_library_deps__do_not_reference"
 
-    native.java_library(
-        name = name,
-        srcs = [gensource_name],
-        visibility = visibility,
-        deps = [
-            "@com_google_code_findbugs_jsr305//jar",
-        ] + deps + added_deps,
+    _java_rpc_library(
+        name = inner_name,
+        srcs = srcs,
+        deps = deps,
+        flavor = flavor,
+        runtime = runtime,
+        visibility = inner_visibility,
+        tags = inner_tags,
         **kwargs
     )
+
+    if flavor == "lite":
+        # Use java_import to work around error with android_binary:
+        # Dependencies on .jar artifacts are not allowed in Android binaries,
+        # please use a java_import to depend on...
+        native.java_import(
+            name = name,
+            deps = deps + [runtime],
+            jars = [":lib{}.jar".format(inner_name)],
+            srcjar = ":lib{}-src.jar".format(inner_name),
+            visibility = visibility,
+            tags = tags,
+            **kwargs
+        )