changeset 50:700b17652ef6

Merge
author tbell
date Mon, 16 Jun 2008 22:23:33 -0700
parents 5ee49b24d378 (current diff) b9bcea8bbe24 (diff)
children 3cb4fb6e0720
files src/share/classes/com/sun/tools/javac/util/BaseFileObject.java src/share/classes/com/sun/tools/javac/util/JavacFileManager.java src/share/classes/com/sun/tools/javac/util/Old199.java src/share/classes/com/sun/tools/javac/util/Paths.java src/share/classes/com/sun/tools/javac/zip/ZipFileIndex.java src/share/classes/com/sun/tools/javac/zip/ZipFileIndexEntry.java
diffstat 36 files changed, 3854 insertions(+), 3846 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java	Mon Jun 16 22:23:33 2008 -0700
@@ -26,20 +26,14 @@
 package com.sun.tools.apt.main;
 
 import java.io.*;
-import java.nio.CharBuffer;
-import java.util.Set;
-import java.util.HashSet;
 import java.util.Map;
-import java.util.HashMap;
 
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.code.*;
-import com.sun.tools.javac.tree.*;
-import com.sun.tools.javac.parser.*;
-import com.sun.tools.javac.comp.*;
 import com.sun.tools.javac.jvm.*;
 
 import com.sun.tools.javac.code.Symbol.*;
--- a/src/share/classes/com/sun/tools/apt/main/Main.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/apt/main/Main.java	Mon Jun 16 22:23:33 2008 -0700
@@ -44,7 +44,7 @@
 import java.io.File;
 import java.net.MalformedURLException;
 
-import com.sun.tools.javac.util.Paths;
+import com.sun.tools.javac.file.Paths;
 import com.sun.tools.javac.code.Source;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Type;
--- a/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Mon Jun 16 22:23:33 2008 -0700
@@ -36,12 +36,12 @@
 import javax.lang.model.type.TypeMirror;
 import javax.tools.*;
 
-import com.sun.source.tree.Tree;
 import com.sun.source.tree.*;
 import com.sun.source.util.*;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.comp.*;
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.main.*;
 import com.sun.tools.javac.model.*;
 import com.sun.tools.javac.parser.Parser;
--- a/src/share/classes/com/sun/tools/javac/api/JavacTool.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/api/JavacTool.java	Mon Jun 16 22:23:33 2008 -0700
@@ -31,7 +31,6 @@
 import java.io.PrintWriter;
 import java.io.Writer;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.Iterator;
