langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java
changeset 41164 69167c89e68f
parent 38530 8e89d567748c
child 41442 14db641d4a9f
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java	Mon Sep 26 13:18:11 2016 -0700
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java	Mon Sep 26 13:39:50 2016 -0700
@@ -29,6 +29,8 @@
 import com.sun.tools.classfile.ConstantPoolException;
 import com.sun.tools.classfile.Dependencies.ClassFileError;
 
+import jdk.internal.util.jar.VersionedStream;
+
 import java.io.Closeable;
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -50,6 +52,7 @@
 import java.util.jar.JarFile;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+import java.util.zip.ZipFile;
 
 /**
  * ClassFileReader reads ClassFile(s) of a given path that can be
@@ -60,6 +63,13 @@
      * Returns a ClassFileReader instance of a given path.
      */
     public static ClassFileReader newInstance(Path path) throws IOException {
+        return newInstance(path, JarFile.baseVersion());
+    }
+
+    /**
+     * Returns a ClassFileReader instance of a given path.
+     */
+    public static ClassFileReader newInstance(Path path, Runtime.Version version) throws IOException {
         if (Files.notExists(path)) {
             throw new FileNotFoundException(path.toString());
         }
@@ -67,20 +77,13 @@
         if (Files.isDirectory(path)) {
             return new DirectoryReader(path);
         } else if (path.getFileName().toString().endsWith(".jar")) {
-            return new JarFileReader(path);
+            return new JarFileReader(path, version);
         } else {
             return new ClassFileReader(path);
         }
     }
 
     /**
-     * Returns a ClassFileReader instance of a given JarFile.
-     */
-    public static ClassFileReader newInstance(Path path, JarFile jf) throws IOException {
-        return new JarFileReader(path, jf);
-    }
-
-    /**
      * Returns a ClassFileReader instance of a given FileSystem and path.
      *
      * This method is used for reading classes from jrtfs.
@@ -302,13 +305,16 @@
 
     static class JarFileReader extends ClassFileReader {
         private final JarFile jarfile;
-        JarFileReader(Path path) throws IOException {
-            this(path, new JarFile(path.toFile(), false));
+        private final Runtime.Version version;
+
+        JarFileReader(Path path, Runtime.Version version) throws IOException {
+            this(path, openJarFile(path.toFile(), version), version);
         }
 
-        JarFileReader(Path path, JarFile jf) throws IOException {
+        JarFileReader(Path path, JarFile jf, Runtime.Version version) throws IOException {
             super(path);
             this.jarfile = jf;
+            this.version = version;
         }
 
         @Override
@@ -316,9 +322,26 @@
             jarfile.close();
         }
 
+        private static JarFile openJarFile(File f, Runtime.Version version)
+                throws IOException {
+            JarFile jf;
+            if (version == null) {
+                jf = new JarFile(f, false);
+                if (jf.isMultiRelease()) {
+                    throw new MultiReleaseException("err.multirelease.option.notfound", f.getName());
+                }
+            } else {
+                jf = new JarFile(f, false, ZipFile.OPEN_READ, version);
+                if (!jf.isMultiRelease()) {
+                    throw new MultiReleaseException("err.multirelease.option.exists", f.getName());
+                }
+            }
+            return jf;
+        }
+
         protected Set<String> scan() {
-            try (JarFile jf = new JarFile(path.toFile())) {
-                return jf.stream().map(JarEntry::getName)
+            try (JarFile jf = openJarFile(path.toFile(), version)) {
+                return VersionedStream.stream(jf).map(JarEntry::getName)
                          .filter(n -> n.endsWith(".class"))
                          .collect(Collectors.toSet());
             } catch (IOException e) {
@@ -348,15 +371,14 @@
         }
 
         protected ClassFile readClassFile(JarFile jarfile, JarEntry e) throws IOException {
-            InputStream is = null;
-            try {
-                is = jarfile.getInputStream(e);
-                return ClassFile.read(is);
+            try (InputStream is = jarfile.getInputStream(e)) {
+                ClassFile cf = ClassFile.read(is);
+                if (jarfile.isMultiRelease()) {
+                    VersionHelper.add(jarfile, e, cf);
+                }
+                return cf;
             } catch (ConstantPoolException ex) {
                 throw new ClassFileError(ex);
-            } finally {
-                if (is != null)
-                    is.close();
             }
         }
 
@@ -370,6 +392,21 @@
         }
     }
 
+    Enumeration<JarEntry> versionedEntries(JarFile jf) {
+        Iterator<JarEntry> it = VersionedStream.stream(jf).iterator();
+        return new Enumeration<>() {
+            @Override
+            public boolean hasMoreElements() {
+                return it.hasNext();
+            }
+
+            @Override
+            public JarEntry nextElement() {
+                return it.next();
+            }
+        };
+    }
+
     class JarFileIterator implements Iterator<ClassFile> {
         protected final JarFileReader reader;
         protected Enumeration<JarEntry> entries;
@@ -388,7 +425,7 @@
             if (jarfile == null) return;
 
             this.jf = jarfile;
-            this.entries = jf.entries();
+            this.entries = versionedEntries(jf);
             this.nextEntry = nextEntry();
         }