changeset 106:5c2858bccb3f

6962236: backport JavacFileManager fixes from 7 to 6-open 6410637: Make decision on deprecated methods in DefaultFileManager and BaseFileObject. 6419701: DefaultFileManager clean up: URI.create 6483788: DefaultFileManager.ZipFileObject.toUri() fails to escape space characters 6501502: JSR 199: FileObject.toUri should return file:///c:/ or file:/c:/ not file://c:/ 6508981: cleanup file separator handling in JavacFileManager 6625520: javac handles missing entries on classpath badly 6705935: javac reports path name of entry in ZipFileIndex incorectly 6705945: com.sun.tools.javac.zip files do not have valid copyright 6714364: refactor javac File handling code into new javac.file package 6714365: refactor JavacFileManager to move nested classes to top level 6743107: clean up use of static caches in file manager 6794582: javadoc should read files using a FileManager 6832154: refactor Paths to be just a utility class for JavacFileManager 6838467: JSR199 FileObjects don't obey general contract of equals. 6877206: JavaFileObject.toUri returns bogus URI (win) 6877223: tests @ignored because of issues with File.toURI on Windows 6885123: JavaFileObject getName issues 6907660: stupid typo in ZipFileIndex guarantees NPE 6930076: "null" can incorrectly appear in error message compiler.err.error.reading.file Reviewed-by: darcy
author jjg
date Tue, 22 Jun 2010 18:30:16 -0700
parents 7e27c39553e1
children 27f03394a69d
files src/share/classes/com/sun/tools/apt/main/JavaCompiler.java src/share/classes/com/sun/tools/apt/main/Main.java src/share/classes/com/sun/tools/apt/mirror/util/SourcePositionImpl.java src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java src/share/classes/com/sun/tools/javac/api/JavacTool.java src/share/classes/com/sun/tools/javac/file/BaseFileObject.java src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java src/share/classes/com/sun/tools/javac/file/FSInfo.java src/share/classes/com/sun/tools/javac/file/JavacFileManager.java src/share/classes/com/sun/tools/javac/file/Paths.java src/share/classes/com/sun/tools/javac/file/RegularFileObject.java src/share/classes/com/sun/tools/javac/file/RelativePath.java src/share/classes/com/sun/tools/javac/file/SymbolArchive.java src/share/classes/com/sun/tools/javac/file/ZipArchive.java src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java src/share/classes/com/sun/tools/javac/jvm/ClassReader.java src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java src/share/classes/com/sun/tools/javac/main/JavaCompiler.java src/share/classes/com/sun/tools/javac/main/Main.java src/share/classes/com/sun/tools/javac/parser/Scanner.java src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java src/share/classes/com/sun/tools/javac/util/BaseFileManager.java src/share/classes/com/sun/tools/javac/util/BaseFileObject.java src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java src/share/classes/com/sun/tools/javac/util/JavacFileManager.java src/share/classes/com/sun/tools/javac/util/Log.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 src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java src/share/classes/com/sun/tools/javadoc/DocEnv.java src/share/classes/com/sun/tools/javadoc/DocImpl.java src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java src/share/classes/com/sun/tools/javadoc/JavadocTool.java src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java src/share/classes/com/sun/tools/javadoc/RootDocImpl.java src/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java test/tools/javac/6304921/TestLog.java test/tools/javac/6508981/TestInferBinaryName.java test/tools/javac/6508981/p/A.java test/tools/javac/6589361/T6589361.java test/tools/javac/T6358024.java test/tools/javac/T6358166.java test/tools/javac/T6358168.java test/tools/javac/T6625520.java test/tools/javac/T6705935.java test/tools/javac/T6725036.java test/tools/javac/api/6411310/T6411310.java test/tools/javac/api/6411310/Test.java test/tools/javac/api/6440333/T6440333.java test/tools/javac/api/6440528/T6440528.java test/tools/javac/api/6733837/T6733837.java test/tools/javac/api/Sibling.java test/tools/javac/api/T6358786.java test/tools/javac/api/T6483788.java test/tools/javac/api/T6501502.java test/tools/javac/api/T6838467.java test/tools/javac/api/T6877206.java test/tools/javac/api/TestResolveIdent.java test/tools/javac/util/filemanager/TestName.java
diffstat 69 files changed, 6290 insertions(+), 4488 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java	Tue Jun 22 18:30:16 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2009, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,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.*;
@@ -239,6 +233,7 @@
 
         ListBuffer<ClassSymbol> classes = new ListBuffer<ClassSymbol>();
         try {
+            JavacFileManager fm = (JavacFileManager)fileManager;
             //parse all files
             ListBuffer<JCCompilationUnit> trees = new ListBuffer<JCCompilationUnit>();
             for (List<String> l = filenames; l.nonEmpty(); l = l.tail) {
@@ -256,7 +251,8 @@
                         continue;
                     }
                 }
-                trees.append(parse(l.head));
+                JavaFileObject fo = fm.getJavaFileObjectsFromStrings(List.of(l.head)).iterator().next();
+                trees.append(parse(fo));
             }
 
             //enter symbols for all files
--- a/src/share/classes/com/sun/tools/apt/main/Main.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/apt/main/Main.java	Tue Jun 22 18:30:16 2010 -0700
@@ -26,7 +26,6 @@
 package com.sun.tools.apt.main;
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -37,14 +36,15 @@
 import java.util.Map;
 import java.util.HashMap;
 import java.util.Collections;
-import java.util.Collection;
 
 import java.net.URLClassLoader;
 import java.net.URL;
-import java.io.File;
 import java.net.MalformedURLException;
 
-import com.sun.tools.javac.util.Paths;
+import javax.tools.JavaFileManager;
+import javax.tools.StandardLocation;
+
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.code.Source;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Type;
@@ -56,6 +56,8 @@
 import com.sun.tools.apt.util.Bark;
 import com.sun.mirror.apt.AnnotationProcessorFactory;
 
+import static com.sun.tools.javac.file.Paths.pathToURLs;
+
 /** This class provides a commandline interface to the apt build-time
  *  tool.
  *
@@ -766,6 +768,7 @@
         providedFactory = factory;
 
         Context context = new Context();
+        JavacFileManager.preRegister(context);
         options = Options.instance(context);
         Bark bark;
 
@@ -779,7 +782,6 @@
         // prefixed to command line arguments.
         processArgs(forcedOpts);
 
-
         /*
          * A run of apt only gets passed the most recently generated
          * files; the initial run of apt gets passed the files from
@@ -862,14 +864,14 @@
             }
             origOptions = Collections.unmodifiableMap(origOptions);
 
+            JavacFileManager fm = (JavacFileManager) context.get(JavaFileManager.class);
             {
                 // Note: it might be necessary to check for an empty
                 // component ("") of the source path or class path
-                Paths paths = Paths.instance(context);
 
                 String sourceDest = options.get("-s");
-                if (paths.sourcePath() != null) {
-                    for(File f: paths.sourcePath())
+                if (fm.hasLocation(StandardLocation.SOURCE_PATH)) {
+                    for(File f: fm.getLocation(StandardLocation.SOURCE_PATH))
                         augmentedSourcePath += (f + File.pathSeparator);
                     augmentedSourcePath += (sourceDest == null)?".":sourceDest;
                 } else {
@@ -880,8 +882,8 @@
                 }
 
                 String classDest = options.get("-d");
-                if (paths.userClassPath() != null) {
-                    for(File f: paths.userClassPath())
+                if (fm.hasLocation(StandardLocation.CLASS_PATH)) {
+                    for(File f: fm.getLocation(StandardLocation.CLASS_PATH))
                         baseClassPath += (f + File.pathSeparator);
                     // put baseClassPath into map to handle any
                     // value needed for the classloader
@@ -908,9 +910,8 @@
              * uses.
              */
                 String aptclasspath = "";
-                Paths paths = Paths.instance(context);
                 String bcp = "";
-                Collection<File> bootclasspath = paths.bootClassPath();
+                Iterable<? extends File> bootclasspath = fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH);
 
                 if (bootclasspath != null) {
                     for(File f: bootclasspath)
@@ -1271,59 +1272,4 @@
             }
         }
     }
-
-    // Borrowed from DocletInvoker
-    /**
-     * Utility method for converting a search path string to an array
-     * of directory and JAR file URLs.
-     *
-     * @param path the search path string
-     * @return the resulting array of directory and JAR file URLs
-     */
-    static URL[] pathToURLs(String path) {
-        StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
-        URL[] urls = new URL[st.countTokens()];
-        int count = 0;
-        while (st.hasMoreTokens()) {
-            URL url = fileToURL(new File(st.nextToken()));
-            if (url != null) {
-                urls[count++] = url;
-            }
-        }
-        if (urls.length != count) {
-            URL[] tmp = new URL[count];
-            System.arraycopy(urls, 0, tmp, 0, count);
-            urls = tmp;
-        }
-        return urls;
-    }
-
-    /**
-     * Returns the directory or JAR file URL corresponding to the specified
-     * local file name.
-     *
-     * @param file the File object
-     * @return the resulting directory or JAR file URL, or null if unknown
-     */
-    static URL fileToURL(File file) {
-        String name;
-        try {
-            name = file.getCanonicalPath();
-        } catch (IOException e) {
-            name = file.getAbsolutePath();
-        }
-        name = name.replace(File.separatorChar, '/');
-        if (!name.startsWith("/")) {
-            name = "/" + name;
-        }
-        // If the file does not exist, then assume that it's a directory
-        if (!file.isFile()) {
-            name = name + "/";
-        }
-        try {
-            return new URL("file", "", name);
-        } catch (MalformedURLException e) {
-            throw new IllegalArgumentException("file");
-        }
-    }
 }
--- a/src/share/classes/com/sun/tools/apt/mirror/util/SourcePositionImpl.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/apt/mirror/util/SourcePositionImpl.java	Tue Jun 22 18:30:16 2010 -0700
@@ -67,15 +67,15 @@
     public String toString() {
         int ln = line();
         return (ln == Position.NOPOS)
-                ? sourcefile.toString()
-                : sourcefile + ":" + ln;
+                ? sourcefile.getName()
+                : sourcefile.getName() + ":" + ln;
     }
 
     /**
      * {@inheritDoc}
      */
     public File file() {
-        return new File(sourcefile.toString());
+        return new File(sourcefile.toUri());
     }
 
     /**
--- a/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java	Tue Jun 22 18:30:16 2010 -0700
@@ -25,12 +25,11 @@
 
 package com.sun.tools.doclets.formats.html.markup;
 
-import com.sun.tools.doclets.internal.toolkit.*;
+import java.io.*;
+import java.util.*;
 
 import com.sun.javadoc.*;
-import java.io.*;
-import java.util.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
+import com.sun.tools.doclets.internal.toolkit.*;
 
 
 /**
@@ -56,8 +55,9 @@
         super(configuration,
               null, configuration.destDirName + filename,
               configuration.docencoding);
+        // use File to normalize file separators
         configuration.message.notice("doclet.Generating_0",
-                                     configuration.destDirName + filename);
+            new File(configuration.destDirName, filename));
     }
 
     public HtmlDocWriter(Configuration configuration,
@@ -65,10 +65,10 @@
         super(configuration,
               configuration.destDirName + path, filename,
               configuration.docencoding);
+        // use File to normalize file separators
         configuration.message.notice("doclet.Generating_0",
-                                     configuration.destDirName +
-                                         ((path.length() > 0)?
-                                              path + File.separator: "") + filename);
+            new File(configuration.destDirName,
+                    ((path.length() > 0)? path + File.separator: "") + filename));
     }
 
     /**
--- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java	Tue Jun 22 18:30:16 2010 -0700
@@ -81,46 +81,14 @@
     }
 
     /**
-     * get and format message string from resource
-     *
-     * @param key selects message from resource
-     */
-    public String getText(String key) {
-        return getText(key, (String)null);
-    }
-
-    /**
      * Get and format message string from resource
      *
      * @param key selects message from resource
-     * @param a1 Argument, to be repalced in the message.
-     */
-    public String getText(String key, String a1) {
-        return getText(key, a1, null);
-    }
-
-    /**
-     * Get and format message string from resource
-     *
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     */
-    public String getText(String key, String a1, String a2) {
-        return getText(key, a1, a2, null);
-    }
-
-    /**
-     * Get and format message string from resource
-     *
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     * @param a3 third argument to be replaced in the message.
+     * @param args arguments to be replaced in the message.
      * @throws MissingResourceException when the key does not
      * exist in the properties file.
      */