@@ -42,13 +41,13 @@
 import javax.tools.*;
 
 import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.main.JavacOption.OptionKind;
 import com.sun.tools.javac.main.JavacOption;
 import com.sun.tools.javac.main.Main;
 import com.sun.tools.javac.main.RecognizedOptions.GrumpyHelper;
 import com.sun.tools.javac.main.RecognizedOptions;
 import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.JavacFileManager;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.Options;
 import com.sun.tools.javac.util.Pair;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java	Mon Jun 16 22:23:33 2008 -0700
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.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.nio.charset.CharsetDecoder;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.tools.JavaFileObject;
+
+import static javax.tools.JavaFileObject.Kind.*;
+
+public abstract class BaseFileObject implements JavaFileObject {
+
+    public JavaFileObject.Kind getKind() {
+        String n = getName();
+        if (n.endsWith(CLASS.extension))
+            return CLASS;
+        else if (n.endsWith(SOURCE.extension))
+            return SOURCE;
+        else if (n.endsWith(HTML.extension))
+            return HTML;
+        else
+            return OTHER;
+    }
+
+    @Override
+    public String toString() {
+        return getPath();
+    }
+
+    /** @deprecated see bug 6410637 */
+    @Deprecated
+    public String getPath() {
+        return getName();
+    }
+
+    /** @deprecated see bug 6410637 */
+    @Deprecated
+    abstract public String getName();
+
+    public NestingKind getNestingKind() { return null; }
+
+    public Modifier getAccessLevel()  { return null; }
+
+    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
+        return new InputStreamReader(openInputStream(), getDecoder(ignoreEncodingErrors));
+    }
+
+    protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+        throw new UnsupportedOperationException();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Mon Jun 16 22:23:33 2008 -0700
@@ -0,0 +1,1718 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.lang.ref.SoftReference;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import javax.lang.model.SourceVersion;
+import javax.tools.FileObject;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.main.JavacOption;
+import com.sun.tools.javac.main.OptionName;
+import com.sun.tools.javac.main.RecognizedOptions;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Options;
+
+import static com.sun.tools.javac.main.OptionName.*;
+import static javax.tools.StandardLocation.*;
+
+/**
+ * This class provides access to the source, class and other files
+ * used by the compiler and related tools.
+ */
+public class JavacFileManager implements StandardJavaFileManager {
+
+    private static final String[] symbolFileLocation = { "lib", "ct.sym" };
+    private static final String symbolFilePrefix = "META-INF/sym/rt.jar/";
+
+    boolean useZipFileIndex;
+
+    private static int symbolFilePrefixLength = 0;
+    static {
+        try {
+            symbolFilePrefixLength = symbolFilePrefix.getBytes("UTF-8").length;
+        } catch (java.io.UnsupportedEncodingException uee) {
+            // Can't happen...UTF-8 is always supported.
+        }
+    }
+
+    private static boolean CHECK_ZIP_TIMESTAMP = false;
+    private static Map<File, Boolean> isDirectory = new ConcurrentHashMap<File, Boolean>();
+
+
+    public static char[] toArray(CharBuffer buffer) {
+        if (buffer.hasArray())
+            return ((CharBuffer)buffer.compact().flip()).array();
+        else
+            return buffer.toString().toCharArray();
+    }
+
+    /**
+     * The log to be used for error reporting.
+     */
+    protected Log log;
+
+    /** Encapsulates knowledge of paths
+     */
+    private Paths paths;
+
+    private Options options;
+
+    private final File uninited = new File("U N I N I T E D");
+
+    private final Set<JavaFileObject.Kind> sourceOrClass =
+        EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS);
+
+    /** The standard output directory, primarily used for classes.
+     *  Initialized by the "-d" option.
+     *  If classOutDir = null, files are written into same directory as the sources
+     *  they were generated from.
+     */
+    private File classOutDir = uninited;
+
+    /** The output directory, used when generating sources while processing annotations.
+     *  Initialized by the "-s" option.
+     */
+    private File sourceOutDir = uninited;
+
+    protected boolean mmappedIO;
+    protected boolean ignoreSymbolFile;
+
+    /**
+     * User provided charset (through javax.tools).
+     */
+    protected Charset charset;
+
+    /**
+     * Register a Context.Factory to create a JavacFileManager.
+     */
+    public static void preRegister(final Context context) {
+        context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() {
+            public JavaFileManager make() {
+                return new JavacFileManager(context, true, null);
+            }
+        });
+    }
+
+    /**
+     * Create a JavacFileManager using a given context, optionally registering
+     * it as the JavaFileManager for that context.
+     */
+    public JavacFileManager(Context context, boolean register, Charset charset) {
+        if (register)
+            context.put(JavaFileManager.class, this);
+        byteBufferCache = new ByteBufferCache();
+        this.charset = charset;
+        setContext(context);
+    }
+
+    /**
+     * Set the context for JavacFileManager.
+     */
+    public void setContext(Context context) {
+        log = Log.instance(context);
+        if (paths == null) {
+            paths = Paths.instance(context);
+        } else {
+            // Reuse the Paths object as it stores the locations that
+            // have been set with setLocation, etc.
+            paths.setContext(context);
+        }
+
+        options = Options.instance(context);
+
+        useZipFileIndex = System.getProperty("useJavaUtilZip") == null;// TODO: options.get("useJavaUtilZip") == null;
+        CHECK_ZIP_TIMESTAMP = System.getProperty("checkZipIndexTimestamp") != null;// TODO: options.get("checkZipIndexTimestamp") != null;
+
+        mmappedIO = options.get("mmappedIO") != null;
+        ignoreSymbolFile = options.get("ignore.symbol.file") != null;
+    }
+
+    public JavaFileObject getFileForInput(String name) {
+        return getRegularFile(new File(name));
+    }
+
+    public JavaFileObject getRegularFile(File file) {
+        return new RegularFileObject(file);
+    }
+
+    public JavaFileObject getFileForOutput(String classname,
+                                           JavaFileObject.Kind kind,
+                                           JavaFileObject sibling)
+        throws IOException
+    {
+        return getJavaFileForOutput(CLASS_OUTPUT, classname, kind, sibling);
+    }
+
+    public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
+        ListBuffer<File> files = new ListBuffer<File>();
+        for (String name : names)
+            files.append(new File(nullCheck(name)));
+        return getJavaFileObjectsFromFiles(files.toList());
+    }
+
+    public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) {
+        return getJavaFileObjectsFromStrings(Arrays.asList(nullCheck(names)));
+    }
+
+    protected JavaFileObject.Kind getKind(String extension) {
+        if (extension.equals(JavaFileObject.Kind.CLASS.extension))
+            return JavaFileObject.Kind.CLASS;
+        else if (extension.equals(JavaFileObject.Kind.SOURCE.extension))
+            return JavaFileObject.Kind.SOURCE;
+        else if (extension.equals(JavaFileObject.Kind.HTML.extension))
+            return JavaFileObject.Kind.HTML;
+        else
+            return JavaFileObject.Kind.OTHER;
+    }
+
+    private static boolean isValidName(String name) {
+        // Arguably, isValidName should reject keywords (such as in SourceVersion.isName() ),
+        // but the set of keywords depends on the source level, and we don't want
+        // impls of JavaFileManager to have to be dependent on the source level.
+        // Therefore we simply check that the argument is a sequence of identifiers
+        // separated by ".".
+        for (String s : name.split("\\.", -1)) {
+            if (!SourceVersion.isIdentifier(s))
+                return false;
+        }
+        return true;
+    }
+
+    private static void validateClassName(String className) {
+        if (!isValidName(className))
+            throw new IllegalArgumentException("Invalid class name: " + className);
+    }
+
+    private static void validatePackageName(String packageName) {
+        if (packageName.length() > 0 && !isValidName(packageName))
+            throw new IllegalArgumentException("Invalid packageName name: " + packageName);
+    }
+
+    public static void testName(String name,
+                                boolean isValidPackageName,
+                                boolean isValidClassName)
+    {
+        try {
+            validatePackageName(name);
+            if (!isValidPackageName)
+                throw new AssertionError("Invalid package name accepted: " + name);
+            printAscii("Valid package name: \"%s\"", name);
+        } catch (IllegalArgumentException e) {
+            if (isValidPackageName)
+                throw new AssertionError("Valid package name rejected: " + name);
+            printAscii("Invalid package name: \"%s\"", name);
+        }
+        try {
+            validateClassName(name);
+            if (!isValidClassName)
+                throw new AssertionError("Invalid class name accepted: " + name);
+            printAscii("Valid class name: \"%s\"", name);
+        } catch (IllegalArgumentException e) {
+            if (isValidClassName)
+                throw new AssertionError("Valid class name rejected: " + name);
+            printAscii("Invalid class name: \"%s\"", name);
+        }
+    }
+    private static void printAscii(String format, Object... args) {
+        String message;
+        try {
+            final String ascii = "US-ASCII";
+            message = new String(String.format(null, format, args).getBytes(ascii), ascii);
+        } catch (java.io.UnsupportedEncodingException ex) {
+            throw new AssertionError(ex);
+        }
+        System.out.println(message);
+    }
+
+    /** Return external representation of name,
+     *  converting '.' to File.separatorChar.
+     */
+    private static String externalizeFileName(CharSequence name) {
+        return name.toString().replace('.', File.separatorChar);
+    }
+
+    private static String externalizeFileName(CharSequence n, JavaFileObject.Kind kind) {
+        return externalizeFileName(n) + kind.extension;
+    }
+
+    private static String baseName(String fileName) {
+        return fileName.substring(fileName.lastIndexOf(File.separatorChar) + 1);
+    }
+
+    /**
+     * Insert all files in subdirectory `subdirectory' of `directory' which end
+     * in one of the extensions in `extensions' into packageSym.
+     */
+    private void listDirectory(File directory,
+                               String subdirectory,
+                               Set<JavaFileObject.Kind> fileKinds,
+                               boolean recurse,
+                               ListBuffer<JavaFileObject> l) {
+        Archive archive = archives.get(directory);
+
+        boolean isFile = false;
+        if (CHECK_ZIP_TIMESTAMP) {
+            Boolean isf = isDirectory.get(directory);
+            if (isf == null) {
+                isFile = directory.isFile();
+                isDirectory.put(directory, isFile);
+            }
+            else {
+                isFile = directory.isFile();
+            }
+        }
+        else {
+            isFile = directory.isFile();
+        }
+
+        if (archive != null || isFile) {
+            if (archive == null) {
+                try {
+                    archive = openArchive(directory);
+                } catch (IOException ex) {
+                    log.error("error.reading.file",
+                       directory, ex.getLocalizedMessage());
+                    return;
+                }
+            }
+            if (subdirectory.length() != 0) {
+                if (!useZipFileIndex) {
+                    subdirectory = subdirectory.replace('\\', '/');
+                    if (!subdirectory.endsWith("/")) subdirectory = subdirectory + "/";
+                }
+                else {
+                    if (File.separatorChar == '/') {
+                        subdirectory = subdirectory.replace('\\', '/');
+                    }
+                    else {
+                        subdirectory = subdirectory.replace('/', '\\');
+                    }
+
+                    if (!subdirectory.endsWith(File.separator)) subdirectory = subdirectory + File.separator;
+                }
+            }
+
+            List<String> files = archive.getFiles(subdirectory);
+            if (files != null) {
+                for (String file; !files.isEmpty(); files = files.tail) {
+                    file = files.head;
+                    if (isValidFile(file, fileKinds)) {
+                        l.append(archive.getFileObject(subdirectory, file));
+                    }
+                }
+            }
+            if (recurse) {
+                for (String s: archive.getSubdirectories()) {
+                    if (s.startsWith(subdirectory) && !s.equals(subdirectory)) {
+                        // 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.
+                        listDirectory(directory, s, fileKinds, false, l);
+                    }
+                }
+            }
+        } else {
+            File d = subdirectory.length() != 0
+                ? new File(directory, subdirectory)
+                : directory;
+            if (!caseMapCheck(d, subdirectory))
+                return;
+
+            File[] files = d.listFiles();
+            if (files == null)
+                return;
+
+            for (File f: files) {
+                String fname = f.getName();
+                if (f.isDirectory()) {
+                    if (recurse && SourceVersion.isIdentifier(fname)) {
+                        listDirectory(directory,
+                                      subdirectory + File.separator + fname,
+                                      fileKinds,
+                                      recurse,
+                                      l);
+                    }
+                } else {
+                    if (isValidFile(fname, fileKinds)) {
+                        JavaFileObject fe =
+                        new RegularFileObject(fname, new File(d, fname));
+                        l.append(fe);
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
+        int lastDot = s.lastIndexOf(".");
+        String extn = (lastDot == -1 ? s : s.substring(lastDot));
+        JavaFileObject.Kind kind = getKind(extn);
+        return fileKinds.contains(kind);
+    }
+
+    private static final boolean fileSystemIsCaseSensitive =
+        File.separatorChar == '/';
+
+    /** Hack to make Windows case sensitive. Test whether given path
+     *  ends in a string of characters with the same case as given name.
+     *  Ignore file separators in both path and name.
+     */
+    private boolean caseMapCheck(File f, String name) {
+        if (fileSystemIsCaseSensitive) return true;
+        // Note that getCanonicalPath() returns the case-sensitive
+        // spelled file name.
+        String path;
+        try {
+            path = f.getCanonicalPath();
+        } catch (IOException ex) {
+            return false;
+        }
+        char[] pcs = path.toCharArray();
+        char[] ncs = name.toCharArray();
+        int i = pcs.length - 1;
+        int j = ncs.length - 1;
+        while (i >= 0 && j >= 0) {
+            while (i >= 0 && pcs[i] == File.separatorChar) i--;
+            while (j >= 0 && ncs[j] == File.separatorChar) j--;
+            if (i >= 0 && j >= 0) {
+                if (pcs[i] != ncs[j]) return false;
+                i--;
+                j--;
+            }
+        }
+        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(String name);
+
+        JavaFileObject getFileObject(String subdirectory, String file);
+
+        List<String> getFiles(String subdirectory);
+
+        Set<String> getSubdirectories();
+    }
+
+    public class ZipArchive implements Archive {
+        protected final Map<String,List<String>> map;
+        protected final ZipFile zdir;
+        public ZipArchive(ZipFile zdir) throws IOException {
+            this.zdir = zdir;
+            this.map = new HashMap<String,List<String>>();
+            for (Enumeration<? extends ZipEntry> e = zdir.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('/');
+            String dirname = 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(String name) {
+            int i = name.lastIndexOf('/');
+            String dirname = name.substring(0, i+1);
+            String basename = name.substring(i+1);
+            if (basename.length() == 0)
+                return false;
+            List<String> list = map.get(dirname);
+            return (list != null && list.contains(basename));
+        }
+
+        public List<String> getFiles(String subdirectory) {
+            return map.get(subdirectory);
+        }
+
+        public JavaFileObject getFileObject(String subdirectory, String file) {
+            ZipEntry ze = zdir.getEntry(subdirectory + file);
+            return new ZipFileObject(file, zdir, ze);
+        }
+
+        public Set<String> getSubdirectories() {
+            return map.keySet();
+        }
+
+        public void close() throws IOException {
+            zdir.close();
+        }
+    }
+
+    public class SymbolArchive extends ZipArchive {
+        final File origFile;
+        public SymbolArchive(File orig, ZipFile zdir) throws IOException {
+            super(zdir);
+            this.origFile = orig;
+        }
+
+        @Override
+        void addZipEntry(ZipEntry entry) {
+            // called from super constructor, may not refer to origFile.
+            String name = entry.getName();
+            if (!name.startsWith(symbolFilePrefix))
+                return;
+            name = name.substring(symbolFilePrefix.length());
+            int i = name.lastIndexOf('/');
+            String dirname = 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);
+        }
+
+        @Override
+        public JavaFileObject getFileObject(String subdirectory, String file) {
+            return super.getFileObject(symbolFilePrefix + subdirectory, file);
+        }
+    }
+
+    public class MissingArchive implements Archive {
+        final File zipFileName;
+        public MissingArchive(File name) {
+            zipFileName = name;
+        }
+        public boolean contains(String name) {
+              return false;
+        }
+
+        public void close() {
+        }
+
+        public JavaFileObject getFileObject(String subdirectory, String file) {
+            return null;
+        }
+
+        public List<String> getFiles(String subdirectory) {
+            return List.nil();
+        }
+
+        public Set<String> getSubdirectories() {
+            return Collections.emptySet();
+        }
+    }
+
+    /** A directory of zip files already opened.
+     */
+    Map<File, Archive> archives = new HashMap<File,Archive>();
+
+    /** Open a new zip file directory.
+     */
+    protected Archive openArchive(File zipFileName) throws IOException {
+        Archive archive = archives.get(zipFileName);
+        if (archive == null) {
+            File origZipFileName = zipFileName;
+            if (!ignoreSymbolFile && paths.isBootClassPathRtJar(zipFileName)) {
+                File file = zipFileName.getParentFile().getParentFile(); // ${java.home}
+                if (new File(file.getName()).equals(new File("jre")))
+                    file = file.getParentFile();
+                // file == ${jdk.home}
+                for (String name : symbolFileLocation)
+                    file = new File(file, name);
+                // file == ${jdk.home}/lib/ct.sym
+                if (file.exists())
+                    zipFileName = file;
+            }
+
+            try {
+
+                ZipFile zdir = null;
+
+                boolean usePreindexedCache = false;
+                String preindexCacheLocation = null;
+
+                if (!useZipFileIndex) {
+                    zdir = new ZipFile(zipFileName);
+                }
+                else {
+                    usePreindexedCache = options.get("usezipindex") != null;
+                    preindexCacheLocation = options.get("java.io.tmpdir");
+                    String optCacheLoc = options.get("cachezipindexdir");
+
+                    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 (origZipFileName == zipFileName) {
+                    if (!useZipFileIndex) {
+                        archive = new ZipArchive(zdir);
+                    } else {
+                        archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, 0,
+                                usePreindexedCache, preindexCacheLocation, options.get("writezipindexfiles") != null));
+                    }
+                }
+                else {
+                    if (!useZipFileIndex) {
+                        archive = new SymbolArchive(origZipFileName, zdir);
+                    }
+                    else {
+                        archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, symbolFilePrefixLength,
+                                usePreindexedCache, preindexCacheLocation, options.get("writezipindexfiles") != null));
+                    }
+                }
+            } catch (FileNotFoundException ex) {
+                archive = new MissingArchive(zipFileName);
+            } catch (IOException ex) {
+                log.error("error.reading.file", zipFileName, ex.getLocalizedMessage());
+                archive = new MissingArchive(zipFileName);
+            }
+
+            archives.put(origZipFileName, archive);
+        }
+        return archive;
+    }
+
+    /** Flush any output resources.
+     */
+    public void flush() {
+        contentCache.clear();
+    }
+
+    /**
+     * Close the JavaFileManager, releasing resources.
+     */
+    public void close() {
+        for (Iterator<Archive> i = archives.values().iterator(); i.hasNext(); ) {
+            Archive a = i.next();
+            i.remove();
+            try {
+                a.close();
+            } catch (IOException e) {
+            }
+        }
+    }
+
+    private Map<JavaFileObject, SoftReference<CharBuffer>> contentCache = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
+
+    private String defaultEncodingName;
+    private String getDefaultEncodingName() {
+        if (defaultEncodingName == null) {
+            defaultEncodingName =
+                new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
+        }
+        return defaultEncodingName;
+    }
+
+    protected String getEncodingName() {
+        String encName = options.get(OptionName.ENCODING);
+        if (encName == null)
+            return getDefaultEncodingName();
+        else
+            return encName;
+    }
+
+    protected Source getSource() {
+        String sourceName = options.get(OptionName.SOURCE);
+        Source source = null;
+        if (sourceName != null)
+            source = Source.lookup(sourceName);
+        return (source != null ? source : Source.DEFAULT);
+    }
+
+    /**
+     * Make a byte buffer from an input stream.
+     */
+    private ByteBuffer makeByteBuffer(InputStream in)
+        throws IOException {
+        int limit = in.available();
+        if (mmappedIO && in instanceof FileInputStream) {
+            // Experimental memory mapped I/O
+            FileInputStream fin = (FileInputStream)in;
+            return fin.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, limit);
+        }
+        if (limit < 1024) limit = 1024;
+        ByteBuffer result = byteBufferCache.get(limit);
+        int position = 0;
+        while (in.available() != 0) {
+            if (position >= limit)
+                // expand buffer
+                result = ByteBuffer.
+                    allocate(limit <<= 1).
+                    put((ByteBuffer)result.flip());
+            int count = in.read(result.array(),
+                position,
+                limit - position);
+            if (count < 0) break;
+            result.position(position += count);
+        }
+        return (ByteBuffer)result.flip();
+    }
+
+    /**
+     * A single-element cache of direct byte buffers.
+     */
+    private static class ByteBufferCache {
+        private ByteBuffer cached;
+        ByteBuffer get(int capacity) {
+            if (capacity < 20480) capacity = 20480;
+            ByteBuffer result =
+                (cached != null && cached.capacity() >= capacity)
+                ? (ByteBuffer)cached.clear()
+                : ByteBuffer.allocate(capacity + capacity>>1);
+            cached = null;
+            return result;
+        }
+        void put(ByteBuffer x) {
+            cached = x;
+        }
+    }
+    private final ByteBufferCache byteBufferCache;
+
+    private CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
+        Charset charset = (this.charset == null)
+            ? Charset.forName(encodingName)
+            : this.charset;
+        CharsetDecoder decoder = charset.newDecoder();
+
+        CodingErrorAction action;
+        if (ignoreEncodingErrors)
+            action = CodingErrorAction.REPLACE;
+        else
+            action = CodingErrorAction.REPORT;
+
+        return decoder
+            .onMalformedInput(action)
+            .onUnmappableCharacter(action);
+    }
+
+    /**
+     * Decode a ByteBuffer into a CharBuffer.
+     */
+    private CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
+        String encodingName = getEncodingName();
+        CharsetDecoder decoder;
+        try {
+            decoder = getDecoder(encodingName, ignoreEncodingErrors);
+        } catch (IllegalCharsetNameException e) {
+            log.error("unsupported.encoding", encodingName);
+            return (CharBuffer)CharBuffer.allocate(1).flip();
+        } catch (UnsupportedCharsetException e) {
+            log.error("unsupported.encoding", encodingName);
+            return (CharBuffer)CharBuffer.allocate(1).flip();
+        }
+
+        // slightly overestimate the buffer size to avoid reallocation.
+        float factor =
+            decoder.averageCharsPerByte() * 0.8f +
+            decoder.maxCharsPerByte() * 0.2f;
+        CharBuffer dest = CharBuffer.
+            allocate(10 + (int)(inbuf.remaining()*factor));
+
+        while (true) {
+            CoderResult result = decoder.decode(inbuf, dest, true);
+            dest.flip();
+
+            if (result.isUnderflow()) { // done reading
+                // make sure there is at least one extra character
+                if (dest.limit() == dest.capacity()) {
+                    dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
+                    dest.flip();
+                }
+                return dest;
+            } else if (result.isOverflow()) { // buffer too small; expand
+                int newCapacity =
+                    10 + dest.capacity() +
+                    (int)(inbuf.remaining()*decoder.maxCharsPerByte());
+                dest = CharBuffer.allocate(newCapacity).put(dest);
+            } else if (result.isMalformed() || result.isUnmappable()) {
+                // bad character in input
+
+                // report coding error (warn only pre 1.5)
+                if (!getSource().allowEncodingErrors()) {
+                    log.error(new SimpleDiagnosticPosition(dest.limit()),
+                              "illegal.char.for.encoding",
+                              charset == null ? encodingName : charset.name());
+                } else {
+                    log.warning(new SimpleDiagnosticPosition(dest.limit()),
+                                "illegal.char.for.encoding",
+                                charset == null ? encodingName : charset.name());
+                }
+
+                // skip past the coding error
+                inbuf.position(inbuf.position() + result.length());
+
+                // undo the flip() to prepare the output buffer
+                // for more translation
+                dest.position(dest.limit());
+                dest.limit(dest.capacity());
+                dest.put((char)0xfffd); // backward compatible
+            } else {
+                throw new AssertionError(result);
+            }
+        }
+        // unreached
+    }
+
+    public ClassLoader getClassLoader(Location location) {
+        nullCheck(location);
+        Iterable<? extends File> path = getLocation(location);
+        if (path == null)
+            return null;
+        ListBuffer<URL> lb = new ListBuffer<URL>();
+        for (File f: path) {
+            try {
+                lb.append(f.toURI().toURL());
+            } catch (MalformedURLException e) {
+                throw new AssertionError(e);
+            }
+        }
+        return new URLClassLoader(lb.toArray(new URL[lb.size()]),
+            getClass().getClassLoader());
+    }
+
+    public Iterable<JavaFileObject> list(Location location,
+                                         String packageName,
+                                         Set<JavaFileObject.Kind> kinds,
+                                         boolean recurse)
+        throws IOException
+    {
+        // validatePackageName(packageName);
+        nullCheck(packageName);
+        nullCheck(kinds);
+
+        Iterable<? extends File> path = getLocation(location);
+        if (path == null)
+            return List.nil();
+        String subdirectory = externalizeFileName(packageName);
+        ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
+
+        for (File directory : path)
+            listDirectory(directory, subdirectory, kinds, recurse, results);
+
+        return results.toList();
+    }
+
+    public String inferBinaryName(Location location, JavaFileObject file) {
+        file.getClass(); // null check
+        location.getClass(); // null check
+        // Need to match the path semantics of list(location, ...)
+        Iterable<? extends File> path = getLocation(location);
+        if (path == null) {
+            //System.err.println("Path for " + location + " is null");
+            return null;
+        }
+        //System.err.println("Path for " + location + " is " + path);
+
+        if (file instanceof RegularFileObject) {
+            RegularFileObject r = (RegularFileObject) file;
+            String rPath = r.getPath();
+            //System.err.println("RegularFileObject " + file + " " +r.getPath());
+            for (File dir: path) {
+                //System.err.println("dir: " + dir);
+                String dPath = dir.getPath();
+                if (!dPath.endsWith(File.separator))
+                    dPath += File.separator;
+                if (rPath.regionMatches(true, 0, dPath, 0, dPath.length())
+                    && new File(rPath.substring(0, dPath.length())).equals(new File(dPath))) {
+                    String relativeName = rPath.substring(dPath.length());
+                    return removeExtension(relativeName).replace(File.separatorChar, '.');
+                }
+            }
+        } else if (file instanceof ZipFileObject) {
+            ZipFileObject z = (ZipFileObject) file;
+            String entryName = z.getZipEntryName();
+            if (entryName.startsWith(symbolFilePrefix))
+                entryName = entryName.substring(symbolFilePrefix.length());
+            return removeExtension(entryName).replace('/', '.');
+        } else if (file instanceof ZipFileIndexFileObject) {
+            ZipFileIndexFileObject z = (ZipFileIndexFileObject) file;
+            String entryName = z.getZipEntryName();
+            if (entryName.startsWith(symbolFilePrefix))
+                entryName = entryName.substring(symbolFilePrefix.length());
+            return removeExtension(entryName).replace(File.separatorChar, '.');
+        } else
+            throw new IllegalArgumentException(file.getClass().getName());
+        // System.err.println("inferBinaryName failed for " + file);
+        return null;
+    }
+    // where
+        private static String removeExtension(String fileName) {
+            int lastDot = fileName.lastIndexOf(".");
+            return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
+        }
+
+    public boolean isSameFile(FileObject a, FileObject b) {
+        nullCheck(a);
+        nullCheck(b);
+        if (!(a instanceof BaseFileObject))
+            throw new IllegalArgumentException("Not supported: " + a);
+        if (!(b instanceof BaseFileObject))
+            throw new IllegalArgumentException("Not supported: " + b);
+        return a.equals(b);
+    }
+
+    public boolean handleOption(String current, Iterator<String> remaining) {
+        for (JavacOption o: javacFileManagerOptions) {
+            if (o.matches(current))  {
+                if (o.hasArg()) {
+                    if (remaining.hasNext()) {
+                        if (!o.process(options, current, remaining.next()))
+                            return true;
+                    }
+                } else {
+                    if (!o.process(options, current))
+                        return true;
+                }
+                // operand missing, or process returned false
+                throw new IllegalArgumentException(current);
+            }
+        }
+
+        return false;
+    }
+    // where
+        private static JavacOption[] javacFileManagerOptions =
+            RecognizedOptions.getJavacFileManagerOptions(
+            new RecognizedOptions.GrumpyHelper());
+
+    public int isSupportedOption(String option) {
+        for (JavacOption o : javacFileManagerOptions) {
+            if (o.matches(option))
+                return o.hasArg() ? 1 : 0;
+        }
+        return -1;
+    }
+
+    public boolean hasLocation(Location location) {
+        return getLocation(location) != null;
+    }
+
+    public JavaFileObject getJavaFileForInput(Location location,
+                                              String className,
+                                              JavaFileObject.Kind kind)
+        throws IOException
+    {
+        nullCheck(location);
+        // validateClassName(className);
+        nullCheck(className);
+        nullCheck(kind);
+        if (!sourceOrClass.contains(kind))
+            throw new IllegalArgumentException("Invalid kind " + kind);
+        return getFileForInput(location, externalizeFileName(className, kind));
+    }
+
+    public FileObject getFileForInput(Location location,
+                                      String packageName,
+                                      String relativeName)
+        throws IOException
+    {
+        nullCheck(location);
+        // validatePackageName(packageName);
+        nullCheck(packageName);
+        if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
+            throw new IllegalArgumentException("Invalid relative name: " + relativeName);
+        String name = packageName.length() == 0
+            ? relativeName
+            : new File(externalizeFileName(packageName), relativeName).getPath();
+        return getFileForInput(location, name);
+    }
+
+    private JavaFileObject getFileForInput(Location location, String name) throws IOException {
+        Iterable<? extends File> path = getLocation(location);
+        if (path == null)
+            return null;
+
+        for (File dir: path) {
+            if (dir.isDirectory()) {
+                File f = new File(dir, name.replace('/', File.separatorChar));
+                if (f.exists())
+                    return new RegularFileObject(f);
+            } else {
+                Archive a = openArchive(dir);
+                if (a.contains(name)) {
+                    int i = name.lastIndexOf('/');
+                    String dirname = name.substring(0, i+1);
+                    String basename = name.substring(i+1);
+                    return a.getFileObject(dirname, basename);
+                }
+
+            }
+        }
+        return null;
+
+    }
+
+    public JavaFileObject getJavaFileForOutput(Location location,
+                                               String className,
+                                               JavaFileObject.Kind kind,
+                                               FileObject sibling)
+        throws IOException
+    {
+        nullCheck(location);
+        // validateClassName(className);
+        nullCheck(className);
+        nullCheck(kind);
+        if (!sourceOrClass.contains(kind))
+            throw new IllegalArgumentException("Invalid kind " + kind);
+        return getFileForOutput(location, externalizeFileName(className, kind), sibling);
+    }
+
+    public FileObject getFileForOutput(Location location,
+                                       String packageName,
+                                       String relativeName,
+                                       FileObject sibling)
+        throws IOException
+    {
+        nullCheck(location);
+        // validatePackageName(packageName);
+        nullCheck(packageName);
+        if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
+            throw new IllegalArgumentException("relativeName is invalid");
+        String name = packageName.length() == 0
+            ? relativeName
+            : new File(externalizeFileName(packageName), relativeName).getPath();
+        return getFileForOutput(location, name, sibling);
+    }
+
+    private JavaFileObject getFileForOutput(Location location,
+                                            String fileName,
+                                            FileObject sibling)
+        throws IOException
+    {
+        File dir;
+        if (location == CLASS_OUTPUT) {
+            if (getClassOutDir() != null) {
+                dir = getClassOutDir();
+            } else {
+                File siblingDir = null;
+                if (sibling != null && sibling instanceof RegularFileObject) {
+                    siblingDir = ((RegularFileObject)sibling).f.getParentFile();
+                }
+                return new RegularFileObject(new File(siblingDir, baseName(fileName)));
+            }
+        } else if (location == SOURCE_OUTPUT) {
+            dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
+        } else {
+            Iterable<? extends File> path = paths.getPathForLocation(location);
+            dir = null;
+            for (File f: path) {
+                dir = f;
+                break;
+            }
+        }
+
+        File file = (dir == null ? new File(fileName) : new File(dir, fileName));
+        return new RegularFileObject(file);
+
+    }
+
+    public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(
+        Iterable<? extends File> files)
+    {
+        ArrayList<RegularFileObject> result;
+        if (files instanceof Collection)
+            result = new ArrayList<RegularFileObject>(((Collection)files).size());
+        else
+            result = new ArrayList<RegularFileObject>();
+        for (File f: files)
+            result.add(new RegularFileObject(nullCheck(f)));
+        return result;
+    }
+
+    public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
+        return getJavaFileObjectsFromFiles(Arrays.asList(nullCheck(files)));
+    }
+
+    public void setLocation(Location location,
+                            Iterable<? extends File> path)
+        throws IOException
+    {
+        nullCheck(location);
+        paths.lazy();
+
+        final File dir = location.isOutputLocation() ? getOutputDirectory(path) : null;
+
+        if (location == CLASS_OUTPUT)
+            classOutDir = getOutputLocation(dir, D);
+        else if (location == SOURCE_OUTPUT)
+            sourceOutDir = getOutputLocation(dir, S);
+        else
+            paths.setPathForLocation(location, path);
+    }
+    // where
+        private File getOutputDirectory(Iterable<? extends File> path) throws IOException {
+            if (path == null)
+                return null;
+            Iterator<? extends File> pathIter = path.iterator();
+            if (!pathIter.hasNext())
+                throw new IllegalArgumentException("empty path for directory");
+            File dir = pathIter.next();
+            if (pathIter.hasNext())
+                throw new IllegalArgumentException("path too long for directory");
+            if (!dir.exists())
+                throw new FileNotFoundException(dir + ": does not exist");
+            else if (!dir.isDirectory())
+                throw new IOException(dir + ": not a directory");
+            return dir;
+        }
+
+    private File getOutputLocation(File dir, OptionName defaultOptionName) {
+        if (dir != null)
+            return dir;
+        String arg = options.get(defaultOptionName);
+        if (arg == null)
+            return null;
+        return new File(arg);
+    }
+
+    public Iterable<? extends File> getLocation(Location location) {
+        nullCheck(location);
+        paths.lazy();
+        if (location == CLASS_OUTPUT) {
+            return (getClassOutDir() == null ? null : List.of(getClassOutDir()));
+        } else if (location == SOURCE_OUTPUT) {
+            return (getSourceOutDir() == null ? null : List.of(getSourceOutDir()));
+        } else
+            return paths.getPathForLocation(location);
+    }
+
+    private File getClassOutDir() {
+        if (classOutDir == uninited)
+            classOutDir = getOutputLocation(null, D);
+        return classOutDir;
+    }
+
+    private File getSourceOutDir() {
+        if (sourceOutDir == uninited)
+            sourceOutDir = getOutputLocation(null, S);
+        return sourceOutDir;
+    }
+
+    /**
+     * Enforces the specification of a "relative" URI as used in
+     * {@linkplain #getFileForInput(Location,String,URI)
+     * getFileForInput}.  This method must follow the rules defined in
+     * that method, do not make any changes without consulting the
+     * specification.
+     */
+    protected static boolean isRelativeUri(URI uri) {
+        if (uri.isAbsolute())
+            return false;
+        String path = uri.normalize().getPath();
+        if (path.length() == 0 /* isEmpty() is mustang API */)
+            return false;
+        char first = path.charAt(0);
+        return first != '.' && first != '/';
+    }
+
+    /**
+     * Converts a relative file name to a relative URI.  This is
+     * different from File.toURI as this method does not canonicalize
+     * the file before creating the URI.  Furthermore, no schema is
+     * used.
+     * @param file a relative file name
+     * @return a relative URI
+     * @throws IllegalArgumentException if the file name is not
+     * relative according to the definition given in {@link
+     * javax.tools.JavaFileManager#getFileForInput}
+     */
+    public static String getRelativeName(File file) {
+        if (!file.isAbsolute()) {
+            String result = file.getPath().replace(File.separatorChar, '/');
+            if (JavacFileManager.isRelativeUri(URI.create(result))) // FIXME 6419701
+                return result;
+        }
+        throw new IllegalArgumentException("Invalid relative path: " + file);
+    }
+
+    @SuppressWarnings("deprecation") // bug 6410637
+    public static String getJavacFileName(FileObject file) {
+        if (file instanceof BaseFileObject)
+            return ((BaseFileObject)file).getPath();
+        URI uri = file.toUri();
+        String scheme = uri.getScheme();
+        if (scheme == null || scheme.equals("file") || scheme.equals("jar"))
+            return uri.getPath();
+        else
+            return uri.toString();
+    }
+
+    @SuppressWarnings("deprecation") // bug 6410637
+    public static String getJavacBaseFileName(FileObject file) {
+        if (file instanceof BaseFileObject)
+            return ((BaseFileObject)file).getName();
+        URI uri = file.toUri();
+        String scheme = uri.getScheme();
+        if (scheme == null || scheme.equals("file") || scheme.equals("jar")) {
+            String path = uri.getPath();
+            if (path == null)
+                return null;
+            if (scheme != null && scheme.equals("jar"))
+                path = path.substring(path.lastIndexOf('!') + 1);
+            return path.substring(path.lastIndexOf('/') + 1);
+        } else {
+            return uri.toString();
+        }
+    }
+
+    private static <T> T nullCheck(T o) {
+        o.getClass(); // null check
+        return o;
+    }
+
+    private static <T> Iterable<T> nullCheck(Iterable<T> it) {
+        for (T t : it)
+            t.getClass(); // null check
+        return it;
+    }
+
+    /**
+     * A subclass of JavaFileObject representing regular files.
+     */
+    private class RegularFileObject extends BaseFileObject {
+        /** Have the parent directories been created?
+         */
+        private boolean hasParents=false;
+
+        /** The file's name.
+         */
+        private String name;
+
+        /** The underlying file.
+         */
+        final File f;
+
+        public RegularFileObject(File f) {
+            this(f.getName(), f);
+        }
+
+        public RegularFileObject(String name, File f) {
+            if (f.isDirectory())
+                throw new IllegalArgumentException("directories not supported");
+            this.name = name;
+            this.f = f;
+        }
+
+        public InputStream openInputStream() throws IOException {
+            return new FileInputStream(f);
+        }
+
+        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+            return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
+        }
+
+        public OutputStream openOutputStream() throws IOException {
+            ensureParentDirectoriesExist();
+            return new FileOutputStream(f);
+        }
+
+        public Writer openWriter() throws IOException {
+            ensureParentDirectoriesExist();
+            return new OutputStreamWriter(new FileOutputStream(f), getEncodingName());
+        }
+
+        private void ensureParentDirectoriesExist() throws IOException {
+            if (!hasParents) {
+                File parent = f.getParentFile();
+                if (parent != null && !parent.exists()) {
+                    if (!parent.mkdirs()) {
+                        // if the mkdirs failed, it may be because another process concurrently
+                        // created the directory, so check if the directory got created
+                        // anyway before throwing an exception
+                        if (!parent.exists() || !parent.isDirectory())
+                            throw new IOException("could not create parent directories");
+                    }
+                }
+                hasParents = true;
+            }
+        }
+
+        /** @deprecated see bug 6410637 */
+        @Deprecated
+        public String getName() {
+            return name;
+        }
+
+        public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) {
+            cn.getClass(); // null check
+            if (kind == Kind.OTHER && getKind() != kind)
+                return false;
+            String n = cn + kind.extension;
+            if (name.equals(n))
+                return true;
+            if (name.equalsIgnoreCase(n)) {
+                try {
+                    // allow for Windows
+                    return (f.getCanonicalFile().getName().equals(n));
+                } catch (IOException e) {
+                }
+            }
+            return false;
+        }
+
+        /** @deprecated see bug 6410637 */
+        @Deprecated
+        public String getPath() {
+            return f.getPath();
+        }
+
+        public long getLastModified() {
+            return f.lastModified();
+        }
+
+        public boolean delete() {
+            return f.delete();
+        }
+
+        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+            SoftReference<CharBuffer> r = contentCache.get(this);
+            CharBuffer cb = (r == null ? null : r.get());
+            if (cb == null) {
+                InputStream in = new FileInputStream(f);
+                try {
+                    ByteBuffer bb = makeByteBuffer(in);
+                    JavaFileObject prev = log.useSource(this);
+                    try {
+                        cb = decode(bb, ignoreEncodingErrors);
+                    } finally {
+                        log.useSource(prev);
+                    }
+                    byteBufferCache.put(bb); // save for next time
+                    if (!ignoreEncodingErrors)
+                        contentCache.put(this, new SoftReference<CharBuffer>(cb));
+                } finally {
+                    in.close();
+                }
+            }
+            return cb;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof RegularFileObject))
+                return false;
+            RegularFileObject o = (RegularFileObject) other;
+            try {
+                return f.equals(o.f)
+                    || f.getCanonicalFile().equals(o.f.getCanonicalFile());
+            } catch (IOException e) {
+                return false;
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            return f.hashCode();
+        }
+
+        public URI toUri() {
+            try {
+                // Do no use File.toURI to avoid file system access
+                String path = f.getAbsolutePath().replace(File.separatorChar, '/');
+                return new URI("file://" + path).normalize();
+            } catch (URISyntaxException ex) {
+                return f.toURI();
+            }
+        }
+
+    }
+
+    /**
+     * A subclass of JavaFileObject representing zip entries.
+     */
+    public class ZipFileObject extends BaseFileObject {
+
+        /** The entry's name.
+         */
+        private String name;
+
+        /** The zipfile containing the entry.
+         */
+        ZipFile zdir;
+
+        /** The underlying zip entry object.
+         */
+        ZipEntry entry;
+
+        public ZipFileObject(String name, ZipFile zdir, ZipEntry entry) {
+            this.name = name;
+            this.zdir = zdir;
+            this.entry = entry;
+        }
+
+        public InputStream openInputStream() throws IOException {
+            return zdir.getInputStream(entry);
+        }
+
+        public OutputStream openOutputStream() throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+            return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
+        }
+
+        public Writer openWriter() throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        /** @deprecated see bug 6410637 */
+        @Deprecated
+        public String getName() {
+            return name;
+        }
+
+        public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
+            cn.getClass(); // null check
+            if (k == Kind.OTHER && getKind() != k)
+                return false;
+            return name.equals(cn + k.extension);
+        }
+
+        /** @deprecated see bug 6410637 */
+        @Deprecated
+        public String getPath() {
+            return zdir.getName() + "(" + entry + ")";
+        }
+
+        public long getLastModified() {
+            return entry.getTime();
+        }
+
+        public boolean delete() {
+            throw new UnsupportedOperationException();
+        }
+
+        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+            SoftReference<CharBuffer> r = contentCache.get(this);
+            CharBuffer cb = (r == null ? null : r.get());
+            if (cb == null) {
+                InputStream in = zdir.getInputStream(entry);
+                try {
+                    ByteBuffer bb = makeByteBuffer(in);
+                    JavaFileObject prev = log.useSource(this);
+                    try {
+                        cb = decode(bb, ignoreEncodingErrors);
+                    } finally {
+                        log.useSource(prev);
+                    }
+                    byteBufferCache.put(bb); // save for next time
+                    if (!ignoreEncodingErrors)
+                        contentCache.put(this, new SoftReference<CharBuffer>(cb));
+                } finally {
+                    in.close();
+                }
+            }
+            return cb;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof ZipFileObject))
+                return false;
+            ZipFileObject o = (ZipFileObject) other;
+            return zdir.equals(o.zdir) || name.equals(o.name);
+        }
+
+        @Override
+        public int hashCode() {
+            return zdir.hashCode() + name.hashCode();
+        }
+
+        public String getZipName() {
+            return zdir.getName();
+        }
+
+        public String getZipEntryName() {
+            return entry.getName();
+        }
+
+        public URI toUri() {
+            String zipName = new File(getZipName()).toURI().normalize().getPath();
+            String entryName = getZipEntryName();
+            return URI.create("jar:" + zipName + "!" + entryName);
+        }
+
+    }
+
+    /**
+     * A subclass of JavaFileObject representing zip entries using the com.sun.tools.javac.zip.ZipFileIndex implementation.
+     */
+    public class ZipFileIndexFileObject extends BaseFileObject {
+
+            /** The entry's name.
+         */
+        private String name;
+
+        /** The zipfile containing the entry.
+         */
+        ZipFileIndex zfIndex;
+
+        /** The underlying zip entry object.
+         */
+        ZipFileIndexEntry entry;
+
+        /** The InputStream for this zip entry (file.)
+         */
+        InputStream inputStream = null;
+
+        /** The name of the zip file where this entry resides.
+         */
+        String zipName;
+
+        JavacFileManager defFileManager = null;
+
+        public ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndexEntry entry, String zipFileName) {
+            super();
+            this.name = entry.getFileName();
+            this.zfIndex = zfIndex;
+            this.entry = entry;
+            this.zipName = zipFileName;
+            defFileManager = fileManager;
+        }
+
+        public InputStream openInputStream() throws IOException {
+
+            if (inputStream == null) {
+                inputStream = new ByteArrayInputStream(read());
+            }
+            return inputStream;
+        }
+
+        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+            return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
+        }
+
+        public OutputStream openOutputStream() throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        public Writer openWriter() throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        /** @deprecated see bug 6410637 */
+        @Deprecated
+        public String getName() {
+            return name;
+        }
+
+        public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
+            cn.getClass(); // null check
+            if (k == Kind.OTHER && getKind() != k)
+                return false;
+            return name.equals(cn + k.extension);
+        }
+
+        /** @deprecated see bug 6410637 */
+        @Deprecated
+        public String getPath() {
+            return zipName + "(" + entry.getName() + ")";
+        }
+
+        public long getLastModified() {
+            return entry.getLastModified();
+        }
+
+        public boolean delete() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof ZipFileIndexFileObject))
+                return false;
+            ZipFileIndexFileObject o = (ZipFileIndexFileObject) other;
+            return entry.equals(o.entry);
+        }
+
+        @Override
+        public int hashCode() {
+            return zipName.hashCode() + (name.hashCode() << 10);
+        }
+
+        public String getZipName() {
+            return zipName;
+        }
+
+        public String getZipEntryName() {
+            return entry.getName();
+        }
+
+        public URI toUri() {
+            String zipName = new File(getZipName()).toURI().normalize().getPath();
+            String entryName = getZipEntryName();
+            if (File.separatorChar != '/') {
+                entryName = entryName.replace(File.separatorChar, '/');
+            }
+            return URI.create("jar:" + zipName + "!" + entryName);
+        }
+
+        private byte[] read() throws IOException {
+            if (entry == null) {
+                entry = zfIndex.getZipIndexEntry(name);
+                if (entry == null)
+                  throw new FileNotFoundException();
+            }
+            return zfIndex.read(entry);
+        }
+
+        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+            SoftReference<CharBuffer> r = defFileManager.contentCache.get(this);
+            CharBuffer cb = (r == null ? null : r.get());
+            if (cb == null) {
+                InputStream in = new ByteArrayInputStream(zfIndex.read(entry));
+                try {
+                    ByteBuffer bb = makeByteBuffer(in);
+                    JavaFileObject prev = log.useSource(this);
+                    try {
+                        cb = decode(bb, ignoreEncodingErrors);
+                    } finally {
+                        log.useSource(prev);
+                    }
+                    byteBufferCache.put(bb); // save for next time
+                    if (!ignoreEncodingErrors)
+                        defFileManager.contentCache.put(this, new SoftReference<CharBuffer>(cb));
+                } finally {
+                    in.close();
+                }
+            }
+            return cb;
+        }
+    }
+
+    public class ZipFileIndexArchive implements Archive {
+        private final ZipFileIndex zfIndex;
+        private JavacFileManager fileManager;
+
+        public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException {
+            this.fileManager = fileManager;
+            this.zfIndex = zdir;
+        }
+
+        public boolean contains(String name) {
+            return zfIndex.contains(name);
+        }
+
+        public com.sun.tools.javac.util.List<String> getFiles(String subdirectory) {
+              return zfIndex.getFiles(((subdirectory.endsWith("/") || subdirectory.endsWith("\\"))? subdirectory.substring(0, subdirectory.length() - 1) : subdirectory));
+        }
+
+        public JavaFileObject getFileObject(String subdirectory, String file) {
+            String fullZipFileName = subdirectory + file;
+            ZipFileIndexEntry entry = zfIndex.getZipIndexEntry(fullZipFileName);
+            JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile().getPath());
+            return ret;
+        }
+
+        public Set<String> getSubdirectories() {
+            return zfIndex.getAllDirectories();
+        }
+
+        public void close() throws IOException {
+            zfIndex.close();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/Old199.java	Mon Jun 16 22:23:33 2008 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import javax.tools.FileObject;
+
+/**
+ * Provides an easy migration to JSR 199 v3.3.  The class is
+ * deprecated as we should remove it as soon as possible.
+ *
+ * <p><b>This is NOT part of any API supported by Sun Microsystems.
+ * 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></p>
+ *
+ * @author Peter von der Ah\u00e9
+ */
+@Deprecated
+public class Old199 {
+
+    private Old199() {}
+
+    public static String getPath(FileObject jfo) {
+        return JavacFileManager.getJavacFileName(jfo);
+    }
+
+    public static String getName(FileObject jfo) {
+        return JavacFileManager.getJavacBaseFileName(jfo);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/Paths.java	Mon Jun 16 22:23:33 2008 -0700
@@ -0,0 +1,577 @@
+/*
+ * Copyright 2003-2006 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.jar.Attributes;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+import java.util.zip.ZipFile;
+import java.util.ArrayList;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import javax.tools.JavaFileManager.Location;
+
+import com.sun.tools.javac.code.Lint;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Options;
+
+import static javax.tools.StandardLocation.*;
+import static com.sun.tools.javac.main.OptionName.*;
+
+/** This class converts command line arguments, environment variables
+ *  and system properties (in File.pathSeparator-separated String form)
+ *  into a boot class path, user class path, and source path (in
+ *  Collection<String> form).
+ *
+ *  <p><b>This is NOT part of any API supported by Sun Microsystems.  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 Paths {
+
+    /** The context key for the todo list */
+    protected static final Context.Key<Paths> pathsKey =
+        new Context.Key<Paths>();
+
+    /** Get the Paths instance for this context.
+     *  @param context the context
+     *  @return the Paths instance for this context
+     */
+    public static Paths instance(Context context) {
+        Paths instance = context.get(pathsKey);
+        if (instance == null)
+            instance = new Paths(context);
+        return instance;
+    }
+
+    /** The log to use for warning output */
+    private Log log;
+
+    /** Collection of command-line options */
+    private Options options;
+
+    /** Handler for -Xlint options */
+    private Lint lint;
+
+    private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
+    private static Map<File, PathEntry> pathExistanceCache = new ConcurrentHashMap<File, PathEntry>();
+    private static Map<File, java.util.List<File>> manifestEntries = new ConcurrentHashMap<File, java.util.List<File>>();
+    private static Map<File, Boolean> isDirectory = new ConcurrentHashMap<File, Boolean>();
+    private static Lock lock = new ReentrantLock();
+
+    public static void clearPathExistanceCache() {
+            pathExistanceCache.clear();
+    }
+
+    static class PathEntry {
+        boolean exists = false;
+        boolean isFile = false;
+        File cannonicalPath = null;
+    }
+
+    protected Paths(Context context) {
+        context.put(pathsKey, this);
+        pathsForLocation = new HashMap<Location,Path>(16);
+        setContext(context);
+    }
+
+    void setContext(Context context) {
+        log = Log.instance(context);
+        options = Options.instance(context);
+        lint = Lint.instance(context);
+    }
+
+    /** Whether to warn about non-existent path elements */
+    private boolean warn;
+
+    private Map<Location, Path> pathsForLocation;
+
+    private boolean inited = false; // TODO? caching bad?
+
+    /**
+     * rt.jar as found on the default bootclass path.  If the user specified a
+     * bootclasspath, null is used.
+     */
+    private File bootClassPathRtJar = null;
+
+    Path getPathForLocation(Location location) {
+        Path path = pathsForLocation.get(location);
+        if (path == null)
+            setPathForLocation(location, null);
+        return pathsForLocation.get(location);
+    }
+
+    void setPathForLocation(Location location, Iterable<? extends File> path) {
+        // TODO? if (inited) throw new IllegalStateException
+        // TODO: otherwise reset sourceSearchPath, classSearchPath as needed
+        Path p;
+        if (path == null) {
+            if (location == CLASS_PATH)
+                p = computeUserClassPath();
+            else if (location == PLATFORM_CLASS_PATH)
+                p = computeBootClassPath();
+            else if (location == ANNOTATION_PROCESSOR_PATH)
+                p = computeAnnotationProcessorPath();
+            else if (location == SOURCE_PATH)
+                p = computeSourcePath();
+            else
+                // no defaults for other paths
+                p = null;
+        } else {
+            p = new Path();
+            for (File f: path)
+                p.addFile(f, warn); // TODO: is use of warn appropriate?
+        }
+        pathsForLocation.put(location, p);
+    }
+
+    protected void lazy() {
+        if (!inited) {
+            warn = lint.isEnabled(Lint.LintCategory.PATH);
+
+            pathsForLocation.put(PLATFORM_CLASS_PATH, computeBootClassPath());
+            pathsForLocation.put(CLASS_PATH, computeUserClassPath());
+            pathsForLocation.put(SOURCE_PATH, computeSourcePath());
+
+            inited = true;
+        }
+    }
+
+    public Collection<File> bootClassPath() {
+        lazy();
+        return Collections.unmodifiableCollection(getPathForLocation(PLATFORM_CLASS_PATH));
+    }
+    public Collection<File> userClassPath() {
+        lazy();
+        return Collections.unmodifiableCollection(getPathForLocation(CLASS_PATH));
+    }
+    public Collection<File> sourcePath() {
+        lazy();
+        Path p = getPathForLocation(SOURCE_PATH);
+        return p == null || p.size() == 0
+            ? null
+            : Collections.unmodifiableCollection(p);
+    }
+
+    boolean isBootClassPathRtJar(File file) {
+        return file.equals(bootClassPathRtJar);
+    }
+
+    private static class PathIterator implements Iterable<String> {
+        private int pos = 0;
+        private final String path;
+        private final String emptyPathDefault;
+
+        public PathIterator(String path, String emptyPathDefault) {
+            this.path = path;
+            this.emptyPathDefault = emptyPathDefault;
+        }
+        public PathIterator(String path) { this(path, null); }
+        public Iterator<String> iterator() {
+            return new Iterator<String>() {
+                public boolean hasNext() {
+                    return pos <= path.length();
+                }
+                public String next() {
+                    int beg = pos;
+                    int end = path.indexOf(File.pathSeparator, beg);
+                    if (end == -1)
+                        end = path.length();
+                    pos = end + 1;
+
+                    if (beg == end && emptyPathDefault != null)
+                        return emptyPathDefault;
+                    else
+                        return path.substring(beg, end);
+                }
+                public void remove() {
+                    throw new UnsupportedOperationException();
+                }
+            };
+        }
+    }
+
+    private class Path extends LinkedHashSet<File> {
+        private static final long serialVersionUID = 0;
+
+        private boolean expandJarClassPaths = false;
+        private Set<File> canonicalValues = new HashSet<File>();
+
+        public Path expandJarClassPaths(boolean x) {
+            expandJarClassPaths = x;
+            return this;
+        }
+
+        /** What to use when path element is the empty string */
+        private String emptyPathDefault = null;
+
+        public Path emptyPathDefault(String x) {
+            emptyPathDefault = x;
+            return this;
+        }
+
+        public Path() { super(); }
+
+        public Path addDirectories(String dirs, boolean warn) {
+            if (dirs != null)
+                for (String dir : new PathIterator(dirs))
+                    addDirectory(dir, warn);
+            return this;
+        }
+
+        public Path addDirectories(String dirs) {
+            return addDirectories(dirs, warn);
+        }
+
+        private void addDirectory(String dir, boolean warn) {
+            if (! new File(dir).isDirectory()) {
+                if (warn)
+                    log.warning("dir.path.element.not.found", dir);
+                return;
+            }
+
+            File[] files = new File(dir).listFiles();
+            if (files == null)
+                return;
+
+            for (File direntry : files) {
+                if (isArchive(direntry))
+                    addFile(direntry, warn);
+            }
+        }
+
+        public Path addFiles(String files, boolean warn) {
+            if (files != null)
+                for (String file : new PathIterator(files, emptyPathDefault))
+                    addFile(file, warn);
+            return this;
+        }
+
+        public Path addFiles(String files) {
+            return addFiles(files, warn);
+        }
+
+        public Path addFile(String file, boolean warn) {
+            addFile(new File(file), warn);
+            return this;
+        }
+
+        public void addFile(File file, boolean warn) {
+            boolean foundInCache = false;
+            PathEntry pe = null;
+            if (!NON_BATCH_MODE) {
+                    pe = pathExistanceCache.get(file);
+                    if (pe != null) {
+                        foundInCache = true;
+                    }
+                    else {
+                        pe = new PathEntry();
+                    }
+            }
+            else {
+                pe = new PathEntry();
+            }
+
+            File canonFile;
+            try {
+                if (!foundInCache) {
+                    pe.cannonicalPath = file.getCanonicalFile();
+                }
+                else {
+                   canonFile = pe.cannonicalPath;
+                }
+            } catch (IOException e) {
+                pe.cannonicalPath = canonFile = file;
+            }
+
+            if (contains(file) || canonicalValues.contains(pe.cannonicalPath)) {
+                /* Discard duplicates and avoid infinite recursion */
+                return;
+            }
+
+            if (!foundInCache) {
+                pe.exists = file.exists();
+                pe.isFile = file.isFile();
+                if (!NON_BATCH_MODE) {
+                    pathExistanceCache.put(file, pe);
+                }
+            }
+
+            if (! pe.exists) {
+                /* No such file or directory exists */
+                if (warn)
+                    log.warning("path.element.not.found", file);
+            } else if (pe.isFile) {
+                /* File is an ordinary file. */
+                if (!isArchive(file)) {
+                    /* Not a recognized extension; open it to see if
+                     it looks like a valid zip file. */
+                    try {
+                        ZipFile z = new ZipFile(file);
+                        z.close();
+                        if (warn)
+                            log.warning("unexpected.archive.file", file);
+                    } catch (IOException e) {
+                        // FIXME: include e.getLocalizedMessage in warning
+                        if (warn)
+                            log.warning("invalid.archive.file", file);
+                        return;
+                    }
+                }
+            }
+
+            /* Now what we have left is either a directory or a file name
+               confirming to archive naming convention */
+            super.add(file);
+            canonicalValues.add(pe.cannonicalPath);
+
+            if (expandJarClassPaths && file.exists() && file.isFile())
+                addJarClassPath(file, warn);
+        }
+
+        // Adds referenced classpath elements from a jar's Class-Path
+        // Manifest entry.  In some future release, we may want to
+        // update this code to recognize URLs rather than simple
+        // filenames, but if we do, we should redo all path-related code.
+        private void addJarClassPath(File jarFile, boolean warn) {
+            try {
+                java.util.List<File> manifestsList = manifestEntries.get(jarFile);
+                if (!NON_BATCH_MODE) {
+                    lock.lock();
+                    try {
+                        if (manifestsList != null) {
+                            for (File entr : manifestsList) {
+                                addFile(entr, warn);
+                            }
+                            return;
+                        }
+                    }
+                    finally {
+                        lock.unlock();
+                    }
+                }
+
+                if (!NON_BATCH_MODE) {
+                    manifestsList = new ArrayList<File>();
+                    manifestEntries.put(jarFile, manifestsList);
+                }
+
+                String jarParent = jarFile.getParent();
+                JarFile jar = new JarFile(jarFile);
+
+                try {
+                    Manifest man = jar.getManifest();
+                    if (man == null) return;
+
+                    Attributes attr = man.getMainAttributes();
+                    if (attr == null) return;
+
+                    String path = attr.getValue(Attributes.Name.CLASS_PATH);
+                    if (path == null) return;
+
+                    for (StringTokenizer st = new StringTokenizer(path);
+                         st.hasMoreTokens();) {
+                        String elt = st.nextToken();
+                        File f = (jarParent == null ? new File(elt) : new File(jarParent, elt));
+                        addFile(f, warn);
+
+                        if (!NON_BATCH_MODE) {
+                            lock.lock();
+                            try {
+                                manifestsList.add(f);
+                            }
+                            finally {
+                                lock.unlock();
+                            }
+                        }
+                    }
+                } finally {
+                    jar.close();
+                }
+            } catch (IOException e) {
+                log.error("error.reading.file", jarFile, e.getLocalizedMessage());
+            }
+        }
+    }
+
+    private Path computeBootClassPath() {
+        bootClassPathRtJar = null;
+        String optionValue;
+        Path path = new Path();
+
+        path.addFiles(options.get(XBOOTCLASSPATH_PREPEND));
+
+        if ((optionValue = options.get(ENDORSEDDIRS)) != null)
+            path.addDirectories(optionValue);
+        else
+            path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
+
+        if ((optionValue = options.get(BOOTCLASSPATH)) != null) {
+            path.addFiles(optionValue);
+        } else {
+            // Standard system classes for this compiler's release.
+            String files = System.getProperty("sun.boot.class.path");
+            path.addFiles(files, false);
+            File rt_jar = new File("rt.jar");
+            for (String file : new PathIterator(files, null)) {
+                File f = new File(file);
+                if (new File(f.getName()).equals(rt_jar))
+                    bootClassPathRtJar = f;
+            }
+        }
+
+        path.addFiles(options.get(XBOOTCLASSPATH_APPEND));
+
+        // Strictly speaking, standard extensions are not bootstrap
+        // classes, but we treat them identically, so we'll pretend
+        // that they are.
+        if ((optionValue = options.get(EXTDIRS)) != null)
+            path.addDirectories(optionValue);
+        else
+            path.addDirectories(System.getProperty("java.ext.dirs"), false);
+
+        return path;
+    }
+
+    private Path computeUserClassPath() {
+        String cp = options.get(CLASSPATH);
+
+        // CLASSPATH environment variable when run from `javac'.
+        if (cp == null) cp = System.getProperty("env.class.path");
+
+        // If invoked via a java VM (not the javac launcher), use the
+        // platform class path
+        if (cp == null && System.getProperty("application.home") == null)
+            cp = System.getProperty("java.class.path");
+
+        // Default to current working directory.
+        if (cp == null) cp = ".";
+
+        return new Path()
+            .expandJarClassPaths(true) // Only search user jars for Class-Paths
+            .emptyPathDefault(".")     // Empty path elt ==> current directory
+            .addFiles(cp);
+    }
+
+    private Path computeSourcePath() {
+        String sourcePathArg = options.get(SOURCEPATH);
+        if (sourcePathArg == null)
+            return null;
+
+        return new Path().addFiles(sourcePathArg);
+    }
+
+    private Path computeAnnotationProcessorPath() {
+        String processorPathArg = options.get(PROCESSORPATH);
+        if (processorPathArg == null)
+            return null;
+
+        return new Path().addFiles(processorPathArg);
+    }
+
+    /** The actual effective locations searched for sources */
+    private Path sourceSearchPath;
+
+    public Collection<File> sourceSearchPath() {
+        if (sourceSearchPath == null) {
+            lazy();
+            Path sourcePath = getPathForLocation(SOURCE_PATH);
+            Path userClassPath = getPathForLocation(CLASS_PATH);
+            sourceSearchPath = sourcePath != null ? sourcePath : userClassPath;
+        }
+        return Collections.unmodifiableCollection(sourceSearchPath);
+    }
+
+    /** The actual effective locations searched for classes */
+    private Path classSearchPath;
+
+    public Collection<File> classSearchPath() {
+        if (classSearchPath == null) {
+            lazy();
+            Path bootClassPath = getPathForLocation(PLATFORM_CLASS_PATH);
+            Path userClassPath = getPathForLocation(CLASS_PATH);
+            classSearchPath = new Path();
+            classSearchPath.addAll(bootClassPath);
+            classSearchPath.addAll(userClassPath);
+        }
+        return Collections.unmodifiableCollection(classSearchPath);
+    }
+
+    /** The actual effective locations for non-source, non-class files */
+    private Path otherSearchPath;
+
+    Collection<File> otherSearchPath() {
+        if (otherSearchPath == null) {
+            lazy();
+            Path userClassPath = getPathForLocation(CLASS_PATH);
+            Path sourcePath = getPathForLocation(SOURCE_PATH);
+            if (sourcePath == null)
+                otherSearchPath = userClassPath;
+            else {
+                otherSearchPath = new Path();
+                otherSearchPath.addAll(userClassPath);
+                otherSearchPath.addAll(sourcePath);
+            }
+        }
+        return Collections.unmodifiableCollection(otherSearchPath);
+    }
+
+    /** Is this the name of an archive file? */
+    private static boolean isArchive(File file) {
+        String n = file.getName().toLowerCase();
+        boolean isFile = false;
+        if (!NON_BATCH_MODE) {
+            Boolean isf = isDirectory.get(file);
+            if (isf == null) {
+                isFile = file.isFile();
+                isDirectory.put(file, isFile);
+            }
+            else {
+                isFile = isf;
+            }
+        }
+        else {
+            isFile = file.isFile();
+        }
+
+        return isFile
+            && (n.endsWith(".jar") || n.endsWith(".zip"));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java	Mon Jun 16 22:23:33 2008 -0700
@@ -0,0 +1,1248 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.zip.DataFormatException;
+import java.util.zip.Inflater;
+import java.util.zip.ZipException;
+
+/** This class implements building of index of a zip archive and access to it's context.
+ *  It also uses prebuild index if available. It supports invocations where it will
+ *  serialize an optimized zip index file to disk.
+ *
+ *  In oreder to use secondary index file make sure the option "usezipindex" is 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
+ *  "-XDcachezipindexdir=<directory>". If this flag is not provided, the dfault location is
+ *  the value of the "java.io.tmpdir" system property.
+ *
+ *  If key "-XDwritezipindexfiles" is specified, there will be new optimized index file
+ *  created for each archive, used by the compiler for compilation, at location,
+ *  specified by "cachezipindexdir" option.
+ *
+ * If nonBatchMode option is specified (-XDnonBatchMode) 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.
+ */
+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 Map<File, ZipFileIndex> zipFileIndexCache = new HashMap<File, ZipFileIndex>();
+    private static ReentrantLock lock = new ReentrantLock();
+
+    private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
+
+    private Map<String, DirectoryEntry> directories = Collections.<String, DirectoryEntry>emptyMap();
+    private Set<String> allDirs = Collections.<String>emptySet();
+
+    // ZipFileIndex data entries
+    private File zipFile;
+    private long zipFileLastModified = NOT_MODIFIED;
+    private RandomAccessFile zipRandomFile;
+    private ZipFileIndexEntry[] entries;
+
+    private boolean readFromIndex = false;
+    private File zipIndexFile = null;
+    private boolean triedToReadIndex = false;
+    private int symbolFilePrefixLength = 0;
+    private boolean hasPopulatedData = false;
+    private long lastReferenceTimeStamp = NOT_MODIFIED;
+
+    private boolean usePreindexedCache = false;
+    private String preindexedCacheLocation = null;
+
+    private boolean writeIndex = false;
+
+    /**
+     * Returns a list of all ZipFileIndex entries
+     *
+     * @return A list of ZipFileIndex entries, or an empty list
+     */
+    public static 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 static List<ZipFileIndex> getZipFileIndexes(boolean openedOnly) {
+        List<ZipFileIndex> zipFileIndexes = new ArrayList<ZipFileIndex>();
+        lock.lock();
+        try {
+            zipFileIndexes.addAll(zipFileIndexCache.values());
+
+            if (openedOnly) {
+                for(ZipFileIndex elem : zipFileIndexes) {
+                    if (!elem.isOpen()) {
+                        zipFileIndexes.remove(elem);
+                    }
+                }
+            }
+        }
+        finally {
+            lock.unlock();
+        }
+        return zipFileIndexes;
+    }
+
+    public boolean isOpen() {
+        lock.lock();
+        try {
+            return zipRandomFile != null;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public static ZipFileIndex getZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean useCache, String cacheLocation, boolean writeIndex) throws IOException {
+        ZipFileIndex zi = null;
+        lock.lock();
+        try {
+            zi = getExistingZipIndex(zipFile);
+
+            if (zi == null || (zi != null && zipFile.lastModified() != zi.zipFileLastModified)) {
+                zi = new ZipFileIndex(zipFile, symbolFilePrefixLen, writeIndex,
+                        useCache, cacheLocation);
+                zipFileIndexCache.put(zipFile, zi);
+            }
+        }
+        finally {
+            lock.unlock();
+        }
+        return zi;
+    }
+
+    public static ZipFileIndex getExistingZipIndex(File zipFile) {
+        lock.lock();
+        try {
+            return zipFileIndexCache.get(zipFile);
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public static void clearCache() {
+        lock.lock();
+        try {
+            zipFileIndexCache.clear();
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public static void clearCache(long timeNotUsed) {
+        lock.lock();
+        try {
+            Iterator<File> cachedFileIterator = zipFileIndexCache.keySet().iterator();
+            while (cachedFileIterator.hasNext()) {
+                File cachedFile = cachedFileIterator.next();
+                ZipFileIndex cachedZipIndex = zipFileIndexCache.get(cachedFile);
+                if (cachedZipIndex != null) {
+                    long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed;
+                    if (timeToTest < cachedZipIndex.lastReferenceTimeStamp || // Overflow...
+                            System.currentTimeMillis() > timeToTest) {
+                        zipFileIndexCache.remove(cachedFile);
+                    }
+                }
+            }
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public static void removeFromCache(File file) {
+        lock.lock();
+        try {
+            zipFileIndexCache.remove(file);
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    /** 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 static void setOpenedIndexes(List<ZipFileIndex>indexes) throws IllegalStateException {
+        lock.lock();
+        try {
+            if (zipFileIndexCache.isEmpty()) {
+                throw new IllegalStateException("Setting opened indexes should be called only when the ZipFileCache is empty. Call JavacFileManager.flush() before calling this method.");
+            }
+
+            for (ZipFileIndex zfi : indexes) {
+                zipFileIndexCache.put(zfi.zipFile, zfi);
+            }
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    private ZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean writeIndex,
+            boolean useCache, String cacheLocation) throws IOException {
+        this.zipFile = zipFile;
+        this.symbolFilePrefixLength = symbolFilePrefixLen;
+        this.writeIndex = writeIndex;
+        this.usePreindexedCache = useCache;
+        this.preindexedCacheLocation = cacheLocation;
+
+        if (zipFile != null) {
+            this.zipFileLastModified = zipFile.lastModified();
+        }
+
+        // Validate integrity of the zip file
+        checkIndex();
+    }
+
+    public String toString() {
+        return "ZipFileIndex of file:(" + zipFile + ")";
+    }
+
+    // Just in case...
+    protected void finalize() {
+        closeFile();
+    }
+
+    private boolean isUpToDate() {
+        if (zipFile != null &&
+                ((!NON_BATCH_MODE) || zipFileLastModified == zipFile.lastModified()) &&
+                hasPopulatedData) {
+            return true;
+        }
+
+        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.<String, DirectoryEntry>emptyMap();
+        allDirs = Collections.<String>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, "r");
+        }
+    }
+
+    private void cleanupState() {
+        // Make sure there is a valid but empty index if the file doesn't exist
+        entries = ZipFileIndexEntry.EMPTY_ARRAY;
+        directories = Collections.<String, DirectoryEntry>emptyMap();
+        zipFileLastModified = NOT_MODIFIED;
+        allDirs = Collections.<String>emptySet();
+    }
+
+    public void close() {
+        lock.lock();
+        try {
+            writeIndex();
+            closeFile();
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    private void closeFile() {
+        if (zipRandomFile != null) {
+            try {
+                zipRandomFile.close();
+            } catch (IOException ex) {
+            }
+            zipRandomFile = null;
+        }
+    }
+
+    /**
+     * Returns the ZipFileIndexEntry for an absolute path, if there is one.
+     */
+    public ZipFileIndexEntry getZipIndexEntry(String path) {
+        if (File.separatorChar != '/') {
+            path = path.replace('/', File.separatorChar);
+        }
+        lock.lock();
+        try {
+            checkIndex();
+            String lookFor = "";
+            int lastSepIndex = path.lastIndexOf(File.separatorChar);
+            boolean noSeparator = false;
+            if (lastSepIndex == -1) {
+                noSeparator = true;
+            }
+
+            DirectoryEntry de = directories.get(noSeparator ? "" : path.substring(0, lastSepIndex));
+
+            lookFor = path.substring(noSeparator ? 0 : lastSepIndex + 1);
+
+            return de == null ? null : de.getEntry(lookFor);
+        }
+        catch (IOException e) {
+            return null;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Returns a javac List of filenames within an absolute path in the ZipFileIndex.
+     */
+    public com.sun.tools.javac.util.List<String> getFiles(String path) {
+        if (File.separatorChar != '/') {
+            path = path.replace('/', File.separatorChar);
+        }
+
+        lock.lock();
+        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();
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public List<String> getAllDirectories(String path) {
+
+        if (File.separatorChar != '/') {
+            path = path.replace('/', File.separatorChar);
+        }
+
+        lock.lock();
+        try {
+            checkIndex();
+            path = path.intern();
+
+            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();
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public Set<String> getAllDirectories() {
+        lock.lock();
+        try {
+            checkIndex();
+            if (allDirs == Collections.EMPTY_SET) {
+                Set<String> alldirs = new HashSet<String>();
+                Iterator<String> dirsIter = directories.keySet().iterator();
+                while (dirsIter.hasNext()) {
+                    alldirs.add(new String(dirsIter.next()));
+                }
+
+                allDirs = alldirs;
+            }
+
+            return allDirs;
+        }
+        catch (IOException e) {
+            return Collections.<String>emptySet();
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * 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 boolean contains(String path) {
+        lock.lock();
+        try {
+            checkIndex();
+            return getZipIndexEntry(path) != null;
+        }
+        catch (IOException e) {
+            return false;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public boolean isDirectory(String path) throws IOException {
+        lock.lock();
+        try {
+            // The top level in a zip file is always a directory.
+            if (path.length() == 0) {
+                lastReferenceTimeStamp = System.currentTimeMillis();
+                return true;
+            }
+
+            if (File.separatorChar != '/')
+                path = path.replace('/', File.separatorChar);
+            checkIndex();
+            return directories.get(path) != null;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public long getLastModified(String path) throws IOException {
+        lock.lock();
+        try {
+            ZipFileIndexEntry entry = getZipIndexEntry(path);
+            if (entry == null)
+                throw new FileNotFoundException();
+            return entry.getLastModified();
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public int length(String path) throws IOException {
+        lock.lock();
+        try {
+            ZipFileIndexEntry 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;
+            }
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public byte[] read(String path) throws IOException {
+        lock.lock();
+        try {
+            ZipFileIndexEntry entry = getZipIndexEntry(path);
+            if (entry == null)
+                throw new FileNotFoundException(MessageFormat.format("Path not found in ZIP: {0}", path));
+            return read(entry);
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public byte[] read(ZipFileIndexEntry entry) throws IOException {
+        lock.lock();
+        try {
+            openFile();
+            byte[] result = readBytes(entry);
+            closeFile();
+            return result;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public int read(String path, byte[] buffer) throws IOException {
+        lock.lock();
+        try {
+            ZipFileIndexEntry entry = getZipIndexEntry(path);
+            if (entry == null)
+                throw new FileNotFoundException();
+            return read(entry, buffer);
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public int read(ZipFileIndexEntry entry, byte[] buffer)
+            throws IOException {
+        lock.lock();
+        try {
+            int result = readBytes(entry, buffer);
+            return result;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    private byte[] readBytes(ZipFileIndexEntry 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(ZipFileIndexEntry 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(ZipFileIndexEntry 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 static Inflater inflater;
+    private int inflate(byte[] src, byte[] dest) {
+
+        // construct the inflater object or reuse an existing one
+        if (inflater == null)
+            inflater = new Inflater(true);
+
+        synchronized (inflater) {
+            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 String 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;
+
+            findCENRecord(start, end);
+        }
+
+        /*
+         * 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) + 2];
+                    zipDir[0] = endbuf[i + 10];
+                    zipDir[1] = endbuf[i + 11];
+                    zipRandomFile.seek(start + get4ByteLittleEndian(endbuf, i + 16));
+                    zipRandomFile.readFully(zipDir, 2, zipDir.length - 2);
+                    return;
+                } else {
+                    endbufend = endbufpos + 21;
+                }
+            }
+            throw new ZipException("cannot read zip file");
+        }
+        private void buildIndex() throws IOException {
+            int entryCount = get2ByteLittleEndian(zipDir, 0);
+
+            entries = new ZipFileIndexEntry[entryCount];
+            // Add each of the files
+            if (entryCount > 0) {
+                directories = new HashMap<String, DirectoryEntry>();
+                ArrayList<ZipFileIndexEntry> entryList = new ArrayList<ZipFileIndexEntry>();
+                int pos = 2;
+                for (int i = 0; i < entryCount; i++) {
+                    pos = readEntry(pos, entryList, directories);
+                }
+
+                // Add the accumulated dirs into the same list
+                Iterator i = directories.keySet().iterator();
+                while (i.hasNext()) {
+                    ZipFileIndexEntry zipFileIndexEntry = new ZipFileIndexEntry( (String) i.next());
+                    zipFileIndexEntry.isDir = true;
+                    entryList.add(zipFileIndexEntry);
+                }
+
+                entries = entryList.toArray(new ZipFileIndexEntry[entryList.size()]);
+                Arrays.sort(entries);
+            } else {
+                cleanupState();
+            }
+        }
+
+        private int readEntry(int pos, List<ZipFileIndexEntry> entryList,
+                Map<String, 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;
+            }
+
+            // Use the OS's path separator. Keep the position of the last one.
+            for (int index = fileStart; index < fileEnd; index++) {
+                byte nextByte = zipDir[index];
+                if (nextByte == (byte)'\\' || nextByte == (byte)'/') {
+                    zipDir[index] = (byte)File.separatorChar;
+                    fileStart = index + 1;
+                }
+            }
+
+            String directory = null;
+            if (fileStart == dirStart)
+                directory = "";
+            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 = new String(zipDir, dirStart, lastLen, "UTF-8").intern();
+                lastDir = directory;
+
+                // Enter also all the parent directories
+                String tempDirectory = directory;
+
+                while (directories.get(tempDirectory) == null) {
+                    directories.put(tempDirectory, new DirectoryEntry(tempDirectory, zipFileIndex));
+                    int separator = tempDirectory.lastIndexOf(File.separatorChar);
+                    if (separator == -1)
+                        break;
+                    tempDirectory = tempDirectory.substring(0, separator);
+                }
+            }
+            else {
+                directory = directory.intern();
+                if (directories.get(directory) == null) {
+                    directories.put(directory, new DirectoryEntry(directory, zipFileIndex));
+                }
+            }
+
+            // For each dir create also a file
+            if (fileStart != fileEnd) {
+                ZipFileIndexEntry entry = new ZipFileIndexEntry(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 {
+        lock.lock();
+        try {
+            checkIndex();
+            return zipFileLastModified;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    /** ------------------------------------------------------------------------
+     *  DirectoryEntry class
+     * -------------------------------------------------------------------------*/
+    static class DirectoryEntry {
+        private boolean filesInited;
+        private boolean directoriesInited;
+        private boolean zipFileEntriesInited;
+        private boolean entriesInited;
+
+        private long writtenOffsetOffset = 0;
+
+        private String 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<ZipFileIndexEntry>  zipFileEntries = com.sun.tools.javac.util.List.<ZipFileIndexEntry>nil();
+
+        private List<ZipFileIndexEntry> entries = new ArrayList<ZipFileIndexEntry>();
+
+        private ZipFileIndex zipFileIndex;
+
+        private int numEntries;
+
+        DirectoryEntry(String dirName, ZipFileIndex index) {
+        filesInited = false;
+            directoriesInited = false;
+            entriesInited = false;
+
+            if (File.separatorChar == '/') {
+                dirName.replace('\\', '/');
+            }
+            else {
+                dirName.replace('/', '\\');
+            }
+
+            this.dirName = dirName.intern();
+            this.zipFileIndex = index;
+        }
+
+        private com.sun.tools.javac.util.List<String> getFiles() {
+            if (filesInited) {
+                return zipFileEntriesFiles;
+            }
+
+            initEntries();
+
+            for (ZipFileIndexEntry 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) {
+                return zipFileEntriesFiles;
+            }
+
+            initEntries();
+
+            for (ZipFileIndexEntry e : entries) {
+                if (e.isDir) {
+                    zipFileEntriesDirectories = zipFileEntriesDirectories.append(e.name);
+                }
+            }
+
+            directoriesInited = true;
+
+            return zipFileEntriesDirectories;
+        }
+
+        private com.sun.tools.javac.util.List<ZipFileIndexEntry> getEntries() {
+            if (zipFileEntriesInited) {
+                return zipFileEntries;
+            }
+
+            initEntries();
+
+            zipFileEntries = com.sun.tools.javac.util.List.nil();
+            for (ZipFileIndexEntry zfie : entries) {
+                zipFileEntries = zipFileEntries.append(zfie);
+            }
+
+            zipFileEntriesInited = true;
+
+            return zipFileEntries;
+        }
+
+        private ZipFileIndexEntry getEntry(String rootName) {
+            initEntries();
+            int index = Collections.binarySearch(entries, new ZipFileIndexEntry(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 ZipFileIndexEntry(dirName, ZipFileIndex.MIN_CHAR)) - 1;
+                int to = -Arrays.binarySearch(zipFileIndex.entries,
+                        new ZipFileIndexEntry(dirName, MAX_CHAR)) - 1;
+
+                boolean emptyList = false;
+
+                for (int i = from; i < to; i++) {
+                    entries.add(zipFileIndex.entries[i]);
+                }
+            } else {
+                File indexFile = zipFileIndex.getIndexFile();
+                if (indexFile != null) {
+                    RandomAccessFile raf = null;
+                    try {
+                        raf = new RandomAccessFile(indexFile, "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();
+
+                            ZipFileIndexEntry rfie = new ZipFileIndexEntry(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<ZipFileIndexEntry> getEntriesAsCollection() {
+            initEntries();
+
+            return entries;
+        }
+    }
+
+    private boolean readIndex() {
+        if (triedToReadIndex || !usePreindexedCache) {
+            return false;
+        }
+
+        boolean ret = false;
+        lock.lock();
+        try {
+            triedToReadIndex = true;
+            RandomAccessFile raf = null;
+            try {
+                File indexFileName = getIndexFile();
+                raf = new RandomAccessFile(indexFileName, "r");
+
+                long fileStamp = raf.readLong();
+                if (zipFile.lastModified() != fileStamp) {
+                    ret = false;
+                } else {
+                    directories = new HashMap<String, DirectoryEntry>();
+                    int numDirs = raf.readInt();
+                    for (int nDirs = 0; nDirs < numDirs; nDirs++) {
+                        int dirNameBytesLen = raf.readInt();
+                        byte [] dirNameBytes = new byte[dirNameBytesLen];
+                        raf.read(dirNameBytes);
+
+                        String dirNameStr = 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;
+            }
+        }
+        finally {
+            lock.unlock();
+        }
+
+        return ret;
+    }
+
+    private boolean writeIndex() {
+        boolean ret = false;
+        if (readFromIndex || !usePreindexedCache) {
+            return true;
+        }
+
+        if (!writeIndex) {
+            return true;
+        }
+
+        File indexFile = getIndexFile();
+        if (indexFile == null) {
+            return false;
+        }
+
+        RandomAccessFile raf = null;
+        long writtenSoFar = 0;
+        try {
+            raf = new RandomAccessFile(indexFile, "rw");
+
+            raf.writeLong(zipFileLastModified);
+            writtenSoFar += 8;
+
+
+            Iterator<String> iterDirName = directories.keySet().iterator();
+            List<DirectoryEntry> directoriesToWrite = new ArrayList<DirectoryEntry>();
+            Map<String, Long> offsets = new HashMap<String, Long>();
+            raf.writeInt(directories.keySet().size());
+            writtenSoFar += 4;
+
+            while(iterDirName.hasNext()) {
+                String dirName = iterDirName.next();
+                DirectoryEntry dirEntry = directories.get(dirName);
+
+                directoriesToWrite.add(dirEntry);
+
+                // Write the dir name bytes
+                byte [] dirNameBytes = dirName.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 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<ZipFileIndexEntry> entries = de.getEntriesAsCollection();
+                for (ZipFileIndexEntry zfie : entries) {
+                    // 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() {
+        lock.lock();
+        try {
+            return writeIndex();
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    private File getIndexFile() {
+        if (zipIndexFile == null) {
+            if (zipFile == null) {
+                return null;
+            }
+
+            zipIndexFile = new File((preindexedCacheLocation == null ? "" : preindexedCacheLocation) +
+                    zipFile.getName() + ".index");
+        }
+
+        return zipIndexFile;
+    }
+
+    public File getZipFile() {
+        return zipFile;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndexEntry.java	Mon Jun 16 22:23:33 2008 -0700
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+
+public final class ZipFileIndexEntry implements Comparable<ZipFileIndexEntry> {
+    public static final ZipFileIndexEntry[] EMPTY_ARRAY = {};
+
+    // Directory related
+    String dir;
+    boolean isDir;
+
+    // File related
+    String name;
+
+    int offset;
+    int size;
+    int compressedSize;
+    long javatime;
+
+    private int nativetime;
+
+    public ZipFileIndexEntry(String path) {
+        int separator = path.lastIndexOf(File.separatorChar);
+        if (separator == -1) {
+            dir = "".intern();
+            name = path;
+        } else {
+            dir = path.substring(0, separator).intern();
+            name = path.substring(separator + 1);
+        }
+    }
+
+    public ZipFileIndexEntry(String directory, String name) {
+        this.dir = directory.intern();
+        this.name = name;
+    }
+
+    public String getName() {
+        if (dir == null || dir.length() == 0) {
+            return name;
+        }
+
+        StringBuilder sb = new StringBuilder();
+        sb.append(dir);
+        sb.append(File.separatorChar);
+        sb.append(name);
+        return sb.toString();
+    }
+
+    public String getFileName() {
+        return name;
+    }
+
+    public long getLastModified() {
+        if (javatime == 0) {
+                javatime = dosToJavaTime(nativetime);
+        }
+        return javatime;
+    }
+
+    // From java.util.zip
+    private static long dosToJavaTime(int nativetime) {
+        // Bootstrap build problems prevent me from using the code directly
+        // Convert the raw/native time to a long for now
+        return (long)nativetime;
+    }
+
+    void setNativeTime(int natTime) {
+        nativetime = natTime;
+    }
+
+    public boolean isDirectory() {
+        return isDir;
+    }
+
+    public int compareTo(ZipFileIndexEntry other) {
+        String otherD = other.dir;
+        if (dir != otherD) {
+            int c = dir.compareTo(otherD);
+            if (c != 0)
+                return c;
+        }
+        return name.compareTo(other.name);
+    }
+
+
+    public String toString() {
+        return isDir ? ("Dir:" + dir + " : " + name) :
+            (dir + ":" + name);
+    }
+}
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Jun 16 22:23:33 2008 -0700
@@ -42,6 +42,7 @@
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.file.BaseFileObject;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.List;
 
--- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Mon Jun 16 22:23:33 2008 -0700
@@ -40,6 +40,7 @@
 import javax.tools.JavaFileObject;
 import javax.tools.DiagnosticListener;
 
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.source.util.TaskEvent;
 import com.sun.source.util.TaskListener;
 
--- a/src/share/classes/com/sun/tools/javac/main/Main.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/main/Main.java	Mon Jun 16 22:23:33 2008 -0700
@@ -25,13 +25,13 @@
 
 package com.sun.tools.javac.main;
 
-import com.sun.tools.javac.util.Options;
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.MissingResourceException;
 
 import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.jvm.Target;
 import com.sun.tools.javac.main.JavacOption.Option;
 import com.sun.tools.javac.main.RecognizedOptions.OptionHelper;
--- a/src/share/classes/com/sun/tools/javac/parser/Scanner.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/parser/Scanner.java	Mon Jun 16 22:23:33 2008 -0700
@@ -25,16 +25,12 @@
 
 package com.sun.tools.javac.parser;
 
-import java.io.*;
 import java.nio.*;
-import java.nio.ByteBuffer;
-import java.nio.charset.*;
-import java.nio.channels.*;
-import java.util.regex.*;
 
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.util.*;
 
-import com.sun.tools.javac.code.Source;
 
 import static com.sun.tools.javac.parser.Token.*;
 import static com.sun.tools.javac.util.LayoutCharacters.*;
--- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Mon Jun 16 22:23:33 2008 -0700
@@ -25,22 +25,17 @@
 
 package com.sun.tools.javac.processing;
 
-import com.sun.source.util.TaskEvent;
-import com.sun.source.util.TaskListener;
-import com.sun.tools.javac.api.JavacTaskImpl;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.*;
-import com.sun.tools.javac.code.*;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.comp.*;
-import com.sun.tools.javac.jvm.*;
-import com.sun.tools.javac.tree.*;
-import com.sun.tools.javac.parser.*;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.model.JavacElements;
-import com.sun.tools.javac.model.JavacTypes;
-import com.sun.tools.javac.tree.JCTree.*;
-import com.sun.tools.javac.main.JavaCompiler;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.regex.*;
+
+import java.net.URL;
+import java.io.Closeable;
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.IOException;
+import java.net.MalformedURLException;
 import java.io.StringWriter;
 
 import javax.annotation.processing.*;
@@ -50,24 +45,34 @@
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.util.*;
-
 import javax.tools.JavaFileManager;
 import javax.tools.StandardJavaFileManager;
 import javax.tools.JavaFileObject;
 import javax.tools.DiagnosticListener;
-import static javax.tools.StandardLocation.*;
-
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.regex.*;
 
-import java.net.URLClassLoader;
-import java.net.URL;
-import java.io.Closeable;
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.IOException;
-import java.net.MalformedURLException;
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskListener;
+import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.file.Paths;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.jvm.*;
+import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.model.JavacElements;
+import com.sun.tools.javac.model.JavacTypes;
+import com.sun.tools.javac.parser.*;
+import com.sun.tools.javac.tree.*;
+import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.util.Abort;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Options;
+
+import static javax.tools.StandardLocation.*;
 
 /**
  * Objects of this class hold and manage the state needed to support
--- a/src/share/classes/com/sun/tools/javac/util/BaseFileObject.java	Thu Jun 12 13:19:16 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright 2005-2006 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package com.sun.tools.javac.util;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.CharsetDecoder;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.NestingKind;
-import javax.tools.JavaFileObject;
-
-import static javax.tools.JavaFileObject.Kind.*;
-
-public abstract class BaseFileObject implements JavaFileObject {
-
-    public JavaFileObject.Kind getKind() {
-        String n = getName();
-        if (n.endsWith(CLASS.extension))
-            return CLASS;
-        else if (n.endsWith(SOURCE.extension))
-            return SOURCE;
-        else if (n.endsWith(HTML.extension))
-            return HTML;
-        else
-            return OTHER;
-    }
-
-    @Override
-    public String toString() {
-        return getPath();
-    }
-
-    /** @deprecated see bug 6410637 */
-    @Deprecated
-    public String getPath() {
-        return getName();
-    }
-
-    /** @deprecated see bug 6410637 */
-    @Deprecated
-    abstract public String getName();
-
-    public NestingKind getNestingKind() { return null; }
-
-    public Modifier getAccessLevel()  { return null; }
-
-    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
-        return new InputStreamReader(openInputStream(), getDecoder(ignoreEncodingErrors));
-    }
-
-    protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
-        throw new UnsupportedOperationException();
-    }
-
-}
--- a/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java	Mon Jun 16 22:23:33 2008 -0700
@@ -27,6 +27,7 @@
 
 import javax.tools.JavaFileObject;
 
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticSource;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
 
--- a/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Mon Jun 16 22:23:33 2008 -0700
@@ -25,17 +25,13 @@
 
 package com.sun.tools.javac.util;
 
-import java.net.URI;
-import java.text.MessageFormat;
 import java.util.Locale;
 import java.util.Map;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
 
 import javax.tools.Diagnostic;
-import javax.tools.FileObject;
 import javax.tools.JavaFileObject;
 
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.tree.JCTree;
 
 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
--- a/src/share/classes/com/sun/tools/javac/util/JavacFileManager.java	Thu Jun 12 13:19:16 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1715 +0,0 @@
-/*
- * Copyright 2005-2006 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package com.sun.tools.javac.util;
-
-import com.sun.tools.javac.main.JavacOption;
-import com.sun.tools.javac.main.OptionName;
-import com.sun.tools.javac.main.RecognizedOptions;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.lang.ref.SoftReference;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CoderResult;
-import java.nio.charset.CodingErrorAction;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.UnsupportedCharsetException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import javax.lang.model.SourceVersion;
-import javax.tools.FileObject;
-import javax.tools.JavaFileManager;
-import javax.tools.JavaFileObject;
-
-import com.sun.tools.javac.code.Source;
-import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
-import java.util.concurrent.ConcurrentHashMap;
-import javax.tools.StandardJavaFileManager;
-
-import com.sun.tools.javac.zip.*;
-import java.io.ByteArrayInputStream;
-
-import static com.sun.tools.javac.main.OptionName.*;
-import static javax.tools.StandardLocation.*;
-
-/**
- * This class provides access to the source, class and other files
- * used by the compiler and related tools.
- */
-public class JavacFileManager implements StandardJavaFileManager {
-
-    private static final String[] symbolFileLocation = { "lib", "ct.sym" };
-    private static final String symbolFilePrefix = "META-INF/sym/rt.jar/";
-
-    boolean useZipFileIndex;
-
-    private static int symbolFilePrefixLength = 0;
-    static {
-        try {
-            symbolFilePrefixLength = symbolFilePrefix.getBytes("UTF-8").length;
-        } catch (java.io.UnsupportedEncodingException uee) {
-            // Can't happen...UTF-8 is always supported.
-        }
-    }
-
-    private static boolean CHECK_ZIP_TIMESTAMP = false;
-    private static Map<File, Boolean> isDirectory = new ConcurrentHashMap<File, Boolean>();
-
-
-    public static char[] toArray(CharBuffer buffer) {
-        if (buffer.hasArray())
-            return ((CharBuffer)buffer.compact().flip()).array();
-        else
-            return buffer.toString().toCharArray();
-    }
-
-    /**
-     * The log to be used for error reporting.
-     */
-    protected Log log;
-
-    /** Encapsulates knowledge of paths
-     */
-    private Paths paths;
-
-    private Options options;
-
-    private final File uninited = new File("U N I N I T E D");
-
-    private final Set<JavaFileObject.Kind> sourceOrClass =
-        EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS);
-
-    /** The standard output directory, primarily used for classes.
-     *  Initialized by the "-d" option.
-     *  If classOutDir = null, files are written into same directory as the sources
-     *  they were generated from.
-     */
-    private File classOutDir = uninited;
-
-    /** The output directory, used when generating sources while processing annotations.
-     *  Initialized by the "-s" option.
-     */
-    private File sourceOutDir = uninited;
-
-    protected boolean mmappedIO;
-    protected boolean ignoreSymbolFile;
-
-    /**
-     * User provided charset (through javax.tools).
-     */
-    protected Charset charset;
-
-    /**
-     * Register a Context.Factory to create a JavacFileManager.
-     */
-    public static void preRegister(final Context context) {
-        context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() {
-            public JavaFileManager make() {
-                return new JavacFileManager(context, true, null);
-            }
-        });
-    }
-
-    /**
-     * Create a JavacFileManager using a given context, optionally registering
-     * it as the JavaFileManager for that context.
-     */
-    public JavacFileManager(Context context, boolean register, Charset charset) {
-        if (register)
-            context.put(JavaFileManager.class, this);
-        byteBufferCache = new ByteBufferCache();
-        this.charset = charset;
-        setContext(context);
-    }
-
-    /**
-     * Set the context for JavacFileManager.
-     */
-    public void setContext(Context context) {
-        log = Log.instance(context);
-        if (paths == null) {
-            paths = Paths.instance(context);
-        } else {
-            // Reuse the Paths object as it stores the locations that
-            // have been set with setLocation, etc.
-            paths.setContext(context);
-        }
-
-        options = Options.instance(context);
-
-        useZipFileIndex = System.getProperty("useJavaUtilZip") == null;// TODO: options.get("useJavaUtilZip") == null;
-        CHECK_ZIP_TIMESTAMP = System.getProperty("checkZipIndexTimestamp") != null;// TODO: options.get("checkZipIndexTimestamp") != null;
-
-        mmappedIO = options.get("mmappedIO") != null;
-        ignoreSymbolFile = options.get("ignore.symbol.file") != null;
-    }
-
-    public JavaFileObject getFileForInput(String name) {
-        return getRegularFile(new File(name));
-    }
-
-    public JavaFileObject getRegularFile(File file) {
-        return new RegularFileObject(file);
-    }
-
-    public JavaFileObject getFileForOutput(String classname,
-                                           JavaFileObject.Kind kind,
-                                           JavaFileObject sibling)
-        throws IOException
-    {
-        return getJavaFileForOutput(CLASS_OUTPUT, classname, kind, sibling);
-    }
-
-    public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
-        ListBuffer<File> files = new ListBuffer<File>();
-        for (String name : names)
-            files.append(new File(nullCheck(name)));
-        return getJavaFileObjectsFromFiles(files.toList());
-    }
-
-    public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) {
-        return getJavaFileObjectsFromStrings(Arrays.asList(nullCheck(names)));
-    }
-
-    protected JavaFileObject.Kind getKind(String extension) {
-        if (extension.equals(JavaFileObject.Kind.CLASS.extension))
-            return JavaFileObject.Kind.CLASS;
-        else if (extension.equals(JavaFileObject.Kind.SOURCE.extension))
-            return JavaFileObject.Kind.SOURCE;
-        else if (extension.equals(JavaFileObject.Kind.HTML.extension))
-            return JavaFileObject.Kind.HTML;
-        else
-            return JavaFileObject.Kind.OTHER;
-    }
-
-    private static boolean isValidName(String name) {
-        // Arguably, isValidName should reject keywords (such as in SourceVersion.isName() ),
-        // but the set of keywords depends on the source level, and we don't want
-        // impls of JavaFileManager to have to be dependent on the source level.
-        // Therefore we simply check that the argument is a sequence of identifiers
-        // separated by ".".
-        for (String s : name.split("\\.", -1)) {
-            if (!SourceVersion.isIdentifier(s))
-                return false;
-        }
-        return true;
-    }
-
-    private static void validateClassName(String className) {
-        if (!isValidName(className))
-            throw new IllegalArgumentException("Invalid class name: " + className);
-    }
-
-    private static void validatePackageName(String packageName) {
-        if (packageName.length() > 0 && !isValidName(packageName))
-            throw new IllegalArgumentException("Invalid packageName name: " + packageName);
-    }
-
-    public static void testName(String name,
-                                boolean isValidPackageName,
-                                boolean isValidClassName)
-    {
-        try {
-            validatePackageName(name);
-            if (!isValidPackageName)
-                throw new AssertionError("Invalid package name accepted: " + name);
-            printAscii("Valid package name: \"%s\"", name);
-        } catch (IllegalArgumentException e) {
-            if (isValidPackageName)
-                throw new AssertionError("Valid package name rejected: " + name);
-            printAscii("Invalid package name: \"%s\"", name);
-        }
-        try {
-            validateClassName(name);
-            if (!isValidClassName)
-                throw new AssertionError("Invalid class name accepted: " + name);
-            printAscii("Valid class name: \"%s\"", name);
-        } catch (IllegalArgumentException e) {
-            if (isValidClassName)
-                throw new AssertionError("Valid class name rejected: " + name);
-            printAscii("Invalid class name: \"%s\"", name);
-        }
-    }
-    private static void printAscii(String format, Object... args) {
-        String message;
-        try {
-            final String ascii = "US-ASCII";
-            message = new String(String.format(null, format, args).getBytes(ascii), ascii);
-        } catch (java.io.UnsupportedEncodingException ex) {
-            throw new AssertionError(ex);
-        }
-        System.out.println(message);
-    }
-
-    /** Return external representation of name,
-     *  converting '.' to File.separatorChar.
-     */
-    private static String externalizeFileName(CharSequence name) {
-        return name.toString().replace('.', File.separatorChar);
-    }
-
-    private static String externalizeFileName(CharSequence n, JavaFileObject.Kind kind) {
-        return externalizeFileName(n) + kind.extension;
-    }
-
-    private static String baseName(String fileName) {
-        return fileName.substring(fileName.lastIndexOf(File.separatorChar) + 1);
-    }
-
-    /**
-     * Insert all files in subdirectory `subdirectory' of `directory' which end
-     * in one of the extensions in `extensions' into packageSym.
-     */
-    private void listDirectory(File directory,
-                               String subdirectory,
-                               Set<JavaFileObject.Kind> fileKinds,
-                               boolean recurse,
-                               ListBuffer<JavaFileObject> l) {
-        Archive archive = archives.get(directory);
-
-        boolean isFile = false;
-        if (CHECK_ZIP_TIMESTAMP) {
-            Boolean isf = isDirectory.get(directory);
-            if (isf == null) {
-                isFile = directory.isFile();
-                isDirectory.put(directory, isFile);
-            }
-            else {
-                isFile = directory.isFile();
-            }
-        }
-        else {
-            isFile = directory.isFile();
-        }
-
-        if (archive != null || isFile) {
-            if (archive == null) {
-                try {
-                    archive = openArchive(directory);
-                } catch (IOException ex) {
-                    log.error("error.reading.file",
-                       directory, ex.getLocalizedMessage());
-                    return;
-                }
-            }
-            if (subdirectory.length() != 0) {
-                if (!useZipFileIndex) {
-                    subdirectory = subdirectory.replace('\\', '/');
-                    if (!subdirectory.endsWith("/")) subdirectory = subdirectory + "/";
-                }
-                else {
-                    if (File.separatorChar == '/') {
-                        subdirectory = subdirectory.replace('\\', '/');
-                    }
-                    else {
-                        subdirectory = subdirectory.replace('/', '\\');
-                    }
-
-                    if (!subdirectory.endsWith(File.separator)) subdirectory = subdirectory + File.separator;
-                }
-            }
-
-            List<String> files = archive.getFiles(subdirectory);
-            if (files != null) {
-                for (String file; !files.isEmpty(); files = files.tail) {
-                    file = files.head;
-                    if (isValidFile(file, fileKinds)) {
-                        l.append(archive.getFileObject(subdirectory, file));
-                    }
-                }
-            }
-            if (recurse) {
-                for (String s: archive.getSubdirectories()) {
-                    if (s.startsWith(subdirectory) && !s.equals(subdirectory)) {
-                        // 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.
-                        listDirectory(directory, s, fileKinds, false, l);
-                    }
-                }
-            }
-        } else {
-            File d = subdirectory.length() != 0
-                ? new File(directory, subdirectory)
-                : directory;
-            if (!caseMapCheck(d, subdirectory))
-                return;
-
-            File[] files = d.listFiles();
-            if (files == null)
-                return;
-
-            for (File f: files) {
-                String fname = f.getName();
-                if (f.isDirectory()) {
-                    if (recurse && SourceVersion.isIdentifier(fname)) {
-                        listDirectory(directory,
-                                      subdirectory + File.separator + fname,
-                                      fileKinds,
-                                      recurse,
-                                      l);
-                    }
-                } else {
-                    if (isValidFile(fname, fileKinds)) {
-                        JavaFileObject fe =
-                        new RegularFileObject(fname, new File(d, fname));
-                        l.append(fe);
-                    }
-                }
-            }
-        }
-    }
-
-    private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
-        int lastDot = s.lastIndexOf(".");
-        String extn = (lastDot == -1 ? s : s.substring(lastDot));
-        JavaFileObject.Kind kind = getKind(extn);
-        return fileKinds.contains(kind);
-    }
-
-    private static final boolean fileSystemIsCaseSensitive =
-        File.separatorChar == '/';
-
-    /** Hack to make Windows case sensitive. Test whether given path
-     *  ends in a string of characters with the same case as given name.
-     *  Ignore file separators in both path and name.
-     */
-    private boolean caseMapCheck(File f, String name) {
-        if (fileSystemIsCaseSensitive) return true;
-        // Note that getCanonicalPath() returns the case-sensitive
-        // spelled file name.
-        String path;
-        try {
-            path = f.getCanonicalPath();
-        } catch (IOException ex) {
-            return false;
-        }
-        char[] pcs = path.toCharArray();
-        char[] ncs = name.toCharArray();
-        int i = pcs.length - 1;
-        int j = ncs.length - 1;
-        while (i >= 0 && j >= 0) {
-            while (i >= 0 && pcs[i] == File.separatorChar) i--;
-            while (j >= 0 && ncs[j] == File.separatorChar) j--;
-            if (i >= 0 && j >= 0) {
-                if (pcs[i] != ncs[j]) return false;
-                i--;
-                j--;
-            }
-        }
-        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(String name);
-
-        JavaFileObject getFileObject(String subdirectory, String file);
-
-        List<String> getFiles(String subdirectory);
-
-        Set<String> getSubdirectories();
-    }
-
-    public class ZipArchive implements Archive {
-        protected final Map<String,List<String>> map;
-        protected final ZipFile zdir;
-        public ZipArchive(ZipFile zdir) throws IOException {
-            this.zdir = zdir;
-            this.map = new HashMap<String,List<String>>();
-            for (Enumeration<? extends ZipEntry> e = zdir.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('/');
-            String dirname = 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(String name) {
-            int i = name.lastIndexOf('/');
-            String dirname = name.substring(0, i+1);
-            String basename = name.substring(i+1);
-            if (basename.length() == 0)
-                return false;
-            List<String> list = map.get(dirname);
-            return (list != null && list.contains(basename));
-        }
-
-        public List<String> getFiles(String subdirectory) {
-            return map.get(subdirectory);
-        }
-
-        public JavaFileObject getFileObject(String subdirectory, String file) {
-            ZipEntry ze = zdir.getEntry(subdirectory + file);
-            return new ZipFileObject(file, zdir, ze);
-        }
-
-        public Set<String> getSubdirectories() {
-            return map.keySet();
-        }
-
-        public void close() throws IOException {
-            zdir.close();
-        }
-    }
-
-    public class SymbolArchive extends ZipArchive {
-        final File origFile;
-        public SymbolArchive(File orig, ZipFile zdir) throws IOException {
-            super(zdir);
-            this.origFile = orig;
-        }
-
-        @Override
-        void addZipEntry(ZipEntry entry) {
-            // called from super constructor, may not refer to origFile.
-            String name = entry.getName();
-            if (!name.startsWith(symbolFilePrefix))
-                return;
-            name = name.substring(symbolFilePrefix.length());
-            int i = name.lastIndexOf('/');
-            String dirname = 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);
-        }
-
-        @Override
-        public JavaFileObject getFileObject(String subdirectory, String file) {
-            return super.getFileObject(symbolFilePrefix + subdirectory, file);
-        }
-    }
-
-    public class MissingArchive implements Archive {
-        final File zipFileName;
-        public MissingArchive(File name) {
-            zipFileName = name;
-        }
-        public boolean contains(String name) {
-              return false;
-        }
-
-        public void close() {
-        }
-
-        public JavaFileObject getFileObject(String subdirectory, String file) {
-            return null;
-        }
-
-        public List<String> getFiles(String subdirectory) {
-            return List.nil();
-        }
-
-        public Set<String> getSubdirectories() {
-            return Collections.emptySet();
-        }
-    }
-
-    /** A directory of zip files already opened.
-     */
-    Map<File, Archive> archives = new HashMap<File,Archive>();
-
-    /** Open a new zip file directory.
-     */
-    protected Archive openArchive(File zipFileName) throws IOException {
-        Archive archive = archives.get(zipFileName);
-        if (archive == null) {
-            File origZipFileName = zipFileName;
-            if (!ignoreSymbolFile && paths.isBootClassPathRtJar(zipFileName)) {
-                File file = zipFileName.getParentFile().getParentFile(); // ${java.home}
-                if (new File(file.getName()).equals(new File("jre")))
-                    file = file.getParentFile();
-                // file == ${jdk.home}
-                for (String name : symbolFileLocation)
-                    file = new File(file, name);
-                // file == ${jdk.home}/lib/ct.sym
-                if (file.exists())
-                    zipFileName = file;
-            }
-
-            try {
-
-                ZipFile zdir = null;
-
-                boolean usePreindexedCache = false;
-                String preindexCacheLocation = null;
-
-                if (!useZipFileIndex) {
-                    zdir = new ZipFile(zipFileName);
-                }
-                else {
-                    usePreindexedCache = options.get("usezipindex") != null;
-                    preindexCacheLocation = options.get("java.io.tmpdir");
-                    String optCacheLoc = options.get("cachezipindexdir");
-
-                    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 (origZipFileName == zipFileName) {
-                    if (!useZipFileIndex) {
-                        archive = new ZipArchive(zdir);
-                    } else {
-                        archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, 0,
-                                usePreindexedCache, preindexCacheLocation, options.get("writezipindexfiles") != null));
-                    }
-                }
-                else {
-                    if (!useZipFileIndex) {
-                        archive = new SymbolArchive(origZipFileName, zdir);
-                    }
-                    else {
-                        archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, symbolFilePrefixLength,
-                                usePreindexedCache, preindexCacheLocation, options.get("writezipindexfiles") != null));
-                    }
-                }
-            } catch (FileNotFoundException ex) {
-                archive = new MissingArchive(zipFileName);
-            } catch (IOException ex) {
-                log.error("error.reading.file", zipFileName, ex.getLocalizedMessage());
-                archive = new MissingArchive(zipFileName);
-            }
-
-            archives.put(origZipFileName, archive);
-        }
-        return archive;
-    }
-
-    /** Flush any output resources.
-     */
-    public void flush() {
-        contentCache.clear();
-    }
-
-    /**
-     * Close the JavaFileManager, releasing resources.
-     */
-    public void close() {
-        for (Iterator<Archive> i = archives.values().iterator(); i.hasNext(); ) {
-            Archive a = i.next();
-            i.remove();
-            try {
-                a.close();
-            } catch (IOException e) {
-            }
-        }
-    }
-
-    private Map<JavaFileObject, SoftReference<CharBuffer>> contentCache = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
-
-    private String defaultEncodingName;
-    private String getDefaultEncodingName() {
-        if (defaultEncodingName == null) {
-            defaultEncodingName =
-                new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
-        }
-        return defaultEncodingName;
-    }
-
-    protected String getEncodingName() {
-        String encName = options.get(OptionName.ENCODING);
-        if (encName == null)
-            return getDefaultEncodingName();
-        else
-            return encName;
-    }
-
-    protected Source getSource() {
-        String sourceName = options.get(OptionName.SOURCE);
-        Source source = null;
-        if (sourceName != null)
-            source = Source.lookup(sourceName);
-        return (source != null ? source : Source.DEFAULT);
-    }
-
-    /**
-     * Make a byte buffer from an input stream.
-     */
-    private ByteBuffer makeByteBuffer(InputStream in)
-        throws IOException {
-        int limit = in.available();
-        if (mmappedIO && in instanceof FileInputStream) {
-            // Experimental memory mapped I/O
-            FileInputStream fin = (FileInputStream)in;
-            return fin.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, limit);
-        }
-        if (limit < 1024) limit = 1024;
-        ByteBuffer result = byteBufferCache.get(limit);
-        int position = 0;
-        while (in.available() != 0) {
-            if (position >= limit)
-                // expand buffer
-                result = ByteBuffer.
-                    allocate(limit <<= 1).
-                    put((ByteBuffer)result.flip());
-            int count = in.read(result.array(),
-                position,
-                limit - position);
-            if (count < 0) break;
-            result.position(position += count);
-        }
-        return (ByteBuffer)result.flip();
-    }
-
-    /**
-     * A single-element cache of direct byte buffers.
-     */
-    private static class ByteBufferCache {
-        private ByteBuffer cached;
-        ByteBuffer get(int capacity) {
-            if (capacity < 20480) capacity = 20480;
-            ByteBuffer result =
-                (cached != null && cached.capacity() >= capacity)
-                ? (ByteBuffer)cached.clear()
-                : ByteBuffer.allocate(capacity + capacity>>1);
-            cached = null;
-            return result;
-        }
-        void put(ByteBuffer x) {
-            cached = x;
-        }
-    }
-    private final ByteBufferCache byteBufferCache;
-
-    private CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
-        Charset charset = (this.charset == null)
-            ? Charset.forName(encodingName)
-            : this.charset;
-        CharsetDecoder decoder = charset.newDecoder();
-
-        CodingErrorAction action;
-        if (ignoreEncodingErrors)
-            action = CodingErrorAction.REPLACE;
-        else
-            action = CodingErrorAction.REPORT;
-
-        return decoder
-            .onMalformedInput(action)
-            .onUnmappableCharacter(action);
-    }
-
-    /**
-     * Decode a ByteBuffer into a CharBuffer.
-     */
-    private CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
-        String encodingName = getEncodingName();
-        CharsetDecoder decoder;
-        try {
-            decoder = getDecoder(encodingName, ignoreEncodingErrors);
-        } catch (IllegalCharsetNameException e) {
-            log.error("unsupported.encoding", encodingName);
-            return (CharBuffer)CharBuffer.allocate(1).flip();
-        } catch (UnsupportedCharsetException e) {
-            log.error("unsupported.encoding", encodingName);
-            return (CharBuffer)CharBuffer.allocate(1).flip();
-        }
-
-        // slightly overestimate the buffer size to avoid reallocation.
-        float factor =
-            decoder.averageCharsPerByte() * 0.8f +
-            decoder.maxCharsPerByte() * 0.2f;
-        CharBuffer dest = CharBuffer.
-            allocate(10 + (int)(inbuf.remaining()*factor));
-
-        while (true) {
-            CoderResult result = decoder.decode(inbuf, dest, true);
-            dest.flip();
-
-            if (result.isUnderflow()) { // done reading
-                // make sure there is at least one extra character
-                if (dest.limit() == dest.capacity()) {
-                    dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
-                    dest.flip();
-                }
-                return dest;
-            } else if (result.isOverflow()) { // buffer too small; expand
-                int newCapacity =
-                    10 + dest.capacity() +
-                    (int)(inbuf.remaining()*decoder.maxCharsPerByte());
-                dest = CharBuffer.allocate(newCapacity).put(dest);
-            } else if (result.isMalformed() || result.isUnmappable()) {
-                // bad character in input
-
-                // report coding error (warn only pre 1.5)
-                if (!getSource().allowEncodingErrors()) {
-                    log.error(new SimpleDiagnosticPosition(dest.limit()),
-                              "illegal.char.for.encoding",
-                              charset == null ? encodingName : charset.name());
-                } else {
-                    log.warning(new SimpleDiagnosticPosition(dest.limit()),
-                                "illegal.char.for.encoding",
-                                charset == null ? encodingName : charset.name());
-                }
-
-                // skip past the coding error
-                inbuf.position(inbuf.position() + result.length());
-
-                // undo the flip() to prepare the output buffer
-                // for more translation
-                dest.position(dest.limit());
-                dest.limit(dest.capacity());
-                dest.put((char)0xfffd); // backward compatible
-            } else {
-                throw new AssertionError(result);
-            }
-        }
-        // unreached
-    }
-
-    public ClassLoader getClassLoader(Location location) {
-        nullCheck(location);
-        Iterable<? extends File> path = getLocation(location);
-        if (path == null)
-            return null;
-        ListBuffer<URL> lb = new ListBuffer<URL>();
-        for (File f: path) {
-            try {
-                lb.append(f.toURI().toURL());
-            } catch (MalformedURLException e) {
-                throw new AssertionError(e);
-            }
-        }
-        return new URLClassLoader(lb.toArray(new URL[lb.size()]),
-            getClass().getClassLoader());
-    }
-
-    public Iterable<JavaFileObject> list(Location location,
-                                         String packageName,
-                                         Set<JavaFileObject.Kind> kinds,
-                                         boolean recurse)
-        throws IOException
-    {
-        // validatePackageName(packageName);
-        nullCheck(packageName);
-        nullCheck(kinds);
-
-        Iterable<? extends File> path = getLocation(location);
-        if (path == null)
-            return List.nil();
-        String subdirectory = externalizeFileName(packageName);
-        ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
-
-        for (File directory : path)
-            listDirectory(directory, subdirectory, kinds, recurse, results);
-
-        return results.toList();
-    }
-
-    public String inferBinaryName(Location location, JavaFileObject file) {
-        file.getClass(); // null check
-        location.getClass(); // null check
-        // Need to match the path semantics of list(location, ...)
-        Iterable<? extends File> path = getLocation(location);
-        if (path == null) {
-            //System.err.println("Path for " + location + " is null");
-            return null;
-        }
-        //System.err.println("Path for " + location + " is " + path);
-
-        if (file instanceof RegularFileObject) {
-            RegularFileObject r = (RegularFileObject) file;
-            String rPath = r.getPath();
-            //System.err.println("RegularFileObject " + file + " " +r.getPath());
-            for (File dir: path) {
-                //System.err.println("dir: " + dir);
-                String dPath = dir.getPath();
-                if (!dPath.endsWith(File.separator))
-                    dPath += File.separator;
-                if (rPath.regionMatches(true, 0, dPath, 0, dPath.length())
-                    && new File(rPath.substring(0, dPath.length())).equals(new File(dPath))) {
-                    String relativeName = rPath.substring(dPath.length());
-                    return removeExtension(relativeName).replace(File.separatorChar, '.');
-                }
-            }
-        } else if (file instanceof ZipFileObject) {
-            ZipFileObject z = (ZipFileObject) file;
-            String entryName = z.getZipEntryName();
-            if (entryName.startsWith(symbolFilePrefix))
-                entryName = entryName.substring(symbolFilePrefix.length());
-            return removeExtension(entryName).replace('/', '.');
-        } else if (file instanceof ZipFileIndexFileObject) {
-            ZipFileIndexFileObject z = (ZipFileIndexFileObject) file;
-            String entryName = z.getZipEntryName();
-            if (entryName.startsWith(symbolFilePrefix))
-                entryName = entryName.substring(symbolFilePrefix.length());
-            return removeExtension(entryName).replace(File.separatorChar, '.');
-        } else
-            throw new IllegalArgumentException(file.getClass().getName());
-        // System.err.println("inferBinaryName failed for " + file);
-        return null;
-    }
-    // where
-        private static String removeExtension(String fileName) {
-            int lastDot = fileName.lastIndexOf(".");
-            return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
-        }
-
-    public boolean isSameFile(FileObject a, FileObject b) {
-        nullCheck(a);
-        nullCheck(b);
-        if (!(a instanceof BaseFileObject))
-            throw new IllegalArgumentException("Not supported: " + a);
-        if (!(b instanceof BaseFileObject))
-            throw new IllegalArgumentException("Not supported: " + b);
-        return a.equals(b);
-    }
-
-    public boolean handleOption(String current, Iterator<String> remaining) {
-        for (JavacOption o: javacFileManagerOptions) {
-            if (o.matches(current))  {
-                if (o.hasArg()) {
-                    if (remaining.hasNext()) {
-                        if (!o.process(options, current, remaining.next()))
-                            return true;
-                    }
-                } else {
-                    if (!o.process(options, current))
-                        return true;
-                }
-                // operand missing, or process returned false
-                throw new IllegalArgumentException(current);
-            }
-        }
-
-        return false;
-    }
-    // where
-        private static JavacOption[] javacFileManagerOptions =
-            RecognizedOptions.getJavacFileManagerOptions(
-            new RecognizedOptions.GrumpyHelper());
-
-    public int isSupportedOption(String option) {
-        for (JavacOption o : javacFileManagerOptions) {
-            if (o.matches(option))
-                return o.hasArg() ? 1 : 0;
-        }
-        return -1;
-    }
-
-    public boolean hasLocation(Location location) {
-        return getLocation(location) != null;
-    }
-
-    public JavaFileObject getJavaFileForInput(Location location,
-                                              String className,
-                                              JavaFileObject.Kind kind)
-        throws IOException
-    {
-        nullCheck(location);
-        // validateClassName(className);
-        nullCheck(className);
-        nullCheck(kind);
-        if (!sourceOrClass.contains(kind))
-            throw new IllegalArgumentException("Invalid kind " + kind);
-        return getFileForInput(location, externalizeFileName(className, kind));
-    }
-
-    public FileObject getFileForInput(Location location,
-                                      String packageName,
-                                      String relativeName)
-        throws IOException
-    {
-        nullCheck(location);
-        // validatePackageName(packageName);
-        nullCheck(packageName);
-        if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
-            throw new IllegalArgumentException("Invalid relative name: " + relativeName);
-        String name = packageName.length() == 0
-            ? relativeName
-            : new File(externalizeFileName(packageName), relativeName).getPath();
-        return getFileForInput(location, name);
-    }
-
-    private JavaFileObject getFileForInput(Location location, String name) throws IOException {
-        Iterable<? extends File> path = getLocation(location);
-        if (path == null)
-            return null;
-
-        for (File dir: path) {
-            if (dir.isDirectory()) {
-                File f = new File(dir, name.replace('/', File.separatorChar));
-                if (f.exists())
-                    return new RegularFileObject(f);
-            } else {
-                Archive a = openArchive(dir);
-                if (a.contains(name)) {
-                    int i = name.lastIndexOf('/');
-                    String dirname = name.substring(0, i+1);
-                    String basename = name.substring(i+1);
-                    return a.getFileObject(dirname, basename);
-                }
-
-            }
-        }
-        return null;
-
-    }
-
-    public JavaFileObject getJavaFileForOutput(Location location,
-                                               String className,
-                                               JavaFileObject.Kind kind,
-                                               FileObject sibling)
-        throws IOException
-    {
-        nullCheck(location);
-        // validateClassName(className);
-        nullCheck(className);
-        nullCheck(kind);
-        if (!sourceOrClass.contains(kind))
-            throw new IllegalArgumentException("Invalid kind " + kind);
-        return getFileForOutput(location, externalizeFileName(className, kind), sibling);
-    }
-
-    public FileObject getFileForOutput(Location location,
-                                       String packageName,
-                                       String relativeName,
-                                       FileObject sibling)
-        throws IOException
-    {
-        nullCheck(location);
-        // validatePackageName(packageName);
-        nullCheck(packageName);
-        if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
-            throw new IllegalArgumentException("relativeName is invalid");
-        String name = packageName.length() == 0
-            ? relativeName
-            : new File(externalizeFileName(packageName), relativeName).getPath();
-        return getFileForOutput(location, name, sibling);
-    }
-
-    private JavaFileObject getFileForOutput(Location location,
-                                            String fileName,
-                                            FileObject sibling)
-        throws IOException
-    {
-        File dir;
-        if (location == CLASS_OUTPUT) {
-            if (getClassOutDir() != null) {
-                dir = getClassOutDir();
-            } else {
-                File siblingDir = null;
-                if (sibling != null && sibling instanceof RegularFileObject) {
-                    siblingDir = ((RegularFileObject)sibling).f.getParentFile();
-                }
-                return new RegularFileObject(new File(siblingDir, baseName(fileName)));
-            }
-        } else if (location == SOURCE_OUTPUT) {
-            dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
-        } else {
-            Iterable<? extends File> path = paths.getPathForLocation(location);
-            dir = null;
-            for (File f: path) {
-                dir = f;
-                break;
-            }
-        }
-
-        File file = (dir == null ? new File(fileName) : new File(dir, fileName));
-        return new RegularFileObject(file);
-
-    }
-
-    public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(
-        Iterable<? extends File> files)
-    {
-        ArrayList<RegularFileObject> result;
-        if (files instanceof Collection)
-            result = new ArrayList<RegularFileObject>(((Collection)files).size());
-        else
-            result = new ArrayList<RegularFileObject>();
-        for (File f: files)
-            result.add(new RegularFileObject(nullCheck(f)));
-        return result;
-    }
-
-    public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
-        return getJavaFileObjectsFromFiles(Arrays.asList(nullCheck(files)));
-    }
-
-    public void setLocation(Location location,
-                            Iterable<? extends File> path)
-        throws IOException
-    {
-        nullCheck(location);
-        paths.lazy();
-
-        final File dir = location.isOutputLocation() ? getOutputDirectory(path) : null;
-
-        if (location == CLASS_OUTPUT)
-            classOutDir = getOutputLocation(dir, D);
-        else if (location == SOURCE_OUTPUT)
-            sourceOutDir = getOutputLocation(dir, S);
-        else
-            paths.setPathForLocation(location, path);
-    }
-    // where
-        private File getOutputDirectory(Iterable<? extends File> path) throws IOException {
-            if (path == null)
-                return null;
-            Iterator<? extends File> pathIter = path.iterator();
-            if (!pathIter.hasNext())
-                throw new IllegalArgumentException("empty path for directory");
-            File dir = pathIter.next();
-            if (pathIter.hasNext())
-                throw new IllegalArgumentException("path too long for directory");
-            if (!dir.exists())
-                throw new FileNotFoundException(dir + ": does not exist");
-            else if (!dir.isDirectory())
-                throw new IOException(dir + ": not a directory");
-            return dir;
-        }
-
-    private File getOutputLocation(File dir, OptionName defaultOptionName) {
-        if (dir != null)
-            return dir;
-        String arg = options.get(defaultOptionName);
-        if (arg == null)
-            return null;
-        return new File(arg);
-    }
-
-    public Iterable<? extends File> getLocation(Location location) {
-        nullCheck(location);
-        paths.lazy();
-        if (location == CLASS_OUTPUT) {
-            return (getClassOutDir() == null ? null : List.of(getClassOutDir()));
-        } else if (location == SOURCE_OUTPUT) {
-            return (getSourceOutDir() == null ? null : List.of(getSourceOutDir()));
-        } else
-            return paths.getPathForLocation(location);
-    }
-
-    private File getClassOutDir() {
-        if (classOutDir == uninited)
-            classOutDir = getOutputLocation(null, D);
-        return classOutDir;
-    }
-
-    private File getSourceOutDir() {
-        if (sourceOutDir == uninited)
-            sourceOutDir = getOutputLocation(null, S);
-        return sourceOutDir;
-    }
-
-    /**
-     * Enforces the specification of a "relative" URI as used in
-     * {@linkplain #getFileForInput(Location,String,URI)
-     * getFileForInput}.  This method must follow the rules defined in
-     * that method, do not make any changes without consulting the
-     * specification.
-     */
-    protected static boolean isRelativeUri(URI uri) {
-        if (uri.isAbsolute())
-            return false;
-        String path = uri.normalize().getPath();
-        if (path.length() == 0 /* isEmpty() is mustang API */)
-            return false;
-        char first = path.charAt(0);
-        return first != '.' && first != '/';
-    }
-
-    /**
-     * Converts a relative file name to a relative URI.  This is
-     * different from File.toURI as this method does not canonicalize
-     * the file before creating the URI.  Furthermore, no schema is
-     * used.
-     * @param file a relative file name
-     * @return a relative URI
-     * @throws IllegalArgumentException if the file name is not
-     * relative according to the definition given in {@link
-     * javax.tools.JavaFileManager#getFileForInput}
-     */
-    public static String getRelativeName(File file) {
-        if (!file.isAbsolute()) {
-            String result = file.getPath().replace(File.separatorChar, '/');
-            if (JavacFileManager.isRelativeUri(URI.create(result))) // FIXME 6419701
-                return result;
-        }
-        throw new IllegalArgumentException("Invalid relative path: " + file);
-    }
-
-    @SuppressWarnings("deprecation") // bug 6410637
-    protected static String getJavacFileName(FileObject file) {
-        if (file instanceof BaseFileObject)
-            return ((BaseFileObject)file).getPath();
-        URI uri = file.toUri();
-        String scheme = uri.getScheme();
-        if (scheme == null || scheme.equals("file") || scheme.equals("jar"))
-            return uri.getPath();
-        else
-            return uri.toString();
-    }
-
-    @SuppressWarnings("deprecation") // bug 6410637
-    protected static String getJavacBaseFileName(FileObject file) {
-        if (file instanceof BaseFileObject)
-            return ((BaseFileObject)file).getName();
-        URI uri = file.toUri();
-        String scheme = uri.getScheme();
-        if (scheme == null || scheme.equals("file") || scheme.equals("jar")) {
-            String path = uri.getPath();
-            if (path == null)
-                return null;
-            if (scheme != null && scheme.equals("jar"))
-                path = path.substring(path.lastIndexOf('!') + 1);
-            return path.substring(path.lastIndexOf('/') + 1);
-        } else {
-            return uri.toString();
-        }
-    }
-
-    private static <T> T nullCheck(T o) {
-        o.getClass(); // null check
-        return o;
-    }
-
-    private static <T> Iterable<T> nullCheck(Iterable<T> it) {
-        for (T t : it)
-            t.getClass(); // null check
-        return it;
-    }
-
-    /**
-     * A subclass of JavaFileObject representing regular files.
-     */
-    private class RegularFileObject extends BaseFileObject {
-        /** Have the parent directories been created?
-         */
-        private boolean hasParents=false;
-
-        /** The file's name.
-         */
-        private String name;
-
-        /** The underlying file.
-         */
-        final File f;
-
-        public RegularFileObject(File f) {
-            this(f.getName(), f);
-        }
-
-        public RegularFileObject(String name, File f) {
-            if (f.isDirectory())
-                throw new IllegalArgumentException("directories not supported");
-            this.name = name;
-            this.f = f;
-        }
-
-        public InputStream openInputStream() throws IOException {
-            return new FileInputStream(f);
-        }
-
-        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
-            return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
-        }
-
-        public OutputStream openOutputStream() throws IOException {
-            ensureParentDirectoriesExist();
-            return new FileOutputStream(f);
-        }
-
-        public Writer openWriter() throws IOException {
-            ensureParentDirectoriesExist();
-            return new OutputStreamWriter(new FileOutputStream(f), getEncodingName());
-        }
-
-        private void ensureParentDirectoriesExist() throws IOException {
-            if (!hasParents) {
-                File parent = f.getParentFile();
-                if (parent != null && !parent.exists()) {
-                    if (!parent.mkdirs()) {
-                        // if the mkdirs failed, it may be because another process concurrently
-                        // created the directory, so check if the directory got created
-                        // anyway before throwing an exception
-                        if (!parent.exists() || !parent.isDirectory())
-                            throw new IOException("could not create parent directories");
-                    }
-                }
-                hasParents = true;
-            }
-        }
-
-        /** @deprecated see bug 6410637 */
-        @Deprecated
-        public String getName() {
-            return name;
-        }
-
-        public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) {
-            cn.getClass(); // null check
-            if (kind == Kind.OTHER && getKind() != kind)
-                return false;
-            String n = cn + kind.extension;
-            if (name.equals(n))
-                return true;
-            if (name.equalsIgnoreCase(n)) {
-                try {
-                    // allow for Windows
-                    return (f.getCanonicalFile().getName().equals(n));
-                } catch (IOException e) {
-                }
-            }
-            return false;
-        }
-
-        /** @deprecated see bug 6410637 */
-        @Deprecated
-        public String getPath() {
-            return f.getPath();
-        }
-
-        public long getLastModified() {
-            return f.lastModified();
-        }
-
-        public boolean delete() {
-            return f.delete();
-        }
-
-        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
-            SoftReference<CharBuffer> r = contentCache.get(this);
-            CharBuffer cb = (r == null ? null : r.get());
-            if (cb == null) {
-                InputStream in = new FileInputStream(f);
-                try {
-                    ByteBuffer bb = makeByteBuffer(in);
-                    JavaFileObject prev = log.useSource(this);
-                    try {
-                        cb = decode(bb, ignoreEncodingErrors);
-                    } finally {
-                        log.useSource(prev);
-                    }
-                    byteBufferCache.put(bb); // save for next time
-                    if (!ignoreEncodingErrors)
-                        contentCache.put(this, new SoftReference<CharBuffer>(cb));
-                } finally {
-                    in.close();
-                }
-            }
-            return cb;
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof RegularFileObject))
-                return false;
-            RegularFileObject o = (RegularFileObject) other;
-            try {
-                return f.equals(o.f)
-                    || f.getCanonicalFile().equals(o.f.getCanonicalFile());
-            } catch (IOException e) {
-                return false;
-            }
-        }
-
-        @Override
-        public int hashCode() {
-            return f.hashCode();
-        }
-
-        public URI toUri() {
-            try {
-                // Do no use File.toURI to avoid file system access
-                String path = f.getAbsolutePath().replace(File.separatorChar, '/');
-                return new URI("file://" + path).normalize();
-            } catch (URISyntaxException ex) {
-                return f.toURI();
-            }
-        }
-
-    }
-
-    /**
-     * A subclass of JavaFileObject representing zip entries.
-     */
-    public class ZipFileObject extends BaseFileObject {
-
-        /** The entry's name.
-         */
-        private String name;
-
-        /** The zipfile containing the entry.
-         */
-        ZipFile zdir;
-
-        /** The underlying zip entry object.
-         */
-        ZipEntry entry;
-
-        public ZipFileObject(String name, ZipFile zdir, ZipEntry entry) {
-            this.name = name;
-            this.zdir = zdir;
-            this.entry = entry;
-        }
-
-        public InputStream openInputStream() throws IOException {
-            return zdir.getInputStream(entry);
-        }
-
-        public OutputStream openOutputStream() throws IOException {
-            throw new UnsupportedOperationException();
-        }
-
-        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
-            return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
-        }
-
-        public Writer openWriter() throws IOException {
-            throw new UnsupportedOperationException();
-        }
-
-        /** @deprecated see bug 6410637 */
-        @Deprecated
-        public String getName() {
-            return name;
-        }
-
-        public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
-            cn.getClass(); // null check
-            if (k == Kind.OTHER && getKind() != k)
-                return false;
-            return name.equals(cn + k.extension);
-        }
-
-        /** @deprecated see bug 6410637 */
-        @Deprecated
-        public String getPath() {
-            return zdir.getName() + "(" + entry + ")";
-        }
-
-        public long getLastModified() {
-            return entry.getTime();
-        }
-
-        public boolean delete() {
-            throw new UnsupportedOperationException();
-        }
-
-        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
-            SoftReference<CharBuffer> r = contentCache.get(this);
-            CharBuffer cb = (r == null ? null : r.get());
-            if (cb == null) {
-                InputStream in = zdir.getInputStream(entry);
-                try {
-                    ByteBuffer bb = makeByteBuffer(in);
-                    JavaFileObject prev = log.useSource(this);
-                    try {
-                        cb = decode(bb, ignoreEncodingErrors);
-                    } finally {
-                        log.useSource(prev);
-                    }
-                    byteBufferCache.put(bb); // save for next time
-                    if (!ignoreEncodingErrors)
-                        contentCache.put(this, new SoftReference<CharBuffer>(cb));
-                } finally {
-                    in.close();
-                }
-            }
-            return cb;
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof ZipFileObject))
-                return false;
-            ZipFileObject o = (ZipFileObject) other;
-            return zdir.equals(o.zdir) || name.equals(o.name);
-        }
-
-        @Override
-        public int hashCode() {
-            return zdir.hashCode() + name.hashCode();
-        }
-
-        public String getZipName() {
-            return zdir.getName();
-        }
-
-        public String getZipEntryName() {
-            return entry.getName();
-        }
-
-        public URI toUri() {
-            String zipName = new File(getZipName()).toURI().normalize().getPath();
-            String entryName = getZipEntryName();
-            return URI.create("jar:" + zipName + "!" + entryName);
-        }
-
-    }
-
-    /**
-     * A subclass of JavaFileObject representing zip entries using the com.sun.tools.javac.zip.ZipFileIndex implementation.
-     */
-    public class ZipFileIndexFileObject extends BaseFileObject {
-
-            /** The entry's name.
-         */
-        private String name;
-
-        /** The zipfile containing the entry.
-         */
-        ZipFileIndex zfIndex;
-
-        /** The underlying zip entry object.
-         */
-        ZipFileIndexEntry entry;
-
-        /** The InputStream for this zip entry (file.)
-         */
-        InputStream inputStream = null;
-
-        /** The name of the zip file where this entry resides.
-         */
-        String zipName;
-
-        JavacFileManager defFileManager = null;
-
-        public ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndexEntry entry, String zipFileName) {
-            super();
-            this.name = entry.getFileName();
-            this.zfIndex = zfIndex;
-            this.entry = entry;
-            this.zipName = zipFileName;
-            defFileManager = fileManager;
-        }
-
-        public InputStream openInputStream() throws IOException {
-
-            if (inputStream == null) {
-                inputStream = new ByteArrayInputStream(read());
-            }
-            return inputStream;
-        }
-
-        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
-            return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
-        }
-
-        public OutputStream openOutputStream() throws IOException {
-            throw new UnsupportedOperationException();
-        }
-
-        public Writer openWriter() throws IOException {
-            throw new UnsupportedOperationException();
-        }
-
-        /** @deprecated see bug 6410637 */
-        @Deprecated
-        public String getName() {
-            return name;
-        }
-
-        public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
-            cn.getClass(); // null check
-            if (k == Kind.OTHER && getKind() != k)
-                return false;
-            return name.equals(cn + k.extension);
-        }
-
-        /** @deprecated see bug 6410637 */
-        @Deprecated
-        public String getPath() {
-            return zipName + "(" + entry.getName() + ")";
-        }
-
-        public long getLastModified() {
-            return entry.getLastModified();
-        }
-
-        public boolean delete() {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof ZipFileIndexFileObject))
-                return false;
-            ZipFileIndexFileObject o = (ZipFileIndexFileObject) other;
-            return entry.equals(o.entry);
-        }
-
-        @Override
-        public int hashCode() {
-            return zipName.hashCode() + (name.hashCode() << 10);
-        }
-
-        public String getZipName() {
-            return zipName;
-        }
-
-        public String getZipEntryName() {
-            return entry.getName();
-        }
-
-        public URI toUri() {
-            String zipName = new File(getZipName()).toURI().normalize().getPath();
-            String entryName = getZipEntryName();
-            if (File.separatorChar != '/') {
-                entryName = entryName.replace(File.separatorChar, '/');
-            }
-            return URI.create("jar:" + zipName + "!" + entryName);
-        }
-
-        private byte[] read() throws IOException {
-            if (entry == null) {
-                entry = zfIndex.getZipIndexEntry(name);
-                if (entry == null)
-                  throw new FileNotFoundException();
-            }
-            return zfIndex.read(entry);
-        }
-
-        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
-            SoftReference<CharBuffer> r = defFileManager.contentCache.get(this);
-            CharBuffer cb = (r == null ? null : r.get());
-            if (cb == null) {
-                InputStream in = new ByteArrayInputStream(zfIndex.read(entry));
-                try {
-                    ByteBuffer bb = makeByteBuffer(in);
-                    JavaFileObject prev = log.useSource(this);
-                    try {
-                        cb = decode(bb, ignoreEncodingErrors);
-                    } finally {
-                        log.useSource(prev);
-                    }
-                    byteBufferCache.put(bb); // save for next time
-                    if (!ignoreEncodingErrors)
-                        defFileManager.contentCache.put(this, new SoftReference<CharBuffer>(cb));
-                } finally {
-                    in.close();
-                }
-            }
-            return cb;
-        }
-    }
-
-    public class ZipFileIndexArchive implements Archive {
-        private final ZipFileIndex zfIndex;
-        private JavacFileManager fileManager;
-
-        public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException {
-            this.fileManager = fileManager;
-            this.zfIndex = zdir;
-        }
-
-        public boolean contains(String name) {
-            return zfIndex.contains(name);
-        }
-
-        public com.sun.tools.javac.util.List<String> getFiles(String subdirectory) {
-              return zfIndex.getFiles(((subdirectory.endsWith("/") || subdirectory.endsWith("\\"))? subdirectory.substring(0, subdirectory.length() - 1) : subdirectory));
-        }
-
-        public JavaFileObject getFileObject(String subdirectory, String file) {
-            String fullZipFileName = subdirectory + file;
-            ZipFileIndexEntry entry = zfIndex.getZipIndexEntry(fullZipFileName);
-            JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile().getPath());
-            return ret;
-        }
-
-        public Set<String> getSubdirectories() {
-            return zfIndex.getAllDirectories();
-        }
-
-        public void close() throws IOException {
-            zfIndex.close();
-        }
-    }
-}
--- a/src/share/classes/com/sun/tools/javac/util/Log.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/util/Log.java	Mon Jun 16 22:23:33 2008 -0700
@@ -33,11 +33,14 @@
 import java.util.Set;
 import javax.tools.DiagnosticListener;
 import javax.tools.JavaFileObject;
+
 import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
+
 import static com.sun.tools.javac.util.LayoutCharacters.*;
 
 /** A class for error logs. Reports errors and warnings, and
--- a/src/share/classes/com/sun/tools/javac/util/Old199.java	Thu Jun 12 13:19:16 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright 2006 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package com.sun.tools.javac.util;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import javax.tools.*;
-
-import static javax.tools.StandardLocation.SOURCE_PATH;
-
-/**
- * Provides an easy migration to JSR 199 v3.3.  The class is
- * deprecated as we should remove it as soon as possible.
- *
- * <p><b>This is NOT part of any API supported by Sun Microsystems.
- * 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></p>
- *
- * @author Peter von der Ah\u00e9
- */
-@Deprecated
-public class Old199 {
-
-    private Old199() {}
-
-    public static String getPath(FileObject jfo) {
-        return JavacFileManager.getJavacFileName(jfo);
-    }
-
-    public static String getName(FileObject jfo) {
-        return JavacFileManager.getJavacBaseFileName(jfo);
-    }
-
-}
--- a/src/share/classes/com/sun/tools/javac/util/Paths.java	Thu Jun 12 13:19:16 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,572 +0,0 @@
-/*
- * Copyright 2003-2006 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package com.sun.tools.javac.util;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-import java.util.jar.Attributes;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Iterator;
-import java.util.StringTokenizer;
-import java.util.zip.ZipFile;
-import com.sun.tools.javac.code.Lint;
-import java.util.ArrayList;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-import javax.tools.JavaFileManager.Location;
-
-import static com.sun.tools.javac.main.OptionName.*;
-import static javax.tools.StandardLocation.*;
-
-/** This class converts command line arguments, environment variables
- *  and system properties (in File.pathSeparator-separated String form)
- *  into a boot class path, user class path, and source path (in
- *  Collection<String> form).
- *
- *  <p><b>This is NOT part of any API supported by Sun Microsystems.  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 Paths {
-
-    /** The context key for the todo list */
-    protected static final Context.Key<Paths> pathsKey =
-        new Context.Key<Paths>();
-
-    /** Get the Paths instance for this context.
-     *  @param context the context
-     *  @return the Paths instance for this context
-     */
-    public static Paths instance(Context context) {
-        Paths instance = context.get(pathsKey);
-        if (instance == null)
-            instance = new Paths(context);
-        return instance;
-    }
-
-    /** The log to use for warning output */
-    private Log log;
-
-    /** Collection of command-line options */
-    private Options options;
-
-    /** Handler for -Xlint options */
-    private Lint lint;
-
-    private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
-    private static Map<File, PathEntry> pathExistanceCache = new ConcurrentHashMap<File, PathEntry>();
-    private static Map<File, java.util.List<File>> manifestEntries = new ConcurrentHashMap<File, java.util.List<File>>();
-    private static Map<File, Boolean> isDirectory = new ConcurrentHashMap<File, Boolean>();
-    private static Lock lock = new ReentrantLock();
-
-    public static void clearPathExistanceCache() {
-            pathExistanceCache.clear();
-    }
-
-    static class PathEntry {
-        boolean exists = false;
-        boolean isFile = false;
-        File cannonicalPath = null;
-    }
-
-    protected Paths(Context context) {
-        context.put(pathsKey, this);
-        pathsForLocation = new HashMap<Location,Path>(16);
-        setContext(context);
-    }
-
-    void setContext(Context context) {
-        log = Log.instance(context);
-        options = Options.instance(context);
-        lint = Lint.instance(context);
-    }
-
-    /** Whether to warn about non-existent path elements */
-    private boolean warn;
-
-    private Map<Location, Path> pathsForLocation;
-
-    private boolean inited = false; // TODO? caching bad?
-
-    /**
-     * rt.jar as found on the default bootclass path.  If the user specified a
-     * bootclasspath, null is used.
-     */
-    private File bootClassPathRtJar = null;
-
-    Path getPathForLocation(Location location) {
-        Path path = pathsForLocation.get(location);
-        if (path == null)
-            setPathForLocation(location, null);
-        return pathsForLocation.get(location);
-    }
-
-    void setPathForLocation(Location location, Iterable<? extends File> path) {
-        // TODO? if (inited) throw new IllegalStateException
-        // TODO: otherwise reset sourceSearchPath, classSearchPath as needed
-        Path p;
-        if (path == null) {
-            if (location == CLASS_PATH)
-                p = computeUserClassPath();
-            else if (location == PLATFORM_CLASS_PATH)
-                p = computeBootClassPath();
-            else if (location == ANNOTATION_PROCESSOR_PATH)
-                p = computeAnnotationProcessorPath();
-            else if (location == SOURCE_PATH)
-                p = computeSourcePath();
-            else
-                // no defaults for other paths
-                p = null;
-        } else {
-            p = new Path();
-            for (File f: path)
-                p.addFile(f, warn); // TODO: is use of warn appropriate?
-        }
-        pathsForLocation.put(location, p);
-    }
-
-    protected void lazy() {
-        if (!inited) {
-            warn = lint.isEnabled(Lint.LintCategory.PATH);
-
-            pathsForLocation.put(PLATFORM_CLASS_PATH, computeBootClassPath());
-            pathsForLocation.put(CLASS_PATH, computeUserClassPath());
-            pathsForLocation.put(SOURCE_PATH, computeSourcePath());
-
-            inited = true;
-        }
-    }
-
-    public Collection<File> bootClassPath() {
-        lazy();
-        return Collections.unmodifiableCollection(getPathForLocation(PLATFORM_CLASS_PATH));
-    }
-    public Collection<File> userClassPath() {
-        lazy();
-        return Collections.unmodifiableCollection(getPathForLocation(CLASS_PATH));
-    }
-    public Collection<File> sourcePath() {
-        lazy();
-        Path p = getPathForLocation(SOURCE_PATH);
-        return p == null || p.size() == 0
-            ? null
-            : Collections.unmodifiableCollection(p);
-    }
-
-    boolean isBootClassPathRtJar(File file) {
-        return file.equals(bootClassPathRtJar);
-    }
-
-    private static class PathIterator implements Iterable<String> {
-        private int pos = 0;
-        private final String path;
-        private final String emptyPathDefault;
-
-        public PathIterator(String path, String emptyPathDefault) {
-            this.path = path;
-            this.emptyPathDefault = emptyPathDefault;
-        }
-        public PathIterator(String path) { this(path, null); }
-        public Iterator<String> iterator() {
-            return new Iterator<String>() {
-                public boolean hasNext() {
-                    return pos <= path.length();
-                }
-                public String next() {
-                    int beg = pos;
-                    int end = path.indexOf(File.pathSeparator, beg);
-                    if (end == -1)
-                        end = path.length();
-                    pos = end + 1;
-
-                    if (beg == end && emptyPathDefault != null)
-                        return emptyPathDefault;
-                    else
-                        return path.substring(beg, end);
-                }
-                public void remove() {
-                    throw new UnsupportedOperationException();
-                }
-            };
-        }
-    }
-
-    private class Path extends LinkedHashSet<File> {
-        private static final long serialVersionUID = 0;
-
-        private boolean expandJarClassPaths = false;
-        private Set<File> canonicalValues = new HashSet<File>();
-
-        public Path expandJarClassPaths(boolean x) {
-            expandJarClassPaths = x;
-            return this;
-        }
-
-        /** What to use when path element is the empty string */
-        private String emptyPathDefault = null;
-
-        public Path emptyPathDefault(String x) {
-            emptyPathDefault = x;
-            return this;
-        }
-
-        public Path() { super(); }
-
-        public Path addDirectories(String dirs, boolean warn) {
-            if (dirs != null)
-                for (String dir : new PathIterator(dirs))
-                    addDirectory(dir, warn);
-            return this;
-        }
-
-        public Path addDirectories(String dirs) {
-            return addDirectories(dirs, warn);
-        }
-
-        private void addDirectory(String dir, boolean warn) {
-            if (! new File(dir).isDirectory()) {
-                if (warn)
-                    log.warning("dir.path.element.not.found", dir);
-                return;
-            }
-
-            File[] files = new File(dir).listFiles();
-            if (files == null)
-                return;
-
-            for (File direntry : files) {
-                if (isArchive(direntry))
-                    addFile(direntry, warn);
-            }
-        }
-
-        public Path addFiles(String files, boolean warn) {
-            if (files != null)
-                for (String file : new PathIterator(files, emptyPathDefault))
-                    addFile(file, warn);
-            return this;
-        }
-
-        public Path addFiles(String files) {
-            return addFiles(files, warn);
-        }
-
-        public Path addFile(String file, boolean warn) {
-            addFile(new File(file), warn);
-            return this;
-        }
-
-        public void addFile(File file, boolean warn) {
-            boolean foundInCache = false;
-            PathEntry pe = null;
-            if (!NON_BATCH_MODE) {
-                    pe = pathExistanceCache.get(file);
-                    if (pe != null) {
-                        foundInCache = true;
-                    }
-                    else {
-                        pe = new PathEntry();
-                    }
-            }
-            else {
-                pe = new PathEntry();
-            }
-
-            File canonFile;
-            try {
-                if (!foundInCache) {
-                    pe.cannonicalPath = file.getCanonicalFile();
-                }
-                else {
-                   canonFile = pe.cannonicalPath;
-                }
-            } catch (IOException e) {
-                pe.cannonicalPath = canonFile = file;
-            }
-
-            if (contains(file) || canonicalValues.contains(pe.cannonicalPath)) {
-                /* Discard duplicates and avoid infinite recursion */
-                return;
-            }
-
-            if (!foundInCache) {
-                pe.exists = file.exists();
-                pe.isFile = file.isFile();
-                if (!NON_BATCH_MODE) {
-                    pathExistanceCache.put(file, pe);
-                }
-            }
-
-            if (! pe.exists) {
-                /* No such file or directory exists */
-                if (warn)
-                    log.warning("path.element.not.found", file);
-            } else if (pe.isFile) {
-                /* File is an ordinary file. */
-                if (!isArchive(file)) {
-                    /* Not a recognized extension; open it to see if
-                     it looks like a valid zip file. */
-                    try {
-                        ZipFile z = new ZipFile(file);
-                        z.close();
-                        if (warn)
-                            log.warning("unexpected.archive.file", file);
-                    } catch (IOException e) {
-                        // FIXME: include e.getLocalizedMessage in warning
-                        if (warn)
-                            log.warning("invalid.archive.file", file);
-                        return;
-                    }
-                }
-            }
-
-            /* Now what we have left is either a directory or a file name
-               confirming to archive naming convention */
-            super.add(file);
-            canonicalValues.add(pe.cannonicalPath);
-
-            if (expandJarClassPaths && file.exists() && file.isFile())
-                addJarClassPath(file, warn);
-        }
-
-        // Adds referenced classpath elements from a jar's Class-Path
-        // Manifest entry.  In some future release, we may want to
-        // update this code to recognize URLs rather than simple
-        // filenames, but if we do, we should redo all path-related code.
-        private void addJarClassPath(File jarFile, boolean warn) {
-            try {
-                java.util.List<File> manifestsList = manifestEntries.get(jarFile);
-                if (!NON_BATCH_MODE) {
-                    lock.lock();
-                    try {
-                        if (manifestsList != null) {
-                            for (File entr : manifestsList) {
-                                addFile(entr, warn);
-                            }
-                            return;
-                        }
-                    }
-                    finally {
-                        lock.unlock();
-                    }
-                }
-
-                if (!NON_BATCH_MODE) {
-                    manifestsList = new ArrayList<File>();
-                    manifestEntries.put(jarFile, manifestsList);
-                }
-
-                String jarParent = jarFile.getParent();
-                JarFile jar = new JarFile(jarFile);
-
-                try {
-                    Manifest man = jar.getManifest();
-                    if (man == null) return;
-
-                    Attributes attr = man.getMainAttributes();
-                    if (attr == null) return;
-
-                    String path = attr.getValue(Attributes.Name.CLASS_PATH);
-                    if (path == null) return;
-
-                    for (StringTokenizer st = new StringTokenizer(path);
-                         st.hasMoreTokens();) {
-                        String elt = st.nextToken();
-                        File f = (jarParent == null ? new File(elt) : new File(jarParent, elt));
-                        addFile(f, warn);
-
-                        if (!NON_BATCH_MODE) {
-                            lock.lock();
-                            try {
-                                manifestsList.add(f);
-                            }
-                            finally {
-                                lock.unlock();
-                            }
-                        }
-                    }
-                } finally {
-                    jar.close();
-                }
-            } catch (IOException e) {
-                log.error("error.reading.file", jarFile, e.getLocalizedMessage());
-            }
-        }
-    }
-
-    private Path computeBootClassPath() {
-        bootClassPathRtJar = null;
-        String optionValue;
-        Path path = new Path();
-
-        path.addFiles(options.get(XBOOTCLASSPATH_PREPEND));
-
-        if ((optionValue = options.get(ENDORSEDDIRS)) != null)
-            path.addDirectories(optionValue);
-        else
-            path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
-
-        if ((optionValue = options.get(BOOTCLASSPATH)) != null) {
-            path.addFiles(optionValue);
-        } else {
-            // Standard system classes for this compiler's release.
-            String files = System.getProperty("sun.boot.class.path");
-            path.addFiles(files, false);
-            File rt_jar = new File("rt.jar");
-            for (String file : new PathIterator(files, null)) {
-                File f = new File(file);
-                if (new File(f.getName()).equals(rt_jar))
-                    bootClassPathRtJar = f;
-            }
-        }
-
-        path.addFiles(options.get(XBOOTCLASSPATH_APPEND));
-
-        // Strictly speaking, standard extensions are not bootstrap
-        // classes, but we treat them identically, so we'll pretend
-        // that they are.
-        if ((optionValue = options.get(EXTDIRS)) != null)
-            path.addDirectories(optionValue);
-        else
-            path.addDirectories(System.getProperty("java.ext.dirs"), false);
-
-        return path;
-    }
-
-    private Path computeUserClassPath() {
-        String cp = options.get(CLASSPATH);
-
-        // CLASSPATH environment variable when run from `javac'.
-        if (cp == null) cp = System.getProperty("env.class.path");
-
-        // If invoked via a java VM (not the javac launcher), use the
-        // platform class path
-        if (cp == null && System.getProperty("application.home") == null)
-            cp = System.getProperty("java.class.path");
-
-        // Default to current working directory.
-        if (cp == null) cp = ".";
-
-        return new Path()
-            .expandJarClassPaths(true) // Only search user jars for Class-Paths
-            .emptyPathDefault(".")     // Empty path elt ==> current directory
-            .addFiles(cp);
-    }
-
-    private Path computeSourcePath() {
-        String sourcePathArg = options.get(SOURCEPATH);
-        if (sourcePathArg == null)
-            return null;
-
-        return new Path().addFiles(sourcePathArg);
-    }
-
-    private Path computeAnnotationProcessorPath() {
-        String processorPathArg = options.get(PROCESSORPATH);
-        if (processorPathArg == null)
-            return null;
-
-        return new Path().addFiles(processorPathArg);
-    }
-
-    /** The actual effective locations searched for sources */
-    private Path sourceSearchPath;
-
-    public Collection<File> sourceSearchPath() {
-        if (sourceSearchPath == null) {
-            lazy();
-            Path sourcePath = getPathForLocation(SOURCE_PATH);
-            Path userClassPath = getPathForLocation(CLASS_PATH);
-            sourceSearchPath = sourcePath != null ? sourcePath : userClassPath;
-        }
-        return Collections.unmodifiableCollection(sourceSearchPath);
-    }
-
-    /** The actual effective locations searched for classes */
-    private Path classSearchPath;
-
-    public Collection<File> classSearchPath() {
-        if (classSearchPath == null) {
-            lazy();
-            Path bootClassPath = getPathForLocation(PLATFORM_CLASS_PATH);
-            Path userClassPath = getPathForLocation(CLASS_PATH);
-            classSearchPath = new Path();
-            classSearchPath.addAll(bootClassPath);
-            classSearchPath.addAll(userClassPath);
-        }
-        return Collections.unmodifiableCollection(classSearchPath);
-    }
-
-    /** The actual effective locations for non-source, non-class files */
-    private Path otherSearchPath;
-
-    Collection<File> otherSearchPath() {
-        if (otherSearchPath == null) {
-            lazy();
-            Path userClassPath = getPathForLocation(CLASS_PATH);
-            Path sourcePath = getPathForLocation(SOURCE_PATH);
-            if (sourcePath == null)
-                otherSearchPath = userClassPath;
-            else {
-                otherSearchPath = new Path();
-                otherSearchPath.addAll(userClassPath);
-                otherSearchPath.addAll(sourcePath);
-            }
-        }
-        return Collections.unmodifiableCollection(otherSearchPath);
-    }
-
-    /** Is this the name of an archive file? */
-    private static boolean isArchive(File file) {
-        String n = file.getName().toLowerCase();
-        boolean isFile = false;
-        if (!NON_BATCH_MODE) {
-            Boolean isf = isDirectory.get(file);
-            if (isf == null) {
-                isFile = file.isFile();
-                isDirectory.put(file, isFile);
-            }
-            else {
-                isFile = isf;
-            }
-        }
-        else {
-            isFile = file.isFile();
-        }
-
-        return isFile
-            && (n.endsWith(".jar") || n.endsWith(".zip"));
-    }
-}
--- a/src/share/classes/com/sun/tools/javac/zip/ZipFileIndex.java	Thu Jun 12 13:19:16 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1236 +0,0 @@
-/*
- * Copyright 2007-2008 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package com.sun.tools.javac.zip;
-
-import java.io.*;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.List;
-import java.util.concurrent.locks.ReentrantLock;
-import java.util.zip.*;
-
-/** This class implements building of index of a zip archive and access to it's context.
- *  It also uses prebuild index if available. It supports invocations where it will
- *  serialize an optimized zip index file to disk.
- *
- *  In oreder to use secondary index file make sure the option "usezipindex" is 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
- *  "-XDcachezipindexdir=<directory>". If this flag is not provided, the dfault location is
- *  the value of the "java.io.tmpdir" system property.
- *
- *  If key "-XDwritezipindexfiles" is specified, there will be new optimized index file
- *  created for each archive, used by the compiler for compilation, at location,
- *  specified by "cachezipindexdir" option.
- *
- * If nonBatchMode option is specified (-XDnonBatchMode) 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.
- */
-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 Map<File, ZipFileIndex> zipFileIndexCache = new HashMap<File, ZipFileIndex>();
-    private static ReentrantLock lock = new ReentrantLock();
-
-    private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
-
-    private Map<String, DirectoryEntry> directories = Collections.<String, DirectoryEntry>emptyMap();
-    private Set<String> allDirs = Collections.<String>emptySet();
-
-    // ZipFileIndex data entries
-    private File zipFile;
-    private long zipFileLastModified = NOT_MODIFIED;
-    private RandomAccessFile zipRandomFile;
-    private ZipFileIndexEntry[] entries;
-
-    private boolean readFromIndex = false;
-    private File zipIndexFile = null;
-    private boolean triedToReadIndex = false;
-    private int symbolFilePrefixLength = 0;
-    private boolean hasPopulatedData = false;
-    private long lastReferenceTimeStamp = NOT_MODIFIED;
-
-    private boolean usePreindexedCache = false;
-    private String preindexedCacheLocation = null;
-
-    private boolean writeIndex = false;
-
-    /**
-     * Returns a list of all ZipFileIndex entries
-     *
-     * @return A list of ZipFileIndex entries, or an empty list
-     */
-    public static 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 static List<ZipFileIndex> getZipFileIndexes(boolean openedOnly) {
-        List<ZipFileIndex> zipFileIndexes = new ArrayList<ZipFileIndex>();
-        lock.lock();
-        try {
-            zipFileIndexes.addAll(zipFileIndexCache.values());
-
-            if (openedOnly) {
-                for(ZipFileIndex elem : zipFileIndexes) {
-                    if (!elem.isOpen()) {
-                        zipFileIndexes.remove(elem);
-                    }
-                }
-            }
-        }
-        finally {
-            lock.unlock();
-        }
-        return zipFileIndexes;
-    }
-
-    public boolean isOpen() {
-        lock.lock();
-        try {
-            return zipRandomFile != null;
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    public static ZipFileIndex getZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean useCache, String cacheLocation, boolean writeIndex) throws IOException {
-        ZipFileIndex zi = null;
-        lock.lock();
-        try {
-            zi = getExistingZipIndex(zipFile);
-
-            if (zi == null || (zi != null && zipFile.lastModified() != zi.zipFileLastModified)) {
-                zi = new ZipFileIndex(zipFile, symbolFilePrefixLen, writeIndex,
-                        useCache, cacheLocation);
-                zipFileIndexCache.put(zipFile, zi);
-            }
-        }
-        finally {
-            lock.unlock();
-        }
-        return zi;
-    }
-
-    public static ZipFileIndex getExistingZipIndex(File zipFile) {
-        lock.lock();
-        try {
-            return zipFileIndexCache.get(zipFile);
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    public static void clearCache() {
-        lock.lock();
-        try {
-            zipFileIndexCache.clear();
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    public static void clearCache(long timeNotUsed) {
-        lock.lock();
-        try {
-            Iterator<File> cachedFileIterator = zipFileIndexCache.keySet().iterator();
-            while (cachedFileIterator.hasNext()) {
-                File cachedFile = cachedFileIterator.next();
-                ZipFileIndex cachedZipIndex = zipFileIndexCache.get(cachedFile);
-                if (cachedZipIndex != null) {
-                    long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed;
-                    if (timeToTest < cachedZipIndex.lastReferenceTimeStamp || // Overflow...
-                            System.currentTimeMillis() > timeToTest) {
-                        zipFileIndexCache.remove(cachedFile);
-                    }
-                }
-            }
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    public static void removeFromCache(File file) {
-        lock.lock();
-        try {
-            zipFileIndexCache.remove(file);
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    /** 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 static void setOpenedIndexes(List<ZipFileIndex>indexes) throws IllegalStateException {
-        lock.lock();
-        try {
-            if (zipFileIndexCache.isEmpty()) {
-                throw new IllegalStateException("Setting opened indexes should be called only when the ZipFileCache is empty. Call JavacFileManager.flush() before calling this method.");
-            }
-
-            for (ZipFileIndex zfi : indexes) {
-                zipFileIndexCache.put(zfi.zipFile, zfi);
-            }
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    private ZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean writeIndex,
-            boolean useCache, String cacheLocation) throws IOException {
-        this.zipFile = zipFile;
-        this.symbolFilePrefixLength = symbolFilePrefixLen;
-        this.writeIndex = writeIndex;
-        this.usePreindexedCache = useCache;
-        this.preindexedCacheLocation = cacheLocation;
-
-        if (zipFile != null) {
-            this.zipFileLastModified = zipFile.lastModified();
-        }
-
-        // Validate integrity of the zip file
-        checkIndex();
-    }
-
-    public String toString() {
-        return "ZipFileIndex of file:(" + zipFile + ")";
-    }
-
-    // Just in case...
-    protected void finalize() {
-        closeFile();
-    }
-
-    private boolean isUpToDate() {
-        if (zipFile != null &&
-                ((!NON_BATCH_MODE) || zipFileLastModified == zipFile.lastModified()) &&
-                hasPopulatedData) {
-            return true;
-        }
-
-        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.<String, DirectoryEntry>emptyMap();
-        allDirs = Collections.<String>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, "r");
-        }
-    }
-
-    private void cleanupState() {
-        // Make sure there is a valid but empty index if the file doesn't exist
-        entries = ZipFileIndexEntry.EMPTY_ARRAY;
-        directories = Collections.<String, DirectoryEntry>emptyMap();
-        zipFileLastModified = NOT_MODIFIED;
-        allDirs = Collections.<String>emptySet();
-    }
-
-    public void close() {
-        lock.lock();
-        try {
-            writeIndex();
-            closeFile();
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    private void closeFile() {
-        if (zipRandomFile != null) {
-            try {
-                zipRandomFile.close();
-            } catch (IOException ex) {
-            }
-            zipRandomFile = null;
-        }
-    }
-
-    /**
-     * Returns the ZipFileIndexEntry for an absolute path, if there is one.
-     */
-    public ZipFileIndexEntry getZipIndexEntry(String path) {
-        if (File.separatorChar != '/') {
-            path = path.replace('/', File.separatorChar);
-        }
-        lock.lock();
-        try {
-            checkIndex();
-            String lookFor = "";
-            int lastSepIndex = path.lastIndexOf(File.separatorChar);
-            boolean noSeparator = false;
-            if (lastSepIndex == -1) {
-                noSeparator = true;
-            }
-
-            DirectoryEntry de = directories.get(noSeparator ? "" : path.substring(0, lastSepIndex));
-
-            lookFor = path.substring(noSeparator ? 0 : lastSepIndex + 1);
-
-            return de == null ? null : de.getEntry(lookFor);
-        }
-        catch (IOException e) {
-            return null;
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Returns a javac List of filenames within an absolute path in the ZipFileIndex.
-     */
-    public com.sun.tools.javac.util.List<String> getFiles(String path) {
-        if (File.separatorChar != '/') {
-            path = path.replace('/', File.separatorChar);
-        }
-
-        lock.lock();
-        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();
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    public List<String> getAllDirectories(String path) {
-
-        if (File.separatorChar != '/') {
-            path = path.replace('/', File.separatorChar);
-        }
-
-        lock.lock();
-        try {
-            checkIndex();
-            path = path.intern();
-
-            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();
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    public Set<String> getAllDirectories() {
-        lock.lock();
-        try {
-            checkIndex();
-            if (allDirs == Collections.EMPTY_SET) {
-                Set<String> alldirs = new HashSet<String>();
-                Iterator<String> dirsIter = directories.keySet().iterator();
-                while (dirsIter.hasNext()) {
-                    alldirs.add(new String(dirsIter.next()));
-                }
-
-                allDirs = alldirs;
-            }
-
-            return allDirs;
-        }
-        catch (IOException e) {
-            return Collections.<String>emptySet();
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * 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 boolean contains(String path) {
-        lock.lock();
-        try {
-            checkIndex();
-            return getZipIndexEntry(path) != null;
-        }
-        catch (IOException e) {
-            return false;
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    public boolean isDirectory(String path) throws IOException {
-        lock.lock();
-        try {
-            // The top level in a zip file is always a directory.
-            if (path.length() == 0) {
-                lastReferenceTimeStamp = System.currentTimeMillis();
-                return true;
-            }
-
-            if (File.separatorChar != '/')
-                path = path.replace('/', File.separatorChar);
-            checkIndex();
-            return directories.get(path) != null;
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    public long getLastModified(String path) throws IOException {
-        lock.lock();
-        try {
-            ZipFileIndexEntry entry = getZipIndexEntry(path);
-            if (entry == null)
-                throw new FileNotFoundException();
-            return entry.getLastModified();
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    public int length(String path) throws IOException {
-        lock.lock();
-        try {
-            ZipFileIndexEntry 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;
-            }
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    public byte[] read(String path) throws IOException {
-        lock.lock();
-        try {
-            ZipFileIndexEntry entry = getZipIndexEntry(path);
-            if (entry == null)
-                throw new FileNotFoundException(MessageFormat.format("Path not found in ZIP: {0}", path));
-            return read(entry);
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    public byte[] read(ZipFileIndexEntry entry) throws IOException {
-        lock.lock();
-        try {
-            openFile();
-            byte[] result = readBytes(entry);
-            closeFile();
-            return result;
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    public int read(String path, byte[] buffer) throws IOException {
-        lock.lock();
-        try {
-            ZipFileIndexEntry entry = getZipIndexEntry(path);
-            if (entry == null)
-                throw new FileNotFoundException();
-            return read(entry, buffer);
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    public int read(ZipFileIndexEntry entry, byte[] buffer)
-            throws IOException {
-        lock.lock();
-        try {
-            int result = readBytes(entry, buffer);
-            return result;
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    private byte[] readBytes(ZipFileIndexEntry 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(ZipFileIndexEntry 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(ZipFileIndexEntry 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 static Inflater inflater;
-    private int inflate(byte[] src, byte[] dest) {
-
-        // construct the inflater object or reuse an existing one
-        if (inflater == null)
-            inflater = new Inflater(true);
-
-        synchronized (inflater) {
-            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 String 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;
-
-            findCENRecord(start, end);
-        }
-
-        /*
-         * 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) + 2];
-                    zipDir[0] = endbuf[i + 10];
-                    zipDir[1] = endbuf[i + 11];
-                    zipRandomFile.seek(start + get4ByteLittleEndian(endbuf, i + 16));
-                    zipRandomFile.readFully(zipDir, 2, zipDir.length - 2);
-                    return;
-                } else {
-                    endbufend = endbufpos + 21;
-                }
-            }
-            throw new ZipException("cannot read zip file");
-        }
-        private void buildIndex() throws IOException {
-            int entryCount = get2ByteLittleEndian(zipDir, 0);
-
-            entries = new ZipFileIndexEntry[entryCount];
-            // Add each of the files
-            if (entryCount > 0) {
-                directories = new HashMap<String, DirectoryEntry>();
-                ArrayList<ZipFileIndexEntry> entryList = new ArrayList<ZipFileIndexEntry>();
-                int pos = 2;
-                for (int i = 0; i < entryCount; i++) {
-                    pos = readEntry(pos, entryList, directories);
-                }
-
-                // Add the accumulated dirs into the same list
-                Iterator i = directories.keySet().iterator();
-                while (i.hasNext()) {
-                    ZipFileIndexEntry zipFileIndexEntry = new ZipFileIndexEntry( (String) i.next());
-                    zipFileIndexEntry.isDir = true;
-                    entryList.add(zipFileIndexEntry);
-                }
-
-                entries = entryList.toArray(new ZipFileIndexEntry[entryList.size()]);
-                Arrays.sort(entries);
-            } else {
-                cleanupState();
-            }
-        }
-
-        private int readEntry(int pos, List<ZipFileIndexEntry> entryList,
-                Map<String, 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;
-            }
-
-            // Use the OS's path separator. Keep the position of the last one.
-            for (int index = fileStart; index < fileEnd; index++) {
-                byte nextByte = zipDir[index];
-                if (nextByte == (byte)'\\' || nextByte == (byte)'/') {
-                    zipDir[index] = (byte)File.separatorChar;
-                    fileStart = index + 1;
-                }
-            }
-
-            String directory = null;
-            if (fileStart == dirStart)
-                directory = "";
-            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 = new String(zipDir, dirStart, lastLen, "UTF-8").intern();
-                lastDir = directory;
-
-                // Enter also all the parent directories
-                String tempDirectory = directory;
-
-                while (directories.get(tempDirectory) == null) {
-                    directories.put(tempDirectory, new DirectoryEntry(tempDirectory, zipFileIndex));
-                    int separator = tempDirectory.lastIndexOf(File.separatorChar);
-                    if (separator == -1)
-                        break;
-                    tempDirectory = tempDirectory.substring(0, separator);
-                }
-            }
-            else {
-                directory = directory.intern();
-                if (directories.get(directory) == null) {
-                    directories.put(directory, new DirectoryEntry(directory, zipFileIndex));
-                }
-            }
-
-            // For each dir create also a file
-            if (fileStart != fileEnd) {
-                ZipFileIndexEntry entry = new ZipFileIndexEntry(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 {
-        lock.lock();
-        try {
-            checkIndex();
-            return zipFileLastModified;
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    /** ------------------------------------------------------------------------
-     *  DirectoryEntry class
-     * -------------------------------------------------------------------------*/
-    static class DirectoryEntry {
-        private boolean filesInited;
-        private boolean directoriesInited;
-        private boolean zipFileEntriesInited;
-        private boolean entriesInited;
-
-        private long writtenOffsetOffset = 0;
-
-        private String 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<ZipFileIndexEntry>  zipFileEntries = com.sun.tools.javac.util.List.<ZipFileIndexEntry>nil();
-
-        private List<ZipFileIndexEntry> entries = new ArrayList<ZipFileIndexEntry>();
-
-        private ZipFileIndex zipFileIndex;
-
-        private int numEntries;
-
-        DirectoryEntry(String dirName, ZipFileIndex index) {
-        filesInited = false;
-            directoriesInited = false;
-            entriesInited = false;
-
-            if (File.separatorChar == '/') {
-                dirName.replace('\\', '/');
-            }
-            else {
-                dirName.replace('/', '\\');
-            }
-
-            this.dirName = dirName.intern();
-            this.zipFileIndex = index;
-        }
-
-        private com.sun.tools.javac.util.List<String> getFiles() {
-            if (filesInited) {
-                return zipFileEntriesFiles;
-            }
-
-            initEntries();
-
-            for (ZipFileIndexEntry 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) {
-                return zipFileEntriesFiles;
-            }
-
-            initEntries();
-
-            for (ZipFileIndexEntry e : entries) {
-                if (e.isDir) {
-                    zipFileEntriesDirectories = zipFileEntriesDirectories.append(e.name);
-                }
-            }
-
-            directoriesInited = true;
-
-            return zipFileEntriesDirectories;
-        }
-
-        private com.sun.tools.javac.util.List<ZipFileIndexEntry> getEntries() {
-            if (zipFileEntriesInited) {
-                return zipFileEntries;
-            }
-
-            initEntries();
-
-            zipFileEntries = com.sun.tools.javac.util.List.nil();
-            for (ZipFileIndexEntry zfie : entries) {
-                zipFileEntries = zipFileEntries.append(zfie);
-            }
-
-            zipFileEntriesInited = true;
-
-            return zipFileEntries;
-        }
-
-        private ZipFileIndexEntry getEntry(String rootName) {
-            initEntries();
-            int index = Collections.binarySearch(entries, new ZipFileIndexEntry(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 ZipFileIndexEntry(dirName, ZipFileIndex.MIN_CHAR)) - 1;
-                int to = -Arrays.binarySearch(zipFileIndex.entries,
-                        new ZipFileIndexEntry(dirName, MAX_CHAR)) - 1;
-
-                boolean emptyList = false;
-
-                for (int i = from; i < to; i++) {
-                    entries.add(zipFileIndex.entries[i]);
-                }
-            } else {
-                File indexFile = zipFileIndex.getIndexFile();
-                if (indexFile != null) {
-                    RandomAccessFile raf = null;
-                    try {
-                        raf = new RandomAccessFile(indexFile, "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();
-
-                            ZipFileIndexEntry rfie = new ZipFileIndexEntry(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<ZipFileIndexEntry> getEntriesAsCollection() {
-            initEntries();
-
-            return entries;
-        }
-    }
-
-    private boolean readIndex() {
-        if (triedToReadIndex || !usePreindexedCache) {
-            return false;
-        }
-
-        boolean ret = false;
-        lock.lock();
-        try {
-            triedToReadIndex = true;
-            RandomAccessFile raf = null;
-            try {
-                File indexFileName = getIndexFile();
-                raf = new RandomAccessFile(indexFileName, "r");
-
-                long fileStamp = raf.readLong();
-                if (zipFile.lastModified() != fileStamp) {
-                    ret = false;
-                } else {
-                    directories = new HashMap<String, DirectoryEntry>();
-                    int numDirs = raf.readInt();
-                    for (int nDirs = 0; nDirs < numDirs; nDirs++) {
-                        int dirNameBytesLen = raf.readInt();
-                        byte [] dirNameBytes = new byte[dirNameBytesLen];
-                        raf.read(dirNameBytes);
-
-                        String dirNameStr = 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;
-            }
-        }
-        finally {
-            lock.unlock();
-        }
-
-        return ret;
-    }
-
-    private boolean writeIndex() {
-        boolean ret = false;
-        if (readFromIndex || !usePreindexedCache) {
-            return true;
-        }
-
-        if (!writeIndex) {
-            return true;
-        }
-
-        File indexFile = getIndexFile();
-        if (indexFile == null) {
-            return false;
-        }
-
-        RandomAccessFile raf = null;
-        long writtenSoFar = 0;
-        try {
-            raf = new RandomAccessFile(indexFile, "rw");
-
-            raf.writeLong(zipFileLastModified);
-            writtenSoFar += 8;
-
-
-            Iterator<String> iterDirName = directories.keySet().iterator();
-            List<DirectoryEntry> directoriesToWrite = new ArrayList<DirectoryEntry>();
-            Map<String, Long> offsets = new HashMap<String, Long>();
-            raf.writeInt(directories.keySet().size());
-            writtenSoFar += 4;
-
-            while(iterDirName.hasNext()) {
-                String dirName = iterDirName.next();
-                DirectoryEntry dirEntry = directories.get(dirName);
-
-                directoriesToWrite.add(dirEntry);
-
-                // Write the dir name bytes
-                byte [] dirNameBytes = dirName.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 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<ZipFileIndexEntry> entries = de.getEntriesAsCollection();
-                for (ZipFileIndexEntry zfie : entries) {
-                    // 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() {
-        lock.lock();
-        try {
-            return writeIndex();
-        }
-        finally {
-            lock.unlock();
-        }
-    }
-
-    private File getIndexFile() {
-        if (zipIndexFile == null) {
-            if (zipFile == null) {
-                return null;
-            }
-
-            zipIndexFile = new File((preindexedCacheLocation == null ? "" : preindexedCacheLocation) +
-                    zipFile.getName() + ".index");
-        }
-
-        return zipIndexFile;
-    }
-
-    public File getZipFile() {
-        return zipFile;
-    }
-}
--- a/src/share/classes/com/sun/tools/javac/zip/ZipFileIndexEntry.java	Thu Jun 12 13:19:16 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * Copyright 2007-2008 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package com.sun.tools.javac.zip;
-
-import java.io.File;
-
-public final class ZipFileIndexEntry implements Comparable<ZipFileIndexEntry> {
-    public static final ZipFileIndexEntry[] EMPTY_ARRAY = {};
-
-    // Directory related
-    String dir;
-    boolean isDir;
-
-    // File related
-    String name;
-
-    int offset;
-    int size;
-    int compressedSize;
-    long javatime;
-
-    private int nativetime;
-
-    public ZipFileIndexEntry(String path) {
-        int separator = path.lastIndexOf(File.separatorChar);
-        if (separator == -1) {
-            dir = "".intern();
-            name = path;
-        } else {
-            dir = path.substring(0, separator).intern();
-            name = path.substring(separator + 1);
-        }
-    }
-
-    public ZipFileIndexEntry(String directory, String name) {
-        this.dir = directory.intern();
-        this.name = name;
-    }
-
-    public String getName() {
-        if (dir == null || dir.length() == 0) {
-            return name;
-        }
-
-        StringBuilder sb = new StringBuilder();
-        sb.append(dir);
-        sb.append(File.separatorChar);
-        sb.append(name);
-        return sb.toString();
-    }
-
-    public String getFileName() {
-        return name;
-    }
-
-    public long getLastModified() {
-        if (javatime == 0) {
-                javatime = dosToJavaTime(nativetime);
-        }
-        return javatime;
-    }
-
-    // From java.util.zip
-    private static long dosToJavaTime(int nativetime) {
-        // Bootstrap build problems prevent me from using the code directly
-        // Convert the raw/native time to a long for now
-        return (long)nativetime;
-    }
-
-    void setNativeTime(int natTime) {
-        nativetime = natTime;
-    }
-
-    public boolean isDirectory() {
-        return isDir;
-    }
-
-    public int compareTo(ZipFileIndexEntry other) {
-        String otherD = other.dir;
-        if (dir != otherD) {
-            int c = dir.compareTo(otherD);
-            if (c != 0)
-                return c;
-        }
-        return name.compareTo(other.name);
-    }
-
-
-    public String toString() {
-        return isDir ? ("Dir:" + dir + " : " + name) :
-            (dir + ":" + name);
-    }
-}
--- a/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java	Mon Jun 16 22:23:33 2008 -0700
@@ -26,10 +26,10 @@
 package com.sun.tools.javadoc;
 
 import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.file.Old199;
 import com.sun.tools.javac.jvm.ClassReader;
 import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.JavacFileManager;
-import com.sun.tools.javac.util.Old199;
 
 import java.io.File;
 import java.util.EnumSet;
--- a/src/share/classes/com/sun/tools/javadoc/JavadocTool.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/JavadocTool.java	Mon Jun 16 22:23:33 2008 -0700
@@ -29,19 +29,14 @@
 
 import java.util.Collection;
 
-import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.comp.*;
-import com.sun.tools.javac.jvm.ClassReader;
-import com.sun.tools.javac.jvm.ClassWriter;
+import com.sun.tools.javac.file.Paths;
 import com.sun.tools.javac.parser.DocCommentScanner;
-import com.sun.tools.javac.util.Paths;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.*;
 
-import com.sun.javadoc.LanguageVersion;
-import static com.sun.javadoc.LanguageVersion.*;
 
 /**
  *  This class could be the main entry point for Javadoc when Javadoc is used as a
@@ -147,7 +142,7 @@
                 } else if (isValidPackageName(name)) {
                     names = names.append(name);
                 } else if (name.endsWith(".java")) {
-                    docenv.error(null, "main.file_not_found", name);;
+                    docenv.error(null, "main.file_not_found", name);
                 } else {
                     docenv.error(null, "main.illegal_package_name", name);
                 }
--- a/src/share/classes/com/sun/tools/javap/JavapFileManager.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/javap/JavapFileManager.java	Mon Jun 16 22:23:33 2008 -0700
@@ -32,9 +32,9 @@
 import javax.tools.DiagnosticListener;
 import javax.tools.JavaFileObject;
 
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.JCDiagnostic;
-import com.sun.tools.javac.util.JavacFileManager;
 
 /**
  *  javap's implementation of JavaFileManager.
--- a/test/tools/javac/6304921/TestLog.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/test/tools/javac/6304921/TestLog.java	Mon Jun 16 22:23:33 2008 -0700
@@ -32,12 +32,12 @@
 import java.net.URI;
 import javax.tools.JavaFileObject;
 import javax.tools.SimpleJavaFileObject;
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.parser.Parser;
 import com.sun.tools.javac.parser.Scanner;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.TreeScanner;
 import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.JavacFileManager;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.JCDiagnostic;
 import com.sun.tools.javac.util.Options;
--- a/test/tools/javac/6589361/T6589361.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/test/tools/javac/6589361/T6589361.java	Mon Jun 16 22:23:33 2008 -0700
@@ -4,8 +4,8 @@
  * @summary 6589361:Failing building ct.sym file as part of the control build
  */
 
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.JavacFileManager;
 import java.io.File;
 import javax.tools.FileObject;
 import javax.tools.JavaFileObject;
--- a/test/tools/javac/T6358024.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/test/tools/javac/T6358024.java	Mon Jun 16 22:23:33 2008 -0700
@@ -35,6 +35,7 @@
 import javax.tools.*;
 import com.sun.source.util.*;
 import com.sun.tools.javac.api.*;
+import com.sun.tools.javac.file.*;
 import com.sun.tools.javac.main.*;
 import com.sun.tools.javac.util.*;
 
--- a/test/tools/javac/T6358166.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/test/tools/javac/T6358166.java	Mon Jun 16 22:23:33 2008 -0700
@@ -32,6 +32,7 @@
 import javax.annotation.processing.*;
 import javax.lang.model.element.*;
 import javax.tools.*;
+import com.sun.tools.javac.file.*;
 import com.sun.tools.javac.main.JavaCompiler;
 import com.sun.tools.javac.main.*;
 import com.sun.tools.javac.util.*;
--- a/test/tools/javac/T6358168.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/test/tools/javac/T6358168.java	Mon Jun 16 22:23:33 2008 -0700
@@ -33,6 +33,7 @@
 import javax.annotation.processing.*;
 import javax.lang.model.element.*;
 import javax.tools.*;
+import com.sun.tools.javac.file.*;
 import com.sun.tools.javac.main.JavaCompiler;
 import com.sun.tools.javac.main.*;
 import com.sun.tools.javac.util.*;
--- a/test/tools/javac/T6705935.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/test/tools/javac/T6705935.java	Mon Jun 16 22:23:33 2008 -0700
@@ -30,7 +30,7 @@
 import java.io.*;
 import java.util.*;
 import javax.tools.*;
-import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.file.*;
 
 public class T6705935 {
     public static void main(String... args) throws Exception {
--- a/test/tools/javac/api/T6358786.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/test/tools/javac/api/T6358786.java	Mon Jun 16 22:23:33 2008 -0700
@@ -30,7 +30,7 @@
  */
 
 import com.sun.tools.javac.api.JavacTaskImpl;
-import com.sun.tools.javac.util.JavacFileManager;
+import com.sun.tools.javac.file.JavacFileManager;
 import java.util.Arrays;
 
 import javax.lang.model.util.Elements;
--- a/test/tools/javac/api/TestResolveIdent.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/test/tools/javac/api/TestResolveIdent.java	Mon Jun 16 22:23:33 2008 -0700
@@ -30,8 +30,8 @@
  */
 
 import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.main.JavaCompiler;
-import com.sun.tools.javac.util.JavacFileManager;
 import java.io.File;
 import java.io.IOException;
 import javax.lang.model.element.TypeElement;
--- a/test/tools/javac/util/filemanager/TestName.java	Thu Jun 12 13:19:16 2008 -0700
+++ b/test/tools/javac/util/filemanager/TestName.java	Mon Jun 16 22:23:33 2008 -0700
@@ -29,7 +29,7 @@
  * @author  Peter von der Ah\u00e9
  */
 
-import com.sun.tools.javac.util.JavacFileManager;
+import com.sun.tools.javac.file.JavacFileManager;
 
 public class TestName {
     public static void main(String... args) {