changeset 10877:0558a0be5539

Update rmic to work a modular image Contributed-by: sundararajan.athijegannathan@oracle.com
author alanb
date Fri, 24 Oct 2014 13:38:40 +0100
parents 36e40a1f2a61
children 48c2ee51c271
files src/java.base/share/classes/jdk/internal/jimage/ImageReader.java src/jdk.rmic/share/classes/sun/rmi/rmic/BatchEnvironment.java src/jdk.rmic/share/classes/sun/rmi/rmic/RMIGenerator.java src/jdk.rmic/share/classes/sun/tools/java/ClassFile.java src/jdk.rmic/share/classes/sun/tools/java/ClassPath.java src/jdk.rmic/share/classes/sun/tools/java/FileClassFile.java src/jdk.rmic/share/classes/sun/tools/java/PathClassFile.java src/jdk.rmic/share/classes/sun/tools/java/ZipClassFile.java src/jdk.rmic/share/classes/sun/tools/javac/BatchEnvironment.java src/jdk.rmic/share/classes/sun/tools/javac/Main.java
diffstat 10 files changed, 589 insertions(+), 176 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java	Thu Oct 23 19:43:05 2014 +0100
+++ b/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java	Fri Oct 24 13:38:40 2014 +0100
@@ -387,6 +387,8 @@
         Directory top = (Directory) nodes.get(name);
         if (top == null) {
             top = newDirectory(rootDir, name);
+            // support trailing '/' directory name as well
+            nodes.put(parent.substring(0, idx+1), top);
         }
         Directory last = top;
         while ((idx = parent.indexOf('/', idx + 1)) != -1) {
@@ -394,6 +396,8 @@
             Directory nextDir = (Directory) nodes.get(name);
             if (nextDir == null) {
                 nextDir = newDirectory(last, name);
+                // support trailing '/' directory name as well
+                nodes.put(parent.substring(0, idx+1), nextDir);
             }
             last = nextDir;
         }
--- a/src/jdk.rmic/share/classes/sun/rmi/rmic/BatchEnvironment.java	Thu Oct 23 19:43:05 2014 +0100
+++ b/src/jdk.rmic/share/classes/sun/rmi/rmic/BatchEnvironment.java	Fri Oct 24 13:38:40 2014 +0100
@@ -389,7 +389,8 @@
                 /* File is an ordinay file  */
                 String arcname = file.toLowerCase();
                 if (! (arcname.endsWith(".zip") ||
-                       arcname.endsWith(".jar"))) {
+                       arcname.endsWith(".jar") ||
+                       arcname.endsWith(".jimage"))) {
                     /* File name don't have right extension */
 //                      if (warn)
 //                          log.warning(Position.NOPOS,
--- a/src/jdk.rmic/share/classes/sun/rmi/rmic/RMIGenerator.java	Thu Oct 23 19:43:05 2014 +0100
+++ b/src/jdk.rmic/share/classes/sun/rmi/rmic/RMIGenerator.java	Fri Oct 24 13:38:40 2014 +0100
@@ -140,7 +140,7 @@
             if (env.verbose()) {
                 env.output(Main.getText("rmic.wrote", stubFile.getPath()));
             }
-            env.parseFile(new ClassFile(stubFile));
+            env.parseFile(ClassFile.newClassFile(stubFile));
         } catch (IOException e) {
             env.error(0, "cant.write", stubFile.toString());
             return;
@@ -161,7 +161,7 @@
                     env.output(Main.getText("rmic.wrote",
                         skeletonFile.getPath()));
                 }
