diff --git a/Documentation/dev-eclipse.txt b/Documentation/dev-eclipse.txt index 6e3950283d..0f23db5201 100644 --- a/Documentation/dev-eclipse.txt +++ b/Documentation/dev-eclipse.txt @@ -3,7 +3,7 @@ This document is about configuring Gerrit Code Review into an Eclipse workspace for development and debugging with GWT. -Java 6 or later SDK is also required to run GWT's compiler and +Java 8 or later SDK is also required to run GWT's compiler and runtime debugging environment. @@ -49,6 +49,19 @@ the same way you would when link:dev-build-plugins.html#_bundle_custom_plugin_in_release_war[bundling in release.war] and run `tools/eclipse/project.py`. +[[Newer Java versions]] + +Java 9 and later are supported, but some adjustments must be done, because +Java 8 is still the default: + +* Add JRE, e.g.: directory: /usr/lib64/jvm/java-9-openjdk, name: java-9-openjdk-9 +* Change execution environemnt for gerrit project to: JavaSE-9 (java-9-openjdk-9) +* Check that compiler compliance level in gerrit project is set to: 9 +* Add this parameter to VM argument for gerrit_daemin launcher: +---- + --add-modules java.activation \ + --add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED +---- [[Formatting]] == Code Formatter Settings diff --git a/java/com/google/gerrit/httpd/raw/BazelBuild.java b/java/com/google/gerrit/httpd/raw/BazelBuild.java index 940a51bf82..2b390a92e1 100644 --- a/java/com/google/gerrit/httpd/raw/BazelBuild.java +++ b/java/com/google/gerrit/httpd/raw/BazelBuild.java @@ -23,14 +23,15 @@ import com.google.common.flogger.FluentLogger; import com.google.common.html.HtmlEscapers; import com.google.common.io.ByteStreams; import com.google.gerrit.common.TimeUtil; +import com.google.gerrit.launcher.GerritLauncher; import com.google.gerrit.util.http.CacheHeaders; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.NoSuchFileException; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import java.util.Properties; import javax.servlet.http.HttpServletResponse; import org.eclipse.jgit.util.RawParseUtils; @@ -122,20 +123,19 @@ public class BazelBuild { } } - private Properties loadBuildProperties(Path propPath) throws IOException { - Properties properties = new Properties(); - try (InputStream in = Files.newInputStream(propPath)) { - properties.load(in); - } catch (NoSuchFileException e) { - // Ignore; will be run from PATH, with a descriptive error if it fails. - } - return properties; - } - private ProcessBuilder newBuildProcess(Label label) throws IOException { - Properties properties = loadBuildProperties(sourceRoot.resolve(".bazel_path")); + Properties properties = GerritLauncher.loadBuildProperties(sourceRoot.resolve(".bazel_path")); String bazel = firstNonNull(properties.getProperty("bazel"), "bazel"); - ProcessBuilder proc = new ProcessBuilder(bazel, "build", label.fullName()); + List cmd = new ArrayList<>(); + cmd.add(bazel); + cmd.add("build"); + if (GerritLauncher.isJdk9OrLater()) { + String v = GerritLauncher.getJdkVersionPostJdk8(); + cmd.add("--host_java_toolchain=@bazel_tools//tools/jdk:toolchain_java" + v); + cmd.add("--java_toolchain=@bazel_tools//tools/jdk:toolchain_java" + v); + } + cmd.add(label.fullName()); + ProcessBuilder proc = new ProcessBuilder(cmd); if (properties.containsKey("PATH")) { proc.environment().put("PATH", properties.getProperty("PATH")); } diff --git a/java/com/google/gerrit/launcher/GerritLauncher.java b/java/com/google/gerrit/launcher/GerritLauncher.java index 13dad0ef0b..0d26fe7b61 100644 --- a/java/com/google/gerrit/launcher/GerritLauncher.java +++ b/java/com/google/gerrit/launcher/GerritLauncher.java @@ -34,6 +34,7 @@ import java.net.URLClassLoader; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; +import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; import java.security.CodeSource; @@ -44,6 +45,7 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Scanner; import java.util.SortedMap; import java.util.TreeMap; @@ -644,6 +646,25 @@ public final class GerritLauncher { return resolveInSourceRoot("eclipse-out"); } + public static boolean isJdk9OrLater() { + return Double.parseDouble(System.getProperty("java.class.version")) >= 53.0; + } + + public static String getJdkVersionPostJdk8() { + // 9.0.4 => 9 + return System.getProperty("java.version").substring(0, 1); + } + + public static Properties loadBuildProperties(Path propPath) throws IOException { + Properties properties = new Properties(); + try (InputStream in = Files.newInputStream(propPath)) { + properties.load(in); + } catch (NoSuchFileException e) { + // Ignore; will be run from PATH, with a descriptive error if it fails. + } + return properties; + } + static final String SOURCE_ROOT_RESOURCE = "/com/google/gerrit/launcher/workspace-root.txt"; /** @@ -708,14 +729,36 @@ public final class GerritLauncher { return ret; } - private static ClassLoader useDevClasspath() throws MalformedURLException, FileNotFoundException { + private static ClassLoader useDevClasspath() throws IOException { Path out = getDeveloperEclipseOut(); List dirs = new ArrayList<>(); dirs.add(out.resolve("classes").toUri().toURL()); ClassLoader cl = GerritLauncher.class.getClassLoader(); - for (URL u : ((URLClassLoader) cl).getURLs()) { - if (includeJar(u)) { - dirs.add(u); + + if (isJdk9OrLater()) { + Path rootPath = resolveInSourceRoot(".").normalize(); + + Properties properties = loadBuildProperties(rootPath.resolve(".bazel_path")); + Path outputBase = Paths.get(properties.getProperty("output_base")); + + Path runtimeClasspath = + rootPath.resolve("bazel-bin/tools/eclipse/main_classpath_collect.runtime_classpath"); + for (String f : Files.readAllLines(runtimeClasspath, UTF_8)) { + URL url; + if (f.startsWith("external")) { + url = outputBase.resolve(f).toUri().toURL(); + } else { + url = rootPath.resolve(f).toUri().toURL(); + } + if (includeJar(url)) { + dirs.add(url); + } + } + } else { + for (URL u : ((URLClassLoader) cl).getURLs()) { + if (includeJar(u)) { + dirs.add(u); + } } } return URLClassLoader.newInstance( @@ -724,7 +767,9 @@ public final class GerritLauncher { private static boolean includeJar(URL u) { String path = u.getPath(); - return path.endsWith(".jar") && !path.endsWith("-src.jar"); + return path.endsWith(".jar") + && !path.endsWith("-src.jar") + && !path.contains("/com/google/gerrit"); } private GerritLauncher() {} diff --git a/tools/eclipse/project.py b/tools/eclipse/project.py index b99c04e612..9b60a3725b 100755 --- a/tools/eclipse/project.py +++ b/tools/eclipse/project.py @@ -32,7 +32,7 @@ AUTO = '//lib/auto:auto-value' JRE = '/'.join([ 'org.eclipse.jdt.launching.JRE_CONTAINER', 'org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType', - 'JavaSE-1.8', + 'JavaSE-9', ]) # Map of targets to corresponding classpath collector rules cp_targets = { @@ -52,10 +52,12 @@ opts.add_option('--name', help='name of the generated project', action='store', default='gerrit', dest='project_name') opts.add_option('-b', '--batch', action='store_true', dest='batch', help='Bazel batch option') +opts.add_option('-j', '--java', action='store', + dest='java', help='Post Java 8 support (9|10|11|...)') args, _ = opts.parse_args() batch_option = '--batch' if args.batch else None - +custom_java = args.java def _build_bazel_cmd(*args): cmd = ['bazel'] @@ -63,6 +65,9 @@ def _build_bazel_cmd(*args): cmd.append('--batch') for arg in args: cmd.append(arg) + if custom_java: + cmd.append('--host_java_toolchain=@bazel_tools//tools/jdk:toolchain_java%s' % custom_java) + cmd.append('--java_toolchain=@bazel_tools//tools/jdk:toolchain_java%s' % custom_java) return cmd @@ -70,9 +75,10 @@ def retrieve_ext_location(): return check_output(_build_bazel_cmd('info', 'output_base')).strip() -def gen_bazel_path(): +def gen_bazel_path(ext_location): bazel = check_output(['which', 'bazel']).strip().decode('UTF-8') with open(path.join(ROOT, ".bazel_path"), 'w') as fd: + fd.write("output_base=%s\n" % ext_location) fd.write("bazel=%s\n" % bazel) fd.write("PATH=%s\n" % environ["PATH"]) @@ -301,7 +307,7 @@ try: gen_project(args.project_name) gen_classpath(ext_location) gen_factorypath(ext_location) - gen_bazel_path() + gen_bazel_path(ext_location) # TODO(davido): Remove this when GWT gone gwt_working_dir = ".gwt_work_dir"