8059976: Convert JavacFileManager to use java.nio.file internally
authorjjg
Mon, 07 Dec 2015 14:02:55 -0800
changeset 34560 b6a567b677f7
parent 34481 e0ff9821f1e8
child 34561 79c436257611
8059976: Convert JavacFileManager to use java.nio.file internally Reviewed-by: jlahoda
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileObject.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RegularFileObject.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipArchive.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndex.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndexCache.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java
langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java
langtools/test/tools/javac/6508981/TestInferBinaryName.java
langtools/test/tools/javac/T6358024.java
langtools/test/tools/javac/T6358166.java
langtools/test/tools/javac/T6705935.java
langtools/test/tools/javac/T6725036.java
langtools/test/tools/javac/api/6440528/T6440528.java
langtools/test/tools/javac/api/T6358955.java
langtools/test/tools/javac/api/T6838467.java
langtools/test/tools/javac/api/T6877206.java
langtools/test/tools/javac/file/zip/T8076104.java
langtools/test/tools/javac/options/modes/Tester.java
langtools/test/tools/javac/parser/T4910483.java
langtools/test/tools/javac/processing/errors/CrashOnNonExistingAnnotation/Processor.java
langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/Processor.java
langtools/test/tools/javac/warnings/suppress/VerifySuppressWarnings.java
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java	Mon Dec 07 14:02:55 2015 -0800
@@ -343,7 +343,7 @@
                 }
                 currentClassFile = classfile;
                 if (verbose) {
-                    log.printVerbose("loading", currentClassFile.toString());
+                    log.printVerbose("loading", currentClassFile.getName());
                 }
                 if (classfile.getKind() == JavaFileObject.Kind.CLASS ||
                     classfile.getKind() == JavaFileObject.Kind.OTHER) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileObject.java	Mon Dec 07 09:18:07 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2005, 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 com.sun.tools.javac.file;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.charset.CharsetDecoder;
