Use rules_jvm_external to fetch jars dependencies (part 1)

Closes #17142.

Signed-off-by: Yun Peng <pcloudy@google.com>
diff --git a/third_party/rules_jvm_external.patch b/third_party/rules_jvm_external.patch
new file mode 100644
index 0000000..8b4ccfe
--- /dev/null
+++ b/third_party/rules_jvm_external.patch
@@ -0,0 +1,127 @@
+commit 569fe4da2530d7b1356265d7cc62ca74f93ec7e5
+Author: Yun Peng <pcloudy@google.com>
+Date:   Thu Jan 5 16:37:29 2023 +0800
+
+    Add targets to make it easier to vendor the `@maven` repository
+    
+    This change is required to support Bazel's offline bootstrap build.
+    More context in https://github.com/bazelbuild/bazel/pull/17112
+    
+    Instead of checking in jar files in Bazel's source tree, Bazel wants to use rules_jvm_external
+    to fetch jars dependencies. However, to support Bazel's bootstrap build,
+    we need to patch rules_jvm_external for vendoring the @maven repository.
+    
+    - Generate a BUILD.vendor file to be used in the vendored `@maven` repository.
+      Added a jvm_import and a filegroup rule for each downloaded jar artifact.
+      The filegroup rule is required by the bootstrap Java toolchain used in Bazel's
+      bootstrap build. The bootstrap Java toolchain cannot depend on a jvm_import target.
+      Because the jvm_import rule depends on a java_binary tool "AddJarManifestEntry",
+      which requires a Java toolchain. Depending on the jar via a filegroup rule helps
+      avoid this cyclic dependency.
+    - Added a filegroup rule to collect all sources needed for vendoring `@maven`,
+      including BUILD.vendor, WORKSPACE and jar files.
+
+diff --git a/coursier.bzl b/coursier.bzl
+index 901a6b0..d763f01 100644
+--- a/coursier.bzl
++++ b/coursier.bzl
+@@ -47,6 +47,12 @@ bzl_library(
+ )
+ """
+ 
++_BUILD_VENDOR = """
++load("@rules_jvm_external//private/rules:jvm_import.bzl", "jvm_import")
++
++{vendor_targets}
++"""
++
+ DEFAULT_AAR_IMPORT_LABEL = "@build_bazel_rules_android//android:rules.bzl"
+ 
+ _AAR_IMPORT_STATEMENT = """\
+@@ -577,7 +583,7 @@ def _pinned_coursier_fetch_impl(repository_ctx):
+     )
+ 
+     repository_ctx.report_progress("Generating BUILD targets..")
+-    (generated_imports, jar_versionless_target_labels) = parser.generate_imports(
++    (generated_imports, jar_versionless_target_labels, generated_vendor_targets) = parser.generate_imports(
+         repository_ctx = repository_ctx,
+         dep_tree = dep_tree,
+         explicit_artifacts = {
+@@ -616,6 +622,14 @@ def _pinned_coursier_fetch_impl(repository_ctx):
+         executable = False,
+     )
+ 
++    repository_ctx.file(
++        "BUILD.vendor",
++        (_BUILD_VENDOR).format(
++            vendor_targets = generated_vendor_targets,
++        ),
++        executable = False,
++    )
++
+     _add_outdated_files(repository_ctx, artifacts, repositories)
+ 
+     # Generate a compatibility layer of external repositories for all jar artifacts.
+@@ -1135,7 +1149,7 @@ def _coursier_fetch_impl(repository_ctx):
+     })
+ 
+     repository_ctx.report_progress("Generating BUILD targets..")
+-    (generated_imports, jar_versionless_target_labels) = parser.generate_imports(
++    (generated_imports, jar_versionless_target_labels, _) = parser.generate_imports(
+         repository_ctx = repository_ctx,
+         dep_tree = dep_tree,
+         explicit_artifacts = {
+diff --git a/private/dependency_tree_parser.bzl b/private/dependency_tree_parser.bzl
+index 8515bf5..7653dea 100644
+--- a/private/dependency_tree_parser.bzl
++++ b/private/dependency_tree_parser.bzl
+@@ -107,6 +107,9 @@ def _generate_imports(repository_ctx, dep_tree, explicit_artifacts, neverlink_ar
+     for jetify_include_artifact in repository_ctx.attr.jetify_include_list:
+         jetify_include_dict[jetify_include_artifact] = None
+ 
++    artifact_paths = []
++    vendor_targets = []
++
+     # Iterate through the list of artifacts, and generate the target declaration strings.
+     for artifact in dep_tree["dependencies"]:
+         artifact_path = artifact["file"]
+@@ -336,6 +339,7 @@ def _generate_imports(repository_ctx, dep_tree, explicit_artifacts, neverlink_ar
+             target_import_string.append(")")
+ 
+             all_imports.append("\n".join(target_import_string))
++            vendor_targets.append("\n".join(target_import_string))
+ 
+             # 10. Create a versionless alias target
+             #
+@@ -346,6 +350,9 @@ def _generate_imports(repository_ctx, dep_tree, explicit_artifacts, neverlink_ar
+             versioned_target_alias_label = escape(strip_packaging_and_classifier(artifact["coord"]))
+             all_imports.append("alias(\n\tname = \"%s\",\n\tactual = \"%s\",\n%s)" %
+                                (versioned_target_alias_label, target_label, alias_visibility))
++            file_group_target_string = "filegroup(\n\tname = \"%s\",\n\tsrcs = [\"%s\"],\n%s)" % (target_label + "_file", artifact_path, alias_visibility)
++            all_imports.append(file_group_target_string)
++            vendor_targets.append(file_group_target_string)
+ 
+             # 11. If using maven_install.json, use a genrule to copy the file from the http_file
+             # repository into this repository.
+@@ -359,6 +366,9 @@ def _generate_imports(repository_ctx, dep_tree, explicit_artifacts, neverlink_ar
+             if repository_ctx.attr.maven_install_json:
+                 all_imports.append(_genrule_copy_artifact_from_http_file(artifact, default_visibilities))
+ 
++            # 12. collect the artifact_path for the filegroup rule collecting all necessary sources for vendoring
++            artifact_paths.append("\"%s\"" % artifact_path)
++
+         else:  # artifact_path == None:
+             # Special case for certain artifacts that only come with a POM file.
+             # Such artifacts "aggregate" their dependencies, so they don't have
+@@ -410,7 +420,10 @@ def _generate_imports(repository_ctx, dep_tree, explicit_artifacts, neverlink_ar
+             all_imports.append("alias(\n\tname = \"%s\",\n\tactual = \"%s\",\n%s)" %
+                                (versioned_target_alias_label, target_label, alias_visibility))
+ 
+-    return ("\n".join(all_imports), jar_versionless_target_labels)
++    all_imports.append("filegroup(\n\tname = \"srcs\",\n\tsrcs = [\n\t\t%s,\n\t],\n\tvisibility = [\"//visibility:public\"],\n)" %
++                       (",\n\t\t".join(["\"BUILD.vendor\"", "\"defs.bzl\"", "\"WORKSPACE\""] + artifact_paths)))
++
++    return ("\n".join(all_imports), jar_versionless_target_labels, "\n".join(vendor_targets))
+ 
+ parser = struct(
+     generate_imports = _generate_imports,