Build ONOS exclusively with Bazel-provided remote JDK

This change make it possible to build ONOS in a host system without JDK
installed, or ignoring the one installed, instead relying exclusively on
the "remote" JDK provided by Bazel. The JDK version, along with the
toolchain configuration (language source and target values), are checked
in as part of the build files (tools/build/bazel/BUILD), thus enabling
deterministic builds that are less dependent of the host environment.

To allow this, this change replaces all references to JDK-related tools
expected to be on the host PATH, such as the jar command, with their
counterpart from the remote JDK (now a sandboxed relative path). This is
achieved by:

  * Creating a new "jdk_genrule" macro that exposes the remote JDK bin
    directory to the PATH visible by the genrule command. This is used
    for all genrule targets invoking for example `jar`;
  * Modifying custom Starlak rule implementations by replacing
    invocation to JDK tools with a path from the remote one.
  * Renaming the onos/lib directory to onos/deps as it clashes with
    the Bazel-provided JDK's lib directory (that for some strange reason
    is resolved on the ONOS workspace)

Finally, this change is reflected on the Dockerfile which now builds
ONOS from an Ubuntu image with no JDK installed.

Change-Id: Ie7d990cfce6fef00ddb4ffffe4c6205b8530fb47
diff --git a/tools/build/bazel/BUILD b/tools/build/bazel/BUILD
index cf20246..57f700d 100644
--- a/tools/build/bazel/BUILD
+++ b/tools/build/bazel/BUILD
@@ -1,15 +1,20 @@
 load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain")
 
-# This is where we define the language source and target values passed to javac
-# when building ONOS. This toolchain should be used when invoking bazel build
+# This is where we define the JDK used to build ONOS, as well as the language
+# source and target values passed to javac. The :default_toolchain and
+# :default_jdk are expected to be passed as arguments when invoking bazel build
 # (see onos/.bazelrc)
 default_java_toolchain(
     name = "default_toolchain",
     source_version = "11",
     target_version = "11",
-    visibility = [
-        "//visibility:public",
-    ],
+    visibility = ["//visibility:public"],
+)
+
+alias(
+    name = "default_jdk",
+    actual = "@bazel_tools//tools/jdk:remote_jdk11",
+    visibility = ["//visibility:public"],
 )
 
 py_binary(
diff --git a/tools/build/bazel/checkstyle.bzl b/tools/build/bazel/checkstyle.bzl
index b651dd2..8e6e37f 100644
--- a/tools/build/bazel/checkstyle.bzl
+++ b/tools/build/bazel/checkstyle.bzl
@@ -27,8 +27,11 @@
         need_colon = True
         classpath += file.path
 
+    java_runtime = ctx.attr._jdk[java_common.JavaRuntimeInfo]
+    java_exe_path = java_runtime.java_executable_runfiles_path
+
     cmd = " ".join(
-        ["java -cp %s com.puppycrawl.tools.checkstyle.Main" % classpath] +
+        ["%s -cp %s com.puppycrawl.tools.checkstyle.Main" % (java_exe_path, classpath)] +
         ["-c %s" % ctx.attr._config.files.to_list()[0].path] +
         [src_file.path for src_file in ctx.files.srcs],
     )
@@ -44,7 +47,10 @@
               ctx.attr._suppressions.files.to_list() +
               ctx.attr._java_header.files.to_list())
 
