diff --git a/tools/sigtest/pom.xml b/tools/sigtest/pom.xml
index 12e88c22a..8fe760dd5 100644
--- a/tools/sigtest/pom.xml
+++ b/tools/sigtest/pom.xml
@@ -27,26 +27,40 @@
UTF-8
${java.home}/lib/ct.sym
+
+ 11
+
+ 17
+ ${maven.compiler.testRelease}
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ 3.4.1
+
+
+ enforce-java-version
+
+ enforce
+
+
+
+
+ To build this project JDK ${jdk.min.version} (or greater) is required.
+ ${jdk.min.version}
+
+
+
+
+
+
org.apache.maven.plugins
maven-compiler-plugin
- 3.8.1
-
-
- org.frgaal
- compiler-maven-plugin
- 21.0.0
-
-
+ 3.12.1
- frgaal
-
- 1.8
- 15
- 15
-Xlint:deprecation
@@ -214,12 +228,6 @@
3.9.6
jar
-
- org.frgaal
- compiler
- 21.0.0
- test
-
org.netbeans.tools
ct-sym
diff --git a/tools/sigtest/src/main/java/com/sun/tdk/signaturetest/classpath/Release.java b/tools/sigtest/src/main/java/com/sun/tdk/signaturetest/classpath/Release.java
index c623e6031..e6fd39651 100644
--- a/tools/sigtest/src/main/java/com/sun/tdk/signaturetest/classpath/Release.java
+++ b/tools/sigtest/src/main/java/com/sun/tdk/signaturetest/classpath/Release.java
@@ -4,20 +4,34 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
public final class Release {
- public static final Release BOOT_CLASS_PATH = new Release('0', null);
+ public static final Release BOOT_CLASS_PATH = new Release('0', null, null);
private final char version;
+ private final FileSystem zipFs;
private final String[] prefixes;
- private Release(char version, String... prefixes) {
+ private Release(char version, FileSystem zipFs, String... prefixes) {
this.version = version;
- this.prefixes = prefixes;
+ this.zipFs = zipFs;
+ this.prefixes =prefixes;
}
/**
@@ -39,8 +53,31 @@ InputStream findClass(String name) {
return ClassLoader.getSystemClassLoader().getResourceAsStream(resourceName);
} else {
for (String p : prefixes) {
- final String resourceName = "/META-INF/sigtest/" + p + "/" + name.replace('.', '/') + ".sig";
- InputStream is = Release.class.getResourceAsStream(resourceName);
+ InputStream is = null;
+ // We're using the local ct.sym file
+ if (zipFs != null) {
+ if (p.endsWith("system-modules")) {
+ // The current release does not container sig files we need to just return the class resource
+ // from our current class path.
+ final String resourceName = name.replace('.', '/') + ".class";
+ return ClassLoader.getSystemClassLoader().getResourceAsStream(resourceName);
+ }
+ try {
+ // Look for the signature file in the ct.sym archive.
+ final Path sigFile = zipFs.getPath(p + "/" + name.replace('.', '/') + ".sig");
+ if (Files.exists(sigFile)) {
+ is = Files.newInputStream(sigFile);
+ }
+ } catch (IOException e) {
+ // This is unlikely, but it seems we should fail early on this as an indicator to what might
+ // be wrong.
+ throw new UncheckedIOException(e);
+ }
+ } else {
+ // Attempt to use signature files that may be on the class path
+ final String resourceName = "/META-INF/sigtest/" + p + "/" + name.replace('.', '/') + ".sig";
+ is = Release.class.getResourceAsStream(resourceName);
+ }
if (is != null) {
return is;
}
@@ -53,18 +90,67 @@ InputStream findClass(String name) {
private static final Map RELEASES;
static {
List lines = new ArrayList<>();
- try {
- try (BufferedReader r = new BufferedReader(new InputStreamReader(Release.class.getResourceAsStream("/META-INF/sigtest.ls")))) {
- for (;;) {
- String l = r.readLine();
- if (l == null) {
- break;
+ final FileSystem zipFs;
+ final Path ctSym = Paths.get(System.getProperty("java.home"), "lib", "ct.sym");
+ // If the ct.sym file exists, use it. This is useful when testing with a JVM which is newer than the used to
+ // create the library that embeds the signature files.
+ if (Files.exists(ctSym)) {
+ try {
+ zipFs = zipFs(ctSym);
+ // We need to shut down the FileSystem. This is not ideal in some environments, but it's better than
+ // leaving resources open.
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ try {
+ zipFs.close();
+ } catch (IOException ignore) {
+ }
+ }));
+ // Walk the root of the ZIP file to build the prefixes. This is akin to what
+ // org.netbeans.apitest.ListCtSym does.
+ Files.walkFileTree(zipFs.getPath("/"), Set.of(), 2, new SimpleFileVisitor<>() {
+ private String prefix;
+
+ @Override
+ public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) {
+ prefix = dir.getFileName() == null ? null : dir.getFileName().toString();
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) {
+ final String fileName = file.getFileName().toString();
+ String newPrefix = prefix == null ? fileName : prefix + "/" + fileName;
+ if (prefix != null) {
+ lines.add(newPrefix);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) {
+ prefix = null;
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ } catch (IOException e) {
+ throw new InternalError(e);
+ }
+ } else {
+ // The ct.sym file does not exist. Use the sigtest.ls file which should be on the class path
+ zipFs = null;
+ try {
+ try (BufferedReader r = new BufferedReader(new InputStreamReader(Release.class.getResourceAsStream("/META-INF/sigtest.ls")))) {
+ for (; ; ) {
+ String l = r.readLine();
+ if (l == null) {
+ break;
+ }
+ lines.add(l);
}
- lines.add(l);
}
+ } catch (IOException ex) {
+ throw new InternalError(ex);
}
- } catch (IOException ex) {
- throw new InternalError(ex);
}
Map> prefixes = new HashMap<>();
@@ -86,9 +172,19 @@ InputStream findClass(String name) {
for (Map.Entry> entry : prefixes.entrySet()) {
Character key = entry.getKey();
List value = entry.getValue();
- releases.put(key, new Release(key, value.toArray(new String[0])));
+ releases.put(key, new Release(key, zipFs, value.toArray(new String[0])));
}
RELEASES = releases;
}
+
+ private static FileSystem zipFs(final Path path) throws IOException {
+ // locate file system by using the syntax defined in java.net.JarURLConnection
+ URI uri = URI.create("jar:" + path.toUri());
+ try {
+ return FileSystems.getFileSystem(uri);
+ } catch (FileSystemNotFoundException ignore) {
+ }
+ return FileSystems.newFileSystem(uri, Map.of());
+ }
}
diff --git a/tools/sigtest/src/test/java/com/sun/tdk/signaturetest/classpath/ReleaseTest.java b/tools/sigtest/src/test/java/com/sun/tdk/signaturetest/classpath/ReleaseTest.java
index cd12a960a..ec08d501a 100644
--- a/tools/sigtest/src/test/java/com/sun/tdk/signaturetest/classpath/ReleaseTest.java
+++ b/tools/sigtest/src/test/java/com/sun/tdk/signaturetest/classpath/ReleaseTest.java
@@ -92,6 +92,18 @@ public void testFindJDK15() throws ClassNotFoundException {
assertMethods(deprecatedClass, "forRemoval", "since");
}
+ @Test
+ public void testFindJDK17() throws ClassNotFoundException {
+ Release jdk17 = Release.find(17);
+ assertNotNull(jdk17.findClass("java.lang.Object"));
+ assertNotNull(jdk17.findClass("java.lang.Module"));
+ assertNotNull(jdk17.findClass("java.lang.Record"));
+ assertNotNull(jdk17.findClass("java.util.random.RandomGeneratorFactory"));
+ BinaryClassDescrLoader loader = new BinaryClassDescrLoader(new ClasspathImpl(jdk17, null), 4096);
+ ClassDescription deprecatedClass = loader.load("java.lang.Deprecated");
+ assertMethods(deprecatedClass, "forRemoval", "since");
+ }
+
private void assertMethods(ClassDescription deprecatedClass, String... names) {
MethodDescr[] arr = deprecatedClass.getDeclaredMethods();
assertEquals("Same number of methods: " + Arrays.toString(arr), names.length, arr.length);