Set up Eclipse to work with Java 9 and later

To create .classpath with java 9, run:

  $ tools/eclipse/project.py --java 9

Start Eclipse, and follow the instructions provided in dev-eclipse.txt to
switch to Java 9 or later.

To run gerrit from Eclipse, the system classpath is cast to
URLClassLoader to retrieve the needed JARs. In Java 9 system classpath
cannot be cast to URLClassLoader. To rectify, extract the classpath from
Bazel.

Change-Id: Ie341cd4dfee5520f689fc50f34aa5395b74b5e7d
This commit is contained in:
David Ostrovsky 2018-06-25 23:45:15 +02:00 committed by David Ostrovsky
parent f51cf2323b
commit 8aae31c376
4 changed files with 88 additions and 24 deletions

View File

@ -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

View File

@ -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<String> 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"));
}

View File

@ -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,23 +729,47 @@ public final class GerritLauncher {
return ret;
}
private static ClassLoader useDevClasspath() throws MalformedURLException, FileNotFoundException {
private static ClassLoader useDevClasspath() throws IOException {
Path out = getDeveloperEclipseOut();
List<URL> dirs = new ArrayList<>();
dirs.add(out.resolve("classes").toUri().toURL());
ClassLoader cl = GerritLauncher.class.getClassLoader();
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(
dirs.toArray(new URL[dirs.size()]), ClassLoader.getSystemClassLoader().getParent());
}
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() {}

View File

@ -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"