-    public String getText(String key, String a1, String a2, String a3) throws MissingResourceException {
+    public String getText(String key, Object... args) throws MissingResourceException {
         if (messageRB == null) {
             try {
                 messageRB = ResourceBundle.getBundle(resourcelocation);
@@ -130,7 +98,7 @@
             }
         }
         String message = messageRB.getString(key);
-        return MessageFormat.format(message, a1, a2, a3);
+        return MessageFormat.format(message, args);
     }
 
     /**
@@ -195,87 +163,20 @@
      *
      * @param pos the position of the source
      * @param key selects message from resource
+     * @param args arguments to be replaced in the message.
      */
-    public void error(SourcePosition pos, String key) {
-        printError(pos, getText(key));
+    public void error(SourcePosition pos, String key, Object... args) {
+        printError(pos, getText(key, args));
     }
 
     /**
      * Print error message, increment error count.
      *
      * @param key selects message from resource
+     * @param args arguments to be replaced in the message.
      */
-    public void error(String key) {
-        printError(getText(key));
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param pos the position of the source
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     */
-    public void error(SourcePosition pos, String key, String a1) {
-        printError(pos, getText(key, a1));
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     */
-    public void error(String key, String a1) {
-        printError(getText(key, a1));
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param pos the position of the source
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     */
-    public void error(SourcePosition pos, String key, String a1, String a2) {
-        printError(pos, getText(key, a1, a2));
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     */
-    public void error(String key, String a1, String a2) {
-        printError(getText(key, a1, a2));
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param pos the position of the source
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     * @param a3 third argument to be replaced in the message.
-     */
-    public void error(SourcePosition pos, String key, String a1, String a2, String a3) {
-        printError(pos, getText(key, a1, a2, a3));
-    }
-
-    /**
-     * Print error message, increment error count.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     * @param a3 third argument to be replaced in the message.
-     */
-    public void error(String key, String a1, String a2, String a3) {
-        printError(getText(key, a1, a2, a3));
+    public void error(String key, Object... args) {
+        printError(getText(key, args));
     }
 
     /**
@@ -283,87 +184,20 @@
      *
      * @param pos the position of the source
      * @param key selects message from resource
+     * @param args arguments to be replaced in the message.
      */
-    public void warning(SourcePosition pos, String key) {
-        printWarning(pos, getText(key));
+    public void warning(SourcePosition pos, String key, Object... args) {
+        printWarning(pos, getText(key, args));
     }
 
     /**
      * Print warning message, increment warning count.
      *
      * @param key selects message from resource
+     * @param args arguments to be replaced in the message.
      */
-    public void warning(String key) {
-        printWarning(getText(key));
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param pos the position of the source
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     */
-    public void warning(SourcePosition pos, String key, String a1) {
-        printWarning(pos, getText(key, a1));
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     */
-    public void warning(String key, String a1) {
-        printWarning(getText(key, a1));
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param pos the position of the source
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     */
-    public void warning(SourcePosition pos, String key, String a1, String a2) {
-        printWarning(pos, getText(key, a1, a2));
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     */
-    public void warning(String key, String a1, String a2) {
-        printWarning(getText(key, a1, a2));
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param pos the position of the source
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     * @param a3 third argument to be replaced in the message.
-     */
-    public void warning(SourcePosition pos, String key, String a1, String a2, String a3) {
-        printWarning(pos, getText(key, a1, a2, a3));
-    }
-
-    /**
-     * Print warning message, increment warning count.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     * @param a3 third argument to be replaced in the message.
-     */
-    public void warning(String key, String a1, String a2, String a3) {
-        printWarning(getText(key, a1, a2, a3));
+    public void warning(String key, Object... args) {
+        printWarning(getText(key, args));
     }
 
     /**
@@ -371,85 +205,19 @@
      *
      * @param pos the position of the source
      * @param key selects message from resource
+     * @param args arguments to be replaced in the message.
      */
-    public void notice(SourcePosition pos, String key) {
-        printNotice(pos, getText(key));
+    public void notice(SourcePosition pos, String key, Object... args) {
+        printNotice(pos, getText(key, args));
     }
 
     /**
      * Print a message.
      *
      * @param key selects message from resource
+     * @param args arguments to be replaced in the message.
      */
-    public void notice(String key) {
-        printNotice(getText(key));
-    }
-
-    /**
-     * Print a message.
-     * @param pos the position of the source
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     */
-    public void notice(SourcePosition pos, String key, String a1) {
-        printNotice(pos, getText(key, a1));
-    }
-
-    /**
-     * Print a message.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     */
-    public void notice(String key, String a1) {
-        printNotice(getText(key, a1));
-    }
-
-    /**
-     * Print a message.
-     *
-     * @param pos the position of the source
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     */
-    public void notice(SourcePosition pos, String key, String a1, String a2) {
-        printNotice(pos, getText(key, a1, a2));
-    }
-
-    /**
-     * Print a message.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     */
-    public void notice(String key, String a1, String a2) {
-        printNotice(getText(key, a1, a2));
-    }
-
-    /**
-     * Print a message.
-     *
-     * @param pos the position of the source
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     * @param a3 third argument to be replaced in the message.
-     */
-    public void notice(SourcePosition pos, String key, String a1, String a2, String a3) {
-        printNotice(pos, getText(key, a1, a2, a3));
-    }
-
-    /**
-     * Print a message.
-     *
-     * @param key selects message from resource
-     * @param a1 first argument to be replaced in the message.
-     * @param a2 second argument to be replaced in the message.
-     * @param a3 third argument to be replaced in the message.
-     */
-    public void notice(String key, String a1, String a2, String a3) {
-        printNotice(getText(key, a1, a2, a3));
+    public void notice(String key, Object... args) {
+        printNotice(getText(key, args));
     }
 }
--- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java	Tue Jun 22 18:30:16 2010 -0700
@@ -25,10 +25,12 @@
 
 package com.sun.tools.doclets.internal.toolkit.util;
 
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.javadoc.*;
 import java.io.*;
 import java.util.*;
+import javax.tools.FileObject;
+
+import com.sun.javadoc.*;
+import com.sun.tools.doclets.internal.toolkit.*;
 
 /**
  * Converts Java Source Code to HTML.
@@ -123,16 +125,27 @@
         if (cd == null || outputdir == null) {
             return;
         }
-        File file;
-        SourcePosition sp = cd.position();
-        if (sp == null || (file = sp.file()) == null) {
-            return;
-        }
         try {
+            SourcePosition sp = cd.position();
+            if (sp == null)
+                return;
+            Reader r;
+            // temp hack until we can update SourcePosition API.
+            if (sp instanceof com.sun.tools.javadoc.SourcePositionImpl) {
+                FileObject fo = ((com.sun.tools.javadoc.SourcePositionImpl) sp).fileObject();
+                if (fo == null)
+                    return;
+                r = fo.openReader(true);
+            } else {
+                File file = sp.file();
+                if (file == null)
+                    return;
+                r = new FileReader(file);
+            }
+            LineNumberReader reader = new LineNumberReader(r);
             int lineno = 1;
             String line;
             StringBuffer output = new StringBuffer();
-            LineNumberReader reader = new LineNumberReader(new FileReader(file));
             try {
                 while ((line = reader.readLine()) != null) {
                     output.append(formatLine(line, configuration.sourcetab, lineno));
@@ -260,12 +273,12 @@
      * @param docs the array of <code>Doc</code>s to add anchors for.
      * @param hash the <code>HashMap</code> to add to.
      */
-    protected static void addToHash(Doc[] docs, HashMap hash) {
+    protected static void addToHash(Doc[] docs, HashMap<Integer,String> hash) {
         if(docs == null) {
             return;
         }
         for(int i = 0; i < docs.length; i++) {
-            hash.put(new Integer(docs[i].position().line()), getAnchor(docs[i]));
+            hash.put(docs[i].position().line(), getAnchor(docs[i]));
         }
     }
 
--- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java	Tue Jun 22 18:30:16 2010 -0700
@@ -25,10 +25,11 @@
 
 package com.sun.tools.doclets.internal.toolkit.util;
 
+import java.io.*;
+import java.util.*;
+
 import com.sun.javadoc.*;
 import com.sun.tools.doclets.internal.toolkit.*;
-import java.util.*;
-import java.io.*;
 
 /**
  * Utilities Class for Doclets.
@@ -579,7 +580,7 @@
      * @param docencoding Encoding to be used for this file.
      * @exception IOException Exception raised by the FileWriter is passed on
      * to next level.
-     * @exception UnSupportedEncodingException Exception raised by the
+     * @exception UnsupportedEncodingException Exception raised by the
      * OutputStreamWriter is passed on to next level.
      * @return Writer Writer for the file getting generated.
      * @see java.io.FileOutputStream
@@ -598,9 +599,7 @@
             fos = new FileOutputStream(filename);
         }
         if (docencoding == null) {
-            OutputStreamWriter oswriter = new OutputStreamWriter(fos);
-            docencoding = oswriter.getEncoding();
-            return oswriter;
+            return new OutputStreamWriter(fos);
         } else {
             return new OutputStreamWriter(fos, docencoding);
         }
--- a/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Tue Jun 22 18:30:16 2010 -0700
@@ -42,6 +42,7 @@
 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	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/api/JavacTool.java	Tue Jun 22 18:30:16 2010 -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	Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.CharsetDecoder;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.tools.FileObject;
+import javax.tools.JavaFileObject;
+
+import static javax.tools.JavaFileObject.Kind.*;
+
+import com.sun.tools.javac.util.BaseFileManager;
+
+/**
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+*/
+public abstract class BaseFileObject implements JavaFileObject {
+    protected BaseFileObject(JavacFileManager fileManager) {
+        this.fileManager = fileManager;
+    }
+
+    /** Return a short name for the object, such as for use in raw diagnostics
+     */
+    public abstract String getShortName();
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + getName() + "]";
+    }
+
+    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();
+    }
+
+    protected abstract String inferBinaryName(Iterable<? extends File> path);
+
+    protected static JavaFileObject.Kind getKind(String filename) {
+        return BaseFileManager.getKind(filename);
+    }
+
+    protected static String removeExtension(String fileName) {
+        int lastDot = fileName.lastIndexOf(".");
+        return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
+    }
+
+    protected static URI createJarUri(File jarFile, String entryName) {
+        URI jarURI = jarFile.toURI().normalize();
+        String separator = entryName.startsWith("/") ? "!" : "!/";
+        try {
+            // The jar URI convention appears to be not to re-encode the jarURI
+            return new URI("jar:" + jarURI + separator + entryName);
+        } catch (URISyntaxException e) {
+            throw new CannotCreateUriError(jarURI + separator + entryName, e);
+        }
+    }
+
+    /** Used when URLSyntaxException is thrown unexpectedly during
+     *  implementations of (Base)FileObject.toURI(). */
+    protected static class CannotCreateUriError extends Error {
+        private static final long serialVersionUID = 9101708840997613546L;
+        public CannotCreateUriError(String value, Throwable cause) {
+            super(value, cause);
+        }
+    }
+
+    /** Return the last component of a presumed hierarchical URI.
+     *  From the scheme specific part of the URI, it returns the substring
+     *  after the last "/" if any, or everything if no "/" is found.
+     */
+    public static String getSimpleName(FileObject fo) {
+        URI uri = fo.toUri();
+        String s = uri.getSchemeSpecificPart();
+        return s.substring(s.lastIndexOf("/") + 1); // safe when / not found
+
+    }
+
+    // force subtypes to define equals
+    @Override
+    public abstract boolean equals(Object other);
+
+    // force subtypes to define hashCode
+    @Override
+    public abstract int hashCode();
+
+    /** The file manager that created this JavaFileObject. */
+    protected final JavacFileManager fileManager;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java	Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import com.sun.tools.javac.util.Context;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Caching implementation of FSInfo.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class CacheFSInfo extends FSInfo {
+
+    /**
+     * Register a Context.Factory to create a singleton CacheFSInfo.
+     */
+    public static void preRegister(final Context context) {
+        context.put(FSInfo.class, new Context.Factory<FSInfo>() {
+            public FSInfo make() {
+                if (singleton == null)
+                    singleton = new CacheFSInfo();
+                context.put(FSInfo.class, singleton);
+                return singleton;
+            }
+        });
+    }
+
+    static CacheFSInfo singleton;
+
+    public void clearCache() {
+        cache.clear();
+    }
+
+    @Override
+    public File getCanonicalFile(File file) {
+        Entry e = getEntry(file);
+        return e.canonicalFile;
+    }
+
+    @Override
+    public boolean exists(File file) {
+        Entry e = getEntry(file);
+        return e.exists;
+    }
+
+    @Override
+    public boolean isDirectory(File file) {
+        Entry e = getEntry(file);
+        return e.isDirectory;
+    }
+
+    @Override
+    public boolean isFile(File file) {
+        Entry e = getEntry(file);
+        return e.isFile;
+    }
+
+    @Override
+    public List<File> getJarClassPath(File file) throws IOException {
+        // don't bother to lock the cache, because it is thread-safe, and
+        // because the worst that can happen would be to create two identical
+        // jar class paths together and have one overwrite the other.
+        Entry e = getEntry(file);
+        if (e.jarClassPath == null)
+            e.jarClassPath = super.getJarClassPath(file);
+        return e.jarClassPath;
+    }
+
+    private Entry getEntry(File file) {
+        // don't bother to lock the cache, because it is thread-safe, and
+        // because the worst that can happen would be to create two identical
+        // entries together and have one overwrite the other.
+        Entry e = cache.get(file);
+        if (e == null) {
+            e = new Entry();
+            e.canonicalFile = super.getCanonicalFile(file);
+            e.exists = super.exists(file);
+            e.isDirectory = super.isDirectory(file);
+            e.isFile = super.isFile(file);
+            cache.put(file, e);
+        }
+        return e;
+    }
+
+    // could also be a Map<File,SoftReference<Entry>> ?
+    private Map<File,Entry> cache = new ConcurrentHashMap<File,Entry>();
+
+    private static class Entry {
+        File canonicalFile;
+        boolean exists;
+        boolean isFile;
+        boolean isDirectory;
+        List<File> jarClassPath;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/FSInfo.java	Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,94 @@
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import com.sun.tools.javac.util.Context;
+
+/**
+ * Get meta-info about files. Default direct (non-caching) implementation.
+ * @see CacheFSInfo
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class FSInfo {
+
+    /** Get the FSInfo instance for this context.
+     *  @param context the context
+     *  @return the Paths instance for this context
+     */
+    public static FSInfo instance(Context context) {
+        FSInfo instance = context.get(FSInfo.class);
+        if (instance == null)
+            instance = new FSInfo();
+        return instance;
+    }
+
+    protected FSInfo() {
+    }
+
+    protected FSInfo(Context context) {
+        context.put(FSInfo.class, this);
+    }
+
+    public File getCanonicalFile(File file) {
+        try {
+            return file.getCanonicalFile();
+        } catch (IOException e) {
+            return file.getAbsoluteFile();
+        }
+    }
+
+    public boolean exists(File file) {
+        return file.exists();
+    }
+
+    public boolean isDirectory(File file) {
+        return file.isDirectory();
+    }
+
+    public boolean isFile(File file) {
+        return file.isFile();
+    }
+
+    public List<File> getJarClassPath(File file) throws IOException {
+        String parent = file.getParent();
+        JarFile jarFile = new JarFile(file);
+        try {
+            Manifest man = jarFile.getManifest();
+            if (man == null)
+                return Collections.emptyList();
+
+            Attributes attr = man.getMainAttributes();
+            if (attr == null)
+                return Collections.emptyList();
+
+            String path = attr.getValue(Attributes.Name.CLASS_PATH);
+            if (path == null)
+                return Collections.emptyList();
+
+            List<File> list = new ArrayList<File>();
+
+            for (StringTokenizer st = new StringTokenizer(path); st.hasMoreTokens(); ) {
+                String elt = st.nextToken();
+                File f = (parent == null ? new File(elt) : new File(parent, elt));
+                list.add(f);
+            }
+
+            return list;
+        } finally {
+            jarFile.close();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,860 @@
+/*
+ * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+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.file.RelativePath.RelativeFile;
+import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
+import com.sun.tools.javac.main.OptionName;
+import com.sun.tools.javac.util.BaseFileManager;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+
+import static javax.tools.StandardLocation.*;
+import static com.sun.tools.javac.main.OptionName.*;
+
+/**
+ * This class provides access to the source, class and other files
+ * used by the compiler and related tools.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class JavacFileManager extends BaseFileManager implements StandardJavaFileManager {
+
+    boolean useZipFileIndex;
+
+    public static char[] toArray(CharBuffer buffer) {
+        if (buffer.hasArray())
+            return ((CharBuffer)buffer.compact().flip()).array();
+        else
+            return buffer.toString().toCharArray();
+    }
+
+    /** Encapsulates knowledge of paths
+     */
+    private Paths paths;
+
+    private FSInfo fsInfo;
+
+    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;
+
+    /**
+     * 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) {
+        super(charset);
+        if (register)
+            context.put(JavaFileManager.class, this);
+        setContext(context);
+    }
+
+    /**
+     * Set the context for JavacFileManager.
+     */
+    @Override
+    public void setContext(Context context) {
+        super.setContext(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);
+        }
+
+        fsInfo = FSInfo.instance(context);
+
+        useZipFileIndex = System.getProperty("useJavaUtilZip") == null;// TODO: options.get("useJavaUtilZip") == 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(this, 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)));
+    }
+
+    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);
+    }
+
+    /**
+     * Insert all files in subdirectory `subdirectory' of `directory' which end
+     * in one of the extensions in `extensions' into packageSym.
+     */
+    private void listDirectory(File directory,
+                               RelativeDirectory subdirectory,
+                               Set<JavaFileObject.Kind> fileKinds,
+                               boolean recurse,
+                               ListBuffer<JavaFileObject> l) {
+        Archive archive = archives.get(directory);
+
+        boolean isFile = fsInfo.isFile(directory);
+
+        if (archive != null || isFile) {
+            if (archive == null) {
+                try {
+                    archive = openArchive(directory);
+                } catch (IOException ex) {
+                    log.error("error.reading.file",
+                       directory, getMessage(ex));
+                    return;
+                }
+            }
+
+            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 (RelativeDirectory s: archive.getSubdirectories()) {
+                    if (subdirectory.contains(s)) {
+                        // Because the archive map is a flat list of directories,
+                        // the enclosing loop will pick up all child subdirectories.
+                        // Therefore, there is no need to recurse deeper.
+                        listDirectory(directory, s, fileKinds, false, l);
+                    }
+                }
+            }
+        } else {
+            File d = subdirectory.getFile(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,
+                                      new RelativeDirectory(subdirectory, fname),
+                                      fileKinds,
+                                      recurse,
+                                      l);
+                    }
+                } else {
+                    if (isValidFile(fname, fileKinds)) {
+                        JavaFileObject fe =
+                            new RegularFileObject(this, fname, new File(d, fname));
+                        l.append(fe);
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
+        JavaFileObject.Kind kind = getKind(s);
+        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, RelativePath 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.path.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] == '/') 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(RelativePath name);
+
+        JavaFileObject getFileObject(RelativeDirectory subdirectory, String file);
+
+        List<String> getFiles(RelativeDirectory subdirectory);
+
+        Set<RelativeDirectory> getSubdirectories();
+    }
+
+    public class MissingArchive implements Archive {
+        final File zipFileName;
+        public MissingArchive(File name) {
+            zipFileName = name;
+        }
+        public boolean contains(RelativePath name) {
+            return false;
+        }
+
+        public void close() {
+        }
+
+        public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
+            return null;
+        }
+
+        public List<String> getFiles(RelativeDirectory subdirectory) {
+            return List.nil();
+        }
+
+        public Set<RelativeDirectory> getSubdirectories() {
+            return Collections.emptySet();
+        }
+
+        @Override
+        public String toString() {
+            return "MissingArchive[" + zipFileName + "]";
+        }
+    }
+
+    /** A directory of zip files already opened.
+     */
+    Map<File, Archive> archives = new HashMap<File,Archive>();
+
+    private static final String[] symbolFileLocation = { "lib", "ct.sym" };
+    private static final RelativeDirectory symbolFilePrefix
+            = new RelativeDirectory("META-INF/sym/rt.jar/");
+
+    /** 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(this, zdir);
+                    } else {
+                        archive = new ZipFileIndexArchive(this,
+                                ZipFileIndex.getZipFileIndex(zipFileName,
+                                    null,
+                                    usePreindexedCache,
+                                    preindexCacheLocation,
+                                    options.get("writezipindexfiles") != null));
+                    }
+                }
+                else {
+                    if (!useZipFileIndex) {
+                        archive = new SymbolArchive(this, origZipFileName, zdir, symbolFilePrefix);
+                    }
+                    else {
+                        archive = new ZipFileIndexArchive(this,
+                                ZipFileIndex.getZipFileIndex(zipFileName,
+                                    symbolFilePrefix,
+                                    usePreindexedCache,
+                                    preindexCacheLocation,
+                                    options.get("writezipindexfiles") != null));
+                    }
+                }
+            } catch (FileNotFoundException ex) {
+                archive = new MissingArchive(zipFileName);
+            } catch (IOException ex) {
+                if (zipFileName.exists())
+                    log.error("error.reading.file", zipFileName, getMessage(ex));
+                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 String defaultEncodingName;
+    private String getDefaultEncodingName() {
+        if (defaultEncodingName == null) {
+            defaultEncodingName =
+                new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
+        }
+        return defaultEncodingName;
+    }
+
+    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 getClassLoader(lb.toArray(new URL[lb.size()]));
+    }
+
+    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();
+        RelativeDirectory subdirectory = RelativeDirectory.forPackage(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) {
+            return null;
+        }
+
+        if (file instanceof BaseFileObject) {
+            return ((BaseFileObject) file).inferBinaryName(path);
+        } else
+            throw new IllegalArgumentException(file.getClass().getName());
+    }
+
+    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 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, RelativeFile.forClass(className, kind));
+    }
+
+    public FileObject getFileForInput(Location location,
+                                      String packageName,
+                                      String relativeName)
+        throws IOException
+    {
+        nullCheck(location);
+        // validatePackageName(packageName);
+        nullCheck(packageName);
+        if (!isRelativeUri(relativeName))
+            throw new IllegalArgumentException("Invalid relative name: " + relativeName);
+        RelativeFile name = packageName.length() == 0
+            ? new RelativeFile(relativeName)
+            : new RelativeFile(RelativeDirectory.forPackage(packageName), relativeName);
+        return getFileForInput(location, name);
+    }
+
+    private JavaFileObject getFileForInput(Location location, RelativeFile name) throws IOException {
+        Iterable<? extends File> path = getLocation(location);
+        if (path == null)
+            return null;
+
+        for (File dir: path) {
+            if (dir.isDirectory()) {
+                File f = name.getFile(dir);
+                if (f.exists())
+                    return new RegularFileObject(this, f);
+            } else {
+                Archive a = openArchive(dir);
+                if (a.contains(name)) {
+                    return a.getFileObject(name.dirname(), name.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, RelativeFile.forClass(className, kind), sibling);
+    }
+
+    public FileObject getFileForOutput(Location location,
+                                       String packageName,
+                                       String relativeName,
+                                       FileObject sibling)
+        throws IOException
+    {
+        nullCheck(location);
+        // validatePackageName(packageName);
+        nullCheck(packageName);
+        if (!isRelativeUri(relativeName))
+            throw new IllegalArgumentException("relativeName is invalid");
+        RelativeFile name = packageName.length() == 0
+            ? new RelativeFile(relativeName)
+            : new RelativeFile(RelativeDirectory.forPackage(packageName), relativeName);
+        return getFileForOutput(location, name, sibling);
+    }
+
+    private JavaFileObject getFileForOutput(Location location,
+                                            RelativeFile 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).file.getParentFile();
+                }
+                return new RegularFileObject(this, new File(siblingDir, fileName.basename()));
+            }
+        } 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 = fileName.getFile(dir); // null-safe
+        return new RegularFileObject(this, 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(this, 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 != '/';
+    }
+
+    // Convenience method
+    protected static boolean isRelativeUri(String u) {
+        try {
+            return isRelativeUri(new URI(u));
+        } catch (URISyntaxException e) {
+            return false;
+        }
+    }
+
+    /**
+     * 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 (isRelativeUri(result))
+                return result;
+        }
+        throw new IllegalArgumentException("Invalid relative path: " + file);
+    }
+
+    /**
+     * Get a detail message from an IOException.
+     * Most, but not all, instances of IOException provide a non-null result
+     * for getLocalizedMessage().  But some instances return null: in these
+     * cases, fallover to getMessage(), and if even that is null, return the
+     * name of the exception itself.
+     * @param e an IOException
+     * @return a string to include in a compiler diagnostic
+     */
+    public static String getMessage(IOException e) {
+        String s = e.getLocalizedMessage();
+        if (s != null)
+            return s;
+        s = e.getMessage();
+        if (s != null)
+            return s;
+        return e.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/Paths.java	Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.StringTokenizer;
+import java.util.zip.ZipFile;
+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.ListBuffer;
+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 supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class 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;
+
+    /** Access to (possibly cached) file info */
+    private FSInfo fsInfo;
+
+    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);
+        fsInfo = FSInfo.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);
+    }
+
+    /**
+     * Split a path into its elements. Empty path elements will be ignored.
+     * @param path The path to be split
+     * @return The elements of the path
+     */
+    private static Iterable<File> getPathEntries(String path) {
+        return getPathEntries(path, null);
+    }
+
+    /**
+     * Split a path into its elements. If emptyPathDefault is not null, all
+     * empty elements in the path, including empty elements at either end of
+     * the path, will be replaced with the value of emptyPathDefault.
+     * @param path The path to be split
+     * @param emptyPathDefault The value to substitute for empty path elements,
+     *  or null, to ignore empty path elements
+     * @return The elements of the path
+     */
+    private static Iterable<File> getPathEntries(String path, File emptyPathDefault) {
+        ListBuffer<File> entries = new ListBuffer<File>();
+        int start = 0;
+        while (start <= path.length()) {
+            int sep = path.indexOf(File.pathSeparatorChar, start);
+            if (sep == -1)
+                sep = path.length();
+            if (start < sep)
+                entries.add(new File(path.substring(start, sep)));
+            else if (emptyPathDefault != null)
+                entries.add(emptyPathDefault);
+            start = sep + 1;
+        }
+        return entries;
+    }
+
+    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 File emptyPathDefault = null;
+
+        public Path emptyPathDefault(File x) {
+            emptyPathDefault = x;
+            return this;
+        }
+
+        public Path() { super(); }
+
+        public Path addDirectories(String dirs, boolean warn) {
+            if (dirs != null)
+                for (File dir : getPathEntries(dirs))
+                    addDirectory(dir, warn);
+            return this;
+        }
+
+        public Path addDirectories(String dirs) {
+            return addDirectories(dirs, warn);
+        }
+
+        private void addDirectory(File dir, boolean warn) {
+            if (!dir.isDirectory()) {
+                if (warn)
+                    log.warning("dir.path.element.not.found", dir);
+                return;
+            }
+
+            File[] files = 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 (File file : getPathEntries(files, emptyPathDefault))
+                    addFile(file, warn);
+            return this;
+        }
+
+        public Path addFiles(String files) {
+            return addFiles(files, warn);
+        }
+
+        public void addFile(File file, boolean warn) {
+            File canonFile = fsInfo.getCanonicalFile(file);
+            if (contains(file) || canonicalValues.contains(canonFile)) {
+                /* Discard duplicates and avoid infinite recursion */
+                return;
+            }
+
+            if (! fsInfo.exists(file)) {
+                /* No such file or directory exists */
+                if (warn)
+                    log.warning("path.element.not.found", file);
+            } else if (fsInfo.isFile(file)) {
+                /* 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(canonFile);
+
+            if (expandJarClassPaths && fsInfo.exists(file) && fsInfo.isFile(file))
+                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 {
+                for (File f: fsInfo.getJarClassPath(jarFile)) {
+                    addFile(f, warn);
+                }
+            } catch (IOException e) {
+                log.error("error.reading.file", jarFile, JavacFileManager.getMessage(e));
+            }
+        }
+    }
+
+    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 (File file : getPathEntries(files)) {
+                if (new File(file.getName()).equals(rt_jar))
+                    bootClassPathRtJar = file;
+            }
+        }
+
+        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(new File("."))  // 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 boolean isArchive(File file) {
+        String n = file.getName().toLowerCase();
+        return fsInfo.isFile(file)
+            && (n.endsWith(".jar") || n.endsWith(".zip"));
+    }
+
+    /**
+     * Utility method for converting a search path string to an array
+     * of directory and JAR file URLs.
+     *
+     * Note that this method is called by apt and the DocletInvoker.
+     *
+     * @param path the search path string
+     * @return the resulting array of directory and JAR file URLs
+     */
+    public static URL[] pathToURLs(String path) {
+        StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
+        URL[] urls = new URL[st.countTokens()];
+        int count = 0;
+        while (st.hasMoreTokens()) {
+            URL url = fileToURL(new File(st.nextToken()));
+            if (url != null) {
+                urls[count++] = url;
+            }
+        }
+        if (urls.length != count) {
+            URL[] tmp = new URL[count];
+            System.arraycopy(urls, 0, tmp, 0, count);
+            urls = tmp;
+        }
+        return urls;
+    }
+
+    /**
+     * Returns the directory or JAR file URL corresponding to the specified
+     * local file name.
+     *
+     * @param file the File object
+     * @return the resulting directory or JAR file URL, or null if unknown
+     */
+    private static URL fileToURL(File file) {
+        String name;
+        try {
+            name = file.getCanonicalPath();
+        } catch (IOException e) {
+            name = file.getAbsolutePath();
+        }
+        name = name.replace(File.separatorChar, '/');
+        if (!name.startsWith("/")) {
+            name = "/" + name;
+        }
+        // If the file does not exist, then assume that it's a directory
+        if (!file.isFile()) {
+            name = name + "/";
+        }
+        try {
+            return new URL("file", "", name);
+        } catch (MalformedURLException e) {
+            throw new IllegalArgumentException(file.toString());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java	Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.FileInputStream;
+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.Reference;
+import java.lang.ref.SoftReference;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import javax.tools.JavaFileObject;
+
+/**
+ * A subclass of JavaFileObject representing regular files.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+class RegularFileObject extends BaseFileObject {
+
+    /** Have the parent directories been created?
+     */
+    private boolean hasParents = false;
+    private String name;
+    final File file;
+    private Reference<File> absFileRef;
+
+    public RegularFileObject(JavacFileManager fileManager, File f) {
+        this(fileManager, f.getName(), f);
+    }
+
+    public RegularFileObject(JavacFileManager fileManager, String name, File f) {
+        super(fileManager);
+        if (f.isDirectory()) {
+            throw new IllegalArgumentException("directories not supported");
+        }
+        this.name = name;
+        this.file = f;
+    }
+
+    //@Override
+    public URI toUri() {
+        return file.toURI().normalize();
+    }
+
+    //@Override
+    public String getName() {
+        return file.getPath();
+    }
+
+    //@Override
+    public String getShortName() {
+        return name;
+    }
+
+    //@Override
+    public JavaFileObject.Kind getKind() {
+        return getKind(name);
+    }
+
+    //@Override
+    public InputStream openInputStream() throws IOException {
+        return new FileInputStream(file);
+    }
+
+    //@Override
+    public OutputStream openOutputStream() throws IOException {
+        ensureParentDirectoriesExist();
+        return new FileOutputStream(file);
+    }
+
+    //@Override
+    public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+        CharBuffer cb = fileManager.getCachedContent(this);
+        if (cb == null) {
+            InputStream in = new FileInputStream(file);
+            try {
+                ByteBuffer bb = fileManager.makeByteBuffer(in);
+                JavaFileObject prev = fileManager.log.useSource(this);
+                try {
+                    cb = fileManager.decode(bb, ignoreEncodingErrors);
+                } finally {
+                    fileManager.log.useSource(prev);
+                }
+                fileManager.recycleByteBuffer(bb);
+                if (!ignoreEncodingErrors) {
+                    fileManager.cache(this, cb);
+                }
+            } finally {
+                in.close();
+            }
+        }
+        return cb;
+    }
+
+    //@Override
+    public Writer openWriter() throws IOException {
+        ensureParentDirectoriesExist();
+        return new OutputStreamWriter(new FileOutputStream(file), fileManager.getEncodingName());
+    }
+
+    //@Override
+    public long getLastModified() {
+        return file.lastModified();
+    }
+
+    //@Override
+    public boolean delete() {
+        return file.delete();
+    }
+
+    //@Override
+    protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+        return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
+    }
+
+    //@Override
+    protected String inferBinaryName(Iterable<? extends File> path) {
+        String fPath = file.getPath();
+        //System.err.println("RegularFileObject " + file + " " +r.getPath());
+        for (File dir: path) {
+            //System.err.println("dir: " + dir);
+            String dPath = dir.getPath();
+            if (dPath.length() == 0)
+                dPath = System.getProperty("user.dir");
+            if (!dPath.endsWith(File.separator))
+                dPath += File.separator;
+            if (fPath.regionMatches(true, 0, dPath, 0, dPath.length())
+                && new File(fPath.substring(0, dPath.length())).equals(new File(dPath))) {
+                String relativeName = fPath.substring(dPath.length());
+                return removeExtension(relativeName).replace(File.separatorChar, '.');
+            }
+        }
+        return null;
+    }
+
+    //@Override
+    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 file.getCanonicalFile().getName().equals(n);
+            } catch (IOException e) {
+            }
+        }
+        return false;
+    }
+
+    private void ensureParentDirectoriesExist() throws IOException {
+        if (!hasParents) {
+            File parent = file.getParentFile();
+            if (parent != null && !parent.exists()) {
+                if (!parent.mkdirs()) {
+                    if (!parent.exists() || !parent.isDirectory()) {
+                        throw new IOException("could not create parent directories");
+                    }
+                }
+            }
+            hasParents = true;
+        }
+    }
+
+    /**
+     * Check if two file objects are equal.
+     * Two RegularFileObjects are equal if the absolute paths of the underlying
+     * files are equal.
+     */
+    //@Override
+    public boolean equals(Object other) {
+        if (this == other)
+            return true;
+
+        if (!(other instanceof RegularFileObject))
+            return false;
+
+        RegularFileObject o = (RegularFileObject) other;
+        return getAbsoluteFile().equals(o.getAbsoluteFile());
+    }
+
+    //@Override
+    public int hashCode() {
+        return getAbsoluteFile().hashCode();
+    }
+
+    private File getAbsoluteFile() {
+        File absFile = (absFileRef == null ? null : absFileRef.get());
+        if (absFile == null) {
+            absFile = file.getAbsoluteFile();
+            absFileRef = new SoftReference<File>(absFile);
+        }
+        return absFile;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/RelativePath.java	Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import javax.tools.JavaFileObject;
+
+/**
+ * Used to represent a platform-neutral path within a platform-specific
+ * container, such as a directory or zip file.
+ * Internally, the file separator is always '/'.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public abstract class RelativePath implements Comparable<RelativePath> {
+    /**
+     * @param p must use '/' as an internal separator
+     */
+    protected RelativePath(String p) {
+        path = p;
+    }
+
+    public abstract RelativeDirectory dirname();
+
+    public abstract String basename();
+
+    public File getFile(File directory) {
+        if (path.length() == 0)
+            return directory;
+        return new File(directory, path.replace('/', File.separatorChar));
+    }
+
+    public int compareTo(RelativePath other) {
+        return path.compareTo(other.path);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof RelativePath))
+            return false;
+         return path.equals(((RelativePath) other).path);
+    }
+
+    @Override
+    public int hashCode() {
+        return path.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "RelPath[" + path + "]";
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    protected final String path;
+
+    /**
+     * Used to represent a platform-neutral subdirectory within a platform-specific
+     * container, such as a directory or zip file.
+     * Internally, the file separator is always '/', and if the path is not empty,
+     * it always ends in a '/' as well.
+     */
+    public static class RelativeDirectory extends RelativePath {
+
+        static RelativeDirectory forPackage(CharSequence packageName) {
+            return new RelativeDirectory(packageName.toString().replace('.', '/'));
+        }
+
+        /**
+         * @param p must use '/' as an internal separator
+         */
+        public RelativeDirectory(String p) {
+            super(p.length() == 0 || p.endsWith("/") ? p : p + "/");
+        }
+
+        /**
+         * @param p must use '/' as an internal separator
+         */
+        public RelativeDirectory(RelativeDirectory d, String p) {
+            this(d.path + p);
+        }
+
+        @Override
+        public RelativeDirectory dirname() {
+            int l = path.length();
+            if (l == 0)
+                return this;
+            int sep = path.lastIndexOf('/', l - 2);
+            return new RelativeDirectory(path.substring(0, sep + 1));
+        }
+
+        @Override
+        public String basename() {
+            int l = path.length();
+            if (l == 0)
+                return path;
+            int sep = path.lastIndexOf('/', l - 2);
+            return path.substring(sep + 1, l - 1);
+        }
+
+        /**
+         * Return true if this subdirectory "contains" the other path.
+         * A subdirectory path does not contain itself.
+         **/
+        boolean contains(RelativePath other) {
+            return other.path.length() > path.length() && other.path.startsWith(path);
+        }
+
+        @Override
+        public String toString() {
+            return "RelativeDirectory[" + path + "]";
+        }
+    }
+
+    /**
+     * Used to represent a platform-neutral file within a platform-specific
+     * container, such as a directory or zip file.
+     * Internally, the file separator is always '/'. It never ends in '/'.
+     */
+    public static class RelativeFile extends RelativePath {
+        static RelativeFile forClass(CharSequence className, JavaFileObject.Kind kind) {
+            return new RelativeFile(className.toString().replace('.', '/') + kind.extension);
+        }
+
+        public RelativeFile(String p) {
+            super(p);
+            if (p.endsWith("/"))
+                throw new IllegalArgumentException(p);
+        }
+
+        /**
+         * @param p must use '/' as an internal separator
+         */
+        public RelativeFile(RelativeDirectory d, String p) {
+            this(d.path + p);
+        }
+
+        RelativeFile(RelativeDirectory d, RelativePath p) {
+            this(d, p.path);
+        }
+
+        @Override
+        public RelativeDirectory dirname() {
+            int sep = path.lastIndexOf('/');
+            return new RelativeDirectory(path.substring(0, sep + 1));
+        }
+
+        @Override
+        public String basename() {
+            int sep = path.lastIndexOf('/');
+            return path.substring(sep + 1);
+        }
+
+        ZipEntry getZipEntry(ZipFile zip) {
+            return zip.getEntry(path);
+        }
+
+        @Override
+        public String toString() {
+            return "RelativeFile[" + path + "]";
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/SymbolArchive.java	Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
+import com.sun.tools.javac.file.RelativePath.RelativeFile;
+import com.sun.tools.javac.util.List;
+
+/**
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+*/
+public class SymbolArchive extends ZipArchive {
+
+    final File origFile;
+    final RelativeDirectory prefix;
+
+    public SymbolArchive(JavacFileManager fileManager, File orig, ZipFile zdir, RelativeDirectory prefix) throws IOException {
+        super(fileManager, zdir, false);
+        this.origFile = orig;
+        this.prefix = prefix;
+        initMap();
+    }
+
+    @Override
+    void addZipEntry(ZipEntry entry) {
+        String name = entry.getName();
+        if (!name.startsWith(prefix.path)) {
+            return;
+        }
+        name = name.substring(prefix.path.length());
+        int i = name.lastIndexOf('/');
+        RelativeDirectory dirname = new RelativeDirectory(name.substring(0, i+1));
+        String basename = name.substring(i + 1);
+        if (basename.length() == 0) {
+            return;
+        }
+        List<String> list = map.get(dirname);
+        if (list == null)
+            list = List.nil();
+        list = list.prepend(basename);
+        map.put(dirname, list);
+    }
+
+    @Override
+    public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
+        RelativeDirectory prefix_subdir = new RelativeDirectory(prefix, subdirectory.path);
+        ZipEntry ze = new RelativeFile(prefix_subdir, file).getZipEntry(zfile);
+        return new SymbolFileObject(this, file, ze);
+    }
+
+    @Override
+    public String toString() {
+        return "SymbolArchive[" + zfile.getName() + "]";
+    }
+
+    /**
+     * A subclass of JavaFileObject representing zip entries in a symbol file.
+     */
+    public static class SymbolFileObject extends ZipFileObject {
+        protected SymbolFileObject(SymbolArchive zarch, String name, ZipEntry entry) {
+            super(zarch, name, entry);
+        }
+
+        @Override
+        protected String inferBinaryName(Iterable<? extends File> path) {
+            String entryName = entry.getName();
+            String prefix = ((SymbolArchive) zarch).prefix.path;
+            if (entryName.startsWith(prefix))
+                entryName = entryName.substring(prefix.length());
+            return removeExtension(entryName).replace('/', '.');
+        }
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/ZipArchive.java	Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.file.JavacFileManager.Archive;
+import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
+import com.sun.tools.javac.file.RelativePath.RelativeFile;
+import com.sun.tools.javac.util.List;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+
+/**
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class ZipArchive implements Archive {
+
+    public ZipArchive(JavacFileManager fm, ZipFile zfile) throws IOException {
+        this(fm, zfile, true);
+    }
+
+    protected ZipArchive(JavacFileManager fm, ZipFile zfile, boolean initMap) throws IOException {
+        this.fileManager = fm;
+        this.zfile = zfile;
+        this.map = new HashMap<RelativeDirectory,List<String>>();
+        if (initMap)
+            initMap();
+    }
+
+    protected void initMap() throws IOException {
+        for (Enumeration<? extends ZipEntry> e = zfile.entries(); e.hasMoreElements(); ) {
+            ZipEntry entry;
+            try {
+                entry = e.nextElement();
+            } catch (InternalError ex) {
+                IOException io = new IOException();
+                io.initCause(ex); // convenience constructors added in Mustang :-(
+                throw io;
+            }
+            addZipEntry(entry);
+        }
+    }
+
+    void addZipEntry(ZipEntry entry) {
+        String name = entry.getName();
+        int i = name.lastIndexOf('/');
+        RelativeDirectory dirname = new RelativeDirectory(name.substring(0, i+1));
+        String basename = name.substring(i+1);
+        if (basename.length() == 0)
+            return;
+        List<String> list = map.get(dirname);
+        if (list == null)
+            list = List.nil();
+        list = list.prepend(basename);
+        map.put(dirname, list);
+    }
+
+    public boolean contains(RelativePath name) {
+        RelativeDirectory dirname = name.dirname();
+        String basename = name.basename();
+        if (basename.length() == 0)
+            return false;
+        List<String> list = map.get(dirname);
+        return (list != null && list.contains(basename));
+    }
+
+    public List<String> getFiles(RelativeDirectory subdirectory) {
+        return map.get(subdirectory);
+    }
+
+    public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
+        ZipEntry ze = new RelativeFile(subdirectory, file).getZipEntry(zfile);
+        return new ZipFileObject(this, file, ze);
+    }
+
+    public Set<RelativeDirectory> getSubdirectories() {
+        return map.keySet();
+    }
+
+    public void close() throws IOException {
+        zfile.close();
+    }
+
+    @Override
+    public String toString() {
+        return "ZipArchive[" + zfile.getName() + "]";
+    }
+
+    private File getAbsoluteFile() {
+        File absFile = (absFileRef == null ? null : absFileRef.get());
+        if (absFile == null) {
+            absFile = new File(zfile.getName()).getAbsoluteFile();
+            absFileRef = new SoftReference<File>(absFile);
+        }
+        return absFile;
+    }
+
+    /**
+     * The file manager that created this archive.
+     */
+    protected JavacFileManager fileManager;
+    /**
+     * The index for the contents of this archive.
+     */
+    protected final Map<RelativeDirectory,List<String>> map;
+    /**
+     * The zip file for the archive.
+     */
+    protected final ZipFile zfile;
+    /**
+     * A reference to the absolute filename for the zip file for the archive.
+     */
+    protected Reference<File> absFileRef;
+
+    /**
+     * A subclass of JavaFileObject representing zip entries.
+     */
+    public static class ZipFileObject extends BaseFileObject {
+
+        private String name;
+        ZipArchive zarch;
+        ZipEntry entry;
+
+        protected ZipFileObject(ZipArchive zarch, String name, ZipEntry entry) {
+            super(zarch.fileManager);
+            this.zarch = zarch;
+            this.name = name;
+            this.entry = entry;
+        }
+
+        public URI toUri() {
+            File zipFile = new File(zarch.zfile.getName());
+            return createJarUri(zipFile, entry.getName());
+        }
+
+        //@Override
+        public String getName() {
+            return zarch.zfile.getName() + "(" + entry.getName() + ")";
+        }
+
+        //@Override
+        public String getShortName() {
+            return new File(zarch.zfile.getName()).getName() + "(" + entry + ")";
+        }
+
+        //@Override
+        public JavaFileObject.Kind getKind() {
+            return getKind(entry.getName());
+        }
+
+        //@Override
+        public InputStream openInputStream() throws IOException {
+            return zarch.zfile.getInputStream(entry);
+        }
+
+        //@Override
+        public OutputStream openOutputStream() throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        //@Override
+        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+            CharBuffer cb = fileManager.getCachedContent(this);
+            if (cb == null) {
+                InputStream in = zarch.zfile.getInputStream(entry);
+                try {
+                    ByteBuffer bb = fileManager.makeByteBuffer(in);
+                    JavaFileObject prev = fileManager.log.useSource(this);
+                    try {
+                        cb = fileManager.decode(bb, ignoreEncodingErrors);
+                    } finally {
+                        fileManager.log.useSource(prev);
+                    }
+                    fileManager.recycleByteBuffer(bb);
+                    if (!ignoreEncodingErrors) {
+                        fileManager.cache(this, cb);
+                    }
+                } finally {
+                    in.close();
+                }
+            }
+            return cb;
+        }
+
+        //@Override
+        public Writer openWriter() throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        //@Override
+        public long getLastModified() {
+            return entry.getTime();
+        }
+
+        //@Override
+        public boolean delete() {
+            throw new UnsupportedOperationException();
+        }
+
+        //@Override
+        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+            return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
+        }
+
+        //@Override
+        protected String inferBinaryName(Iterable<? extends File> path) {
+            String entryName = entry.getName();
+            return removeExtension(entryName).replace('/', '.');
+        }
+
+        //@Override
+        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);
+        }
+
+        /**
+         * Check if two file objects are equal.
+         * Two ZipFileObjects are equal if the absolute paths of the underlying
+         * zip files are equal and if the paths within those zip files are equal.
+         */
+        //@Override
+        public boolean equals(Object other) {
+            if (this == other)
+                return true;
+
+            if (!(other instanceof ZipFileObject))
+                return false;
+
+            ZipFileObject o = (ZipFileObject) other;
+            return zarch.getAbsoluteFile().equals(o.zarch.getAbsoluteFile())
+                    && name.equals(o.name);
+        }
+
+        //@Override
+        public int hashCode() {
+            return zarch.getAbsoluteFile().hashCode() + name.hashCode();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java	Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,1338 @@
+/*
+ * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+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;
+
+import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
+import com.sun.tools.javac.file.RelativePath.RelativeFile;
+
+/** 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.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class ZipFileIndex {
+    private static final String MIN_CHAR = String.valueOf(Character.MIN_VALUE);
+    private static final String MAX_CHAR = String.valueOf(Character.MAX_VALUE);
+
+    public final static long NOT_MODIFIED = Long.MIN_VALUE;
+
+    private static 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<RelativeDirectory, DirectoryEntry> directories = Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
+    private Set<RelativeDirectory> allDirs = Collections.<RelativeDirectory>emptySet();
+
+    // ZipFileIndex data entries
+    private File zipFile;
+    private Reference<File> absFileRef;
+    private long zipFileLastModified = NOT_MODIFIED;
+    private RandomAccessFile zipRandomFile;
+    private Entry[] entries;
+
+    private boolean readFromIndex = false;
+    private File zipIndexFile = null;
+    private boolean triedToReadIndex = false;
+    final RelativeDirectory symbolFilePrefix;
+    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;
+
+    private Map <String, SoftReference<RelativeDirectory>> relativeDirectoryCache =
+            new HashMap<String, SoftReference<RelativeDirectory>>();
+
+    /**
+     * 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,
+            RelativeDirectory symbolFilePrefix,
+            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, symbolFilePrefix, 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, RelativeDirectory symbolFilePrefix, boolean writeIndex,
+            boolean useCache, String cacheLocation) throws IOException {
+        this.zipFile = zipFile;
+        this.symbolFilePrefix = symbolFilePrefix;
+        this.symbolFilePrefixLength = (symbolFilePrefix == null ? 0 :
+            symbolFilePrefix.getPath().getBytes("UTF-8").length);
+        this.writeIndex = writeIndex;
+        this.usePreindexedCache = useCache;
+        this.preindexedCacheLocation = cacheLocation;
+
+        if (zipFile != null) {
+            this.zipFileLastModified = zipFile.lastModified();
+        }
+
+        // Validate integrity of the zip file
+        checkIndex();
+    }
+
+    public String toString() {
+        return "ZipFileIndex[" + 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.<RelativeDirectory, DirectoryEntry>emptyMap();
+        allDirs = Collections.<RelativeDirectory>emptySet();
+
+        try {
+            openFile();
+            long totalLength = zipRandomFile.length();
+            ZipDirectory directory = new ZipDirectory(zipRandomFile, 0L, totalLength, this);
+            directory.buildIndex();
+        } finally {
+            if (zipRandomFile != null) {
+                closeFile();
+            }
+        }
+
+        lastReferenceTimeStamp = System.currentTimeMillis();
+    }
+
+    private void openFile() throws FileNotFoundException {
+        if (zipRandomFile == null && zipFile != null) {
+            zipRandomFile = new RandomAccessFile(zipFile, "r");
+        }
+    }
+
+    private void cleanupState() {
+        // Make sure there is a valid but empty index if the file doesn't exist
+        entries = Entry.EMPTY_ARRAY;
+        directories = Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
+        zipFileLastModified = NOT_MODIFIED;
+        allDirs = Collections.<RelativeDirectory>emptySet();
+    }
+
+    public 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.
+     */
+    Entry getZipIndexEntry(RelativePath path) {
+        lock.lock();
+        try {
+            checkIndex();
+            DirectoryEntry de = directories.get(path.dirname());
+            String lookFor = path.basename();
+            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(RelativeDirectory path) {
+        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> getDirectories(RelativeDirectory path) {
+        lock.lock();
+        try {
+            checkIndex();
+
+            DirectoryEntry de = directories.get(path);
+            com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getDirectories();
+
+            if (ret == null) {
+                return com.sun.tools.javac.util.List.<String>nil();
+            }
+
+            return ret;
+        }
+        catch (IOException e) {
+            return com.sun.tools.javac.util.List.<String>nil();
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public Set<RelativeDirectory> getAllDirectories() {
+        lock.lock();
+        try {
+            checkIndex();
+            if (allDirs == Collections.EMPTY_SET) {
+                allDirs = new HashSet<RelativeDirectory>(directories.keySet());
+            }
+
+            return allDirs;
+        }
+        catch (IOException e) {
+            return Collections.<RelativeDirectory>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(RelativePath path) {
+        lock.lock();
+        try {
+            checkIndex();
+            return getZipIndexEntry(path) != null;
+        }
+        catch (IOException e) {
+            return false;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public boolean isDirectory(RelativePath path) throws IOException {
+        lock.lock();
+        try {
+            // The top level in a zip file is always a directory.
+            if (path.getPath().length() == 0) {
+                lastReferenceTimeStamp = System.currentTimeMillis();
+                return true;
+            }
+
+            checkIndex();
+            return directories.get(path) != null;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public long getLastModified(RelativeFile path) throws IOException {
+        lock.lock();
+        try {
+            Entry entry = getZipIndexEntry(path);
+            if (entry == null)
+                throw new FileNotFoundException();
+            return entry.getLastModified();
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public int length(RelativeFile path) throws IOException {
+        lock.lock();
+        try {
+            Entry entry = getZipIndexEntry(path);
+            if (entry == null)
+                throw new FileNotFoundException();
+
+            if (entry.isDir) {
+                return 0;
+            }
+
+            byte[] header = getHeader(entry);
+            // entry is not compressed?
+            if (get2ByteLittleEndian(header, 8) == 0) {
+                return entry.compressedSize;
+            } else {
+                return entry.size;
+            }
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public byte[] read(RelativeFile path) throws IOException {
+        lock.lock();
+        try {
+            Entry entry = getZipIndexEntry(path);
+            if (entry == null)
+                throw new FileNotFoundException("Path not found in ZIP: " + path.path);
+            return read(entry);
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    byte[] read(Entry entry) throws IOException {
+        lock.lock();
+        try {
+            openFile();
+            byte[] result = readBytes(entry);
+            closeFile();
+            return result;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    public int read(RelativeFile path, byte[] buffer) throws IOException {
+        lock.lock();
+        try {
+            Entry entry = getZipIndexEntry(path);
+            if (entry == null)
+                throw new FileNotFoundException();
+            return read(entry, buffer);
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    int read(Entry entry, byte[] buffer)
+            throws IOException {
+        lock.lock();
+        try {
+            int result = readBytes(entry, buffer);
+            return result;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    private byte[] readBytes(Entry entry) throws IOException {
+        byte[] header = getHeader(entry);
+        int csize = entry.compressedSize;
+        byte[] cbuf = new byte[csize];
+        zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
+        zipRandomFile.readFully(cbuf, 0, csize);
+
+        // is this compressed - offset 8 in the ZipEntry header
+        if (get2ByteLittleEndian(header, 8) == 0)
+            return cbuf;
+
+        int size = entry.size;
+        byte[] buf = new byte[size];
+        if (inflate(cbuf, buf) != size)
+            throw new ZipException("corrupted zip file");
+
+        return buf;
+    }
+
+    /**
+     *
+     */
+    private int readBytes(Entry entry, byte[] buffer) throws IOException {
+        byte[] header = getHeader(entry);
+
+        // entry is not compressed?
+        if (get2ByteLittleEndian(header, 8) == 0) {
+            zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
+            int offset = 0;
+            int size = buffer.length;
+            while (offset < size) {
+                int count = zipRandomFile.read(buffer, offset, size - offset);
+                if (count == -1)
+                    break;
+                offset += count;
+            }
+            return entry.size;
+        }
+
+        int csize = entry.compressedSize;
+        byte[] cbuf = new byte[csize];
+        zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
+        zipRandomFile.readFully(cbuf, 0, csize);
+
+        int count = inflate(cbuf, buffer);
+        if (count == -1)
+            throw new ZipException("corrupted zip file");
+
+        return entry.size;
+    }
+
+    //----------------------------------------------------------------------------
+    // Zip utilities
+    //----------------------------------------------------------------------------
+
+    private byte[] getHeader(Entry entry) throws IOException {
+        zipRandomFile.seek(entry.offset);
+        byte[] header = new byte[30];
+        zipRandomFile.readFully(header);
+        if (get4ByteLittleEndian(header, 0) != 0x04034b50)
+            throw new ZipException("corrupted zip file");
+        if ((get2ByteLittleEndian(header, 6) & 1) != 0)
+            throw new ZipException("encrypted zip file"); // offset 6 in the header of the ZipFileEntry
+        return header;
+    }
+
+  /*
+   * Inflate using the java.util.zip.Inflater class
+   */
+    private 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 RelativeDirectory lastDir;
+        private int lastStart;
+        private int lastLen;
+
+        byte[] zipDir;
+        RandomAccessFile zipRandomFile = null;
+        ZipFileIndex zipFileIndex = null;
+
+        public ZipDirectory(RandomAccessFile zipRandomFile, long start, long end, ZipFileIndex index) throws IOException {
+            this.zipRandomFile = zipRandomFile;
+            this.zipFileIndex = index;
+
+            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);
+
+            // Add each of the files
+            if (entryCount > 0) {
+                directories = new HashMap<RelativeDirectory, DirectoryEntry>();
+                ArrayList<Entry> entryList = new ArrayList<Entry>();
+                int pos = 2;
+                for (int i = 0; i < entryCount; i++) {
+                    pos = readEntry(pos, entryList, directories);
+                }
+
+                // Add the accumulated dirs into the same list
+                for (RelativeDirectory d: directories.keySet()) {
+                    // use shared RelativeDirectory objects for parent dirs
+                    RelativeDirectory parent = getRelativeDirectory(d.dirname().getPath());
+                    String file = d.basename();
+                    Entry zipFileIndexEntry = new Entry(parent, file);
+                    zipFileIndexEntry.isDir = true;
+                    entryList.add(zipFileIndexEntry);
+                }
+
+                entries = entryList.toArray(new Entry[entryList.size()]);
+                Arrays.sort(entries);
+            } else {
+                cleanupState();
+            }
+        }
+
+        private int readEntry(int pos, List<Entry> entryList,
+                Map<RelativeDirectory, DirectoryEntry> directories) throws IOException {
+            if (get4ByteLittleEndian(zipDir, pos) != 0x02014b50) {
+                throw new ZipException("cannot read zip file entry");
+            }
+
+            int dirStart = pos + 46;
+            int fileStart = dirStart;
+            int fileEnd = fileStart + get2ByteLittleEndian(zipDir, pos + 28);
+
+            if (zipFileIndex.symbolFilePrefixLength != 0 &&
+                    ((fileEnd - fileStart) >= symbolFilePrefixLength)) {
+                dirStart += zipFileIndex.symbolFilePrefixLength;
+               fileStart += zipFileIndex.symbolFilePrefixLength;
+            }
+            // Force any '\' to '/'. Keep the position of the last separator.
+            for (int index = fileStart; index < fileEnd; index++) {
+                byte nextByte = zipDir[index];
+                if (nextByte == (byte)'\\') {
+                    zipDir[index] = (byte)'/';
+                    fileStart = index + 1;
+                } else if (nextByte == (byte)'/') {
+                    fileStart = index + 1;
+                }
+            }
+
+            RelativeDirectory directory = null;
+            if (fileStart == dirStart)
+                directory = getRelativeDirectory("");
+            else if (lastDir != null && lastLen == fileStart - dirStart - 1) {
+                int index = lastLen - 1;
+                while (zipDir[lastStart + index] == zipDir[dirStart + index]) {
+                    if (index == 0) {
+                        directory = lastDir;
+                        break;
+                    }
+                    index--;
+                }
+            }
+
+            // Sub directories
+            if (directory == null) {
+                lastStart = dirStart;
+                lastLen = fileStart - dirStart - 1;
+
+                directory = getRelativeDirectory(new String(zipDir, dirStart, lastLen, "UTF-8"));
+                lastDir = directory;
+
+                // Enter also all the parent directories
+                RelativeDirectory tempDirectory = directory;
+
+                while (directories.get(tempDirectory) == null) {
+                    directories.put(tempDirectory, new DirectoryEntry(tempDirectory, zipFileIndex));
+                    if (tempDirectory.path.indexOf("/") == tempDirectory.path.length() - 1)
+                        break;
+                    else {
+                        // use shared RelativeDirectory objects for parent dirs
+                        tempDirectory = getRelativeDirectory(tempDirectory.dirname().getPath());
+                    }
+                }
+            }
+            else {
+                if (directories.get(directory) == null) {
+                    directories.put(directory, new DirectoryEntry(directory, zipFileIndex));
+                }
+            }
+
+            // For each dir create also a file
+            if (fileStart != fileEnd) {
+                Entry entry = new Entry(directory,
+                        new String(zipDir, fileStart, fileEnd - fileStart, "UTF-8"));
+
+                entry.setNativeTime(get4ByteLittleEndian(zipDir, pos + 12));
+                entry.compressedSize = get4ByteLittleEndian(zipDir, pos + 20);
+                entry.size = get4ByteLittleEndian(zipDir, pos + 24);
+                entry.offset = get4ByteLittleEndian(zipDir, pos + 42);
+                entryList.add(entry);
+            }
+
+            return pos + 46 +
+                    get2ByteLittleEndian(zipDir, pos + 28) +
+                    get2ByteLittleEndian(zipDir, pos + 30) +
+                    get2ByteLittleEndian(zipDir, pos + 32);
+        }
+    }
+
+    /**
+     * Returns the last modified timestamp of a zip file.
+     * @return long
+     */
+    public long getZipFileLastModified() throws IOException {
+        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 RelativeDirectory dirName;
+
+        private com.sun.tools.javac.util.List<String> zipFileEntriesFiles = com.sun.tools.javac.util.List.<String>nil();
+        private com.sun.tools.javac.util.List<String> zipFileEntriesDirectories = com.sun.tools.javac.util.List.<String>nil();
+        private com.sun.tools.javac.util.List<Entry>  zipFileEntries = com.sun.tools.javac.util.List.<Entry>nil();
+
+        private List<Entry> entries = new ArrayList<Entry>();
+
+        private ZipFileIndex zipFileIndex;
+
+        private int numEntries;
+
+        DirectoryEntry(RelativeDirectory dirName, ZipFileIndex index) {
+            filesInited = false;
+            directoriesInited = false;
+            entriesInited = false;
+
+            this.dirName = dirName;
+            this.zipFileIndex = index;
+        }
+
+        private com.sun.tools.javac.util.List<String> getFiles() {
+            if (!filesInited) {
+                initEntries();
+                for (Entry e : entries) {
+                    if (!e.isDir) {
+                        zipFileEntriesFiles = zipFileEntriesFiles.append(e.name);
+                    }
+                }
+                filesInited = true;
+            }
+            return zipFileEntriesFiles;
+        }
+
+        private com.sun.tools.javac.util.List<String> getDirectories() {
+            if (!directoriesInited) {
+                initEntries();
+                for (Entry e : entries) {
+                    if (e.isDir) {
+                        zipFileEntriesDirectories = zipFileEntriesDirectories.append(e.name);
+                    }
+                }
+                directoriesInited = true;
+            }
+            return zipFileEntriesDirectories;
+        }
+
+        private com.sun.tools.javac.util.List<Entry> getEntries() {
+            if (!zipFileEntriesInited) {
+                initEntries();
+                zipFileEntries = com.sun.tools.javac.util.List.nil();
+                for (Entry zfie : entries) {
+                    zipFileEntries = zipFileEntries.append(zfie);
+                }
+                zipFileEntriesInited = true;
+            }
+            return zipFileEntries;
+        }
+
+        private Entry getEntry(String rootName) {
+            initEntries();
+            int index = Collections.binarySearch(entries, new Entry(dirName, rootName));
+            if (index < 0) {
+                return null;
+            }
+
+            return entries.get(index);
+        }
+
+        private void initEntries() {
+            if (entriesInited) {
+                return;
+            }
+
+            if (!zipFileIndex.readFromIndex) {
+                int from = -Arrays.binarySearch(zipFileIndex.entries,
+                        new Entry(dirName, ZipFileIndex.MIN_CHAR)) - 1;
+                int to = -Arrays.binarySearch(zipFileIndex.entries,
+                        new Entry(dirName, MAX_CHAR)) - 1;
+
+                for (int i = from; i < to; i++) {
+                    entries.add(zipFileIndex.entries[i]);
+                }
+            } else {
+                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();
+
+                            Entry rfie = new Entry(dirName, eName);
+                            rfie.isDir = eIsDir;
+                            rfie.offset = eOffset;
+                            rfie.size = eSize;
+                            rfie.compressedSize = eCsize;
+                            rfie.javatime = eJavaTimestamp;
+                            entries.add(rfie);
+                        }
+                    } catch (Throwable t) {
+                        // Do nothing
+                    } finally {
+                        try {
+                            if (raf != null) {
+                                raf.close();
+                            }
+                        } catch (Throwable t) {
+                            // Do nothing
+                        }
+                    }
+                }
+            }
+
+            entriesInited = true;
+        }
+
+        List<Entry> getEntriesAsCollection() {
+            initEntries();
+
+            return entries;
+        }
+    }
+
+    private boolean readIndex() {
+        if (triedToReadIndex || !usePreindexedCache) {
+            return false;
+        }
+
+        boolean ret = false;
+        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<RelativeDirectory, DirectoryEntry>();
+                    int numDirs = raf.readInt();
+                    for (int nDirs = 0; nDirs < numDirs; nDirs++) {
+                        int dirNameBytesLen = raf.readInt();
+                        byte [] dirNameBytes = new byte[dirNameBytesLen];
+                        raf.read(dirNameBytes);
+
+                        RelativeDirectory dirNameStr = getRelativeDirectory(new String(dirNameBytes, "UTF-8"));
+                        DirectoryEntry de = new DirectoryEntry(dirNameStr, this);
+                        de.numEntries = raf.readInt();
+                        de.writtenOffsetOffset = raf.readLong();
+                        directories.put(dirNameStr, de);
+                    }
+                    ret = true;
+                    zipFileLastModified = fileStamp;
+                }
+            } catch (Throwable t) {
+                // Do nothing
+            } finally {
+                if (raf != null) {
+                    try {
+                        raf.close();
+                    } catch (Throwable tt) {
+                        // Do nothing
+                    }
+                }
+            }
+            if (ret == true) {
+                readFromIndex = true;
+            }
+        }
+        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;
+
+            List<DirectoryEntry> directoriesToWrite = new ArrayList<DirectoryEntry>();
+            Map<RelativeDirectory, Long> offsets = new HashMap<RelativeDirectory, Long>();
+            raf.writeInt(directories.keySet().size());
+            writtenSoFar += 4;
+
+            for (RelativeDirectory dirName: directories.keySet()) {
+                DirectoryEntry dirEntry = directories.get(dirName);
+
+                directoriesToWrite.add(dirEntry);
+
+                // Write the dir name bytes
+                byte [] dirNameBytes = dirName.getPath().getBytes("UTF-8");
+                int dirNameBytesLen = dirNameBytes.length;
+                raf.writeInt(dirNameBytesLen);
+                writtenSoFar += 4;
+
+                raf.write(dirNameBytes);
+                writtenSoFar += dirNameBytesLen;
+
+                // Write the number of files in the dir
+                List<Entry> dirEntries = dirEntry.getEntriesAsCollection();
+                raf.writeInt(dirEntries.size());
+                writtenSoFar += 4;
+
+                offsets.put(dirName, new Long(writtenSoFar));
+
+                // Write the offset of the file's data in the dir
+                dirEntry.writtenOffsetOffset = 0L;
+                raf.writeLong(0L);
+                writtenSoFar += 8;
+            }
+
+            for (DirectoryEntry de : directoriesToWrite) {
+                // Fix up the offset in the directory table
+                long currFP = raf.getFilePointer();
+
+                long offsetOffset = offsets.get(de.dirName).longValue();
+                raf.seek(offsetOffset);
+                raf.writeLong(writtenSoFar);
+
+                raf.seek(currFP);
+
+                // Now write each of the files in the DirectoryEntry
+                List<Entry> entries = de.getEntriesAsCollection();
+                for (Entry 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;
+    }
+
+    File getAbsoluteFile() {
+        File absFile = (absFileRef == null ? null : absFileRef.get());
+        if (absFile == null) {
+            absFile = zipFile.getAbsoluteFile();
+            absFileRef = new SoftReference<File>(absFile);
+        }
+        return absFile;
+    }
+
+    private RelativeDirectory getRelativeDirectory(String path) {
+        RelativeDirectory rd;
+        SoftReference<RelativeDirectory> ref = relativeDirectoryCache.get(path);
+        if (ref != null) {
+            rd = ref.get();
+            if (rd != null)
+                return rd;
+        }
+        rd = new RelativeDirectory(path);
+        relativeDirectoryCache.put(path, new SoftReference<RelativeDirectory>(rd));
+        return rd;
+    }
+
+    static class Entry implements Comparable<Entry> {
+        public static final Entry[] EMPTY_ARRAY = {};
+
+        // Directory related
+        RelativeDirectory dir;
+        boolean isDir;
+
+        // File related
+        String name;
+
+        int offset;
+        int size;
+        int compressedSize;
+        long javatime;
+
+        private int nativetime;
+
+        public Entry(RelativePath path) {
+            this(path.dirname(), path.basename());
+        }
+
+        public Entry(RelativeDirectory directory, String name) {
+            this.dir = directory;
+            this.name = name;
+        }
+
+        public String getName() {
+            return new RelativeFile(dir, name).getPath();
+        }
+
+        public String getFileName() {
+            return name;
+        }
+
+        public long getLastModified() {
+            if (javatime == 0) {
+                    javatime = dosToJavaTime(nativetime);
+            }
+            return javatime;
+        }
+
+        // based on dosToJavaTime in java.util.Zip, but avoiding the
+        // use of deprecated Date constructor
+        private static long dosToJavaTime(int dtime) {
+            Calendar c = Calendar.getInstance();
+            c.set(Calendar.YEAR,        ((dtime >> 25) & 0x7f) + 1980);
+            c.set(Calendar.MONTH,       ((dtime >> 21) & 0x0f) - 1);
+            c.set(Calendar.DATE,        ((dtime >> 16) & 0x1f));
+            c.set(Calendar.HOUR_OF_DAY, ((dtime >> 11) & 0x1f));
+            c.set(Calendar.MINUTE,      ((dtime >>  5) & 0x3f));
+            c.set(Calendar.SECOND,      ((dtime <<  1) & 0x3e));
+            c.set(Calendar.MILLISECOND, 0);
+            return c.getTimeInMillis();
+        }
+
+        void setNativeTime(int natTime) {
+            nativetime = natTime;
+        }
+
+        public boolean isDirectory() {
+            return isDir;
+        }
+
+        public int compareTo(Entry other) {
+            RelativeDirectory otherD = other.dir;
+            if (dir != otherD) {
+                int c = dir.compareTo(otherD);
+                if (c != 0)
+                    return c;
+            }
+            return name.compareTo(other.name);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof Entry))
+                return false;
+            Entry other = (Entry) o;
+            return dir.equals(other.dir) && name.equals(other.name);
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 7;
+            hash = 97 * hash + (this.dir != null ? this.dir.hashCode() : 0);
+            hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0);
+            return hash;
+        }
+
+
+        public String toString() {
+            return isDir ? ("Dir:" + dir + " : " + name) :
+                (dir + ":" + name);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java	Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.IOException;
+import java.util.Set;
+import javax.tools.JavaFileObject;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+
+import com.sun.tools.javac.file.JavacFileManager.Archive;
+import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
+import com.sun.tools.javac.file.RelativePath.RelativeFile;
+import com.sun.tools.javac.util.List;
+
+/**
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class ZipFileIndexArchive implements Archive {
+
+    private final ZipFileIndex zfIndex;
+    private JavacFileManager fileManager;
+
+    public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException {
+        super();
+        this.fileManager = fileManager;
+        this.zfIndex = zdir;
+    }
+
+    public boolean contains(RelativePath name) {
+        return zfIndex.contains(name);
+    }
+
+    public List<String> getFiles(RelativeDirectory subdirectory) {
+        return zfIndex.getFiles(subdirectory);
+    }
+
+    public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
+        RelativeFile fullZipFileName = new RelativeFile(subdirectory, file);
+        ZipFileIndex.Entry entry = zfIndex.getZipIndexEntry(fullZipFileName);
+        JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile());
+        return ret;
+    }
+
+    public Set<RelativeDirectory> getSubdirectories() {
+        return zfIndex.getAllDirectories();
+    }
+
+    public void close() throws IOException {
+        zfIndex.close();
+    }
+
+    @Override
+    public String toString() {
+        return "ZipFileIndexArchive[" + zfIndex + "]";
+    }
+
+    /**
+     * A subclass of JavaFileObject representing zip entries using the com.sun.tools.javac.file.ZipFileIndex implementation.
+     */
+    public static class ZipFileIndexFileObject extends BaseFileObject {
+
+        /** The entry's name.
+         */
+        private String name;
+
+        /** The zipfile containing the entry.
+         */
+        ZipFileIndex zfIndex;
+
+        /** The underlying zip entry object.
+         */
+        ZipFileIndex.Entry entry;
+
+        /** The InputStream for this zip entry (file.)
+         */
+        InputStream inputStream = null;
+
+        /** The name of the zip file where this entry resides.
+         */
+        File zipName;
+
+
+        ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndex.Entry entry, File zipFileName) {
+            super(fileManager);
+            this.name = entry.getFileName();
+            this.zfIndex = zfIndex;
+            this.entry = entry;
+            this.zipName = zipFileName;
+        }
+
+        //@Override
+        public URI toUri() {
+            return createJarUri(zipName, getPrefixedEntryName());
+        }
+
+        //@Override
+        public String getName() {
+            return zipName + "(" + getPrefixedEntryName() + ")";
+        }
+
+        //@Override
+        public String getShortName() {
+            return zipName.getName() + "(" + entry.getName() + ")";
+        }
+
+        //@Override
+        public JavaFileObject.Kind getKind() {
+            return getKind(entry.getName());
+        }
+
+        //@Override
+        public InputStream openInputStream() throws IOException {
+            if (inputStream == null) {
+                assert entry != null; // see constructor
+                inputStream = new ByteArrayInputStream(zfIndex.read(entry));
+            }
+            return inputStream;
+        }
+
+        //@Override
+        public OutputStream openOutputStream() throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        //@Override
+        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+            CharBuffer cb = fileManager.getCachedContent(this);
+            if (cb == null) {
+                InputStream in = new ByteArrayInputStream(zfIndex.read(entry));
+                try {
+                    ByteBuffer bb = fileManager.makeByteBuffer(in);
+                    JavaFileObject prev = fileManager.log.useSource(this);
+                    try {
+                        cb = fileManager.decode(bb, ignoreEncodingErrors);
+                    } finally {
+                        fileManager.log.useSource(prev);
+                    }
+                    fileManager.recycleByteBuffer(bb); // save for next time
+                    if (!ignoreEncodingErrors)
+                        fileManager.cache(this, cb);
+                } finally {
+                    in.close();
+                }
+            }
+            return cb;
+        }
+
+        //@Override
+        public Writer openWriter() throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        //@Override
+        public long getLastModified() {
+            return entry.getLastModified();
+        }
+
+        //@Override
+        public boolean delete() {
+            throw new UnsupportedOperationException();
+        }
+
+        //@Override
+        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+            return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
+        }
+
+        //@Override
+        protected String inferBinaryName(Iterable<? extends File> path) {
+            String entryName = entry.getName();
+            if (zfIndex.symbolFilePrefix != null) {
+                String prefix = zfIndex.symbolFilePrefix.path;
+                if (entryName.startsWith(prefix))
+                    entryName = entryName.substring(prefix.length());
+            }
+            return removeExtension(entryName).replace('/', '.');
+        }
+
+        //@Override
+        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);
+        }
+
+        /**
+         * Check if two file objects are equal.
+         * Two ZipFileIndexFileObjects are equal if the absolute paths of the underlying
+         * zip files are equal and if the paths within those zip files are equal.
+         */
+        //@Override
+        public boolean equals(Object other) {
+            if (this == other)
+                return true;
+
+            if (!(other instanceof ZipFileIndexFileObject))
+                return false;
+
+            ZipFileIndexFileObject o = (ZipFileIndexFileObject) other;
+            return zfIndex.getAbsoluteFile().equals(o.zfIndex.getAbsoluteFile())
+                    && name.equals(o.name);
+        }
+
+        //@Override
+        public int hashCode() {
+            return zfIndex.getAbsoluteFile().hashCode() + name.hashCode();
+        }
+
+        private String getPrefixedEntryName() {
+            if (zfIndex.symbolFilePrefix != null)
+                return zfIndex.symbolFilePrefix.path + entry.getName();
+            else
+                return entry.getName();
+        }
+    }
+
+}
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Tue Jun 22 18:30:16 2010 -0700
@@ -25,6 +25,7 @@
 
 package com.sun.tools.javac.jvm;
 
+import java.net.URISyntaxException;
 import java.io.*;
 import java.net.URI;
 import java.nio.CharBuffer;
@@ -42,6 +43,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;
 
@@ -1047,7 +1049,7 @@
     void readClassAttr(ClassSymbol c, Name attrName, int attrLen) {
         if (attrName == names.SourceFile) {
             Name n = readName(nextChar());
-            c.sourcefile = new SourceFileObject(n);
+            c.sourcefile = new SourceFileObject(n, c.flatname);
         } else if (attrName == names.InnerClasses) {
             readInnerClasses(c);
         } else if (allowGenerics && attrName == names.Signature) {
@@ -2212,69 +2214,103 @@
         /** The file's name.
          */
         private Name name;
+        private Name flatname;
 
-        public SourceFileObject(Name name) {
+        public SourceFileObject(Name name, Name flatname) {
+            super(null); // no file manager; never referenced for this file object
             this.name = name;
+            this.flatname = flatname;
         }
 
+        //@Override
+        public URI toUri() {
+            try {
+                return new URI(null, name.toString(), null);
+            } catch (URISyntaxException e) {
+                throw new CannotCreateUriError(name.toString(), e);
+            }
+        }
+
+        //@Override
+        public String getName() {
+            return name.toString();
+        }
+
+        //@Override
+        public String getShortName() {
+            return getName();
+        }
+
+        //@Override
+        public JavaFileObject.Kind getKind() {
+            return getKind(getName());
+        }
+
+        //@Override
         public InputStream openInputStream() {
             throw new UnsupportedOperationException();
         }
 
+        //@Override
         public OutputStream openOutputStream() {
             throw new UnsupportedOperationException();
         }
 
-        public Reader openReader() {
+        //@Override
+        public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
             throw new UnsupportedOperationException();
         }
 
+        //@Override
+        public Reader openReader(boolean ignoreEncodingErrors) {
+            throw new UnsupportedOperationException();
+        }
+
+        //@Override
         public Writer openWriter() {
             throw new UnsupportedOperationException();
         }
 
-        /** @deprecated see bug 6410637 */
-        @Deprecated
-        public String getName() {
-            return name.toString();
-        }
-
+        //@Override
         public long getLastModified() {
             throw new UnsupportedOperationException();
         }
 
+        //@Override
         public boolean delete() {
             throw new UnsupportedOperationException();
         }
 
-        public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
-            throw new UnsupportedOperationException();
+        //@Override
+        protected String inferBinaryName(Iterable<? extends File> path) {
+            return flatname.toString();
         }
 
-        @Override
+        //@Override
+        public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
+            return true; // fail-safe mode
+        }
+
+        /**
+         * Check if two file objects are equal.
+         * SourceFileObjects are just placeholder objects for the value of a
+         * SourceFile attribute, and do not directly represent specific files.
+         * Two SourceFileObjects are equal if their names are equal.
+         */
+        //@Override
         public boolean equals(Object other) {
+            if (this == other)
+                return true;
+
             if (!(other instanceof SourceFileObject))
                 return false;
             SourceFileObject o = (SourceFileObject) other;
             return name.equals(o.name);
         }
 
-        @Override
+        //@Override
         public int hashCode() {
             return name.hashCode();
         }
-
-        public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
-            return true; // fail-safe mode
-        }
-
-        public URI toUri() {
-            return URI.create(name.toString());
-        }
-
-        public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
-            throw new UnsupportedOperationException();
-        }
-
     }
 }
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Tue Jun 22 18:30:16 2010 -0700
@@ -37,6 +37,7 @@
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.file.BaseFileObject;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.List;
 
@@ -1546,13 +1547,8 @@
             // the last possible moment because the sourcefile may be used
             // elsewhere in error diagnostics. Fixes 4241573.
             //databuf.appendChar(c.pool.put(c.sourcefile));
-            String filename = c.sourcefile.toString();
-            int sepIdx = filename.lastIndexOf(File.separatorChar);
-            // Allow '/' as separator on all platforms, e.g., on Win32.
-            int slashIdx = filename.lastIndexOf('/');
-            if (slashIdx > sepIdx) sepIdx = slashIdx;
-            if (sepIdx >= 0) filename = filename.substring(sepIdx + 1);
-            databuf.appendChar(c.pool.put(names.fromString(filename)));
+            String simpleName = BaseFileObject.getSimpleName(c.sourcefile);
+            databuf.appendChar(c.pool.put(names.fromString(simpleName)));
             endAttr(alenIdx);
             acount++;
         }
--- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Tue Jun 22 18:30:16 2010 -0700
@@ -44,6 +44,7 @@
 import com.sun.source.util.TaskEvent;
 import com.sun.source.util.TaskListener;
 
+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.*;
@@ -553,7 +554,7 @@
             inputFiles.add(filename);
             return filename.getCharContent(false);
         } catch (IOException e) {
-            log.error("error.reading.file", filename, e.getLocalizedMessage());
+            log.error("error.reading.file", filename, JavacFileManager.getMessage(e));
             return null;
         }
     }
@@ -716,7 +717,7 @@
         try {
             tree = parse(filename, filename.getCharContent(false));
         } catch (IOException e) {
-            log.error("error.reading.file", filename, e);
+            log.error("error.reading.file", filename, JavacFileManager.getMessage(e));
             tree = make.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil());
         } finally {
             log.useSource(prev);
--- a/src/share/classes/com/sun/tools/javac/main/Main.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/main/Main.java	Tue Jun 22 18:30:16 2010 -0700
@@ -32,6 +32,8 @@
 import java.util.MissingResourceException;
 
 import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.file.CacheFSInfo;
+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;
@@ -331,13 +333,13 @@
                 return EXIT_CMDERR;
             }
 
-            List<File> filenames;
+            List<File> files;
             try {
-                filenames = processArgs(CommandLine.parse(args));
-                if (filenames == null) {
+                files = processArgs(CommandLine.parse(args));
+                if (files == null) {
                     // null signals an error in options, abort
                     return EXIT_CMDERR;
-                } else if (filenames.isEmpty() && fileObjects.isEmpty() && classnames.isEmpty()) {
+                } else if (files.isEmpty() && fileObjects.isEmpty() && classnames.isEmpty()) {
                     // it is allowed to compile nothing if just asking for help or version info
                     if (options.get("-help") != null
                         || options.get("-X") != null
@@ -362,17 +364,23 @@
 
             context.put(Log.outKey, out);
 
+            // allow System property in following line as a Mustang legacy
+            boolean batchMode = (options.get("nonBatchMode") == null
+                        && System.getProperty("nonBatchMode") == null);
+            if (batchMode)
+                CacheFSInfo.preRegister(context);
+
             fileManager = context.get(JavaFileManager.class);
 
             comp = JavaCompiler.instance(context);
             if (comp == null) return EXIT_SYSERR;
 
-            if (!filenames.isEmpty()) {
+            if (!files.isEmpty()) {
                 // add filenames to fileObjects
                 comp = JavaCompiler.instance(context);
                 List<JavaFileObject> otherFiles = List.nil();
                 JavacFileManager dfm = (JavacFileManager)fileManager;
-                for (JavaFileObject fo : dfm.getJavaFileObjectsFromFiles(filenames))
+                for (JavaFileObject fo : dfm.getJavaFileObjectsFromFiles(files))
                     otherFiles = otherFiles.prepend(fo);
                 for (JavaFileObject fo : otherFiles)
                     fileObjects = fileObjects.prepend(fo);
--- a/src/share/classes/com/sun/tools/javac/parser/Scanner.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/parser/Scanner.java	Tue Jun 22 18:30:16 2010 -0700
@@ -32,6 +32,7 @@
 import java.nio.channels.*;
 import java.util.regex.*;
 
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.util.*;
 
 import com.sun.tools.javac.code.Source;
--- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Tue Jun 22 18:30:16 2010 -0700
@@ -28,6 +28,7 @@
 import com.sun.source.util.TaskEvent;
 import com.sun.source.util.TaskListener;
 import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.code.*;
@@ -169,7 +170,6 @@
     }
 
     private void initProcessorIterator(Context context, Iterable<? extends Processor> processors) {
-        Paths paths = Paths.instance(context);
         Log   log   = Log.instance(context);
         Iterator<? extends Processor> processorIterator;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java	Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.util;
+
+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.JCDiagnostic.SimpleDiagnosticPosition;
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+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.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+
+/**
+ * Utility methods for building a filemanager.
+ * There are no references here to file-system specific objects such as
+ * java.io.File or java.nio.file.Path.
+ */
+public class BaseFileManager {
+    protected BaseFileManager(Charset charset) {
+        this.charset = charset;
+        byteBufferCache = new ByteBufferCache();
+    }
+
+    /**
+     * Set the context for JavacPathFileManager.
+     */
+    protected void setContext(Context context) {
+        log = Log.instance(context);
+        options = Options.instance(context);
+        classLoaderClass = options.get("procloader");
+    }
+
+    /**
+     * The log to be used for error reporting.
+     */
+    public Log log;
+
+    /**
+     * User provided charset (through javax.tools).
+     */
+    protected Charset charset;
+
+    protected Options options;
+
+    protected String classLoaderClass;
+
+    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);
+    }
+
+    protected ClassLoader getClassLoader(URL[] urls) {
+        ClassLoader thisClassLoader = getClass().getClassLoader();
+
+        // Bug: 6558476
+        // Ideally, ClassLoader should be Closeable, but before JDK7 it is not.
+        // On older versions, try the following, to get a closeable classloader.
+
+        // 1: Allow client to specify the class to use via hidden option
+        if (classLoaderClass != null) {
+            try {
+                Class<? extends ClassLoader> loader =
+                        Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
+                Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
+                Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
+                return constr.newInstance(new Object[] { urls, thisClassLoader });
+            } catch (Throwable t) {
+                // ignore errors loading user-provided class loader, fall through
+            }
+        }
+
+        // 2: If URLClassLoader implements Closeable, use that.
+        if (Closeable.class.isAssignableFrom(URLClassLoader.class))
+            return new URLClassLoader(urls, thisClassLoader);
+
+        // 3: Try using private reflection-based CloseableURLClassLoader
+        try {
+            return new CloseableURLClassLoader(urls, thisClassLoader);
+        } catch (Throwable t) {
+            // ignore errors loading workaround class loader, fall through
+        }
+
+        // 4: If all else fails, use plain old standard URLClassLoader
+        return new URLClassLoader(urls, thisClassLoader);
+    }
+
+    // <editor-fold defaultstate="collapsed" desc="Option handling">
+    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;
+    }
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="Encoding">
+    private String defaultEncodingName;
+    private String getDefaultEncodingName() {
+        if (defaultEncodingName == null) {
+            defaultEncodingName =
+                new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
+        }
+        return defaultEncodingName;
+    }
+
+    public String getEncodingName() {
+        String encName = options.get(OptionName.ENCODING);
+        if (encName == null)
+            return getDefaultEncodingName();
+        else
+            return encName;
+    }
+
+    public 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 CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
+        Charset cs = (this.charset == null)
+            ? Charset.forName(encodingName)
+            : this.charset;
+        CharsetDecoder decoder = cs.newDecoder();
+
+        CodingErrorAction action;
+        if (ignoreEncodingErrors)
+            action = CodingErrorAction.REPLACE;
+        else
+            action = CodingErrorAction.REPORT;
+
+        return decoder
+            .onMalformedInput(action)
+            .onUnmappableCharacter(action);
+    }
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="ByteBuffers">
+    /**
+     * Make a byte buffer from an input stream.
+     */
+    public ByteBuffer makeByteBuffer(InputStream in)
+        throws IOException {
+        int limit = in.available();
+        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();
+    }
+
+    public void recycleByteBuffer(ByteBuffer bb) {
+        byteBufferCache.put(bb);
+    }
+
+    /**
+     * 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;
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="Content cache">
+    public CharBuffer getCachedContent(JavaFileObject file) {
+        SoftReference<CharBuffer> r = contentCache.get(file);
+        return (r == null ? null : r.get());
+    }
+
+    public void cache(JavaFileObject file, CharBuffer cb) {
+        contentCache.put(file, new SoftReference<CharBuffer>(cb));
+    }
+
+    protected final Map<JavaFileObject, SoftReference<CharBuffer>> contentCache
+            = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
+    // </editor-fold>
+
+    public static Kind getKind(String name) {
+        if (name.endsWith(Kind.CLASS.extension))
+            return Kind.CLASS;
+        else if (name.endsWith(Kind.SOURCE.extension))
+            return Kind.SOURCE;
+        else if (name.endsWith(Kind.HTML.extension))
+            return Kind.HTML;
+        else
+            return Kind.OTHER;
+    }
+
+    protected static <T> T nullCheck(T o) {
+        o.getClass(); // null check
+        return o;
+    }
+
+    protected static <T> Collection<T> nullCheck(Collection<T> it) {
+        for (T t : it)
+            t.getClass(); // null check
+        return it;
+    }
+}
--- a/src/share/classes/com/sun/tools/javac/util/BaseFileObject.java	Mon Jun 21 11:43:28 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.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	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java	Tue Jun 22 18:30:16 2010 -0700
@@ -27,6 +27,8 @@
 
 import javax.tools.JavaFileObject;
 
+import com.sun.tools.javac.file.BaseFileObject;
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticSource;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
 
@@ -143,8 +145,10 @@
                 sb.append(format_raw((JCDiagnostic) arg));
                 sb.append(')');
             }
+            else if (arg instanceof BaseFileObject)
+                sb.append(((BaseFileObject) arg).getShortName());
             else if (arg instanceof JavaFileObject)
-                sb.append(JavacFileManager.getJavacBaseFileName((JavaFileObject) arg));
+                sb.append(BaseFileObject.getSimpleName((JavaFileObject) arg));
             else
                 sb.append(arg);
             sep = ", ";
--- a/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Tue Jun 22 18:30:16 2010 -0700
@@ -25,12 +25,8 @@
 
 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;
@@ -341,7 +337,7 @@
      */
     public String getSourceName() {
         JavaFileObject s = getSource();
-        return s == null ? null : JavacFileManager.getJavacFileName(s);
+        return s == null ? null : s.getName();
     }
 
     /**
@@ -445,6 +441,8 @@
             Object arg = args[i];
             if (arg == null)
                 strings[i] = null;
+            else if (arg instanceof FileObject)
+                strings[i] = ((FileObject) arg).getName();
             else if (arg instanceof JCDiagnostic)
                 strings[i] = ((JCDiagnostic) arg).getMessage(null);
             else
--- a/src/share/classes/com/sun/tools/javac/util/JavacFileManager.java	Mon Jun 21 11:43:28 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1754 +0,0 @@
-/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.util;
-
-import java.io.ByteArrayOutputStream;
-import java.io.Closeable;
-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.lang.reflect.Constructor;
-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.JCDiagnostic.SimpleDiagnosticPosition;
-
-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;
-    protected String classLoaderClass;
-
-    /**
-     * 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;
-        classLoaderClass = options.get("procloader");
-    }
-
-    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);
-            }
-        }
-
-        URL[] urls = lb.toArray(new URL[lb.size()]);
-        ClassLoader thisClassLoader = getClass().getClassLoader();
-
-        // Bug: 6558476
-        // Ideally, ClassLoader should be Closeable, but before JDK7 it is not.
-        // On older versions, try the following, to get a closeable classloader.
-
-        // 1: Allow client to specify the class to use via hidden option
-        if (classLoaderClass != null) {
-            try {
-                Class<? extends ClassLoader> loader =
-                        Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
-                Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
-                Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
-                return constr.newInstance(new Object[] { urls, thisClassLoader });
-            } catch (Throwable t) {
-                // ignore errors loading user-provided class loader, fall through
-            }
-        }
-
-        // 2: If URLClassLoader implements Closeable, use that.
-        if (Closeable.class.isAssignableFrom(URLClassLoader.class))
-            return new URLClassLoader(urls, thisClassLoader);
-
-        // 3: Try using private reflection-based CloseableURLClassLoader
-        try {
-            return new CloseableURLClassLoader(urls, thisClassLoader);
-        } catch (Throwable t) {
-            // ignore errors loading workaround class loader, fall through
-        }
-
-        // 4: If all else fails, use plain old standard URLClassLoader
-        return new URLClassLoader(urls, thisClassLoader);
-    }
-
-    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();
-	// allow use of binary package names, per the JavaFileManager spec
-        String subdirectory = externalizeFileName(packageName.replace('/', '.'));
-        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.length() == 0)
-                    dPath = System.getProperty("user.dir");
-                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 entry.getName() + "(" + entry + ")";
-        }
-
-        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	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/util/Log.java	Tue Jun 22 18:30:16 2010 -0700
@@ -33,6 +33,8 @@
 import java.util.Set;
 import javax.tools.DiagnosticListener;
 import javax.tools.JavaFileObject;
+import com.sun.tools.javac.file.BaseFileObject;
+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;
@@ -233,7 +235,10 @@
                         return name;
                     }
                     public CharSequence getName() {
-                        return JavacFileManager.getJavacBaseFileName(getFile());
+                        if (name instanceof BaseFileObject)
+                            return ((BaseFileObject) name).getShortName();
+                        else
+                            return BaseFileObject.getSimpleName(name);
                     }
                     public int getLineNumber(int pos) {
                         return Log.this.getLineNumber(pos);
@@ -522,7 +527,10 @@
                         return file;
                     }
                     public CharSequence getName() {
-                        return JavacFileManager.getJavacBaseFileName(getFile());
+                        if (file instanceof BaseFileObject)
+                            return ((BaseFileObject) file).getShortName();
+                        else
+                            return BaseFileObject.getSimpleName(file);
                     }
                     public int getLineNumber(int pos) {
                         return Log.this.getLineNumber(pos);
@@ -660,7 +668,7 @@
             JavaFileObject file = currentSource();
             if (file != null)
                 printLines(errWriter,
-                           JavacFileManager.getJavacFileName(file) + ":" +
+                           file.getName() + ":" +
                            line + ": " + msg);
             printErrLine(pos, errWriter);
         }
--- a/src/share/classes/com/sun/tools/javac/util/Old199.java	Mon Jun 21 11:43:28 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.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 supported API.
- * If you write code that depends on this, you do so at your own
- * risk.  This code and its internal interfaces are subject to change
- * or deletion without notice.</b></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	Mon Jun 21 11:43:28 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,568 +0,0 @@
-/*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.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.ZipException;
-import java.util.zip.ZipFile;
-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 com.sun.tools.javac.util.Position;
-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 supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- */
-public class 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. */
-    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);
-    }
-
-    /**
-     * Split a path into its elements. Empty path elements will be ignored.
-     * @param path The path to be split
-     * @return The elements of the path
-     */
-    private static Iterable<File> getPathEntries(String path) {
-        return getPathEntries(path, null);
-    }
-
-    /**
-     * Split a path into its elements. If emptyPathDefault is not null, all
-     * empty elements in the path, including empty elements at either end of
-     * the path, will be replaced with the value of emptyPathDefault.
-     * @param path The path to be split
-     * @param emptyPathDefault The value to substitute for empty path elements,
-     *  or null, to ignore empty path elements
-     * @return The elements of the path
-     */
-    private static Iterable<File> getPathEntries(String path, File emptyPathDefault) {
-        ListBuffer<File> entries = new ListBuffer<File>();
-        int start = 0;
-        while (start <= path.length()) {
-            int sep = path.indexOf(File.pathSeparatorChar, start);
-            if (sep == -1)
-                sep = path.length();
-            if (start < sep)
-                entries.append(new File(path.substring(start, sep)));
-            else if (emptyPathDefault != null)
-                entries.append(emptyPathDefault);
-            start = sep + 1;
-        }
-        return entries;
-    }
-
-    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 File emptyPathDefault = null;
-
-        public Path emptyPathDefault(File x) {
-            emptyPathDefault = x;
-            return this;
-        }
-
-        public Path() { super(); }
-
-        public Path addDirectories(String dirs, boolean warn) {
-            if (dirs != null)
-                for (File dir : getPathEntries(dirs))
-                    addDirectory(dir, warn);
-            return this;
-        }
-
-        public Path addDirectories(String dirs) {
-            return addDirectories(dirs, warn);
-        }
-
-        private void addDirectory(File dir, boolean warn) {
-            if (!dir.isDirectory()) {
-                if (warn)
-                    log.warning("dir.path.element.not.found", dir);
-                return;
-            }
-
-            File[] files = 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 (File file : getPathEntries(files, emptyPathDefault))
-                    addFile(file, warn);
-            return this;
-        }
-
-        public Path addFiles(String files) {
-            return addFiles(files, warn);
-        }
-
-        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 (File file : getPathEntries(files)) {
-                if (new File(file.getName()).equals(rt_jar))
-                    bootClassPathRtJar = file;
-            }
-        }
-
-        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(new File("."))  // 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	Mon Jun 21 11:43:28 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1236 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.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	Mon Jun 21 11:43:28 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.zip;
-
-import java.io.File;
-import java.util.Calendar;
-
-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;
-    }
-
-    // based on dosToJavaTime in java.util.Zip, but avoiding the
-    // use of deprecated Date constructor
-    private static long dosToJavaTime(int dtime) {
-        Calendar c = Calendar.getInstance();
-        c.set(Calendar.YEAR,        ((dtime >> 25) & 0x7f) + 1980);
-        c.set(Calendar.MONTH,       ((dtime >> 21) & 0x0f) - 1);
-        c.set(Calendar.DATE,        ((dtime >> 16) & 0x1f));
-        c.set(Calendar.HOUR_OF_DAY, ((dtime >> 11) & 0x1f));
-        c.set(Calendar.MINUTE,      ((dtime >>  5) & 0x3f));
-        c.set(Calendar.SECOND,      ((dtime <<  1) & 0x3e));
-        c.set(Calendar.MILLISECOND, 0);
-        return c.getTimeInMillis();
-    }
-    
-    void setNativeTime(int natTime) {
-        nativetime = natTime;
-    }
-
-    public boolean isDirectory() {
-        return isDir;
-    }
-
-    public int compareTo(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/ClassDocImpl.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java	Tue Jun 22 18:30:16 2010 -0700
@@ -25,44 +25,46 @@
 
 package com.sun.tools.javadoc;
 
-import java.util.*;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Set;
+import javax.tools.FileObject;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
 
 import com.sun.javadoc.*;
 
 import static com.sun.javadoc.LanguageVersion.*;
 
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Kinds;
+import com.sun.tools.javac.code.Scope;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.ClassType;
+import com.sun.tools.javac.code.TypeTags;
+
+import com.sun.tools.javac.comp.AttrContext;
+import com.sun.tools.javac.comp.Env;
+
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
+import com.sun.tools.javac.tree.JCTree.JCImport;
+import com.sun.tools.javac.tree.TreeInfo;
+
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
 import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Position;
 
-import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Kinds;
-import com.sun.tools.javac.code.TypeTags;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.code.Type.ClassType;
-import com.sun.tools.javac.code.Scope;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.*;
-
-import com.sun.tools.javac.comp.AttrContext;
-import com.sun.tools.javac.comp.Env;
-
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
-import com.sun.tools.javac.tree.JCTree.JCImport;
-import com.sun.tools.javac.tree.JCTree.JCClassDecl;
-import com.sun.tools.javac.tree.TreeInfo;
-
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.*;
-import static com.sun.tools.javac.code.TypeTags.*;
-
-import java.io.File;
-import java.util.Set;
-import java.util.HashSet;
-import java.lang.reflect.Modifier;
 
 /**
  * Represents a java class and provides access to information
@@ -274,16 +276,41 @@
      */
     public PackageDoc containingPackage() {
         PackageDocImpl p = env.getPackageDoc(tsym.packge());
-        SourcePosition po = position();
-        if (po != null && p.setDocPath == false && p.zipDocPath == null) {
-            //Set the package path if possible
-            File packageDir = po.file().getParentFile();
-            if (packageDir != null
-                && (new File(packageDir, "package.html")).exists()) {
-                p.setDocPath(packageDir.getPath());
-            } else {
-                p.setDocPath(null);
+        if (p.setDocPath == false) {
+            FileObject docPath;
+            try {
+                Location location = env.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
+                    ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
+
+                docPath = env.fileManager.getFileForInput(
+                        location, p.qualifiedName(), "package.html");
+            } catch (IOException e) {
+                docPath = null;
             }
+
+            if (docPath == null) {
+                // fall back on older semantics of looking in same directory as
+                // source file for this class
+                SourcePosition po = position();
+                if (env.fileManager instanceof StandardJavaFileManager &&
+                        po instanceof SourcePositionImpl) {
+                    URI uri = ((SourcePositionImpl) po).filename.toUri();
+                    if ("file".equals(uri.getScheme())) {
+                        File f = new File(uri);
+                        File dir = f.getParentFile();
+                        if (dir != null) {
+                            File pf = new File(dir, "package.html");
+                            if (pf.exists()) {
+                                StandardJavaFileManager sfm = (StandardJavaFileManager) env.fileManager;
+                                docPath = sfm.getJavaFileObjects(pf).iterator().next();
+                            }
+                        }
+
+                    }
+                }
+            }
+
+            p.setDocPath(docPath);
         }
         return p;
     }
@@ -1254,7 +1281,7 @@
      */
     public SourcePosition position() {
         if (tsym.sourcefile == null) return null;
-        return SourcePositionImpl.make(tsym.sourcefile.toString(),
+        return SourcePositionImpl.make(tsym.sourcefile,
                                        (tree==null) ? Position.NOPOS : tree.pos,
                                        lineMap);
     }
--- a/src/share/classes/com/sun/tools/javadoc/DocEnv.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/DocEnv.java	Tue Jun 22 18:30:16 2010 -0700
@@ -25,24 +25,21 @@
 
 package com.sun.tools.javadoc;
 
+import java.lang.reflect.Modifier;
 import java.util.*;
-import java.lang.reflect.Modifier;
+import javax.tools.JavaFileManager;
 
 import com.sun.javadoc.*;
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.ClassType;
-import com.sun.tools.javac.code.Type.TypeVar;
-import com.sun.tools.javac.comp.Attr;
 import com.sun.tools.javac.comp.Check;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Position;
 
-
 /**
  * Holds the environment for a run of javadoc.
  * Holds only the information needed throughout the
@@ -75,10 +72,6 @@
     /** Referenced directly in RootDocImpl. */
     JavadocClassReader reader;
 
-    /** The compiler's attribution phase (needed to evaluate
-     *  constant initializers). */
-    Attr attr;
-
     /** Javadoc's own version of the compiler's enter phase. */
     JavadocEnter enter;
 
@@ -93,8 +86,6 @@
     /** Access filter (public, protected, ...).  */
     ModifierFilter showAccess;
 
-    private ClassDocImpl runtimeException;
-
     /** True if we are using a sentence BreakIterator. */
     boolean breakiterator;
 
@@ -105,6 +96,7 @@
 
     Check chk;
     Types types;
+    JavaFileManager fileManager;
 
     /** Allow documenting from class files? */
     boolean docClasses = false;
@@ -130,11 +122,11 @@
         syms = Symtab.instance(context);
         reader = JavadocClassReader.instance0(context);
         enter = JavadocEnter.instance0(context);
-        attr = Attr.instance(context);
         names = Name.Table.instance(context);
         externalizableSym = reader.enterClass(names.fromString("java.io.Externalizable"));
         chk = Check.instance(context);
         types = Types.instance(context);
+        fileManager = context.get(JavaFileManager.class);
 
         // Default.  Should normally be reset with setLocale.
         this.doclocale = new DocLocale(this, "", breakiterator);
--- a/src/share/classes/com/sun/tools/javadoc/DocImpl.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/DocImpl.java	Tue Jun 22 18:30:16 2010 -0700
@@ -25,11 +25,13 @@
 
 package com.sun.tools.javadoc;
 
-import com.sun.javadoc.*;
-
 import java.io.InputStream;
 import java.io.IOException;
 import java.text.CollationKey;
+import javax.tools.FileObject;
+
+import com.sun.javadoc.*;
+
 import com.sun.tools.javac.util.Position;
 
 /**
@@ -43,7 +45,7 @@
  * @author Atul M Dambalkar
  * @author Neal Gafter (rewrite)
  */
-abstract class DocImpl implements Doc, Comparable<Object> {
+public abstract class DocImpl implements Doc, Comparable<Object> {
 
     /**
      * Doc environment
@@ -163,7 +165,7 @@
     /**
      * Utility for subclasses which read HTML documentation files.
      */
-    String readHTMLDocumentation(InputStream input, String filename) throws IOException {
+    String readHTMLDocumentation(InputStream input, FileObject filename) throws IOException {
         int filesize = input.available();
         byte[] filecontents = new byte[filesize];
         input.read(filecontents, 0, filesize);
--- a/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java	Tue Jun 22 18:30:16 2010 -0700
@@ -267,7 +267,7 @@
      */
     public SourcePosition position() {
         if (sym.enclClass().sourcefile == null) return null;
-        return SourcePositionImpl.make(sym.enclClass().sourcefile.toString(),
+        return SourcePositionImpl.make(sym.enclClass().sourcefile,
                                        (tree==null) ? 0 : tree.pos,
                                        lineMap);
     }
--- a/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java	Tue Jun 22 18:30:16 2010 -0700
@@ -260,7 +260,7 @@
      */
     public SourcePosition position() {
         if (sym.enclClass().sourcefile == null) return null;
-        return SourcePositionImpl.make(sym.enclClass().sourcefile.toString(),
+        return SourcePositionImpl.make(sym.enclClass().sourcefile,
                                        (tree==null) ? 0 : tree.pos,
                                        lineMap);
     }
--- a/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java	Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java	Tue Jun 22 18:30:16 2010 -0700
@@ -25,15 +25,13 @@
 
 package com.sun.tools.javadoc;
 
+import java.util.EnumSet;
+import javax.tools.JavaFileObject;
+
 import com.sun.tools.javac.code.Symbol.PackageSymbol;
 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;
-import javax.tools.JavaFileObject;
 
 /** Javadoc uses an extended class reader that records package.html entries
  *  @author Neal Gafter
@@ -80,32 +78,7 @@
      */
     @Override
     protected void extraFileActions(PackageSymbol pack, JavaFileObject fo) {
-        CharSequence fileName = Old199.getName(fo);
-        if (docenv != null && fileName.equals("package.html")) {
-            if (fo instanceof JavacFileManager.ZipFileObject) {
-                JavacFileManager.ZipFileObject zfo = (JavacFileManager.ZipFileObject) fo;
-                String zipName = zfo.getZipName();
-                String entryName = zfo.getZipEntryName();
-                int lastSep = entryName.lastIndexOf("/");
-                String classPathName = entryName.substring(0, lastSep + 1);
-                docenv.getPackageDoc(pack).setDocPath(zipName, classPathName);
-            }
-            else if (fo instanceof JavacFileManager.ZipFileIndexFileObject) {
-                JavacFileManager.ZipFileIndexFileObject zfo = (JavacFileManager.ZipFileIndexFileObject) fo;
-                String zipName = zfo.getZipName();
-                String entryName = zfo.getZipEntryName();
-                if (File.separatorChar != '/') {
-                    entryName = entryName.replace(File.separatorChar, '/');
-                }
-
-                int lastSep = entryName.lastIndexOf("/");
-                String classPathName = entryName.substring(0, lastSep + 1);
-                docenv.getPackageDoc(pack).setDocPath(zipName, classPathName);
-            }
-            else {
-                File fileDir = new File(Old199.getPath(fo)).getParentFile();
-                docenv.getPackageDoc(pack).setDocPath(fileDir.getAbsolutePath());
-            }
-        }
+        if (fo.isNameCompatible("package", JavaFileObject.Kind.HTML))
+            docenv.getPackageDoc(pack).setDocPath(fo);