diff options
Diffstat (limited to 'java/com/google/turbine/binder/CtSymClassBinder.java')
-rw-r--r-- | java/com/google/turbine/binder/CtSymClassBinder.java | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/java/com/google/turbine/binder/CtSymClassBinder.java b/java/com/google/turbine/binder/CtSymClassBinder.java index a6f1b3d..1d7ece7 100644 --- a/java/com/google/turbine/binder/CtSymClassBinder.java +++ b/java/com/google/turbine/binder/CtSymClassBinder.java @@ -16,11 +16,15 @@ package com.google.turbine.binder; +import static com.google.common.base.Ascii.toUpperCase; import static com.google.common.base.StandardSystemProperty.JAVA_HOME; +import static java.util.Objects.requireNonNull; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableMap; +import com.google.common.primitives.Ints; import com.google.turbine.binder.bound.ModuleInfo; import com.google.turbine.binder.bytecode.BytecodeBinder; import com.google.turbine.binder.bytecode.BytecodeBoundClass; @@ -32,6 +36,7 @@ import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.ModuleSymbol; import com.google.turbine.zip.Zip; import java.io.IOException; +import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -40,12 +45,13 @@ import java.util.Map; import org.checkerframework.checker.nullness.qual.Nullable; /** Constructs a platform {@link ClassPath} from the current JDK's ct.sym file. */ -public class CtSymClassBinder { +public final class CtSymClassBinder { @Nullable public static ClassPath bind(String version) throws IOException { - Path javaHome = Paths.get(JAVA_HOME.value()); - Path ctSym = javaHome.resolve("lib/ct.sym"); + String javaHome = JAVA_HOME.value(); + requireNonNull(javaHome, "attempted to use --release, but JAVA_HOME is not set"); + Path ctSym = Paths.get(javaHome).resolve("lib/ct.sym"); if (!Files.exists(ctSym)) { throw new IllegalStateException("lib/ct.sym does not exist in " + javaHome); } @@ -59,7 +65,9 @@ public class CtSymClassBinder { } }; // ct.sym contains directories whose names are the concatentation of a list of target versions - // (e.g. 789) and which contain interface class files with a .sig extension. + // formatted as a single character 0-9 or A-Z (e.g. 789A) and which contain interface class + // files with a .sig extension. + String releaseString = formatReleaseVersion(version); for (Zip.Entry ze : new Zip.ZipIterable(ctSym)) { String name = ze.name(); if (!name.endsWith(".sig")) { @@ -70,10 +78,13 @@ public class CtSymClassBinder { continue; } // check if the directory matches the desired release - // TODO(cushon): what happens when version numbers contain more than one digit? - if (!ze.name().substring(0, idx).contains(version)) { + if (!ze.name().substring(0, idx).contains(releaseString)) { continue; } + if (isAtLeastJDK12()) { + // JDK >= 12 includes the module name as a prefix + idx = name.indexOf('/', idx + 1); + } if (name.substring(name.lastIndexOf('/') + 1).equals("module-info.sig")) { ModuleInfo moduleInfo = BytecodeBinder.bindModuleInfo(name, toByteArrayOrDie(ze)); modules.put(new ModuleSymbol(moduleInfo.name()), moduleInfo); @@ -122,4 +133,28 @@ public class CtSymClassBinder { } }); } + + @VisibleForTesting + static String formatReleaseVersion(String version) { + Integer n = Ints.tryParse(version); + if (n == null || n <= 4 || n >= 36) { + throw new IllegalArgumentException("invalid release version: " + version); + } + return toUpperCase(Integer.toString(n, 36)); + } + + private static boolean isAtLeastJDK12() { + int major; + try { + Method versionMethod = Runtime.class.getMethod("version"); + Object version = versionMethod.invoke(null); + major = (int) version.getClass().getMethod("major").invoke(version); + } catch (ReflectiveOperationException e) { + // `Runtime.version()` was added in JDK 9 + return false; + } + return major >= 12; + } + + private CtSymClassBinder() {} } |