-    runfiles = ctx.runfiles(files = inputs)
+    runfiles = ctx.runfiles(
+        files = inputs,
+        transitive_files = java_runtime.files,
+    )
     return [DefaultInfo(runfiles = runfiles)]
 
 """
@@ -66,6 +72,10 @@
         "_config": attr.label(default = Label("//tools/build/conf:checkstyle_xml")),
         "_suppressions": attr.label(default = Label("//tools/build/conf:suppressions_xml")),
         "_java_header": attr.label(default = Label("//tools/build/conf:onos_java_header")),
+        "_jdk": attr.label(
+            default = Label("@bazel_tools//tools/jdk:current_java_runtime"),
+            providers = [java_common.JavaRuntimeInfo],
+        ),
     },
     implementation = _checkstyle_impl,
 )
diff --git a/tools/build/bazel/java_sources.bzl b/tools/build/bazel/java_sources.bzl
index a45ae60..1381a05 100644
--- a/tools/build/bazel/java_sources.bzl
+++ b/tools/build/bazel/java_sources.bzl
@@ -13,24 +13,28 @@
 # limitations under the License.
 
 def _impl(ctx):
-    jar = ctx.outputs.jar
+    outjar = ctx.outputs.jar
 
     src_list = ""
     for src in ctx.files.srcs:
         if src.path.endswith(".srcjar"):
             src_list += " " + src.path
 
+    java_runtime = ctx.attr._jdk[java_common.JavaRuntimeInfo]
+    jar_path = "%s/bin/jar" % java_runtime.java_home
+
     cmd = [
-        "for sj in %s; do jar xf $sj; done" % src_list,
+        "for sj in %s; do %s xf $sj; done" % (src_list, jar_path),
         "dir=$(find . -type d -name java)",
-        "[ -n \"$dir\" -a -d \"$dir\" ] && jar cf %s -C $dir ." % jar.path,
+        "[ -n \"$dir\" -a -d \"$dir\" ] && %s cf %s -C $dir ." % (jar_path, outjar.path),
     ]
 
     ctx.action(
         inputs = ctx.files.srcs,
-        outputs = [jar],
+        outputs = [outjar],
         progress_message = "Generating source jar for %s" % ctx.attr.name,
         command = ";\n".join(cmd),
+        tools = java_runtime.files,
     )
 
 def _impl_alt(ctx):
@@ -68,6 +72,10 @@
 java_sources = rule(
     attrs = {
         "srcs": attr.label_list(allow_files = True),
+        "_jdk": attr.label(
+            default = Label("@bazel_tools//tools/jdk:current_java_runtime"),
+            providers = [java_common.JavaRuntimeInfo],
+        ),
     },
     implementation = _impl,
     outputs = {"jar": "%{name}.jar"},
diff --git a/tools/build/bazel/javadoc.bzl b/tools/build/bazel/javadoc.bzl
index 87e5592..c459f7d 100644
--- a/tools/build/bazel/javadoc.bzl
+++ b/tools/build/bazel/javadoc.bzl
@@ -12,11 +12,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-JAVA_DOCS = "-link https://docs.oracle.com/javase/8/docs/api/"
+JAVA_DOCS = "-link https://docs.oracle.com/javase/11/docs/api/"
 
 def _impl(ctx):
     dir = ctx.label.name
-    jar = ctx.outputs.jar
+    outjar = ctx.outputs.jar
 
     dep_list = []
     for dep in ctx.files.deps:
@@ -26,24 +26,32 @@
     for src in ctx.files.srcs:
         src_list += [src.path]
 
+    java_runtime = ctx.attr._jdk[java_common.JavaRuntimeInfo]
+    jar_exe_path = "%s/bin/jar" % java_runtime.java_home
+
     cmd = [
         "mkdir %s" % dir,
         "javadoc -encoding UTF-8 -quiet -tag onos.rsModel:a:\"onos model\" %s -d %s -cp %s %s" %
         (JAVA_DOCS, dir, ":".join(dep_list), " ".join(src_list)),
-        "jar cf %s -C %s ." % (jar.path, dir),
+        "%s cf %s -C %s ." % (jar_exe_path, outjar.path, dir),
     ]
 
     ctx.action(
         inputs = ctx.files.srcs + ctx.files.deps,
-        outputs = [jar],
+        outputs = [outjar],
         progress_message = "Generating javadocs jar for %s" % ctx.attr.name,
         command = ";\n".join(cmd),
+        tools = java_runtime.files,
     )
 
 javadoc = rule(
     attrs = {
         "deps": attr.label_list(allow_files = True),
         "srcs": attr.label_list(allow_files = True),
+        "_jdk": attr.label(
+            default = Label("@bazel_tools//tools/jdk:current_java_runtime"),
+            providers = [java_common.JavaRuntimeInfo],
+        ),
     },
     implementation = _impl,
     outputs = {"jar": "%{name}.jar"},
diff --git a/tools/build/bazel/jdk_genrule.bzl b/tools/build/bazel/jdk_genrule.bzl
new file mode 100644
index 0000000..14e5aa2
--- /dev/null
+++ b/tools/build/bazel/jdk_genrule.bzl
@@ -0,0 +1,40 @@
+"""
+ Copyright 2018-present Open Networking Foundation
+
+ 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.
+"""
+
+"""
+Extension to genrule that has the JDK bin directory in the PATH, thus allowing
+to invoke commands like jar directly in the genrule "cmd" attribute.
+This allows using JDK-related tools on a host system that does not have the JDK
+installed, instead using the current JDK used by Bazel, e.g. the embedded or
+remote one.
+"""
+
+def jdk_genrule(
+        cmd,
+        tools = [],
+        toolchains = [],
+        **kwargs):
+    new_tools = tools + ["@bazel_tools//tools/jdk:current_java_runtime"]
+    new_toolchains = toolchains + ["@bazel_tools//tools/jdk:current_java_runtime"]
+    new_cmd = "echo \"export PATH=$$PWD/$(JAVABASE)/bin:$$PATH:\" > jdk_genrule_setup.sh; " + \
+              "source jdk_genrule_setup.sh; " + cmd
+
+    native.genrule(
+        cmd = new_cmd,
+        tools = new_tools,
+        toolchains = new_toolchains,
+        **kwargs
+    )
diff --git a/tools/build/bazel/minimal_jar.bzl b/tools/build/bazel/minimal_jar.bzl
index ccc0c65..6615ec9 100644
--- a/tools/build/bazel/minimal_jar.bzl
+++ b/tools/build/bazel/minimal_jar.bzl
@@ -13,19 +13,29 @@
 # limitations under the License.
 
 def _impl(ctx):
-    jar = ctx.outputs.jar
+    outjar = ctx.outputs.jar
+
+    java_runtime = ctx.attr._jdk[java_common.JavaRuntimeInfo]
+    jar_exe_path = "%s/bin/jar" % java_runtime.java_home
 
     cmd = [
-        "mkdir readme && touch readme/README && jar cf %s readme/README" % (jar.path),
+        "mkdir readme && touch readme/README && %s cf %s readme/README" % (jar_exe_path, outjar.path),
     ]
 
     ctx.action(
-        outputs = [jar],
+        outputs = [outjar],
         progress_message = "Generating minimal jar for %s" % ctx.attr.name,
         command = ";\n".join(cmd),
+        tools = java_runtime.files,
     )
 
 minimal_jar = rule(
+    attrs = {
+        "_jdk": attr.label(
+            default = Label("@bazel_tools//tools/jdk:current_java_runtime"),
+            providers = [java_common.JavaRuntimeInfo],
+        ),
+    },
     implementation = _impl,
     outputs = {"jar": "%{name}.jar"},
 )
diff --git a/tools/build/bazel/osgi_java_library.bzl b/tools/build/bazel/osgi_java_library.bzl
index 8296fcf..0ca2047 100644
--- a/tools/build/bazel/osgi_java_library.bzl
+++ b/tools/build/bazel/osgi_java_library.bzl
@@ -714,7 +714,7 @@
         proto_name + "-srcjar",
     ]
     base_deps = [
-        "//lib:com_google_protobuf_protobuf_java",
+        "//deps:com_google_protobuf_protobuf_java",
     ]
     if grpc_proto_lib != None:
         grpc_name = name + "-java-grpc"
@@ -732,9 +732,9 @@
         )
         base_deps.extend([
             "@com_google_guava_guava//jar",
-            "//lib:io_grpc_grpc_api_context",
-            "//lib:io_grpc_grpc_stub",
-            "//lib:io_grpc_grpc_protobuf",
+            "//deps:io_grpc_grpc_api_context",
+            "//deps:io_grpc_grpc_stub",
+            "//deps:io_grpc_grpc_protobuf",
             "@javax_annotation_javax_annotation_api//jar",
         ])
     osgi_jar(
diff --git a/tools/build/bazel/project_javadoc.bzl b/tools/build/bazel/project_javadoc.bzl
index 171b846..7c706d0 100644
--- a/tools/build/bazel/project_javadoc.bzl
+++ b/tools/build/bazel/project_javadoc.bzl
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-JAVA_DOCS = "-link https://docs.oracle.com/javase/8/docs/api/"
+JAVA_DOCS = "-link https://docs.oracle.com/javase/11/docs/api/"
 
 def dump(obj):
     print(dir(obj))
@@ -21,7 +21,7 @@
 
 def _impl(ctx):
     dir = ctx.label.name
-    jar = ctx.outputs.jar
+    outjar = ctx.outputs.jar
 
     classpath = ""
     for dep in ctx.files.deps:
@@ -39,9 +39,13 @@
             packages += ":" + p
         group_list += " -group \"%s\" %s" % (group, packages.replace(":", "", 1))
 
+    java_runtime = ctx.attr._jdk[java_common.JavaRuntimeInfo]
+    jar_exe_path = "%s/bin/jar" % java_runtime.java_home
+    javadoc_exe_path = "%s/bin/javadoc" % java_runtime.java_home
+
     cmd = [
         "mkdir src; cd src",
-        "for s in %s; do jar xf ../$s; done" % src_list,
+        "for s in %s; do ../%s xf ../$s; done" % (src_list, jar_exe_path),
         "rm -f META-INF/MANIFEST.MF",
         "cd ..",
         "cp -r docs/src/main/javadoc/* .",
@@ -54,17 +58,18 @@
         cmd += ["find src -type f | egrep -v 'src/(OSGI|WEB)-INF' | egrep -v '/(impl|internal)/' >> FILES"]
 
     cmd += [
-        "javadoc -encoding UTF-8 -overview overview.html -doctitle '%s' -windowtitle '%s' %s -d apidocs -classpath %s -sourcepath src %s @FILES" %
-        (ctx.attr.title, ctx.attr.title, group_list, classpath.replace(":", "", 1), JAVA_DOCS),
+        "%s -encoding UTF-8 -overview overview.html -doctitle '%s' -windowtitle '%s' %s -d apidocs -classpath %s -sourcepath src %s @FILES" %
+        (javadoc_exe_path, ctx.attr.title, ctx.attr.title, group_list, classpath.replace(":", "", 1), JAVA_DOCS),
         "cp -r doc-files apidocs/doc-files",
-        "jar cf %s apidocs" % jar.path,
+        "%s cf %s apidocs" % (jar_exe_path, outjar.path),
     ]
 
-    ctx.action(
+    ctx.actions.run_shell(
         inputs = ctx.files.srcs + ctx.files.deps,
-        outputs = [jar],
+        outputs = [outjar],
         progress_message = "Generating javadocs jar for %s" % ctx.attr.name,
         command = ";\n".join(cmd),
+        tools = java_runtime.files,
     )
 
 project_javadoc = rule(
@@ -75,6 +80,10 @@
         "deps": attr.label_list(allow_files = True),
         "srcs": attr.label_list(allow_files = True),
         "internal": attr.bool(default = False),
+        "_jdk": attr.label(
+            default = Label("@bazel_tools//tools/jdk:current_java_runtime"),
+            providers = [java_common.JavaRuntimeInfo],
+        ),
     },
     implementation = _impl,
     outputs = {"jar": "%{name}.jar"},
diff --git a/tools/build/bazel/yang.bzl b/tools/build/bazel/yang.bzl
index 18b60e7..d96000f 100644
--- a/tools/build/bazel/yang.bzl
+++ b/tools/build/bazel/yang.bzl
@@ -69,6 +69,9 @@
         executable = ctx.executable._yang_compiler,
     )
 
+    java_runtime = ctx.attr._jdk[java_common.JavaRuntimeInfo]
+    jar_path = "%s/bin/jar" % java_runtime.java_home
+
     ctx.actions.run_shell(
         inputs = [generated_sources],
         outputs = [ctx.outputs.srcjar],
@@ -76,7 +79,8 @@
             ctx.outputs.srcjar.path,
             generated_sources.path,
         ],
-        command = "jar cf $1 -C $2 src",
+        tools = java_runtime.files,
+        command = "%s cf $1 -C $2 src" % jar_path,
         progress_message = "Assembling YANG Java sources: %s" % ctx.attr.name,
     )
 
@@ -87,7 +91,8 @@
             ctx.outputs.schema.path,
             generated_sources.path,
         ],
-        command = "jar cf $1 -C $2 schema",
+        tools = java_runtime.files,
+        command = "%s cf $1 -C $2 schema" % jar_path,
         progress_message = "Assembling YANG compiled schema: %s" % ctx.attr.name,
     )
 
@@ -103,6 +108,10 @@
             allow_files = True,
             default = Label("//tools/build/bazel:onos_yang_compiler"),
         ),
+        "_jdk": attr.label(
+            default = Label("@bazel_tools//tools/jdk:current_java_runtime"),
+            providers = [java_common.JavaRuntimeInfo],
+        ),
     },
     outputs = {
         "srcjar": "model.srcjar",
@@ -139,13 +148,18 @@
     srcs = [name + "-generate"]
 
     if len(java_srcs):
-        srcs += [name + "-srcjar"]
-        native.genrule(
-            name = name + "-srcjar",
-            srcs = java_srcs,
-            outs = [name + ".srcjar"],
-            cmd = "jar cf $(location %s.srcjar) $(SRCS)" % name,
-        )
+        srcs.extend(java_srcs)
+        # FIXME (carmelo): is this genrule really needed?
+        # srcs += [name + "-srcjar"]
+        # native.genrule(
+        #     name = name + "-srcjar",
+        #     srcs = java_srcs,
+        #     outs = [name + ".srcjar"],
+        #     cmd = "$(location //external:jar) cf $(location %s.srcjar) $(SRCS)" % name,
+        #     tools = [
+        #         "//external:jar",
+        #     ]
+        # )
 
     if not custom_registrator:
         srcs += [name + "-registrator"]
diff --git a/tools/build/onos-lib-gen b/tools/build/onos-lib-gen
index 0525438..7e6c951 100755
--- a/tools/build/onos-lib-gen
+++ b/tools/build/onos-lib-gen
@@ -21,4 +21,4 @@
     [ -f $JAR ] && printf "Done.\n"
 fi
 
-java -jar $JAR lib/deps.json tools/build/bazel/generate_workspace.bzl --bazel
\ No newline at end of file
+java -jar $JAR deps/deps.json tools/build/bazel/generate_workspace.bzl --bazel
\ No newline at end of file
diff --git a/tools/build/onos-validate-change-version.excludes b/tools/build/onos-validate-change-version.excludes
index 856a1f4..59eb745 100755
--- a/tools/build/onos-validate-change-version.excludes
+++ b/tools/build/onos-validate-change-version.excludes
@@ -25,7 +25,7 @@
 \./drivers/p4runtime
 \./drivers/bmv2
 \./lib/BUCK
-\./lib/deps.json
+\./deps/deps.json
 \./models/openroadm/pom.xml
 \./out
 \./pom.xml.versionsBackup
diff --git a/tools/gui/BUILD b/tools/gui/BUILD
index d559643..0cec9ea 100644
--- a/tools/gui/BUILD
+++ b/tools/gui/BUILD
@@ -1,3 +1,5 @@
+load("//tools/build/bazel:jdk_genrule.bzl", genrule = "jdk_genrule")
+
 filegroup(
     name = "_tools-gui-gulp-files",
     srcs = [