-                env.parseFile(new ClassFile(skeletonFile));
+                env.parseFile(ClassFile.newClassFile(skeletonFile));
             } catch (IOException e) {
                 env.error(0, "cant.write", stubFile.toString());
                 return;
--- a/src/jdk.rmic/share/classes/sun/tools/java/ClassFile.java	Thu Oct 23 19:43:05 2014 +0100
+++ b/src/jdk.rmic/share/classes/sun/tools/java/ClassFile.java	Fri Oct 24 13:38:40 2014 +0100
@@ -29,134 +29,93 @@
 import java.io.InputStream;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.zip.*;
 
 /**
- * This class is used to represent a file loaded from the class path, and
- * can either be a regular file or a zip file entry.
+ * Abstract class to represent a class file.
  *
  * WARNING: The contents of this source file are not part of any
  * supported API.  Code that depends on them does so at its own risk:
  * they are subject to change or removal without notice.
  */
 public
-class ClassFile {
-    /*
-     * Non-null if this represents a regular file
+abstract class ClassFile {
+    /**
+     * Factory method to create a ClassFile backed by a File.
+     *
+     * @param file a File object
+     * @return a new ClassFile
      */
-    private File file;
-
-    /*
-     * Non-null if this represents a zip file entry
-     */
-    private ZipFile zipFile;
-    private ZipEntry zipEntry;
-
-    /**
-     * Constructor for instance representing a regular file
-     */
-    public ClassFile(File file) {
-        this.file = file;
+    public static ClassFile newClassFile(File file) {
+        return new FileClassFile(file);
     }
 
     /**
-     * Constructor for instance representing a zip file entry
+     * Factory method to create a ClassFile backed by a ZipEntry.
+     *
+     * @param zf a ZipFile
+     * @param ze a ZipEntry within the zip file
+     * @return a new ClassFile
      */
-    public ClassFile(ZipFile zf, ZipEntry ze) {
-        this.zipFile = zf;
-        this.zipEntry = ze;
+    public static ClassFile newClassFile(ZipFile zf, ZipEntry ze) {
+        return new ZipClassFile(zf, ze);
+    }
+
+    /**
+     * Factory method to create a ClassFile backed by a nio Path.
+     *
+     * @param path nio Path object
+     * @return a new ClassFile
+     */
+    public static ClassFile newClassFile(Path path) {
+        return Files.exists(path)? new PathClassFile(path) : null;
     }
 
     /**
      * Returns true if this is zip file entry
      */
-    public boolean isZipped() {
-        return zipFile != null;
-    }
+    public abstract boolean isZipped();
 
     /**
      * Returns input stream to either regular file or zip file entry
      */
-    public InputStream getInputStream() throws IOException {
-        if (file != null) {
-            return new FileInputStream(file);
-        } else {
-            try {
-                return zipFile.getInputStream(zipEntry);
-            } catch (ZipException e) {
-                throw new IOException(e.getMessage());
-            }
-        }
-    }
+    public abstract InputStream getInputStream() throws IOException;
 
     /**
      * Returns true if file exists.
      */
-    public boolean exists() {
-        return file != null ? file.exists() : true;
-    }
+    public abstract boolean exists();
 
     /**
      * Returns true if this is a directory.
      */
-    public boolean isDirectory() {
-        return file != null ? file.isDirectory() :
-                              zipEntry.getName().endsWith("/");
-    }
+    public abstract boolean isDirectory();
 
     /**
      * Return last modification time
      */
-    public long lastModified() {
-        return file != null ? file.lastModified() : zipEntry.getTime();
-    }
+    public abstract long lastModified();
 
     /**
      * Get file path. The path for a zip file entry will also include
      * the zip file name.
      */
-    public String getPath() {
-        if (file != null) {
-            return file.getPath();
-        } else {
-            return zipFile.getName() + "(" + zipEntry.getName() + ")";
-        }
-    }
+    public abstract String getPath();
 
     /**
      * Get name of file entry excluding directory name
      */
-    public String getName() {
-        return file != null ? file.getName() : zipEntry.getName();
-    }
+    public abstract String getName();
 
-//JCOV
     /**
      * Get absolute name of file entry
      */
-    public String getAbsoluteName() {
-        String absoluteName;
-        if (file != null) {
-            try {
-                absoluteName = file.getCanonicalPath();
-            } catch (IOException e) {
-                absoluteName = file.getAbsolutePath();
-            }
-        } else {
-            absoluteName = zipFile.getName() + "(" + zipEntry.getName() + ")";
-        }
-        return absoluteName;
-    }
-// end JCOV
+    public abstract String getAbsoluteName();
 
     /**
      * Get length of file
      */
-    public long length() {
-        return file != null ? file.length() : zipEntry.getSize();
-    }
-
-    public String toString() {
-        return (file != null) ? file.toString() : zipEntry.toString();
-    }
+    public abstract long length();
 }
--- a/src/jdk.rmic/share/classes/sun/tools/java/ClassPath.java	Thu Oct 23 19:43:05 2014 +0100
+++ b/src/jdk.rmic/share/classes/sun/tools/java/ClassPath.java	Fri Oct 24 13:38:40 2014 +0100
@@ -25,11 +25,20 @@
 
 package sun.tools.java;
 
-import java.util.Enumeration;
-import java.util.Hashtable;
 import java.io.File;
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.util.zip.*;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.spi.FileSystemProvider;
 
 /**
  * This class is used to represent a class path, which can contain both
@@ -41,6 +50,38 @@
  */
 public
 class ClassPath {
+    private static final String JIMAGE_EXT = ".jimage";
+    private static boolean jimageSupportEnabled;
+    static {
+        jimageSupportEnabled = false;
+        for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
+            if (provider.getScheme().equalsIgnoreCase("jimage")) {
+                jimageSupportEnabled = true;
+                break;
+            }
+        }
+    }
+
+    private static void checkJImageSupport() {
+        if (! jimageSupportEnabled) {
+            throw new RuntimeException("jimage support not enabled");
+        }
+    }
+
+    private FileSystem getFileSystem(Path p) {
+        FileSystem fs = fileSystems.get(p);
+        if (fs == null) {
+            try {
+                fs = FileSystems.newFileSystem(p, null);
+                fileSystems.put(p, fs);
+            } catch (IOException ioExp) {
+                throw new UncheckedIOException(ioExp);
+            }
+        }
+        return fs;
+    }
+    private final Map<Path,FileSystem> fileSystems = new HashMap<>();
+
     static final char dirSeparator = File.pathSeparatorChar;
 
     /**
@@ -110,22 +151,26 @@
                 j = len;
             }
             if (i == j) {
-                path[n] = new ClassPathEntry();
-                path[n++].dir = new File(".");
+                path[n++] = new DirClassPathEntry(new File("."));
             } else {
-                File file = new File(pathstr.substring(i, j));
+                String filename = pathstr.substring(i, j);
+                File file = new File(filename);
                 if (file.isFile()) {
-                    try {
-                        ZipFile zip = new ZipFile(file);
-                        path[n] = new ClassPathEntry();
-                        path[n++].zip = zip;
-                    } catch (ZipException e) {
-                    } catch (IOException e) {
-                        // Ignore exceptions, at least for now...
+                    if (filename.endsWith(JIMAGE_EXT)) {
+                        checkJImageSupport();
+                        FileSystem fs = getFileSystem(file.toPath());
+                        path[n++] = new JImageClassPathEntry(fs);
+                    } else {
+                        try {
+                            ZipFile zip = new ZipFile(file);
+                            path[n++] = new ZipClassPathEntry(zip);
+                        } catch (ZipException e) {
+                        } catch (IOException e) {
+                            // Ignore exceptions, at least for now...
+                        }
                     }
                 } else {
-                    path[n] = new ClassPathEntry();
-                    path[n++].dir = file;
+                    path[n++] = new DirClassPathEntry(file);
                 }
             }
         }
@@ -153,17 +198,21 @@
         for (String name : patharray) {
             File file = new File(name);
             if (file.isFile()) {
-                try {
-                    ZipFile zip = new ZipFile(file);
-                    path[n] = new ClassPathEntry();
-                    path[n++].zip = zip;
-                } catch (ZipException e) {
-                } catch (IOException e) {
-                    // Ignore exceptions, at least for now...
-                }
+                if (name.endsWith(JIMAGE_EXT)) {
+                    checkJImageSupport();
+                    FileSystem fs = getFileSystem(file.toPath());
+                    path[n++] = new JImageClassPathEntry(fs);
+                } else {
+                    try {
+                        ZipFile zip = new ZipFile(file);
+                        path[n++] = new ZipClassPathEntry(zip);
+                    } catch (ZipException e) {
+                    } catch (IOException e) {
+                        // Ignore exceptions, at least for now...
+                    }
+               }
             } else {
-                path[n] = new ClassPathEntry();
-                path[n++].dir = file;
+                path[n++] = new DirClassPathEntry(file);
             }
         }
         // Trim class path to exact size
@@ -202,29 +251,9 @@
             name = subdir;      // Note: isDirectory==true & basename==""
         }
         for (int i = 0; i < path.length; i++) {
-            if (path[i].zip != null) {
-                String newname = name.replace(File.separatorChar, '/');
-                ZipEntry entry = path[i].zip.getEntry(newname);
-                if (entry != null) {
-                    return new ClassFile(path[i].zip, entry);
-                }
-            } else {
-                File file = new File(path[i].dir.getPath(), name);
-                String list[] = path[i].getFiles(subdir);
-                if (isDirectory) {
-                    if (list.length > 0) {
-                        return new ClassFile(file);
-                    }
-                } else {
-                    for (int j = 0; j < list.length; j++) {
-                        if (basename.equals(list[j])) {
-                            // Don't bother checking !file.isDir,
-                            // since we only look for names which
-                            // cannot already be packages (foo.java, etc).
-                            return new ClassFile(file);
-                        }
-                    }
-                }
+            ClassFile cf = path[i].getFile(name, subdir, basename, isDirectory);
+            if (cf != null) {
+                return cf;
             }
         }
         return null;
@@ -236,27 +265,7 @@
     public Enumeration<ClassFile> getFiles(String pkg, String ext) {
         Hashtable<String, ClassFile> files = new Hashtable<>();
         for (int i = path.length; --i >= 0; ) {
-            if (path[i].zip != null) {
-                Enumeration<? extends ZipEntry> e = path[i].zip.entries();
-                while (e.hasMoreElements()) {
-                    ZipEntry entry = (ZipEntry)e.nextElement();
-                    String name = entry.getName();
-                    name = name.replace('/', File.separatorChar);
-                    if (name.startsWith(pkg) && name.endsWith(ext)) {
-                        files.put(name, new ClassFile(path[i].zip, entry));
-                    }
-                }
-            } else {
-                String[] list = path[i].getFiles(pkg);
-                for (int j = 0; j < list.length; j++) {
-                    String name = list[j];
-                    if (name.endsWith(ext)) {
-                        name = pkg + File.separatorChar + name;
-                        File file = new File(path[i].dir.getPath(), name);
-                        files.put(name, new ClassFile(file));
-                    }
-                }
-            }
+            path[i].fillFiles(pkg, ext, files);
         }
         return files.elements();
     }
@@ -266,9 +275,7 @@
      */
     public void close() throws IOException {
         for (int i = path.length; --i >= 0; ) {
-            if (path[i].zip != null) {
-                path[i].zip.close();
-            }
+            path[i].close();
         }
     }
 
@@ -281,34 +288,146 @@
 }
 
 /**
- * A class path entry, which can either be a directory or an open zip file.
+ * A class path entry, which can either be a directory or an open zip file or an open jimage filesystem.
  */
-class ClassPathEntry {
-    File dir;
-    ZipFile zip;
+abstract class ClassPathEntry {
+    abstract ClassFile getFile(String name, String subdir, String basename, boolean isDirectory);
+    abstract void fillFiles(String pkg, String ext, Hashtable<String, ClassFile> files);
+    abstract void close() throws IOException;
+}
 
-    Hashtable<String, String[]> subdirs = new Hashtable<>(29); // cache of sub-directory listings:
-    String[] getFiles(String subdir) {
+// a ClassPathEntry that represents a directory
+final class DirClassPathEntry extends ClassPathEntry {
+    private final File dir;
+
+    DirClassPathEntry(File dir) {
+        this.dir = dir;
+    }
+
+    private final Hashtable<String, String[]> subdirs = new Hashtable<>(29); // cache of sub-directory listings:
+    private String[] getFiles(String subdir) {
         String files[] = subdirs.get(subdir);
         if (files == null) {
-            // search the directory, exactly once
-            File sd = new File(dir.getPath(), subdir);
-            if (sd.isDirectory()) {
-                files = sd.list();
-                if (files == null) {
-                    // should not happen, but just in case, fail silently
-                    files = new String[0];
-                }
-                if (files.length == 0) {
-                    String nonEmpty[] = { "" };
-                    files = nonEmpty;
-                }
-            } else {
-                files = new String[0];
-            }
+            files = computeFiles(subdir);
             subdirs.put(subdir, files);
         }
         return files;
     }
 
+    private String[] computeFiles(String subdir) {
+        File sd = new File(dir.getPath(), subdir);
+        String[] files = null;
+        if (sd.isDirectory()) {
+            files = sd.list();
+            if (files == null) {
+                // should not happen, but just in case, fail silently
+                files = new String[0];
+            }
+            if (files.length == 0) {
+                String nonEmpty[] = { "" };
+                files = nonEmpty;
+            }
+        } else {
+            files = new String[0];
+        }
+        return files;
+    }
+
+    ClassFile getFile(String name,  String subdir, String basename, boolean isDirectory) {
+        File file = new File(dir.getPath(), name);
+        String list[] = getFiles(subdir);
+        if (isDirectory) {
+            if (list.length > 0) {
+                return ClassFile.newClassFile(file);
+            }
+        } else {
+            for (int j = 0; j < list.length; j++) {
+                if (basename.equals(list[j])) {
+                    // Don't bother checking !file.isDir,
+                    // since we only look for names which
+                    // cannot already be packages (foo.java, etc).
+                    return ClassFile.newClassFile(file);
+                }
+            }
+        }
+        return null;
+    }
+
+    void fillFiles(String pkg, String ext, Hashtable<String, ClassFile> files) {
+        String[] list = getFiles(pkg);
+        for (int j = 0; j < list.length; j++) {
+            String name = list[j];
+            if (name.endsWith(ext)) {
+                name = pkg + File.separatorChar + name;
+                File file = new File(dir.getPath(), name);
+                files.put(name, ClassFile.newClassFile(file));
+            }
+        }
+    }
+
+    void close() throws IOException {
+    }
 }
+
+// a ClassPathEntry that represents a .zip or a .jar file
+final class ZipClassPathEntry extends ClassPathEntry {
+    private final ZipFile zip;
+
+    ZipClassPathEntry(ZipFile zip) {
+        this.zip = zip;
+    }
+
+    void close() throws IOException {
+        zip.close();
+    }
+
+    ClassFile getFile(String name, String subdir, String basename, boolean isDirectory) {
+        String newname = name.replace(File.separatorChar, '/');
+        ZipEntry entry = zip.getEntry(newname);
+        return entry != null? ClassFile.newClassFile(zip, entry) : null;
+    }
+
+    void fillFiles(String pkg, String ext, Hashtable<String, ClassFile> files) {
+        Enumeration<? extends ZipEntry> e = zip.entries();
+        while (e.hasMoreElements()) {
+            ZipEntry entry = (ZipEntry)e.nextElement();
+            String name = entry.getName();
+            name = name.replace('/', File.separatorChar);
+            if (name.startsWith(pkg) && name.endsWith(ext)) {
+                files.put(name, ClassFile.newClassFile(zip, entry));
+            }
+        }
+    }
+}
+
+// a ClassPathEntry that represents a .jimage module file
+final class JImageClassPathEntry extends ClassPathEntry {
+    private final FileSystem fs;
+
+    JImageClassPathEntry(FileSystem fs) {
+        this.fs = fs;
+    }
+
+    void close() throws IOException {
+        fs.close();
+    }
+
+    ClassFile getFile(String name, String subdir, String basename, boolean isDirectory) {
+        return ClassFile.newClassFile(fs.getPath(name));
+    }
+
+    void fillFiles(String pkg, String ext, Hashtable<String, ClassFile> files) {
+        Path dir = fs.getPath(pkg);
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
+            for (Path p : stream) {
+                String name = p.toString();
+                name = name.replace('/', File.separatorChar);
+                if (name.startsWith(pkg) && name.endsWith(ext)) {
+                    files.put(name, ClassFile.newClassFile(p));
+                }
+            }
+        } catch (IOException ioExp) {
+            throw new UncheckedIOException(ioExp);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.rmic/share/classes/sun/tools/java/FileClassFile.java	Fri Oct 24 13:38:40 2014 +0100
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.java;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * This class is used to represent a file loaded from the class path, and
+ * is a regular file.
+ *
+ * WARNING: The contents of this source file are not part of any
+ * supported API.  Code that depends on them does so at its own risk:
+ * they are subject to change or removal without notice.
+ */
+final
+class FileClassFile extends ClassFile {
+    private final File file;
+
+    /**
+     * Constructor for instance representing a regular file
+     */
+    public FileClassFile(File file) {
+        this.file = file;
+    }
+
+    @Override
+    public boolean isZipped() {
+        return false;
+    }
+
+    @Override
+    public InputStream getInputStream() throws IOException {
+        return new FileInputStream(file);
+    }
+
+    @Override
+    public boolean exists() {
+        return file.exists();
+    }
+
+    @Override
+    public boolean isDirectory() {
+        return file.isDirectory();
+    }
+
+    @Override
+    public long lastModified() {
+        return file.lastModified();
+    }
+
+    @Override
+    public String getPath() {
+        return file.getPath();
+    }
+
+    @Override
+    public String getName() {
+        return file.getName();
+    }
+
+//JCOV
+    @Override
+    public String getAbsoluteName() {
+        String absoluteName;
+        try {
+            absoluteName = file.getCanonicalPath();
+        } catch (IOException e) {
+            absoluteName = file.getAbsolutePath();
+        }
+        return absoluteName;
+    }
+// end JCOV
+
+    @Override
+    public long length() {
+        return file.length();
+    }
+
+    @Override
+    public String toString() {
+        return file.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.rmic/share/classes/sun/tools/java/PathClassFile.java	Fri Oct 24 13:38:40 2014 +0100
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.java;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * This class is used to represent a file loaded from the class path, and
+ * is represented by nio Path.
+ *
+ * WARNING: The contents of this source file are not part of any
+ * supported API.  Code that depends on them does so at its own risk:
+ * they are subject to change or removal without notice.
+ */
+final
+class PathClassFile extends ClassFile {
+    private final Path path;
+    private final BasicFileAttributes attrs;
+
+    /**
+     * Constructor for instance representing a Path
+     */
+    public PathClassFile(Path path) {
+        this.path = path;
+        try {
+            this.attrs = Files.readAttributes(path, BasicFileAttributes.class);
+        } catch (IOException ioExp) {
+            throw new UncheckedIOException(ioExp);
+        }
+    }
+
+    @Override
+    public boolean isZipped() {
+        return false;
+    }
+
+    @Override
+    public InputStream getInputStream() throws IOException {
+        return Files.newInputStream(path);
+    }
+
+    @Override
+    public boolean exists() {
+        return true;
+    }
+
+    @Override
+    public boolean isDirectory() {
+        return attrs.isDirectory();
+    }
+
+    @Override
+    public long lastModified() {
+        return attrs.lastModifiedTime().toMillis();
+    }
+
+    @Override
+    public String getPath() {
+        return path.toUri().toString();
+    }
+
+    @Override
+    public String getName() {
+        return path.getFileName().toString();
+    }
+
+//JCOV
+    @Override
+    public String getAbsoluteName() {
+        return path.toAbsolutePath().toUri().toString();
+    }
+// end JCOV
+
+    @Override
+    public long length() {
+        return attrs.size();
+    }
+
+    @Override
+    public String toString() {
+        return path.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.rmic/share/classes/sun/tools/java/ZipClassFile.java	Fri Oct 24 13:38:40 2014 +0100
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.java;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.zip.*;
+
+/**
+ * This class is used to represent a file loaded from the class path, and
+ * is a zip file entry.
+ *
+ * WARNING: The contents of this source file are not part of any
+ * supported API.  Code that depends on them does so at its own risk:
+ * they are subject to change or removal without notice.
+ */
+final
+class ZipClassFile extends ClassFile {
+    private final ZipFile zipFile;
+    private final ZipEntry zipEntry;
+
+    /**
+     * Constructor for instance representing a zip file entry
+     */
+    public ZipClassFile(ZipFile zf, ZipEntry ze) {
+        this.zipFile = zf;
+        this.zipEntry = ze;
+    }
+
+    @Override
+    public boolean isZipped() {
+        return true;
+    }
+
+    @Override
+    public InputStream getInputStream() throws IOException {
+        try {
+            return zipFile.getInputStream(zipEntry);
+        } catch (ZipException e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    @Override
+    public boolean exists() {
+        return true;
+    }
+
+    @Override
+    public boolean isDirectory() {
+        return zipEntry.getName().endsWith("/");
+    }
+
+    @Override
+    public long lastModified() {
+        return zipEntry.getTime();
+    }
+
+    @Override
+    public String getPath() {
+        return zipFile.getName() + "(" + zipEntry.getName() + ")";
+    }
+
+    @Override
+    public String getName() {
+        return zipEntry.getName();
+    }
+
+//JCOV
+    @Override
+    public String getAbsoluteName() {
+        return zipFile.getName() + "(" + zipEntry.getName() + ")";
+    }
+// end JCOV
+
+    @Override
+    public long length() {
+        return zipEntry.getSize();
+    }
+
+    @Override
+    public String toString() {
+        return zipEntry.toString();
+    }
+}
--- a/src/jdk.rmic/share/classes/sun/tools/javac/BatchEnvironment.java	Thu Oct 23 19:43:05 2014 +0100
+++ b/src/jdk.rmic/share/classes/sun/tools/javac/BatchEnvironment.java	Fri Oct 24 13:38:40 2014 +0100
@@ -718,7 +718,7 @@
 
                 // Couldn't find the source, try the one mentioned in the binary
                 if (bc.getSource() != null) {
-                    srcfile = new ClassFile(new File((String)bc.getSource()));
+                    srcfile = ClassFile.newClassFile(new File((String)bc.getSource()));
                     // Look for the source file
                     srcfile = pkg.getSourceFile(srcfile.getName());
                     if ((srcfile != null) && srcfile.exists()) {
@@ -863,7 +863,7 @@
                 }
                 if (srcfile == null) {
                     String fn = (String)c.getClassDefinition().getSource();
-                    srcfile = new ClassFile(new File(fn));
+                    srcfile = ClassFile.newClassFile(new File(fn));
                 }
             } else {
                 // Get a source file name from the package
--- a/src/jdk.rmic/share/classes/sun/tools/javac/Main.java	Thu Oct 23 19:43:05 2014 +0100
+++ b/src/jdk.rmic/share/classes/sun/tools/javac/Main.java	Fri Oct 24 13:38:40 2014 +0100
@@ -503,7 +503,7 @@
             for (Enumeration<String> e = v.elements() ; e.hasMoreElements() ;) {
                 File file = new File(e.nextElement());
                 try {
-                    env.parseFile(new ClassFile(file));
+                    env.parseFile(ClassFile.newClassFile(file));
                 } catch (FileNotFoundException ee) {
                     env.error(0, "cant.read", file.getPath());
                     exitStatus = EXIT_CMDERR;