test/sun/reflect/CallerSensitive/CallerSensitiveFinder.java

Print this page

        

@@ -24,24 +24,26 @@
 import com.sun.tools.classfile.*;
 import com.sun.tools.jdeps.ClassFileReader;
 import static com.sun.tools.classfile.ConstantPool.*;
 import java.io.File;
 import java.io.IOException;
-import java.nio.file.FileVisitResult;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
 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.Collections;
 import java.util.List;
-import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.FutureTask;
+import java.util.stream.Stream;
 
 /*
  * @test
  * @bug 8010117
  * @summary Verify if CallerSensitive methods are annotated with

@@ -50,12 +52,14 @@
  * @run main/othervm/timeout=900 CallerSensitiveFinder
  */
 public class CallerSensitiveFinder {
     private static int numThreads = 3;
     private static boolean verbose = false;
+    private final ExecutorService pool;
+
     public static void main(String[] args) throws Exception {
-        List<Path> classes = new ArrayList<>();
+        Stream<Path> classes = null;
         String testclasses = System.getProperty("test.classes", ".");
         int i = 0;
         while (i < args.length) {
             String arg = args[i++];
             if (arg.equals("-v")) {

@@ -63,29 +67,34 @@
             } else {
                 Path p = Paths.get(testclasses, arg);
                 if (!p.toFile().exists()) {
                     throw new IllegalArgumentException(arg + " does not exist");
                 }
-                classes.add(p);
+                classes = Stream.of(p);
             }
         }
-        if (classes.isEmpty()) {
-            classes.addAll(PlatformClassPath.getJREClasses());
+
+        if (classes == null) {
+            classes = getPlatformClasses();
         }
-        CallerSensitiveFinder csfinder = new CallerSensitiveFinder();
 
+        CallerSensitiveFinder csfinder = new CallerSensitiveFinder();
         List<String> errors = csfinder.run(classes);
+
         if (!errors.isEmpty()) {
             throw new RuntimeException(errors.size() +
                     " caller-sensitive methods are missing @CallerSensitive annotation");
         }
     }
 
-    private final List<String> csMethodsMissingAnnotation = new ArrayList<>();
+    private final List<String> csMethodsMissingAnnotation =
+            Collections.synchronizedList(new ArrayList<>());
     private final ReferenceFinder finder;
     public CallerSensitiveFinder() {
         this.finder = new ReferenceFinder(getFilter(), getVisitor());
+        pool = Executors.newFixedThreadPool(numThreads);
+
     }
 
     private ReferenceFinder.Filter getFilter() {
         final String classname = "sun/reflect/Reflection";
         final String method = "getCallerClass";

@@ -121,28 +130,35 @@
                 }
             }
         };
     }
 
-    public List<String> run(List<Path> classes) throws IOException, InterruptedException,
+    public List<String> run(Stream<Path> classes)throws IOException, InterruptedException,
             ExecutionException, ConstantPoolException
     {
-        ExecutorService pool = Executors.newFixedThreadPool(numThreads);
-        for (Path path : classes) {
+        classes.forEach(this::processPath);
+        waitForCompletion();
+        pool.shutdown();
+        return csMethodsMissingAnnotation;
+    }
+
+    void processPath(Path path) {
+        try {
             ClassFileReader reader = ClassFileReader.newInstance(path);
             for (ClassFile cf : reader.getClassFiles()) {
                 String classFileName = cf.getName();
                 // for each ClassFile
                 //    parse constant pool to find matching method refs
                 //      parse each method (caller)
                 //      - visit and find method references matching the given method name
                 pool.submit(getTask(cf));
             }
+        } catch (IOException x) {
+            throw new UncheckedIOException(x);
+        } catch (ConstantPoolException x) {
+            throw new RuntimeException(x);
         }
-        waitForCompletion();
-        pool.shutdown();
-        return csMethodsMissingAnnotation;
     }
 
     private static final String CALLER_SENSITIVE_ANNOTATION = "Lsun/reflect/CallerSensitive;";
     private static boolean isCallerSensitive(Method m, ConstantPool cp)
             throws ConstantPoolException

@@ -176,63 +192,41 @@
 
     private void waitForCompletion() throws InterruptedException, ExecutionException {
         for (FutureTask<Void> t : tasks) {
             t.get();
         }
+        if (tasks.isEmpty()) {
+            throw new RuntimeException("No classes found, or specified.");
+        }
         System.out.println("Parsed " + tasks.size() + " classfiles");
     }
 
-    static class PlatformClassPath {
-        static List<Path> getJREClasses() throws IOException {
+    static Stream<Path> getPlatformClasses() throws IOException {
             List<Path> result = new ArrayList<Path>();
             Path home = Paths.get(System.getProperty("java.home"));
 
-            if (home.endsWith("jre")) {
-                // jar files in <javahome>/jre/lib
-                // skip <javahome>/lib
-                result.addAll(addJarFiles(home.resolve("lib")));
-            } else if (home.resolve("lib").toFile().exists()) {
-                // either a JRE or a jdk build image
-                File classes = home.resolve("classes").toFile();
-                if (classes.exists() && classes.isDirectory()) {
-                    // jdk build outputdir
-                    result.add(classes.toPath());
+        if (home.resolve("lib").toFile().exists()) {
+            // either an exploded build or an image
+            File classes = home.resolve("modules").toFile();
+            if (classes.isDirectory()) {
+                return Stream.of(classes.toPath());
+            } else {
+                return JrtPaths();
                 }
-                // add other JAR files
-                result.addAll(addJarFiles(home.resolve("lib")));
             } else {
                 throw new RuntimeException("\"" + home + "\" not a JDK home");
             }
-            return result;
         }
 
-        static List<Path> addJarFiles(final Path root) throws IOException {
-            final List<Path> result = new ArrayList<Path>();
-            final Path ext = root.resolve("ext");
-            Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
-                @Override
-                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
-                        throws IOException {
-                    if (dir.equals(root) || dir.equals(ext)) {
-                        return FileVisitResult.CONTINUE;
-                    } else {
-                        // skip other cobundled JAR files
-                        return FileVisitResult.SKIP_SUBTREE;
-                    }
-                }
+    static Stream<Path> JrtPaths() {
+        FileSystem jrt = FileSystems.getFileSystem(URI.create("jrt:/"));
+        Path root = jrt.getPath("/");
 
-                @Override
-                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
-                        throws IOException {
-                    File f = file.toFile();
-                    String fn = f.getName();
-                    // parse alt-rt.jar as well
-                    if (fn.endsWith(".jar") && !fn.equals("jfxrt.jar")) {
-                        result.add(file);
-                    }
-                    return FileVisitResult.CONTINUE;
-                }
-            });
-            return result;
+        try {
+            return Files.walk(root)
+                    .filter(p -> p.getNameCount() > 1)
+                    .filter(p -> p.toString().endsWith(".class"));
+        } catch (IOException x) {
+            throw new UncheckedIOException(x);
         }
     }
 }