Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CtSym.java89
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java9
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java17
3 files changed, 67 insertions, 48 deletions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CtSym.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CtSym.java
index 2dc554db41..d0dc2c96f7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CtSym.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/CtSym.java
@@ -38,8 +38,8 @@ import java.util.concurrent.ConcurrentHashMap;
* <p>
* The only documentation known seem to be the current implementation of
* com.sun.tools.javac.platform.JDKPlatformProvider and probably some JDK build tools that construct ct.sym file. Root
- * directories inside the file are somehow related to the Java release number, encoded as hex (if they contain release
- * number as hex).
+ * directories inside the file are somehow related to the Java release number, encoded as single digit or letter (single
+ * digits for releases 7 to 9, capital letters for 10 and higher).
* <p>
* If a release directory contains "system-modules" file, it is a flag that this release files are not inside ct.sym
* file because it is the current release, and jrt file system should be used instead.
@@ -77,6 +77,11 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class CtSym {
+ /**
+ * 'B' is code for Java 11, see {@link #getReleaseCode(String)}.
+ */
+ private static final char JAVA_11 = 'B';
+
public static final boolean DISABLE_CACHE = Boolean.getBoolean("org.eclipse.jdt.disable_CTSYM_cache"); //$NON-NLS-1$
static boolean VERBOSE = false;
@@ -97,14 +102,14 @@ public class CtSym {
private boolean isJRE12Plus;
/**
- * Paths of all root directories, per release (as hex number). e.g. in JDK 11, Java 10 mapping looks like A -> [A,
+ * Paths of all root directories, per release (versions encoded). e.g. in JDK 11, Java 10 mapping looks like A -> [A,
* A-modules, A789, A9] but to have more fun, in JDK 14, same mapping looks like A -> [A, AB, ABC, ABCD]
*/
private final Map<String, List<Path>> releaseRootPaths = new ConcurrentHashMap<>();
/**
- * All paths that exist in all release root directories, per release (as hex number). The first key is release
- * number in hex. The second key is the "full qualified binary name" of the class (without module name and
+ * All paths that exist in all release root directories, per release (versions encoded). The first key is release
+ * code. The second key is the "full qualified binary name" of the class (without module name and
* with .sig suffix). The value is the full path of the corresponding signature file in the ct.sym file.
*/
private final Map<String, Map<String, Path>> allReleasesPaths = new ConcurrentHashMap<>();
@@ -166,28 +171,23 @@ public class CtSym {
}
/**
- * @param releaseInHex
- * major JDK version segment as hex number (8, 9, A, etc)
+ * @param releaseCode
+ * major JDK version segment as version code (8, 9, A, etc)
* @return set with all root paths related to given release in ct.sym file
*/
- public List<Path> releaseRoots(String releaseInHex) {
- List<Path> list = this.releaseRootPaths.computeIfAbsent(releaseInHex, x -> {
+ public List<Path> releaseRoots(String releaseCode) {
+ List<Path> list = this.releaseRootPaths.computeIfAbsent(releaseCode, x -> {
List<Path> rootDirs = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(this.root)) {
for (final Path subdir : stream) {
String rel = subdir.getFileName().toString();
if (rel.contains("-")) { //$NON-NLS-1$
- // Ignore META-INF etc. We are only interested in A-F 0-9
+ // Ignore META-INF etc. We are only interested in A-Z 0-9
continue;
}
- // Line below looks crazy. Latest with release 24 (hex 18)
- // we will find "8" release paths inside all release 24 related
- // directories and with release 26 (hex 1A) we will match "10" release
- // paths inside release 24 directories. I can't believe this is sane.
- // But looks like similar code is in
// com.sun.tools.javac.platform.JDKPlatformProvider.PlatformDescriptionImpl.getFileManager()
// https://github.com/openjdk/jdk/blob/master/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java
- if (rel.contains(releaseInHex)) {
+ if (rel.contains(releaseCode)) {
rootDirs.add(subdir);
} else {
continue;
@@ -212,21 +212,21 @@ public class CtSym {
* <p>
* java/io/Reader.sig -> /8769/java/io/Reader.sig
*
- * @param releaseInHex release number in hex
+ * @param releaseCode release number encoded (7,8,9,A,B...)
* @param qualifiedSignatureFileName signature file name (without module)
* @param moduleName
* @return corresponding path in ct.sym file system or null if not found
*/
- public Path getFullPath(String releaseInHex, String qualifiedSignatureFileName, String moduleName) {
+ public Path getFullPath(String releaseCode, String qualifiedSignatureFileName, String moduleName) {
String sep = this.fs.getSeparator();
if (DISABLE_CACHE) {
- List<Path> releaseRoots = releaseRoots(releaseInHex);
+ List<Path> releaseRoots = releaseRoots(releaseCode);
for (Path rroot : releaseRoots) {
// Calculate file path
Path p = null;
if (isJRE12Plus()) {
if (moduleName == null) {
- moduleName = getModuleInJre12plus(releaseInHex, qualifiedSignatureFileName);
+ moduleName = getModuleInJre12plus(releaseCode, qualifiedSignatureFileName);
}
p = rroot.resolve(moduleName + sep + qualifiedSignatureFileName);
} else {
@@ -246,14 +246,14 @@ public class CtSym {
}
return null;
}
- Map<String, Path> releasePaths = getCachedReleasePaths(releaseInHex);
+ Map<String, Path> releasePaths = getCachedReleasePaths(releaseCode);
Path path;
if(moduleName != null) {
// Without this, org.eclipse.jdt.core.tests.model.ModuleBuilderTests.testConvertToModule() fails on 12+ JRE
path = releasePaths.get(moduleName + sep + qualifiedSignatureFileName);
// Special handling of broken module shema in java 11 for compilation with --release 10
- if(path == null && !this.isJRE12Plus() && "A".equals(releaseInHex)){ //$NON-NLS-1$
+ if(path == null && !this.isJRE12Plus() && "A".equals(releaseCode)){ //$NON-NLS-1$
path = releasePaths.get(qualifiedSignatureFileName);
}
} else {
@@ -269,11 +269,11 @@ public class CtSym {
return path;
}
- private String getModuleInJre12plus(String releaseInHex, String qualifiedSignatureFileName) {
+ private String getModuleInJre12plus(String releaseCode, String qualifiedSignatureFileName) {
if (DISABLE_CACHE) {
- return findModuleForFileInJre12plus(releaseInHex, qualifiedSignatureFileName);
+ return findModuleForFileInJre12plus(releaseCode, qualifiedSignatureFileName);
}
- Map<String, Path> releasePaths = getCachedReleasePaths(releaseInHex);
+ Map<String, Path> releasePaths = getCachedReleasePaths(releaseCode);
Path path = releasePaths.get(qualifiedSignatureFileName);
if (path != null && path.getNameCount() > 2) {
// First segment is release, second: module
@@ -282,8 +282,8 @@ public class CtSym {
return null;
}
- private String findModuleForFileInJre12plus(String releaseInHex, String qualifiedSignatureFileName) {
- for (Path rroot : releaseRoots(releaseInHex)) {
+ private String findModuleForFileInJre12plus(String releaseCode, String qualifiedSignatureFileName) {
+ for (Path rroot : releaseRoots(releaseCode)) {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(rroot)) {
for (final Path subdir : stream) {
Path p = subdir.resolve(qualifiedSignatureFileName);
@@ -313,9 +313,9 @@ public class CtSym {
* <p>
* before 12: javax/net/ssl/SSLSocketFactory.sig -> /89ABC/java.base/javax/net/ssl/SSLSocketFactory.sig
*/
- private Map<String, Path> getCachedReleasePaths(String releaseInHex) {
- Map<String, Path> result = this.allReleasesPaths.computeIfAbsent(releaseInHex, x -> {
- List<Path> roots = releaseRoots(releaseInHex);
+ private Map<String, Path> getCachedReleasePaths(String releaseCode) {
+ Map<String, Path> result = this.allReleasesPaths.computeIfAbsent(releaseCode, x -> {
+ List<Path> roots = releaseRoots(releaseCode);
Map<String, Path> allReleaseFiles = new HashMap<>(4999);
for (Path start : roots) {
try {
@@ -361,17 +361,18 @@ public class CtSym {
}
private boolean isCurrentRelease12plus() throws IOException {
- try (DirectoryStream<Path> stream = Files.newDirectoryStream(this.root)) {
+ // ignore everything that is not one character (Java release code is one character plus separator)
+ try (DirectoryStream<Path> stream = Files.newDirectoryStream(this.root, p -> p.toString().length() == 2)) {
for (final Path subdir : stream) {
String rel = JRTUtil.sanitizedFileName(subdir);
- if (rel.contains("-")) { //$NON-NLS-1$
+ if (rel.length() != 1) {
continue;
}
try {
- int version = Integer.parseInt(rel, 16);
+ char releaseCode = rel.charAt(0);
// If a release directory contains "system-modules" file, it is a flag
// that this is the *current* release
- if (version > 11 && Files.exists(this.fs.getPath(rel, "system-modules"))) { //$NON-NLS-1$
+ if (releaseCode > JAVA_11 && Files.exists(this.fs.getPath(rel, "system-modules"))) { //$NON-NLS-1$
return true;
}
} catch (NumberFormatException e) {
@@ -409,4 +410,24 @@ public class CtSym {
sb.append("]"); //$NON-NLS-1$
return sb.toString();
}
+
+ /**
+ * Tries to translate numeric Java version to the corresponding release "code".
+ * <ul>
+ * <li>7, 8 and 9 are just returned "as is"
+ * <li>versions up from 10 are returned as upper letters starting with "A", so 10 is "A", 11 is "B" and so on.
+ * </ul>
+ *
+ * @param release
+ * release version as number (8, 9, 10, ...)
+ * @return the "code" used by ct.sym for given Java version
+ */
+ public static String getReleaseCode(String release) {
+ int numericVersion = Integer.parseInt(release);
+ if(numericVersion < 10) {
+ return String.valueOf(numericVersion);
+ }
+ return String.valueOf((char) ('A' + (numericVersion - 10)));
+ }
+
} \ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
index 789ec9e0ff..58e0d5b409 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
@@ -231,7 +231,6 @@ public class JRTUtil {
class JrtFileSystemWithOlderRelease extends JrtFileSystem {
final String release;
- String releaseInHex;
private List<Path> releaseRoots = Collections.emptyList();
protected Path modulePath;
private CtSym ctSym;
@@ -259,14 +258,14 @@ class JrtFileSystemWithOlderRelease extends JrtFileSystem {
private void initialize(File jdk, String rel) throws IOException {
super.initialize(jdk);
this.fs = null;// reset and proceed, TODO: this is crude and need to be removed.
- this.releaseInHex = Integer.toHexString(Integer.parseInt(this.release)).toUpperCase();
+ String releaseCode = CtSym.getReleaseCode(this.release);
this.ctSym = JRTUtil.getCtSym(Paths.get(this.jdkHome));
this.fs = this.ctSym.getFs();
- if (!Files.exists(this.fs.getPath(this.releaseInHex))
- || Files.exists(this.fs.getPath(this.releaseInHex, "system-modules"))) { //$NON-NLS-1$
+ if (!Files.exists(this.fs.getPath(releaseCode))
+ || Files.exists(this.fs.getPath(releaseCode, "system-modules"))) { //$NON-NLS-1$
this.fs = null;
}
- this.releaseRoots = this.ctSym.releaseRoots(this.releaseInHex);
+ this.releaseRoots = this.ctSym.releaseRoots(releaseCode);
}
@Override
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java
index 8384bf4978..58adc80954 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java
@@ -49,7 +49,7 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
static String MODULE_INFO = "module-info.sig"; //$NON-NLS-1$
final String release;
- String releaseInHex;
+ String releaseCode;
/**
* Null for releases without ct.sym file or for releases matching current one
*/
@@ -106,25 +106,24 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
* @see CtSym
*/
protected void initialize() throws CoreException {
- this.releaseInHex = Integer.toHexString(Integer.parseInt(this.release)).toUpperCase();
+ this.releaseCode = CtSym.getReleaseCode(this.release);
this.fs = this.ctSym.getFs();
this.releasePath = this.ctSym.getRoot();
- Path modPath = this.fs.getPath(this.releaseInHex + (this.ctSym.isJRE12Plus() ? "" : "-modules")); //$NON-NLS-1$ //$NON-NLS-2$
+ Path modPath = this.fs.getPath(this.releaseCode + (this.ctSym.isJRE12Plus() ? "" : "-modules")); //$NON-NLS-1$ //$NON-NLS-2$
if (Files.exists(modPath)) {
this.modulePath = modPath;
this.modPathString = this.zipFilename + "|"+ modPath.toString(); //$NON-NLS-1$
}
- if (!Files.exists(this.releasePath.resolve(this.releaseInHex))) {
+ if (!Files.exists(this.releasePath.resolve(this.releaseCode))) {
Exception e = new IllegalArgumentException("release " + this.release + " is not found in the system"); //$NON-NLS-1$//$NON-NLS-2$
throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, e.getMessage(), e));
}
- if (Files.exists(this.fs.getPath(this.releaseInHex, "system-modules"))) { //$NON-NLS-1$
+ if (Files.exists(this.fs.getPath(this.releaseCode, "system-modules"))) { //$NON-NLS-1$
this.fs = null; // Fallback to default version, all classes are on jrt fs, not here.
}
}
-
HashMap<String, SimpleSet> findPackagesInModules() {
// In JDK 11 and before, classes are not listed under their respective modules
// Hence, we simply go to the default module system for package-module mapping
@@ -181,7 +180,7 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
}
HashMap<String, IModule> cache = ModulesCache.get(this.modPathString);
if (cache == null) {
- List<Path> releaseRoots = this.ctSym.releaseRoots(this.releaseInHex);
+ List<Path> releaseRoots = this.ctSym.releaseRoots(this.releaseCode);
for (Path root : releaseRoots) {
try {
Files.walkFileTree(root, Collections.EMPTY_SET, 2, new FileVisitor<java.nio.file.Path>() {
@@ -238,7 +237,7 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
if (!isPackage(qualifiedPackageName, moduleName)) {
return null; // most common case
}
- List<Path> releaseRoots = this.ctSym.releaseRoots(this.releaseInHex);
+ List<Path> releaseRoots = this.ctSym.releaseRoots(this.releaseCode);
try {
IBinaryType reader = null;
byte[] content = null;
@@ -246,7 +245,7 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
if (!releaseRoots.isEmpty()) {
qualifiedBinaryFileName = qualifiedBinaryFileName.replace(".class", ".sig"); //$NON-NLS-1$ //$NON-NLS-2$
- Path fullPath = this.ctSym.getFullPath(this.releaseInHex, qualifiedBinaryFileName, moduleName);
+ Path fullPath = this.ctSym.getFullPath(this.releaseCode, qualifiedBinaryFileName, moduleName);
// If file is known, read it from ct.sym
if (fullPath != null) {
content = this.ctSym.getFileBytes(fullPath);

Back to the top