-import java.nio.file.Path;
-
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.NestingKind;
-import javax.tools.FileObject;
-import javax.tools.JavaFileObject;
-
-import com.sun.tools.javac.util.DefinedBy;
-import com.sun.tools.javac.util.DefinedBy.Api;
-
-/**
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
-*/
-public abstract class BaseFileObject implements JavaFileObject {
-    protected BaseFileObject(JavacFileManager fileManager) {
-        this.fileManager = fileManager;
-    }
-
-    /** Return a short name for the object, such as for use in raw diagnostics
-     */
-    public abstract String getShortName();
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[" + getName() + "]";
-    }
-
-    @DefinedBy(Api.COMPILER)
-    public NestingKind getNestingKind() { return null; }
-
-    @DefinedBy(Api.COMPILER)
-    public Modifier getAccessLevel()  { return null; }
-
-    @DefinedBy(Api.COMPILER)
-    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
-        return new InputStreamReader(openInputStream(), getDecoder(ignoreEncodingErrors));
-    }
-
-    protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
-        throw new UnsupportedOperationException();
-    }
-
-    protected abstract String inferBinaryName(Iterable<? extends Path> path);
-
-    protected static JavaFileObject.Kind getKind(String filename) {
-        return BaseFileManager.getKind(filename);
-    }
-
-    protected static String removeExtension(String fileName) {
-        int lastDot = fileName.lastIndexOf(".");
-        return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
-    }
-
-    protected static URI createJarUri(Path jarFile, String entryName) {
-        URI jarURI = jarFile.toUri().normalize();
-        String separator = entryName.startsWith("/") ? "!" : "!/";
-        try {
-            // The jar URI convention appears to be not to re-encode the jarURI
-            return new URI("jar:" + jarURI + separator + entryName);
-        } catch (URISyntaxException e) {
-            throw new CannotCreateUriError(jarURI + separator + entryName, e);
-        }
-    }
-
-    /** Used when URLSyntaxException is thrown unexpectedly during
-     *  implementations of (Base)FileObject.toURI(). */
-    protected static class CannotCreateUriError extends Error {
-        private static final long serialVersionUID = 9101708840997613546L;
-        public CannotCreateUriError(String value, Throwable cause) {
-            super(value, cause);
-        }
-    }
-
-    /** Return the last component of a presumed hierarchical URI.
-     *  From the scheme specific part of the URI, it returns the substring
-     *  after the last "/" if any, or everything if no "/" is found.
-     */
-    public static String getSimpleName(FileObject fo) {
-        URI uri = fo.toUri();
-        String s = uri.getSchemeSpecificPart();
-        return s.substring(s.lastIndexOf("/") + 1); // safe when / not found
-
-    }
-
-    // force subtypes to define equals
-    @Override
-    public abstract boolean equals(Object other);
-
-    // force subtypes to define hashCode
-    @Override
-    public abstract int hashCode();
-
-    /** The file manager that created this JavaFileObject. */
-    protected final JavacFileManager fileManager;
-}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java	Mon Dec 07 14:02:55 2015 -0800
@@ -48,7 +48,7 @@
         try {
             return file.toRealPath();
         } catch (IOException e) {
-            return file.toAbsolutePath();
+            return file.toAbsolutePath().normalize();
         }
     }
 
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java	Mon Dec 07 14:02:55 2015 -0800
@@ -200,7 +200,7 @@
             if (Files.exists(dir)) {
                 try (DirectoryStream<Path> modules = Files.newDirectoryStream(dir)) {
                     for (Path module: modules) {
-                        Path p = rd.getFile(module);
+                        Path p = rd.resolveAgainst(module);
                         if (!Files.exists(p))
                             continue;
                         try (DirectoryStream<Path> stream = Files.newDirectoryStream(p)) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Mon Dec 07 14:02:55 2015 -0800
@@ -26,7 +26,6 @@
 package com.sun.tools.javac.file;
 
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URI;
@@ -34,16 +33,20 @@
 import java.net.URL;
 import java.nio.CharBuffer;
 import java.nio.charset.Charset;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitOption;
+import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.InvalidPathException;
 import java.nio.file.LinkOption;
-import java.nio.file.NoSuchFileException;
 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.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.HashMap;
@@ -53,7 +56,6 @@
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import java.util.zip.ZipFile;
 
 import javax.lang.model.SourceVersion;
 import javax.tools.FileObject;
@@ -69,6 +71,8 @@
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
 
+import static java.nio.file.FileVisitOption.FOLLOW_LINKS;
+
 import static javax.tools.StandardLocation.*;
 
 /**
@@ -92,9 +96,6 @@
 
     private FSInfo fsInfo;
 
-    private boolean contextUseOptimizedZip;
-    private ZipFileIndexCache zipFileIndexCache;
-
     private final Set<JavaFileObject.Kind> sourceOrClass =
         EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS);
 
@@ -149,10 +150,6 @@
 
         fsInfo = FSInfo.instance(context);
 
-        contextUseOptimizedZip = options.getBoolean("useOptimizedZip", true);
-        if (contextUseOptimizedZip)
-            zipFileIndexCache = ZipFileIndexCache.getSharedInstance();
-
         symbolFileEnabled = !options.isSet("ignore.symbol.file");
 
         String sf = options.get("sortFiles");
@@ -173,13 +170,13 @@
     }
 
     // used by tests
-    public JavaFileObject getFileForInput(String name) {
-        return getRegularFile(Paths.get(name));
+    public JavaFileObject getJavaFileObject(String name) {
+        return getJavaFileObjects(name).iterator().next();
     }
 
     // used by tests
-    public JavaFileObject getRegularFile(Path file) {
-        return new RegularFileObject(this, file);
+    public JavaFileObject getJavaFileObject(Path file) {
+        return getJavaFileObjects(file).iterator().next();
     }
 
     public JavaFileObject getFileForOutput(String classname,
@@ -277,7 +274,7 @@
         for (Path file: e.files.values()) {
             if (fileKinds.contains(getKind(file))) {
                 JavaFileObject fe
-                        = PathFileObject.createJRTPathFileObject(JavacFileManager.this, file);
+                        = PathFileObject.forJRTPath(JavacFileManager.this, file);
                 resultList.append(fe);
             }
         }
@@ -302,14 +299,14 @@
      * Insert all files in subdirectory subdirectory of directory directory
      * which match fileKinds into resultList
      */
-    private void listDirectory(Path directory,
+    private void listDirectory(Path directory, Path realDirectory,
                                RelativeDirectory subdirectory,
                                Set<JavaFileObject.Kind> fileKinds,
                                boolean recurse,
                                ListBuffer<JavaFileObject> resultList) {
         Path d;
         try {
-            d = subdirectory.getFile(directory);
+            d = subdirectory.resolveAgainst(directory);
         } catch (InvalidPathException ignore) {
             return;
         }
@@ -329,13 +326,16 @@
             return;
         }
 
+        if (realDirectory == null)
+            realDirectory = fsInfo.getCanonicalFile(directory);
+
         for (Path f: files) {
             String fname = f.getFileName().toString();
             if (fname.endsWith("/"))
                 fname = fname.substring(0, fname.length() - 1);
             if (Files.isDirectory(f)) {
                 if (recurse && SourceVersion.isIdentifier(fname)) {
-                    listDirectory(directory,
+                    listDirectory(directory, realDirectory,
                                   new RelativeDirectory(subdirectory, fname),
                                   fileKinds,
                                   recurse,
@@ -343,8 +343,9 @@
                 }
             } else {
                 if (isValidFile(fname, fileKinds)) {
-                    JavaFileObject fe =
-                        new RegularFileObject(this, fname, d.resolve(fname));
+                    RelativeFile file = new RelativeFile(subdirectory, fname);
+                    JavaFileObject fe = PathFileObject.forDirectoryPath(this,
+                            file.resolveAgainst(realDirectory), directory, file);
                     resultList.append(fe);
                 }
             }
@@ -352,34 +353,61 @@
     }
 
     /**
-     * Insert all files in subdirectory subdirectory of archive archive
+     * Insert all files in subdirectory subdirectory of archive archivePath
      * which match fileKinds into resultList
      */
-    private void listArchive(Archive archive,
-                               RelativeDirectory subdirectory,
-                               Set<JavaFileObject.Kind> fileKinds,
-                               boolean recurse,
-                               ListBuffer<JavaFileObject> resultList) {
-        // Get the files directly in the subdir
-        List<String> files = archive.getFiles(subdirectory);
-        if (files != null) {
-            for (; !files.isEmpty(); files = files.tail) {
-                String file = files.head;
-                if (isValidFile(file, fileKinds)) {
-                    resultList.append(archive.getFileObject(subdirectory, file));
-                }
-            }
+    private void listArchive(Path archivePath,
+            RelativeDirectory subdirectory,
+            Set<JavaFileObject.Kind> fileKinds,
+            boolean recurse,
+            ListBuffer<JavaFileObject> resultList)
+                throws IOException {
+        FileSystem fs = getFileSystem(archivePath);
+        if (fs == null) {
+            return;
+        }
+
+        Path containerSubdir = subdirectory.resolveAgainst(fs);
+        if (!Files.exists(containerSubdir)) {
+            return;
         }
-        if (recurse) {
-            for (RelativeDirectory s: archive.getSubdirectories()) {
-                if (subdirectory.contains(s)) {
-                    // Because the archive map is a flat list of directories,
-                    // the enclosing loop will pick up all child subdirectories.
-                    // Therefore, there is no need to recurse deeper.
-                    listArchive(archive, s, fileKinds, false, resultList);
-                }
-            }
-        }
+
+        int maxDepth = (recurse ? Integer.MAX_VALUE : 1);
+        Set<FileVisitOption> opts = EnumSet.of(FOLLOW_LINKS);
+        Files.walkFileTree(containerSubdir, opts, maxDepth,
+                new SimpleFileVisitor<Path>() {
+                    @Override
+                    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
+                        if (isValid(dir.getFileName())) {
+                            return FileVisitResult.CONTINUE;
+                        } else {
+                            return FileVisitResult.SKIP_SUBTREE;
+                        }
+                    }
+
+                    boolean isValid(Path fileName) {
+                        if (fileName == null) {
+                            return true;
+                        } else {
+                            String name = fileName.toString();
+                            if (name.endsWith("/")) {
+                                name = name.substring(0, name.length() - 1);
+                            }
+                            return SourceVersion.isIdentifier(name);
+                        }
+                    }
+
+                    @Override
+                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+                        if (attrs.isRegularFile() && fileKinds.contains(getKind(file.getFileName().toString()))) {
+                            JavaFileObject fe = PathFileObject.forJarPath(
+                                    JavacFileManager.this, file, archivePath);
+                            resultList.append(fe);
+                        }
+                        return FileVisitResult.CONTINUE;
+                    }
+                });
+
     }
 
     /**
@@ -391,54 +419,46 @@
                                RelativeDirectory subdirectory,
                                Set<JavaFileObject.Kind> fileKinds,
                                boolean recurse,
-                               ListBuffer<JavaFileObject> resultList) {
-        Archive archive = archives.get(container);
-        if (archive == null) {
-            // Very temporary and obnoxious interim hack
-            if (container.endsWith("bootmodules.jimage")) {
-                System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:");
-                container = Locations.JRT_MARKER_FILE;
-            } else if (container.getFileName().toString().endsWith(".jimage")) {
-                System.err.println("Warning: reference to " + container + " ignored");
-                return;
-            }
+                               ListBuffer<JavaFileObject> resultList)
+            throws IOException {
+        // Very temporary and obnoxious interim hack
+        if (container.endsWith("bootmodules.jimage")) {
+            System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:");
+            container = Locations.JRT_MARKER_FILE;
+        } else if (container.getFileName().toString().endsWith(".jimage")) {
+            System.err.println("Warning: reference to " + container + " ignored");
+            return;
+        }
 
-            // archives are not created for directories or jrt: images
-            if (container == Locations.JRT_MARKER_FILE) {
-                try {
-                    listJRTImage(subdirectory,
-                            fileKinds,
-                            recurse,
-                            resultList);
-                } catch (IOException ex) {
-                    ex.printStackTrace(System.err);
-                    log.error("error.reading.file", container, getMessage(ex));
-                }
-                return;
+        if (container == Locations.JRT_MARKER_FILE) {
+            try {
+                listJRTImage(subdirectory,
+                        fileKinds,
+                        recurse,
+                        resultList);
+            } catch (IOException ex) {
+                ex.printStackTrace(System.err);
+                log.error("error.reading.file", container, getMessage(ex));
             }
+            return;
+        }
 
-            if  (fsInfo.isDirectory(container)) {
-                listDirectory(container,
-                              subdirectory,
-                              fileKinds,
-                              recurse,
-                              resultList);
-                return;
-            }
+        if  (fsInfo.isDirectory(container)) {
+            listDirectory(container, null,
+                          subdirectory,
+                          fileKinds,
+                          recurse,
+                          resultList);
+            return;
+        }
 
-            // Not a directory; either a file or non-existant, create the archive
-            try {
-                archive = openArchive(container);
-            } catch (IOException ex) {
-                log.error("error.reading.file", container, getMessage(ex));
-                return;
-            }
-        }
-        listArchive(archive,
+        if (Files.exists(container)) {
+            listArchive(container,
                     subdirectory,
                     fileKinds,
                     recurse,
                     resultList);
+        }
     }
 
     private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
@@ -481,141 +501,17 @@
         return j < 0;
     }
 
-    /**
-     * An archive provides a flat directory structure of a ZipFile by
-     * mapping directory names to lists of files (basenames).
-     */
-    public interface Archive {
-        void close() throws IOException;
-
-        boolean contains(RelativePath name);
-
-        JavaFileObject getFileObject(RelativeDirectory subdirectory, String file);
-
-        List<String> getFiles(RelativeDirectory subdirectory);
-
-        Set<RelativeDirectory> getSubdirectories();
-    }
-
-    public class MissingArchive implements Archive {
-        final Path zipFileName;
-        public MissingArchive(Path name) {
-            zipFileName = name;
-        }
-        @Override
-        public boolean contains(RelativePath name) {
-            return false;
+    private FileSystem getFileSystem(Path path) throws IOException {
+        Path realPath = fsInfo.getCanonicalFile(path);
+        FileSystem fs = fileSystems.get(realPath);
+        if (fs == null) {
+            fileSystems.put(realPath, fs = FileSystems.newFileSystem(realPath, null));
         }
-
-        @Override
-        public void close() {
-        }
-
-        @Override
-        public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
-            return null;
-        }
-
-        @Override
-        public List<String> getFiles(RelativeDirectory subdirectory) {
-            return List.nil();
-        }
-
-        @Override
-        public Set<RelativeDirectory> getSubdirectories() {
-            return Collections.emptySet();
-        }
-
-        @Override
-        public String toString() {
-            return "MissingArchive[" + zipFileName + "]";
-        }
+        return fs;
     }
 
-    /** A directory of zip files already opened.
-     */
-    Map<Path, Archive> archives = new HashMap<>();
-
-    /*
-     * This method looks for a ZipFormatException and takes appropriate
-     * evasive action. If there is a failure in the fast mode then we
-     * fail over to the platform zip, and allow it to deal with a potentially
-     * non compliant zip file.
-     */
-    protected Archive openArchive(Path zipFilename) throws IOException {
-        try {
-            return openArchive(zipFilename, contextUseOptimizedZip);
-        } catch (IOException ioe) {
-            if (ioe instanceof ZipFileIndex.ZipFormatException) {
-                return openArchive(zipFilename, false);
-            } else {
-                throw ioe;
-            }
-        }
-    }
-
-    /** Open a new zip file directory, and cache it.
-     */
-    private Archive openArchive(Path zipFileName, boolean useOptimizedZip) throws IOException {
-        Archive archive;
-        try {
-
-            ZipFile zdir = null;
-
-            boolean usePreindexedCache = false;
-            String preindexCacheLocation = null;
-
-            if (!useOptimizedZip) {
-                zdir = new ZipFile(zipFileName.toFile());
-            } else {
-                usePreindexedCache = options.isSet("usezipindex");
-                preindexCacheLocation = options.get("java.io.tmpdir");
-                String optCacheLoc = options.get("cachezipindexdir");
+    private final Map<Path,FileSystem> fileSystems = new HashMap<>();
 
-                if (optCacheLoc != null && optCacheLoc.length() != 0) {
-                    if (optCacheLoc.startsWith("\"")) {
-                        if (optCacheLoc.endsWith("\"")) {
-                            optCacheLoc = optCacheLoc.substring(1, optCacheLoc.length() - 1);
-                        }
-                        else {
-                            optCacheLoc = optCacheLoc.substring(1);
-                        }
-                    }
-
-                    File cacheDir = new File(optCacheLoc);
-                    if (cacheDir.exists() && cacheDir.canWrite()) {
-                        preindexCacheLocation = optCacheLoc;
-                        if (!preindexCacheLocation.endsWith("/") &&
-                            !preindexCacheLocation.endsWith(File.separator)) {
-                            preindexCacheLocation += File.separator;
-                        }
-                    }
-                }
-            }
-
-                if (!useOptimizedZip) {
-                    archive = new ZipArchive(this, zdir);
-                } else {
-                    archive = new ZipFileIndexArchive(this,
-                                    zipFileIndexCache.getZipFileIndex(zipFileName,
-                                    null,
-                                    usePreindexedCache,
-                                    preindexCacheLocation,
-                                    options.isSet("writezipindexfiles")));
-                }
-        } catch (FileNotFoundException | NoSuchFileException ex) {
-            archive = new MissingArchive(zipFileName);
-        } catch (ZipFileIndex.ZipFormatException zfe) {
-            throw zfe;
-        } catch (IOException ex) {
-            if (Files.exists(zipFileName))
-                log.error("error.reading.file", zipFileName, getMessage(ex));
-            archive = new MissingArchive(zipFileName);
-        }
-
-        archives.put(zipFileName, archive);
-        return archive;
-    }
 
     /** Flush any output resources.
      */
@@ -628,15 +524,9 @@
      * Close the JavaFileManager, releasing resources.
      */
     @Override @DefinedBy(Api.COMPILER)
-    public void close() {
-        for (Iterator<Archive> i = archives.values().iterator(); i.hasNext(); ) {
-            Archive a = i.next();
-            i.remove();
-            try {
-                a.close();
-            } catch (IOException ignore) {
-            }
-        }
+    public void close() throws IOException {
+        for (FileSystem fs: fileSystems.values())
+            fs.close();
     }
 
     @Override @DefinedBy(Api.COMPILER)
@@ -689,10 +579,8 @@
             return null;
         }
 
-        if (file instanceof BaseFileObject) {
-            return ((BaseFileObject) file).inferBinaryName(path);
-        } else if (file instanceof PathFileObject) {
-            return ((PathFileObject) file).inferBinaryName(null);
+        if (file instanceof PathFileObject) {
+            return ((PathFileObject) file).inferBinaryName(path);
         } else
             throw new IllegalArgumentException(file.getClass().getName());
     }
@@ -703,11 +591,6 @@
         nullCheck(b);
         if (a instanceof PathFileObject && b instanceof PathFileObject)
             return ((PathFileObject) a).isSameFile((PathFileObject) b);
-        // In time, we should phase out BaseFileObject in favor of PathFileObject
-        if (!(a instanceof BaseFileObject  || a instanceof PathFileObject))
-            throw new IllegalArgumentException("Not supported: " + a);
-        if (!(b instanceof BaseFileObject || b instanceof PathFileObject))
-            throw new IllegalArgumentException("Not supported: " + b);
         return a.equals(b);
     }
 
@@ -754,32 +637,29 @@
             return null;
 
         for (Path file: path) {
-            Archive a = archives.get(file);
-            if (a == null) {
-                // archives are not created for directories or jrt: images
-                if (file == Locations.JRT_MARKER_FILE) {
-                    JRTIndex.Entry e = getJRTIndex().getEntry(name.dirname());
-                    if (symbolFileEnabled && e.ctSym.hidden)
-                        continue;
-                    Path p = e.files.get(name.basename());
-                    if (p != null)
-                        return PathFileObject.createJRTPathFileObject(this, p);
+            if (file == Locations.JRT_MARKER_FILE) {
+                JRTIndex.Entry e = getJRTIndex().getEntry(name.dirname());
+                if (symbolFileEnabled && e.ctSym.hidden)
                     continue;
-                } else if (fsInfo.isDirectory(file)) {
-                    try {
-                        Path f = name.getFile(file);
-                        if (Files.exists(f))
-                            return new RegularFileObject(this, f);
-                    } catch (InvalidPathException ignore) {
-                    }
-                    continue;
+                Path p = e.files.get(name.basename());
+                if (p != null)
+                    return PathFileObject.forJRTPath(this, p);
+            } else if (fsInfo.isDirectory(file)) {
+                try {
+                    Path f = name.resolveAgainst(file);
+                    if (Files.exists(f))
+                        return PathFileObject.forSimplePath(this,
+                                fsInfo.getCanonicalFile(f), f);
+                } catch (InvalidPathException ignore) {
                 }
-                // Not a directory, create the archive
-                a = openArchive(file);
-            }
-            // Process the archive
-            if (a.contains(name)) {
-                return a.getFileObject(name.dirname(), name.basename());
+            } else if (Files.exists(file)) {
+                FileSystem fs = getFileSystem(file);
+                if (fs != null) {
+                    Path fsRoot = fs.getRootDirectories().iterator().next();
+                    Path f = name.resolveAgainst(fsRoot);
+                    if (Files.exists(f))
+                        return PathFileObject.forJarPath(this, f, file);
+                }
             }
         }
         return null;
@@ -829,14 +709,14 @@
             if (getClassOutDir() != null) {
                 dir = getClassOutDir();
             } else {
-                Path siblingDir = null;
-                if (sibling != null && sibling instanceof RegularFileObject) {
-                    siblingDir = ((RegularFileObject)sibling).file.getParent();
+                String baseName = fileName.basename();
+                if (sibling != null && sibling instanceof PathFileObject) {
+                    return ((PathFileObject) sibling).getSibling(baseName);
+                } else {
+                    Path p = Paths.get(baseName);
+                    Path real = fsInfo.getCanonicalFile(p);
+                    return PathFileObject.forSimplePath(this, real, p);
                 }
-                if (siblingDir == null)
-                    return new RegularFileObject(this, Paths.get(fileName.basename()));
-                else
-                    return new RegularFileObject(this, siblingDir.resolve(fileName.basename()));
             }
         } else if (location == SOURCE_OUTPUT) {
             dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
@@ -850,8 +730,11 @@
         }
 
         try {
-            Path file = fileName.getFile(dir); // null-safe
-            return new RegularFileObject(this, file);
+            if (dir == null) {
+                dir = Paths.get(System.getProperty("user.dir"));
+            }
+            Path path = fileName.resolveAgainst(fsInfo.getCanonicalFile(dir));
+            return PathFileObject.forDirectoryPath(this, path, dir, fileName);
         } catch (InvalidPathException e) {
             throw new IOException("bad filename " + fileName, e);
         }
@@ -861,13 +744,17 @@
     public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(
         Iterable<? extends File> files)
     {
-        ArrayList<RegularFileObject> result;
+        ArrayList<PathFileObject> result;
         if (files instanceof Collection<?>)
             result = new ArrayList<>(((Collection<?>)files).size());
         else
             result = new ArrayList<>();
-        for (File f: files)
-            result.add(new RegularFileObject(this, nullCheck(f).toPath()));
+        for (File f: files) {
+            Objects.requireNonNull(f);
+            Path p = f.toPath();
+            result.add(PathFileObject.forSimplePath(this,
+                    fsInfo.getCanonicalFile(p), p));
+        }
         return result;
     }
 
@@ -875,13 +762,14 @@
     public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
         Iterable<? extends Path> paths)
     {
-        ArrayList<RegularFileObject> result;
+        ArrayList<PathFileObject> result;
         if (paths instanceof Collection<?>)
             result = new ArrayList<>(((Collection<?>)paths).size());
         else
             result = new ArrayList<>();
         for (Path p: paths)
-            result.add(new RegularFileObject(this, nullCheck(p)));
+            result.add(PathFileObject.forSimplePath(this,
+                    fsInfo.getCanonicalFile(p), p));
         return result;
     }
 
@@ -935,8 +823,8 @@
 
     @Override @DefinedBy(Api.COMPILER)
     public Path asPath(FileObject file) {
-        if (file instanceof RegularFileObject) {
-            return ((RegularFileObject) file).file;
+        if (file instanceof PathFileObject) {
+            return ((PathFileObject) file).path;
         } else
             throw new IllegalArgumentException(file.getName());
     }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java	Mon Dec 07 14:02:55 2015 -0800
@@ -33,18 +33,24 @@
 import java.io.Reader;
 import java.io.Writer;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.CharsetDecoder;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.LinkOption;
 import java.nio.file.Path;
+import java.text.Normalizer;
 import java.util.Objects;
 
 import javax.lang.model.element.Modifier;
 import javax.lang.model.element.NestingKind;
+import javax.tools.FileObject;
 import javax.tools.JavaFileObject;
 
+import com.sun.tools.javac.file.RelativePath.RelativeFile;
 import com.sun.tools.javac.util.DefinedBy;
 import com.sun.tools.javac.util.DefinedBy.Api;
 
@@ -53,10 +59,16 @@
  *  Implementation of JavaFileObject using java.nio.file API.
  *
  *  <p>PathFileObjects are, for the most part, straightforward wrappers around
- *  Path objects. The primary complexity is the support for "inferBinaryName".
- *  This is left as an abstract method, implemented by each of a number of
- *  different factory methods, which compute the binary name based on
- *  information available at the time the file object is created.
+ *  immutable absolute Path objects. Different subtypes are used to provide
+ *  specialized implementations of "inferBinaryName" and "getName" that capture
+ *  additional information available at the time the object is created.
+ *
+ *  <p>In general, {@link JavaFileManager#isSameFile} should be used to
+ *  determine whether two file objects refer to the same file on disk.
+ *  PathFileObject also supports the standard {@code equals} and {@code hashCode}
+ *  methods, primarily for convenience when working with collections.
+ *  All of these operations delegate to the equivalent operations on the
+ *  underlying Path object.
  *
  *  <p><b>This is NOT part of any supported API.
  *  If you write code that depends on this, you do so at your own risk.
@@ -64,108 +76,297 @@
  *  deletion without notice.</b>
  */
 public abstract class PathFileObject implements JavaFileObject {
-    private final BaseFileManager fileManager;
-    private final Path path;
+    private static final FileSystem defaultFileSystem = FileSystems.getDefault();
+    private static final boolean isMacOS = System.getProperty("os.name", "").contains("OS X");
+
+    protected final BaseFileManager fileManager;
+    protected final Path path;
+    private boolean hasParents;
 
     /**
-     * Create a PathFileObject within a directory, such that the binary name
-     * can be inferred from the relationship to the parent directory.
+     * Create a PathFileObject for a file within a directory, such that the
+     * binary name can be inferred from the relationship to an enclosing directory.
+     *
+     * The binary name is derived from {@code relativePath}.
+     * The name is derived from the composition of {@code userPackageRootDir}
+     * and {@code relativePath}.
+     *
+     * @param fileManager the file manager creating this file object
+     * @param path the absolute path referred to by this file object
+     * @param userPackageRootDir the path of the directory containing the
+     *          root of the package hierarchy
+     * @param relativePath the path of this file relative to {@code userPackageRootDir}
      */
-    static PathFileObject createDirectoryPathFileObject(BaseFileManager fileManager,
-            final Path path, final Path dir) {
-        return new PathFileObject(fileManager, path) {
-            @Override
-            public String inferBinaryName(Iterable<? extends Path> paths) {
-                return toBinaryName(dir.relativize(path));
-            }
-        };
+    static PathFileObject forDirectoryPath(BaseFileManager fileManager, Path path,
+            Path userPackageRootDir, RelativePath relativePath) {
+        return new DirectoryFileObject(fileManager, path, userPackageRootDir, relativePath);
+    }
+
+    private static class DirectoryFileObject extends PathFileObject {
+        private final Path userPackageRootDir;
+        private final RelativePath relativePath;
+
+        private DirectoryFileObject(BaseFileManager fileManager, Path path,
+                Path userPackageRootDir, RelativePath relativePath) {
+            super(fileManager, path);
+            this.userPackageRootDir = userPackageRootDir;
+            this.relativePath = relativePath;
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public String getName() {
+            return relativePath.resolveAgainst(userPackageRootDir).toString();
+        }
+
+        @Override
+        public String inferBinaryName(Iterable<? extends Path> paths) {
+            return toBinaryName(relativePath);
+        }
+
+        @Override
+        public String toString() {
+            return "DirectoryFileObject[" + userPackageRootDir + ":" + relativePath.path + "]";
+        }
+
+        @Override
+        PathFileObject getSibling(String baseName) {
+            return new DirectoryFileObject(fileManager,
+                    path.resolveSibling(baseName),
+                    userPackageRootDir,
+                    new RelativeFile(relativePath.dirname(), baseName)
+            );
+        }
     }
 
     /**
-     * Create a PathFileObject in a file system such as a jar file, such that
-     * the binary name can be inferred from its position within the filesystem.
+     * Create a PathFileObject for a file in a file system such as a jar file,
+     * such that the binary name can be inferred from its position within the
+     * file system.
+     *
+     * The binary name is derived from {@code path}.
+     * The name is derived from the composition of {@code userJarPath}
+     * and {@code path}.
+     *
+     * @param fileManager the file manager creating this file object
+     * @param path the path referred to by this file object
+     * @param userJarPath the path of the jar file containing the file system.
      */
-    public static PathFileObject createJarPathFileObject(BaseFileManager fileManager,
-            final Path path) {
-        return new PathFileObject(fileManager, path) {
-            @Override
-            public String inferBinaryName(Iterable<? extends Path> paths) {
-                return toBinaryName(path);
-            }
-        };
+    public static PathFileObject forJarPath(BaseFileManager fileManager,
+            Path path, Path userJarPath) {
+        return new JarFileObject(fileManager, path, userJarPath);
     }
 
-    /**
-     * Create a PathFileObject in a modular file system, such as jrt:, such that
-     * the binary name can be inferred from its position within the filesystem.
-     */
-    public static PathFileObject createJRTPathFileObject(BaseFileManager fileManager,
-            final Path path) {
-        return new PathFileObject(fileManager, path) {
-            @Override
-            public String inferBinaryName(Iterable<? extends Path> paths) {
-                // use subpath to ignore the leading /modules/MODULE-NAME
-                return toBinaryName(path.subpath(2, path.getNameCount()));
+    private static class JarFileObject extends PathFileObject {
+        private final Path userJarPath;
+
+        private JarFileObject(BaseFileManager fileManager, Path path, Path userJarPath) {
+            super(fileManager, path);
+            this.userJarPath = userJarPath;
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public String getName() {
+            // The use of ( ) to delimit the entry name is not ideal
+            // but it does match earlier behavior
+            return userJarPath + "(" + path + ")";
+        }
+
+        @Override
+        public String inferBinaryName(Iterable<? extends Path> paths) {
+            Path root = path.getFileSystem().getRootDirectories().iterator().next();
+            return toBinaryName(root.relativize(path));
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public URI toUri() {
+            // Work around bug JDK-8134451:
+            // path.toUri() returns double-encoded URIs, that cannot be opened by URLConnection
+            return createJarUri(userJarPath, path.toString());
+        }
+
+        @Override
+        public String toString() {
+            return "JarFileObject[" + userJarPath + ":" + path + "]";
+        }
+
+        @Override
+        PathFileObject getSibling(String baseName) {
+            return new JarFileObject(fileManager,
+                    path.resolveSibling(baseName),
+                    userJarPath
+            );
+        }
+
+        private static URI createJarUri(Path jarFile, String entryName) {
+            URI jarURI = jarFile.toUri().normalize();
+            String separator = entryName.startsWith("/") ? "!" : "!/";
+            try {
+                // The jar URI convention appears to be not to re-encode the jarURI
+                return new URI("jar:" + jarURI + separator + entryName);
+            } catch (URISyntaxException e) {
+                throw new CannotCreateUriError(jarURI + separator + entryName, e);
             }
-        };
+        }
     }
 
     /**
-     * Create a PathFileObject whose binary name can be inferred from the
-     * relative path to a sibling.
+     * Create a PathFileObject for a file in a modular file system, such as jrt:,
+     * such that the binary name can be inferred from its position within the
+     * filesystem.
+     *
+     * The binary name is derived from {@code path}, ignoring the first two
+     * elements of the name (which are "modules" and a module name).
+     * The name is derived from {@code path}.
+     *
+     * @param fileManager the file manager creating this file object
+     * @param path the path referred to by this file object
      */
-    static PathFileObject createSiblingPathFileObject(BaseFileManager fileManager,
-            final Path path, final String relativePath) {
-        return new PathFileObject(fileManager, path) {
-            @Override
-            public String inferBinaryName(Iterable<? extends Path> paths) {
-                return toBinaryName(relativePath, "/");
-            }
-        };
+    public static PathFileObject forJRTPath(BaseFileManager fileManager,
+            final Path path) {
+        return new JRTFileObject(fileManager, path);
+    }
+
+    private static class JRTFileObject extends PathFileObject {
+        // private final Path javaHome;
+        private JRTFileObject(BaseFileManager fileManager, Path path) {
+            super(fileManager, path);
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public String getName() {
+            return path.toString();
+        }
+
+        @Override
+        public String inferBinaryName(Iterable<? extends Path> paths) {
+            // use subpath to ignore the leading /modules/MODULE-NAME
+            return toBinaryName(path.subpath(2, path.getNameCount()));
+        }
+
+        @Override
+        public String toString() {
+            return "JRTFileObject[" + path + "]";
+        }
+
+        @Override
+        PathFileObject getSibling(String baseName) {
+            return new JRTFileObject(fileManager,
+                    path.resolveSibling(baseName)
+            );
+        }
     }
 
     /**
-     * Create a PathFileObject whose binary name might be inferred from its
-     * position on a search path.
+     * Create a PathFileObject for a file whose binary name must be inferred
+     * from its position on a search path.
+     *
+     * The binary name is inferred by finding an enclosing directory in
+     * the sequence of paths associated with the location given to
+     * {@link JavaFileManager#inferBinaryName).
+     * The name is derived from {@code userPath}.
+     *
+     * @param fileManager the file manager creating this file object
+     * @param path the path referred to by this file object
+     * @param userPath the "user-friendly" name for this path.
      */
-    static PathFileObject createSimplePathFileObject(BaseFileManager fileManager,
-            final Path path) {
-        return new PathFileObject(fileManager, path) {
-            @Override
-            public String inferBinaryName(Iterable<? extends Path> paths) {
-                Path absPath = path.toAbsolutePath();
-                for (Path p: paths) {
-                    Path ap = p.toAbsolutePath();
-                    if (absPath.startsWith(ap)) {
-                        try {
-                            Path rp = ap.relativize(absPath);
-                            if (rp != null) // maybe null if absPath same as ap
-                                return toBinaryName(rp);
-                        } catch (IllegalArgumentException e) {
-                            // ignore this p if cannot relativize path to p
-                        }
+    static PathFileObject forSimplePath(BaseFileManager fileManager,
+            Path path, Path userPath) {
+        return new SimpleFileObject(fileManager, path, userPath);
+    }
+
+    private static class SimpleFileObject extends PathFileObject {
+        private final Path userPath;
+        private SimpleFileObject(BaseFileManager fileManager, Path path, Path userPath) {
+            super(fileManager, path);
+            this.userPath = userPath;
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public String getName() {
+            return userPath.toString();
+        }
+
+        @Override
+        public String inferBinaryName(Iterable<? extends Path> paths) {
+            Path absPath = path.toAbsolutePath();
+            for (Path p: paths) {
+                Path ap = p.toAbsolutePath();
+                if (absPath.startsWith(ap)) {
+                    try {
+                        Path rp = ap.relativize(absPath);
+                        if (rp != null) // maybe null if absPath same as ap
+                            return toBinaryName(rp);
+                    } catch (IllegalArgumentException e) {
+                        // ignore this p if cannot relativize path to p
                     }
                 }
-                return null;
             }
-        };
+            return null;
+        }
+
+        @Override
+        PathFileObject getSibling(String baseName) {
+            return new SimpleFileObject(fileManager,
+                    path.resolveSibling(baseName),
+                    userPath.resolveSibling(baseName)
+            );
+        }
     }
 
+    /**
+     * Create a PathFileObject, for a specified path, in the context of
+     * a given file manager.
+     *
+     * In general, this path should be an
+     * {@link Path#toAbsolutePath absolute path}, if not a
+     * {@link Path#toRealPath} real path.
+     * It will be used as the basis of {@code equals}, {@code hashCode}
+     * and {@code isSameFile} methods on this file object.
+     *
+     * A PathFileObject should also have a "friendly name" per the
+     * specification for {@link FileObject#getName}. The friendly name
+     * is provided by the various subtypes of {@code PathFileObject}.
+     *
+     * @param fileManager the file manager creating this file object
+     * @param path the path contained in this file object.
+     */
     protected PathFileObject(BaseFileManager fileManager, Path path) {
         this.fileManager = Objects.requireNonNull(fileManager);
-        this.path = Objects.requireNonNull(path);
+        if (Files.isDirectory(path)) {
+            throw new IllegalArgumentException("directories not supported");
+        }
+        this.path = path;
     }
 
-    public abstract String inferBinaryName(Iterable<? extends Path> paths);
+    /**
+     * See {@link JavacFileManager#inferBinaryName}.
+     */
+    abstract String inferBinaryName(Iterable<? extends Path> paths);
+
+    /**
+     * Return the file object for a sibling file with a given file name.
+     * See {@link JavacFileManager#getFileForOutput} and
+     * {@link JavacFileManager#getJavaFileForOutput}.
+     */
+    abstract PathFileObject getSibling(String basename);
 
     /**
      * Return the Path for this object.
      * @return the Path for this object.
+     * @see StandardJavaFileManager#asPath
      */
     public Path getPath() {
         return path;
     }
 
+    /**
+     * The short name is used when generating raw diagnostics.
+     * @return the last component of the path
+     */
+    public String getShortName() {
+        return path.getFileName().toString();
+    }
+
     @Override @DefinedBy(Api.COMPILER)
     public Kind getKind() {
         return BaseFileManager.getKind(path.getFileName().toString());
@@ -174,22 +375,43 @@
     @Override @DefinedBy(Api.COMPILER)
     public boolean isNameCompatible(String simpleName, Kind kind) {
         Objects.requireNonNull(simpleName);
-        // null check
+        Objects.requireNonNull(kind);
+
         if (kind == Kind.OTHER && getKind() != kind) {
             return false;
         }
+
         String sn = simpleName + kind.extension;
         String pn = path.getFileName().toString();
         if (pn.equals(sn)) {
             return true;
         }
-        if (pn.equalsIgnoreCase(sn)) {
-            try {
-                // allow for Windows
-                return path.toRealPath(LinkOption.NOFOLLOW_LINKS).getFileName().toString().equals(sn);
-            } catch (IOException e) {
+
+        if (path.getFileSystem() == defaultFileSystem) {
+            if (isMacOS) {
+                String name = path.getFileName().toString();
+                if (Normalizer.isNormalized(name, Normalizer.Form.NFD)
+                        && Normalizer.isNormalized(sn, Normalizer.Form.NFC)) {
+                    // On Mac OS X it is quite possible to have the file name and the
+                    // given simple name normalized in different ways.
+                    // In that case we have to normalize file name to the
+                    // Normal Form Composed (NFC).
+                    String normName = Normalizer.normalize(name, Normalizer.Form.NFC);
+                    if (normName.equals(sn)) {
+                        return true;
+                    }
+                }
+            }
+
+            if (pn.equalsIgnoreCase(sn)) {
+                try {
+                    // allow for Windows
+                    return path.toRealPath(LinkOption.NOFOLLOW_LINKS).getFileName().toString().equals(sn);
+                } catch (IOException e) {
+                }
             }
         }
+
         return false;
     }
 
@@ -209,11 +431,6 @@
     }
 
     @Override @DefinedBy(Api.COMPILER)
-    public String getName() {
-        return path.toString();
-    }
-
-    @Override @DefinedBy(Api.COMPILER)
     public InputStream openInputStream() throws IOException {
         return Files.newInputStream(path);
     }
@@ -264,7 +481,7 @@
         try {
             return Files.getLastModifiedTime(path).toMillis();
         } catch (IOException e) {
-            return -1;
+            return 0;
         }
     }
 
@@ -278,7 +495,7 @@
         }
     }
 
-    public boolean isSameFile(PathFileObject other) {
+    boolean isSameFile(PathFileObject other) {
         try {
             return Files.isSameFile(path, other.path);
         } catch (IOException e) {
@@ -302,17 +519,21 @@
     }
 
     private void ensureParentDirectoriesExist() throws IOException {
-        Path parent = path.getParent();
-        if (parent != null)
-            Files.createDirectories(parent);
+        if (!hasParents) {
+            Path parent = path.getParent();
+            if (parent != null && !Files.isDirectory(parent)) {
+                try {
+                    Files.createDirectories(parent);
+                } catch (IOException e) {
+                    throw new IOException("could not create parent directories", e);
+                }
+            }
+            hasParents = true;
+        }
     }
 
-    private long size() {
-        try {
-            return Files.size(path);
-        } catch (IOException e) {
-            return -1;
-        }
+    protected static String toBinaryName(RelativePath relativePath) {
+        return toBinaryName(relativePath.path, "/");
     }
 
     protected static String toBinaryName(Path relativePath) {
@@ -320,12 +541,32 @@
                 relativePath.getFileSystem().getSeparator());
     }
 
-    protected static String toBinaryName(String relativePath, String sep) {
+    private static String toBinaryName(String relativePath, String sep) {
         return removeExtension(relativePath).replace(sep, ".");
     }
 
-    protected static String removeExtension(String fileName) {
+    private static String removeExtension(String fileName) {
         int lastDot = fileName.lastIndexOf(".");
         return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
     }
+
+    /** Return the last component of a presumed hierarchical URI.
+     *  From the scheme specific part of the URI, it returns the substring
+     *  after the last "/" if any, or everything if no "/" is found.
+     */
+    public static String getSimpleName(FileObject fo) {
+        URI uri = fo.toUri();
+        String s = uri.getSchemeSpecificPart();
+        return s.substring(s.lastIndexOf("/") + 1); // safe when / not found
+
+    }
+
+    /** Used when URLSyntaxException is thrown unexpectedly during
+     *  implementations of FileObject.toURI(). */
+    public static class CannotCreateUriError extends Error {
+        private static final long serialVersionUID = 9101708840997613546L;
+        public CannotCreateUriError(String value, Throwable cause) {
+            super(value, cause);
+        }
+    }
 }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RegularFileObject.java	Mon Dec 07 09:18:07 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,265 +0,0 @@
-/*
- * Copyright (c) 2005, 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 com.sun.tools.javac.file;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
-import java.net.URI;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharsetDecoder;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.text.Normalizer;
-import java.util.Objects;
-
-import javax.tools.JavaFileObject;
-
-import com.sun.tools.javac.util.DefinedBy;
-import com.sun.tools.javac.util.DefinedBy.Api;
-
-/**
- * A subclass of JavaFileObject representing regular files.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-class RegularFileObject extends BaseFileObject {
-
-    /** Have the parent directories been created?
-     */
-    private boolean hasParents = false;
-    private String name;
-    final Path file;
-    private Reference<Path> absFileRef;
-    final static boolean isMacOS = System.getProperty("os.name", "").contains("OS X");
-
-    public RegularFileObject(JavacFileManager fileManager, Path f) {
-        this(fileManager, f.getFileName().toString(), f);
-    }
-
-    public RegularFileObject(JavacFileManager fileManager, String name, Path f) {
-        super(fileManager);
-        if (Files.isDirectory(f)) {
-            throw new IllegalArgumentException("directories not supported");
-        }
-        this.name = name;
-        this.file = f;
-        if (getLastModified() > System.currentTimeMillis())
-            fileManager.log.warning("file.from.future", f);
-    }
-
-    @Override @DefinedBy(Api.COMPILER)
-    public URI toUri() {
-        return file.toUri().normalize();
-    }
-
-    @Override @DefinedBy(Api.COMPILER)
-    public String getName() {
-        return file.toString();
-    }
-
-    @Override
-    public String getShortName() {
-        return name;
-    }
-
-    @Override @DefinedBy(Api.COMPILER)
-    public JavaFileObject.Kind getKind() {
-        return getKind(name);
-    }
-
-    @Override @DefinedBy(Api.COMPILER)
-    public InputStream openInputStream() throws IOException {
-        return Files.newInputStream(file);
-    }
-
-    @Override @DefinedBy(Api.COMPILER)
-    public OutputStream openOutputStream() throws IOException {
-        fileManager.flushCache(this);
-        ensureParentDirectoriesExist();
-        return Files.newOutputStream(file);
-    }
-
-    @Override @DefinedBy(Api.COMPILER)
-    public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
-        CharBuffer cb = fileManager.getCachedContent(this);
-        if (cb == null) {
-            try (InputStream in = Files.newInputStream(file)) {
-                ByteBuffer bb = fileManager.makeByteBuffer(in);
-                JavaFileObject prev = fileManager.log.useSource(this);
-                try {
-                    cb = fileManager.decode(bb, ignoreEncodingErrors);
-                } finally {
-                    fileManager.log.useSource(prev);
-                }
-                fileManager.recycleByteBuffer(bb);
-                if (!ignoreEncodingErrors) {
-                    fileManager.cache(this, cb);
-                }
-            }
-        }
-        return cb;
-    }
-
-    @Override @DefinedBy(Api.COMPILER)
-    public Writer openWriter() throws IOException {
-        fileManager.flushCache(this);
-        ensureParentDirectoriesExist();
-        return new OutputStreamWriter(Files.newOutputStream(file), fileManager.getEncodingName());
-    }
-
-    @Override @DefinedBy(Api.COMPILER)
-    public long getLastModified() {
-        try {
-            return Files.getLastModifiedTime(file).toMillis();
-        } catch (IOException e) {
-            return 0;
-        }
-    }
-
-    @Override @DefinedBy(Api.COMPILER)
-    public boolean delete() {
-        try {
-            Files.delete(file);
-            return true;
-        } catch (IOException e) {
-            return false;
-        }
-    }
-
-    @Override
-    protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
-        return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
-    }
-
-    @Override
-    protected String inferBinaryName(Iterable<? extends Path> path) {
-        String fPath = file.toString();
-        //System.err.println("RegularFileObject " + file + " " +r.getPath());
-        for (Path dir: path) {
-            //System.err.println("dir: " + dir);
-            String sep = dir.getFileSystem().getSeparator();
-            String dPath = dir.toString();
-            if (dPath.length() == 0)
-                dPath = System.getProperty("user.dir");
-            if (!dPath.endsWith(sep))
-                dPath += sep;
-            if (fPath.regionMatches(true, 0, dPath, 0, dPath.length())
-                && Paths.get(fPath.substring(0, dPath.length())).equals(Paths.get(dPath))) {
-                String relativeName = fPath.substring(dPath.length());
-                return removeExtension(relativeName).replace(sep, ".");
-            }
-        }
-        return null;
-    }
-
-    @Override @DefinedBy(Api.COMPILER)
-    public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) {
-        Objects.requireNonNull(cn);
-        // null check
-        if (kind == Kind.OTHER && getKind() != kind) {
-            return false;
-        }
-        String n = cn + kind.extension;
-        if (name.equals(n)) {
-            return true;
-        }
-        if (isMacOS && Normalizer.isNormalized(name, Normalizer.Form.NFD)
-            && Normalizer.isNormalized(n, Normalizer.Form.NFC)) {
-            // On Mac OS X it is quite possible to file name and class
-            // name normalized in a different way - in that case we have to normalize file name
-            // to the Normal Form Compised (NFC)
-            String normName = Normalizer.normalize(name, Normalizer.Form.NFC);
-            if (normName.equals(n)) {
-                this.name = normName;
-                return true;
-            }
-        }
-
-            if (name.equalsIgnoreCase(n)) {
-            try {
-                // allow for Windows
-                return file.toRealPath().getFileName().toString().equals(n);
-            } catch (IOException e) {
-            }
-        }
-        return false;
-    }
-
-    private void ensureParentDirectoriesExist() throws IOException {
-        if (!hasParents) {
-            Path parent = file.getParent();
-            if (parent != null && !Files.isDirectory(parent)) {
-                try {
-                    Files.createDirectories(parent);
-                } catch (IOException e) {
-                    throw new IOException("could not create parent directories", e);
-                }
-            }
-            hasParents = true;
-        }
-    }
-
-    /**
-     * Check if two file objects are equal.
-     * Two RegularFileObjects are equal if the absolute paths of the underlying
-     * files are equal.
-     */
-    @Override
-    public boolean equals(Object other) {
-        if (this == other)
-            return true;
-
-        if (!(other instanceof RegularFileObject))
-            return false;
-
-        RegularFileObject o = (RegularFileObject) other;
-        return getAbsoluteFile().equals(o.getAbsoluteFile());
-    }
-
-    @Override
-    public int hashCode() {
-        return getAbsoluteFile().hashCode();
-    }
-
-    private Path getAbsoluteFile() {
-        Path absFile = (absFileRef == null ? null : absFileRef.get());
-        if (absFile == null) {
-            absFile = file.toAbsolutePath();
-            absFileRef = new SoftReference<>(absFile);
-        }
-        return absFile;
-    }
-}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java	Mon Dec 07 14:02:55 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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
@@ -26,6 +26,7 @@
 package com.sun.tools.javac.file;
 
 import java.io.File;
+import java.nio.file.FileSystem;
 import java.nio.file.FileSystems;
 import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
@@ -57,7 +58,7 @@
 
     public abstract String basename();
 
-    public Path getFile(Path directory) throws /*unchecked*/ InvalidPathException {
+    public Path resolveAgainst(Path directory) throws /*unchecked*/ InvalidPathException {
         if (directory == null) {
             String sep = FileSystems.getDefault().getSeparator();
             return Paths.get(path.replace("/", sep));
@@ -67,6 +68,12 @@
         }
     }
 
+    public Path resolveAgainst(FileSystem fs) throws /*unchecked*/ InvalidPathException {
+        String sep = fs.getSeparator();
+        Path root = fs.getRootDirectories().iterator().next();
+        return root.resolve(path.replace("/", sep));
+    }
+
     @Override
     public int compareTo(RelativePath other) {
         return path.compareTo(other.path);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipArchive.java	Mon Dec 07 09:18:07 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-/*
- * Copyright (c) 2005, 2015, 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 com.sun.tools.javac.file;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Writer;
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
-import java.net.URI;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharsetDecoder;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import javax.tools.JavaFileObject;
-
-import com.sun.tools.javac.file.JavacFileManager.Archive;
-import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
-import com.sun.tools.javac.file.RelativePath.RelativeFile;
-import com.sun.tools.javac.util.DefinedBy;
-import com.sun.tools.javac.util.DefinedBy.Api;
-import com.sun.tools.javac.util.List;
-
-/**
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class ZipArchive implements Archive {
-
-    public ZipArchive(JavacFileManager fm, ZipFile zfile) throws IOException {
-        this(fm, zfile, true);
-    }
-
-    protected ZipArchive(JavacFileManager fm, ZipFile zfile, boolean initMap) throws IOException {
-        this.fileManager = fm;
-        this.zfile = zfile;
-        this.map = new HashMap<>();
-        if (initMap)
-            initMap();
-    }
-
-    protected void initMap() throws IOException {
-        for (Enumeration<? extends ZipEntry> e = zfile.entries(); e.hasMoreElements(); ) {
-            ZipEntry entry;
-            try {
-                entry = e.nextElement();
-            } catch (InternalError ex) {
-                IOException io = new IOException();
-                io.initCause(ex); // convenience constructors added in Mustang :-(
-                throw io;
-            }
-            addZipEntry(entry);
-        }
-    }
-
-    void addZipEntry(ZipEntry entry) {
-        String name = entry.getName();
-        int i = name.lastIndexOf('/');
-        RelativeDirectory dirname = new RelativeDirectory(name.substring(0, i+1));
-        String basename = name.substring(i+1);
-        if (basename.length() == 0)
-            return;
-        List<String> list = map.get(dirname);
-        if (list == null)
-            list = List.nil();
-        list = list.prepend(basename);
-        map.put(dirname, list);
-    }
-
-    public boolean contains(RelativePath name) {
-        RelativeDirectory dirname = name.dirname();
-        String basename = name.basename();
-        if (basename.length() == 0)
-            return false;
-        List<String> list = map.get(dirname);
-        return (list != null && list.contains(basename));
-    }
-
-    public List<String> getFiles(RelativeDirectory subdirectory) {
-        return map.get(subdirectory);
-    }
-
-    public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
-        ZipEntry ze = new RelativeFile(subdirectory, file).getZipEntry(zfile);
-        return new ZipFileObject(this, file, ze);
-    }
-
-    public Set<RelativeDirectory> getSubdirectories() {
-        return map.keySet();
-    }
-
-    public void close() throws IOException {
-        zfile.close();
-    }
-
-    @Override
-    public String toString() {
-        return "ZipArchive[" + zfile.getName() + "]";
-    }
-
-    private Path getAbsoluteFile() {
-        Path absFile = (absFileRef == null ? null : absFileRef.get());
-        if (absFile == null) {
-            absFile = Paths.get(zfile.getName()).toAbsolutePath();
-            absFileRef = new SoftReference<>(absFile);
-        }
-        return absFile;
-    }
-
-    /**
-     * The file manager that created this archive.
-     */
-    protected JavacFileManager fileManager;
-    /**
-     * The index for the contents of this archive.
-     */
-    protected final Map<RelativeDirectory,List<String>> map;
-    /**
-     * The zip file for the archive.
-     */
-    protected final ZipFile zfile;
-    /**
-     * A reference to the absolute filename for the zip file for the archive.
-     */
-    protected Reference<Path> absFileRef;
-
-    /**
-     * A subclass of JavaFileObject representing zip entries.
-     */
-    public static class ZipFileObject extends BaseFileObject {
-
-        private String name;
-        ZipArchive zarch;
-        ZipEntry entry;
-
-        protected ZipFileObject(ZipArchive zarch, String name, ZipEntry entry) {
-            super(zarch.fileManager);
-            this.zarch = zarch;
-            this.name = name;
-            this.entry = entry;
-        }
-
-        @DefinedBy(Api.COMPILER)
-        public URI toUri() {
-            Path zipFile = Paths.get(zarch.zfile.getName());
-            return createJarUri(zipFile, entry.getName());
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public String getName() {
-            return zarch.zfile.getName() + "(" + entry.getName() + ")";
-        }
-
-        @Override
-        public String getShortName() {
-            return Paths.get(zarch.zfile.getName()).getFileName() + "(" + entry + ")";
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public JavaFileObject.Kind getKind() {
-            return getKind(entry.getName());
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public InputStream openInputStream() throws IOException {
-            return zarch.zfile.getInputStream(entry);
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public OutputStream openOutputStream() throws IOException {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
-            CharBuffer cb = fileManager.getCachedContent(this);
-            if (cb == null) {
-                try (InputStream in = zarch.zfile.getInputStream(entry)) {
-                    ByteBuffer bb = fileManager.makeByteBuffer(in);
-                    JavaFileObject prev = fileManager.log.useSource(this);
-                    try {
-                        cb = fileManager.decode(bb, ignoreEncodingErrors);
-                    } finally {
-                        fileManager.log.useSource(prev);
-                    }
-                    fileManager.recycleByteBuffer(bb);
-                    if (!ignoreEncodingErrors) {
-                        fileManager.cache(this, cb);
-                    }
-                }
-            }
-            return cb;
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public Writer openWriter() throws IOException {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public long getLastModified() {
-            return entry.getTime();
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public boolean delete() {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
-            return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
-        }
-
-        @Override
-        protected String inferBinaryName(Iterable<? extends Path> path) {
-            String entryName = entry.getName();
-            return removeExtension(entryName).replace('/', '.');
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
-            Objects.requireNonNull(cn);
-            // null check
-            if (k == Kind.OTHER && getKind() != k) {
-                return false;
-            }
-            return name.equals(cn + k.extension);
-        }
-
-        /**
-         * Check if two file objects are equal.
-         * Two ZipFileObjects are equal if the absolute paths of the underlying
-         * zip files are equal and if the paths within those zip files are equal.
-         */
-        @Override
-        public boolean equals(Object other) {
-            if (this == other)
-                return true;
-
-            if (!(other instanceof ZipFileObject))
-                return false;
-
-            ZipFileObject o = (ZipFileObject) other;
-            return zarch.getAbsoluteFile().equals(o.zarch.getAbsoluteFile())
-                    && entry.getName().equals(o.entry.getName());
-        }
-
-        @Override
-        public int hashCode() {
-            return zarch.getAbsoluteFile().hashCode() + entry.getName().hashCode();
-        }
-    }
-
-}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndex.java	Mon Dec 07 09:18:07 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1171 +0,0 @@
-/*
- * Copyright (c) 2007, 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 com.sun.tools.javac.file;
-
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.zip.DataFormatException;
-import java.util.zip.Inflater;
-import java.util.zip.ZipException;
-
-import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
-import com.sun.tools.javac.file.RelativePath.RelativeFile;
-
-/**
- * This class implements the building of index of a zip archive and access to
- * its context. It also uses a prebuilt index if available.
- * It supports invocations where it will serialize an optimized zip index file
- * to disk.
- *
- * In order to use a secondary index file, set "usezipindex" in the Options
- * object when JavacFileManager is invoked. (You can pass "-XDusezipindex" on
- * the command line.)
- *
- * Location where to look for/generate optimized zip index files can be
- * provided using "{@code -XDcachezipindexdir=<directory>}". If this flag is not
- * provided, the default location is the value of the "java.io.tmpdir" system
- * property.
- *
- * If "-XDwritezipindexfiles" is specified, there will be new optimized index
- * file created for each archive, used by the compiler for compilation, at the
- * location specified by the "cachezipindexdir" option.
- *
- * If system property nonBatchMode option is specified the compiler will use
- * timestamp checking to reindex the zip files if it is needed. In batch mode
- * the timestamps are not checked and the compiler uses the cached indexes.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class ZipFileIndex {
-    private static final String MIN_CHAR = String.valueOf(Character.MIN_VALUE);
-    private static final String MAX_CHAR = String.valueOf(Character.MAX_VALUE);
-
-    public final static long NOT_MODIFIED = Long.MIN_VALUE;
-
-
-    private static final boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
-
-    private Map<RelativeDirectory, DirectoryEntry> directories =
-            Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
-    private Set<RelativeDirectory> allDirs =
-            Collections.<RelativeDirectory>emptySet();
-
-    // ZipFileIndex data entries
-    final Path zipFile;
-    private Reference<Path> absFileRef;
-    long zipFileLastModified = NOT_MODIFIED;
-    private RandomAccessFile zipRandomFile;
-    private Entry[] entries;
-
-    private boolean readFromIndex = false;
-    private Path zipIndexFile = null;
-    private boolean triedToReadIndex = false;
-    final RelativeDirectory symbolFilePrefix;
-    private final int symbolFilePrefixLength;
-    private boolean hasPopulatedData = false;
-    long lastReferenceTimeStamp = NOT_MODIFIED;
-
-    private final boolean usePreindexedCache;
-    private final String preindexedCacheLocation;
-
-    private boolean writeIndex = false;
-
-    private Map<String, SoftReference<RelativeDirectory>> relativeDirectoryCache = new HashMap<>();
-
-
-    public synchronized boolean isOpen() {
-        return (zipRandomFile != null);
-    }
-
-    ZipFileIndex(Path zipFile, RelativeDirectory symbolFilePrefix, boolean writeIndex,
-            boolean useCache, String cacheLocation) throws IOException {
-        this.zipFile = zipFile;
-        this.symbolFilePrefix = symbolFilePrefix;
-        this.symbolFilePrefixLength = (symbolFilePrefix == null ? 0 :
-            symbolFilePrefix.getPath().getBytes("UTF-8").length);
-        this.writeIndex = writeIndex;
-        this.usePreindexedCache = useCache;
-        this.preindexedCacheLocation = cacheLocation;
-
-        if (zipFile != null) {
-            this.zipFileLastModified = Files.getLastModifiedTime(zipFile).toMillis();
-        }
-
-        // Validate integrity of the zip file
-        checkIndex();
-    }
-
-    @Override
-    public String toString() {
-        return "ZipFileIndex[" + zipFile + "]";
-    }
-
-    // Just in case...
-    @Override
-    protected void finalize() throws Throwable {
-        closeFile();
-        super.finalize();
-    }
-
-    private boolean isUpToDate() {
-        try {
-            return (zipFile != null
-                    && ((!NON_BATCH_MODE) || zipFileLastModified == Files.getLastModifiedTime(zipFile).toMillis())
-                    && hasPopulatedData);
-        } catch (IOException ignore) {
-        }
-
-        return false;
-    }
-
-    /**
-     * Here we need to make sure that the ZipFileIndex is valid. Check the timestamp of the file and
-     * if its the same as the one at the time the index was build we don't need to reopen anything.
-     */
-    private void checkIndex() throws IOException {
-        boolean isUpToDate = true;
-        if (!isUpToDate()) {
-            closeFile();
-            isUpToDate = false;
-        }
-
-        if (zipRandomFile != null || isUpToDate) {
-            lastReferenceTimeStamp = System.currentTimeMillis();
-            return;
-        }
-
-        hasPopulatedData = true;
-
-        if (readIndex()) {
-            lastReferenceTimeStamp = System.currentTimeMillis();
-            return;
-        }
-
-        directories = Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
-        allDirs = Collections.<RelativeDirectory>emptySet();
-
-        try {
-            openFile();
-            long totalLength = zipRandomFile.length();
-            ZipDirectory directory = new ZipDirectory(zipRandomFile, 0L, totalLength, this);
-            directory.buildIndex();
-        } finally {
-            if (zipRandomFile != null) {
-                closeFile();
-            }
-        }
-
-        lastReferenceTimeStamp = System.currentTimeMillis();
-    }
-
-    private void openFile() throws FileNotFoundException {
-        if (zipRandomFile == null && zipFile != null) {
-            zipRandomFile = new RandomAccessFile(zipFile.toFile(), "r");
-        }
-    }
-
-    private void cleanupState() {
-        // Make sure there is a valid but empty index if the file doesn't exist
-        entries = Entry.EMPTY_ARRAY;
-        directories = Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
-        zipFileLastModified = NOT_MODIFIED;
-        allDirs = Collections.<RelativeDirectory>emptySet();
-    }
-
-    public synchronized void close() {
-        writeIndex();
-        closeFile();
-    }
-
-    private void closeFile() {
-        if (zipRandomFile != null) {
-            try {
-                zipRandomFile.close();
-            } catch (IOException ex) {
-            }
-            zipRandomFile = null;
-        }
-    }
-
-    /**
-     * Returns the ZipFileIndexEntry for a path, if there is one.
-     */
-    synchronized Entry getZipIndexEntry(RelativePath path) {
-        try {
-            checkIndex();
-            DirectoryEntry de = directories.get(path.dirname());
-            String lookFor = path.basename();
-            return (de == null) ? null : de.getEntry(lookFor);
-        }
-        catch (IOException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Returns a javac List of filenames within a directory in the ZipFileIndex.
-     */
-    public synchronized com.sun.tools.javac.util.List<String> getFiles(RelativeDirectory path) {
-        try {
-            checkIndex();
-
-            DirectoryEntry de = directories.get(path);
-            com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getFiles();
-
-            if (ret == null) {
-                return com.sun.tools.javac.util.List.<String>nil();
-            }
-            return ret;
-        }
-        catch (IOException e) {
-            return com.sun.tools.javac.util.List.<String>nil();
-        }
-    }
-
-    public synchronized List<String> getDirectories(RelativeDirectory path) {
-        try {
-            checkIndex();
-
-            DirectoryEntry de = directories.get(path);
-            com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getDirectories();
-
-            if (ret == null) {
-                return com.sun.tools.javac.util.List.<String>nil();
-            }
-
-            return ret;
-        }
-        catch (IOException e) {
-            return com.sun.tools.javac.util.List.<String>nil();
-        }
-    }
-
-    public synchronized Set<RelativeDirectory> getAllDirectories() {
-        try {
-            checkIndex();
-            if (allDirs == Collections.EMPTY_SET) {
-                allDirs = new java.util.LinkedHashSet<>(directories.keySet());
-            }
-
-            return allDirs;
-        }
-        catch (IOException e) {
-            return Collections.<RelativeDirectory>emptySet();
-        }
-    }
-
-    /**
-     * Tests if a specific path exists in the zip.  This method will return true
-     * for file entries and directories.
-     *
-     * @param path A path within the zip.
-     * @return True if the path is a file or dir, false otherwise.
-     */
-    public synchronized boolean contains(RelativePath path) {
-        try {
-            checkIndex();
-            return getZipIndexEntry(path) != null;
-        }
-        catch (IOException e) {
-            return false;
-        }
-    }
-
-    public synchronized boolean isDirectory(RelativePath path) throws IOException {
-        // The top level in a zip file is always a directory.
-        if (path.getPath().length() == 0) {
-            lastReferenceTimeStamp = System.currentTimeMillis();
-            return true;
-        }
-
-        checkIndex();
-        return directories.get(path) != null;
-    }
-
-    public synchronized long getLastModified(RelativeFile path) throws IOException {
-        Entry entry = getZipIndexEntry(path);
-        if (entry == null)
-            throw new FileNotFoundException();
-        return entry.getLastModified();
-    }
-
-    public synchronized int length(RelativeFile path) throws IOException {
-        Entry entry = getZipIndexEntry(path);
-        if (entry == null)
-            throw new FileNotFoundException();
-
-        if (entry.isDir) {
-            return 0;
-        }
-
-        byte[] header = getHeader(entry);
-        // entry is not compressed?
-        if (get2ByteLittleEndian(header, 8) == 0) {
-            return entry.compressedSize;
-        } else {
-            return entry.size;
-        }
-    }
-
-    public synchronized byte[] read(RelativeFile path) throws IOException {
-        Entry entry = getZipIndexEntry(path);
-        if (entry == null)
-            throw new FileNotFoundException("Path not found in ZIP: " + path.path);
-        return read(entry);
-    }
-
-    synchronized byte[] read(Entry entry) throws IOException {
-        openFile();
-        byte[] result = readBytes(entry);
-        closeFile();
-        return result;
-    }
-
-    public synchronized int read(RelativeFile path, byte[] buffer) throws IOException {
-        Entry entry = getZipIndexEntry(path);
-        if (entry == null)
-            throw new FileNotFoundException();
-        return read(entry, buffer);
-    }
-
-    synchronized int read(Entry entry, byte[] buffer)
-            throws IOException {
-        int result = readBytes(entry, buffer);
-        return  result;
-    }
-
-    private byte[] readBytes(Entry entry) throws IOException {
-        byte[] header = getHeader(entry);
-        int csize = entry.compressedSize;
-        byte[] cbuf = new byte[csize];
-        zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
-        zipRandomFile.readFully(cbuf, 0, csize);
-
-        // is this compressed - offset 8 in the ZipEntry header
-        if (get2ByteLittleEndian(header, 8) == 0)
-            return cbuf;
-
-        int size = entry.size;
-        byte[] buf = new byte[size];
-        if (inflate(cbuf, buf) != size)
-            throw new ZipException("corrupted zip file");
-
-        return buf;
-    }
-
-    /**
-     *
-     */
-    private int readBytes(Entry entry, byte[] buffer) throws IOException {
-        byte[] header = getHeader(entry);
-
-        // entry is not compressed?
-        if (get2ByteLittleEndian(header, 8) == 0) {
-            zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
-            int offset = 0;
-            int size = buffer.length;
-            while (offset < size) {
-                int count = zipRandomFile.read(buffer, offset, size - offset);
-                if (count == -1)
-                    break;
-                offset += count;
-            }
-            return entry.size;
-        }
-
-        int csize = entry.compressedSize;
-        byte[] cbuf = new byte[csize];
-        zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
-        zipRandomFile.readFully(cbuf, 0, csize);
-
-        int count = inflate(cbuf, buffer);
-        if (count == -1)
-            throw new ZipException("corrupted zip file");
-
-        return entry.size;
-    }
-
-    //----------------------------------------------------------------------------
-    // Zip utilities
-    //----------------------------------------------------------------------------
-
-    private byte[] getHeader(Entry entry) throws IOException {
-        zipRandomFile.seek(entry.offset);
-        byte[] header = new byte[30];
-        zipRandomFile.readFully(header);
-        if (get4ByteLittleEndian(header, 0) != 0x04034b50)
-            throw new ZipException("corrupted zip file");
-        if ((get2ByteLittleEndian(header, 6) & 1) != 0)
-            throw new ZipException("encrypted zip file"); // offset 6 in the header of the ZipFileEntry
-        return header;
-    }
-
-  /*
-   * Inflate using the java.util.zip.Inflater class
-   */
-    private SoftReference<Inflater> inflaterRef;
-    private int inflate(byte[] src, byte[] dest) {
-        Inflater inflater = (inflaterRef == null ? null : inflaterRef.get());
-
-        // construct the inflater object or reuse an existing one
-        if (inflater == null)
-            inflaterRef = new SoftReference<>(inflater = new Inflater(true));
-
-        inflater.reset();
-        inflater.setInput(src);
-        try {
-            return inflater.inflate(dest);
-        } catch (DataFormatException ex) {
-            return -1;
-        }
-    }
-
-    /**
-     * return the two bytes buf[pos], buf[pos+1] as an unsigned integer in little
-     * endian format.
-     */
-    private static int get2ByteLittleEndian(byte[] buf, int pos) {
-        return (buf[pos] & 0xFF) + ((buf[pos+1] & 0xFF) << 8);
-    }
-
-    /**
-     * return the 4 bytes buf[i..i+3] as an integer in little endian format.
-     */
-    private static int get4ByteLittleEndian(byte[] buf, int pos) {
-        return (buf[pos] & 0xFF) + ((buf[pos + 1] & 0xFF) << 8) +
-                ((buf[pos + 2] & 0xFF) << 16) + ((buf[pos + 3] & 0xFF) << 24);
-    }
-
-    /* ----------------------------------------------------------------------------
-     * ZipDirectory
-     * ----------------------------------------------------------------------------*/
-
-    private class ZipDirectory {
-        private RelativeDirectory lastDir;
-        private int lastStart;
-        private int lastLen;
-
-        byte[] zipDir;
-        RandomAccessFile zipRandomFile = null;
-        ZipFileIndex zipFileIndex = null;
-
-        public ZipDirectory(RandomAccessFile zipRandomFile, long start, long end, ZipFileIndex index) throws IOException {
-            this.zipRandomFile = zipRandomFile;
-            this.zipFileIndex = index;
-            hasValidHeader();
-            findCENRecord(start, end);
-        }
-
-        /*
-         * the zip entry signature should be at offset 0, otherwise allow the
-         * calling logic to take evasive action by throwing ZipFormatException.
-         */
-        private boolean hasValidHeader() throws IOException {
-            final long pos = zipRandomFile.getFilePointer();
-            try {
-                if (zipRandomFile.read() == 'P') {
-                    if (zipRandomFile.read() == 'K') {
-                        if (zipRandomFile.read() == 0x03) {
-                            if (zipRandomFile.read() == 0x04) {
-                                return true;
-                            }
-                        }
-                    }
-                }
-            } finally {
-                zipRandomFile.seek(pos);
-            }
-            throw new ZipFormatException("invalid zip magic");
-        }
-
-        /*
-         * Reads zip file central directory.
-         * For more details see readCEN in zip_util.c from the JDK sources.
-         * This is a Java port of that function.
-         */
-        private void findCENRecord(long start, long end) throws IOException {
-            long totalLength = end - start;
-            int endbuflen = 1024;
-            byte[] endbuf = new byte[endbuflen];
-            long endbufend = end - start;
-
-            // There is a variable-length field after the dir offset record. We need to do consequential search.
-            while (endbufend >= 22) {
-                if (endbufend < endbuflen)
-                    endbuflen = (int)endbufend;
-                long endbufpos = endbufend - endbuflen;
-                zipRandomFile.seek(start + endbufpos);
-                zipRandomFile.readFully(endbuf, 0, endbuflen);
-                int i = endbuflen - 22;
-                while (i >= 0 &&
-                        !(endbuf[i] == 0x50 &&
-                        endbuf[i + 1] == 0x4b &&
-                        endbuf[i + 2] == 0x05 &&
-                        endbuf[i + 3] == 0x06 &&
-                        endbufpos + i + 22 +
-                        get2ByteLittleEndian(endbuf, i + 20) == totalLength)) {
-                    i--;
-                }
-
-                if (i >= 0) {
-                    zipDir = new byte[get4ByteLittleEndian(endbuf, i + 12)];
-                    int sz = get4ByteLittleEndian(endbuf, i + 16);
-                    // a negative offset or the entries field indicates a
-                    // potential zip64 archive
-                    if (sz < 0 || get2ByteLittleEndian(endbuf, i + 10) == 0xffff) {
-                        throw new ZipFormatException("detected a zip64 archive");
-                    }
-                    zipRandomFile.seek(start + sz);
-                    zipRandomFile.readFully(zipDir, 0, zipDir.length);
-                    return;
-                } else {
-                    endbufend = endbufpos + 21;
-                }
-            }
-            throw new ZipException("cannot read zip file");
-        }
-
-        private void buildIndex() throws IOException {
-            int len = zipDir.length;
-
-            // Add each of the files
-            if (len > 0) {
-                directories = new LinkedHashMap<>();
-                ArrayList<Entry> entryList = new ArrayList<>();
-                for (int pos = 0; pos < len; ) {
-                    pos = readEntry(pos, entryList, directories);
-                }
-
-                // Add the accumulated dirs into the same list
-                for (RelativeDirectory d: directories.keySet()) {
-                    // use shared RelativeDirectory objects for parent dirs
-                    RelativeDirectory parent = getRelativeDirectory(d.dirname().getPath());
-                    String file = d.basename();
-                    Entry zipFileIndexEntry = new Entry(parent, file);
-                    zipFileIndexEntry.isDir = true;
-                    entryList.add(zipFileIndexEntry);
-                }
-
-                entries = entryList.toArray(new Entry[entryList.size()]);
-                Arrays.sort(entries);
-            } else {
-                cleanupState();
-            }
-        }
-
-        private int readEntry(int pos, List<Entry> entryList,
-                Map<RelativeDirectory, DirectoryEntry> directories) throws IOException {
-            if (get4ByteLittleEndian(zipDir, pos) != 0x02014b50) {
-                throw new ZipException("cannot read zip file entry");
-            }
-
-            int dirStart = pos + 46;
-            int fileStart = dirStart;
-            int fileEnd = fileStart + get2ByteLittleEndian(zipDir, pos + 28);
-
-            if (zipFileIndex.symbolFilePrefixLength != 0 &&
-                    ((fileEnd - fileStart) >= symbolFilePrefixLength)) {
-                dirStart += zipFileIndex.symbolFilePrefixLength;
-               fileStart += zipFileIndex.symbolFilePrefixLength;
-            }
-            // Force any '\' to '/'. Keep the position of the last separator.
-            for (int index = fileStart; index < fileEnd; index++) {
-                byte nextByte = zipDir[index];
-                if (nextByte == (byte)'\\') {
-                    zipDir[index] = (byte)'/';
-                    fileStart = index + 1;
-                } else if (nextByte == (byte)'/') {
-                    fileStart = index + 1;
-                }
-            }
-
-            RelativeDirectory directory = null;
-            if (fileStart == dirStart)
-                directory = getRelativeDirectory("");
-            else if (lastDir != null && lastLen == fileStart - dirStart - 1) {
-                int index = lastLen - 1;
-                while (zipDir[lastStart + index] == zipDir[dirStart + index]) {
-                    if (index == 0) {
-                        directory = lastDir;
-                        break;
-                    }
-                    index--;
-                }
-            }
-
-            // Sub directories
-            if (directory == null) {
-                lastStart = dirStart;
-                lastLen = fileStart - dirStart - 1;
-
-                directory = getRelativeDirectory(new String(zipDir, dirStart, lastLen, "UTF-8"));
-                lastDir = directory;
-
-                // Enter also all the parent directories
-                RelativeDirectory tempDirectory = directory;
-
-                while (directories.get(tempDirectory) == null) {
-                    directories.put(tempDirectory, new DirectoryEntry(tempDirectory, zipFileIndex));
-                    if (tempDirectory.path.indexOf("/") == tempDirectory.path.length() - 1)
-                        break;
-                    else {
-                        // use shared RelativeDirectory objects for parent dirs
-                        tempDirectory = getRelativeDirectory(tempDirectory.dirname().getPath());
-                    }
-                }
-            }
-            else {
-                if (directories.get(directory) == null) {
-                    directories.put(directory, new DirectoryEntry(directory, zipFileIndex));
-                }
-            }
-
-            // For each dir create also a file
-            if (fileStart != fileEnd) {
-                Entry entry = new Entry(directory,
-                        new String(zipDir, fileStart, fileEnd - fileStart, "UTF-8"));
-
-                entry.setNativeTime(get4ByteLittleEndian(zipDir, pos + 12));
-                entry.compressedSize = get4ByteLittleEndian(zipDir, pos + 20);
-                entry.size = get4ByteLittleEndian(zipDir, pos + 24);
-                entry.offset = get4ByteLittleEndian(zipDir, pos + 42);
-                entryList.add(entry);
-            }
-
-            return pos + 46 +
-                    get2ByteLittleEndian(zipDir, pos + 28) +
-                    get2ByteLittleEndian(zipDir, pos + 30) +
-                    get2ByteLittleEndian(zipDir, pos + 32);
-        }
-    }
-
-    /**
-     * Returns the last modified timestamp of a zip file.
-     * @return long
-     */
-    public long getZipFileLastModified() throws IOException {
-        synchronized (this) {
-            checkIndex();
-            return zipFileLastModified;
-        }
-    }
-
-    /** ------------------------------------------------------------------------
-     *  DirectoryEntry class
-     * -------------------------------------------------------------------------*/
-
-    static class DirectoryEntry {
-        private boolean filesInited;
-        private boolean directoriesInited;
-        private boolean zipFileEntriesInited;
-        private boolean entriesInited;
-
-        private long writtenOffsetOffset = 0;
-
-        private RelativeDirectory dirName;
-
-        private com.sun.tools.javac.util.List<String> zipFileEntriesFiles = com.sun.tools.javac.util.List.<String>nil();
-        private com.sun.tools.javac.util.List<String> zipFileEntriesDirectories = com.sun.tools.javac.util.List.<String>nil();
-        private com.sun.tools.javac.util.List<Entry>  zipFileEntries = com.sun.tools.javac.util.List.<Entry>nil();
-
-        private List<Entry> entries = new ArrayList<>();
-
-        private ZipFileIndex zipFileIndex;
-
-        private int numEntries;
-
-        DirectoryEntry(RelativeDirectory dirName, ZipFileIndex index) {
-            filesInited = false;
-            directoriesInited = false;
-            entriesInited = false;
-
-            this.dirName = dirName;
-            this.zipFileIndex = index;
-        }
-
-        private com.sun.tools.javac.util.List<String> getFiles() {
-            if (!filesInited) {
-                initEntries();
-                for (Entry e : entries) {
-                    if (!e.isDir) {
-                        zipFileEntriesFiles = zipFileEntriesFiles.append(e.name);
-                    }
-                }
-                filesInited = true;
-            }
-            return zipFileEntriesFiles;
-        }
-
-        private com.sun.tools.javac.util.List<String> getDirectories() {
-            if (!directoriesInited) {
-                initEntries();
-                for (Entry e : entries) {
-                    if (e.isDir) {
-                        zipFileEntriesDirectories = zipFileEntriesDirectories.append(e.name);
-                    }
-                }
-                directoriesInited = true;
-            }
-            return zipFileEntriesDirectories;
-        }
-
-        private com.sun.tools.javac.util.List<Entry> getEntries() {
-            if (!zipFileEntriesInited) {
-                initEntries();
-                zipFileEntries = com.sun.tools.javac.util.List.nil();
-                for (Entry zfie : entries) {
-                    zipFileEntries = zipFileEntries.append(zfie);
-                }
-                zipFileEntriesInited = true;
-            }
-            return zipFileEntries;
-        }
-
-        private Entry getEntry(String rootName) {
-            initEntries();
-            int index = Collections.binarySearch(entries, new Entry(dirName, rootName));
-            if (index < 0) {
-                return null;
-            }
-
-            return entries.get(index);
-        }
-
-        private void initEntries() {
-            if (entriesInited) {
-                return;
-            }
-
-            if (!zipFileIndex.readFromIndex) {
-                int from = -Arrays.binarySearch(zipFileIndex.entries,
-                        new Entry(dirName, ZipFileIndex.MIN_CHAR)) - 1;
-                int to = -Arrays.binarySearch(zipFileIndex.entries,
-                        new Entry(dirName, MAX_CHAR)) - 1;
-
-                for (int i = from; i < to; i++) {
-                    entries.add(zipFileIndex.entries[i]);
-                }
-            } else {
-                Path indexFile = zipFileIndex.getIndexFile();
-                if (indexFile != null) {
-                    RandomAccessFile raf = null;
-                    try {
-                        raf = new RandomAccessFile(indexFile.toFile(), "r");
-                        raf.seek(writtenOffsetOffset);
-
-                        for (int nFiles = 0; nFiles < numEntries; nFiles++) {
-                            // Read the name bytes
-                            int zfieNameBytesLen = raf.readInt();
-                            byte [] zfieNameBytes = new byte[zfieNameBytesLen];
-                            raf.read(zfieNameBytes);
-                            String eName = new String(zfieNameBytes, "UTF-8");
-
-                            // Read isDir
-                            boolean eIsDir = raf.readByte() == (byte)0 ? false : true;
-
-                            // Read offset of bytes in the real Jar/Zip file
-                            int eOffset = raf.readInt();
-
-                            // Read size of the file in the real Jar/Zip file
-                            int eSize = raf.readInt();
-
-                            // Read compressed size of the file in the real Jar/Zip file
-                            int eCsize = raf.readInt();
-
-                            // Read java time stamp of the file in the real Jar/Zip file
-                            long eJavaTimestamp = raf.readLong();
-
-                            Entry rfie = new Entry(dirName, eName);
-                            rfie.isDir = eIsDir;
-                            rfie.offset = eOffset;
-                            rfie.size = eSize;
-                            rfie.compressedSize = eCsize;
-                            rfie.javatime = eJavaTimestamp;
-                            entries.add(rfie);
-                        }
-                    } catch (Throwable t) {
-                        // Do nothing
-                    } finally {
-                        try {
-                            if (raf != null) {
-                                raf.close();
-                            }
-                        } catch (Throwable t) {
-                            // Do nothing
-                        }
-                    }
-                }
-            }
-
-            entriesInited = true;
-        }
-
-        List<Entry> getEntriesAsCollection() {
-            initEntries();
-
-            return entries;
-        }
-    }
-
-    private boolean readIndex() {
-        if (triedToReadIndex || !usePreindexedCache) {
-            return false;
-        }
-
-        boolean ret = false;
-        synchronized (this) {
-            triedToReadIndex = true;
-            RandomAccessFile raf = null;
-            try {
-                Path indexFileName = getIndexFile();
-                raf = new RandomAccessFile(indexFileName.toFile(), "r");
-
-                long fileStamp = raf.readLong();
-                if (Files.getLastModifiedTime(zipFile).toMillis() != fileStamp) {
-                    ret = false;
-                } else {
-                    directories = new LinkedHashMap<>();
-                    int numDirs = raf.readInt();
-                    for (int nDirs = 0; nDirs < numDirs; nDirs++) {
-                        int dirNameBytesLen = raf.readInt();
-                        byte [] dirNameBytes = new byte[dirNameBytesLen];
-                        raf.read(dirNameBytes);
-
-                        RelativeDirectory dirNameStr = getRelativeDirectory(new String(dirNameBytes, "UTF-8"));
-                        DirectoryEntry de = new DirectoryEntry(dirNameStr, this);
-                        de.numEntries = raf.readInt();
-                        de.writtenOffsetOffset = raf.readLong();
-                        directories.put(dirNameStr, de);
-                    }
-                    ret = true;
-                    zipFileLastModified = fileStamp;
-                }
-            } catch (Throwable t) {
-                // Do nothing
-            } finally {
-                if (raf != null) {
-                    try {
-                        raf.close();
-                    } catch (Throwable tt) {
-                        // Do nothing
-                    }
-                }
-            }
-            if (ret == true) {
-                readFromIndex = true;
-            }
-        }
-
-        return ret;
-    }
-
-    private boolean writeIndex() {
-        boolean ret = false;
-        if (readFromIndex || !usePreindexedCache) {
-            return true;
-        }
-
-        if (!writeIndex) {
-            return true;
-        }
-
-        Path indexFile = getIndexFile();
-        if (indexFile == null) {
-            return false;
-        }
-
-        RandomAccessFile raf = null;
-        long writtenSoFar = 0;
-        try {
-            raf = new RandomAccessFile(indexFile.toFile(), "rw");
-
-            raf.writeLong(zipFileLastModified);
-            writtenSoFar += 8;
-
-            List<DirectoryEntry> directoriesToWrite = new ArrayList<>();
-            Map<RelativeDirectory, Long> offsets = new HashMap<>();
-            raf.writeInt(directories.keySet().size());
-            writtenSoFar += 4;
-
-            for (RelativeDirectory dirName: directories.keySet()) {
-                DirectoryEntry dirEntry = directories.get(dirName);
-
-                directoriesToWrite.add(dirEntry);
-
-                // Write the dir name bytes
-                byte [] dirNameBytes = dirName.getPath().getBytes("UTF-8");
-                int dirNameBytesLen = dirNameBytes.length;
-                raf.writeInt(dirNameBytesLen);
-                writtenSoFar += 4;
-
-                raf.write(dirNameBytes);
-                writtenSoFar += dirNameBytesLen;
-
-                // Write the number of files in the dir
-                List<Entry> dirEntries = dirEntry.getEntriesAsCollection();
-                raf.writeInt(dirEntries.size());
-                writtenSoFar += 4;
-
-                offsets.put(dirName, new Long(writtenSoFar));
-
-                // Write the offset of the file's data in the dir
-                dirEntry.writtenOffsetOffset = 0L;
-                raf.writeLong(0L);
-                writtenSoFar += 8;
-            }
-
-            for (DirectoryEntry de : directoriesToWrite) {
-                // Fix up the offset in the directory table
-                long currFP = raf.getFilePointer();
-
-                long offsetOffset = offsets.get(de.dirName).longValue();
-                raf.seek(offsetOffset);
-                raf.writeLong(writtenSoFar);
-
-                raf.seek(currFP);
-
-                // Now write each of the files in the DirectoryEntry
-                List<Entry> list = de.getEntriesAsCollection();
-                for (Entry zfie : list) {
-                    // Write the name bytes
-                    byte [] zfieNameBytes = zfie.name.getBytes("UTF-8");
-                    int zfieNameBytesLen = zfieNameBytes.length;
-                    raf.writeInt(zfieNameBytesLen);
-                    writtenSoFar += 4;
-                    raf.write(zfieNameBytes);
-                    writtenSoFar += zfieNameBytesLen;
-
-                    // Write isDir
-                    raf.writeByte(zfie.isDir ? (byte)1 : (byte)0);
-                    writtenSoFar += 1;
-
-                    // Write offset of bytes in the real Jar/Zip file
-                    raf.writeInt(zfie.offset);
-                    writtenSoFar += 4;
-
-                    // Write size of the file in the real Jar/Zip file
-                    raf.writeInt(zfie.size);
-                    writtenSoFar += 4;
-
-                    // Write compressed size of the file in the real Jar/Zip file
-                    raf.writeInt(zfie.compressedSize);
-                    writtenSoFar += 4;
-
-                    // Write java time stamp of the file in the real Jar/Zip file
-                    raf.writeLong(zfie.getLastModified());
-                    writtenSoFar += 8;
-                }
-            }
-        } catch (Throwable t) {
-            // Do nothing
-        } finally {
-            try {
-                if (raf != null) {
-                    raf.close();
-                }
-            } catch(IOException ioe) {
-                // Do nothing
-            }
-        }
-
-        return ret;
-    }
-
-    public boolean writeZipIndex() {
-        synchronized (this) {
-            return writeIndex();
-        }
-    }
-
-    private Path getIndexFile() {
-        if (zipIndexFile == null) {
-            if (zipFile == null) {
-                return null;
-            }
-
-            zipIndexFile = Paths.get((preindexedCacheLocation == null ? "" : preindexedCacheLocation) +
-                    zipFile.getFileName() + ".index");
-        }
-
-        return zipIndexFile;
-    }
-
-    public Path getZipFile() {
-        return zipFile;
-    }
-
-    Path getAbsoluteFile() {
-        Path absFile = (absFileRef == null ? null : absFileRef.get());
-        if (absFile == null) {
-            absFile = zipFile.toAbsolutePath();
-            absFileRef = new SoftReference<>(absFile);
-        }
-        return absFile;
-    }
-
-    private RelativeDirectory getRelativeDirectory(String path) {
-        RelativeDirectory rd;
-        SoftReference<RelativeDirectory> ref = relativeDirectoryCache.get(path);
-        if (ref != null) {
-            rd = ref.get();
-            if (rd != null)
-                return rd;
-        }
-        rd = new RelativeDirectory(path);
-        relativeDirectoryCache.put(path, new SoftReference<>(rd));
-        return rd;
-    }
-
-    static class Entry implements Comparable<Entry> {
-        public static final Entry[] EMPTY_ARRAY = {};
-
-        // Directory related
-        RelativeDirectory dir;
-        boolean isDir;
-
-        // File related
-        String name;
-
-        int offset;
-        int size;
-        int compressedSize;
-        long javatime;
-
-        private int nativetime;
-
-        public Entry(RelativePath path) {
-            this(path.dirname(), path.basename());
-        }
-
-        public Entry(RelativeDirectory directory, String name) {
-            this.dir = directory;
-            this.name = name;
-        }
-
-        public String getName() {
-            return new RelativeFile(dir, name).getPath();
-        }
-
-        public String getFileName() {
-            return name;
-        }
-
-        public long getLastModified() {
-            if (javatime == 0) {
-                    javatime = dosToJavaTime(nativetime);
-            }
-            return javatime;
-        }
-
-        // based on dosToJavaTime in java.util.Zip, but avoiding the
-        // use of deprecated Date constructor
-        private static long dosToJavaTime(int dtime) {
-            Calendar c = Calendar.getInstance();
-            c.set(Calendar.YEAR,        ((dtime >> 25) & 0x7f) + 1980);
-            c.set(Calendar.MONTH,       ((dtime >> 21) & 0x0f) - 1);
-            c.set(Calendar.DATE,        ((dtime >> 16) & 0x1f));
-            c.set(Calendar.HOUR_OF_DAY, ((dtime >> 11) & 0x1f));
-            c.set(Calendar.MINUTE,      ((dtime >>  5) & 0x3f));
-            c.set(Calendar.SECOND,      ((dtime <<  1) & 0x3e));
-            c.set(Calendar.MILLISECOND, 0);
-            return c.getTimeInMillis();
-        }
-
-        void setNativeTime(int natTime) {
-            nativetime = natTime;
-        }
-
-        public boolean isDirectory() {
-            return isDir;
-        }
-
-        public int compareTo(Entry other) {
-            RelativeDirectory otherD = other.dir;
-            if (dir != otherD) {
-                int c = dir.compareTo(otherD);
-                if (c != 0)
-                    return c;
-            }
-            return name.compareTo(other.name);
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (!(o instanceof Entry))
-                return false;
-            Entry other = (Entry) o;
-            return dir.equals(other.dir) && name.equals(other.name);
-        }
-
-        @Override
-        public int hashCode() {
-            int hash = 7;
-            hash = 97 * hash + (this.dir != null ? this.dir.hashCode() : 0);
-            hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0);
-            return hash;
-        }
-
-        @Override
-        public String toString() {
-            return isDir ? ("Dir:" + dir + " : " + name) :
-                (dir + ":" + name);
-        }
-    }
-
-    /*
-     * Exception primarily used to implement a failover, used exclusively here.
-     */
-
-    static final class ZipFormatException extends IOException {
-        private static final long serialVersionUID = 8000196834066748623L;
-        protected ZipFormatException(String message) {
-            super(message);
-        }
-
-        protected ZipFormatException(String message, Throwable cause) {
-            super(message, cause);
-        }
-    }
-}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java	Mon Dec 07 09:18:07 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,247 +0,0 @@
-/*
- * Copyright (c) 2005, 2015, 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 com.sun.tools.javac.file;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Writer;
-import java.net.URI;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharsetDecoder;
-import java.nio.file.Path;
-import java.util.Objects;
-import java.util.Set;
-
-import javax.tools.JavaFileObject;
-
-import com.sun.tools.javac.file.JavacFileManager.Archive;
-import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
-import com.sun.tools.javac.file.RelativePath.RelativeFile;
-import com.sun.tools.javac.util.Assert;
-import com.sun.tools.javac.util.DefinedBy;
-import com.sun.tools.javac.util.DefinedBy.Api;
-import com.sun.tools.javac.util.List;
-
-/**
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class ZipFileIndexArchive implements Archive {
-
-    private final ZipFileIndex zfIndex;
-    private final JavacFileManager fileManager;
-
-    public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException {
-        super();
-        this.fileManager = fileManager;
-        this.zfIndex = zdir;
-    }
-
-    public boolean contains(RelativePath name) {
-        return zfIndex.contains(name);
-    }
-
-    public List<String> getFiles(RelativeDirectory subdirectory) {
-        return zfIndex.getFiles(subdirectory);
-    }
-
-    public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
-        RelativeFile fullZipFileName = new RelativeFile(subdirectory, file);
-        ZipFileIndex.Entry entry = zfIndex.getZipIndexEntry(fullZipFileName);
-        JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile());
-        return ret;
-    }
-
-    public Set<RelativeDirectory> getSubdirectories() {
-        return zfIndex.getAllDirectories();
-    }
-
-    public void close() throws IOException {
-        zfIndex.close();
-    }
-
-    @Override
-    public String toString() {
-        return "ZipFileIndexArchive[" + zfIndex + "]";
-    }
-
-    /**
-     * A subclass of JavaFileObject representing zip entries using the com.sun.tools.javac.file.ZipFileIndex implementation.
-     */
-    public static class ZipFileIndexFileObject extends BaseFileObject {
-
-        /** The entry's name.
-         */
-        private String name;
-
-        /** The zipfile containing the entry.
-         */
-        ZipFileIndex zfIndex;
-
-        /** The underlying zip entry object.
-         */
-        ZipFileIndex.Entry entry;
-
-        /** The name of the zip file where this entry resides.
-         */
-        Path zipName;
-
-
-        ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndex.Entry entry, Path zipFileName) {
-            super(fileManager);
-            this.name = entry.getFileName();
-            this.zfIndex = zfIndex;
-            this.entry = entry;
-            this.zipName = zipFileName;
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public URI toUri() {
-            return createJarUri(zipName, getPrefixedEntryName());
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public String getName() {
-            return zipName + "(" + getPrefixedEntryName() + ")";
-        }
-
-        @Override
-        public String getShortName() {
-            return zipName.getFileName() + "(" + entry.getName() + ")";
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public JavaFileObject.Kind getKind() {
-            return getKind(entry.getName());
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public InputStream openInputStream() throws IOException {
-            Assert.checkNonNull(entry); // see constructor
-            return new ByteArrayInputStream(zfIndex.read(entry));
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public OutputStream openOutputStream() throws IOException {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
-            CharBuffer cb = fileManager.getCachedContent(this);
-            if (cb == null) {
-                try (InputStream in = new ByteArrayInputStream(zfIndex.read(entry))) {
-                    ByteBuffer bb = fileManager.makeByteBuffer(in);
-                    JavaFileObject prev = fileManager.log.useSource(this);
-                    try {
-                        cb = fileManager.decode(bb, ignoreEncodingErrors);
-                    } finally {
-                        fileManager.log.useSource(prev);
-                    }
-                    fileManager.recycleByteBuffer(bb); // save for next time
-                    if (!ignoreEncodingErrors)
-                        fileManager.cache(this, cb);
-                }
-            }
-            return cb;
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public Writer openWriter() throws IOException {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public long getLastModified() {
-            return entry.getLastModified();
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public boolean delete() {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
-            return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
-        }
-
-        @Override
-        protected String inferBinaryName(Iterable<? extends Path> path) {
-            String entryName = entry.getName();
-            if (zfIndex.symbolFilePrefix != null) {
-                String prefix = zfIndex.symbolFilePrefix.path;
-                if (entryName.startsWith(prefix))
-                    entryName = entryName.substring(prefix.length());
-            }
-            return removeExtension(entryName).replace('/', '.');
-        }
-
-        @Override @DefinedBy(Api.COMPILER)
-        public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
-            Objects.requireNonNull(cn);
-            if (k == Kind.OTHER && getKind() != k)
-                return false;
-            return name.equals(cn + k.extension);
-        }
-
-        /**
-         * Check if two file objects are equal.
-         * Two ZipFileIndexFileObjects are equal if the absolute paths of the underlying
-         * zip files are equal and if the paths within those zip files are equal.
-         */
-        @Override
-        public boolean equals(Object other) {
-            if (this == other)
-                return true;
-
-            if (!(other instanceof ZipFileIndexFileObject))
-                return false;
-
-            ZipFileIndexFileObject o = (ZipFileIndexFileObject) other;
-            return zfIndex.getAbsoluteFile().equals(o.zfIndex.getAbsoluteFile())
-                    && entry.equals(o.entry);
-        }
-
-        @Override
-        public int hashCode() {
-            return zfIndex.getAbsoluteFile().hashCode() + entry.hashCode();
-        }
-
-        private String getPrefixedEntryName() {
-            if (zfIndex.symbolFilePrefix != null)
-                return zfIndex.symbolFilePrefix.path + entry.getName();
-            else
-                return entry.getName();
-        }
-    }
-
-}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndexCache.java	Mon Dec 07 09:18:07 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 2007, 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 com.sun.tools.javac.file;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
-import com.sun.tools.javac.util.Context;
-
-
-/** A cache for ZipFileIndex objects. */
-public class ZipFileIndexCache {
-
-    private final Map<Path, ZipFileIndex> map = new HashMap<>();
-
-    /** Get a shared instance of the cache. */
-    private static ZipFileIndexCache sharedInstance;
-    public synchronized static ZipFileIndexCache getSharedInstance() {
-        if (sharedInstance == null)
-            sharedInstance = new ZipFileIndexCache();
-        return sharedInstance;
-    }
-
-    /** Get a context-specific instance of a cache. */
-    public static ZipFileIndexCache instance(Context context) {
-        ZipFileIndexCache instance = context.get(ZipFileIndexCache.class);
-        if (instance == null)
-            context.put(ZipFileIndexCache.class, instance = new ZipFileIndexCache());
-        return instance;
-    }
-
-    /**
-     * Returns a list of all ZipFileIndex entries
-     *
-     * @return A list of ZipFileIndex entries, or an empty list
-     */
-    public List<ZipFileIndex> getZipFileIndexes() {
-        return getZipFileIndexes(false);
-    }
-
-    /**
-     * Returns a list of all ZipFileIndex entries
-     *
-     * @param openedOnly If true it returns a list of only opened ZipFileIndex entries, otherwise
-     *                   all ZipFileEntry(s) are included into the list.
-     * @return A list of ZipFileIndex entries, or an empty list
-     */
-    public synchronized List<ZipFileIndex> getZipFileIndexes(boolean openedOnly) {
-        List<ZipFileIndex> zipFileIndexes = new ArrayList<>();
-
-        zipFileIndexes.addAll(map.values());
-
-        if (openedOnly) {
-            for(ZipFileIndex elem : zipFileIndexes) {
-                if (!elem.isOpen()) {
-                    zipFileIndexes.remove(elem);
-                }
-            }
-        }
-
-        return zipFileIndexes;
-    }
-
-    public synchronized ZipFileIndex getZipFileIndex(Path zipFile,
-            RelativeDirectory symbolFilePrefix,
-            boolean useCache, String cacheLocation,
-            boolean writeIndex) throws IOException {
-        ZipFileIndex zi = getExistingZipIndex(zipFile);
-
-        if (zi == null || (zi != null && Files.getLastModifiedTime(zipFile).toMillis() != zi.zipFileLastModified)) {
-            zi = new ZipFileIndex(zipFile, symbolFilePrefix, writeIndex,
-                    useCache, cacheLocation);
-            map.put(zipFile, zi);
-        }
-        return zi;
-    }
-
-    public synchronized ZipFileIndex getExistingZipIndex(Path zipFile) {
-        return map.get(zipFile);
-    }
-
-    public synchronized void clearCache() {
-        map.clear();
-    }
-
-    public synchronized void clearCache(long timeNotUsed) {
-        for (Path cachedFile : map.keySet()) {
-            ZipFileIndex cachedZipIndex = map.get(cachedFile);
-            if (cachedZipIndex != null) {
-                long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed;
-                if (timeToTest < cachedZipIndex.lastReferenceTimeStamp || // Overflow...
-                    System.currentTimeMillis() > timeToTest) {
-                    map.remove(cachedFile);
-                }
-            }
-        }
-    }
-
-    public synchronized void removeFromCache(Path file) {
-        map.remove(file);
-    }
-
-    /** Sets already opened list of ZipFileIndexes from an outside client
-      * of the compiler. This functionality should be used in a non-batch clients of the compiler.
-      */
-    public synchronized void setOpenedIndexes(List<ZipFileIndex>indexes) throws IllegalStateException {
-        if (map.isEmpty()) {
-            String msg =
-                    "Setting opened indexes should be called only when the ZipFileCache is empty. "
-                    + "Call JavacFileManager.flush() before calling this method.";
-            throw new IllegalStateException(msg);
-        }
-
-        for (ZipFileIndex zfi : indexes) {
-            map.put(zfi.zipFile, zfi);
-        }
-    }
-}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Dec 07 14:02:55 2015 -0800
@@ -29,15 +29,18 @@
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.nio.CharBuffer;
-import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
+
 import com.sun.tools.javac.comp.Annotate;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
 import com.sun.tools.javac.code.*;
@@ -47,7 +50,8 @@
 import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
-import com.sun.tools.javac.file.BaseFileObject;
+import com.sun.tools.javac.file.BaseFileManager;
+import com.sun.tools.javac.file.PathFileObject;
 import com.sun.tools.javac.jvm.ClassFile.NameAndType;
 import com.sun.tools.javac.jvm.ClassFile.Version;
 import com.sun.tools.javac.util.*;
@@ -2465,15 +2469,14 @@
      * to be valid as is, so operations other than those to access the name throw
      * UnsupportedOperationException
      */
-    private static class SourceFileObject extends BaseFileObject {
+    private static class SourceFileObject implements JavaFileObject {
 
         /** The file's name.
          */
-        private Name name;
-        private Name flatname;
+        private final Name name;
+        private final Name flatname;
 
         public SourceFileObject(Name name, Name flatname) {
-            super(null); // no file manager; never referenced for this file object
             this.name = name;
             this.flatname = flatname;
         }
@@ -2483,7 +2486,7 @@
             try {
                 return new URI(null, name.toString(), null);
             } catch (URISyntaxException e) {
-                throw new CannotCreateUriError(name.toString(), e);
+                throw new PathFileObject.CannotCreateUriError(name.toString(), e);
             }
         }
 
@@ -2492,14 +2495,9 @@
             return name.toString();
         }
 
-        @Override
-        public String getShortName() {
-            return getName();
-        }
-
         @Override @DefinedBy(Api.COMPILER)
         public JavaFileObject.Kind getKind() {
-            return getKind(getName());
+            return BaseFileManager.getKind(getName());
         }
 
         @Override @DefinedBy(Api.COMPILER)
@@ -2537,14 +2535,19 @@
             throw new UnsupportedOperationException();
         }
 
-        @Override
-        protected String inferBinaryName(Iterable<? extends Path> path) {
-            return flatname.toString();
+        @Override @DefinedBy(Api.COMPILER)
+        public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
+            return true; // fail-safe mode
         }
 
         @Override @DefinedBy(Api.COMPILER)
-        public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
-            return true; // fail-safe mode
+        public NestingKind getNestingKind() {
+            return null;
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public Modifier getAccessLevel() {
+            return null;
         }
 
         /**
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Mon Dec 07 14:02:55 2015 -0800
@@ -40,7 +40,7 @@
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.code.Types.UniqueType;
-import com.sun.tools.javac.file.BaseFileObject;
+import com.sun.tools.javac.file.PathFileObject;
 import com.sun.tools.javac.jvm.Pool.DynamicMethod;
 import com.sun.tools.javac.jvm.Pool.Method;
 import com.sun.tools.javac.jvm.Pool.MethodHandle;
@@ -52,6 +52,7 @@
 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
 import static com.sun.tools.javac.code.TypeTag.*;
 import static com.sun.tools.javac.main.Option.*;
+
 import static javax.tools.StandardLocation.CLASS_OUTPUT;
 
 /** This class provides operations to map an internal symbol table graph
@@ -1699,7 +1700,7 @@
             // the last possible moment because the sourcefile may be used
             // elsewhere in error diagnostics. Fixes 4241573.
             //databuf.appendChar(c.pool.put(c.sourcefile));
-            String simpleName = BaseFileObject.getSimpleName(c.sourcefile);
+            String simpleName = PathFileObject.getSimpleName(c.sourcefile);
             databuf.appendChar(c.pool.put(names.fromString(simpleName)));
             endAttr(alenIdx);
             acount++;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java	Mon Dec 07 14:02:55 2015 -0800
@@ -141,8 +141,11 @@
         JavacFileManager.preRegister(context); // can't create it until Log has been set up
         Result result = compile(args, context);
         if (fileManager instanceof JavacFileManager) {
-            // A fresh context was created above, so jfm must be a JavacFileManager
-            ((JavacFileManager)fileManager).close();
+            try {
+                // A fresh context was created above, so jfm must be a JavacFileManager
+                ((JavacFileManager)fileManager).close();
+            } catch (IOException ignore) {
+            }
         }
         return result;
     }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Mon Dec 07 14:02:55 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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
@@ -45,7 +45,7 @@
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Type;
 import com.sun.tools.javac.code.Type.CapturedType;
-import com.sun.tools.javac.file.BaseFileObject;
+import com.sun.tools.javac.file.PathFileObject;
 import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.tree.Pretty;
@@ -144,10 +144,10 @@
             throw new IllegalArgumentException(); // d should have source set
         if (fullname)
             return fo.getName();
-        else if (fo instanceof BaseFileObject)
-            return ((BaseFileObject) fo).getShortName();
+        else if (fo instanceof PathFileObject)
+            return ((PathFileObject) fo).getShortName();
         else
-            return BaseFileObject.getSimpleName(fo);
+            return PathFileObject.getSimpleName(fo);
     }
 
     /**
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java	Mon Dec 07 14:02:55 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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
@@ -31,7 +31,7 @@
 
 import com.sun.tools.javac.api.DiagnosticFormatter.Configuration.*;
 import com.sun.tools.javac.api.Formattable;
-import com.sun.tools.javac.file.BaseFileObject;
+import com.sun.tools.javac.file.PathFileObject;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration;
 
@@ -123,8 +123,8 @@
         } else if (arg instanceof JCExpression) {
             JCExpression tree = (JCExpression)arg;
             s = "@" + tree.getStartPosition();
-        } else if (arg instanceof BaseFileObject) {
-            s = ((BaseFileObject) arg).getShortName();
+        } else if (arg instanceof PathFileObject) {
+            s = ((PathFileObject) arg).getShortName();
         } else {
             s = super.formatArgument(diag, arg, null);
         }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java	Mon Dec 07 14:02:55 2015 -0800
@@ -115,7 +115,11 @@
             // Clean up
             JavaFileManager fileManager = context.get(JavaFileManager.class);
             if (fileManager instanceof JavacFileManager) {
-                ((JavacFileManager) fileManager).close();
+                try {
+                    ((JavacFileManager) fileManager).close();
+                } catch (IOException e) {
+                    return RC_FATAL;
+                }
             }
             return result.exitCode;
 
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java	Mon Dec 07 14:02:55 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, 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
@@ -103,10 +103,14 @@
         String fn = filename.getName();
         if (fn.endsWith(")")) {
             int paren = fn.lastIndexOf("(");
-            if (paren != -1)
+            if (paren != -1) {
+                int i = paren+1;
+                if (fn.charAt(i) == '/')
+                    i++;
                 fn = fn.substring(0, paren)
                         + File.separatorChar
-                        + fn.substring(paren + 1, fn.length() - 1);
+                        + fn.substring(i, fn.length() - 1);
+            }
         }
 
         if (position == Position.NOPOS)
--- a/langtools/test/tools/javac/6508981/TestInferBinaryName.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/6508981/TestInferBinaryName.java	Mon Dec 07 14:02:55 2015 -0800
@@ -53,9 +53,6 @@
  * the impl of inferBinaryName for that file object.
  */
 public class TestInferBinaryName {
-    static final boolean DONT_USE_ZIP_FILE_INDEX = false;
-    static final boolean USE_ZIP_FILE_INDEX = true;
-
     public static void main(String... args) throws Exception {
         new TestInferBinaryName().run();
     }
@@ -64,10 +61,7 @@
         testDirectory();
 
         File testJar = createJar();
-
         testZipArchive(testJar);
-        testZipFileIndexArchive(testJar);
-        testZipFileIndexArchive2(testJar);
 
         if (errors > 0)
             throw new Exception(errors + " error found");
@@ -87,40 +81,18 @@
     void testDirectory() throws IOException {
         String testClassName = "p.A";
         List<File> testClasses = Arrays.asList(new File(System.getProperty("test.classes")));
-        try (JavaFileManager fm =
-                getFileManager(testClasses, USE_ZIP_FILE_INDEX)) {
+        try (JavaFileManager fm = getFileManager(testClasses)) {
             test("testDirectory",
-                fm, testClassName, "com.sun.tools.javac.file.RegularFileObject");
+                fm, testClassName, "SimpleFileObject");
         }
     }
 
     void testZipArchive(File testJar) throws IOException {
         String testClassName = "java.lang.String";
         List<File> path = Arrays.asList(testJar);
-        try (JavaFileManager fm =
-                getFileManager(path, DONT_USE_ZIP_FILE_INDEX)) {
+        try (JavaFileManager fm = getFileManager(path)) {
             test("testZipArchive",
-                 fm, testClassName, "com.sun.tools.javac.file.ZipArchive$ZipFileObject");
-        }
-    }
-
-    void testZipFileIndexArchive(File testJar) throws IOException {
-        String testClassName = "java.lang.String";
-        List<File> path = Arrays.asList(testJar);
-        try (JavaFileManager fm =
-                getFileManager(path, USE_ZIP_FILE_INDEX)) {
-            test("testZipFileIndexArchive",
-                 fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
-        }
-    }
-
-    void testZipFileIndexArchive2(File testJar) throws IOException {
-        String testClassName = "java.lang.String";
-        List<File> path = Arrays.asList(testJar);
-        try (JavaFileManager fm =
-                getFileManager(path, USE_ZIP_FILE_INDEX)) {
-            test("testZipFileIndexArchive2",
-                 fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
+                 fm, testClassName, "JarFileObject");
         }
     }
 
@@ -141,21 +113,17 @@
             return;
         }
 
-        String cn = fo.getClass().getName();
+        String cn = fo.getClass().getSimpleName();
         String bn = fm.inferBinaryName(CLASS_PATH, fo);
         System.err.println(testName + " " + cn + " " + bn);
-        check(cn, implClassName);
-        check(bn, testClassName);
+        checkEqual(cn, implClassName);
+        checkEqual(bn, testClassName);
         System.err.println("OK");
     }
 
-    JavaFileManager getFileManager(List<File> path,
-                                   boolean zipFileIndexKind)
+    JavaFileManager getFileManager(List<File> path)
             throws IOException {
         Context ctx = new Context();
-        Options options = Options.instance(ctx);
-        options.put("useOptimizedZip",
-                Boolean.toString(zipFileIndexKind == USE_ZIP_FILE_INDEX));
 
         JavacFileManager fm = new JavacFileManager(ctx, false, null);
         fm.setLocation(CLASS_PATH, path);
@@ -163,7 +131,7 @@
     }
 
     List<File> getPath(String s) {
-        List<File> path = new ArrayList<File>();
+        List<File> path = new ArrayList<>();
         for (String f: s.split(File.pathSeparator)) {
             if (f.length() > 0)
                 path.add(new File(f));
@@ -172,7 +140,7 @@
         return path;
     }
 
-    void check(String found, String expect) {
+    void checkEqual(String found, String expect) {
         if (!found.equals(expect)) {
             System.err.println("Expected: " + expect);
             System.err.println("   Found: " + found);
--- a/langtools/test/tools/javac/T6358024.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/T6358024.java	Mon Dec 07 14:02:55 2015 -0800
@@ -53,7 +53,7 @@
         String testSrc = System.getProperty("test.src");
 
         fm = new JavacFileManager(new Context(), false, null);
-        JavaFileObject f = fm.getFileForInput(testSrc + File.separatorChar + self + ".java");
+        JavaFileObject f = fm.getJavaFileObject(testSrc + File.separatorChar + self + ".java");
 
         test(fm, f,
              new Option[] { new Option("-d", ".")},
--- a/langtools/test/tools/javac/T6358166.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/T6358166.java	Mon Dec 07 14:02:55 2015 -0800
@@ -54,7 +54,7 @@
         String testSrc = System.getProperty("test.src");
 
         JavacFileManager fm = new JavacFileManager(new Context(), false, null);
-        JavaFileObject f = fm.getFileForInput(testSrc + File.separatorChar + self + ".java");
+        JavaFileObject f = fm.getJavaFileObject(testSrc + File.separatorChar + self + ".java");
 
         test(fm, f, "-verbose", "-d", ".");
 
--- a/langtools/test/tools/javac/T6705935.java	Mon Dec 07 09:18:07 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2008, 2015, 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.
- *
- * 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.
- */
-
-/*
- * @test
- * @bug 6705935
- * @summary javac reports path name of entry in ZipFileIndex incorectly
- * @modules jdk.compiler/com.sun.tools.javac.file
- */
-
-import java.io.*;
-import java.util.*;
-import javax.tools.*;
-import com.sun.tools.javac.file.*;
-import com.sun.tools.javac.file.ZipArchive.ZipFileObject;
-import com.sun.tools.javac.file.ZipFileIndexArchive.ZipFileIndexFileObject;
-
-public class T6705935 {
-    public static void main(String... args) throws Exception {
-        new T6705935().run();
-    }
-
-    public void run() throws Exception {
-        File java_home = new File(System.getProperty("java.home"));
-
-        JavaCompiler c = ToolProvider.getSystemJavaCompiler();
-        try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) {
-            //System.err.println("platform class path: " + asList(fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH)));
-
-            for (JavaFileObject fo: fm.list(StandardLocation.PLATFORM_CLASS_PATH,
-                                            "java.lang",
-                                            Collections.singleton(JavaFileObject.Kind.CLASS),
-                                            false)) {
-                test++;
-
-                if (!(fo instanceof ZipFileObject || fo instanceof ZipFileIndexFileObject)) {
-                    System.out.println("Skip " + fo.getClass().getSimpleName() + " " + fo.getName());
-                    skip++;
-                    continue;
-                }
-
-                //System.err.println(fo.getName());
-                String p = fo.getName();
-                int bra = p.indexOf("(");
-                int ket = p.indexOf(")");
-                //System.err.println(bra + "," + ket + "," + p.length());
-                if (bra == -1 || ket != p.length() -1)
-                    throw new Exception("unexpected path: " + p + "[" + bra + "," + ket + "," + p.length());
-                String part1 = p.substring(0, bra);
-                String part2 = p.substring(bra + 1, ket);
-                //System.err.println("[" + part1 + "|" + part2 + "]" + " " + java_home);
-                if (part1.equals(part2) || !part1.startsWith(java_home.getPath()))
-                    throw new Exception("bad path: " + p);
-
-            }
-
-            if (test == 0)
-                throw new Exception("no files found");
-
-            if (skip == 0)
-                System.out.println(test + " files found");
-            else
-                System.out.println(test + " files found, " + skip + " files skipped");
-
-            if (test == skip)
-                System.out.println("Warning: all files skipped; no platform classes found in zip files.");
-        }
-    }
-
-    private <T> List<T> asList(Iterable<? extends T> items) {
-        List<T> list = new ArrayList<T>();
-        for (T item: items)
-            list.add(item);
-        return list;
-     }
-
-    private int skip;
-    private int test;
-}
--- a/langtools/test/tools/javac/T6725036.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/T6725036.java	Mon Dec 07 14:02:55 2015 -0800
@@ -37,16 +37,15 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Collections;
 import java.util.Date;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
+
 import javax.tools.*;
 
 import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.file.RelativePath.RelativeFile;
-import com.sun.tools.javac.file.ZipFileIndex;
-import com.sun.tools.javac.file.ZipFileIndexArchive;
-import com.sun.tools.javac.file.ZipFileIndexCache;
 import com.sun.tools.javac.util.Context;
 
 public class T6725036 {
@@ -63,21 +62,14 @@
             JarEntry je = j.getJarEntry(TEST_ENTRY_NAME.getPath());
             long jarEntryTime = je.getTime();
 
-            ZipFileIndexCache zfic = ZipFileIndexCache.getSharedInstance();
-            ZipFileIndex zfi = zfic.getZipFileIndex(testJar.toPath(), null, false, null, false);
-            long zfiTime = zfi.getLastModified(TEST_ENTRY_NAME);
-
-            check(je, jarEntryTime, zfi + ":" + TEST_ENTRY_NAME.getPath(), zfiTime);
-
             Context context = new Context();
             JavacFileManager fm = new JavacFileManager(context, false, null);
-            ZipFileIndexArchive zfia = new ZipFileIndexArchive(fm, zfi);
-            JavaFileObject jfo =
-                zfia.getFileObject(TEST_ENTRY_NAME.dirname(),
-                                       TEST_ENTRY_NAME.basename());
-            long jfoTime = jfo.getLastModified();
+            fm.setLocation(StandardLocation.CLASS_PATH, Collections.singletonList(testJar));
+            FileObject fo =
+                fm.getFileForInput(StandardLocation.CLASS_PATH, "", TEST_ENTRY_NAME.getPath());
+            long jfoTime = fo.getLastModified();
 
-            check(je, jarEntryTime, jfo, jfoTime);
+            check(je, jarEntryTime, fo, jfoTime);
 
             if (errors > 0)
                 throw new Exception(errors + " occurred");
--- a/langtools/test/tools/javac/api/6440528/T6440528.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/api/6440528/T6440528.java	Mon Dec 07 14:02:55 2015 -0800
@@ -55,19 +55,13 @@
                                              "package-info.class",
                                              src);
         File expect = new File(test_src, "package-info.class");
-        File got = getUnderlyingFile(cls);
+        File got = fm.asPath(cls).toFile();
         if (!got.equals(expect))
             throw new AssertionError(String.format("Expected: %s; got: %s", expect, got));
         System.err.println("Expected: " + expect);
         System.err.println("Got:      " + got);
     }
 
-    private File getUnderlyingFile(FileObject o) throws Exception {
-        Field file = o.getClass().getDeclaredField("file"); // assumes RegularFileObject
-        file.setAccessible(true);
-        return ((Path)file.get(o)).toFile();
-    }
-
     public static void main(String... args) throws Exception {
         try (T6440528 t = new T6440528()) {
             t.test(args);
--- a/langtools/test/tools/javac/api/T6358955.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/api/T6358955.java	Mon Dec 07 14:02:55 2015 -0800
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6358955
- * @summary JavacFileManager.getFileForInput(dir) shuld throw IAE
+ * @summary JavacFileManager.getFileForInput(dir) should throw IAE
  * @modules java.compiler
  *          jdk.compiler
  */
--- a/langtools/test/tools/javac/api/T6838467.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/api/T6838467.java	Mon Dec 07 14:02:55 2015 -0800
@@ -32,18 +32,18 @@
 import java.io.*;
 import java.util.*;
 import java.util.zip.*;
+
 import javax.tools.*;
+import javax.tools.JavaFileManager.Location;
+
 import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.Options;
 
 public class T6838467 {
-    boolean fileSystemIsCaseSignificant = !new File("a").equals(new File("A"));
 
     enum FileKind {
         DIR("dir"),
-        ZIP("zip"),
-        ZIPFILEINDEX("zip");
+        ZIP("zip");
         FileKind(String path) {
             file = new File(path);
         }
@@ -52,15 +52,19 @@
 
     enum CompareKind {
         SAME {
+            @Override
             File other(File f) { return f; }
         },
         ABSOLUTE {
+            @Override
             File other(File f) { return f.getAbsoluteFile(); }
         },
         DIFFERENT {
+            @Override
             File other(File f) { return new File("not_" + f.getPath()); }
         },
         CASEEQUIV {
+            @Override
             File other(File f) { return new File(f.getPath().toUpperCase()); }
         };
         abstract File other(File f);
@@ -73,10 +77,17 @@
     }
 
     void run() throws Exception {
+        boolean fileNameIsCaseSignificant = isFileNameCaseSignificant();
+        boolean fileLookupIsCaseSignificant = isFileLookupCaseSignificant();
+
+        String osName = System.getProperty("os.name");
+        System.err.println("OS: " + osName);
+        System.err.println("fileNameIsCaseSignificant:" + fileNameIsCaseSignificant);
+        System.err.println("fileLookupIsCaseSignificant:" + fileLookupIsCaseSignificant);
+
         // on Windows, verify file system is not case significant
-        if (System.getProperty("os.name").toLowerCase().startsWith("windows")
-                && fileSystemIsCaseSignificant) {
-            error("fileSystemIsCaseSignificant is set on Windows.");
+        if ((osName.startsWith("windows")) && fileNameIsCaseSignificant) {
+            error("fileNameIsCaseSignificant is set on " + osName + ".");
         }
 
         // create a set of directories and zip files to compare
@@ -84,7 +95,7 @@
         createTestDir(new File("not_dir"), paths);
         createTestZip(new File("zip"), paths);
         createTestZip(new File("not_zip"), paths);
-        if (fileSystemIsCaseSignificant) {
+        if (fileNameIsCaseSignificant || fileLookupIsCaseSignificant) {
             createTestDir(new File("DIR"), paths);
             createTestZip(new File("ZIP"), paths);
         }
@@ -99,8 +110,9 @@
 
         // verify that the various different types of file object were all
         // tested
-        Set<String> expectClasses = new HashSet<String>(Arrays.asList(
-                "RegularFileObject", "ZipFileObject", "ZipFileIndexFileObject" ));
+        Set<String> expectClasses = new HashSet<>(Arrays.asList(
+                "DirectoryFileObject",
+                "JarFileObject" ));
         if (!foundClasses.equals(expectClasses)) {
             error("expected fileobject classes not found\n"
                     + "expected: " + expectClasses + "\n"
@@ -112,26 +124,22 @@
     }
 
     void test(FileKind fk, CompareKind ck) throws IOException {
-        File f1 = fk.file;
-        JavaFileManager fm1 = createFileManager(fk, f1);
+        try (StandardJavaFileManager fm = createFileManager()) {
+            File f1 = fk.file;
+            Location l1 = createLocation(fm, "l1", f1);
 
-        File f2 = ck.other(fk.file);
-        JavaFileManager fm2 = createFileManager(fk, f2);
+            File f2 = ck.other(fk.file);
+            Location l2 = createLocation(fm, "l2", f2);
 
-        try {
             // If the directories or zip files match, we expect "n" matches in
             // the "n-squared" comparisons to come, where "n" is the number of
             // entries in the the directories or zip files.
             // If the directories or zip files don't themselves match,
             // we obviously don't expect any of their contents to match either.
-            int expect = (f1.getAbsoluteFile().equals(f2.getAbsoluteFile()) ? paths.length : 0);
+            int expectEqualCount = (f1.getCanonicalFile().equals(f2.getCanonicalFile()) ? paths.length : 0);
 
             System.err.println("test " + (++count) + " " + fk + " " + ck + " " + f1 + " " + f2);
-            test(fm1, fm2, expect);
-
-        } finally {
-            fm1.close();
-            fm2.close();
+            test(fm, l1, l2, expectEqualCount);
         }
     }
 
@@ -140,17 +148,17 @@
     // returned from the other.  For each pair of files, verify that if they
     // are equal, the hashcode is equal as well, and finally verify that the
     // expected number of matches was found.
-    void test(JavaFileManager fm1, JavaFileManager fm2, int expectEqualCount) throws IOException {
+    void test(JavaFileManager fm, Location l1, Location l2, int expectEqualCount) throws IOException {
         boolean foundFiles1 = false;
         boolean foundFiles2 = false;
         int foundEqualCount = 0;
         Set<JavaFileObject.Kind> kinds =  EnumSet.allOf(JavaFileObject.Kind.class);
-        for (FileObject fo1: fm1.list(StandardLocation.CLASS_PATH, "p", kinds, false)) {
+        for (FileObject fo1: fm.list(l1, "p", kinds, false)) {
             foundFiles1 = true;
             foundClasses.add(fo1.getClass().getSimpleName());
-            for (FileObject fo2: fm2.list(StandardLocation.CLASS_PATH, "p", kinds, false)) {
+            for (FileObject fo2: fm.list(l2, "p", kinds, false)) {
                 foundFiles2 = true;
-                foundClasses.add(fo1.getClass().getSimpleName());
+                foundClasses.add(fo2.getClass().getSimpleName());
                 System.err.println("compare " + fo1 + " " + fo2);
                 if (fo1.equals(fo2)) {
                     foundEqualCount++;
@@ -163,26 +171,35 @@
             }
         }
         if (!foundFiles1)
-            error("no files found for file manager 1");
+            error("no files found for location " + l1);
         if (!foundFiles2)
-            error("no files found for file manager 2");
+            error("no files found for location " + l2);
         // verify the expected number of matches were found
         if (foundEqualCount != expectEqualCount)
             error("expected matches not found: expected " + expectEqualCount + ", found " + foundEqualCount);
     }
 
-    // create a file manager to test a FileKind, with a given directory
-    // or zip file placed on the classpath
-    JavaFileManager createFileManager(FileKind fk, File classpath) throws IOException {
-        StandardJavaFileManager fm = createFileManager(fk == FileKind.ZIP);
-        fm.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(classpath));
-        return fm;
+    // create and initialize a location to test a FileKind, with a given directory
+    // or zip file placed on the path
+    Location createLocation(StandardJavaFileManager fm, String name, File classpath) throws IOException {
+        Location l = new Location() {
+            @Override
+            public String getName() {
+                return name;
+            }
+
+            @Override
+            public boolean isOutputLocation() {
+                return false;
+            }
+
+        };
+        fm.setLocation(l, Arrays.asList(classpath));
+        return l;
     }
 
-    JavacFileManager createFileManager(boolean useOptimizedZip) {
+    JavacFileManager createFileManager() {
         Context ctx = new Context();
-        Options options = Options.instance(ctx);
-        options.put("useOptimizedZip", Boolean.toString(useOptimizedZip));
         return new JavacFileManager(ctx, false, null);
     }
 
@@ -191,21 +208,17 @@
         for (String p: paths) {
             File file = new File(dir, p);
             file.getParentFile().mkdirs();
-            FileWriter out = new FileWriter(file);
-            try {
+            try (FileWriter out = new FileWriter(file)) {
                 out.write(p);
-            } finally {
-                out.close();
             }
         }
     }
 
-    // create a sip file containing a given set of entries
+    // create a zip file containing a given set of entries
     void createTestZip(File zip, String[] paths) throws IOException {
         if (zip.getParentFile() != null)
             zip.getParentFile().mkdirs();
-        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
-        try {
+        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip))) {
             for (String p: paths) {
                 ZipEntry ze = new ZipEntry(p);
                 zos.putNextEntry(ze);
@@ -213,8 +226,6 @@
                 zos.write(bytes, 0, bytes.length);
                 zos.closeEntry();
             }
-        } finally {
-            zos.close();
         }
     }
 
@@ -223,8 +234,24 @@
         errors++;
     }
 
+    boolean isFileNameCaseSignificant() {
+        File lower = new File("test.txt");
+        File upper = new File(lower.getPath().toUpperCase());
+        return !lower.equals(upper);
+    }
+
+    boolean isFileLookupCaseSignificant() throws IOException {
+        File lower = new File("test.txt");
+        File upper = new File(lower.getPath().toUpperCase());
+        if (upper.exists()) {
+            upper.delete();
+        }
+        try (FileWriter out = new FileWriter(lower)) { }
+        return !upper.exists();
+    }
+
     int count;
     int errors;
-    Set<String> foundClasses = new HashSet<String>();
+    Set<String> foundClasses = new HashSet<>();
 }
 
--- a/langtools/test/tools/javac/api/T6877206.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/api/T6877206.java	Mon Dec 07 14:02:55 2015 -0800
@@ -62,15 +62,12 @@
 
         test(createFileManager(), createDir("dir", entries), "p", entries.length);
         test(createFileManager(), createDir("a b/dir", entries), "p", entries.length);
-
-        for (boolean useOptimizedZip: new boolean[] { false, true }) {
-            test(createFileManager(useOptimizedZip), createJar("jar", entries), "p", entries.length);
-            test(createFileManager(useOptimizedZip), createJar("jar jar", entries), "p", entries.length);
-        }
+        test(createFileManager(), createJar("jar", entries), "p", entries.length);
+        test(createFileManager(), createJar("jar jar", entries), "p", entries.length);
 
         // Verify that we hit the files we intended
         checkCoverage("classes", foundClasses,
-                "RegularFileObject", "ZipFileIndexFileObject", "ZipFileObject");
+                "DirectoryFileObject", "JarFileObject");
 
         // Verify that we hit the jar files we intended
         checkCoverage("jar files", foundJars, "jar", "jar jar");
@@ -153,17 +150,12 @@
     }
 
     JavacFileManager createFileManager() {
-        return createFileManager(false, false);
+        return createFileManager(false);
     }
 
-    JavacFileManager createFileManager(boolean useOptimizedZip) {
-        return createFileManager(useOptimizedZip, false);
-    }
-
-    JavacFileManager createFileManager(boolean useOptimizedZip, boolean useSymbolFile) {
+    JavacFileManager createFileManager(boolean useSymbolFile) {
         Context ctx = new Context();
         Options options = Options.instance(ctx);
-        options.put("useOptimizedZip", Boolean.toString(useOptimizedZip));
         if (!useSymbolFile) {
             options.put("ignore.symbol.file", "true");
         }
--- a/langtools/test/tools/javac/file/zip/T8076104.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/file/zip/T8076104.java	Mon Dec 07 14:02:55 2015 -0800
@@ -60,7 +60,6 @@
     void run() throws Exception {
         File testJar = createJar();
         doTest(testJar);
-        doTest(testJar, "-XDuseOptimizedZip=false");
     }
 
     File createJar() throws Exception {
--- a/langtools/test/tools/javac/options/modes/Tester.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/options/modes/Tester.java	Mon Dec 07 14:02:55 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, 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
@@ -136,8 +136,11 @@
         } catch (IllegalArgumentException | IllegalStateException | IOException e) {
             tr.setThrown(e);
         } finally {
-            ((JavacFileManager) context.get(JavaFileManager.class)).close();
-            tr.setLogs(sw.toString(), sysOut.close(), sysErr.close());
+            try {
+                ((JavacFileManager) context.get(JavaFileManager.class)).close();
+                tr.setLogs(sw.toString(), sysOut.close(), sysErr.close());
+            } catch (IOException e) {
+            }
         }
         tr.setContext(context);
         tr.show();
@@ -149,6 +152,7 @@
     class TestResult {
         final List<String> args;
         Throwable thrown;
+        List<Throwable> suppressed = new ArrayList<>();
         Object rc; // Number or Boolean
         Map<Log, String> logs;
         Context context;
@@ -172,6 +176,10 @@
             this.rc = ok ? 0 : 1;
         }
 
+        void setSuppressed(Throwable thrown) {
+            this.suppressed.add(thrown);
+        }
+
         void setThrown(Throwable thrown) {
             this.thrown = thrown;
         }
@@ -199,6 +207,11 @@
                 out.print("thrown:" + thrown);
                 needSep = true;
             }
+            if (!suppressed.isEmpty()) {
+                if (needSep) out.print("; ");
+                out.print("suppressed:" + suppressed);
+                needSep = true;
+            }
             if (needSep)
                 out.println();
             logs.forEach((k, v) -> {
--- a/langtools/test/tools/javac/parser/T4910483.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/parser/T4910483.java	Mon Dec 07 14:02:55 2015 -0800
@@ -49,7 +49,7 @@
 
         String testSrc = System.getProperty("test.src");
         JavacFileManager fm = new JavacFileManager(new Context(), false, null);
-        JavaFileObject f = fm.getFileForInput(testSrc + File.separatorChar + "T4910483.java");
+        JavaFileObject f = fm.getJavaFileObject(testSrc + File.separatorChar + "T4910483.java");
 
         JCTree.JCCompilationUnit cu = compiler.parse(f);
         JCTree classDef = cu.getTypeDecls().head;
--- a/langtools/test/tools/javac/processing/errors/CrashOnNonExistingAnnotation/Processor.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/processing/errors/CrashOnNonExistingAnnotation/Processor.java	Mon Dec 07 14:02:55 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, 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
@@ -88,7 +88,7 @@
         if (!testFile.canRead()) throw new IllegalStateException("Cannot read the test source");
         JavacTool compiler = JavacTool.create();
         JavacFileManager fm = compiler.getStandardFileManager(null, null, null);
-        testContent = fm.getRegularFile(testFile.toPath()).getCharContent(true).toString();
+        testContent = fm.getJavaFileObject(testFile.toPath()).getCharContent(true).toString();
         JavaFileObject testFileObject = new TestFO(new URI("mem://" + args[0]), testContent);
         TestFM testFileManager = new TestFM(fm);
         JavacTask task = compiler.getTask(null,
--- a/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/Processor.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/Processor.java	Mon Dec 07 14:02:55 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, 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
@@ -71,7 +71,7 @@
             File inp = new File(sp, args[0]);
 
             if (inp.canRead()) {
-                testContent = fm.getRegularFile(inp.toPath()).getCharContent(true).toString();
+                testContent = fm.getJavaFileObject(inp.toPath()).getCharContent(true).toString();
             }
         }
         if (testContent == null) throw new IllegalStateException();
--- a/langtools/test/tools/javac/warnings/suppress/VerifySuppressWarnings.java	Mon Dec 07 09:18:07 2015 -0800
+++ b/langtools/test/tools/javac/warnings/suppress/VerifySuppressWarnings.java	Mon Dec 07 14:02:55 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, 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
@@ -74,7 +74,7 @@
             File inp = new File(sp, args[0]);
 
             if (inp.canRead()) {
-                testContent = fm.getRegularFile(inp.toPath()).getCharContent(true).toString();
+                testContent = fm.getJavaFileObject(inp.toPath()).getCharContent(true).toString();
             }
         }
         if (testContent == null) throw new IllegalStateException();