6714364: refactor javac File handling code into new javac.file package

Mon, 16 Jun 2008 13:28:00 -0700

author
jjg
date
Mon, 16 Jun 2008 13:28:00 -0700
changeset 50
b9bcea8bbe24
parent 48
c2abfb92ba69
child 51
700b17652ef6
child 56
f9a4b9e1a521

6714364: refactor javac File handling code into new javac.file package
Reviewed-by: mcimadamore

src/share/classes/com/sun/tools/apt/main/JavaCompiler.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/apt/main/Main.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/api/JavacTool.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/file/BaseFileObject.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/file/JavacFileManager.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/file/Old199.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/file/Paths.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/file/ZipFileIndexEntry.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/jvm/ClassReader.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/main/JavaCompiler.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/main/Main.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/parser/Scanner.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/BaseFileObject.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/JavacFileManager.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/Log.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/Old199.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/Paths.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/zip/ZipFileIndex.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/zip/ZipFileIndexEntry.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javadoc/JavadocTool.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javap/JavapFileManager.java file | annotate | diff | comparison | revisions
test/tools/javac/6304921/TestLog.java file | annotate | diff | comparison | revisions
test/tools/javac/6589361/T6589361.java file | annotate | diff | comparison | revisions
test/tools/javac/T6358024.java file | annotate | diff | comparison | revisions
test/tools/javac/T6358166.java file | annotate | diff | comparison | revisions
test/tools/javac/T6358168.java file | annotate | diff | comparison | revisions
test/tools/javac/T6705935.java file | annotate | diff | comparison | revisions
test/tools/javac/api/T6358786.java file | annotate | diff | comparison | revisions
test/tools/javac/api/TestResolveIdent.java file | annotate | diff | comparison | revisions
test/tools/javac/util/filemanager/TestName.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java	Fri Jun 06 15:17:35 2008 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java	Mon Jun 16 13:28:00 2008 -0700
     1.3 @@ -26,20 +26,14 @@
     1.4  package com.sun.tools.apt.main;
     1.5  
     1.6  import java.io.*;
     1.7 -import java.nio.CharBuffer;
     1.8 -import java.util.Set;
     1.9 -import java.util.HashSet;
    1.10  import java.util.Map;
    1.11 -import java.util.HashMap;
    1.12  
    1.13  import javax.tools.JavaFileManager;
    1.14  import javax.tools.JavaFileObject;
    1.15  
    1.16 +import com.sun.tools.javac.file.JavacFileManager;
    1.17  import com.sun.tools.javac.util.*;
    1.18  import com.sun.tools.javac.code.*;
    1.19 -import com.sun.tools.javac.tree.*;
    1.20 -import com.sun.tools.javac.parser.*;
    1.21 -import com.sun.tools.javac.comp.*;
    1.22  import com.sun.tools.javac.jvm.*;
    1.23  
    1.24  import com.sun.tools.javac.code.Symbol.*;
     2.1 --- a/src/share/classes/com/sun/tools/apt/main/Main.java	Fri Jun 06 15:17:35 2008 -0700
     2.2 +++ b/src/share/classes/com/sun/tools/apt/main/Main.java	Mon Jun 16 13:28:00 2008 -0700
     2.3 @@ -44,7 +44,7 @@
     2.4  import java.io.File;
     2.5  import java.net.MalformedURLException;
     2.6  
     2.7 -import com.sun.tools.javac.util.Paths;
     2.8 +import com.sun.tools.javac.file.Paths;
     2.9  import com.sun.tools.javac.code.Source;
    2.10  import com.sun.tools.javac.code.Symbol;
    2.11  import com.sun.tools.javac.code.Type;
     3.1 --- a/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Fri Jun 06 15:17:35 2008 -0700
     3.2 +++ b/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Mon Jun 16 13:28:00 2008 -0700
     3.3 @@ -36,12 +36,12 @@
     3.4  import javax.lang.model.type.TypeMirror;
     3.5  import javax.tools.*;
     3.6  
     3.7 -import com.sun.source.tree.Tree;
     3.8  import com.sun.source.tree.*;
     3.9  import com.sun.source.util.*;
    3.10  import com.sun.tools.javac.code.*;
    3.11  import com.sun.tools.javac.code.Symbol.*;
    3.12  import com.sun.tools.javac.comp.*;
    3.13 +import com.sun.tools.javac.file.JavacFileManager;
    3.14  import com.sun.tools.javac.main.*;
    3.15  import com.sun.tools.javac.model.*;
    3.16  import com.sun.tools.javac.parser.Parser;
     4.1 --- a/src/share/classes/com/sun/tools/javac/api/JavacTool.java	Fri Jun 06 15:17:35 2008 -0700
     4.2 +++ b/src/share/classes/com/sun/tools/javac/api/JavacTool.java	Mon Jun 16 13:28:00 2008 -0700
     4.3 @@ -31,7 +31,6 @@
     4.4  import java.io.PrintWriter;
     4.5  import java.io.Writer;
     4.6  import java.util.ArrayList;
     4.7 -import java.util.Arrays;
     4.8  import java.util.Collections;
     4.9  import java.util.EnumSet;
    4.10  import java.util.Iterator;
    4.11 @@ -42,13 +41,13 @@
    4.12  import javax.tools.*;
    4.13  
    4.14  import com.sun.source.util.JavacTask;
    4.15 +import com.sun.tools.javac.file.JavacFileManager;
    4.16  import com.sun.tools.javac.main.JavacOption.OptionKind;
    4.17  import com.sun.tools.javac.main.JavacOption;
    4.18  import com.sun.tools.javac.main.Main;
    4.19  import com.sun.tools.javac.main.RecognizedOptions.GrumpyHelper;
    4.20  import com.sun.tools.javac.main.RecognizedOptions;
    4.21  import com.sun.tools.javac.util.Context;
    4.22 -import com.sun.tools.javac.util.JavacFileManager;
    4.23  import com.sun.tools.javac.util.Log;
    4.24  import com.sun.tools.javac.util.Options;
    4.25  import com.sun.tools.javac.util.Pair;
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java	Mon Jun 16 13:28:00 2008 -0700
     5.3 @@ -0,0 +1,79 @@
     5.4 +/*
     5.5 + * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
     5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.7 + *
     5.8 + * This code is free software; you can redistribute it and/or modify it
     5.9 + * under the terms of the GNU General Public License version 2 only, as
    5.10 + * published by the Free Software Foundation.  Sun designates this
    5.11 + * particular file as subject to the "Classpath" exception as provided
    5.12 + * by Sun in the LICENSE file that accompanied this code.
    5.13 + *
    5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.17 + * version 2 for more details (a copy is included in the LICENSE file that
    5.18 + * accompanied this code).
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License version
    5.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.23 + *
    5.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    5.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    5.26 + * have any questions.
    5.27 + */
    5.28 +
    5.29 +package com.sun.tools.javac.file;
    5.30 +
    5.31 +import java.io.IOException;
    5.32 +import java.io.InputStreamReader;
    5.33 +import java.io.Reader;
    5.34 +import java.nio.charset.CharsetDecoder;
    5.35 +import javax.lang.model.element.Modifier;
    5.36 +import javax.lang.model.element.NestingKind;
    5.37 +import javax.tools.JavaFileObject;
    5.38 +
    5.39 +import static javax.tools.JavaFileObject.Kind.*;
    5.40 +
    5.41 +public abstract class BaseFileObject implements JavaFileObject {
    5.42 +
    5.43 +    public JavaFileObject.Kind getKind() {
    5.44 +        String n = getName();
    5.45 +        if (n.endsWith(CLASS.extension))
    5.46 +            return CLASS;
    5.47 +        else if (n.endsWith(SOURCE.extension))
    5.48 +            return SOURCE;
    5.49 +        else if (n.endsWith(HTML.extension))
    5.50 +            return HTML;
    5.51 +        else
    5.52 +            return OTHER;
    5.53 +    }
    5.54 +
    5.55 +    @Override
    5.56 +    public String toString() {
    5.57 +        return getPath();
    5.58 +    }
    5.59 +
    5.60 +    /** @deprecated see bug 6410637 */
    5.61 +    @Deprecated
    5.62 +    public String getPath() {
    5.63 +        return getName();
    5.64 +    }
    5.65 +
    5.66 +    /** @deprecated see bug 6410637 */
    5.67 +    @Deprecated
    5.68 +    abstract public String getName();
    5.69 +
    5.70 +    public NestingKind getNestingKind() { return null; }
    5.71 +
    5.72 +    public Modifier getAccessLevel()  { return null; }
    5.73 +
    5.74 +    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
    5.75 +        return new InputStreamReader(openInputStream(), getDecoder(ignoreEncodingErrors));
    5.76 +    }
    5.77 +
    5.78 +    protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
    5.79 +        throw new UnsupportedOperationException();
    5.80 +    }
    5.81 +
    5.82 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Mon Jun 16 13:28:00 2008 -0700
     6.3 @@ -0,0 +1,1718 @@
     6.4 +/*
     6.5 + * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
     6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.7 + *
     6.8 + * This code is free software; you can redistribute it and/or modify it
     6.9 + * under the terms of the GNU General Public License version 2 only, as
    6.10 + * published by the Free Software Foundation.  Sun designates this
    6.11 + * particular file as subject to the "Classpath" exception as provided
    6.12 + * by Sun in the LICENSE file that accompanied this code.
    6.13 + *
    6.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    6.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    6.17 + * version 2 for more details (a copy is included in the LICENSE file that
    6.18 + * accompanied this code).
    6.19 + *
    6.20 + * You should have received a copy of the GNU General Public License version
    6.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    6.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    6.23 + *
    6.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    6.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    6.26 + * have any questions.
    6.27 + */
    6.28 +
    6.29 +package com.sun.tools.javac.file;
    6.30 +
    6.31 +import java.io.ByteArrayInputStream;
    6.32 +import java.io.ByteArrayOutputStream;
    6.33 +import java.io.File;
    6.34 +import java.io.FileInputStream;
    6.35 +import java.io.FileNotFoundException;
    6.36 +import java.io.FileOutputStream;
    6.37 +import java.io.IOException;
    6.38 +import java.io.InputStream;
    6.39 +import java.io.OutputStream;
    6.40 +import java.io.OutputStreamWriter;
    6.41 +import java.io.Writer;
    6.42 +import java.lang.ref.SoftReference;
    6.43 +import java.net.MalformedURLException;
    6.44 +import java.net.URI;
    6.45 +import java.net.URISyntaxException;
    6.46 +import java.net.URL;
    6.47 +import java.net.URLClassLoader;
    6.48 +import java.nio.ByteBuffer;
    6.49 +import java.nio.CharBuffer;
    6.50 +import java.nio.channels.FileChannel;
    6.51 +import java.nio.charset.Charset;
    6.52 +import java.nio.charset.CharsetDecoder;
    6.53 +import java.nio.charset.CoderResult;
    6.54 +import java.nio.charset.CodingErrorAction;
    6.55 +import java.nio.charset.IllegalCharsetNameException;
    6.56 +import java.nio.charset.UnsupportedCharsetException;
    6.57 +import java.util.ArrayList;
    6.58 +import java.util.Arrays;
    6.59 +import java.util.Collection;
    6.60 +import java.util.Collections;
    6.61 +import java.util.EnumSet;
    6.62 +import java.util.Enumeration;
    6.63 +import java.util.HashMap;
    6.64 +import java.util.Iterator;
    6.65 +import java.util.Map;
    6.66 +import java.util.Set;
    6.67 +import java.util.concurrent.ConcurrentHashMap;
    6.68 +import java.util.zip.ZipEntry;
    6.69 +import java.util.zip.ZipFile;
    6.70 +
    6.71 +import javax.lang.model.SourceVersion;
    6.72 +import javax.tools.FileObject;
    6.73 +import javax.tools.JavaFileManager;
    6.74 +import javax.tools.JavaFileObject;
    6.75 +import javax.tools.StandardJavaFileManager;
    6.76 +
    6.77 +import com.sun.tools.javac.code.Source;
    6.78 +import com.sun.tools.javac.main.JavacOption;
    6.79 +import com.sun.tools.javac.main.OptionName;
    6.80 +import com.sun.tools.javac.main.RecognizedOptions;
    6.81 +import com.sun.tools.javac.util.Context;
    6.82 +import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
    6.83 +import com.sun.tools.javac.util.List;
    6.84 +import com.sun.tools.javac.util.ListBuffer;
    6.85 +import com.sun.tools.javac.util.Log;
    6.86 +import com.sun.tools.javac.util.Options;
    6.87 +
    6.88 +import static com.sun.tools.javac.main.OptionName.*;
    6.89 +import static javax.tools.StandardLocation.*;
    6.90 +
    6.91 +/**
    6.92 + * This class provides access to the source, class and other files
    6.93 + * used by the compiler and related tools.
    6.94 + */
    6.95 +public class JavacFileManager implements StandardJavaFileManager {
    6.96 +
    6.97 +    private static final String[] symbolFileLocation = { "lib", "ct.sym" };
    6.98 +    private static final String symbolFilePrefix = "META-INF/sym/rt.jar/";
    6.99 +
   6.100 +    boolean useZipFileIndex;
   6.101 +
   6.102 +    private static int symbolFilePrefixLength = 0;
   6.103 +    static {
   6.104 +        try {
   6.105 +            symbolFilePrefixLength = symbolFilePrefix.getBytes("UTF-8").length;
   6.106 +        } catch (java.io.UnsupportedEncodingException uee) {
   6.107 +            // Can't happen...UTF-8 is always supported.
   6.108 +        }
   6.109 +    }
   6.110 +
   6.111 +    private static boolean CHECK_ZIP_TIMESTAMP = false;
   6.112 +    private static Map<File, Boolean> isDirectory = new ConcurrentHashMap<File, Boolean>();
   6.113 +
   6.114 +
   6.115 +    public static char[] toArray(CharBuffer buffer) {
   6.116 +        if (buffer.hasArray())
   6.117 +            return ((CharBuffer)buffer.compact().flip()).array();
   6.118 +        else
   6.119 +            return buffer.toString().toCharArray();
   6.120 +    }
   6.121 +
   6.122 +    /**
   6.123 +     * The log to be used for error reporting.
   6.124 +     */
   6.125 +    protected Log log;
   6.126 +
   6.127 +    /** Encapsulates knowledge of paths
   6.128 +     */
   6.129 +    private Paths paths;
   6.130 +
   6.131 +    private Options options;
   6.132 +
   6.133 +    private final File uninited = new File("U N I N I T E D");
   6.134 +
   6.135 +    private final Set<JavaFileObject.Kind> sourceOrClass =
   6.136 +        EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS);
   6.137 +
   6.138 +    /** The standard output directory, primarily used for classes.
   6.139 +     *  Initialized by the "-d" option.
   6.140 +     *  If classOutDir = null, files are written into same directory as the sources
   6.141 +     *  they were generated from.
   6.142 +     */
   6.143 +    private File classOutDir = uninited;
   6.144 +
   6.145 +    /** The output directory, used when generating sources while processing annotations.
   6.146 +     *  Initialized by the "-s" option.
   6.147 +     */
   6.148 +    private File sourceOutDir = uninited;
   6.149 +
   6.150 +    protected boolean mmappedIO;
   6.151 +    protected boolean ignoreSymbolFile;
   6.152 +
   6.153 +    /**
   6.154 +     * User provided charset (through javax.tools).
   6.155 +     */
   6.156 +    protected Charset charset;
   6.157 +
   6.158 +    /**
   6.159 +     * Register a Context.Factory to create a JavacFileManager.
   6.160 +     */
   6.161 +    public static void preRegister(final Context context) {
   6.162 +        context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() {
   6.163 +            public JavaFileManager make() {
   6.164 +                return new JavacFileManager(context, true, null);
   6.165 +            }
   6.166 +        });
   6.167 +    }
   6.168 +
   6.169 +    /**
   6.170 +     * Create a JavacFileManager using a given context, optionally registering
   6.171 +     * it as the JavaFileManager for that context.
   6.172 +     */
   6.173 +    public JavacFileManager(Context context, boolean register, Charset charset) {
   6.174 +        if (register)
   6.175 +            context.put(JavaFileManager.class, this);
   6.176 +        byteBufferCache = new ByteBufferCache();
   6.177 +        this.charset = charset;
   6.178 +        setContext(context);
   6.179 +    }
   6.180 +
   6.181 +    /**
   6.182 +     * Set the context for JavacFileManager.
   6.183 +     */
   6.184 +    public void setContext(Context context) {
   6.185 +        log = Log.instance(context);
   6.186 +        if (paths == null) {
   6.187 +            paths = Paths.instance(context);
   6.188 +        } else {
   6.189 +            // Reuse the Paths object as it stores the locations that
   6.190 +            // have been set with setLocation, etc.
   6.191 +            paths.setContext(context);
   6.192 +        }
   6.193 +
   6.194 +        options = Options.instance(context);
   6.195 +
   6.196 +        useZipFileIndex = System.getProperty("useJavaUtilZip") == null;// TODO: options.get("useJavaUtilZip") == null;
   6.197 +        CHECK_ZIP_TIMESTAMP = System.getProperty("checkZipIndexTimestamp") != null;// TODO: options.get("checkZipIndexTimestamp") != null;
   6.198 +
   6.199 +        mmappedIO = options.get("mmappedIO") != null;
   6.200 +        ignoreSymbolFile = options.get("ignore.symbol.file") != null;
   6.201 +    }
   6.202 +
   6.203 +    public JavaFileObject getFileForInput(String name) {
   6.204 +        return getRegularFile(new File(name));
   6.205 +    }
   6.206 +
   6.207 +    public JavaFileObject getRegularFile(File file) {
   6.208 +        return new RegularFileObject(file);
   6.209 +    }
   6.210 +
   6.211 +    public JavaFileObject getFileForOutput(String classname,
   6.212 +                                           JavaFileObject.Kind kind,
   6.213 +                                           JavaFileObject sibling)
   6.214 +        throws IOException
   6.215 +    {
   6.216 +        return getJavaFileForOutput(CLASS_OUTPUT, classname, kind, sibling);
   6.217 +    }
   6.218 +
   6.219 +    public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
   6.220 +        ListBuffer<File> files = new ListBuffer<File>();
   6.221 +        for (String name : names)
   6.222 +            files.append(new File(nullCheck(name)));
   6.223 +        return getJavaFileObjectsFromFiles(files.toList());
   6.224 +    }
   6.225 +
   6.226 +    public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) {
   6.227 +        return getJavaFileObjectsFromStrings(Arrays.asList(nullCheck(names)));
   6.228 +    }
   6.229 +
   6.230 +    protected JavaFileObject.Kind getKind(String extension) {
   6.231 +        if (extension.equals(JavaFileObject.Kind.CLASS.extension))
   6.232 +            return JavaFileObject.Kind.CLASS;
   6.233 +        else if (extension.equals(JavaFileObject.Kind.SOURCE.extension))
   6.234 +            return JavaFileObject.Kind.SOURCE;
   6.235 +        else if (extension.equals(JavaFileObject.Kind.HTML.extension))
   6.236 +            return JavaFileObject.Kind.HTML;
   6.237 +        else
   6.238 +            return JavaFileObject.Kind.OTHER;
   6.239 +    }
   6.240 +
   6.241 +    private static boolean isValidName(String name) {
   6.242 +        // Arguably, isValidName should reject keywords (such as in SourceVersion.isName() ),
   6.243 +        // but the set of keywords depends on the source level, and we don't want
   6.244 +        // impls of JavaFileManager to have to be dependent on the source level.
   6.245 +        // Therefore we simply check that the argument is a sequence of identifiers
   6.246 +        // separated by ".".
   6.247 +        for (String s : name.split("\\.", -1)) {
   6.248 +            if (!SourceVersion.isIdentifier(s))
   6.249 +                return false;
   6.250 +        }
   6.251 +        return true;
   6.252 +    }
   6.253 +
   6.254 +    private static void validateClassName(String className) {
   6.255 +        if (!isValidName(className))
   6.256 +            throw new IllegalArgumentException("Invalid class name: " + className);
   6.257 +    }
   6.258 +
   6.259 +    private static void validatePackageName(String packageName) {
   6.260 +        if (packageName.length() > 0 && !isValidName(packageName))
   6.261 +            throw new IllegalArgumentException("Invalid packageName name: " + packageName);
   6.262 +    }
   6.263 +
   6.264 +    public static void testName(String name,
   6.265 +                                boolean isValidPackageName,
   6.266 +                                boolean isValidClassName)
   6.267 +    {
   6.268 +        try {
   6.269 +            validatePackageName(name);
   6.270 +            if (!isValidPackageName)
   6.271 +                throw new AssertionError("Invalid package name accepted: " + name);
   6.272 +            printAscii("Valid package name: \"%s\"", name);
   6.273 +        } catch (IllegalArgumentException e) {
   6.274 +            if (isValidPackageName)
   6.275 +                throw new AssertionError("Valid package name rejected: " + name);
   6.276 +            printAscii("Invalid package name: \"%s\"", name);
   6.277 +        }
   6.278 +        try {
   6.279 +            validateClassName(name);
   6.280 +            if (!isValidClassName)
   6.281 +                throw new AssertionError("Invalid class name accepted: " + name);
   6.282 +            printAscii("Valid class name: \"%s\"", name);
   6.283 +        } catch (IllegalArgumentException e) {
   6.284 +            if (isValidClassName)
   6.285 +                throw new AssertionError("Valid class name rejected: " + name);
   6.286 +            printAscii("Invalid class name: \"%s\"", name);
   6.287 +        }
   6.288 +    }
   6.289 +    private static void printAscii(String format, Object... args) {
   6.290 +        String message;
   6.291 +        try {
   6.292 +            final String ascii = "US-ASCII";
   6.293 +            message = new String(String.format(null, format, args).getBytes(ascii), ascii);
   6.294 +        } catch (java.io.UnsupportedEncodingException ex) {
   6.295 +            throw new AssertionError(ex);
   6.296 +        }
   6.297 +        System.out.println(message);
   6.298 +    }
   6.299 +
   6.300 +    /** Return external representation of name,
   6.301 +     *  converting '.' to File.separatorChar.
   6.302 +     */
   6.303 +    private static String externalizeFileName(CharSequence name) {
   6.304 +        return name.toString().replace('.', File.separatorChar);
   6.305 +    }
   6.306 +
   6.307 +    private static String externalizeFileName(CharSequence n, JavaFileObject.Kind kind) {
   6.308 +        return externalizeFileName(n) + kind.extension;
   6.309 +    }
   6.310 +
   6.311 +    private static String baseName(String fileName) {
   6.312 +        return fileName.substring(fileName.lastIndexOf(File.separatorChar) + 1);
   6.313 +    }
   6.314 +
   6.315 +    /**
   6.316 +     * Insert all files in subdirectory `subdirectory' of `directory' which end
   6.317 +     * in one of the extensions in `extensions' into packageSym.
   6.318 +     */
   6.319 +    private void listDirectory(File directory,
   6.320 +                               String subdirectory,
   6.321 +                               Set<JavaFileObject.Kind> fileKinds,
   6.322 +                               boolean recurse,
   6.323 +                               ListBuffer<JavaFileObject> l) {
   6.324 +        Archive archive = archives.get(directory);
   6.325 +
   6.326 +        boolean isFile = false;
   6.327 +        if (CHECK_ZIP_TIMESTAMP) {
   6.328 +            Boolean isf = isDirectory.get(directory);
   6.329 +            if (isf == null) {
   6.330 +                isFile = directory.isFile();
   6.331 +                isDirectory.put(directory, isFile);
   6.332 +            }
   6.333 +            else {
   6.334 +                isFile = directory.isFile();
   6.335 +            }
   6.336 +        }
   6.337 +        else {
   6.338 +            isFile = directory.isFile();
   6.339 +        }
   6.340 +
   6.341 +        if (archive != null || isFile) {
   6.342 +            if (archive == null) {
   6.343 +                try {
   6.344 +                    archive = openArchive(directory);
   6.345 +                } catch (IOException ex) {
   6.346 +                    log.error("error.reading.file",
   6.347 +                       directory, ex.getLocalizedMessage());
   6.348 +                    return;
   6.349 +                }
   6.350 +            }
   6.351 +            if (subdirectory.length() != 0) {
   6.352 +                if (!useZipFileIndex) {
   6.353 +                    subdirectory = subdirectory.replace('\\', '/');
   6.354 +                    if (!subdirectory.endsWith("/")) subdirectory = subdirectory + "/";
   6.355 +                }
   6.356 +                else {
   6.357 +                    if (File.separatorChar == '/') {
   6.358 +                        subdirectory = subdirectory.replace('\\', '/');
   6.359 +                    }
   6.360 +                    else {
   6.361 +                        subdirectory = subdirectory.replace('/', '\\');
   6.362 +                    }
   6.363 +
   6.364 +                    if (!subdirectory.endsWith(File.separator)) subdirectory = subdirectory + File.separator;
   6.365 +                }
   6.366 +            }
   6.367 +
   6.368 +            List<String> files = archive.getFiles(subdirectory);
   6.369 +            if (files != null) {
   6.370 +                for (String file; !files.isEmpty(); files = files.tail) {
   6.371 +                    file = files.head;
   6.372 +                    if (isValidFile(file, fileKinds)) {
   6.373 +                        l.append(archive.getFileObject(subdirectory, file));
   6.374 +                    }
   6.375 +                }
   6.376 +            }
   6.377 +            if (recurse) {
   6.378 +                for (String s: archive.getSubdirectories()) {
   6.379 +                    if (s.startsWith(subdirectory) && !s.equals(subdirectory)) {
   6.380 +                        // Because the archive map is a flat list of directories,
   6.381 +                        // the enclosing loop will pick up all child subdirectories.
   6.382 +                        // Therefore, there is no need to recurse deeper.
   6.383 +                        listDirectory(directory, s, fileKinds, false, l);
   6.384 +                    }
   6.385 +                }
   6.386 +            }
   6.387 +        } else {
   6.388 +            File d = subdirectory.length() != 0
   6.389 +                ? new File(directory, subdirectory)
   6.390 +                : directory;
   6.391 +            if (!caseMapCheck(d, subdirectory))
   6.392 +                return;
   6.393 +
   6.394 +            File[] files = d.listFiles();
   6.395 +            if (files == null)
   6.396 +                return;
   6.397 +
   6.398 +            for (File f: files) {
   6.399 +                String fname = f.getName();
   6.400 +                if (f.isDirectory()) {
   6.401 +                    if (recurse && SourceVersion.isIdentifier(fname)) {
   6.402 +                        listDirectory(directory,
   6.403 +                                      subdirectory + File.separator + fname,
   6.404 +                                      fileKinds,
   6.405 +                                      recurse,
   6.406 +                                      l);
   6.407 +                    }
   6.408 +                } else {
   6.409 +                    if (isValidFile(fname, fileKinds)) {
   6.410 +                        JavaFileObject fe =
   6.411 +                        new RegularFileObject(fname, new File(d, fname));
   6.412 +                        l.append(fe);
   6.413 +                    }
   6.414 +                }
   6.415 +            }
   6.416 +        }
   6.417 +    }
   6.418 +
   6.419 +    private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
   6.420 +        int lastDot = s.lastIndexOf(".");
   6.421 +        String extn = (lastDot == -1 ? s : s.substring(lastDot));
   6.422 +        JavaFileObject.Kind kind = getKind(extn);
   6.423 +        return fileKinds.contains(kind);
   6.424 +    }
   6.425 +
   6.426 +    private static final boolean fileSystemIsCaseSensitive =
   6.427 +        File.separatorChar == '/';
   6.428 +
   6.429 +    /** Hack to make Windows case sensitive. Test whether given path
   6.430 +     *  ends in a string of characters with the same case as given name.
   6.431 +     *  Ignore file separators in both path and name.
   6.432 +     */
   6.433 +    private boolean caseMapCheck(File f, String name) {
   6.434 +        if (fileSystemIsCaseSensitive) return true;
   6.435 +        // Note that getCanonicalPath() returns the case-sensitive
   6.436 +        // spelled file name.
   6.437 +        String path;
   6.438 +        try {
   6.439 +            path = f.getCanonicalPath();
   6.440 +        } catch (IOException ex) {
   6.441 +            return false;
   6.442 +        }
   6.443 +        char[] pcs = path.toCharArray();
   6.444 +        char[] ncs = name.toCharArray();
   6.445 +        int i = pcs.length - 1;
   6.446 +        int j = ncs.length - 1;
   6.447 +        while (i >= 0 && j >= 0) {
   6.448 +            while (i >= 0 && pcs[i] == File.separatorChar) i--;
   6.449 +            while (j >= 0 && ncs[j] == File.separatorChar) j--;
   6.450 +            if (i >= 0 && j >= 0) {
   6.451 +                if (pcs[i] != ncs[j]) return false;
   6.452 +                i--;
   6.453 +                j--;
   6.454 +            }
   6.455 +        }
   6.456 +        return j < 0;
   6.457 +    }
   6.458 +
   6.459 +    /**
   6.460 +     * An archive provides a flat directory structure of a ZipFile by
   6.461 +     * mapping directory names to lists of files (basenames).
   6.462 +     */
   6.463 +    public interface Archive {
   6.464 +        void close() throws IOException;
   6.465 +
   6.466 +        boolean contains(String name);
   6.467 +
   6.468 +        JavaFileObject getFileObject(String subdirectory, String file);
   6.469 +
   6.470 +        List<String> getFiles(String subdirectory);
   6.471 +
   6.472 +        Set<String> getSubdirectories();
   6.473 +    }
   6.474 +
   6.475 +    public class ZipArchive implements Archive {
   6.476 +        protected final Map<String,List<String>> map;
   6.477 +        protected final ZipFile zdir;
   6.478 +        public ZipArchive(ZipFile zdir) throws IOException {
   6.479 +            this.zdir = zdir;
   6.480 +            this.map = new HashMap<String,List<String>>();
   6.481 +            for (Enumeration<? extends ZipEntry> e = zdir.entries(); e.hasMoreElements(); ) {
   6.482 +                ZipEntry entry;
   6.483 +                try {
   6.484 +                    entry = e.nextElement();
   6.485 +                } catch (InternalError ex) {
   6.486 +                    IOException io = new IOException();
   6.487 +                    io.initCause(ex); // convenience constructors added in Mustang :-(
   6.488 +                    throw io;
   6.489 +                }
   6.490 +                addZipEntry(entry);
   6.491 +            }
   6.492 +        }
   6.493 +
   6.494 +        void addZipEntry(ZipEntry entry) {
   6.495 +            String name = entry.getName();
   6.496 +            int i = name.lastIndexOf('/');
   6.497 +            String dirname = name.substring(0, i+1);
   6.498 +            String basename = name.substring(i+1);
   6.499 +            if (basename.length() == 0)
   6.500 +                return;
   6.501 +            List<String> list = map.get(dirname);
   6.502 +            if (list == null)
   6.503 +                list = List.nil();
   6.504 +            list = list.prepend(basename);
   6.505 +            map.put(dirname, list);
   6.506 +        }
   6.507 +
   6.508 +        public boolean contains(String name) {
   6.509 +            int i = name.lastIndexOf('/');
   6.510 +            String dirname = name.substring(0, i+1);
   6.511 +            String basename = name.substring(i+1);
   6.512 +            if (basename.length() == 0)
   6.513 +                return false;
   6.514 +            List<String> list = map.get(dirname);
   6.515 +            return (list != null && list.contains(basename));
   6.516 +        }
   6.517 +
   6.518 +        public List<String> getFiles(String subdirectory) {
   6.519 +            return map.get(subdirectory);
   6.520 +        }
   6.521 +
   6.522 +        public JavaFileObject getFileObject(String subdirectory, String file) {
   6.523 +            ZipEntry ze = zdir.getEntry(subdirectory + file);
   6.524 +            return new ZipFileObject(file, zdir, ze);
   6.525 +        }
   6.526 +
   6.527 +        public Set<String> getSubdirectories() {
   6.528 +            return map.keySet();
   6.529 +        }
   6.530 +
   6.531 +        public void close() throws IOException {
   6.532 +            zdir.close();
   6.533 +        }
   6.534 +    }
   6.535 +
   6.536 +    public class SymbolArchive extends ZipArchive {
   6.537 +        final File origFile;
   6.538 +        public SymbolArchive(File orig, ZipFile zdir) throws IOException {
   6.539 +            super(zdir);
   6.540 +            this.origFile = orig;
   6.541 +        }
   6.542 +
   6.543 +        @Override
   6.544 +        void addZipEntry(ZipEntry entry) {
   6.545 +            // called from super constructor, may not refer to origFile.
   6.546 +            String name = entry.getName();
   6.547 +            if (!name.startsWith(symbolFilePrefix))
   6.548 +                return;
   6.549 +            name = name.substring(symbolFilePrefix.length());
   6.550 +            int i = name.lastIndexOf('/');
   6.551 +            String dirname = name.substring(0, i+1);
   6.552 +            String basename = name.substring(i+1);
   6.553 +            if (basename.length() == 0)
   6.554 +                return;
   6.555 +            List<String> list = map.get(dirname);
   6.556 +            if (list == null)
   6.557 +                list = List.nil();
   6.558 +            list = list.prepend(basename);
   6.559 +            map.put(dirname, list);
   6.560 +        }
   6.561 +
   6.562 +        @Override
   6.563 +        public JavaFileObject getFileObject(String subdirectory, String file) {
   6.564 +            return super.getFileObject(symbolFilePrefix + subdirectory, file);
   6.565 +        }
   6.566 +    }
   6.567 +
   6.568 +    public class MissingArchive implements Archive {
   6.569 +        final File zipFileName;
   6.570 +        public MissingArchive(File name) {
   6.571 +            zipFileName = name;
   6.572 +        }
   6.573 +        public boolean contains(String name) {
   6.574 +              return false;
   6.575 +        }
   6.576 +
   6.577 +        public void close() {
   6.578 +        }
   6.579 +
   6.580 +        public JavaFileObject getFileObject(String subdirectory, String file) {
   6.581 +            return null;
   6.582 +        }
   6.583 +
   6.584 +        public List<String> getFiles(String subdirectory) {
   6.585 +            return List.nil();
   6.586 +        }
   6.587 +
   6.588 +        public Set<String> getSubdirectories() {
   6.589 +            return Collections.emptySet();
   6.590 +        }
   6.591 +    }
   6.592 +
   6.593 +    /** A directory of zip files already opened.
   6.594 +     */
   6.595 +    Map<File, Archive> archives = new HashMap<File,Archive>();
   6.596 +
   6.597 +    /** Open a new zip file directory.
   6.598 +     */
   6.599 +    protected Archive openArchive(File zipFileName) throws IOException {
   6.600 +        Archive archive = archives.get(zipFileName);
   6.601 +        if (archive == null) {
   6.602 +            File origZipFileName = zipFileName;
   6.603 +            if (!ignoreSymbolFile && paths.isBootClassPathRtJar(zipFileName)) {
   6.604 +                File file = zipFileName.getParentFile().getParentFile(); // ${java.home}
   6.605 +                if (new File(file.getName()).equals(new File("jre")))
   6.606 +                    file = file.getParentFile();
   6.607 +                // file == ${jdk.home}
   6.608 +                for (String name : symbolFileLocation)
   6.609 +                    file = new File(file, name);
   6.610 +                // file == ${jdk.home}/lib/ct.sym
   6.611 +                if (file.exists())
   6.612 +                    zipFileName = file;
   6.613 +            }
   6.614 +
   6.615 +            try {
   6.616 +
   6.617 +                ZipFile zdir = null;
   6.618 +
   6.619 +                boolean usePreindexedCache = false;
   6.620 +                String preindexCacheLocation = null;
   6.621 +
   6.622 +                if (!useZipFileIndex) {
   6.623 +                    zdir = new ZipFile(zipFileName);
   6.624 +                }
   6.625 +                else {
   6.626 +                    usePreindexedCache = options.get("usezipindex") != null;
   6.627 +                    preindexCacheLocation = options.get("java.io.tmpdir");
   6.628 +                    String optCacheLoc = options.get("cachezipindexdir");
   6.629 +
   6.630 +                    if (optCacheLoc != null && optCacheLoc.length() != 0) {
   6.631 +                        if (optCacheLoc.startsWith("\"")) {
   6.632 +                            if (optCacheLoc.endsWith("\"")) {
   6.633 +                                optCacheLoc = optCacheLoc.substring(1, optCacheLoc.length() - 1);
   6.634 +                            }
   6.635 +                           else {
   6.636 +                                optCacheLoc = optCacheLoc.substring(1);
   6.637 +                            }
   6.638 +                        }
   6.639 +
   6.640 +                        File cacheDir = new File(optCacheLoc);
   6.641 +                        if (cacheDir.exists() && cacheDir.canWrite()) {
   6.642 +                            preindexCacheLocation = optCacheLoc;
   6.643 +                            if (!preindexCacheLocation.endsWith("/") &&
   6.644 +                                !preindexCacheLocation.endsWith(File.separator)) {
   6.645 +                                preindexCacheLocation += File.separator;
   6.646 +                            }
   6.647 +                        }
   6.648 +                    }
   6.649 +                }
   6.650 +
   6.651 +                if (origZipFileName == zipFileName) {
   6.652 +                    if (!useZipFileIndex) {
   6.653 +                        archive = new ZipArchive(zdir);
   6.654 +                    } else {
   6.655 +                        archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, 0,
   6.656 +                                usePreindexedCache, preindexCacheLocation, options.get("writezipindexfiles") != null));
   6.657 +                    }
   6.658 +                }
   6.659 +                else {
   6.660 +                    if (!useZipFileIndex) {
   6.661 +                        archive = new SymbolArchive(origZipFileName, zdir);
   6.662 +                    }
   6.663 +                    else {
   6.664 +                        archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, symbolFilePrefixLength,
   6.665 +                                usePreindexedCache, preindexCacheLocation, options.get("writezipindexfiles") != null));
   6.666 +                    }
   6.667 +                }
   6.668 +            } catch (FileNotFoundException ex) {
   6.669 +                archive = new MissingArchive(zipFileName);
   6.670 +            } catch (IOException ex) {
   6.671 +                log.error("error.reading.file", zipFileName, ex.getLocalizedMessage());
   6.672 +                archive = new MissingArchive(zipFileName);
   6.673 +            }
   6.674 +
   6.675 +            archives.put(origZipFileName, archive);
   6.676 +        }
   6.677 +        return archive;
   6.678 +    }
   6.679 +
   6.680 +    /** Flush any output resources.
   6.681 +     */
   6.682 +    public void flush() {
   6.683 +        contentCache.clear();
   6.684 +    }
   6.685 +
   6.686 +    /**
   6.687 +     * Close the JavaFileManager, releasing resources.
   6.688 +     */
   6.689 +    public void close() {
   6.690 +        for (Iterator<Archive> i = archives.values().iterator(); i.hasNext(); ) {
   6.691 +            Archive a = i.next();
   6.692 +            i.remove();
   6.693 +            try {
   6.694 +                a.close();
   6.695 +            } catch (IOException e) {
   6.696 +            }
   6.697 +        }
   6.698 +    }
   6.699 +
   6.700 +    private Map<JavaFileObject, SoftReference<CharBuffer>> contentCache = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
   6.701 +
   6.702 +    private String defaultEncodingName;
   6.703 +    private String getDefaultEncodingName() {
   6.704 +        if (defaultEncodingName == null) {
   6.705 +            defaultEncodingName =
   6.706 +                new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
   6.707 +        }
   6.708 +        return defaultEncodingName;
   6.709 +    }
   6.710 +
   6.711 +    protected String getEncodingName() {
   6.712 +        String encName = options.get(OptionName.ENCODING);
   6.713 +        if (encName == null)
   6.714 +            return getDefaultEncodingName();
   6.715 +        else
   6.716 +            return encName;
   6.717 +    }
   6.718 +
   6.719 +    protected Source getSource() {
   6.720 +        String sourceName = options.get(OptionName.SOURCE);
   6.721 +        Source source = null;
   6.722 +        if (sourceName != null)
   6.723 +            source = Source.lookup(sourceName);
   6.724 +        return (source != null ? source : Source.DEFAULT);
   6.725 +    }
   6.726 +
   6.727 +    /**
   6.728 +     * Make a byte buffer from an input stream.
   6.729 +     */
   6.730 +    private ByteBuffer makeByteBuffer(InputStream in)
   6.731 +        throws IOException {
   6.732 +        int limit = in.available();
   6.733 +        if (mmappedIO && in instanceof FileInputStream) {
   6.734 +            // Experimental memory mapped I/O
   6.735 +            FileInputStream fin = (FileInputStream)in;
   6.736 +            return fin.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, limit);
   6.737 +        }
   6.738 +        if (limit < 1024) limit = 1024;
   6.739 +        ByteBuffer result = byteBufferCache.get(limit);
   6.740 +        int position = 0;
   6.741 +        while (in.available() != 0) {
   6.742 +            if (position >= limit)
   6.743 +                // expand buffer
   6.744 +                result = ByteBuffer.
   6.745 +                    allocate(limit <<= 1).
   6.746 +                    put((ByteBuffer)result.flip());
   6.747 +            int count = in.read(result.array(),
   6.748 +                position,
   6.749 +                limit - position);
   6.750 +            if (count < 0) break;
   6.751 +            result.position(position += count);
   6.752 +        }
   6.753 +        return (ByteBuffer)result.flip();
   6.754 +    }
   6.755 +
   6.756 +    /**
   6.757 +     * A single-element cache of direct byte buffers.
   6.758 +     */
   6.759 +    private static class ByteBufferCache {
   6.760 +        private ByteBuffer cached;
   6.761 +        ByteBuffer get(int capacity) {
   6.762 +            if (capacity < 20480) capacity = 20480;
   6.763 +            ByteBuffer result =
   6.764 +                (cached != null && cached.capacity() >= capacity)
   6.765 +                ? (ByteBuffer)cached.clear()
   6.766 +                : ByteBuffer.allocate(capacity + capacity>>1);
   6.767 +            cached = null;
   6.768 +            return result;
   6.769 +        }
   6.770 +        void put(ByteBuffer x) {
   6.771 +            cached = x;
   6.772 +        }
   6.773 +    }
   6.774 +    private final ByteBufferCache byteBufferCache;
   6.775 +
   6.776 +    private CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
   6.777 +        Charset charset = (this.charset == null)
   6.778 +            ? Charset.forName(encodingName)
   6.779 +            : this.charset;
   6.780 +        CharsetDecoder decoder = charset.newDecoder();
   6.781 +
   6.782 +        CodingErrorAction action;
   6.783 +        if (ignoreEncodingErrors)
   6.784 +            action = CodingErrorAction.REPLACE;
   6.785 +        else
   6.786 +            action = CodingErrorAction.REPORT;
   6.787 +
   6.788 +        return decoder
   6.789 +            .onMalformedInput(action)
   6.790 +            .onUnmappableCharacter(action);
   6.791 +    }
   6.792 +
   6.793 +    /**
   6.794 +     * Decode a ByteBuffer into a CharBuffer.
   6.795 +     */
   6.796 +    private CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
   6.797 +        String encodingName = getEncodingName();
   6.798 +        CharsetDecoder decoder;
   6.799 +        try {
   6.800 +            decoder = getDecoder(encodingName, ignoreEncodingErrors);
   6.801 +        } catch (IllegalCharsetNameException e) {
   6.802 +            log.error("unsupported.encoding", encodingName);
   6.803 +            return (CharBuffer)CharBuffer.allocate(1).flip();
   6.804 +        } catch (UnsupportedCharsetException e) {
   6.805 +            log.error("unsupported.encoding", encodingName);
   6.806 +            return (CharBuffer)CharBuffer.allocate(1).flip();
   6.807 +        }
   6.808 +
   6.809 +        // slightly overestimate the buffer size to avoid reallocation.
   6.810 +        float factor =
   6.811 +            decoder.averageCharsPerByte() * 0.8f +
   6.812 +            decoder.maxCharsPerByte() * 0.2f;
   6.813 +        CharBuffer dest = CharBuffer.
   6.814 +            allocate(10 + (int)(inbuf.remaining()*factor));
   6.815 +
   6.816 +        while (true) {
   6.817 +            CoderResult result = decoder.decode(inbuf, dest, true);
   6.818 +            dest.flip();
   6.819 +
   6.820 +            if (result.isUnderflow()) { // done reading
   6.821 +                // make sure there is at least one extra character
   6.822 +                if (dest.limit() == dest.capacity()) {
   6.823 +                    dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
   6.824 +                    dest.flip();
   6.825 +                }
   6.826 +                return dest;
   6.827 +            } else if (result.isOverflow()) { // buffer too small; expand
   6.828 +                int newCapacity =
   6.829 +                    10 + dest.capacity() +
   6.830 +                    (int)(inbuf.remaining()*decoder.maxCharsPerByte());
   6.831 +                dest = CharBuffer.allocate(newCapacity).put(dest);
   6.832 +            } else if (result.isMalformed() || result.isUnmappable()) {
   6.833 +                // bad character in input
   6.834 +
   6.835 +                // report coding error (warn only pre 1.5)
   6.836 +                if (!getSource().allowEncodingErrors()) {
   6.837 +                    log.error(new SimpleDiagnosticPosition(dest.limit()),
   6.838 +                              "illegal.char.for.encoding",
   6.839 +                              charset == null ? encodingName : charset.name());
   6.840 +                } else {
   6.841 +                    log.warning(new SimpleDiagnosticPosition(dest.limit()),
   6.842 +                                "illegal.char.for.encoding",
   6.843 +                                charset == null ? encodingName : charset.name());
   6.844 +                }
   6.845 +
   6.846 +                // skip past the coding error
   6.847 +                inbuf.position(inbuf.position() + result.length());
   6.848 +
   6.849 +                // undo the flip() to prepare the output buffer
   6.850 +                // for more translation
   6.851 +                dest.position(dest.limit());
   6.852 +                dest.limit(dest.capacity());
   6.853 +                dest.put((char)0xfffd); // backward compatible
   6.854 +            } else {
   6.855 +                throw new AssertionError(result);
   6.856 +            }
   6.857 +        }
   6.858 +        // unreached
   6.859 +    }
   6.860 +
   6.861 +    public ClassLoader getClassLoader(Location location) {
   6.862 +        nullCheck(location);
   6.863 +        Iterable<? extends File> path = getLocation(location);
   6.864 +        if (path == null)
   6.865 +            return null;
   6.866 +        ListBuffer<URL> lb = new ListBuffer<URL>();
   6.867 +        for (File f: path) {
   6.868 +            try {
   6.869 +                lb.append(f.toURI().toURL());
   6.870 +            } catch (MalformedURLException e) {
   6.871 +                throw new AssertionError(e);
   6.872 +            }
   6.873 +        }
   6.874 +        return new URLClassLoader(lb.toArray(new URL[lb.size()]),
   6.875 +            getClass().getClassLoader());
   6.876 +    }
   6.877 +
   6.878 +    public Iterable<JavaFileObject> list(Location location,
   6.879 +                                         String packageName,
   6.880 +                                         Set<JavaFileObject.Kind> kinds,
   6.881 +                                         boolean recurse)
   6.882 +        throws IOException
   6.883 +    {
   6.884 +        // validatePackageName(packageName);
   6.885 +        nullCheck(packageName);
   6.886 +        nullCheck(kinds);
   6.887 +
   6.888 +        Iterable<? extends File> path = getLocation(location);
   6.889 +        if (path == null)
   6.890 +            return List.nil();
   6.891 +        String subdirectory = externalizeFileName(packageName);
   6.892 +        ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
   6.893 +
   6.894 +        for (File directory : path)
   6.895 +            listDirectory(directory, subdirectory, kinds, recurse, results);
   6.896 +
   6.897 +        return results.toList();
   6.898 +    }
   6.899 +
   6.900 +    public String inferBinaryName(Location location, JavaFileObject file) {
   6.901 +        file.getClass(); // null check
   6.902 +        location.getClass(); // null check
   6.903 +        // Need to match the path semantics of list(location, ...)
   6.904 +        Iterable<? extends File> path = getLocation(location);
   6.905 +        if (path == null) {
   6.906 +            //System.err.println("Path for " + location + " is null");
   6.907 +            return null;
   6.908 +        }
   6.909 +        //System.err.println("Path for " + location + " is " + path);
   6.910 +
   6.911 +        if (file instanceof RegularFileObject) {
   6.912 +            RegularFileObject r = (RegularFileObject) file;
   6.913 +            String rPath = r.getPath();
   6.914 +            //System.err.println("RegularFileObject " + file + " " +r.getPath());
   6.915 +            for (File dir: path) {
   6.916 +                //System.err.println("dir: " + dir);
   6.917 +                String dPath = dir.getPath();
   6.918 +                if (!dPath.endsWith(File.separator))
   6.919 +                    dPath += File.separator;
   6.920 +                if (rPath.regionMatches(true, 0, dPath, 0, dPath.length())
   6.921 +                    && new File(rPath.substring(0, dPath.length())).equals(new File(dPath))) {
   6.922 +                    String relativeName = rPath.substring(dPath.length());
   6.923 +                    return removeExtension(relativeName).replace(File.separatorChar, '.');
   6.924 +                }
   6.925 +            }
   6.926 +        } else if (file instanceof ZipFileObject) {
   6.927 +            ZipFileObject z = (ZipFileObject) file;
   6.928 +            String entryName = z.getZipEntryName();
   6.929 +            if (entryName.startsWith(symbolFilePrefix))
   6.930 +                entryName = entryName.substring(symbolFilePrefix.length());
   6.931 +            return removeExtension(entryName).replace('/', '.');
   6.932 +        } else if (file instanceof ZipFileIndexFileObject) {
   6.933 +            ZipFileIndexFileObject z = (ZipFileIndexFileObject) file;
   6.934 +            String entryName = z.getZipEntryName();
   6.935 +            if (entryName.startsWith(symbolFilePrefix))
   6.936 +                entryName = entryName.substring(symbolFilePrefix.length());
   6.937 +            return removeExtension(entryName).replace(File.separatorChar, '.');
   6.938 +        } else
   6.939 +            throw new IllegalArgumentException(file.getClass().getName());
   6.940 +        // System.err.println("inferBinaryName failed for " + file);
   6.941 +        return null;
   6.942 +    }
   6.943 +    // where
   6.944 +        private static String removeExtension(String fileName) {
   6.945 +            int lastDot = fileName.lastIndexOf(".");
   6.946 +            return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
   6.947 +        }
   6.948 +
   6.949 +    public boolean isSameFile(FileObject a, FileObject b) {
   6.950 +        nullCheck(a);
   6.951 +        nullCheck(b);
   6.952 +        if (!(a instanceof BaseFileObject))
   6.953 +            throw new IllegalArgumentException("Not supported: " + a);
   6.954 +        if (!(b instanceof BaseFileObject))
   6.955 +            throw new IllegalArgumentException("Not supported: " + b);
   6.956 +        return a.equals(b);
   6.957 +    }
   6.958 +
   6.959 +    public boolean handleOption(String current, Iterator<String> remaining) {
   6.960 +        for (JavacOption o: javacFileManagerOptions) {
   6.961 +            if (o.matches(current))  {
   6.962 +                if (o.hasArg()) {
   6.963 +                    if (remaining.hasNext()) {
   6.964 +                        if (!o.process(options, current, remaining.next()))
   6.965 +                            return true;
   6.966 +                    }
   6.967 +                } else {
   6.968 +                    if (!o.process(options, current))
   6.969 +                        return true;
   6.970 +                }
   6.971 +                // operand missing, or process returned false
   6.972 +                throw new IllegalArgumentException(current);
   6.973 +            }
   6.974 +        }
   6.975 +
   6.976 +        return false;
   6.977 +    }
   6.978 +    // where
   6.979 +        private static JavacOption[] javacFileManagerOptions =
   6.980 +            RecognizedOptions.getJavacFileManagerOptions(
   6.981 +            new RecognizedOptions.GrumpyHelper());
   6.982 +
   6.983 +    public int isSupportedOption(String option) {
   6.984 +        for (JavacOption o : javacFileManagerOptions) {
   6.985 +            if (o.matches(option))
   6.986 +                return o.hasArg() ? 1 : 0;
   6.987 +        }
   6.988 +        return -1;
   6.989 +    }
   6.990 +
   6.991 +    public boolean hasLocation(Location location) {
   6.992 +        return getLocation(location) != null;
   6.993 +    }
   6.994 +
   6.995 +    public JavaFileObject getJavaFileForInput(Location location,
   6.996 +                                              String className,
   6.997 +                                              JavaFileObject.Kind kind)
   6.998 +        throws IOException
   6.999 +    {
  6.1000 +        nullCheck(location);
  6.1001 +        // validateClassName(className);
  6.1002 +        nullCheck(className);
  6.1003 +        nullCheck(kind);
  6.1004 +        if (!sourceOrClass.contains(kind))
  6.1005 +            throw new IllegalArgumentException("Invalid kind " + kind);
  6.1006 +        return getFileForInput(location, externalizeFileName(className, kind));
  6.1007 +    }
  6.1008 +
  6.1009 +    public FileObject getFileForInput(Location location,
  6.1010 +                                      String packageName,
  6.1011 +                                      String relativeName)
  6.1012 +        throws IOException
  6.1013 +    {
  6.1014 +        nullCheck(location);
  6.1015 +        // validatePackageName(packageName);
  6.1016 +        nullCheck(packageName);
  6.1017 +        if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
  6.1018 +            throw new IllegalArgumentException("Invalid relative name: " + relativeName);
  6.1019 +        String name = packageName.length() == 0
  6.1020 +            ? relativeName
  6.1021 +            : new File(externalizeFileName(packageName), relativeName).getPath();
  6.1022 +        return getFileForInput(location, name);
  6.1023 +    }
  6.1024 +
  6.1025 +    private JavaFileObject getFileForInput(Location location, String name) throws IOException {
  6.1026 +        Iterable<? extends File> path = getLocation(location);
  6.1027 +        if (path == null)
  6.1028 +            return null;
  6.1029 +
  6.1030 +        for (File dir: path) {
  6.1031 +            if (dir.isDirectory()) {
  6.1032 +                File f = new File(dir, name.replace('/', File.separatorChar));
  6.1033 +                if (f.exists())
  6.1034 +                    return new RegularFileObject(f);
  6.1035 +            } else {
  6.1036 +                Archive a = openArchive(dir);
  6.1037 +                if (a.contains(name)) {
  6.1038 +                    int i = name.lastIndexOf('/');
  6.1039 +                    String dirname = name.substring(0, i+1);
  6.1040 +                    String basename = name.substring(i+1);
  6.1041 +                    return a.getFileObject(dirname, basename);
  6.1042 +                }
  6.1043 +
  6.1044 +            }
  6.1045 +        }
  6.1046 +        return null;
  6.1047 +
  6.1048 +    }
  6.1049 +
  6.1050 +    public JavaFileObject getJavaFileForOutput(Location location,
  6.1051 +                                               String className,
  6.1052 +                                               JavaFileObject.Kind kind,
  6.1053 +                                               FileObject sibling)
  6.1054 +        throws IOException
  6.1055 +    {
  6.1056 +        nullCheck(location);
  6.1057 +        // validateClassName(className);
  6.1058 +        nullCheck(className);
  6.1059 +        nullCheck(kind);
  6.1060 +        if (!sourceOrClass.contains(kind))
  6.1061 +            throw new IllegalArgumentException("Invalid kind " + kind);
  6.1062 +        return getFileForOutput(location, externalizeFileName(className, kind), sibling);
  6.1063 +    }
  6.1064 +
  6.1065 +    public FileObject getFileForOutput(Location location,
  6.1066 +                                       String packageName,
  6.1067 +                                       String relativeName,
  6.1068 +                                       FileObject sibling)
  6.1069 +        throws IOException
  6.1070 +    {
  6.1071 +        nullCheck(location);
  6.1072 +        // validatePackageName(packageName);
  6.1073 +        nullCheck(packageName);
  6.1074 +        if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
  6.1075 +            throw new IllegalArgumentException("relativeName is invalid");
  6.1076 +        String name = packageName.length() == 0
  6.1077 +            ? relativeName
  6.1078 +            : new File(externalizeFileName(packageName), relativeName).getPath();
  6.1079 +        return getFileForOutput(location, name, sibling);
  6.1080 +    }
  6.1081 +
  6.1082 +    private JavaFileObject getFileForOutput(Location location,
  6.1083 +                                            String fileName,
  6.1084 +                                            FileObject sibling)
  6.1085 +        throws IOException
  6.1086 +    {
  6.1087 +        File dir;
  6.1088 +        if (location == CLASS_OUTPUT) {
  6.1089 +            if (getClassOutDir() != null) {
  6.1090 +                dir = getClassOutDir();
  6.1091 +            } else {
  6.1092 +                File siblingDir = null;
  6.1093 +                if (sibling != null && sibling instanceof RegularFileObject) {
  6.1094 +                    siblingDir = ((RegularFileObject)sibling).f.getParentFile();
  6.1095 +                }
  6.1096 +                return new RegularFileObject(new File(siblingDir, baseName(fileName)));
  6.1097 +            }
  6.1098 +        } else if (location == SOURCE_OUTPUT) {
  6.1099 +            dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
  6.1100 +        } else {
  6.1101 +            Iterable<? extends File> path = paths.getPathForLocation(location);
  6.1102 +            dir = null;
  6.1103 +            for (File f: path) {
  6.1104 +                dir = f;
  6.1105 +                break;
  6.1106 +            }
  6.1107 +        }
  6.1108 +
  6.1109 +        File file = (dir == null ? new File(fileName) : new File(dir, fileName));
  6.1110 +        return new RegularFileObject(file);
  6.1111 +
  6.1112 +    }
  6.1113 +
  6.1114 +    public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(
  6.1115 +        Iterable<? extends File> files)
  6.1116 +    {
  6.1117 +        ArrayList<RegularFileObject> result;
  6.1118 +        if (files instanceof Collection)
  6.1119 +            result = new ArrayList<RegularFileObject>(((Collection)files).size());
  6.1120 +        else
  6.1121 +            result = new ArrayList<RegularFileObject>();
  6.1122 +        for (File f: files)
  6.1123 +            result.add(new RegularFileObject(nullCheck(f)));
  6.1124 +        return result;
  6.1125 +    }
  6.1126 +
  6.1127 +    public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
  6.1128 +        return getJavaFileObjectsFromFiles(Arrays.asList(nullCheck(files)));
  6.1129 +    }
  6.1130 +
  6.1131 +    public void setLocation(Location location,
  6.1132 +                            Iterable<? extends File> path)
  6.1133 +        throws IOException
  6.1134 +    {
  6.1135 +        nullCheck(location);
  6.1136 +        paths.lazy();
  6.1137 +
  6.1138 +        final File dir = location.isOutputLocation() ? getOutputDirectory(path) : null;
  6.1139 +
  6.1140 +        if (location == CLASS_OUTPUT)
  6.1141 +            classOutDir = getOutputLocation(dir, D);
  6.1142 +        else if (location == SOURCE_OUTPUT)
  6.1143 +            sourceOutDir = getOutputLocation(dir, S);
  6.1144 +        else
  6.1145 +            paths.setPathForLocation(location, path);
  6.1146 +    }
  6.1147 +    // where
  6.1148 +        private File getOutputDirectory(Iterable<? extends File> path) throws IOException {
  6.1149 +            if (path == null)
  6.1150 +                return null;
  6.1151 +            Iterator<? extends File> pathIter = path.iterator();
  6.1152 +            if (!pathIter.hasNext())
  6.1153 +                throw new IllegalArgumentException("empty path for directory");
  6.1154 +            File dir = pathIter.next();
  6.1155 +            if (pathIter.hasNext())
  6.1156 +                throw new IllegalArgumentException("path too long for directory");
  6.1157 +            if (!dir.exists())
  6.1158 +                throw new FileNotFoundException(dir + ": does not exist");
  6.1159 +            else if (!dir.isDirectory())
  6.1160 +                throw new IOException(dir + ": not a directory");
  6.1161 +            return dir;
  6.1162 +        }
  6.1163 +
  6.1164 +    private File getOutputLocation(File dir, OptionName defaultOptionName) {
  6.1165 +        if (dir != null)
  6.1166 +            return dir;
  6.1167 +        String arg = options.get(defaultOptionName);
  6.1168 +        if (arg == null)
  6.1169 +            return null;
  6.1170 +        return new File(arg);
  6.1171 +    }
  6.1172 +
  6.1173 +    public Iterable<? extends File> getLocation(Location location) {
  6.1174 +        nullCheck(location);
  6.1175 +        paths.lazy();
  6.1176 +        if (location == CLASS_OUTPUT) {
  6.1177 +            return (getClassOutDir() == null ? null : List.of(getClassOutDir()));
  6.1178 +        } else if (location == SOURCE_OUTPUT) {
  6.1179 +            return (getSourceOutDir() == null ? null : List.of(getSourceOutDir()));
  6.1180 +        } else
  6.1181 +            return paths.getPathForLocation(location);
  6.1182 +    }
  6.1183 +
  6.1184 +    private File getClassOutDir() {
  6.1185 +        if (classOutDir == uninited)
  6.1186 +            classOutDir = getOutputLocation(null, D);
  6.1187 +        return classOutDir;
  6.1188 +    }
  6.1189 +
  6.1190 +    private File getSourceOutDir() {
  6.1191 +        if (sourceOutDir == uninited)
  6.1192 +            sourceOutDir = getOutputLocation(null, S);
  6.1193 +        return sourceOutDir;
  6.1194 +    }
  6.1195 +
  6.1196 +    /**
  6.1197 +     * Enforces the specification of a "relative" URI as used in
  6.1198 +     * {@linkplain #getFileForInput(Location,String,URI)
  6.1199 +     * getFileForInput}.  This method must follow the rules defined in
  6.1200 +     * that method, do not make any changes without consulting the
  6.1201 +     * specification.
  6.1202 +     */
  6.1203 +    protected static boolean isRelativeUri(URI uri) {
  6.1204 +        if (uri.isAbsolute())
  6.1205 +            return false;
  6.1206 +        String path = uri.normalize().getPath();
  6.1207 +        if (path.length() == 0 /* isEmpty() is mustang API */)
  6.1208 +            return false;
  6.1209 +        char first = path.charAt(0);
  6.1210 +        return first != '.' && first != '/';
  6.1211 +    }
  6.1212 +
  6.1213 +    /**
  6.1214 +     * Converts a relative file name to a relative URI.  This is
  6.1215 +     * different from File.toURI as this method does not canonicalize
  6.1216 +     * the file before creating the URI.  Furthermore, no schema is
  6.1217 +     * used.
  6.1218 +     * @param file a relative file name
  6.1219 +     * @return a relative URI
  6.1220 +     * @throws IllegalArgumentException if the file name is not
  6.1221 +     * relative according to the definition given in {@link
  6.1222 +     * javax.tools.JavaFileManager#getFileForInput}
  6.1223 +     */
  6.1224 +    public static String getRelativeName(File file) {
  6.1225 +        if (!file.isAbsolute()) {
  6.1226 +            String result = file.getPath().replace(File.separatorChar, '/');
  6.1227 +            if (JavacFileManager.isRelativeUri(URI.create(result))) // FIXME 6419701
  6.1228 +                return result;
  6.1229 +        }
  6.1230 +        throw new IllegalArgumentException("Invalid relative path: " + file);
  6.1231 +    }
  6.1232 +
  6.1233 +    @SuppressWarnings("deprecation") // bug 6410637
  6.1234 +    public static String getJavacFileName(FileObject file) {
  6.1235 +        if (file instanceof BaseFileObject)
  6.1236 +            return ((BaseFileObject)file).getPath();
  6.1237 +        URI uri = file.toUri();
  6.1238 +        String scheme = uri.getScheme();
  6.1239 +        if (scheme == null || scheme.equals("file") || scheme.equals("jar"))
  6.1240 +            return uri.getPath();
  6.1241 +        else
  6.1242 +            return uri.toString();
  6.1243 +    }
  6.1244 +
  6.1245 +    @SuppressWarnings("deprecation") // bug 6410637
  6.1246 +    public static String getJavacBaseFileName(FileObject file) {
  6.1247 +        if (file instanceof BaseFileObject)
  6.1248 +            return ((BaseFileObject)file).getName();
  6.1249 +        URI uri = file.toUri();
  6.1250 +        String scheme = uri.getScheme();
  6.1251 +        if (scheme == null || scheme.equals("file") || scheme.equals("jar")) {
  6.1252 +            String path = uri.getPath();
  6.1253 +            if (path == null)
  6.1254 +                return null;
  6.1255 +            if (scheme != null && scheme.equals("jar"))
  6.1256 +                path = path.substring(path.lastIndexOf('!') + 1);
  6.1257 +            return path.substring(path.lastIndexOf('/') + 1);
  6.1258 +        } else {
  6.1259 +            return uri.toString();
  6.1260 +        }
  6.1261 +    }
  6.1262 +
  6.1263 +    private static <T> T nullCheck(T o) {
  6.1264 +        o.getClass(); // null check
  6.1265 +        return o;
  6.1266 +    }
  6.1267 +
  6.1268 +    private static <T> Iterable<T> nullCheck(Iterable<T> it) {
  6.1269 +        for (T t : it)
  6.1270 +            t.getClass(); // null check
  6.1271 +        return it;
  6.1272 +    }
  6.1273 +
  6.1274 +    /**
  6.1275 +     * A subclass of JavaFileObject representing regular files.
  6.1276 +     */
  6.1277 +    private class RegularFileObject extends BaseFileObject {
  6.1278 +        /** Have the parent directories been created?
  6.1279 +         */
  6.1280 +        private boolean hasParents=false;
  6.1281 +
  6.1282 +        /** The file's name.
  6.1283 +         */
  6.1284 +        private String name;
  6.1285 +
  6.1286 +        /** The underlying file.
  6.1287 +         */
  6.1288 +        final File f;
  6.1289 +
  6.1290 +        public RegularFileObject(File f) {
  6.1291 +            this(f.getName(), f);
  6.1292 +        }
  6.1293 +
  6.1294 +        public RegularFileObject(String name, File f) {
  6.1295 +            if (f.isDirectory())
  6.1296 +                throw new IllegalArgumentException("directories not supported");
  6.1297 +            this.name = name;
  6.1298 +            this.f = f;
  6.1299 +        }
  6.1300 +
  6.1301 +        public InputStream openInputStream() throws IOException {
  6.1302 +            return new FileInputStream(f);
  6.1303 +        }
  6.1304 +
  6.1305 +        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
  6.1306 +            return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
  6.1307 +        }
  6.1308 +
  6.1309 +        public OutputStream openOutputStream() throws IOException {
  6.1310 +            ensureParentDirectoriesExist();
  6.1311 +            return new FileOutputStream(f);
  6.1312 +        }
  6.1313 +
  6.1314 +        public Writer openWriter() throws IOException {
  6.1315 +            ensureParentDirectoriesExist();
  6.1316 +            return new OutputStreamWriter(new FileOutputStream(f), getEncodingName());
  6.1317 +        }
  6.1318 +
  6.1319 +        private void ensureParentDirectoriesExist() throws IOException {
  6.1320 +            if (!hasParents) {
  6.1321 +                File parent = f.getParentFile();
  6.1322 +                if (parent != null && !parent.exists()) {
  6.1323 +                    if (!parent.mkdirs()) {
  6.1324 +                        // if the mkdirs failed, it may be because another process concurrently
  6.1325 +                        // created the directory, so check if the directory got created
  6.1326 +                        // anyway before throwing an exception
  6.1327 +                        if (!parent.exists() || !parent.isDirectory())
  6.1328 +                            throw new IOException("could not create parent directories");
  6.1329 +                    }
  6.1330 +                }
  6.1331 +                hasParents = true;
  6.1332 +            }
  6.1333 +        }
  6.1334 +
  6.1335 +        /** @deprecated see bug 6410637 */
  6.1336 +        @Deprecated
  6.1337 +        public String getName() {
  6.1338 +            return name;
  6.1339 +        }
  6.1340 +
  6.1341 +        public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) {
  6.1342 +            cn.getClass(); // null check
  6.1343 +            if (kind == Kind.OTHER && getKind() != kind)
  6.1344 +                return false;
  6.1345 +            String n = cn + kind.extension;
  6.1346 +            if (name.equals(n))
  6.1347 +                return true;
  6.1348 +            if (name.equalsIgnoreCase(n)) {
  6.1349 +                try {
  6.1350 +                    // allow for Windows
  6.1351 +                    return (f.getCanonicalFile().getName().equals(n));
  6.1352 +                } catch (IOException e) {
  6.1353 +                }
  6.1354 +            }
  6.1355 +            return false;
  6.1356 +        }
  6.1357 +
  6.1358 +        /** @deprecated see bug 6410637 */
  6.1359 +        @Deprecated
  6.1360 +        public String getPath() {
  6.1361 +            return f.getPath();
  6.1362 +        }
  6.1363 +
  6.1364 +        public long getLastModified() {
  6.1365 +            return f.lastModified();
  6.1366 +        }
  6.1367 +
  6.1368 +        public boolean delete() {
  6.1369 +            return f.delete();
  6.1370 +        }
  6.1371 +
  6.1372 +        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
  6.1373 +            SoftReference<CharBuffer> r = contentCache.get(this);
  6.1374 +            CharBuffer cb = (r == null ? null : r.get());
  6.1375 +            if (cb == null) {
  6.1376 +                InputStream in = new FileInputStream(f);
  6.1377 +                try {
  6.1378 +                    ByteBuffer bb = makeByteBuffer(in);
  6.1379 +                    JavaFileObject prev = log.useSource(this);
  6.1380 +                    try {
  6.1381 +                        cb = decode(bb, ignoreEncodingErrors);
  6.1382 +                    } finally {
  6.1383 +                        log.useSource(prev);
  6.1384 +                    }
  6.1385 +                    byteBufferCache.put(bb); // save for next time
  6.1386 +                    if (!ignoreEncodingErrors)
  6.1387 +                        contentCache.put(this, new SoftReference<CharBuffer>(cb));
  6.1388 +                } finally {
  6.1389 +                    in.close();
  6.1390 +                }
  6.1391 +            }
  6.1392 +            return cb;
  6.1393 +        }
  6.1394 +
  6.1395 +        @Override
  6.1396 +        public boolean equals(Object other) {
  6.1397 +            if (!(other instanceof RegularFileObject))
  6.1398 +                return false;
  6.1399 +            RegularFileObject o = (RegularFileObject) other;
  6.1400 +            try {
  6.1401 +                return f.equals(o.f)
  6.1402 +                    || f.getCanonicalFile().equals(o.f.getCanonicalFile());
  6.1403 +            } catch (IOException e) {
  6.1404 +                return false;
  6.1405 +            }
  6.1406 +        }
  6.1407 +
  6.1408 +        @Override
  6.1409 +        public int hashCode() {
  6.1410 +            return f.hashCode();
  6.1411 +        }
  6.1412 +
  6.1413 +        public URI toUri() {
  6.1414 +            try {
  6.1415 +                // Do no use File.toURI to avoid file system access
  6.1416 +                String path = f.getAbsolutePath().replace(File.separatorChar, '/');
  6.1417 +                return new URI("file://" + path).normalize();
  6.1418 +            } catch (URISyntaxException ex) {
  6.1419 +                return f.toURI();
  6.1420 +            }
  6.1421 +        }
  6.1422 +
  6.1423 +    }
  6.1424 +
  6.1425 +    /**
  6.1426 +     * A subclass of JavaFileObject representing zip entries.
  6.1427 +     */
  6.1428 +    public class ZipFileObject extends BaseFileObject {
  6.1429 +
  6.1430 +        /** The entry's name.
  6.1431 +         */
  6.1432 +        private String name;
  6.1433 +
  6.1434 +        /** The zipfile containing the entry.
  6.1435 +         */
  6.1436 +        ZipFile zdir;
  6.1437 +
  6.1438 +        /** The underlying zip entry object.
  6.1439 +         */
  6.1440 +        ZipEntry entry;
  6.1441 +
  6.1442 +        public ZipFileObject(String name, ZipFile zdir, ZipEntry entry) {
  6.1443 +            this.name = name;
  6.1444 +            this.zdir = zdir;
  6.1445 +            this.entry = entry;
  6.1446 +        }
  6.1447 +
  6.1448 +        public InputStream openInputStream() throws IOException {
  6.1449 +            return zdir.getInputStream(entry);
  6.1450 +        }
  6.1451 +
  6.1452 +        public OutputStream openOutputStream() throws IOException {
  6.1453 +            throw new UnsupportedOperationException();
  6.1454 +        }
  6.1455 +
  6.1456 +        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
  6.1457 +            return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
  6.1458 +        }
  6.1459 +
  6.1460 +        public Writer openWriter() throws IOException {
  6.1461 +            throw new UnsupportedOperationException();
  6.1462 +        }
  6.1463 +
  6.1464 +        /** @deprecated see bug 6410637 */
  6.1465 +        @Deprecated
  6.1466 +        public String getName() {
  6.1467 +            return name;
  6.1468 +        }
  6.1469 +
  6.1470 +        public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
  6.1471 +            cn.getClass(); // null check
  6.1472 +            if (k == Kind.OTHER && getKind() != k)
  6.1473 +                return false;
  6.1474 +            return name.equals(cn + k.extension);
  6.1475 +        }
  6.1476 +
  6.1477 +        /** @deprecated see bug 6410637 */
  6.1478 +        @Deprecated
  6.1479 +        public String getPath() {
  6.1480 +            return zdir.getName() + "(" + entry + ")";
  6.1481 +        }
  6.1482 +
  6.1483 +        public long getLastModified() {
  6.1484 +            return entry.getTime();
  6.1485 +        }
  6.1486 +
  6.1487 +        public boolean delete() {
  6.1488 +            throw new UnsupportedOperationException();
  6.1489 +        }
  6.1490 +
  6.1491 +        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
  6.1492 +            SoftReference<CharBuffer> r = contentCache.get(this);
  6.1493 +            CharBuffer cb = (r == null ? null : r.get());
  6.1494 +            if (cb == null) {
  6.1495 +                InputStream in = zdir.getInputStream(entry);
  6.1496 +                try {
  6.1497 +                    ByteBuffer bb = makeByteBuffer(in);
  6.1498 +                    JavaFileObject prev = log.useSource(this);
  6.1499 +                    try {
  6.1500 +                        cb = decode(bb, ignoreEncodingErrors);
  6.1501 +                    } finally {
  6.1502 +                        log.useSource(prev);
  6.1503 +                    }
  6.1504 +                    byteBufferCache.put(bb); // save for next time
  6.1505 +                    if (!ignoreEncodingErrors)
  6.1506 +                        contentCache.put(this, new SoftReference<CharBuffer>(cb));
  6.1507 +                } finally {
  6.1508 +                    in.close();
  6.1509 +                }
  6.1510 +            }
  6.1511 +            return cb;
  6.1512 +        }
  6.1513 +
  6.1514 +        @Override
  6.1515 +        public boolean equals(Object other) {
  6.1516 +            if (!(other instanceof ZipFileObject))
  6.1517 +                return false;
  6.1518 +            ZipFileObject o = (ZipFileObject) other;
  6.1519 +            return zdir.equals(o.zdir) || name.equals(o.name);
  6.1520 +        }
  6.1521 +
  6.1522 +        @Override
  6.1523 +        public int hashCode() {
  6.1524 +            return zdir.hashCode() + name.hashCode();
  6.1525 +        }
  6.1526 +
  6.1527 +        public String getZipName() {
  6.1528 +            return zdir.getName();
  6.1529 +        }
  6.1530 +
  6.1531 +        public String getZipEntryName() {
  6.1532 +            return entry.getName();
  6.1533 +        }
  6.1534 +
  6.1535 +        public URI toUri() {
  6.1536 +            String zipName = new File(getZipName()).toURI().normalize().getPath();
  6.1537 +            String entryName = getZipEntryName();
  6.1538 +            return URI.create("jar:" + zipName + "!" + entryName);
  6.1539 +        }
  6.1540 +
  6.1541 +    }
  6.1542 +
  6.1543 +    /**
  6.1544 +     * A subclass of JavaFileObject representing zip entries using the com.sun.tools.javac.zip.ZipFileIndex implementation.
  6.1545 +     */
  6.1546 +    public class ZipFileIndexFileObject extends BaseFileObject {
  6.1547 +
  6.1548 +            /** The entry's name.
  6.1549 +         */
  6.1550 +        private String name;
  6.1551 +
  6.1552 +        /** The zipfile containing the entry.
  6.1553 +         */
  6.1554 +        ZipFileIndex zfIndex;
  6.1555 +
  6.1556 +        /** The underlying zip entry object.
  6.1557 +         */
  6.1558 +        ZipFileIndexEntry entry;
  6.1559 +
  6.1560 +        /** The InputStream for this zip entry (file.)
  6.1561 +         */
  6.1562 +        InputStream inputStream = null;
  6.1563 +
  6.1564 +        /** The name of the zip file where this entry resides.
  6.1565 +         */
  6.1566 +        String zipName;
  6.1567 +
  6.1568 +        JavacFileManager defFileManager = null;
  6.1569 +
  6.1570 +        public ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndexEntry entry, String zipFileName) {
  6.1571 +            super();
  6.1572 +            this.name = entry.getFileName();
  6.1573 +            this.zfIndex = zfIndex;
  6.1574 +            this.entry = entry;
  6.1575 +            this.zipName = zipFileName;
  6.1576 +            defFileManager = fileManager;
  6.1577 +        }
  6.1578 +
  6.1579 +        public InputStream openInputStream() throws IOException {
  6.1580 +
  6.1581 +            if (inputStream == null) {
  6.1582 +                inputStream = new ByteArrayInputStream(read());
  6.1583 +            }
  6.1584 +            return inputStream;
  6.1585 +        }
  6.1586 +
  6.1587 +        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
  6.1588 +            return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
  6.1589 +        }
  6.1590 +
  6.1591 +        public OutputStream openOutputStream() throws IOException {
  6.1592 +            throw new UnsupportedOperationException();
  6.1593 +        }
  6.1594 +
  6.1595 +        public Writer openWriter() throws IOException {
  6.1596 +            throw new UnsupportedOperationException();
  6.1597 +        }
  6.1598 +
  6.1599 +        /** @deprecated see bug 6410637 */
  6.1600 +        @Deprecated
  6.1601 +        public String getName() {
  6.1602 +            return name;
  6.1603 +        }
  6.1604 +
  6.1605 +        public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
  6.1606 +            cn.getClass(); // null check
  6.1607 +            if (k == Kind.OTHER && getKind() != k)
  6.1608 +                return false;
  6.1609 +            return name.equals(cn + k.extension);
  6.1610 +        }
  6.1611 +
  6.1612 +        /** @deprecated see bug 6410637 */
  6.1613 +        @Deprecated
  6.1614 +        public String getPath() {
  6.1615 +            return zipName + "(" + entry.getName() + ")";
  6.1616 +        }
  6.1617 +
  6.1618 +        public long getLastModified() {
  6.1619 +            return entry.getLastModified();
  6.1620 +        }
  6.1621 +
  6.1622 +        public boolean delete() {
  6.1623 +            throw new UnsupportedOperationException();
  6.1624 +        }
  6.1625 +
  6.1626 +        @Override
  6.1627 +        public boolean equals(Object other) {
  6.1628 +            if (!(other instanceof ZipFileIndexFileObject))
  6.1629 +                return false;
  6.1630 +            ZipFileIndexFileObject o = (ZipFileIndexFileObject) other;
  6.1631 +            return entry.equals(o.entry);
  6.1632 +        }
  6.1633 +
  6.1634 +        @Override
  6.1635 +        public int hashCode() {
  6.1636 +            return zipName.hashCode() + (name.hashCode() << 10);
  6.1637 +        }
  6.1638 +
  6.1639 +        public String getZipName() {
  6.1640 +            return zipName;
  6.1641 +        }
  6.1642 +
  6.1643 +        public String getZipEntryName() {
  6.1644 +            return entry.getName();
  6.1645 +        }
  6.1646 +
  6.1647 +        public URI toUri() {
  6.1648 +            String zipName = new File(getZipName()).toURI().normalize().getPath();
  6.1649 +            String entryName = getZipEntryName();
  6.1650 +            if (File.separatorChar != '/') {
  6.1651 +                entryName = entryName.replace(File.separatorChar, '/');
  6.1652 +            }
  6.1653 +            return URI.create("jar:" + zipName + "!" + entryName);
  6.1654 +        }
  6.1655 +
  6.1656 +        private byte[] read() throws IOException {
  6.1657 +            if (entry == null) {
  6.1658 +                entry = zfIndex.getZipIndexEntry(name);
  6.1659 +                if (entry == null)
  6.1660 +                  throw new FileNotFoundException();
  6.1661 +            }
  6.1662 +            return zfIndex.read(entry);
  6.1663 +        }
  6.1664 +
  6.1665 +        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
  6.1666 +            SoftReference<CharBuffer> r = defFileManager.contentCache.get(this);
  6.1667 +            CharBuffer cb = (r == null ? null : r.get());
  6.1668 +            if (cb == null) {
  6.1669 +                InputStream in = new ByteArrayInputStream(zfIndex.read(entry));
  6.1670 +                try {
  6.1671 +                    ByteBuffer bb = makeByteBuffer(in);
  6.1672 +                    JavaFileObject prev = log.useSource(this);
  6.1673 +                    try {
  6.1674 +                        cb = decode(bb, ignoreEncodingErrors);
  6.1675 +                    } finally {
  6.1676 +                        log.useSource(prev);
  6.1677 +                    }
  6.1678 +                    byteBufferCache.put(bb); // save for next time
  6.1679 +                    if (!ignoreEncodingErrors)
  6.1680 +                        defFileManager.contentCache.put(this, new SoftReference<CharBuffer>(cb));
  6.1681 +                } finally {
  6.1682 +                    in.close();
  6.1683 +                }
  6.1684 +            }
  6.1685 +            return cb;
  6.1686 +        }
  6.1687 +    }
  6.1688 +
  6.1689 +    public class ZipFileIndexArchive implements Archive {
  6.1690 +        private final ZipFileIndex zfIndex;
  6.1691 +        private JavacFileManager fileManager;
  6.1692 +
  6.1693 +        public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException {
  6.1694 +            this.fileManager = fileManager;
  6.1695 +            this.zfIndex = zdir;
  6.1696 +        }
  6.1697 +
  6.1698 +        public boolean contains(String name) {
  6.1699 +            return zfIndex.contains(name);
  6.1700 +        }
  6.1701 +
  6.1702 +        public com.sun.tools.javac.util.List<String> getFiles(String subdirectory) {
  6.1703 +              return zfIndex.getFiles(((subdirectory.endsWith("/") || subdirectory.endsWith("\\"))? subdirectory.substring(0, subdirectory.length() - 1) : subdirectory));
  6.1704 +        }
  6.1705 +
  6.1706 +        public JavaFileObject getFileObject(String subdirectory, String file) {
  6.1707 +            String fullZipFileName = subdirectory + file;
  6.1708 +            ZipFileIndexEntry entry = zfIndex.getZipIndexEntry(fullZipFileName);
  6.1709 +            JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile().getPath());
  6.1710 +            return ret;
  6.1711 +        }
  6.1712 +
  6.1713 +        public Set<String> getSubdirectories() {
  6.1714 +            return zfIndex.getAllDirectories();
  6.1715 +        }
  6.1716 +
  6.1717 +        public void close() throws IOException {
  6.1718 +            zfIndex.close();
  6.1719 +        }
  6.1720 +    }
  6.1721 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/share/classes/com/sun/tools/javac/file/Old199.java	Mon Jun 16 13:28:00 2008 -0700
     7.3 @@ -0,0 +1,54 @@
     7.4 +/*
     7.5 + * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
     7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 + *
     7.8 + * This code is free software; you can redistribute it and/or modify it
     7.9 + * under the terms of the GNU General Public License version 2 only, as
    7.10 + * published by the Free Software Foundation.  Sun designates this
    7.11 + * particular file as subject to the "Classpath" exception as provided
    7.12 + * by Sun in the LICENSE file that accompanied this code.
    7.13 + *
    7.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    7.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.17 + * version 2 for more details (a copy is included in the LICENSE file that
    7.18 + * accompanied this code).
    7.19 + *
    7.20 + * You should have received a copy of the GNU General Public License version
    7.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    7.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.23 + *
    7.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    7.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    7.26 + * have any questions.
    7.27 + */
    7.28 +
    7.29 +package com.sun.tools.javac.file;
    7.30 +
    7.31 +import javax.tools.FileObject;
    7.32 +
    7.33 +/**
    7.34 + * Provides an easy migration to JSR 199 v3.3.  The class is
    7.35 + * deprecated as we should remove it as soon as possible.
    7.36 + *
    7.37 + * <p><b>This is NOT part of any API supported by Sun Microsystems.
    7.38 + * If you write code that depends on this, you do so at your own
    7.39 + * risk.  This code and its internal interfaces are subject to change
    7.40 + * or deletion without notice.</b></p>
    7.41 + *
    7.42 + * @author Peter von der Ah\u00e9
    7.43 + */
    7.44 +@Deprecated
    7.45 +public class Old199 {
    7.46 +
    7.47 +    private Old199() {}
    7.48 +
    7.49 +    public static String getPath(FileObject jfo) {
    7.50 +        return JavacFileManager.getJavacFileName(jfo);
    7.51 +    }
    7.52 +
    7.53 +    public static String getName(FileObject jfo) {
    7.54 +        return JavacFileManager.getJavacBaseFileName(jfo);
    7.55 +    }
    7.56 +
    7.57 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/share/classes/com/sun/tools/javac/file/Paths.java	Mon Jun 16 13:28:00 2008 -0700
     8.3 @@ -0,0 +1,577 @@
     8.4 +/*
     8.5 + * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
     8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.7 + *
     8.8 + * This code is free software; you can redistribute it and/or modify it
     8.9 + * under the terms of the GNU General Public License version 2 only, as
    8.10 + * published by the Free Software Foundation.  Sun designates this
    8.11 + * particular file as subject to the "Classpath" exception as provided
    8.12 + * by Sun in the LICENSE file that accompanied this code.
    8.13 + *
    8.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    8.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    8.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    8.17 + * version 2 for more details (a copy is included in the LICENSE file that
    8.18 + * accompanied this code).
    8.19 + *
    8.20 + * You should have received a copy of the GNU General Public License version
    8.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    8.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    8.23 + *
    8.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    8.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    8.26 + * have any questions.
    8.27 + */
    8.28 +
    8.29 +package com.sun.tools.javac.file;
    8.30 +
    8.31 +import java.io.File;
    8.32 +import java.io.IOException;
    8.33 +import java.util.HashMap;
    8.34 +import java.util.HashSet;
    8.35 +import java.util.Map;
    8.36 +import java.util.Set;
    8.37 +import java.util.jar.JarFile;
    8.38 +import java.util.jar.Manifest;
    8.39 +import java.util.jar.Attributes;
    8.40 +import java.util.Collection;
    8.41 +import java.util.Collections;
    8.42 +import java.util.LinkedHashSet;
    8.43 +import java.util.Iterator;
    8.44 +import java.util.StringTokenizer;
    8.45 +import java.util.zip.ZipFile;
    8.46 +import java.util.ArrayList;
    8.47 +import java.util.concurrent.ConcurrentHashMap;
    8.48 +import java.util.concurrent.locks.Lock;
    8.49 +import java.util.concurrent.locks.ReentrantLock;
    8.50 +import javax.tools.JavaFileManager.Location;
    8.51 +
    8.52 +import com.sun.tools.javac.code.Lint;
    8.53 +import com.sun.tools.javac.util.Context;
    8.54 +import com.sun.tools.javac.util.Log;
    8.55 +import com.sun.tools.javac.util.Options;
    8.56 +
    8.57 +import static javax.tools.StandardLocation.*;
    8.58 +import static com.sun.tools.javac.main.OptionName.*;
    8.59 +
    8.60 +/** This class converts command line arguments, environment variables
    8.61 + *  and system properties (in File.pathSeparator-separated String form)
    8.62 + *  into a boot class path, user class path, and source path (in
    8.63 + *  Collection<String> form).
    8.64 + *
    8.65 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    8.66 + *  you write code that depends on this, you do so at your own risk.
    8.67 + *  This code and its internal interfaces are subject to change or
    8.68 + *  deletion without notice.</b>
    8.69 + */
    8.70 +public class Paths {
    8.71 +
    8.72 +    /** The context key for the todo list */
    8.73 +    protected static final Context.Key<Paths> pathsKey =
    8.74 +        new Context.Key<Paths>();
    8.75 +
    8.76 +    /** Get the Paths instance for this context.
    8.77 +     *  @param context the context
    8.78 +     *  @return the Paths instance for this context
    8.79 +     */
    8.80 +    public static Paths instance(Context context) {
    8.81 +        Paths instance = context.get(pathsKey);
    8.82 +        if (instance == null)
    8.83 +            instance = new Paths(context);
    8.84 +        return instance;
    8.85 +    }
    8.86 +
    8.87 +    /** The log to use for warning output */
    8.88 +    private Log log;
    8.89 +
    8.90 +    /** Collection of command-line options */
    8.91 +    private Options options;
    8.92 +
    8.93 +    /** Handler for -Xlint options */
    8.94 +    private Lint lint;
    8.95 +
    8.96 +    private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
    8.97 +    private static Map<File, PathEntry> pathExistanceCache = new ConcurrentHashMap<File, PathEntry>();
    8.98 +    private static Map<File, java.util.List<File>> manifestEntries = new ConcurrentHashMap<File, java.util.List<File>>();
    8.99 +    private static Map<File, Boolean> isDirectory = new ConcurrentHashMap<File, Boolean>();
   8.100 +    private static Lock lock = new ReentrantLock();
   8.101 +
   8.102 +    public static void clearPathExistanceCache() {
   8.103 +            pathExistanceCache.clear();
   8.104 +    }
   8.105 +
   8.106 +    static class PathEntry {
   8.107 +        boolean exists = false;
   8.108 +        boolean isFile = false;
   8.109 +        File cannonicalPath = null;
   8.110 +    }
   8.111 +
   8.112 +    protected Paths(Context context) {
   8.113 +        context.put(pathsKey, this);
   8.114 +        pathsForLocation = new HashMap<Location,Path>(16);
   8.115 +        setContext(context);
   8.116 +    }
   8.117 +
   8.118 +    void setContext(Context context) {
   8.119 +        log = Log.instance(context);
   8.120 +        options = Options.instance(context);
   8.121 +        lint = Lint.instance(context);
   8.122 +    }
   8.123 +
   8.124 +    /** Whether to warn about non-existent path elements */
   8.125 +    private boolean warn;
   8.126 +
   8.127 +    private Map<Location, Path> pathsForLocation;
   8.128 +
   8.129 +    private boolean inited = false; // TODO? caching bad?
   8.130 +
   8.131 +    /**
   8.132 +     * rt.jar as found on the default bootclass path.  If the user specified a
   8.133 +     * bootclasspath, null is used.
   8.134 +     */
   8.135 +    private File bootClassPathRtJar = null;
   8.136 +
   8.137 +    Path getPathForLocation(Location location) {
   8.138 +        Path path = pathsForLocation.get(location);
   8.139 +        if (path == null)
   8.140 +            setPathForLocation(location, null);
   8.141 +        return pathsForLocation.get(location);
   8.142 +    }
   8.143 +
   8.144 +    void setPathForLocation(Location location, Iterable<? extends File> path) {
   8.145 +        // TODO? if (inited) throw new IllegalStateException
   8.146 +        // TODO: otherwise reset sourceSearchPath, classSearchPath as needed
   8.147 +        Path p;
   8.148 +        if (path == null) {
   8.149 +            if (location == CLASS_PATH)
   8.150 +                p = computeUserClassPath();
   8.151 +            else if (location == PLATFORM_CLASS_PATH)
   8.152 +                p = computeBootClassPath();
   8.153 +            else if (location == ANNOTATION_PROCESSOR_PATH)
   8.154 +                p = computeAnnotationProcessorPath();
   8.155 +            else if (location == SOURCE_PATH)
   8.156 +                p = computeSourcePath();
   8.157 +            else
   8.158 +                // no defaults for other paths
   8.159 +                p = null;
   8.160 +        } else {
   8.161 +            p = new Path();
   8.162 +            for (File f: path)
   8.163 +                p.addFile(f, warn); // TODO: is use of warn appropriate?
   8.164 +        }
   8.165 +        pathsForLocation.put(location, p);
   8.166 +    }
   8.167 +
   8.168 +    protected void lazy() {
   8.169 +        if (!inited) {
   8.170 +            warn = lint.isEnabled(Lint.LintCategory.PATH);
   8.171 +
   8.172 +            pathsForLocation.put(PLATFORM_CLASS_PATH, computeBootClassPath());
   8.173 +            pathsForLocation.put(CLASS_PATH, computeUserClassPath());
   8.174 +            pathsForLocation.put(SOURCE_PATH, computeSourcePath());
   8.175 +
   8.176 +            inited = true;
   8.177 +        }
   8.178 +    }
   8.179 +
   8.180 +    public Collection<File> bootClassPath() {
   8.181 +        lazy();
   8.182 +        return Collections.unmodifiableCollection(getPathForLocation(PLATFORM_CLASS_PATH));
   8.183 +    }
   8.184 +    public Collection<File> userClassPath() {
   8.185 +        lazy();
   8.186 +        return Collections.unmodifiableCollection(getPathForLocation(CLASS_PATH));
   8.187 +    }
   8.188 +    public Collection<File> sourcePath() {
   8.189 +        lazy();
   8.190 +        Path p = getPathForLocation(SOURCE_PATH);
   8.191 +        return p == null || p.size() == 0
   8.192 +            ? null
   8.193 +            : Collections.unmodifiableCollection(p);
   8.194 +    }
   8.195 +
   8.196 +    boolean isBootClassPathRtJar(File file) {
   8.197 +        return file.equals(bootClassPathRtJar);
   8.198 +    }
   8.199 +
   8.200 +    private static class PathIterator implements Iterable<String> {
   8.201 +        private int pos = 0;
   8.202 +        private final String path;
   8.203 +        private final String emptyPathDefault;
   8.204 +
   8.205 +        public PathIterator(String path, String emptyPathDefault) {
   8.206 +            this.path = path;
   8.207 +            this.emptyPathDefault = emptyPathDefault;
   8.208 +        }
   8.209 +        public PathIterator(String path) { this(path, null); }
   8.210 +        public Iterator<String> iterator() {
   8.211 +            return new Iterator<String>() {
   8.212 +                public boolean hasNext() {
   8.213 +                    return pos <= path.length();
   8.214 +                }
   8.215 +                public String next() {
   8.216 +                    int beg = pos;
   8.217 +                    int end = path.indexOf(File.pathSeparator, beg);
   8.218 +                    if (end == -1)
   8.219 +                        end = path.length();
   8.220 +                    pos = end + 1;
   8.221 +
   8.222 +                    if (beg == end && emptyPathDefault != null)
   8.223 +                        return emptyPathDefault;
   8.224 +                    else
   8.225 +                        return path.substring(beg, end);
   8.226 +                }
   8.227 +                public void remove() {
   8.228 +                    throw new UnsupportedOperationException();
   8.229 +                }
   8.230 +            };
   8.231 +        }
   8.232 +    }
   8.233 +
   8.234 +    private class Path extends LinkedHashSet<File> {
   8.235 +        private static final long serialVersionUID = 0;
   8.236 +
   8.237 +        private boolean expandJarClassPaths = false;
   8.238 +        private Set<File> canonicalValues = new HashSet<File>();
   8.239 +
   8.240 +        public Path expandJarClassPaths(boolean x) {
   8.241 +            expandJarClassPaths = x;
   8.242 +            return this;
   8.243 +        }
   8.244 +
   8.245 +        /** What to use when path element is the empty string */
   8.246 +        private String emptyPathDefault = null;
   8.247 +
   8.248 +        public Path emptyPathDefault(String x) {
   8.249 +            emptyPathDefault = x;
   8.250 +            return this;
   8.251 +        }
   8.252 +
   8.253 +        public Path() { super(); }
   8.254 +
   8.255 +        public Path addDirectories(String dirs, boolean warn) {
   8.256 +            if (dirs != null)
   8.257 +                for (String dir : new PathIterator(dirs))
   8.258 +                    addDirectory(dir, warn);
   8.259 +            return this;
   8.260 +        }
   8.261 +
   8.262 +        public Path addDirectories(String dirs) {
   8.263 +            return addDirectories(dirs, warn);
   8.264 +        }
   8.265 +
   8.266 +        private void addDirectory(String dir, boolean warn) {
   8.267 +            if (! new File(dir).isDirectory()) {
   8.268 +                if (warn)
   8.269 +                    log.warning("dir.path.element.not.found", dir);
   8.270 +                return;
   8.271 +            }
   8.272 +
   8.273 +            File[] files = new File(dir).listFiles();
   8.274 +            if (files == null)
   8.275 +                return;
   8.276 +
   8.277 +            for (File direntry : files) {
   8.278 +                if (isArchive(direntry))
   8.279 +                    addFile(direntry, warn);
   8.280 +            }
   8.281 +        }
   8.282 +
   8.283 +        public Path addFiles(String files, boolean warn) {
   8.284 +            if (files != null)
   8.285 +                for (String file : new PathIterator(files, emptyPathDefault))
   8.286 +                    addFile(file, warn);
   8.287 +            return this;
   8.288 +        }
   8.289 +
   8.290 +        public Path addFiles(String files) {
   8.291 +            return addFiles(files, warn);
   8.292 +        }
   8.293 +
   8.294 +        public Path addFile(String file, boolean warn) {
   8.295 +            addFile(new File(file), warn);
   8.296 +            return this;
   8.297 +        }
   8.298 +
   8.299 +        public void addFile(File file, boolean warn) {
   8.300 +            boolean foundInCache = false;
   8.301 +            PathEntry pe = null;
   8.302 +            if (!NON_BATCH_MODE) {
   8.303 +                    pe = pathExistanceCache.get(file);
   8.304 +                    if (pe != null) {
   8.305 +                        foundInCache = true;
   8.306 +                    }
   8.307 +                    else {
   8.308 +                        pe = new PathEntry();
   8.309 +                    }
   8.310 +            }
   8.311 +            else {
   8.312 +                pe = new PathEntry();
   8.313 +            }
   8.314 +
   8.315 +            File canonFile;
   8.316 +            try {
   8.317 +                if (!foundInCache) {
   8.318 +                    pe.cannonicalPath = file.getCanonicalFile();
   8.319 +                }
   8.320 +                else {
   8.321 +                   canonFile = pe.cannonicalPath;
   8.322 +                }
   8.323 +            } catch (IOException e) {
   8.324 +                pe.cannonicalPath = canonFile = file;
   8.325 +            }
   8.326 +
   8.327 +            if (contains(file) || canonicalValues.contains(pe.cannonicalPath)) {
   8.328 +                /* Discard duplicates and avoid infinite recursion */
   8.329 +                return;
   8.330 +            }
   8.331 +
   8.332 +            if (!foundInCache) {
   8.333 +                pe.exists = file.exists();
   8.334 +                pe.isFile = file.isFile();
   8.335 +                if (!NON_BATCH_MODE) {
   8.336 +                    pathExistanceCache.put(file, pe);
   8.337 +                }
   8.338 +            }
   8.339 +
   8.340 +            if (! pe.exists) {
   8.341 +                /* No such file or directory exists */
   8.342 +                if (warn)
   8.343 +                    log.warning("path.element.not.found", file);
   8.344 +            } else if (pe.isFile) {
   8.345 +                /* File is an ordinary file. */
   8.346 +                if (!isArchive(file)) {
   8.347 +                    /* Not a recognized extension; open it to see if
   8.348 +                     it looks like a valid zip file. */
   8.349 +                    try {
   8.350 +                        ZipFile z = new ZipFile(file);
   8.351 +                        z.close();
   8.352 +                        if (warn)
   8.353 +                            log.warning("unexpected.archive.file", file);
   8.354 +                    } catch (IOException e) {
   8.355 +                        // FIXME: include e.getLocalizedMessage in warning
   8.356 +                        if (warn)
   8.357 +                            log.warning("invalid.archive.file", file);
   8.358 +                        return;
   8.359 +                    }
   8.360 +                }
   8.361 +            }
   8.362 +
   8.363 +            /* Now what we have left is either a directory or a file name
   8.364 +               confirming to archive naming convention */
   8.365 +            super.add(file);
   8.366 +            canonicalValues.add(pe.cannonicalPath);
   8.367 +
   8.368 +            if (expandJarClassPaths && file.exists() && file.isFile())
   8.369 +                addJarClassPath(file, warn);
   8.370 +        }
   8.371 +
   8.372 +        // Adds referenced classpath elements from a jar's Class-Path
   8.373 +        // Manifest entry.  In some future release, we may want to
   8.374 +        // update this code to recognize URLs rather than simple
   8.375 +        // filenames, but if we do, we should redo all path-related code.
   8.376 +        private void addJarClassPath(File jarFile, boolean warn) {
   8.377 +            try {
   8.378 +                java.util.List<File> manifestsList = manifestEntries.get(jarFile);
   8.379 +                if (!NON_BATCH_MODE) {
   8.380 +                    lock.lock();
   8.381 +                    try {
   8.382 +                        if (manifestsList != null) {
   8.383 +                            for (File entr : manifestsList) {
   8.384 +                                addFile(entr, warn);
   8.385 +                            }
   8.386 +                            return;
   8.387 +                        }
   8.388 +                    }
   8.389 +                    finally {
   8.390 +                        lock.unlock();
   8.391 +                    }
   8.392 +                }
   8.393 +
   8.394 +                if (!NON_BATCH_MODE) {
   8.395 +                    manifestsList = new ArrayList<File>();
   8.396 +                    manifestEntries.put(jarFile, manifestsList);
   8.397 +                }
   8.398 +
   8.399 +                String jarParent = jarFile.getParent();
   8.400 +                JarFile jar = new JarFile(jarFile);
   8.401 +
   8.402 +                try {
   8.403 +                    Manifest man = jar.getManifest();
   8.404 +                    if (man == null) return;
   8.405 +
   8.406 +                    Attributes attr = man.getMainAttributes();
   8.407 +                    if (attr == null) return;
   8.408 +
   8.409 +                    String path = attr.getValue(Attributes.Name.CLASS_PATH);
   8.410 +                    if (path == null) return;
   8.411 +
   8.412 +                    for (StringTokenizer st = new StringTokenizer(path);
   8.413 +                         st.hasMoreTokens();) {
   8.414 +                        String elt = st.nextToken();
   8.415 +                        File f = (jarParent == null ? new File(elt) : new File(jarParent, elt));
   8.416 +                        addFile(f, warn);
   8.417 +
   8.418 +                        if (!NON_BATCH_MODE) {
   8.419 +                            lock.lock();
   8.420 +                            try {
   8.421 +                                manifestsList.add(f);
   8.422 +                            }
   8.423 +                            finally {
   8.424 +                                lock.unlock();
   8.425 +                            }
   8.426 +                        }
   8.427 +                    }
   8.428 +                } finally {
   8.429 +                    jar.close();
   8.430 +                }
   8.431 +            } catch (IOException e) {
   8.432 +                log.error("error.reading.file", jarFile, e.getLocalizedMessage());
   8.433 +            }
   8.434 +        }
   8.435 +    }
   8.436 +
   8.437 +    private Path computeBootClassPath() {
   8.438 +        bootClassPathRtJar = null;
   8.439 +        String optionValue;
   8.440 +        Path path = new Path();
   8.441 +
   8.442 +        path.addFiles(options.get(XBOOTCLASSPATH_PREPEND));
   8.443 +
   8.444 +        if ((optionValue = options.get(ENDORSEDDIRS)) != null)
   8.445 +            path.addDirectories(optionValue);
   8.446 +        else
   8.447 +            path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
   8.448 +
   8.449 +        if ((optionValue = options.get(BOOTCLASSPATH)) != null) {
   8.450 +            path.addFiles(optionValue);
   8.451 +        } else {
   8.452 +            // Standard system classes for this compiler's release.
   8.453 +            String files = System.getProperty("sun.boot.class.path");
   8.454 +            path.addFiles(files, false);
   8.455 +            File rt_jar = new File("rt.jar");
   8.456 +            for (String file : new PathIterator(files, null)) {
   8.457 +                File f = new File(file);
   8.458 +                if (new File(f.getName()).equals(rt_jar))
   8.459 +                    bootClassPathRtJar = f;
   8.460 +            }
   8.461 +        }
   8.462 +
   8.463 +        path.addFiles(options.get(XBOOTCLASSPATH_APPEND));
   8.464 +
   8.465 +        // Strictly speaking, standard extensions are not bootstrap
   8.466 +        // classes, but we treat them identically, so we'll pretend
   8.467 +        // that they are.
   8.468 +        if ((optionValue = options.get(EXTDIRS)) != null)
   8.469 +            path.addDirectories(optionValue);
   8.470 +        else
   8.471 +            path.addDirectories(System.getProperty("java.ext.dirs"), false);
   8.472 +
   8.473 +        return path;
   8.474 +    }
   8.475 +
   8.476 +    private Path computeUserClassPath() {
   8.477 +        String cp = options.get(CLASSPATH);
   8.478 +
   8.479 +        // CLASSPATH environment variable when run from `javac'.
   8.480 +        if (cp == null) cp = System.getProperty("env.class.path");
   8.481 +
   8.482 +        // If invoked via a java VM (not the javac launcher), use the
   8.483 +        // platform class path
   8.484 +        if (cp == null && System.getProperty("application.home") == null)
   8.485 +            cp = System.getProperty("java.class.path");
   8.486 +
   8.487 +        // Default to current working directory.
   8.488 +        if (cp == null) cp = ".";
   8.489 +
   8.490 +        return new Path()
   8.491 +            .expandJarClassPaths(true) // Only search user jars for Class-Paths
   8.492 +            .emptyPathDefault(".")     // Empty path elt ==> current directory
   8.493 +            .addFiles(cp);
   8.494 +    }
   8.495 +
   8.496 +    private Path computeSourcePath() {
   8.497 +        String sourcePathArg = options.get(SOURCEPATH);
   8.498 +        if (sourcePathArg == null)
   8.499 +            return null;
   8.500 +
   8.501 +        return new Path().addFiles(sourcePathArg);
   8.502 +    }
   8.503 +
   8.504 +    private Path computeAnnotationProcessorPath() {
   8.505 +        String processorPathArg = options.get(PROCESSORPATH);
   8.506 +        if (processorPathArg == null)
   8.507 +            return null;
   8.508 +
   8.509 +        return new Path().addFiles(processorPathArg);
   8.510 +    }
   8.511 +
   8.512 +    /** The actual effective locations searched for sources */
   8.513 +    private Path sourceSearchPath;
   8.514 +
   8.515 +    public Collection<File> sourceSearchPath() {
   8.516 +        if (sourceSearchPath == null) {
   8.517 +            lazy();
   8.518 +            Path sourcePath = getPathForLocation(SOURCE_PATH);
   8.519 +            Path userClassPath = getPathForLocation(CLASS_PATH);
   8.520 +            sourceSearchPath = sourcePath != null ? sourcePath : userClassPath;
   8.521 +        }
   8.522 +        return Collections.unmodifiableCollection(sourceSearchPath);
   8.523 +    }
   8.524 +
   8.525 +    /** The actual effective locations searched for classes */
   8.526 +    private Path classSearchPath;
   8.527 +
   8.528 +    public Collection<File> classSearchPath() {
   8.529 +        if (classSearchPath == null) {
   8.530 +            lazy();
   8.531 +            Path bootClassPath = getPathForLocation(PLATFORM_CLASS_PATH);
   8.532 +            Path userClassPath = getPathForLocation(CLASS_PATH);
   8.533 +            classSearchPath = new Path();
   8.534 +            classSearchPath.addAll(bootClassPath);
   8.535 +            classSearchPath.addAll(userClassPath);
   8.536 +        }
   8.537 +        return Collections.unmodifiableCollection(classSearchPath);
   8.538 +    }
   8.539 +
   8.540 +    /** The actual effective locations for non-source, non-class files */
   8.541 +    private Path otherSearchPath;
   8.542 +
   8.543 +    Collection<File> otherSearchPath() {
   8.544 +        if (otherSearchPath == null) {
   8.545 +            lazy();
   8.546 +            Path userClassPath = getPathForLocation(CLASS_PATH);
   8.547 +            Path sourcePath = getPathForLocation(SOURCE_PATH);
   8.548 +            if (sourcePath == null)
   8.549 +                otherSearchPath = userClassPath;
   8.550 +            else {
   8.551 +                otherSearchPath = new Path();
   8.552 +                otherSearchPath.addAll(userClassPath);
   8.553 +                otherSearchPath.addAll(sourcePath);
   8.554 +            }
   8.555 +        }
   8.556 +        return Collections.unmodifiableCollection(otherSearchPath);
   8.557 +    }
   8.558 +
   8.559 +    /** Is this the name of an archive file? */
   8.560 +    private static boolean isArchive(File file) {
   8.561 +        String n = file.getName().toLowerCase();
   8.562 +        boolean isFile = false;
   8.563 +        if (!NON_BATCH_MODE) {
   8.564 +            Boolean isf = isDirectory.get(file);
   8.565 +            if (isf == null) {
   8.566 +                isFile = file.isFile();
   8.567 +                isDirectory.put(file, isFile);
   8.568 +            }
   8.569 +            else {
   8.570 +                isFile = isf;
   8.571 +            }
   8.572 +        }
   8.573 +        else {
   8.574 +            isFile = file.isFile();
   8.575 +        }
   8.576 +
   8.577 +        return isFile
   8.578 +            && (n.endsWith(".jar") || n.endsWith(".zip"));
   8.579 +    }
   8.580 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java	Mon Jun 16 13:28:00 2008 -0700
     9.3 @@ -0,0 +1,1248 @@
     9.4 +/*
     9.5 + * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
     9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.7 + *
     9.8 + * This code is free software; you can redistribute it and/or modify it
     9.9 + * under the terms of the GNU General Public License version 2 only, as
    9.10 + * published by the Free Software Foundation.  Sun designates this
    9.11 + * particular file as subject to the "Classpath" exception as provided
    9.12 + * by Sun in the LICENSE file that accompanied this code.
    9.13 + *
    9.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    9.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    9.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    9.17 + * version 2 for more details (a copy is included in the LICENSE file that
    9.18 + * accompanied this code).
    9.19 + *
    9.20 + * You should have received a copy of the GNU General Public License version
    9.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    9.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    9.23 + *
    9.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    9.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    9.26 + * have any questions.
    9.27 + */
    9.28 +
    9.29 +package com.sun.tools.javac.file;
    9.30 +
    9.31 +import java.io.File;
    9.32 +import java.io.FileNotFoundException;
    9.33 +import java.io.IOException;
    9.34 +import java.io.RandomAccessFile;
    9.35 +import java.text.MessageFormat;
    9.36 +import java.util.ArrayList;
    9.37 +import java.util.Arrays;
    9.38 +import java.util.Collections;
    9.39 +import java.util.HashMap;
    9.40 +import java.util.HashSet;
    9.41 +import java.util.Iterator;
    9.42 +import java.util.List;
    9.43 +import java.util.Map;
    9.44 +import java.util.Set;
    9.45 +import java.util.concurrent.locks.ReentrantLock;
    9.46 +import java.util.zip.DataFormatException;
    9.47 +import java.util.zip.Inflater;
    9.48 +import java.util.zip.ZipException;
    9.49 +
    9.50 +/** This class implements building of index of a zip archive and access to it's context.
    9.51 + *  It also uses prebuild index if available. It supports invocations where it will
    9.52 + *  serialize an optimized zip index file to disk.
    9.53 + *
    9.54 + *  In oreder to use secondary index file make sure the option "usezipindex" is in the Options object,
    9.55 + *  when JavacFileManager is invoked. (You can pass "-XDusezipindex" on the command line.
    9.56 + *
    9.57 + *  Location where to look for/generate optimized zip index files can be provided using
    9.58 + *  "-XDcachezipindexdir=<directory>". If this flag is not provided, the dfault location is
    9.59 + *  the value of the "java.io.tmpdir" system property.
    9.60 + *
    9.61 + *  If key "-XDwritezipindexfiles" is specified, there will be new optimized index file
    9.62 + *  created for each archive, used by the compiler for compilation, at location,
    9.63 + *  specified by "cachezipindexdir" option.
    9.64 + *
    9.65 + * If nonBatchMode option is specified (-XDnonBatchMode) the compiler will use timestamp
    9.66 + * checking to reindex the zip files if it is needed. In batch mode the timestamps are not checked
    9.67 + * and the compiler uses the cached indexes.
    9.68 + */
    9.69 +public class ZipFileIndex {
    9.70 +    private static final String MIN_CHAR = String.valueOf(Character.MIN_VALUE);
    9.71 +    private static final String MAX_CHAR = String.valueOf(Character.MAX_VALUE);
    9.72 +
    9.73 +    public final static long NOT_MODIFIED = Long.MIN_VALUE;
    9.74 +
    9.75 +    private static Map<File, ZipFileIndex> zipFileIndexCache = new HashMap<File, ZipFileIndex>();
    9.76 +    private static ReentrantLock lock = new ReentrantLock();
    9.77 +
    9.78 +    private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
    9.79 +
    9.80 +    private Map<String, DirectoryEntry> directories = Collections.<String, DirectoryEntry>emptyMap();
    9.81 +    private Set<String> allDirs = Collections.<String>emptySet();
    9.82 +
    9.83 +    // ZipFileIndex data entries
    9.84 +    private File zipFile;
    9.85 +    private long zipFileLastModified = NOT_MODIFIED;
    9.86 +    private RandomAccessFile zipRandomFile;
    9.87 +    private ZipFileIndexEntry[] entries;
    9.88 +
    9.89 +    private boolean readFromIndex = false;
    9.90 +    private File zipIndexFile = null;
    9.91 +    private boolean triedToReadIndex = false;
    9.92 +    private int symbolFilePrefixLength = 0;
    9.93 +    private boolean hasPopulatedData = false;
    9.94 +    private long lastReferenceTimeStamp = NOT_MODIFIED;
    9.95 +
    9.96 +    private boolean usePreindexedCache = false;
    9.97 +    private String preindexedCacheLocation = null;
    9.98 +
    9.99 +    private boolean writeIndex = false;
   9.100 +
   9.101 +    /**
   9.102 +     * Returns a list of all ZipFileIndex entries
   9.103 +     *
   9.104 +     * @return A list of ZipFileIndex entries, or an empty list
   9.105 +     */
   9.106 +    public static List<ZipFileIndex> getZipFileIndexes() {
   9.107 +        return getZipFileIndexes(false);
   9.108 +    }
   9.109 +
   9.110 +    /**
   9.111 +     * Returns a list of all ZipFileIndex entries
   9.112 +     *
   9.113 +     * @param openedOnly If true it returns a list of only opened ZipFileIndex entries, otherwise
   9.114 +     *                   all ZipFileEntry(s) are included into the list.
   9.115 +     * @return A list of ZipFileIndex entries, or an empty list
   9.116 +     */
   9.117 +    public static List<ZipFileIndex> getZipFileIndexes(boolean openedOnly) {
   9.118 +        List<ZipFileIndex> zipFileIndexes = new ArrayList<ZipFileIndex>();
   9.119 +        lock.lock();
   9.120 +        try {
   9.121 +            zipFileIndexes.addAll(zipFileIndexCache.values());
   9.122 +
   9.123 +            if (openedOnly) {
   9.124 +                for(ZipFileIndex elem : zipFileIndexes) {
   9.125 +                    if (!elem.isOpen()) {
   9.126 +                        zipFileIndexes.remove(elem);
   9.127 +                    }
   9.128 +                }
   9.129 +            }
   9.130 +        }
   9.131 +        finally {
   9.132 +            lock.unlock();
   9.133 +        }
   9.134 +        return zipFileIndexes;
   9.135 +    }
   9.136 +
   9.137 +    public boolean isOpen() {
   9.138 +        lock.lock();
   9.139 +        try {
   9.140 +            return zipRandomFile != null;
   9.141 +        }
   9.142 +        finally {
   9.143 +            lock.unlock();
   9.144 +        }
   9.145 +    }
   9.146 +
   9.147 +    public static ZipFileIndex getZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean useCache, String cacheLocation, boolean writeIndex) throws IOException {
   9.148 +        ZipFileIndex zi = null;
   9.149 +        lock.lock();
   9.150 +        try {
   9.151 +            zi = getExistingZipIndex(zipFile);
   9.152 +
   9.153 +            if (zi == null || (zi != null && zipFile.lastModified() != zi.zipFileLastModified)) {
   9.154 +                zi = new ZipFileIndex(zipFile, symbolFilePrefixLen, writeIndex,
   9.155 +                        useCache, cacheLocation);
   9.156 +                zipFileIndexCache.put(zipFile, zi);
   9.157 +            }
   9.158 +        }
   9.159 +        finally {
   9.160 +            lock.unlock();
   9.161 +        }
   9.162 +        return zi;
   9.163 +    }
   9.164 +
   9.165 +    public static ZipFileIndex getExistingZipIndex(File zipFile) {
   9.166 +        lock.lock();
   9.167 +        try {
   9.168 +            return zipFileIndexCache.get(zipFile);
   9.169 +        }
   9.170 +        finally {
   9.171 +            lock.unlock();
   9.172 +        }
   9.173 +    }
   9.174 +
   9.175 +    public static void clearCache() {
   9.176 +        lock.lock();
   9.177 +        try {
   9.178 +            zipFileIndexCache.clear();
   9.179 +        }
   9.180 +        finally {
   9.181 +            lock.unlock();
   9.182 +        }
   9.183 +    }
   9.184 +
   9.185 +    public static void clearCache(long timeNotUsed) {
   9.186 +        lock.lock();
   9.187 +        try {
   9.188 +            Iterator<File> cachedFileIterator = zipFileIndexCache.keySet().iterator();
   9.189 +            while (cachedFileIterator.hasNext()) {
   9.190 +                File cachedFile = cachedFileIterator.next();
   9.191 +                ZipFileIndex cachedZipIndex = zipFileIndexCache.get(cachedFile);
   9.192 +                if (cachedZipIndex != null) {
   9.193 +                    long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed;
   9.194 +                    if (timeToTest < cachedZipIndex.lastReferenceTimeStamp || // Overflow...
   9.195 +                            System.currentTimeMillis() > timeToTest) {
   9.196 +                        zipFileIndexCache.remove(cachedFile);
   9.197 +                    }
   9.198 +                }
   9.199 +            }
   9.200 +        }
   9.201 +        finally {
   9.202 +            lock.unlock();
   9.203 +        }
   9.204 +    }
   9.205 +
   9.206 +    public static void removeFromCache(File file) {
   9.207 +        lock.lock();
   9.208 +        try {
   9.209 +            zipFileIndexCache.remove(file);
   9.210 +        }
   9.211 +        finally {
   9.212 +            lock.unlock();
   9.213 +        }
   9.214 +    }
   9.215 +
   9.216 +    /** Sets already opened list of ZipFileIndexes from an outside client
   9.217 +      * of the compiler. This functionality should be used in a non-batch clients of the compiler.
   9.218 +      */
   9.219 +    public static void setOpenedIndexes(List<ZipFileIndex>indexes) throws IllegalStateException {
   9.220 +        lock.lock();
   9.221 +        try {
   9.222 +            if (zipFileIndexCache.isEmpty()) {
   9.223 +                throw new IllegalStateException("Setting opened indexes should be called only when the ZipFileCache is empty. Call JavacFileManager.flush() before calling this method.");
   9.224 +            }
   9.225 +
   9.226 +            for (ZipFileIndex zfi : indexes) {
   9.227 +                zipFileIndexCache.put(zfi.zipFile, zfi);
   9.228 +            }
   9.229 +        }
   9.230 +        finally {
   9.231 +            lock.unlock();
   9.232 +        }
   9.233 +    }
   9.234 +
   9.235 +    private ZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean writeIndex,
   9.236 +            boolean useCache, String cacheLocation) throws IOException {
   9.237 +        this.zipFile = zipFile;
   9.238 +        this.symbolFilePrefixLength = symbolFilePrefixLen;
   9.239 +        this.writeIndex = writeIndex;
   9.240 +        this.usePreindexedCache = useCache;
   9.241 +        this.preindexedCacheLocation = cacheLocation;
   9.242 +
   9.243 +        if (zipFile != null) {
   9.244 +            this.zipFileLastModified = zipFile.lastModified();
   9.245 +        }
   9.246 +
   9.247 +        // Validate integrity of the zip file
   9.248 +        checkIndex();
   9.249 +    }
   9.250 +
   9.251 +    public String toString() {
   9.252 +        return "ZipFileIndex of file:(" + zipFile + ")";
   9.253 +    }
   9.254 +
   9.255 +    // Just in case...
   9.256 +    protected void finalize() {
   9.257 +        closeFile();
   9.258 +    }
   9.259 +
   9.260 +    private boolean isUpToDate() {
   9.261 +        if (zipFile != null &&
   9.262 +                ((!NON_BATCH_MODE) || zipFileLastModified == zipFile.lastModified()) &&
   9.263 +                hasPopulatedData) {
   9.264 +            return true;
   9.265 +        }
   9.266 +
   9.267 +        return false;
   9.268 +    }
   9.269 +
   9.270 +    /**
   9.271 +     * Here we need to make sure that the ZipFileIndex is valid. Check the timestamp of the file and
   9.272 +     * if its the same as the one at the time the index was build we don't need to reopen anything.
   9.273 +     */
   9.274 +    private void checkIndex() throws IOException {
   9.275 +        boolean isUpToDate = true;
   9.276 +        if (!isUpToDate()) {
   9.277 +            closeFile();
   9.278 +            isUpToDate = false;
   9.279 +        }
   9.280 +
   9.281 +        if (zipRandomFile != null || isUpToDate) {
   9.282 +            lastReferenceTimeStamp = System.currentTimeMillis();
   9.283 +            return;
   9.284 +        }
   9.285 +
   9.286 +        hasPopulatedData = true;
   9.287 +
   9.288 +        if (readIndex()) {
   9.289 +            lastReferenceTimeStamp = System.currentTimeMillis();
   9.290 +            return;
   9.291 +        }
   9.292 +
   9.293 +        directories = Collections.<String, DirectoryEntry>emptyMap();
   9.294 +        allDirs = Collections.<String>emptySet();
   9.295 +
   9.296 +        try {
   9.297 +            openFile();
   9.298 +            long totalLength = zipRandomFile.length();
   9.299 +            ZipDirectory directory = new ZipDirectory(zipRandomFile, 0L, totalLength, this);
   9.300 +            directory.buildIndex();
   9.301 +        } finally {
   9.302 +            if (zipRandomFile != null) {
   9.303 +                closeFile();
   9.304 +            }
   9.305 +        }
   9.306 +
   9.307 +        lastReferenceTimeStamp = System.currentTimeMillis();
   9.308 +    }
   9.309 +
   9.310 +    private void openFile() throws FileNotFoundException {
   9.311 +        if (zipRandomFile == null && zipFile != null) {
   9.312 +            zipRandomFile = new RandomAccessFile(zipFile, "r");
   9.313 +        }
   9.314 +    }
   9.315 +
   9.316 +    private void cleanupState() {
   9.317 +        // Make sure there is a valid but empty index if the file doesn't exist
   9.318 +        entries = ZipFileIndexEntry.EMPTY_ARRAY;
   9.319 +        directories = Collections.<String, DirectoryEntry>emptyMap();
   9.320 +        zipFileLastModified = NOT_MODIFIED;
   9.321 +        allDirs = Collections.<String>emptySet();
   9.322 +    }
   9.323 +
   9.324 +    public void close() {
   9.325 +        lock.lock();
   9.326 +        try {
   9.327 +            writeIndex();
   9.328 +            closeFile();
   9.329 +        }
   9.330 +        finally {
   9.331 +            lock.unlock();
   9.332 +        }
   9.333 +    }
   9.334 +
   9.335 +    private void closeFile() {
   9.336 +        if (zipRandomFile != null) {
   9.337 +            try {
   9.338 +                zipRandomFile.close();
   9.339 +            } catch (IOException ex) {
   9.340 +            }
   9.341 +            zipRandomFile = null;
   9.342 +        }
   9.343 +    }
   9.344 +
   9.345 +    /**
   9.346 +     * Returns the ZipFileIndexEntry for an absolute path, if there is one.
   9.347 +     */
   9.348 +    public ZipFileIndexEntry getZipIndexEntry(String path) {
   9.349 +        if (File.separatorChar != '/') {
   9.350 +            path = path.replace('/', File.separatorChar);
   9.351 +        }
   9.352 +        lock.lock();
   9.353 +        try {
   9.354 +            checkIndex();
   9.355 +            String lookFor = "";
   9.356 +            int lastSepIndex = path.lastIndexOf(File.separatorChar);
   9.357 +            boolean noSeparator = false;
   9.358 +            if (lastSepIndex == -1) {
   9.359 +                noSeparator = true;
   9.360 +            }
   9.361 +
   9.362 +            DirectoryEntry de = directories.get(noSeparator ? "" : path.substring(0, lastSepIndex));
   9.363 +
   9.364 +            lookFor = path.substring(noSeparator ? 0 : lastSepIndex + 1);
   9.365 +
   9.366 +            return de == null ? null : de.getEntry(lookFor);
   9.367 +        }
   9.368 +        catch (IOException e) {
   9.369 +            return null;
   9.370 +        }
   9.371 +        finally {
   9.372 +            lock.unlock();
   9.373 +        }
   9.374 +    }
   9.375 +
   9.376 +    /**
   9.377 +     * Returns a javac List of filenames within an absolute path in the ZipFileIndex.
   9.378 +     */
   9.379 +    public com.sun.tools.javac.util.List<String> getFiles(String path) {
   9.380 +        if (File.separatorChar != '/') {
   9.381 +            path = path.replace('/', File.separatorChar);
   9.382 +        }
   9.383 +
   9.384 +        lock.lock();
   9.385 +        try {
   9.386 +            checkIndex();
   9.387 +
   9.388 +            DirectoryEntry de = directories.get(path);
   9.389 +            com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getFiles();
   9.390 +
   9.391 +            if (ret == null) {
   9.392 +                return com.sun.tools.javac.util.List.<String>nil();
   9.393 +            }
   9.394 +            return ret;
   9.395 +        }
   9.396 +        catch (IOException e) {
   9.397 +            return com.sun.tools.javac.util.List.<String>nil();
   9.398 +        }
   9.399 +        finally {
   9.400 +            lock.unlock();
   9.401 +        }
   9.402 +    }
   9.403 +
   9.404 +    public List<String> getAllDirectories(String path) {
   9.405 +
   9.406 +        if (File.separatorChar != '/') {
   9.407 +            path = path.replace('/', File.separatorChar);
   9.408 +        }
   9.409 +
   9.410 +        lock.lock();
   9.411 +        try {
   9.412 +            checkIndex();
   9.413 +            path = path.intern();
   9.414 +
   9.415 +            DirectoryEntry de = directories.get(path);
   9.416 +            com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getDirectories();
   9.417 +
   9.418 +            if (ret == null) {
   9.419 +                return com.sun.tools.javac.util.List.<String>nil();
   9.420 +            }
   9.421 +
   9.422 +            return ret;
   9.423 +        }
   9.424 +        catch (IOException e) {
   9.425 +            return com.sun.tools.javac.util.List.<String>nil();
   9.426 +        }
   9.427 +        finally {
   9.428 +            lock.unlock();
   9.429 +        }
   9.430 +    }
   9.431 +
   9.432 +    public Set<String> getAllDirectories() {
   9.433 +        lock.lock();
   9.434 +        try {
   9.435 +            checkIndex();
   9.436 +            if (allDirs == Collections.EMPTY_SET) {
   9.437 +                Set<String> alldirs = new HashSet<String>();
   9.438 +                Iterator<String> dirsIter = directories.keySet().iterator();
   9.439 +                while (dirsIter.hasNext()) {
   9.440 +                    alldirs.add(new String(dirsIter.next()));
   9.441 +                }
   9.442 +
   9.443 +                allDirs = alldirs;
   9.444 +            }
   9.445 +
   9.446 +            return allDirs;
   9.447 +        }
   9.448 +        catch (IOException e) {
   9.449 +            return Collections.<String>emptySet();
   9.450 +        }
   9.451 +        finally {
   9.452 +            lock.unlock();
   9.453 +        }
   9.454 +    }
   9.455 +
   9.456 +    /**
   9.457 +     * Tests if a specific path exists in the zip.  This method will return true
   9.458 +     * for file entries and directories.
   9.459 +     *
   9.460 +     * @param path A path within the zip.
   9.461 +     * @return True if the path is a file or dir, false otherwise.
   9.462 +     */
   9.463 +    public boolean contains(String path) {
   9.464 +        lock.lock();
   9.465 +        try {
   9.466 +            checkIndex();
   9.467 +            return getZipIndexEntry(path) != null;
   9.468 +        }
   9.469 +        catch (IOException e) {
   9.470 +            return false;
   9.471 +        }
   9.472 +        finally {
   9.473 +            lock.unlock();
   9.474 +        }
   9.475 +    }
   9.476 +
   9.477 +    public boolean isDirectory(String path) throws IOException {
   9.478 +        lock.lock();
   9.479 +        try {
   9.480 +            // The top level in a zip file is always a directory.
   9.481 +            if (path.length() == 0) {
   9.482 +                lastReferenceTimeStamp = System.currentTimeMillis();
   9.483 +                return true;
   9.484 +            }
   9.485 +
   9.486 +            if (File.separatorChar != '/')
   9.487 +                path = path.replace('/', File.separatorChar);
   9.488 +            checkIndex();
   9.489 +            return directories.get(path) != null;
   9.490 +        }
   9.491 +        finally {
   9.492 +            lock.unlock();
   9.493 +        }
   9.494 +    }
   9.495 +
   9.496 +    public long getLastModified(String path) throws IOException {
   9.497 +        lock.lock();
   9.498 +        try {
   9.499 +            ZipFileIndexEntry entry = getZipIndexEntry(path);
   9.500 +            if (entry == null)
   9.501 +                throw new FileNotFoundException();
   9.502 +            return entry.getLastModified();
   9.503 +        }
   9.504 +        finally {
   9.505 +            lock.unlock();
   9.506 +        }
   9.507 +    }
   9.508 +
   9.509 +    public int length(String path) throws IOException {
   9.510 +        lock.lock();
   9.511 +        try {
   9.512 +            ZipFileIndexEntry entry = getZipIndexEntry(path);
   9.513 +            if (entry == null)
   9.514 +                throw new FileNotFoundException();
   9.515 +
   9.516 +            if (entry.isDir) {
   9.517 +                return 0;
   9.518 +            }
   9.519 +
   9.520 +            byte[] header = getHeader(entry);
   9.521 +            // entry is not compressed?
   9.522 +            if (get2ByteLittleEndian(header, 8) == 0) {
   9.523 +                return entry.compressedSize;
   9.524 +            } else {
   9.525 +                return entry.size;
   9.526 +            }
   9.527 +        }
   9.528 +        finally {
   9.529 +            lock.unlock();
   9.530 +        }
   9.531 +    }
   9.532 +
   9.533 +    public byte[] read(String path) throws IOException {
   9.534 +        lock.lock();
   9.535 +        try {
   9.536 +            ZipFileIndexEntry entry = getZipIndexEntry(path);
   9.537 +            if (entry == null)
   9.538 +                throw new FileNotFoundException(MessageFormat.format("Path not found in ZIP: {0}", path));
   9.539 +            return read(entry);
   9.540 +        }
   9.541 +        finally {
   9.542 +            lock.unlock();
   9.543 +        }
   9.544 +    }
   9.545 +
   9.546 +    public byte[] read(ZipFileIndexEntry entry) throws IOException {
   9.547 +        lock.lock();
   9.548 +        try {
   9.549 +            openFile();
   9.550 +            byte[] result = readBytes(entry);
   9.551 +            closeFile();
   9.552 +            return result;
   9.553 +        }
   9.554 +        finally {
   9.555 +            lock.unlock();
   9.556 +        }
   9.557 +    }
   9.558 +
   9.559 +    public int read(String path, byte[] buffer) throws IOException {
   9.560 +        lock.lock();
   9.561 +        try {
   9.562 +            ZipFileIndexEntry entry = getZipIndexEntry(path);
   9.563 +            if (entry == null)
   9.564 +                throw new FileNotFoundException();
   9.565 +            return read(entry, buffer);
   9.566 +        }
   9.567 +        finally {
   9.568 +            lock.unlock();
   9.569 +        }
   9.570 +    }
   9.571 +
   9.572 +    public int read(ZipFileIndexEntry entry, byte[] buffer)
   9.573 +            throws IOException {
   9.574 +        lock.lock();
   9.575 +        try {
   9.576 +            int result = readBytes(entry, buffer);
   9.577 +            return result;
   9.578 +        }
   9.579 +        finally {
   9.580 +            lock.unlock();
   9.581 +        }
   9.582 +    }
   9.583 +
   9.584 +    private byte[] readBytes(ZipFileIndexEntry entry) throws IOException {
   9.585 +        byte[] header = getHeader(entry);
   9.586 +        int csize = entry.compressedSize;
   9.587 +        byte[] cbuf = new byte[csize];
   9.588 +        zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
   9.589 +        zipRandomFile.readFully(cbuf, 0, csize);
   9.590 +
   9.591 +        // is this compressed - offset 8 in the ZipEntry header
   9.592 +        if (get2ByteLittleEndian(header, 8) == 0)
   9.593 +            return cbuf;
   9.594 +
   9.595 +        int size = entry.size;
   9.596 +        byte[] buf = new byte[size];
   9.597 +        if (inflate(cbuf, buf) != size)
   9.598 +            throw new ZipException("corrupted zip file");
   9.599 +
   9.600 +        return buf;
   9.601 +    }
   9.602 +
   9.603 +    /**
   9.604 +     *
   9.605 +     */
   9.606 +    private int readBytes(ZipFileIndexEntry entry, byte[] buffer) throws IOException {
   9.607 +        byte[] header = getHeader(entry);
   9.608 +
   9.609 +        // entry is not compressed?
   9.610 +        if (get2ByteLittleEndian(header, 8) == 0) {
   9.611 +            zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
   9.612 +            int offset = 0;
   9.613 +            int size = buffer.length;
   9.614 +            while (offset < size) {
   9.615 +                int count = zipRandomFile.read(buffer, offset, size - offset);
   9.616 +                if (count == -1)
   9.617 +                    break;
   9.618 +                offset += count;
   9.619 +            }
   9.620 +            return entry.size;
   9.621 +        }
   9.622 +
   9.623 +        int csize = entry.compressedSize;
   9.624 +        byte[] cbuf = new byte[csize];
   9.625 +        zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
   9.626 +        zipRandomFile.readFully(cbuf, 0, csize);
   9.627 +
   9.628 +        int count = inflate(cbuf, buffer);
   9.629 +        if (count == -1)
   9.630 +            throw new ZipException("corrupted zip file");
   9.631 +
   9.632 +        return entry.size;
   9.633 +    }
   9.634 +
   9.635 +    //----------------------------------------------------------------------------
   9.636 +    // Zip utilities
   9.637 +    //----------------------------------------------------------------------------
   9.638 +
   9.639 +    private byte[] getHeader(ZipFileIndexEntry entry) throws IOException {
   9.640 +        zipRandomFile.seek(entry.offset);
   9.641 +        byte[] header = new byte[30];
   9.642 +        zipRandomFile.readFully(header);
   9.643 +        if (get4ByteLittleEndian(header, 0) != 0x04034b50)
   9.644 +            throw new ZipException("corrupted zip file");
   9.645 +        if ((get2ByteLittleEndian(header, 6) & 1) != 0)
   9.646 +            throw new ZipException("encrypted zip file"); // offset 6 in the header of the ZipFileEntry
   9.647 +        return header;
   9.648 +    }
   9.649 +
   9.650 +  /*
   9.651 +   * Inflate using the java.util.zip.Inflater class
   9.652 +   */
   9.653 +    private static Inflater inflater;
   9.654 +    private int inflate(byte[] src, byte[] dest) {
   9.655 +
   9.656 +        // construct the inflater object or reuse an existing one
   9.657 +        if (inflater == null)
   9.658 +            inflater = new Inflater(true);
   9.659 +
   9.660 +        synchronized (inflater) {
   9.661 +            inflater.reset();
   9.662 +            inflater.setInput(src);
   9.663 +            try {
   9.664 +                return inflater.inflate(dest);
   9.665 +            } catch (DataFormatException ex) {
   9.666 +                return -1;
   9.667 +            }
   9.668 +        }
   9.669 +    }
   9.670 +
   9.671 +    /**
   9.672 +     * return the two bytes buf[pos], buf[pos+1] as an unsigned integer in little
   9.673 +     * endian format.
   9.674 +     */
   9.675 +    private static int get2ByteLittleEndian(byte[] buf, int pos) {
   9.676 +        return (buf[pos] & 0xFF) + ((buf[pos+1] & 0xFF) << 8);
   9.677 +    }
   9.678 +
   9.679 +    /**
   9.680 +     * return the 4 bytes buf[i..i+3] as an integer in little endian format.
   9.681 +     */
   9.682 +    private static int get4ByteLittleEndian(byte[] buf, int pos) {
   9.683 +        return (buf[pos] & 0xFF) + ((buf[pos + 1] & 0xFF) << 8) +
   9.684 +                ((buf[pos + 2] & 0xFF) << 16) + ((buf[pos + 3] & 0xFF) << 24);
   9.685 +    }
   9.686 +
   9.687 +    /* ----------------------------------------------------------------------------
   9.688 +     * ZipDirectory
   9.689 +     * ----------------------------------------------------------------------------*/
   9.690 +
   9.691 +    private class ZipDirectory {
   9.692 +        private String lastDir;
   9.693 +        private int lastStart;
   9.694 +        private int lastLen;
   9.695 +
   9.696 +        byte[] zipDir;
   9.697 +        RandomAccessFile zipRandomFile = null;
   9.698 +        ZipFileIndex zipFileIndex = null;
   9.699 +
   9.700 +        public ZipDirectory(RandomAccessFile zipRandomFile, long start, long end, ZipFileIndex index) throws IOException {
   9.701 +            this.zipRandomFile = zipRandomFile;
   9.702 +            this.zipFileIndex = index;
   9.703 +
   9.704 +            findCENRecord(start, end);
   9.705 +        }
   9.706 +
   9.707 +        /*
   9.708 +         * Reads zip file central directory.
   9.709 +         * For more details see readCEN in zip_util.c from the JDK sources.
   9.710 +         * This is a Java port of that function.
   9.711 +         */
   9.712 +        private void findCENRecord(long start, long end) throws IOException {
   9.713 +            long totalLength = end - start;
   9.714 +            int endbuflen = 1024;
   9.715 +            byte[] endbuf = new byte[endbuflen];
   9.716 +            long endbufend = end - start;
   9.717 +
   9.718 +            // There is a variable-length field after the dir offset record. We need to do consequential search.
   9.719 +            while (endbufend >= 22) {
   9.720 +                if (endbufend < endbuflen)
   9.721 +                    endbuflen = (int)endbufend;
   9.722 +                long endbufpos = endbufend - endbuflen;
   9.723 +                zipRandomFile.seek(start + endbufpos);
   9.724 +                zipRandomFile.readFully(endbuf, 0, endbuflen);
   9.725 +                int i = endbuflen - 22;
   9.726 +                while (i >= 0 &&
   9.727 +                        !(endbuf[i] == 0x50 &&
   9.728 +                        endbuf[i + 1] == 0x4b &&
   9.729 +                        endbuf[i + 2] == 0x05 &&
   9.730 +                        endbuf[i + 3] == 0x06 &&
   9.731 +                        endbufpos + i + 22 +
   9.732 +                        get2ByteLittleEndian(endbuf, i + 20) == totalLength)) {
   9.733 +                    i--;
   9.734 +                }
   9.735 +
   9.736 +                if (i >= 0) {
   9.737 +                    zipDir = new byte[get4ByteLittleEndian(endbuf, i + 12) + 2];
   9.738 +                    zipDir[0] = endbuf[i + 10];
   9.739 +                    zipDir[1] = endbuf[i + 11];
   9.740 +                    zipRandomFile.seek(start + get4ByteLittleEndian(endbuf, i + 16));
   9.741 +                    zipRandomFile.readFully(zipDir, 2, zipDir.length - 2);
   9.742 +                    return;
   9.743 +                } else {
   9.744 +                    endbufend = endbufpos + 21;
   9.745 +                }
   9.746 +            }
   9.747 +            throw new ZipException("cannot read zip file");
   9.748 +        }
   9.749 +        private void buildIndex() throws IOException {
   9.750 +            int entryCount = get2ByteLittleEndian(zipDir, 0);
   9.751 +
   9.752 +            entries = new ZipFileIndexEntry[entryCount];
   9.753 +            // Add each of the files
   9.754 +            if (entryCount > 0) {
   9.755 +                directories = new HashMap<String, DirectoryEntry>();
   9.756 +                ArrayList<ZipFileIndexEntry> entryList = new ArrayList<ZipFileIndexEntry>();
   9.757 +                int pos = 2;
   9.758 +                for (int i = 0; i < entryCount; i++) {
   9.759 +                    pos = readEntry(pos, entryList, directories);
   9.760 +                }
   9.761 +
   9.762 +                // Add the accumulated dirs into the same list
   9.763 +                Iterator i = directories.keySet().iterator();
   9.764 +                while (i.hasNext()) {
   9.765 +                    ZipFileIndexEntry zipFileIndexEntry = new ZipFileIndexEntry( (String) i.next());
   9.766 +                    zipFileIndexEntry.isDir = true;
   9.767 +                    entryList.add(zipFileIndexEntry);
   9.768 +                }
   9.769 +
   9.770 +                entries = entryList.toArray(new ZipFileIndexEntry[entryList.size()]);
   9.771 +                Arrays.sort(entries);
   9.772 +            } else {
   9.773 +                cleanupState();
   9.774 +            }
   9.775 +        }
   9.776 +
   9.777 +        private int readEntry(int pos, List<ZipFileIndexEntry> entryList,
   9.778 +                Map<String, DirectoryEntry> directories) throws IOException {
   9.779 +            if (get4ByteLittleEndian(zipDir, pos) != 0x02014b50) {
   9.780 +                throw new ZipException("cannot read zip file entry");
   9.781 +            }
   9.782 +
   9.783 +            int dirStart = pos + 46;
   9.784 +            int fileStart = dirStart;
   9.785 +            int fileEnd = fileStart + get2ByteLittleEndian(zipDir, pos + 28);
   9.786 +
   9.787 +            if (zipFileIndex.symbolFilePrefixLength != 0 &&
   9.788 +                    ((fileEnd - fileStart) >= symbolFilePrefixLength)) {
   9.789 +                dirStart += zipFileIndex.symbolFilePrefixLength;
   9.790 +               fileStart += zipFileIndex.symbolFilePrefixLength;
   9.791 +            }
   9.792 +
   9.793 +            // Use the OS's path separator. Keep the position of the last one.
   9.794 +            for (int index = fileStart; index < fileEnd; index++) {
   9.795 +                byte nextByte = zipDir[index];
   9.796 +                if (nextByte == (byte)'\\' || nextByte == (byte)'/') {
   9.797 +                    zipDir[index] = (byte)File.separatorChar;
   9.798 +                    fileStart = index + 1;
   9.799 +                }
   9.800 +            }
   9.801 +
   9.802 +            String directory = null;
   9.803 +            if (fileStart == dirStart)
   9.804 +                directory = "";
   9.805 +            else if (lastDir != null && lastLen == fileStart - dirStart - 1) {
   9.806 +                int index = lastLen - 1;
   9.807 +                while (zipDir[lastStart + index] == zipDir[dirStart + index]) {
   9.808 +                    if (index == 0) {
   9.809 +                        directory = lastDir;
   9.810 +                        break;
   9.811 +                    }
   9.812 +                    index--;
   9.813 +                }
   9.814 +            }
   9.815 +
   9.816 +            // Sub directories
   9.817 +            if (directory == null) {
   9.818 +                lastStart = dirStart;
   9.819 +                lastLen = fileStart - dirStart - 1;
   9.820 +
   9.821 +                directory = new String(zipDir, dirStart, lastLen, "UTF-8").intern();
   9.822 +                lastDir = directory;
   9.823 +
   9.824 +                // Enter also all the parent directories
   9.825 +                String tempDirectory = directory;
   9.826 +
   9.827 +                while (directories.get(tempDirectory) == null) {
   9.828 +                    directories.put(tempDirectory, new DirectoryEntry(tempDirectory, zipFileIndex));
   9.829 +                    int separator = tempDirectory.lastIndexOf(File.separatorChar);
   9.830 +                    if (separator == -1)
   9.831 +                        break;
   9.832 +                    tempDirectory = tempDirectory.substring(0, separator);
   9.833 +                }
   9.834 +            }
   9.835 +            else {
   9.836 +                directory = directory.intern();
   9.837 +                if (directories.get(directory) == null) {
   9.838 +                    directories.put(directory, new DirectoryEntry(directory, zipFileIndex));
   9.839 +                }
   9.840 +            }
   9.841 +
   9.842 +            // For each dir create also a file
   9.843 +            if (fileStart != fileEnd) {
   9.844 +                ZipFileIndexEntry entry = new ZipFileIndexEntry(directory,
   9.845 +                        new String(zipDir, fileStart, fileEnd - fileStart, "UTF-8"));
   9.846 +
   9.847 +                entry.setNativeTime(get4ByteLittleEndian(zipDir, pos + 12));
   9.848 +                entry.compressedSize = get4ByteLittleEndian(zipDir, pos + 20);
   9.849 +                entry.size = get4ByteLittleEndian(zipDir, pos + 24);
   9.850 +                entry.offset = get4ByteLittleEndian(zipDir, pos + 42);
   9.851 +                entryList.add(entry);
   9.852 +            }
   9.853 +
   9.854 +            return pos + 46 +
   9.855 +                    get2ByteLittleEndian(zipDir, pos + 28) +
   9.856 +                    get2ByteLittleEndian(zipDir, pos + 30) +
   9.857 +                    get2ByteLittleEndian(zipDir, pos + 32);
   9.858 +        }
   9.859 +    }
   9.860 +
   9.861 +    /**
   9.862 +     * Returns the last modified timestamp of a zip file.
   9.863 +     * @return long
   9.864 +     */
   9.865 +    public long getZipFileLastModified() throws IOException {
   9.866 +        lock.lock();
   9.867 +        try {
   9.868 +            checkIndex();
   9.869 +            return zipFileLastModified;
   9.870 +        }
   9.871 +        finally {
   9.872 +            lock.unlock();
   9.873 +        }
   9.874 +    }
   9.875 +
   9.876 +    /** ------------------------------------------------------------------------
   9.877 +     *  DirectoryEntry class
   9.878 +     * -------------------------------------------------------------------------*/
   9.879 +    static class DirectoryEntry {
   9.880 +        private boolean filesInited;
   9.881 +        private boolean directoriesInited;
   9.882 +        private boolean zipFileEntriesInited;
   9.883 +        private boolean entriesInited;
   9.884 +
   9.885 +        private long writtenOffsetOffset = 0;
   9.886 +
   9.887 +        private String dirName;
   9.888 +
   9.889 +        private com.sun.tools.javac.util.List<String> zipFileEntriesFiles = com.sun.tools.javac.util.List.<String>nil();
   9.890 +        private com.sun.tools.javac.util.List<String> zipFileEntriesDirectories = com.sun.tools.javac.util.List.<String>nil();
   9.891 +        private com.sun.tools.javac.util.List<ZipFileIndexEntry>  zipFileEntries = com.sun.tools.javac.util.List.<ZipFileIndexEntry>nil();
   9.892 +
   9.893 +        private List<ZipFileIndexEntry> entries = new ArrayList<ZipFileIndexEntry>();
   9.894 +
   9.895 +        private ZipFileIndex zipFileIndex;
   9.896 +
   9.897 +        private int numEntries;
   9.898 +
   9.899 +        DirectoryEntry(String dirName, ZipFileIndex index) {
   9.900 +        filesInited = false;
   9.901 +            directoriesInited = false;
   9.902 +            entriesInited = false;
   9.903 +
   9.904 +            if (File.separatorChar == '/') {
   9.905 +                dirName.replace('\\', '/');
   9.906 +            }
   9.907 +            else {
   9.908 +                dirName.replace('/', '\\');
   9.909 +            }
   9.910 +
   9.911 +            this.dirName = dirName.intern();
   9.912 +            this.zipFileIndex = index;
   9.913 +        }
   9.914 +
   9.915 +        private com.sun.tools.javac.util.List<String> getFiles() {
   9.916 +            if (filesInited) {
   9.917 +                return zipFileEntriesFiles;
   9.918 +            }
   9.919 +
   9.920 +            initEntries();
   9.921 +
   9.922 +            for (ZipFileIndexEntry e : entries) {
   9.923 +                if (!e.isDir) {
   9.924 +                    zipFileEntriesFiles = zipFileEntriesFiles.append(e.name);
   9.925 +                }
   9.926 +            }
   9.927 +            filesInited = true;
   9.928 +            return zipFileEntriesFiles;
   9.929 +        }
   9.930 +
   9.931 +        private com.sun.tools.javac.util.List<String> getDirectories() {
   9.932 +            if (directoriesInited) {
   9.933 +                return zipFileEntriesFiles;
   9.934 +            }
   9.935 +
   9.936 +            initEntries();
   9.937 +
   9.938 +            for (ZipFileIndexEntry e : entries) {
   9.939 +                if (e.isDir) {
   9.940 +                    zipFileEntriesDirectories = zipFileEntriesDirectories.append(e.name);
   9.941 +                }
   9.942 +            }
   9.943 +
   9.944 +            directoriesInited = true;
   9.945 +
   9.946 +            return zipFileEntriesDirectories;
   9.947 +        }
   9.948 +
   9.949 +        private com.sun.tools.javac.util.List<ZipFileIndexEntry> getEntries() {
   9.950 +            if (zipFileEntriesInited) {
   9.951 +                return zipFileEntries;
   9.952 +            }
   9.953 +
   9.954 +            initEntries();
   9.955 +
   9.956 +            zipFileEntries = com.sun.tools.javac.util.List.nil();
   9.957 +            for (ZipFileIndexEntry zfie : entries) {
   9.958 +                zipFileEntries = zipFileEntries.append(zfie);
   9.959 +            }
   9.960 +
   9.961 +            zipFileEntriesInited = true;
   9.962 +
   9.963 +            return zipFileEntries;
   9.964 +        }
   9.965 +
   9.966 +        private ZipFileIndexEntry getEntry(String rootName) {
   9.967 +            initEntries();
   9.968 +            int index = Collections.binarySearch(entries, new ZipFileIndexEntry(dirName, rootName));
   9.969 +            if (index < 0) {
   9.970 +                return null;
   9.971 +            }
   9.972 +
   9.973 +            return entries.get(index);
   9.974 +        }
   9.975 +
   9.976 +        private void initEntries() {
   9.977 +            if (entriesInited) {
   9.978 +                return;
   9.979 +            }
   9.980 +
   9.981 +            if (!zipFileIndex.readFromIndex) {
   9.982 +                int from = -Arrays.binarySearch(zipFileIndex.entries,
   9.983 +                        new ZipFileIndexEntry(dirName, ZipFileIndex.MIN_CHAR)) - 1;
   9.984 +                int to = -Arrays.binarySearch(zipFileIndex.entries,
   9.985 +                        new ZipFileIndexEntry(dirName, MAX_CHAR)) - 1;
   9.986 +
   9.987 +                boolean emptyList = false;
   9.988 +
   9.989 +                for (int i = from; i < to; i++) {
   9.990 +                    entries.add(zipFileIndex.entries[i]);
   9.991 +                }
   9.992 +            } else {
   9.993 +                File indexFile = zipFileIndex.getIndexFile();
   9.994 +                if (indexFile != null) {
   9.995 +                    RandomAccessFile raf = null;
   9.996 +                    try {
   9.997 +                        raf = new RandomAccessFile(indexFile, "r");
   9.998 +                        raf.seek(writtenOffsetOffset);
   9.999 +
  9.1000 +                        for (int nFiles = 0; nFiles < numEntries; nFiles++) {
  9.1001 +                            // Read the name bytes
  9.1002 +                            int zfieNameBytesLen = raf.readInt();
  9.1003 +                            byte [] zfieNameBytes = new byte[zfieNameBytesLen];
  9.1004 +                            raf.read(zfieNameBytes);
  9.1005 +                            String eName = new String(zfieNameBytes, "UTF-8");
  9.1006 +
  9.1007 +                            // Read isDir
  9.1008 +                            boolean eIsDir = raf.readByte() == (byte)0 ? false : true;
  9.1009 +
  9.1010 +                            // Read offset of bytes in the real Jar/Zip file
  9.1011 +                            int eOffset = raf.readInt();
  9.1012 +
  9.1013 +                            // Read size of the file in the real Jar/Zip file
  9.1014 +                            int eSize = raf.readInt();
  9.1015 +
  9.1016 +                            // Read compressed size of the file in the real Jar/Zip file
  9.1017 +                            int eCsize = raf.readInt();
  9.1018 +
  9.1019 +                            // Read java time stamp of the file in the real Jar/Zip file
  9.1020 +                            long eJavaTimestamp = raf.readLong();
  9.1021 +
  9.1022 +                            ZipFileIndexEntry rfie = new ZipFileIndexEntry(dirName, eName);
  9.1023 +                            rfie.isDir = eIsDir;
  9.1024 +                            rfie.offset = eOffset;
  9.1025 +                            rfie.size = eSize;
  9.1026 +                            rfie.compressedSize = eCsize;
  9.1027 +                            rfie.javatime = eJavaTimestamp;
  9.1028 +                            entries.add(rfie);
  9.1029 +                        }
  9.1030 +                    } catch (Throwable t) {
  9.1031 +                        // Do nothing
  9.1032 +                    } finally {
  9.1033 +                        try {
  9.1034 +                            if (raf == null) {
  9.1035 +                                raf.close();
  9.1036 +                            }
  9.1037 +                        } catch (Throwable t) {
  9.1038 +                            // Do nothing
  9.1039 +                        }
  9.1040 +                    }
  9.1041 +                }
  9.1042 +            }
  9.1043 +
  9.1044 +            entriesInited = true;
  9.1045 +        }
  9.1046 +
  9.1047 +        List<ZipFileIndexEntry> getEntriesAsCollection() {
  9.1048 +            initEntries();
  9.1049 +
  9.1050 +            return entries;
  9.1051 +        }
  9.1052 +    }
  9.1053 +
  9.1054 +    private boolean readIndex() {
  9.1055 +        if (triedToReadIndex || !usePreindexedCache) {
  9.1056 +            return false;
  9.1057 +        }
  9.1058 +
  9.1059 +        boolean ret = false;
  9.1060 +        lock.lock();
  9.1061 +        try {
  9.1062 +            triedToReadIndex = true;
  9.1063 +            RandomAccessFile raf = null;
  9.1064 +            try {
  9.1065 +                File indexFileName = getIndexFile();
  9.1066 +                raf = new RandomAccessFile(indexFileName, "r");
  9.1067 +
  9.1068 +                long fileStamp = raf.readLong();
  9.1069 +                if (zipFile.lastModified() != fileStamp) {
  9.1070 +                    ret = false;
  9.1071 +                } else {
  9.1072 +                    directories = new HashMap<String, DirectoryEntry>();
  9.1073 +                    int numDirs = raf.readInt();
  9.1074 +                    for (int nDirs = 0; nDirs < numDirs; nDirs++) {
  9.1075 +                        int dirNameBytesLen = raf.readInt();
  9.1076 +                        byte [] dirNameBytes = new byte[dirNameBytesLen];
  9.1077 +                        raf.read(dirNameBytes);
  9.1078 +
  9.1079 +                        String dirNameStr = new String(dirNameBytes, "UTF-8");
  9.1080 +                        DirectoryEntry de = new DirectoryEntry(dirNameStr, this);
  9.1081 +                        de.numEntries = raf.readInt();
  9.1082 +                        de.writtenOffsetOffset = raf.readLong();
  9.1083 +                        directories.put(dirNameStr, de);
  9.1084 +                    }
  9.1085 +                    ret = true;
  9.1086 +                    zipFileLastModified = fileStamp;
  9.1087 +                }
  9.1088 +            } catch (Throwable t) {
  9.1089 +                // Do nothing
  9.1090 +            } finally {
  9.1091 +                if (raf != null) {
  9.1092 +                    try {
  9.1093 +                        raf.close();
  9.1094 +                    } catch (Throwable tt) {
  9.1095 +                        // Do nothing
  9.1096 +                    }
  9.1097 +                }
  9.1098 +            }
  9.1099 +            if (ret == true) {
  9.1100 +                readFromIndex = true;
  9.1101 +            }
  9.1102 +        }
  9.1103 +        finally {
  9.1104 +            lock.unlock();
  9.1105 +        }
  9.1106 +
  9.1107 +        return ret;
  9.1108 +    }
  9.1109 +
  9.1110 +    private boolean writeIndex() {
  9.1111 +        boolean ret = false;
  9.1112 +        if (readFromIndex || !usePreindexedCache) {
  9.1113 +            return true;
  9.1114 +        }
  9.1115 +
  9.1116 +        if (!writeIndex) {
  9.1117 +            return true;
  9.1118 +        }
  9.1119 +
  9.1120 +        File indexFile = getIndexFile();
  9.1121 +        if (indexFile == null) {
  9.1122 +            return false;
  9.1123 +        }
  9.1124 +
  9.1125 +        RandomAccessFile raf = null;
  9.1126 +        long writtenSoFar = 0;
  9.1127 +        try {
  9.1128 +            raf = new RandomAccessFile(indexFile, "rw");
  9.1129 +
  9.1130 +            raf.writeLong(zipFileLastModified);
  9.1131 +            writtenSoFar += 8;
  9.1132 +
  9.1133 +
  9.1134 +            Iterator<String> iterDirName = directories.keySet().iterator();
  9.1135 +            List<DirectoryEntry> directoriesToWrite = new ArrayList<DirectoryEntry>();
  9.1136 +            Map<String, Long> offsets = new HashMap<String, Long>();
  9.1137 +            raf.writeInt(directories.keySet().size());
  9.1138 +            writtenSoFar += 4;
  9.1139 +
  9.1140 +            while(iterDirName.hasNext()) {
  9.1141 +                String dirName = iterDirName.next();
  9.1142 +                DirectoryEntry dirEntry = directories.get(dirName);
  9.1143 +
  9.1144 +                directoriesToWrite.add(dirEntry);
  9.1145 +
  9.1146 +                // Write the dir name bytes
  9.1147 +                byte [] dirNameBytes = dirName.getBytes("UTF-8");
  9.1148 +                int dirNameBytesLen = dirNameBytes.length;
  9.1149 +                raf.writeInt(dirNameBytesLen);
  9.1150 +                writtenSoFar += 4;
  9.1151 +
  9.1152 +                raf.write(dirNameBytes);
  9.1153 +                writtenSoFar += dirNameBytesLen;
  9.1154 +
  9.1155 +                // Write the number of files in the dir
  9.1156 +                List dirEntries = dirEntry.getEntriesAsCollection();
  9.1157 +                raf.writeInt(dirEntries.size());
  9.1158 +                writtenSoFar += 4;
  9.1159 +
  9.1160 +                offsets.put(dirName, new Long(writtenSoFar));
  9.1161 +
  9.1162 +                // Write the offset of the file's data in the dir
  9.1163 +                dirEntry.writtenOffsetOffset = 0L;
  9.1164 +                raf.writeLong(0L);
  9.1165 +                writtenSoFar += 8;
  9.1166 +            }
  9.1167 +
  9.1168 +            for (DirectoryEntry de : directoriesToWrite) {
  9.1169 +                // Fix up the offset in the directory table
  9.1170 +                long currFP = raf.getFilePointer();
  9.1171 +
  9.1172 +                long offsetOffset = offsets.get(de.dirName).longValue();
  9.1173 +                raf.seek(offsetOffset);
  9.1174 +                raf.writeLong(writtenSoFar);
  9.1175 +
  9.1176 +                raf.seek(currFP);
  9.1177 +
  9.1178 +                // Now write each of the files in the DirectoryEntry
  9.1179 +                List<ZipFileIndexEntry> entries = de.getEntriesAsCollection();
  9.1180 +                for (ZipFileIndexEntry zfie : entries) {
  9.1181 +                    // Write the name bytes
  9.1182 +                    byte [] zfieNameBytes = zfie.name.getBytes("UTF-8");
  9.1183 +                    int zfieNameBytesLen = zfieNameBytes.length;
  9.1184 +                    raf.writeInt(zfieNameBytesLen);
  9.1185 +                    writtenSoFar += 4;
  9.1186 +                    raf.write(zfieNameBytes);
  9.1187 +                    writtenSoFar += zfieNameBytesLen;
  9.1188 +
  9.1189 +                    // Write isDir
  9.1190 +                    raf.writeByte(zfie.isDir ? (byte)1 : (byte)0);
  9.1191 +                    writtenSoFar += 1;
  9.1192 +
  9.1193 +                    // Write offset of bytes in the real Jar/Zip file
  9.1194 +                    raf.writeInt(zfie.offset);
  9.1195 +                    writtenSoFar += 4;
  9.1196 +
  9.1197 +                    // Write size of the file in the real Jar/Zip file
  9.1198 +                    raf.writeInt(zfie.size);
  9.1199 +                    writtenSoFar += 4;
  9.1200 +
  9.1201 +                    // Write compressed size of the file in the real Jar/Zip file
  9.1202 +                    raf.writeInt(zfie.compressedSize);
  9.1203 +                    writtenSoFar += 4;
  9.1204 +
  9.1205 +                    // Write java time stamp of the file in the real Jar/Zip file
  9.1206 +                    raf.writeLong(zfie.getLastModified());
  9.1207 +                    writtenSoFar += 8;
  9.1208 +                }
  9.1209 +            }
  9.1210 +        } catch (Throwable t) {
  9.1211 +            // Do nothing
  9.1212 +        } finally {
  9.1213 +            try {
  9.1214 +                if (raf != null) {
  9.1215 +                    raf.close();
  9.1216 +                }
  9.1217 +            } catch(IOException ioe) {
  9.1218 +                // Do nothing
  9.1219 +            }
  9.1220 +        }
  9.1221 +
  9.1222 +        return ret;
  9.1223 +    }
  9.1224 +
  9.1225 +    public boolean writeZipIndex() {
  9.1226 +        lock.lock();
  9.1227 +        try {
  9.1228 +            return writeIndex();
  9.1229 +        }
  9.1230 +        finally {
  9.1231 +            lock.unlock();
  9.1232 +        }
  9.1233 +    }
  9.1234 +
  9.1235 +    private File getIndexFile() {
  9.1236 +        if (zipIndexFile == null) {
  9.1237 +            if (zipFile == null) {
  9.1238 +                return null;
  9.1239 +            }
  9.1240 +
  9.1241 +            zipIndexFile = new File((preindexedCacheLocation == null ? "" : preindexedCacheLocation) +
  9.1242 +                    zipFile.getName() + ".index");
  9.1243 +        }
  9.1244 +
  9.1245 +        return zipIndexFile;
  9.1246 +    }
  9.1247 +
  9.1248 +    public File getZipFile() {
  9.1249 +        return zipFile;
  9.1250 +    }
  9.1251 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndexEntry.java	Mon Jun 16 13:28:00 2008 -0700
    10.3 @@ -0,0 +1,116 @@
    10.4 +/*
    10.5 + * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
    10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.7 + *
    10.8 + * This code is free software; you can redistribute it and/or modify it
    10.9 + * under the terms of the GNU General Public License version 2 only, as
   10.10 + * published by the Free Software Foundation.  Sun designates this
   10.11 + * particular file as subject to the "Classpath" exception as provided
   10.12 + * by Sun in the LICENSE file that accompanied this code.
   10.13 + *
   10.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   10.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   10.17 + * version 2 for more details (a copy is included in the LICENSE file that
   10.18 + * accompanied this code).
   10.19 + *
   10.20 + * You should have received a copy of the GNU General Public License version
   10.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   10.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   10.23 + *
   10.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   10.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   10.26 + * have any questions.
   10.27 + */
   10.28 +
   10.29 +package com.sun.tools.javac.file;
   10.30 +
   10.31 +import java.io.File;
   10.32 +
   10.33 +public final class ZipFileIndexEntry implements Comparable<ZipFileIndexEntry> {
   10.34 +    public static final ZipFileIndexEntry[] EMPTY_ARRAY = {};
   10.35 +
   10.36 +    // Directory related
   10.37 +    String dir;
   10.38 +    boolean isDir;
   10.39 +
   10.40 +    // File related
   10.41 +    String name;
   10.42 +
   10.43 +    int offset;
   10.44 +    int size;
   10.45 +    int compressedSize;
   10.46 +    long javatime;
   10.47 +
   10.48 +    private int nativetime;
   10.49 +
   10.50 +    public ZipFileIndexEntry(String path) {
   10.51 +        int separator = path.lastIndexOf(File.separatorChar);
   10.52 +        if (separator == -1) {
   10.53 +            dir = "".intern();
   10.54 +            name = path;
   10.55 +        } else {
   10.56 +            dir = path.substring(0, separator).intern();
   10.57 +            name = path.substring(separator + 1);
   10.58 +        }
   10.59 +    }
   10.60 +
   10.61 +    public ZipFileIndexEntry(String directory, String name) {
   10.62 +        this.dir = directory.intern();
   10.63 +        this.name = name;
   10.64 +    }
   10.65 +
   10.66 +    public String getName() {
   10.67 +        if (dir == null || dir.length() == 0) {
   10.68 +            return name;
   10.69 +        }
   10.70 +
   10.71 +        StringBuilder sb = new StringBuilder();
   10.72 +        sb.append(dir);
   10.73 +        sb.append(File.separatorChar);
   10.74 +        sb.append(name);
   10.75 +        return sb.toString();
   10.76 +    }
   10.77 +
   10.78 +    public String getFileName() {
   10.79 +        return name;
   10.80 +    }
   10.81 +
   10.82 +    public long getLastModified() {
   10.83 +        if (javatime == 0) {
   10.84 +                javatime = dosToJavaTime(nativetime);
   10.85 +        }
   10.86 +        return javatime;
   10.87 +    }
   10.88 +
   10.89 +    // From java.util.zip
   10.90 +    private static long dosToJavaTime(int nativetime) {
   10.91 +        // Bootstrap build problems prevent me from using the code directly
   10.92 +        // Convert the raw/native time to a long for now
   10.93 +        return (long)nativetime;
   10.94 +    }
   10.95 +
   10.96 +    void setNativeTime(int natTime) {
   10.97 +        nativetime = natTime;
   10.98 +    }
   10.99 +
  10.100 +    public boolean isDirectory() {
  10.101 +        return isDir;
  10.102 +    }
  10.103 +
  10.104 +    public int compareTo(ZipFileIndexEntry other) {
  10.105 +        String otherD = other.dir;
  10.106 +        if (dir != otherD) {
  10.107 +            int c = dir.compareTo(otherD);
  10.108 +            if (c != 0)
  10.109 +                return c;
  10.110 +        }
  10.111 +        return name.compareTo(other.name);
  10.112 +    }
  10.113 +
  10.114 +
  10.115 +    public String toString() {
  10.116 +        return isDir ? ("Dir:" + dir + " : " + name) :
  10.117 +            (dir + ":" + name);
  10.118 +    }
  10.119 +}
    11.1 --- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri Jun 06 15:17:35 2008 -0700
    11.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Jun 16 13:28:00 2008 -0700
    11.3 @@ -42,6 +42,7 @@
    11.4  import com.sun.tools.javac.code.Type.*;
    11.5  import com.sun.tools.javac.code.Symbol.*;
    11.6  import com.sun.tools.javac.code.Symtab;
    11.7 +import com.sun.tools.javac.file.BaseFileObject;
    11.8  import com.sun.tools.javac.util.*;
    11.9  import com.sun.tools.javac.util.List;
   11.10  
    12.1 --- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Fri Jun 06 15:17:35 2008 -0700
    12.2 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Mon Jun 16 13:28:00 2008 -0700
    12.3 @@ -40,6 +40,7 @@
    12.4  import javax.tools.JavaFileObject;
    12.5  import javax.tools.DiagnosticListener;
    12.6  
    12.7 +import com.sun.tools.javac.file.JavacFileManager;
    12.8  import com.sun.source.util.TaskEvent;
    12.9  import com.sun.source.util.TaskListener;
   12.10  
    13.1 --- a/src/share/classes/com/sun/tools/javac/main/Main.java	Fri Jun 06 15:17:35 2008 -0700
    13.2 +++ b/src/share/classes/com/sun/tools/javac/main/Main.java	Mon Jun 16 13:28:00 2008 -0700
    13.3 @@ -25,13 +25,13 @@
    13.4  
    13.5  package com.sun.tools.javac.main;
    13.6  
    13.7 -import com.sun.tools.javac.util.Options;
    13.8  import java.io.File;
    13.9  import java.io.IOException;
   13.10  import java.io.PrintWriter;
   13.11  import java.util.MissingResourceException;
   13.12  
   13.13  import com.sun.tools.javac.code.Source;
   13.14 +import com.sun.tools.javac.file.JavacFileManager;
   13.15  import com.sun.tools.javac.jvm.Target;
   13.16  import com.sun.tools.javac.main.JavacOption.Option;
   13.17  import com.sun.tools.javac.main.RecognizedOptions.OptionHelper;
    14.1 --- a/src/share/classes/com/sun/tools/javac/parser/Scanner.java	Fri Jun 06 15:17:35 2008 -0700
    14.2 +++ b/src/share/classes/com/sun/tools/javac/parser/Scanner.java	Mon Jun 16 13:28:00 2008 -0700
    14.3 @@ -25,16 +25,12 @@
    14.4  
    14.5  package com.sun.tools.javac.parser;
    14.6  
    14.7 -import java.io.*;
    14.8  import java.nio.*;
    14.9 -import java.nio.ByteBuffer;
   14.10 -import java.nio.charset.*;
   14.11 -import java.nio.channels.*;
   14.12 -import java.util.regex.*;
   14.13  
   14.14 +import com.sun.tools.javac.code.Source;
   14.15 +import com.sun.tools.javac.file.JavacFileManager;
   14.16  import com.sun.tools.javac.util.*;
   14.17  
   14.18 -import com.sun.tools.javac.code.Source;
   14.19  
   14.20  import static com.sun.tools.javac.parser.Token.*;
   14.21  import static com.sun.tools.javac.util.LayoutCharacters.*;
    15.1 --- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Fri Jun 06 15:17:35 2008 -0700
    15.2 +++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Mon Jun 16 13:28:00 2008 -0700
    15.3 @@ -25,22 +25,17 @@
    15.4  
    15.5  package com.sun.tools.javac.processing;
    15.6  
    15.7 -import com.sun.source.util.TaskEvent;
    15.8 -import com.sun.source.util.TaskListener;
    15.9 -import com.sun.tools.javac.api.JavacTaskImpl;
   15.10 -import com.sun.tools.javac.util.List;
   15.11 -import com.sun.tools.javac.util.*;
   15.12 -import com.sun.tools.javac.code.*;
   15.13 -import com.sun.tools.javac.code.Symbol.*;
   15.14 -import com.sun.tools.javac.comp.*;
   15.15 -import com.sun.tools.javac.jvm.*;
   15.16 -import com.sun.tools.javac.tree.*;
   15.17 -import com.sun.tools.javac.parser.*;
   15.18 -import com.sun.tools.javac.code.Symbol.*;
   15.19 -import com.sun.tools.javac.model.JavacElements;
   15.20 -import com.sun.tools.javac.model.JavacTypes;
   15.21 -import com.sun.tools.javac.tree.JCTree.*;
   15.22 -import com.sun.tools.javac.main.JavaCompiler;
   15.23 +
   15.24 +import java.lang.reflect.*;
   15.25 +import java.util.*;
   15.26 +import java.util.regex.*;
   15.27 +
   15.28 +import java.net.URL;
   15.29 +import java.io.Closeable;
   15.30 +import java.io.File;
   15.31 +import java.io.PrintWriter;
   15.32 +import java.io.IOException;
   15.33 +import java.net.MalformedURLException;
   15.34  import java.io.StringWriter;
   15.35  
   15.36  import javax.annotation.processing.*;
   15.37 @@ -50,25 +45,35 @@
   15.38  import javax.lang.model.element.TypeElement;
   15.39  import javax.lang.model.element.PackageElement;
   15.40  import javax.lang.model.util.*;
   15.41 -
   15.42  import javax.tools.JavaFileManager;
   15.43  import javax.tools.StandardJavaFileManager;
   15.44  import javax.tools.JavaFileObject;
   15.45  import javax.tools.DiagnosticListener;
   15.46 +
   15.47 +import com.sun.source.util.TaskEvent;
   15.48 +import com.sun.source.util.TaskListener;
   15.49 +import com.sun.tools.javac.api.JavacTaskImpl;
   15.50 +import com.sun.tools.javac.code.*;
   15.51 +import com.sun.tools.javac.code.Symbol.*;
   15.52 +import com.sun.tools.javac.file.Paths;
   15.53 +import com.sun.tools.javac.file.JavacFileManager;
   15.54 +import com.sun.tools.javac.jvm.*;
   15.55 +import com.sun.tools.javac.main.JavaCompiler;
   15.56 +import com.sun.tools.javac.model.JavacElements;
   15.57 +import com.sun.tools.javac.model.JavacTypes;
   15.58 +import com.sun.tools.javac.parser.*;
   15.59 +import com.sun.tools.javac.tree.*;
   15.60 +import com.sun.tools.javac.tree.JCTree.*;
   15.61 +import com.sun.tools.javac.util.Abort;
   15.62 +import com.sun.tools.javac.util.Context;
   15.63 +import com.sun.tools.javac.util.List;
   15.64 +import com.sun.tools.javac.util.ListBuffer;
   15.65 +import com.sun.tools.javac.util.Log;
   15.66 +import com.sun.tools.javac.util.Name;
   15.67 +import com.sun.tools.javac.util.Options;
   15.68 +
   15.69  import static javax.tools.StandardLocation.*;
   15.70  
   15.71 -import java.lang.reflect.*;
   15.72 -import java.util.*;
   15.73 -import java.util.regex.*;
   15.74 -
   15.75 -import java.net.URLClassLoader;
   15.76 -import java.net.URL;
   15.77 -import java.io.Closeable;
   15.78 -import java.io.File;
   15.79 -import java.io.PrintWriter;
   15.80 -import java.io.IOException;
   15.81 -import java.net.MalformedURLException;
   15.82 -
   15.83  /**
   15.84   * Objects of this class hold and manage the state needed to support
   15.85   * annotation processing.
    16.1 --- a/src/share/classes/com/sun/tools/javac/util/BaseFileObject.java	Fri Jun 06 15:17:35 2008 -0700
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,79 +0,0 @@
    16.4 -/*
    16.5 - * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
    16.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    16.7 - *
    16.8 - * This code is free software; you can redistribute it and/or modify it
    16.9 - * under the terms of the GNU General Public License version 2 only, as
   16.10 - * published by the Free Software Foundation.  Sun designates this
   16.11 - * particular file as subject to the "Classpath" exception as provided
   16.12 - * by Sun in the LICENSE file that accompanied this code.
   16.13 - *
   16.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
   16.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   16.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   16.17 - * version 2 for more details (a copy is included in the LICENSE file that
   16.18 - * accompanied this code).
   16.19 - *
   16.20 - * You should have received a copy of the GNU General Public License version
   16.21 - * 2 along with this work; if not, write to the Free Software Foundation,
   16.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   16.23 - *
   16.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   16.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
   16.26 - * have any questions.
   16.27 - */
   16.28 -
   16.29 -package com.sun.tools.javac.util;
   16.30 -
   16.31 -import java.io.IOException;
   16.32 -import java.io.InputStreamReader;
   16.33 -import java.io.Reader;
   16.34 -import java.nio.charset.CharsetDecoder;
   16.35 -import javax.lang.model.element.Modifier;
   16.36 -import javax.lang.model.element.NestingKind;
   16.37 -import javax.tools.JavaFileObject;
   16.38 -
   16.39 -import static javax.tools.JavaFileObject.Kind.*;
   16.40 -
   16.41 -public abstract class BaseFileObject implements JavaFileObject {
   16.42 -
   16.43 -    public JavaFileObject.Kind getKind() {
   16.44 -        String n = getName();
   16.45 -        if (n.endsWith(CLASS.extension))
   16.46 -            return CLASS;
   16.47 -        else if (n.endsWith(SOURCE.extension))
   16.48 -            return SOURCE;
   16.49 -        else if (n.endsWith(HTML.extension))
   16.50 -            return HTML;
   16.51 -        else
   16.52 -            return OTHER;
   16.53 -    }
   16.54 -
   16.55 -    @Override
   16.56 -    public String toString() {
   16.57 -        return getPath();
   16.58 -    }
   16.59 -
   16.60 -    /** @deprecated see bug 6410637 */
   16.61 -    @Deprecated
   16.62 -    public String getPath() {
   16.63 -        return getName();
   16.64 -    }
   16.65 -
   16.66 -    /** @deprecated see bug 6410637 */
   16.67 -    @Deprecated
   16.68 -    abstract public String getName();
   16.69 -
   16.70 -    public NestingKind getNestingKind() { return null; }
   16.71 -
   16.72 -    public Modifier getAccessLevel()  { return null; }
   16.73 -
   16.74 -    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
   16.75 -        return new InputStreamReader(openInputStream(), getDecoder(ignoreEncodingErrors));
   16.76 -    }
   16.77 -
   16.78 -    protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
   16.79 -        throw new UnsupportedOperationException();
   16.80 -    }
   16.81 -
   16.82 -}
    17.1 --- a/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java	Fri Jun 06 15:17:35 2008 -0700
    17.2 +++ b/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java	Mon Jun 16 13:28:00 2008 -0700
    17.3 @@ -27,6 +27,7 @@
    17.4  
    17.5  import javax.tools.JavaFileObject;
    17.6  
    17.7 +import com.sun.tools.javac.file.JavacFileManager;
    17.8  import com.sun.tools.javac.util.JCDiagnostic.DiagnosticSource;
    17.9  import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
   17.10  
    18.1 --- a/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Fri Jun 06 15:17:35 2008 -0700
    18.2 +++ b/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Mon Jun 16 13:28:00 2008 -0700
    18.3 @@ -25,17 +25,13 @@
    18.4  
    18.5  package com.sun.tools.javac.util;
    18.6  
    18.7 -import java.net.URI;
    18.8 -import java.text.MessageFormat;
    18.9  import java.util.Locale;
   18.10  import java.util.Map;
   18.11 -import java.util.MissingResourceException;
   18.12 -import java.util.ResourceBundle;
   18.13  
   18.14  import javax.tools.Diagnostic;
   18.15 -import javax.tools.FileObject;
   18.16  import javax.tools.JavaFileObject;
   18.17  
   18.18 +import com.sun.tools.javac.file.JavacFileManager;
   18.19  import com.sun.tools.javac.tree.JCTree;
   18.20  
   18.21  import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
    19.1 --- a/src/share/classes/com/sun/tools/javac/util/JavacFileManager.java	Fri Jun 06 15:17:35 2008 -0700
    19.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3 @@ -1,1715 +0,0 @@
    19.4 -/*
    19.5 - * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
    19.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.7 - *
    19.8 - * This code is free software; you can redistribute it and/or modify it
    19.9 - * under the terms of the GNU General Public License version 2 only, as
   19.10 - * published by the Free Software Foundation.  Sun designates this
   19.11 - * particular file as subject to the "Classpath" exception as provided
   19.12 - * by Sun in the LICENSE file that accompanied this code.
   19.13 - *
   19.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
   19.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   19.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   19.17 - * version 2 for more details (a copy is included in the LICENSE file that
   19.18 - * accompanied this code).
   19.19 - *
   19.20 - * You should have received a copy of the GNU General Public License version
   19.21 - * 2 along with this work; if not, write to the Free Software Foundation,
   19.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   19.23 - *
   19.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   19.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
   19.26 - * have any questions.
   19.27 - */
   19.28 -
   19.29 -package com.sun.tools.javac.util;
   19.30 -
   19.31 -import com.sun.tools.javac.main.JavacOption;
   19.32 -import com.sun.tools.javac.main.OptionName;
   19.33 -import com.sun.tools.javac.main.RecognizedOptions;
   19.34 -import java.io.ByteArrayOutputStream;
   19.35 -import java.io.File;
   19.36 -import java.io.FileInputStream;
   19.37 -import java.io.FileNotFoundException;
   19.38 -import java.io.FileOutputStream;
   19.39 -import java.io.IOException;
   19.40 -import java.io.InputStream;
   19.41 -import java.io.OutputStream;
   19.42 -import java.io.OutputStreamWriter;
   19.43 -import java.io.Writer;
   19.44 -import java.lang.ref.SoftReference;
   19.45 -import java.net.MalformedURLException;
   19.46 -import java.net.URI;
   19.47 -import java.net.URISyntaxException;
   19.48 -import java.net.URL;
   19.49 -import java.net.URLClassLoader;
   19.50 -import java.nio.ByteBuffer;
   19.51 -import java.nio.CharBuffer;
   19.52 -import java.nio.channels.FileChannel;
   19.53 -import java.nio.charset.Charset;
   19.54 -import java.nio.charset.CharsetDecoder;
   19.55 -import java.nio.charset.CoderResult;
   19.56 -import java.nio.charset.CodingErrorAction;
   19.57 -import java.nio.charset.IllegalCharsetNameException;
   19.58 -import java.nio.charset.UnsupportedCharsetException;
   19.59 -import java.util.ArrayList;
   19.60 -import java.util.Arrays;
   19.61 -import java.util.Collection;
   19.62 -import java.util.Collections;
   19.63 -import java.util.EnumSet;
   19.64 -import java.util.Enumeration;
   19.65 -import java.util.HashMap;
   19.66 -import java.util.Iterator;
   19.67 -import java.util.Map;
   19.68 -import java.util.Set;
   19.69 -import java.util.zip.ZipEntry;
   19.70 -import java.util.zip.ZipFile;
   19.71 -
   19.72 -import javax.lang.model.SourceVersion;
   19.73 -import javax.tools.FileObject;
   19.74 -import javax.tools.JavaFileManager;
   19.75 -import javax.tools.JavaFileObject;
   19.76 -
   19.77 -import com.sun.tools.javac.code.Source;
   19.78 -import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
   19.79 -import java.util.concurrent.ConcurrentHashMap;
   19.80 -import javax.tools.StandardJavaFileManager;
   19.81 -
   19.82 -import com.sun.tools.javac.zip.*;
   19.83 -import java.io.ByteArrayInputStream;
   19.84 -
   19.85 -import static com.sun.tools.javac.main.OptionName.*;
   19.86 -import static javax.tools.StandardLocation.*;
   19.87 -
   19.88 -/**
   19.89 - * This class provides access to the source, class and other files
   19.90 - * used by the compiler and related tools.
   19.91 - */
   19.92 -public class JavacFileManager implements StandardJavaFileManager {
   19.93 -
   19.94 -    private static final String[] symbolFileLocation = { "lib", "ct.sym" };
   19.95 -    private static final String symbolFilePrefix = "META-INF/sym/rt.jar/";
   19.96 -
   19.97 -    boolean useZipFileIndex;
   19.98 -
   19.99 -    private static int symbolFilePrefixLength = 0;
  19.100 -    static {
  19.101 -        try {
  19.102 -            symbolFilePrefixLength = symbolFilePrefix.getBytes("UTF-8").length;
  19.103 -        } catch (java.io.UnsupportedEncodingException uee) {
  19.104 -            // Can't happen...UTF-8 is always supported.
  19.105 -        }
  19.106 -    }
  19.107 -
  19.108 -    private static boolean CHECK_ZIP_TIMESTAMP = false;
  19.109 -    private static Map<File, Boolean> isDirectory = new ConcurrentHashMap<File, Boolean>();
  19.110 -
  19.111 -
  19.112 -    public static char[] toArray(CharBuffer buffer) {
  19.113 -        if (buffer.hasArray())
  19.114 -            return ((CharBuffer)buffer.compact().flip()).array();
  19.115 -        else
  19.116 -            return buffer.toString().toCharArray();
  19.117 -    }
  19.118 -
  19.119 -    /**
  19.120 -     * The log to be used for error reporting.
  19.121 -     */
  19.122 -    protected Log log;
  19.123 -
  19.124 -    /** Encapsulates knowledge of paths
  19.125 -     */
  19.126 -    private Paths paths;
  19.127 -
  19.128 -    private Options options;
  19.129 -
  19.130 -    private final File uninited = new File("U N I N I T E D");
  19.131 -
  19.132 -    private final Set<JavaFileObject.Kind> sourceOrClass =
  19.133 -        EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS);
  19.134 -
  19.135 -    /** The standard output directory, primarily used for classes.
  19.136 -     *  Initialized by the "-d" option.
  19.137 -     *  If classOutDir = null, files are written into same directory as the sources
  19.138 -     *  they were generated from.
  19.139 -     */
  19.140 -    private File classOutDir = uninited;
  19.141 -
  19.142 -    /** The output directory, used when generating sources while processing annotations.
  19.143 -     *  Initialized by the "-s" option.
  19.144 -     */
  19.145 -    private File sourceOutDir = uninited;
  19.146 -
  19.147 -    protected boolean mmappedIO;
  19.148 -    protected boolean ignoreSymbolFile;
  19.149 -
  19.150 -    /**
  19.151 -     * User provided charset (through javax.tools).
  19.152 -     */
  19.153 -    protected Charset charset;
  19.154 -
  19.155 -    /**
  19.156 -     * Register a Context.Factory to create a JavacFileManager.
  19.157 -     */
  19.158 -    public static void preRegister(final Context context) {
  19.159 -        context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() {
  19.160 -            public JavaFileManager make() {
  19.161 -                return new JavacFileManager(context, true, null);
  19.162 -            }
  19.163 -        });
  19.164 -    }
  19.165 -
  19.166 -    /**
  19.167 -     * Create a JavacFileManager using a given context, optionally registering
  19.168 -     * it as the JavaFileManager for that context.
  19.169 -     */
  19.170 -    public JavacFileManager(Context context, boolean register, Charset charset) {
  19.171 -        if (register)
  19.172 -            context.put(JavaFileManager.class, this);
  19.173 -        byteBufferCache = new ByteBufferCache();
  19.174 -        this.charset = charset;
  19.175 -        setContext(context);
  19.176 -    }
  19.177 -
  19.178 -    /**
  19.179 -     * Set the context for JavacFileManager.
  19.180 -     */
  19.181 -    public void setContext(Context context) {
  19.182 -        log = Log.instance(context);
  19.183 -        if (paths == null) {
  19.184 -            paths = Paths.instance(context);
  19.185 -        } else {
  19.186 -            // Reuse the Paths object as it stores the locations that
  19.187 -            // have been set with setLocation, etc.
  19.188 -            paths.setContext(context);
  19.189 -        }
  19.190 -
  19.191 -        options = Options.instance(context);
  19.192 -
  19.193 -        useZipFileIndex = System.getProperty("useJavaUtilZip") == null;// TODO: options.get("useJavaUtilZip") == null;
  19.194 -        CHECK_ZIP_TIMESTAMP = System.getProperty("checkZipIndexTimestamp") != null;// TODO: options.get("checkZipIndexTimestamp") != null;
  19.195 -
  19.196 -        mmappedIO = options.get("mmappedIO") != null;
  19.197 -        ignoreSymbolFile = options.get("ignore.symbol.file") != null;
  19.198 -    }
  19.199 -
  19.200 -    public JavaFileObject getFileForInput(String name) {
  19.201 -        return getRegularFile(new File(name));
  19.202 -    }
  19.203 -
  19.204 -    public JavaFileObject getRegularFile(File file) {
  19.205 -        return new RegularFileObject(file);
  19.206 -    }
  19.207 -
  19.208 -    public JavaFileObject getFileForOutput(String classname,
  19.209 -                                           JavaFileObject.Kind kind,
  19.210 -                                           JavaFileObject sibling)
  19.211 -        throws IOException
  19.212 -    {
  19.213 -        return getJavaFileForOutput(CLASS_OUTPUT, classname, kind, sibling);
  19.214 -    }
  19.215 -
  19.216 -    public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
  19.217 -        ListBuffer<File> files = new ListBuffer<File>();
  19.218 -        for (String name : names)
  19.219 -            files.append(new File(nullCheck(name)));
  19.220 -        return getJavaFileObjectsFromFiles(files.toList());
  19.221 -    }
  19.222 -
  19.223 -    public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) {
  19.224 -        return getJavaFileObjectsFromStrings(Arrays.asList(nullCheck(names)));
  19.225 -    }
  19.226 -
  19.227 -    protected JavaFileObject.Kind getKind(String extension) {
  19.228 -        if (extension.equals(JavaFileObject.Kind.CLASS.extension))
  19.229 -            return JavaFileObject.Kind.CLASS;
  19.230 -        else if (extension.equals(JavaFileObject.Kind.SOURCE.extension))
  19.231 -            return JavaFileObject.Kind.SOURCE;
  19.232 -        else if (extension.equals(JavaFileObject.Kind.HTML.extension))
  19.233 -            return JavaFileObject.Kind.HTML;
  19.234 -        else
  19.235 -            return JavaFileObject.Kind.OTHER;
  19.236 -    }
  19.237 -
  19.238 -    private static boolean isValidName(String name) {
  19.239 -        // Arguably, isValidName should reject keywords (such as in SourceVersion.isName() ),
  19.240 -        // but the set of keywords depends on the source level, and we don't want
  19.241 -        // impls of JavaFileManager to have to be dependent on the source level.
  19.242 -        // Therefore we simply check that the argument is a sequence of identifiers
  19.243 -        // separated by ".".
  19.244 -        for (String s : name.split("\\.", -1)) {
  19.245 -            if (!SourceVersion.isIdentifier(s))
  19.246 -                return false;
  19.247 -        }
  19.248 -        return true;
  19.249 -    }
  19.250 -
  19.251 -    private static void validateClassName(String className) {
  19.252 -        if (!isValidName(className))
  19.253 -            throw new IllegalArgumentException("Invalid class name: " + className);
  19.254 -    }
  19.255 -
  19.256 -    private static void validatePackageName(String packageName) {
  19.257 -        if (packageName.length() > 0 && !isValidName(packageName))
  19.258 -            throw new IllegalArgumentException("Invalid packageName name: " + packageName);
  19.259 -    }
  19.260 -
  19.261 -    public static void testName(String name,
  19.262 -                                boolean isValidPackageName,
  19.263 -                                boolean isValidClassName)
  19.264 -    {
  19.265 -        try {
  19.266 -            validatePackageName(name);
  19.267 -            if (!isValidPackageName)
  19.268 -                throw new AssertionError("Invalid package name accepted: " + name);
  19.269 -            printAscii("Valid package name: \"%s\"", name);
  19.270 -        } catch (IllegalArgumentException e) {
  19.271 -            if (isValidPackageName)
  19.272 -                throw new AssertionError("Valid package name rejected: " + name);
  19.273 -            printAscii("Invalid package name: \"%s\"", name);
  19.274 -        }
  19.275 -        try {
  19.276 -            validateClassName(name);
  19.277 -            if (!isValidClassName)
  19.278 -                throw new AssertionError("Invalid class name accepted: " + name);
  19.279 -            printAscii("Valid class name: \"%s\"", name);
  19.280 -        } catch (IllegalArgumentException e) {
  19.281 -            if (isValidClassName)
  19.282 -                throw new AssertionError("Valid class name rejected: " + name);
  19.283 -            printAscii("Invalid class name: \"%s\"", name);
  19.284 -        }
  19.285 -    }
  19.286 -    private static void printAscii(String format, Object... args) {
  19.287 -        String message;
  19.288 -        try {
  19.289 -            final String ascii = "US-ASCII";
  19.290 -            message = new String(String.format(null, format, args).getBytes(ascii), ascii);
  19.291 -        } catch (java.io.UnsupportedEncodingException ex) {
  19.292 -            throw new AssertionError(ex);
  19.293 -        }
  19.294 -        System.out.println(message);
  19.295 -    }
  19.296 -
  19.297 -    /** Return external representation of name,
  19.298 -     *  converting '.' to File.separatorChar.
  19.299 -     */
  19.300 -    private static String externalizeFileName(CharSequence name) {
  19.301 -        return name.toString().replace('.', File.separatorChar);
  19.302 -    }
  19.303 -
  19.304 -    private static String externalizeFileName(CharSequence n, JavaFileObject.Kind kind) {
  19.305 -        return externalizeFileName(n) + kind.extension;
  19.306 -    }
  19.307 -
  19.308 -    private static String baseName(String fileName) {
  19.309 -        return fileName.substring(fileName.lastIndexOf(File.separatorChar) + 1);
  19.310 -    }
  19.311 -
  19.312 -    /**
  19.313 -     * Insert all files in subdirectory `subdirectory' of `directory' which end
  19.314 -     * in one of the extensions in `extensions' into packageSym.
  19.315 -     */
  19.316 -    private void listDirectory(File directory,
  19.317 -                               String subdirectory,
  19.318 -                               Set<JavaFileObject.Kind> fileKinds,
  19.319 -                               boolean recurse,
  19.320 -                               ListBuffer<JavaFileObject> l) {
  19.321 -        Archive archive = archives.get(directory);
  19.322 -
  19.323 -        boolean isFile = false;
  19.324 -        if (CHECK_ZIP_TIMESTAMP) {
  19.325 -            Boolean isf = isDirectory.get(directory);
  19.326 -            if (isf == null) {
  19.327 -                isFile = directory.isFile();
  19.328 -                isDirectory.put(directory, isFile);
  19.329 -            }
  19.330 -            else {
  19.331 -                isFile = directory.isFile();
  19.332 -            }
  19.333 -        }
  19.334 -        else {
  19.335 -            isFile = directory.isFile();
  19.336 -        }
  19.337 -
  19.338 -        if (archive != null || isFile) {
  19.339 -            if (archive == null) {
  19.340 -                try {
  19.341 -                    archive = openArchive(directory);
  19.342 -                } catch (IOException ex) {
  19.343 -                    log.error("error.reading.file",
  19.344 -                       directory, ex.getLocalizedMessage());
  19.345 -                    return;
  19.346 -                }
  19.347 -            }
  19.348 -            if (subdirectory.length() != 0) {
  19.349 -                if (!useZipFileIndex) {
  19.350 -                    subdirectory = subdirectory.replace('\\', '/');
  19.351 -                    if (!subdirectory.endsWith("/")) subdirectory = subdirectory + "/";
  19.352 -                }
  19.353 -                else {
  19.354 -                    if (File.separatorChar == '/') {
  19.355 -                        subdirectory = subdirectory.replace('\\', '/');
  19.356 -                    }
  19.357 -                    else {
  19.358 -                        subdirectory = subdirectory.replace('/', '\\');
  19.359 -                    }
  19.360 -
  19.361 -                    if (!subdirectory.endsWith(File.separator)) subdirectory = subdirectory + File.separator;
  19.362 -                }
  19.363 -            }
  19.364 -
  19.365 -            List<String> files = archive.getFiles(subdirectory);
  19.366 -            if (files != null) {
  19.367 -                for (String file; !files.isEmpty(); files = files.tail) {
  19.368 -                    file = files.head;
  19.369 -                    if (isValidFile(file, fileKinds)) {
  19.370 -                        l.append(archive.getFileObject(subdirectory, file));
  19.371 -                    }
  19.372 -                }
  19.373 -            }
  19.374 -            if (recurse) {
  19.375 -                for (String s: archive.getSubdirectories()) {
  19.376 -                    if (s.startsWith(subdirectory) && !s.equals(subdirectory)) {
  19.377 -                        // Because the archive map is a flat list of directories,
  19.378 -                        // the enclosing loop will pick up all child subdirectories.
  19.379 -                        // Therefore, there is no need to recurse deeper.
  19.380 -                        listDirectory(directory, s, fileKinds, false, l);
  19.381 -                    }
  19.382 -                }
  19.383 -            }
  19.384 -        } else {
  19.385 -            File d = subdirectory.length() != 0
  19.386 -                ? new File(directory, subdirectory)
  19.387 -                : directory;
  19.388 -            if (!caseMapCheck(d, subdirectory))
  19.389 -                return;
  19.390 -
  19.391 -            File[] files = d.listFiles();
  19.392 -            if (files == null)
  19.393 -                return;
  19.394 -
  19.395 -            for (File f: files) {
  19.396 -                String fname = f.getName();
  19.397 -                if (f.isDirectory()) {
  19.398 -                    if (recurse && SourceVersion.isIdentifier(fname)) {
  19.399 -                        listDirectory(directory,
  19.400 -                                      subdirectory + File.separator + fname,
  19.401 -                                      fileKinds,
  19.402 -                                      recurse,
  19.403 -                                      l);
  19.404 -                    }
  19.405 -                } else {
  19.406 -                    if (isValidFile(fname, fileKinds)) {
  19.407 -                        JavaFileObject fe =
  19.408 -                        new RegularFileObject(fname, new File(d, fname));
  19.409 -                        l.append(fe);
  19.410 -                    }
  19.411 -                }
  19.412 -            }
  19.413 -        }
  19.414 -    }
  19.415 -
  19.416 -    private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
  19.417 -        int lastDot = s.lastIndexOf(".");
  19.418 -        String extn = (lastDot == -1 ? s : s.substring(lastDot));
  19.419 -        JavaFileObject.Kind kind = getKind(extn);
  19.420 -        return fileKinds.contains(kind);
  19.421 -    }
  19.422 -
  19.423 -    private static final boolean fileSystemIsCaseSensitive =
  19.424 -        File.separatorChar == '/';
  19.425 -
  19.426 -    /** Hack to make Windows case sensitive. Test whether given path
  19.427 -     *  ends in a string of characters with the same case as given name.
  19.428 -     *  Ignore file separators in both path and name.
  19.429 -     */
  19.430 -    private boolean caseMapCheck(File f, String name) {
  19.431 -        if (fileSystemIsCaseSensitive) return true;
  19.432 -        // Note that getCanonicalPath() returns the case-sensitive
  19.433 -        // spelled file name.
  19.434 -        String path;
  19.435 -        try {
  19.436 -            path = f.getCanonicalPath();
  19.437 -        } catch (IOException ex) {
  19.438 -            return false;
  19.439 -        }
  19.440 -        char[] pcs = path.toCharArray();
  19.441 -        char[] ncs = name.toCharArray();
  19.442 -        int i = pcs.length - 1;
  19.443 -        int j = ncs.length - 1;
  19.444 -        while (i >= 0 && j >= 0) {
  19.445 -            while (i >= 0 && pcs[i] == File.separatorChar) i--;
  19.446 -            while (j >= 0 && ncs[j] == File.separatorChar) j--;
  19.447 -            if (i >= 0 && j >= 0) {
  19.448 -                if (pcs[i] != ncs[j]) return false;
  19.449 -                i--;
  19.450 -                j--;
  19.451 -            }
  19.452 -        }
  19.453 -        return j < 0;
  19.454 -    }
  19.455 -
  19.456 -    /**
  19.457 -     * An archive provides a flat directory structure of a ZipFile by
  19.458 -     * mapping directory names to lists of files (basenames).
  19.459 -     */
  19.460 -    public interface Archive {
  19.461 -        void close() throws IOException;
  19.462 -
  19.463 -        boolean contains(String name);
  19.464 -
  19.465 -        JavaFileObject getFileObject(String subdirectory, String file);
  19.466 -
  19.467 -        List<String> getFiles(String subdirectory);
  19.468 -
  19.469 -        Set<String> getSubdirectories();
  19.470 -    }
  19.471 -
  19.472 -    public class ZipArchive implements Archive {
  19.473 -        protected final Map<String,List<String>> map;
  19.474 -        protected final ZipFile zdir;
  19.475 -        public ZipArchive(ZipFile zdir) throws IOException {
  19.476 -            this.zdir = zdir;
  19.477 -            this.map = new HashMap<String,List<String>>();
  19.478 -            for (Enumeration<? extends ZipEntry> e = zdir.entries(); e.hasMoreElements(); ) {
  19.479 -                ZipEntry entry;
  19.480 -                try {
  19.481 -                    entry = e.nextElement();
  19.482 -                } catch (InternalError ex) {
  19.483 -                    IOException io = new IOException();
  19.484 -                    io.initCause(ex); // convenience constructors added in Mustang :-(
  19.485 -                    throw io;
  19.486 -                }
  19.487 -                addZipEntry(entry);
  19.488 -            }
  19.489 -        }
  19.490 -
  19.491 -        void addZipEntry(ZipEntry entry) {
  19.492 -            String name = entry.getName();
  19.493 -            int i = name.lastIndexOf('/');
  19.494 -            String dirname = name.substring(0, i+1);
  19.495 -            String basename = name.substring(i+1);
  19.496 -            if (basename.length() == 0)
  19.497 -                return;
  19.498 -            List<String> list = map.get(dirname);
  19.499 -            if (list == null)
  19.500 -                list = List.nil();
  19.501 -            list = list.prepend(basename);
  19.502 -            map.put(dirname, list);
  19.503 -        }
  19.504 -
  19.505 -        public boolean contains(String name) {
  19.506 -            int i = name.lastIndexOf('/');
  19.507 -            String dirname = name.substring(0, i+1);
  19.508 -            String basename = name.substring(i+1);
  19.509 -            if (basename.length() == 0)
  19.510 -                return false;
  19.511 -            List<String> list = map.get(dirname);
  19.512 -            return (list != null && list.contains(basename));
  19.513 -        }
  19.514 -
  19.515 -        public List<String> getFiles(String subdirectory) {
  19.516 -            return map.get(subdirectory);
  19.517 -        }
  19.518 -
  19.519 -        public JavaFileObject getFileObject(String subdirectory, String file) {
  19.520 -            ZipEntry ze = zdir.getEntry(subdirectory + file);
  19.521 -            return new ZipFileObject(file, zdir, ze);
  19.522 -        }
  19.523 -
  19.524 -        public Set<String> getSubdirectories() {
  19.525 -            return map.keySet();
  19.526 -        }
  19.527 -
  19.528 -        public void close() throws IOException {
  19.529 -            zdir.close();
  19.530 -        }
  19.531 -    }
  19.532 -
  19.533 -    public class SymbolArchive extends ZipArchive {
  19.534 -        final File origFile;
  19.535 -        public SymbolArchive(File orig, ZipFile zdir) throws IOException {
  19.536 -            super(zdir);
  19.537 -            this.origFile = orig;
  19.538 -        }
  19.539 -
  19.540 -        @Override
  19.541 -        void addZipEntry(ZipEntry entry) {
  19.542 -            // called from super constructor, may not refer to origFile.
  19.543 -            String name = entry.getName();
  19.544 -            if (!name.startsWith(symbolFilePrefix))
  19.545 -                return;
  19.546 -            name = name.substring(symbolFilePrefix.length());
  19.547 -            int i = name.lastIndexOf('/');
  19.548 -            String dirname = name.substring(0, i+1);
  19.549 -            String basename = name.substring(i+1);
  19.550 -            if (basename.length() == 0)
  19.551 -                return;
  19.552 -            List<String> list = map.get(dirname);
  19.553 -            if (list == null)
  19.554 -                list = List.nil();
  19.555 -            list = list.prepend(basename);
  19.556 -            map.put(dirname, list);
  19.557 -        }
  19.558 -
  19.559 -        @Override
  19.560 -        public JavaFileObject getFileObject(String subdirectory, String file) {
  19.561 -            return super.getFileObject(symbolFilePrefix + subdirectory, file);
  19.562 -        }
  19.563 -    }
  19.564 -
  19.565 -    public class MissingArchive implements Archive {
  19.566 -        final File zipFileName;
  19.567 -        public MissingArchive(File name) {
  19.568 -            zipFileName = name;
  19.569 -        }
  19.570 -        public boolean contains(String name) {
  19.571 -              return false;
  19.572 -        }
  19.573 -
  19.574 -        public void close() {
  19.575 -        }
  19.576 -
  19.577 -        public JavaFileObject getFileObject(String subdirectory, String file) {
  19.578 -            return null;
  19.579 -        }
  19.580 -
  19.581 -        public List<String> getFiles(String subdirectory) {
  19.582 -            return List.nil();
  19.583 -        }
  19.584 -
  19.585 -        public Set<String> getSubdirectories() {
  19.586 -            return Collections.emptySet();
  19.587 -        }
  19.588 -    }
  19.589 -
  19.590 -    /** A directory of zip files already opened.
  19.591 -     */
  19.592 -    Map<File, Archive> archives = new HashMap<File,Archive>();
  19.593 -
  19.594 -    /** Open a new zip file directory.
  19.595 -     */
  19.596 -    protected Archive openArchive(File zipFileName) throws IOException {
  19.597 -        Archive archive = archives.get(zipFileName);
  19.598 -        if (archive == null) {
  19.599 -            File origZipFileName = zipFileName;
  19.600 -            if (!ignoreSymbolFile && paths.isBootClassPathRtJar(zipFileName)) {
  19.601 -                File file = zipFileName.getParentFile().getParentFile(); // ${java.home}
  19.602 -                if (new File(file.getName()).equals(new File("jre")))
  19.603 -                    file = file.getParentFile();
  19.604 -                // file == ${jdk.home}
  19.605 -                for (String name : symbolFileLocation)
  19.606 -                    file = new File(file, name);
  19.607 -                // file == ${jdk.home}/lib/ct.sym
  19.608 -                if (file.exists())
  19.609 -                    zipFileName = file;
  19.610 -            }
  19.611 -
  19.612 -            try {
  19.613 -
  19.614 -                ZipFile zdir = null;
  19.615 -
  19.616 -                boolean usePreindexedCache = false;
  19.617 -                String preindexCacheLocation = null;
  19.618 -
  19.619 -                if (!useZipFileIndex) {
  19.620 -                    zdir = new ZipFile(zipFileName);
  19.621 -                }
  19.622 -                else {
  19.623 -                    usePreindexedCache = options.get("usezipindex") != null;
  19.624 -                    preindexCacheLocation = options.get("java.io.tmpdir");
  19.625 -                    String optCacheLoc = options.get("cachezipindexdir");
  19.626 -
  19.627 -                    if (optCacheLoc != null && optCacheLoc.length() != 0) {
  19.628 -                        if (optCacheLoc.startsWith("\"")) {
  19.629 -                            if (optCacheLoc.endsWith("\"")) {
  19.630 -                                optCacheLoc = optCacheLoc.substring(1, optCacheLoc.length() - 1);
  19.631 -                            }
  19.632 -                           else {
  19.633 -                                optCacheLoc = optCacheLoc.substring(1);
  19.634 -                            }
  19.635 -                        }
  19.636 -
  19.637 -                        File cacheDir = new File(optCacheLoc);
  19.638 -                        if (cacheDir.exists() && cacheDir.canWrite()) {
  19.639 -                            preindexCacheLocation = optCacheLoc;
  19.640 -                            if (!preindexCacheLocation.endsWith("/") &&
  19.641 -                                !preindexCacheLocation.endsWith(File.separator)) {
  19.642 -                                preindexCacheLocation += File.separator;
  19.643 -                            }
  19.644 -                        }
  19.645 -                    }
  19.646 -                }
  19.647 -
  19.648 -                if (origZipFileName == zipFileName) {
  19.649 -                    if (!useZipFileIndex) {
  19.650 -                        archive = new ZipArchive(zdir);
  19.651 -                    } else {
  19.652 -                        archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, 0,
  19.653 -                                usePreindexedCache, preindexCacheLocation, options.get("writezipindexfiles") != null));
  19.654 -                    }
  19.655 -                }
  19.656 -                else {
  19.657 -                    if (!useZipFileIndex) {
  19.658 -                        archive = new SymbolArchive(origZipFileName, zdir);
  19.659 -                    }
  19.660 -                    else {
  19.661 -                        archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, symbolFilePrefixLength,
  19.662 -                                usePreindexedCache, preindexCacheLocation, options.get("writezipindexfiles") != null));
  19.663 -                    }
  19.664 -                }
  19.665 -            } catch (FileNotFoundException ex) {
  19.666 -                archive = new MissingArchive(zipFileName);
  19.667 -            } catch (IOException ex) {
  19.668 -                log.error("error.reading.file", zipFileName, ex.getLocalizedMessage());
  19.669 -                archive = new MissingArchive(zipFileName);
  19.670 -            }
  19.671 -
  19.672 -            archives.put(origZipFileName, archive);
  19.673 -        }
  19.674 -        return archive;
  19.675 -    }
  19.676 -
  19.677 -    /** Flush any output resources.
  19.678 -     */
  19.679 -    public void flush() {
  19.680 -        contentCache.clear();
  19.681 -    }
  19.682 -
  19.683 -    /**
  19.684 -     * Close the JavaFileManager, releasing resources.
  19.685 -     */
  19.686 -    public void close() {
  19.687 -        for (Iterator<Archive> i = archives.values().iterator(); i.hasNext(); ) {
  19.688 -            Archive a = i.next();
  19.689 -            i.remove();
  19.690 -            try {
  19.691 -                a.close();
  19.692 -            } catch (IOException e) {
  19.693 -            }
  19.694 -        }
  19.695 -    }
  19.696 -
  19.697 -    private Map<JavaFileObject, SoftReference<CharBuffer>> contentCache = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
  19.698 -
  19.699 -    private String defaultEncodingName;
  19.700 -    private String getDefaultEncodingName() {
  19.701 -        if (defaultEncodingName == null) {
  19.702 -            defaultEncodingName =
  19.703 -                new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
  19.704 -        }
  19.705 -        return defaultEncodingName;
  19.706 -    }
  19.707 -
  19.708 -    protected String getEncodingName() {
  19.709 -        String encName = options.get(OptionName.ENCODING);
  19.710 -        if (encName == null)
  19.711 -            return getDefaultEncodingName();
  19.712 -        else
  19.713 -            return encName;
  19.714 -    }
  19.715 -
  19.716 -    protected Source getSource() {
  19.717 -        String sourceName = options.get(OptionName.SOURCE);
  19.718 -        Source source = null;
  19.719 -        if (sourceName != null)
  19.720 -            source = Source.lookup(sourceName);
  19.721 -        return (source != null ? source : Source.DEFAULT);
  19.722 -    }
  19.723 -
  19.724 -    /**
  19.725 -     * Make a byte buffer from an input stream.
  19.726 -     */
  19.727 -    private ByteBuffer makeByteBuffer(InputStream in)
  19.728 -        throws IOException {
  19.729 -        int limit = in.available();
  19.730 -        if (mmappedIO && in instanceof FileInputStream) {
  19.731 -            // Experimental memory mapped I/O
  19.732 -            FileInputStream fin = (FileInputStream)in;
  19.733 -            return fin.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, limit);
  19.734 -        }
  19.735 -        if (limit < 1024) limit = 1024;
  19.736 -        ByteBuffer result = byteBufferCache.get(limit);
  19.737 -        int position = 0;
  19.738 -        while (in.available() != 0) {
  19.739 -            if (position >= limit)
  19.740 -                // expand buffer
  19.741 -                result = ByteBuffer.
  19.742 -                    allocate(limit <<= 1).
  19.743 -                    put((ByteBuffer)result.flip());
  19.744 -            int count = in.read(result.array(),
  19.745 -                position,
  19.746 -                limit - position);
  19.747 -            if (count < 0) break;
  19.748 -            result.position(position += count);
  19.749 -        }
  19.750 -        return (ByteBuffer)result.flip();
  19.751 -    }
  19.752 -
  19.753 -    /**
  19.754 -     * A single-element cache of direct byte buffers.
  19.755 -     */
  19.756 -    private static class ByteBufferCache {
  19.757 -        private ByteBuffer cached;
  19.758 -        ByteBuffer get(int capacity) {
  19.759 -            if (capacity < 20480) capacity = 20480;
  19.760 -            ByteBuffer result =
  19.761 -                (cached != null && cached.capacity() >= capacity)
  19.762 -                ? (ByteBuffer)cached.clear()
  19.763 -                : ByteBuffer.allocate(capacity + capacity>>1);
  19.764 -            cached = null;
  19.765 -            return result;
  19.766 -        }
  19.767 -        void put(ByteBuffer x) {
  19.768 -            cached = x;
  19.769 -        }
  19.770 -    }
  19.771 -    private final ByteBufferCache byteBufferCache;
  19.772 -
  19.773 -    private CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
  19.774 -        Charset charset = (this.charset == null)
  19.775 -            ? Charset.forName(encodingName)
  19.776 -            : this.charset;
  19.777 -        CharsetDecoder decoder = charset.newDecoder();
  19.778 -
  19.779 -        CodingErrorAction action;
  19.780 -        if (ignoreEncodingErrors)
  19.781 -            action = CodingErrorAction.REPLACE;
  19.782 -        else
  19.783 -            action = CodingErrorAction.REPORT;
  19.784 -
  19.785 -        return decoder
  19.786 -            .onMalformedInput(action)
  19.787 -            .onUnmappableCharacter(action);
  19.788 -    }
  19.789 -
  19.790 -    /**
  19.791 -     * Decode a ByteBuffer into a CharBuffer.
  19.792 -     */
  19.793 -    private CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
  19.794 -        String encodingName = getEncodingName();
  19.795 -        CharsetDecoder decoder;
  19.796 -        try {
  19.797 -            decoder = getDecoder(encodingName, ignoreEncodingErrors);
  19.798 -        } catch (IllegalCharsetNameException e) {
  19.799 -            log.error("unsupported.encoding", encodingName);
  19.800 -            return (CharBuffer)CharBuffer.allocate(1).flip();
  19.801 -        } catch (UnsupportedCharsetException e) {
  19.802 -            log.error("unsupported.encoding", encodingName);
  19.803 -            return (CharBuffer)CharBuffer.allocate(1).flip();
  19.804 -        }
  19.805 -
  19.806 -        // slightly overestimate the buffer size to avoid reallocation.
  19.807 -        float factor =
  19.808 -            decoder.averageCharsPerByte() * 0.8f +
  19.809 -            decoder.maxCharsPerByte() * 0.2f;
  19.810 -        CharBuffer dest = CharBuffer.
  19.811 -            allocate(10 + (int)(inbuf.remaining()*factor));
  19.812 -
  19.813 -        while (true) {
  19.814 -            CoderResult result = decoder.decode(inbuf, dest, true);
  19.815 -            dest.flip();
  19.816 -
  19.817 -            if (result.isUnderflow()) { // done reading
  19.818 -                // make sure there is at least one extra character
  19.819 -                if (dest.limit() == dest.capacity()) {
  19.820 -                    dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
  19.821 -                    dest.flip();
  19.822 -                }
  19.823 -                return dest;
  19.824 -            } else if (result.isOverflow()) { // buffer too small; expand
  19.825 -                int newCapacity =
  19.826 -                    10 + dest.capacity() +
  19.827 -                    (int)(inbuf.remaining()*decoder.maxCharsPerByte());
  19.828 -                dest = CharBuffer.allocate(newCapacity).put(dest);
  19.829 -            } else if (result.isMalformed() || result.isUnmappable()) {
  19.830 -                // bad character in input
  19.831 -
  19.832 -                // report coding error (warn only pre 1.5)
  19.833 -                if (!getSource().allowEncodingErrors()) {
  19.834 -                    log.error(new SimpleDiagnosticPosition(dest.limit()),
  19.835 -                              "illegal.char.for.encoding",
  19.836 -                              charset == null ? encodingName : charset.name());
  19.837 -                } else {
  19.838 -                    log.warning(new SimpleDiagnosticPosition(dest.limit()),
  19.839 -                                "illegal.char.for.encoding",
  19.840 -                                charset == null ? encodingName : charset.name());
  19.841 -                }
  19.842 -
  19.843 -                // skip past the coding error
  19.844 -                inbuf.position(inbuf.position() + result.length());
  19.845 -
  19.846 -                // undo the flip() to prepare the output buffer
  19.847 -                // for more translation
  19.848 -                dest.position(dest.limit());
  19.849 -                dest.limit(dest.capacity());
  19.850 -                dest.put((char)0xfffd); // backward compatible
  19.851 -            } else {
  19.852 -                throw new AssertionError(result);
  19.853 -            }
  19.854 -        }
  19.855 -        // unreached
  19.856 -    }
  19.857 -
  19.858 -    public ClassLoader getClassLoader(Location location) {
  19.859 -        nullCheck(location);
  19.860 -        Iterable<? extends File> path = getLocation(location);
  19.861 -        if (path == null)
  19.862 -            return null;
  19.863 -        ListBuffer<URL> lb = new ListBuffer<URL>();
  19.864 -        for (File f: path) {
  19.865 -            try {
  19.866 -                lb.append(f.toURI().toURL());
  19.867 -            } catch (MalformedURLException e) {
  19.868 -                throw new AssertionError(e);
  19.869 -            }
  19.870 -        }
  19.871 -        return new URLClassLoader(lb.toArray(new URL[lb.size()]),
  19.872 -            getClass().getClassLoader());
  19.873 -    }
  19.874 -
  19.875 -    public Iterable<JavaFileObject> list(Location location,
  19.876 -                                         String packageName,
  19.877 -                                         Set<JavaFileObject.Kind> kinds,
  19.878 -                                         boolean recurse)
  19.879 -        throws IOException
  19.880 -    {
  19.881 -        // validatePackageName(packageName);
  19.882 -        nullCheck(packageName);
  19.883 -        nullCheck(kinds);
  19.884 -
  19.885 -        Iterable<? extends File> path = getLocation(location);
  19.886 -        if (path == null)
  19.887 -            return List.nil();
  19.888 -        String subdirectory = externalizeFileName(packageName);
  19.889 -        ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
  19.890 -
  19.891 -        for (File directory : path)
  19.892 -            listDirectory(directory, subdirectory, kinds, recurse, results);
  19.893 -
  19.894 -        return results.toList();
  19.895 -    }
  19.896 -
  19.897 -    public String inferBinaryName(Location location, JavaFileObject file) {
  19.898 -        file.getClass(); // null check
  19.899 -        location.getClass(); // null check
  19.900 -        // Need to match the path semantics of list(location, ...)
  19.901 -        Iterable<? extends File> path = getLocation(location);
  19.902 -        if (path == null) {
  19.903 -            //System.err.println("Path for " + location + " is null");
  19.904 -            return null;
  19.905 -        }
  19.906 -        //System.err.println("Path for " + location + " is " + path);
  19.907 -
  19.908 -        if (file instanceof RegularFileObject) {
  19.909 -            RegularFileObject r = (RegularFileObject) file;
  19.910 -            String rPath = r.getPath();
  19.911 -            //System.err.println("RegularFileObject " + file + " " +r.getPath());
  19.912 -            for (File dir: path) {
  19.913 -                //System.err.println("dir: " + dir);
  19.914 -                String dPath = dir.getPath();
  19.915 -                if (!dPath.endsWith(File.separator))
  19.916 -                    dPath += File.separator;
  19.917 -                if (rPath.regionMatches(true, 0, dPath, 0, dPath.length())
  19.918 -                    && new File(rPath.substring(0, dPath.length())).equals(new File(dPath))) {
  19.919 -                    String relativeName = rPath.substring(dPath.length());
  19.920 -                    return removeExtension(relativeName).replace(File.separatorChar, '.');
  19.921 -                }
  19.922 -            }
  19.923 -        } else if (file instanceof ZipFileObject) {
  19.924 -            ZipFileObject z = (ZipFileObject) file;
  19.925 -            String entryName = z.getZipEntryName();
  19.926 -            if (entryName.startsWith(symbolFilePrefix))
  19.927 -                entryName = entryName.substring(symbolFilePrefix.length());
  19.928 -            return removeExtension(entryName).replace('/', '.');
  19.929 -        } else if (file instanceof ZipFileIndexFileObject) {
  19.930 -            ZipFileIndexFileObject z = (ZipFileIndexFileObject) file;
  19.931 -            String entryName = z.getZipEntryName();
  19.932 -            if (entryName.startsWith(symbolFilePrefix))
  19.933 -                entryName = entryName.substring(symbolFilePrefix.length());
  19.934 -            return removeExtension(entryName).replace(File.separatorChar, '.');
  19.935 -        } else
  19.936 -            throw new IllegalArgumentException(file.getClass().getName());
  19.937 -        // System.err.println("inferBinaryName failed for " + file);
  19.938 -        return null;
  19.939 -    }
  19.940 -    // where
  19.941 -        private static String removeExtension(String fileName) {
  19.942 -            int lastDot = fileName.lastIndexOf(".");
  19.943 -            return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
  19.944 -        }
  19.945 -
  19.946 -    public boolean isSameFile(FileObject a, FileObject b) {
  19.947 -        nullCheck(a);
  19.948 -        nullCheck(b);
  19.949 -        if (!(a instanceof BaseFileObject))
  19.950 -            throw new IllegalArgumentException("Not supported: " + a);
  19.951 -        if (!(b instanceof BaseFileObject))
  19.952 -            throw new IllegalArgumentException("Not supported: " + b);
  19.953 -        return a.equals(b);
  19.954 -    }
  19.955 -
  19.956 -    public boolean handleOption(String current, Iterator<String> remaining) {
  19.957 -        for (JavacOption o: javacFileManagerOptions) {
  19.958 -            if (o.matches(current))  {
  19.959 -                if (o.hasArg()) {
  19.960 -                    if (remaining.hasNext()) {
  19.961 -                        if (!o.process(options, current, remaining.next()))
  19.962 -                            return true;
  19.963 -                    }
  19.964 -                } else {
  19.965 -                    if (!o.process(options, current))
  19.966 -                        return true;
  19.967 -                }
  19.968 -                // operand missing, or process returned false
  19.969 -                throw new IllegalArgumentException(current);
  19.970 -            }
  19.971 -        }
  19.972 -
  19.973 -        return false;
  19.974 -    }
  19.975 -    // where
  19.976 -        private static JavacOption[] javacFileManagerOptions =
  19.977 -            RecognizedOptions.getJavacFileManagerOptions(
  19.978 -            new RecognizedOptions.GrumpyHelper());
  19.979 -
  19.980 -    public int isSupportedOption(String option) {
  19.981 -        for (JavacOption o : javacFileManagerOptions) {
  19.982 -            if (o.matches(option))
  19.983 -                return o.hasArg() ? 1 : 0;
  19.984 -        }
  19.985 -        return -1;
  19.986 -    }
  19.987 -
  19.988 -    public boolean hasLocation(Location location) {
  19.989 -        return getLocation(location) != null;
  19.990 -    }
  19.991 -
  19.992 -    public JavaFileObject getJavaFileForInput(Location location,
  19.993 -                                              String className,
  19.994 -                                              JavaFileObject.Kind kind)
  19.995 -        throws IOException
  19.996 -    {
  19.997 -        nullCheck(location);
  19.998 -        // validateClassName(className);
  19.999 -        nullCheck(className);
 19.1000 -        nullCheck(kind);
 19.1001 -        if (!sourceOrClass.contains(kind))
 19.1002 -            throw new IllegalArgumentException("Invalid kind " + kind);
 19.1003 -        return getFileForInput(location, externalizeFileName(className, kind));
 19.1004 -    }
 19.1005 -
 19.1006 -    public FileObject getFileForInput(Location location,
 19.1007 -                                      String packageName,
 19.1008 -                                      String relativeName)
 19.1009 -        throws IOException
 19.1010 -    {
 19.1011 -        nullCheck(location);
 19.1012 -        // validatePackageName(packageName);
 19.1013 -        nullCheck(packageName);
 19.1014 -        if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
 19.1015 -            throw new IllegalArgumentException("Invalid relative name: " + relativeName);
 19.1016 -        String name = packageName.length() == 0
 19.1017 -            ? relativeName
 19.1018 -            : new File(externalizeFileName(packageName), relativeName).getPath();
 19.1019 -        return getFileForInput(location, name);
 19.1020 -    }
 19.1021 -
 19.1022 -    private JavaFileObject getFileForInput(Location location, String name) throws IOException {
 19.1023 -        Iterable<? extends File> path = getLocation(location);
 19.1024 -        if (path == null)
 19.1025 -            return null;
 19.1026 -
 19.1027 -        for (File dir: path) {
 19.1028 -            if (dir.isDirectory()) {
 19.1029 -                File f = new File(dir, name.replace('/', File.separatorChar));
 19.1030 -                if (f.exists())
 19.1031 -                    return new RegularFileObject(f);
 19.1032 -            } else {
 19.1033 -                Archive a = openArchive(dir);
 19.1034 -                if (a.contains(name)) {
 19.1035 -                    int i = name.lastIndexOf('/');
 19.1036 -                    String dirname = name.substring(0, i+1);
 19.1037 -                    String basename = name.substring(i+1);
 19.1038 -                    return a.getFileObject(dirname, basename);
 19.1039 -                }
 19.1040 -
 19.1041 -            }
 19.1042 -        }
 19.1043 -        return null;
 19.1044 -
 19.1045 -    }
 19.1046 -
 19.1047 -    public JavaFileObject getJavaFileForOutput(Location location,
 19.1048 -                                               String className,
 19.1049 -                                               JavaFileObject.Kind kind,
 19.1050 -                                               FileObject sibling)
 19.1051 -        throws IOException
 19.1052 -    {
 19.1053 -        nullCheck(location);
 19.1054 -        // validateClassName(className);
 19.1055 -        nullCheck(className);
 19.1056 -        nullCheck(kind);
 19.1057 -        if (!sourceOrClass.contains(kind))
 19.1058 -            throw new IllegalArgumentException("Invalid kind " + kind);
 19.1059 -        return getFileForOutput(location, externalizeFileName(className, kind), sibling);
 19.1060 -    }
 19.1061 -
 19.1062 -    public FileObject getFileForOutput(Location location,
 19.1063 -                                       String packageName,
 19.1064 -                                       String relativeName,
 19.1065 -                                       FileObject sibling)
 19.1066 -        throws IOException
 19.1067 -    {
 19.1068 -        nullCheck(location);
 19.1069 -        // validatePackageName(packageName);
 19.1070 -        nullCheck(packageName);
 19.1071 -        if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
 19.1072 -            throw new IllegalArgumentException("relativeName is invalid");
 19.1073 -        String name = packageName.length() == 0
 19.1074 -            ? relativeName
 19.1075 -            : new File(externalizeFileName(packageName), relativeName).getPath();
 19.1076 -        return getFileForOutput(location, name, sibling);
 19.1077 -    }
 19.1078 -
 19.1079 -    private JavaFileObject getFileForOutput(Location location,
 19.1080 -                                            String fileName,
 19.1081 -                                            FileObject sibling)
 19.1082 -        throws IOException
 19.1083 -    {
 19.1084 -        File dir;
 19.1085 -        if (location == CLASS_OUTPUT) {
 19.1086 -            if (getClassOutDir() != null) {
 19.1087 -                dir = getClassOutDir();
 19.1088 -            } else {
 19.1089 -                File siblingDir = null;
 19.1090 -                if (sibling != null && sibling instanceof RegularFileObject) {
 19.1091 -                    siblingDir = ((RegularFileObject)sibling).f.getParentFile();
 19.1092 -                }
 19.1093 -                return new RegularFileObject(new File(siblingDir, baseName(fileName)));
 19.1094 -            }
 19.1095 -        } else if (location == SOURCE_OUTPUT) {
 19.1096 -            dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
 19.1097 -        } else {
 19.1098 -            Iterable<? extends File> path = paths.getPathForLocation(location);
 19.1099 -            dir = null;
 19.1100 -            for (File f: path) {
 19.1101 -                dir = f;
 19.1102 -                break;
 19.1103 -            }
 19.1104 -        }
 19.1105 -
 19.1106 -        File file = (dir == null ? new File(fileName) : new File(dir, fileName));
 19.1107 -        return new RegularFileObject(file);
 19.1108 -
 19.1109 -    }
 19.1110 -
 19.1111 -    public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(
 19.1112 -        Iterable<? extends File> files)
 19.1113 -    {
 19.1114 -        ArrayList<RegularFileObject> result;
 19.1115 -        if (files instanceof Collection)
 19.1116 -            result = new ArrayList<RegularFileObject>(((Collection)files).size());
 19.1117 -        else
 19.1118 -            result = new ArrayList<RegularFileObject>();
 19.1119 -        for (File f: files)
 19.1120 -            result.add(new RegularFileObject(nullCheck(f)));
 19.1121 -        return result;
 19.1122 -    }
 19.1123 -
 19.1124 -    public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
 19.1125 -        return getJavaFileObjectsFromFiles(Arrays.asList(nullCheck(files)));
 19.1126 -    }
 19.1127 -
 19.1128 -    public void setLocation(Location location,
 19.1129 -                            Iterable<? extends File> path)
 19.1130 -        throws IOException
 19.1131 -    {
 19.1132 -        nullCheck(location);
 19.1133 -        paths.lazy();
 19.1134 -
 19.1135 -        final File dir = location.isOutputLocation() ? getOutputDirectory(path) : null;
 19.1136 -
 19.1137 -        if (location == CLASS_OUTPUT)
 19.1138 -            classOutDir = getOutputLocation(dir, D);
 19.1139 -        else if (location == SOURCE_OUTPUT)
 19.1140 -            sourceOutDir = getOutputLocation(dir, S);
 19.1141 -        else
 19.1142 -            paths.setPathForLocation(location, path);
 19.1143 -    }
 19.1144 -    // where
 19.1145 -        private File getOutputDirectory(Iterable<? extends File> path) throws IOException {
 19.1146 -            if (path == null)
 19.1147 -                return null;
 19.1148 -            Iterator<? extends File> pathIter = path.iterator();
 19.1149 -            if (!pathIter.hasNext())
 19.1150 -                throw new IllegalArgumentException("empty path for directory");
 19.1151 -            File dir = pathIter.next();
 19.1152 -            if (pathIter.hasNext())
 19.1153 -                throw new IllegalArgumentException("path too long for directory");
 19.1154 -            if (!dir.exists())
 19.1155 -                throw new FileNotFoundException(dir + ": does not exist");
 19.1156 -            else if (!dir.isDirectory())
 19.1157 -                throw new IOException(dir + ": not a directory");
 19.1158 -            return dir;
 19.1159 -        }
 19.1160 -
 19.1161 -    private File getOutputLocation(File dir, OptionName defaultOptionName) {
 19.1162 -        if (dir != null)
 19.1163 -            return dir;
 19.1164 -        String arg = options.get(defaultOptionName);
 19.1165 -        if (arg == null)
 19.1166 -            return null;
 19.1167 -        return new File(arg);
 19.1168 -    }
 19.1169 -
 19.1170 -    public Iterable<? extends File> getLocation(Location location) {
 19.1171 -        nullCheck(location);
 19.1172 -        paths.lazy();
 19.1173 -        if (location == CLASS_OUTPUT) {
 19.1174 -            return (getClassOutDir() == null ? null : List.of(getClassOutDir()));
 19.1175 -        } else if (location == SOURCE_OUTPUT) {
 19.1176 -            return (getSourceOutDir() == null ? null : List.of(getSourceOutDir()));
 19.1177 -        } else
 19.1178 -            return paths.getPathForLocation(location);
 19.1179 -    }
 19.1180 -
 19.1181 -    private File getClassOutDir() {
 19.1182 -        if (classOutDir == uninited)
 19.1183 -            classOutDir = getOutputLocation(null, D);
 19.1184 -        return classOutDir;
 19.1185 -    }
 19.1186 -
 19.1187 -    private File getSourceOutDir() {
 19.1188 -        if (sourceOutDir == uninited)
 19.1189 -            sourceOutDir = getOutputLocation(null, S);
 19.1190 -        return sourceOutDir;
 19.1191 -    }
 19.1192 -
 19.1193 -    /**
 19.1194 -     * Enforces the specification of a "relative" URI as used in
 19.1195 -     * {@linkplain #getFileForInput(Location,String,URI)
 19.1196 -     * getFileForInput}.  This method must follow the rules defined in
 19.1197 -     * that method, do not make any changes without consulting the
 19.1198 -     * specification.
 19.1199 -     */
 19.1200 -    protected static boolean isRelativeUri(URI uri) {
 19.1201 -        if (uri.isAbsolute())
 19.1202 -            return false;
 19.1203 -        String path = uri.normalize().getPath();
 19.1204 -        if (path.length() == 0 /* isEmpty() is mustang API */)
 19.1205 -            return false;
 19.1206 -        char first = path.charAt(0);
 19.1207 -        return first != '.' && first != '/';
 19.1208 -    }
 19.1209 -
 19.1210 -    /**
 19.1211 -     * Converts a relative file name to a relative URI.  This is
 19.1212 -     * different from File.toURI as this method does not canonicalize
 19.1213 -     * the file before creating the URI.  Furthermore, no schema is
 19.1214 -     * used.
 19.1215 -     * @param file a relative file name
 19.1216 -     * @return a relative URI
 19.1217 -     * @throws IllegalArgumentException if the file name is not
 19.1218 -     * relative according to the definition given in {@link
 19.1219 -     * javax.tools.JavaFileManager#getFileForInput}
 19.1220 -     */
 19.1221 -    public static String getRelativeName(File file) {
 19.1222 -        if (!file.isAbsolute()) {
 19.1223 -            String result = file.getPath().replace(File.separatorChar, '/');
 19.1224 -            if (JavacFileManager.isRelativeUri(URI.create(result))) // FIXME 6419701
 19.1225 -                return result;
 19.1226 -        }
 19.1227 -        throw new IllegalArgumentException("Invalid relative path: " + file);
 19.1228 -    }
 19.1229 -
 19.1230 -    @SuppressWarnings("deprecation") // bug 6410637
 19.1231 -    protected static String getJavacFileName(FileObject file) {
 19.1232 -        if (file instanceof BaseFileObject)
 19.1233 -            return ((BaseFileObject)file).getPath();
 19.1234 -        URI uri = file.toUri();
 19.1235 -        String scheme = uri.getScheme();
 19.1236 -        if (scheme == null || scheme.equals("file") || scheme.equals("jar"))
 19.1237 -            return uri.getPath();
 19.1238 -        else
 19.1239 -            return uri.toString();
 19.1240 -    }
 19.1241 -
 19.1242 -    @SuppressWarnings("deprecation") // bug 6410637
 19.1243 -    protected static String getJavacBaseFileName(FileObject file) {
 19.1244 -        if (file instanceof BaseFileObject)
 19.1245 -            return ((BaseFileObject)file).getName();
 19.1246 -        URI uri = file.toUri();
 19.1247 -        String scheme = uri.getScheme();
 19.1248 -        if (scheme == null || scheme.equals("file") || scheme.equals("jar")) {
 19.1249 -            String path = uri.getPath();
 19.1250 -            if (path == null)
 19.1251 -                return null;
 19.1252 -            if (scheme != null && scheme.equals("jar"))
 19.1253 -                path = path.substring(path.lastIndexOf('!') + 1);
 19.1254 -            return path.substring(path.lastIndexOf('/') + 1);
 19.1255 -        } else {
 19.1256 -            return uri.toString();
 19.1257 -        }
 19.1258 -    }
 19.1259 -
 19.1260 -    private static <T> T nullCheck(T o) {
 19.1261 -        o.getClass(); // null check
 19.1262 -        return o;
 19.1263 -    }
 19.1264 -
 19.1265 -    private static <T> Iterable<T> nullCheck(Iterable<T> it) {
 19.1266 -        for (T t : it)
 19.1267 -            t.getClass(); // null check
 19.1268 -        return it;
 19.1269 -    }
 19.1270 -
 19.1271 -    /**
 19.1272 -     * A subclass of JavaFileObject representing regular files.
 19.1273 -     */
 19.1274 -    private class RegularFileObject extends BaseFileObject {
 19.1275 -        /** Have the parent directories been created?
 19.1276 -         */
 19.1277 -        private boolean hasParents=false;
 19.1278 -
 19.1279 -        /** The file's name.
 19.1280 -         */
 19.1281 -        private String name;
 19.1282 -
 19.1283 -        /** The underlying file.
 19.1284 -         */
 19.1285 -        final File f;
 19.1286 -
 19.1287 -        public RegularFileObject(File f) {
 19.1288 -            this(f.getName(), f);
 19.1289 -        }
 19.1290 -
 19.1291 -        public RegularFileObject(String name, File f) {
 19.1292 -            if (f.isDirectory())
 19.1293 -                throw new IllegalArgumentException("directories not supported");
 19.1294 -            this.name = name;
 19.1295 -            this.f = f;
 19.1296 -        }
 19.1297 -
 19.1298 -        public InputStream openInputStream() throws IOException {
 19.1299 -            return new FileInputStream(f);
 19.1300 -        }
 19.1301 -
 19.1302 -        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
 19.1303 -            return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
 19.1304 -        }
 19.1305 -
 19.1306 -        public OutputStream openOutputStream() throws IOException {
 19.1307 -            ensureParentDirectoriesExist();
 19.1308 -            return new FileOutputStream(f);
 19.1309 -        }
 19.1310 -
 19.1311 -        public Writer openWriter() throws IOException {
 19.1312 -            ensureParentDirectoriesExist();
 19.1313 -            return new OutputStreamWriter(new FileOutputStream(f), getEncodingName());
 19.1314 -        }
 19.1315 -
 19.1316 -        private void ensureParentDirectoriesExist() throws IOException {
 19.1317 -            if (!hasParents) {
 19.1318 -                File parent = f.getParentFile();
 19.1319 -                if (parent != null && !parent.exists()) {
 19.1320 -                    if (!parent.mkdirs()) {
 19.1321 -                        // if the mkdirs failed, it may be because another process concurrently
 19.1322 -                        // created the directory, so check if the directory got created
 19.1323 -                        // anyway before throwing an exception
 19.1324 -                        if (!parent.exists() || !parent.isDirectory())
 19.1325 -                            throw new IOException("could not create parent directories");
 19.1326 -                    }
 19.1327 -                }
 19.1328 -                hasParents = true;
 19.1329 -            }
 19.1330 -        }
 19.1331 -
 19.1332 -        /** @deprecated see bug 6410637 */
 19.1333 -        @Deprecated
 19.1334 -        public String getName() {
 19.1335 -            return name;
 19.1336 -        }
 19.1337 -
 19.1338 -        public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) {
 19.1339 -            cn.getClass(); // null check
 19.1340 -            if (kind == Kind.OTHER && getKind() != kind)
 19.1341 -                return false;
 19.1342 -            String n = cn + kind.extension;
 19.1343 -            if (name.equals(n))
 19.1344 -                return true;
 19.1345 -            if (name.equalsIgnoreCase(n)) {
 19.1346 -                try {
 19.1347 -                    // allow for Windows
 19.1348 -                    return (f.getCanonicalFile().getName().equals(n));
 19.1349 -                } catch (IOException e) {
 19.1350 -                }
 19.1351 -            }
 19.1352 -            return false;
 19.1353 -        }
 19.1354 -
 19.1355 -        /** @deprecated see bug 6410637 */
 19.1356 -        @Deprecated
 19.1357 -        public String getPath() {
 19.1358 -            return f.getPath();
 19.1359 -        }
 19.1360 -
 19.1361 -        public long getLastModified() {
 19.1362 -            return f.lastModified();
 19.1363 -        }
 19.1364 -
 19.1365 -        public boolean delete() {
 19.1366 -            return f.delete();
 19.1367 -        }
 19.1368 -
 19.1369 -        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
 19.1370 -            SoftReference<CharBuffer> r = contentCache.get(this);
 19.1371 -            CharBuffer cb = (r == null ? null : r.get());
 19.1372 -            if (cb == null) {
 19.1373 -                InputStream in = new FileInputStream(f);
 19.1374 -                try {
 19.1375 -                    ByteBuffer bb = makeByteBuffer(in);
 19.1376 -                    JavaFileObject prev = log.useSource(this);
 19.1377 -                    try {
 19.1378 -                        cb = decode(bb, ignoreEncodingErrors);
 19.1379 -                    } finally {
 19.1380 -                        log.useSource(prev);
 19.1381 -                    }
 19.1382 -                    byteBufferCache.put(bb); // save for next time
 19.1383 -                    if (!ignoreEncodingErrors)
 19.1384 -                        contentCache.put(this, new SoftReference<CharBuffer>(cb));
 19.1385 -                } finally {
 19.1386 -                    in.close();
 19.1387 -                }
 19.1388 -            }
 19.1389 -            return cb;
 19.1390 -        }
 19.1391 -
 19.1392 -        @Override
 19.1393 -        public boolean equals(Object other) {
 19.1394 -            if (!(other instanceof RegularFileObject))
 19.1395 -                return false;
 19.1396 -            RegularFileObject o = (RegularFileObject) other;
 19.1397 -            try {
 19.1398 -                return f.equals(o.f)
 19.1399 -                    || f.getCanonicalFile().equals(o.f.getCanonicalFile());
 19.1400 -            } catch (IOException e) {
 19.1401 -                return false;
 19.1402 -            }
 19.1403 -        }
 19.1404 -
 19.1405 -        @Override
 19.1406 -        public int hashCode() {
 19.1407 -            return f.hashCode();
 19.1408 -        }
 19.1409 -
 19.1410 -        public URI toUri() {
 19.1411 -            try {
 19.1412 -                // Do no use File.toURI to avoid file system access
 19.1413 -                String path = f.getAbsolutePath().replace(File.separatorChar, '/');
 19.1414 -                return new URI("file://" + path).normalize();
 19.1415 -            } catch (URISyntaxException ex) {
 19.1416 -                return f.toURI();
 19.1417 -            }
 19.1418 -        }
 19.1419 -
 19.1420 -    }
 19.1421 -
 19.1422 -    /**
 19.1423 -     * A subclass of JavaFileObject representing zip entries.
 19.1424 -     */
 19.1425 -    public class ZipFileObject extends BaseFileObject {
 19.1426 -
 19.1427 -        /** The entry's name.
 19.1428 -         */
 19.1429 -        private String name;
 19.1430 -
 19.1431 -        /** The zipfile containing the entry.
 19.1432 -         */
 19.1433 -        ZipFile zdir;
 19.1434 -
 19.1435 -        /** The underlying zip entry object.
 19.1436 -         */
 19.1437 -        ZipEntry entry;
 19.1438 -
 19.1439 -        public ZipFileObject(String name, ZipFile zdir, ZipEntry entry) {
 19.1440 -            this.name = name;
 19.1441 -            this.zdir = zdir;
 19.1442 -            this.entry = entry;
 19.1443 -        }
 19.1444 -
 19.1445 -        public InputStream openInputStream() throws IOException {
 19.1446 -            return zdir.getInputStream(entry);
 19.1447 -        }
 19.1448 -
 19.1449 -        public OutputStream openOutputStream() throws IOException {
 19.1450 -            throw new UnsupportedOperationException();
 19.1451 -        }
 19.1452 -
 19.1453 -        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
 19.1454 -            return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
 19.1455 -        }
 19.1456 -
 19.1457 -        public Writer openWriter() throws IOException {
 19.1458 -            throw new UnsupportedOperationException();
 19.1459 -        }
 19.1460 -
 19.1461 -        /** @deprecated see bug 6410637 */
 19.1462 -        @Deprecated
 19.1463 -        public String getName() {
 19.1464 -            return name;
 19.1465 -        }
 19.1466 -
 19.1467 -        public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
 19.1468 -            cn.getClass(); // null check
 19.1469 -            if (k == Kind.OTHER && getKind() != k)
 19.1470 -                return false;
 19.1471 -            return name.equals(cn + k.extension);
 19.1472 -        }
 19.1473 -
 19.1474 -        /** @deprecated see bug 6410637 */
 19.1475 -        @Deprecated
 19.1476 -        public String getPath() {
 19.1477 -            return zdir.getName() + "(" + entry + ")";
 19.1478 -        }
 19.1479 -
 19.1480 -        public long getLastModified() {
 19.1481 -            return entry.getTime();
 19.1482 -        }
 19.1483 -
 19.1484 -        public boolean delete() {
 19.1485 -            throw new UnsupportedOperationException();
 19.1486 -        }
 19.1487 -
 19.1488 -        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
 19.1489 -            SoftReference<CharBuffer> r = contentCache.get(this);
 19.1490 -            CharBuffer cb = (r == null ? null : r.get());
 19.1491 -            if (cb == null) {
 19.1492 -                InputStream in = zdir.getInputStream(entry);
 19.1493 -                try {
 19.1494 -                    ByteBuffer bb = makeByteBuffer(in);
 19.1495 -                    JavaFileObject prev = log.useSource(this);
 19.1496 -                    try {
 19.1497 -                        cb = decode(bb, ignoreEncodingErrors);
 19.1498 -                    } finally {
 19.1499 -                        log.useSource(prev);
 19.1500 -                    }
 19.1501 -                    byteBufferCache.put(bb); // save for next time
 19.1502 -                    if (!ignoreEncodingErrors)
 19.1503 -                        contentCache.put(this, new SoftReference<CharBuffer>(cb));
 19.1504 -                } finally {
 19.1505 -                    in.close();
 19.1506 -                }
 19.1507 -            }
 19.1508 -            return cb;
 19.1509 -        }
 19.1510 -
 19.1511 -        @Override
 19.1512 -        public boolean equals(Object other) {
 19.1513 -            if (!(other instanceof ZipFileObject))
 19.1514 -                return false;
 19.1515 -            ZipFileObject o = (ZipFileObject) other;
 19.1516 -            return zdir.equals(o.zdir) || name.equals(o.name);
 19.1517 -        }
 19.1518 -
 19.1519 -        @Override
 19.1520 -        public int hashCode() {
 19.1521 -            return zdir.hashCode() + name.hashCode();
 19.1522 -        }
 19.1523 -
 19.1524 -        public String getZipName() {
 19.1525 -            return zdir.getName();
 19.1526 -        }
 19.1527 -
 19.1528 -        public String getZipEntryName() {
 19.1529 -            return entry.getName();
 19.1530 -        }
 19.1531 -
 19.1532 -        public URI toUri() {
 19.1533 -            String zipName = new File(getZipName()).toURI().normalize().getPath();
 19.1534 -            String entryName = getZipEntryName();
 19.1535 -            return URI.create("jar:" + zipName + "!" + entryName);
 19.1536 -        }
 19.1537 -
 19.1538 -    }
 19.1539 -
 19.1540 -    /**
 19.1541 -     * A subclass of JavaFileObject representing zip entries using the com.sun.tools.javac.zip.ZipFileIndex implementation.
 19.1542 -     */
 19.1543 -    public class ZipFileIndexFileObject extends BaseFileObject {
 19.1544 -
 19.1545 -            /** The entry's name.
 19.1546 -         */
 19.1547 -        private String name;
 19.1548 -
 19.1549 -        /** The zipfile containing the entry.
 19.1550 -         */
 19.1551 -        ZipFileIndex zfIndex;
 19.1552 -
 19.1553 -        /** The underlying zip entry object.
 19.1554 -         */
 19.1555 -        ZipFileIndexEntry entry;
 19.1556 -
 19.1557 -        /** The InputStream for this zip entry (file.)
 19.1558 -         */
 19.1559 -        InputStream inputStream = null;
 19.1560 -
 19.1561 -        /** The name of the zip file where this entry resides.
 19.1562 -         */
 19.1563 -        String zipName;
 19.1564 -
 19.1565 -        JavacFileManager defFileManager = null;
 19.1566 -
 19.1567 -        public ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndexEntry entry, String zipFileName) {
 19.1568 -            super();
 19.1569 -            this.name = entry.getFileName();
 19.1570 -            this.zfIndex = zfIndex;
 19.1571 -            this.entry = entry;
 19.1572 -            this.zipName = zipFileName;
 19.1573 -            defFileManager = fileManager;
 19.1574 -        }
 19.1575 -
 19.1576 -        public InputStream openInputStream() throws IOException {
 19.1577 -
 19.1578 -            if (inputStream == null) {
 19.1579 -                inputStream = new ByteArrayInputStream(read());
 19.1580 -            }
 19.1581 -            return inputStream;
 19.1582 -        }
 19.1583 -
 19.1584 -        protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
 19.1585 -            return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
 19.1586 -        }
 19.1587 -
 19.1588 -        public OutputStream openOutputStream() throws IOException {
 19.1589 -            throw new UnsupportedOperationException();
 19.1590 -        }
 19.1591 -
 19.1592 -        public Writer openWriter() throws IOException {
 19.1593 -            throw new UnsupportedOperationException();
 19.1594 -        }
 19.1595 -
 19.1596 -        /** @deprecated see bug 6410637 */
 19.1597 -        @Deprecated
 19.1598 -        public String getName() {
 19.1599 -            return name;
 19.1600 -        }
 19.1601 -
 19.1602 -        public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
 19.1603 -            cn.getClass(); // null check
 19.1604 -            if (k == Kind.OTHER && getKind() != k)
 19.1605 -                return false;
 19.1606 -            return name.equals(cn + k.extension);
 19.1607 -        }
 19.1608 -
 19.1609 -        /** @deprecated see bug 6410637 */
 19.1610 -        @Deprecated
 19.1611 -        public String getPath() {
 19.1612 -            return zipName + "(" + entry.getName() + ")";
 19.1613 -        }
 19.1614 -
 19.1615 -        public long getLastModified() {
 19.1616 -            return entry.getLastModified();
 19.1617 -        }
 19.1618 -
 19.1619 -        public boolean delete() {
 19.1620 -            throw new UnsupportedOperationException();
 19.1621 -        }
 19.1622 -
 19.1623 -        @Override
 19.1624 -        public boolean equals(Object other) {
 19.1625 -            if (!(other instanceof ZipFileIndexFileObject))
 19.1626 -                return false;
 19.1627 -            ZipFileIndexFileObject o = (ZipFileIndexFileObject) other;
 19.1628 -            return entry.equals(o.entry);
 19.1629 -        }
 19.1630 -
 19.1631 -        @Override
 19.1632 -        public int hashCode() {
 19.1633 -            return zipName.hashCode() + (name.hashCode() << 10);
 19.1634 -        }
 19.1635 -
 19.1636 -        public String getZipName() {
 19.1637 -            return zipName;
 19.1638 -        }
 19.1639 -
 19.1640 -        public String getZipEntryName() {
 19.1641 -            return entry.getName();
 19.1642 -        }
 19.1643 -
 19.1644 -        public URI toUri() {
 19.1645 -            String zipName = new File(getZipName()).toURI().normalize().getPath();
 19.1646 -            String entryName = getZipEntryName();
 19.1647 -            if (File.separatorChar != '/') {
 19.1648 -                entryName = entryName.replace(File.separatorChar, '/');
 19.1649 -            }
 19.1650 -            return URI.create("jar:" + zipName + "!" + entryName);
 19.1651 -        }
 19.1652 -
 19.1653 -        private byte[] read() throws IOException {
 19.1654 -            if (entry == null) {
 19.1655 -                entry = zfIndex.getZipIndexEntry(name);
 19.1656 -                if (entry == null)
 19.1657 -                  throw new FileNotFoundException();
 19.1658 -            }
 19.1659 -            return zfIndex.read(entry);
 19.1660 -        }
 19.1661 -
 19.1662 -        public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
 19.1663 -            SoftReference<CharBuffer> r = defFileManager.contentCache.get(this);
 19.1664 -            CharBuffer cb = (r == null ? null : r.get());
 19.1665 -            if (cb == null) {
 19.1666 -                InputStream in = new ByteArrayInputStream(zfIndex.read(entry));
 19.1667 -                try {
 19.1668 -                    ByteBuffer bb = makeByteBuffer(in);
 19.1669 -                    JavaFileObject prev = log.useSource(this);
 19.1670 -                    try {
 19.1671 -                        cb = decode(bb, ignoreEncodingErrors);
 19.1672 -                    } finally {
 19.1673 -                        log.useSource(prev);
 19.1674 -                    }
 19.1675 -                    byteBufferCache.put(bb); // save for next time
 19.1676 -                    if (!ignoreEncodingErrors)
 19.1677 -                        defFileManager.contentCache.put(this, new SoftReference<CharBuffer>(cb));
 19.1678 -                } finally {
 19.1679 -                    in.close();
 19.1680 -                }
 19.1681 -            }
 19.1682 -            return cb;
 19.1683 -        }
 19.1684 -    }
 19.1685 -
 19.1686 -    public class ZipFileIndexArchive implements Archive {
 19.1687 -        private final ZipFileIndex zfIndex;
 19.1688 -        private JavacFileManager fileManager;
 19.1689 -
 19.1690 -        public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException {
 19.1691 -            this.fileManager = fileManager;
 19.1692 -            this.zfIndex = zdir;
 19.1693 -        }
 19.1694 -
 19.1695 -        public boolean contains(String name) {
 19.1696 -            return zfIndex.contains(name);
 19.1697 -        }
 19.1698 -
 19.1699 -        public com.sun.tools.javac.util.List<String> getFiles(String subdirectory) {
 19.1700 -              return zfIndex.getFiles(((subdirectory.endsWith("/") || subdirectory.endsWith("\\"))? subdirectory.substring(0, subdirectory.length() - 1) : subdirectory));
 19.1701 -        }
 19.1702 -
 19.1703 -        public JavaFileObject getFileObject(String subdirectory, String file) {
 19.1704 -            String fullZipFileName = subdirectory + file;
 19.1705 -            ZipFileIndexEntry entry = zfIndex.getZipIndexEntry(fullZipFileName);
 19.1706 -            JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile().getPath());
 19.1707 -            return ret;
 19.1708 -        }
 19.1709 -
 19.1710 -        public Set<String> getSubdirectories() {
 19.1711 -            return zfIndex.getAllDirectories();
 19.1712 -        }
 19.1713 -
 19.1714 -        public void close() throws IOException {
 19.1715 -            zfIndex.close();
 19.1716 -        }
 19.1717 -    }
 19.1718 -}
    20.1 --- a/src/share/classes/com/sun/tools/javac/util/Log.java	Fri Jun 06 15:17:35 2008 -0700
    20.2 +++ b/src/share/classes/com/sun/tools/javac/util/Log.java	Mon Jun 16 13:28:00 2008 -0700
    20.3 @@ -33,11 +33,14 @@
    20.4  import java.util.Set;
    20.5  import javax.tools.DiagnosticListener;
    20.6  import javax.tools.JavaFileObject;
    20.7 +
    20.8  import com.sun.tools.javac.code.Source;
    20.9 +import com.sun.tools.javac.file.JavacFileManager;
   20.10  import com.sun.tools.javac.tree.JCTree;
   20.11  import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
   20.12  import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
   20.13  import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
   20.14 +
   20.15  import static com.sun.tools.javac.util.LayoutCharacters.*;
   20.16  
   20.17  /** A class for error logs. Reports errors and warnings, and
    21.1 --- a/src/share/classes/com/sun/tools/javac/util/Old199.java	Fri Jun 06 15:17:35 2008 -0700
    21.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.3 @@ -1,60 +0,0 @@
    21.4 -/*
    21.5 - * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
    21.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    21.7 - *
    21.8 - * This code is free software; you can redistribute it and/or modify it
    21.9 - * under the terms of the GNU General Public License version 2 only, as
   21.10 - * published by the Free Software Foundation.  Sun designates this
   21.11 - * particular file as subject to the "Classpath" exception as provided
   21.12 - * by Sun in the LICENSE file that accompanied this code.
   21.13 - *
   21.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
   21.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   21.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   21.17 - * version 2 for more details (a copy is included in the LICENSE file that
   21.18 - * accompanied this code).
   21.19 - *
   21.20 - * You should have received a copy of the GNU General Public License version
   21.21 - * 2 along with this work; if not, write to the Free Software Foundation,
   21.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   21.23 - *
   21.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   21.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
   21.26 - * have any questions.
   21.27 - */
   21.28 -
   21.29 -package com.sun.tools.javac.util;
   21.30 -
   21.31 -import java.io.File;
   21.32 -import java.io.IOException;
   21.33 -import java.net.URI;
   21.34 -import java.net.URISyntaxException;
   21.35 -import javax.tools.*;
   21.36 -
   21.37 -import static javax.tools.StandardLocation.SOURCE_PATH;
   21.38 -
   21.39 -/**
   21.40 - * Provides an easy migration to JSR 199 v3.3.  The class is
   21.41 - * deprecated as we should remove it as soon as possible.
   21.42 - *
   21.43 - * <p><b>This is NOT part of any API supported by Sun Microsystems.
   21.44 - * If you write code that depends on this, you do so at your own
   21.45 - * risk.  This code and its internal interfaces are subject to change
   21.46 - * or deletion without notice.</b></p>
   21.47 - *
   21.48 - * @author Peter von der Ah\u00e9
   21.49 - */
   21.50 -@Deprecated
   21.51 -public class Old199 {
   21.52 -
   21.53 -    private Old199() {}
   21.54 -
   21.55 -    public static String getPath(FileObject jfo) {
   21.56 -        return JavacFileManager.getJavacFileName(jfo);
   21.57 -    }
   21.58 -
   21.59 -    public static String getName(FileObject jfo) {
   21.60 -        return JavacFileManager.getJavacBaseFileName(jfo);
   21.61 -    }
   21.62 -
   21.63 -}
    22.1 --- a/src/share/classes/com/sun/tools/javac/util/Paths.java	Fri Jun 06 15:17:35 2008 -0700
    22.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3 @@ -1,572 +0,0 @@
    22.4 -/*
    22.5 - * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
    22.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    22.7 - *
    22.8 - * This code is free software; you can redistribute it and/or modify it
    22.9 - * under the terms of the GNU General Public License version 2 only, as
   22.10 - * published by the Free Software Foundation.  Sun designates this
   22.11 - * particular file as subject to the "Classpath" exception as provided
   22.12 - * by Sun in the LICENSE file that accompanied this code.
   22.13 - *
   22.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
   22.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   22.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   22.17 - * version 2 for more details (a copy is included in the LICENSE file that
   22.18 - * accompanied this code).
   22.19 - *
   22.20 - * You should have received a copy of the GNU General Public License version
   22.21 - * 2 along with this work; if not, write to the Free Software Foundation,
   22.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   22.23 - *
   22.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
   22.26 - * have any questions.
   22.27 - */
   22.28 -
   22.29 -package com.sun.tools.javac.util;
   22.30 -import java.io.File;
   22.31 -import java.io.IOException;
   22.32 -import java.util.HashMap;
   22.33 -import java.util.HashSet;
   22.34 -import java.util.Map;
   22.35 -import java.util.Set;
   22.36 -import java.util.jar.JarFile;
   22.37 -import java.util.jar.Manifest;
   22.38 -import java.util.jar.Attributes;
   22.39 -import java.util.Collection;
   22.40 -import java.util.Collections;
   22.41 -import java.util.LinkedHashSet;
   22.42 -import java.util.Iterator;
   22.43 -import java.util.StringTokenizer;
   22.44 -import java.util.zip.ZipFile;
   22.45 -import com.sun.tools.javac.code.Lint;
   22.46 -import java.util.ArrayList;
   22.47 -import java.util.concurrent.ConcurrentHashMap;
   22.48 -import java.util.concurrent.locks.Lock;
   22.49 -import java.util.concurrent.locks.ReentrantLock;
   22.50 -import javax.tools.JavaFileManager.Location;
   22.51 -
   22.52 -import static com.sun.tools.javac.main.OptionName.*;
   22.53 -import static javax.tools.StandardLocation.*;
   22.54 -
   22.55 -/** This class converts command line arguments, environment variables
   22.56 - *  and system properties (in File.pathSeparator-separated String form)
   22.57 - *  into a boot class path, user class path, and source path (in
   22.58 - *  Collection<String> form).
   22.59 - *
   22.60 - *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
   22.61 - *  you write code that depends on this, you do so at your own risk.
   22.62 - *  This code and its internal interfaces are subject to change or
   22.63 - *  deletion without notice.</b>
   22.64 - */
   22.65 -public class Paths {
   22.66 -
   22.67 -    /** The context key for the todo list */
   22.68 -    protected static final Context.Key<Paths> pathsKey =
   22.69 -        new Context.Key<Paths>();
   22.70 -
   22.71 -    /** Get the Paths instance for this context.
   22.72 -     *  @param context the context
   22.73 -     *  @return the Paths instance for this context
   22.74 -     */
   22.75 -    public static Paths instance(Context context) {
   22.76 -        Paths instance = context.get(pathsKey);
   22.77 -        if (instance == null)
   22.78 -            instance = new Paths(context);
   22.79 -        return instance;
   22.80 -    }
   22.81 -
   22.82 -    /** The log to use for warning output */
   22.83 -    private Log log;
   22.84 -
   22.85 -    /** Collection of command-line options */
   22.86 -    private Options options;
   22.87 -
   22.88 -    /** Handler for -Xlint options */
   22.89 -    private Lint lint;
   22.90 -
   22.91 -    private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
   22.92 -    private static Map<File, PathEntry> pathExistanceCache = new ConcurrentHashMap<File, PathEntry>();
   22.93 -    private static Map<File, java.util.List<File>> manifestEntries = new ConcurrentHashMap<File, java.util.List<File>>();
   22.94 -    private static Map<File, Boolean> isDirectory = new ConcurrentHashMap<File, Boolean>();
   22.95 -    private static Lock lock = new ReentrantLock();
   22.96 -
   22.97 -    public static void clearPathExistanceCache() {
   22.98 -            pathExistanceCache.clear();
   22.99 -    }
  22.100 -
  22.101 -    static class PathEntry {
  22.102 -        boolean exists = false;
  22.103 -        boolean isFile = false;
  22.104 -        File cannonicalPath = null;
  22.105 -    }
  22.106 -
  22.107 -    protected Paths(Context context) {
  22.108 -        context.put(pathsKey, this);
  22.109 -        pathsForLocation = new HashMap<Location,Path>(16);
  22.110 -        setContext(context);
  22.111 -    }
  22.112 -
  22.113 -    void setContext(Context context) {
  22.114 -        log = Log.instance(context);
  22.115 -        options = Options.instance(context);
  22.116 -        lint = Lint.instance(context);
  22.117 -    }
  22.118 -
  22.119 -    /** Whether to warn about non-existent path elements */
  22.120 -    private boolean warn;
  22.121 -
  22.122 -    private Map<Location, Path> pathsForLocation;
  22.123 -
  22.124 -    private boolean inited = false; // TODO? caching bad?
  22.125 -
  22.126 -    /**
  22.127 -     * rt.jar as found on the default bootclass path.  If the user specified a
  22.128 -     * bootclasspath, null is used.
  22.129 -     */
  22.130 -    private File bootClassPathRtJar = null;
  22.131 -
  22.132 -    Path getPathForLocation(Location location) {
  22.133 -        Path path = pathsForLocation.get(location);
  22.134 -        if (path == null)
  22.135 -            setPathForLocation(location, null);
  22.136 -        return pathsForLocation.get(location);
  22.137 -    }
  22.138 -
  22.139 -    void setPathForLocation(Location location, Iterable<? extends File> path) {
  22.140 -        // TODO? if (inited) throw new IllegalStateException
  22.141 -        // TODO: otherwise reset sourceSearchPath, classSearchPath as needed
  22.142 -        Path p;
  22.143 -        if (path == null) {
  22.144 -            if (location == CLASS_PATH)
  22.145 -                p = computeUserClassPath();
  22.146 -            else if (location == PLATFORM_CLASS_PATH)
  22.147 -                p = computeBootClassPath();
  22.148 -            else if (location == ANNOTATION_PROCESSOR_PATH)
  22.149 -                p = computeAnnotationProcessorPath();
  22.150 -            else if (location == SOURCE_PATH)
  22.151 -                p = computeSourcePath();
  22.152 -            else
  22.153 -                // no defaults for other paths
  22.154 -                p = null;
  22.155 -        } else {
  22.156 -            p = new Path();
  22.157 -            for (File f: path)
  22.158 -                p.addFile(f, warn); // TODO: is use of warn appropriate?
  22.159 -        }
  22.160 -        pathsForLocation.put(location, p);
  22.161 -    }
  22.162 -
  22.163 -    protected void lazy() {
  22.164 -        if (!inited) {
  22.165 -            warn = lint.isEnabled(Lint.LintCategory.PATH);
  22.166 -
  22.167 -            pathsForLocation.put(PLATFORM_CLASS_PATH, computeBootClassPath());
  22.168 -            pathsForLocation.put(CLASS_PATH, computeUserClassPath());
  22.169 -            pathsForLocation.put(SOURCE_PATH, computeSourcePath());
  22.170 -
  22.171 -            inited = true;
  22.172 -        }
  22.173 -    }
  22.174 -
  22.175 -    public Collection<File> bootClassPath() {
  22.176 -        lazy();
  22.177 -        return Collections.unmodifiableCollection(getPathForLocation(PLATFORM_CLASS_PATH));
  22.178 -    }
  22.179 -    public Collection<File> userClassPath() {
  22.180 -        lazy();
  22.181 -        return Collections.unmodifiableCollection(getPathForLocation(CLASS_PATH));
  22.182 -    }
  22.183 -    public Collection<File> sourcePath() {
  22.184 -        lazy();
  22.185 -        Path p = getPathForLocation(SOURCE_PATH);
  22.186 -        return p == null || p.size() == 0
  22.187 -            ? null
  22.188 -            : Collections.unmodifiableCollection(p);
  22.189 -    }
  22.190 -
  22.191 -    boolean isBootClassPathRtJar(File file) {
  22.192 -        return file.equals(bootClassPathRtJar);
  22.193 -    }
  22.194 -
  22.195 -    private static class PathIterator implements Iterable<String> {
  22.196 -        private int pos = 0;
  22.197 -        private final String path;
  22.198 -        private final String emptyPathDefault;
  22.199 -
  22.200 -        public PathIterator(String path, String emptyPathDefault) {
  22.201 -            this.path = path;
  22.202 -            this.emptyPathDefault = emptyPathDefault;
  22.203 -        }
  22.204 -        public PathIterator(String path) { this(path, null); }
  22.205 -        public Iterator<String> iterator() {
  22.206 -            return new Iterator<String>() {
  22.207 -                public boolean hasNext() {
  22.208 -                    return pos <= path.length();
  22.209 -                }
  22.210 -                public String next() {
  22.211 -                    int beg = pos;
  22.212 -                    int end = path.indexOf(File.pathSeparator, beg);
  22.213 -                    if (end == -1)
  22.214 -                        end = path.length();
  22.215 -                    pos = end + 1;
  22.216 -
  22.217 -                    if (beg == end && emptyPathDefault != null)
  22.218 -                        return emptyPathDefault;
  22.219 -                    else
  22.220 -                        return path.substring(beg, end);
  22.221 -                }
  22.222 -                public void remove() {
  22.223 -                    throw new UnsupportedOperationException();
  22.224 -                }
  22.225 -            };
  22.226 -        }
  22.227 -    }
  22.228 -
  22.229 -    private class Path extends LinkedHashSet<File> {
  22.230 -        private static final long serialVersionUID = 0;
  22.231 -
  22.232 -        private boolean expandJarClassPaths = false;
  22.233 -        private Set<File> canonicalValues = new HashSet<File>();
  22.234 -
  22.235 -        public Path expandJarClassPaths(boolean x) {
  22.236 -            expandJarClassPaths = x;
  22.237 -            return this;
  22.238 -        }
  22.239 -
  22.240 -        /** What to use when path element is the empty string */
  22.241 -        private String emptyPathDefault = null;
  22.242 -
  22.243 -        public Path emptyPathDefault(String x) {
  22.244 -            emptyPathDefault = x;
  22.245 -            return this;
  22.246 -        }
  22.247 -
  22.248 -        public Path() { super(); }
  22.249 -
  22.250 -        public Path addDirectories(String dirs, boolean warn) {
  22.251 -            if (dirs != null)
  22.252 -                for (String dir : new PathIterator(dirs))
  22.253 -                    addDirectory(dir, warn);
  22.254 -            return this;
  22.255 -        }
  22.256 -
  22.257 -        public Path addDirectories(String dirs) {
  22.258 -            return addDirectories(dirs, warn);
  22.259 -        }
  22.260 -
  22.261 -        private void addDirectory(String dir, boolean warn) {
  22.262 -            if (! new File(dir).isDirectory()) {
  22.263 -                if (warn)
  22.264 -                    log.warning("dir.path.element.not.found", dir);
  22.265 -                return;
  22.266 -            }
  22.267 -
  22.268 -            File[] files = new File(dir).listFiles();
  22.269 -            if (files == null)
  22.270 -                return;
  22.271 -
  22.272 -            for (File direntry : files) {
  22.273 -                if (isArchive(direntry))
  22.274 -                    addFile(direntry, warn);
  22.275 -            }
  22.276 -        }
  22.277 -
  22.278 -        public Path addFiles(String files, boolean warn) {
  22.279 -            if (files != null)
  22.280 -                for (String file : new PathIterator(files, emptyPathDefault))
  22.281 -                    addFile(file, warn);
  22.282 -            return this;
  22.283 -        }
  22.284 -
  22.285 -        public Path addFiles(String files) {
  22.286 -            return addFiles(files, warn);
  22.287 -        }
  22.288 -
  22.289 -        public Path addFile(String file, boolean warn) {
  22.290 -            addFile(new File(file), warn);
  22.291 -            return this;
  22.292 -        }
  22.293 -
  22.294 -        public void addFile(File file, boolean warn) {
  22.295 -            boolean foundInCache = false;
  22.296 -            PathEntry pe = null;
  22.297 -            if (!NON_BATCH_MODE) {
  22.298 -                    pe = pathExistanceCache.get(file);
  22.299 -                    if (pe != null) {
  22.300 -                        foundInCache = true;
  22.301 -                    }
  22.302 -                    else {
  22.303 -                        pe = new PathEntry();
  22.304 -                    }
  22.305 -            }
  22.306 -            else {
  22.307 -                pe = new PathEntry();
  22.308 -            }
  22.309 -
  22.310 -            File canonFile;
  22.311 -            try {
  22.312 -                if (!foundInCache) {
  22.313 -                    pe.cannonicalPath = file.getCanonicalFile();
  22.314 -                }
  22.315 -                else {
  22.316 -                   canonFile = pe.cannonicalPath;
  22.317 -                }
  22.318 -            } catch (IOException e) {
  22.319 -                pe.cannonicalPath = canonFile = file;
  22.320 -            }
  22.321 -
  22.322 -            if (contains(file) || canonicalValues.contains(pe.cannonicalPath)) {
  22.323 -                /* Discard duplicates and avoid infinite recursion */
  22.324 -                return;
  22.325 -            }
  22.326 -
  22.327 -            if (!foundInCache) {
  22.328 -                pe.exists = file.exists();
  22.329 -                pe.isFile = file.isFile();
  22.330 -                if (!NON_BATCH_MODE) {
  22.331 -                    pathExistanceCache.put(file, pe);
  22.332 -                }
  22.333 -            }
  22.334 -
  22.335 -            if (! pe.exists) {
  22.336 -                /* No such file or directory exists */
  22.337 -                if (warn)
  22.338 -                    log.warning("path.element.not.found", file);
  22.339 -            } else if (pe.isFile) {
  22.340 -                /* File is an ordinary file. */
  22.341 -                if (!isArchive(file)) {
  22.342 -                    /* Not a recognized extension; open it to see if
  22.343 -                     it looks like a valid zip file. */
  22.344 -                    try {
  22.345 -                        ZipFile z = new ZipFile(file);
  22.346 -                        z.close();
  22.347 -                        if (warn)
  22.348 -                            log.warning("unexpected.archive.file", file);
  22.349 -                    } catch (IOException e) {
  22.350 -                        // FIXME: include e.getLocalizedMessage in warning
  22.351 -                        if (warn)
  22.352 -                            log.warning("invalid.archive.file", file);
  22.353 -                        return;
  22.354 -                    }
  22.355 -                }
  22.356 -            }
  22.357 -
  22.358 -            /* Now what we have left is either a directory or a file name
  22.359 -               confirming to archive naming convention */
  22.360 -            super.add(file);
  22.361 -            canonicalValues.add(pe.cannonicalPath);
  22.362 -
  22.363 -            if (expandJarClassPaths && file.exists() && file.isFile())
  22.364 -                addJarClassPath(file, warn);
  22.365 -        }
  22.366 -
  22.367 -        // Adds referenced classpath elements from a jar's Class-Path
  22.368 -        // Manifest entry.  In some future release, we may want to
  22.369 -        // update this code to recognize URLs rather than simple
  22.370 -        // filenames, but if we do, we should redo all path-related code.
  22.371 -        private void addJarClassPath(File jarFile, boolean warn) {
  22.372 -            try {
  22.373 -                java.util.List<File> manifestsList = manifestEntries.get(jarFile);
  22.374 -                if (!NON_BATCH_MODE) {
  22.375 -                    lock.lock();
  22.376 -                    try {
  22.377 -                        if (manifestsList != null) {
  22.378 -                            for (File entr : manifestsList) {
  22.379 -                                addFile(entr, warn);
  22.380 -                            }
  22.381 -                            return;
  22.382 -                        }
  22.383 -                    }
  22.384 -                    finally {
  22.385 -                        lock.unlock();
  22.386 -                    }
  22.387 -                }
  22.388 -
  22.389 -                if (!NON_BATCH_MODE) {
  22.390 -                    manifestsList = new ArrayList<File>();
  22.391 -                    manifestEntries.put(jarFile, manifestsList);
  22.392 -                }
  22.393 -
  22.394 -                String jarParent = jarFile.getParent();
  22.395 -                JarFile jar = new JarFile(jarFile);
  22.396 -
  22.397 -                try {
  22.398 -                    Manifest man = jar.getManifest();
  22.399 -                    if (man == null) return;
  22.400 -
  22.401 -                    Attributes attr = man.getMainAttributes();
  22.402 -                    if (attr == null) return;
  22.403 -
  22.404 -                    String path = attr.getValue(Attributes.Name.CLASS_PATH);
  22.405 -                    if (path == null) return;
  22.406 -
  22.407 -                    for (StringTokenizer st = new StringTokenizer(path);
  22.408 -                         st.hasMoreTokens();) {
  22.409 -                        String elt = st.nextToken();
  22.410 -                        File f = (jarParent == null ? new File(elt) : new File(jarParent, elt));
  22.411 -                        addFile(f, warn);
  22.412 -
  22.413 -                        if (!NON_BATCH_MODE) {
  22.414 -                            lock.lock();
  22.415 -                            try {
  22.416 -                                manifestsList.add(f);
  22.417 -                            }
  22.418 -                            finally {
  22.419 -                                lock.unlock();
  22.420 -                            }
  22.421 -                        }
  22.422 -                    }
  22.423 -                } finally {
  22.424 -                    jar.close();
  22.425 -                }
  22.426 -            } catch (IOException e) {
  22.427 -                log.error("error.reading.file", jarFile, e.getLocalizedMessage());
  22.428 -            }
  22.429 -        }
  22.430 -    }
  22.431 -
  22.432 -    private Path computeBootClassPath() {
  22.433 -        bootClassPathRtJar = null;
  22.434 -        String optionValue;
  22.435 -        Path path = new Path();
  22.436 -
  22.437 -        path.addFiles(options.get(XBOOTCLASSPATH_PREPEND));
  22.438 -
  22.439 -        if ((optionValue = options.get(ENDORSEDDIRS)) != null)
  22.440 -            path.addDirectories(optionValue);
  22.441 -        else
  22.442 -            path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
  22.443 -
  22.444 -        if ((optionValue = options.get(BOOTCLASSPATH)) != null) {
  22.445 -            path.addFiles(optionValue);
  22.446 -        } else {
  22.447 -            // Standard system classes for this compiler's release.
  22.448 -            String files = System.getProperty("sun.boot.class.path");
  22.449 -            path.addFiles(files, false);
  22.450 -            File rt_jar = new File("rt.jar");
  22.451 -            for (String file : new PathIterator(files, null)) {
  22.452 -                File f = new File(file);
  22.453 -                if (new File(f.getName()).equals(rt_jar))
  22.454 -                    bootClassPathRtJar = f;
  22.455 -            }
  22.456 -        }
  22.457 -
  22.458 -        path.addFiles(options.get(XBOOTCLASSPATH_APPEND));
  22.459 -
  22.460 -        // Strictly speaking, standard extensions are not bootstrap
  22.461 -        // classes, but we treat them identically, so we'll pretend
  22.462 -        // that they are.
  22.463 -        if ((optionValue = options.get(EXTDIRS)) != null)
  22.464 -            path.addDirectories(optionValue);
  22.465 -        else
  22.466 -            path.addDirectories(System.getProperty("java.ext.dirs"), false);
  22.467 -
  22.468 -        return path;
  22.469 -    }
  22.470 -
  22.471 -    private Path computeUserClassPath() {
  22.472 -        String cp = options.get(CLASSPATH);
  22.473 -
  22.474 -        // CLASSPATH environment variable when run from `javac'.
  22.475 -        if (cp == null) cp = System.getProperty("env.class.path");
  22.476 -
  22.477 -        // If invoked via a java VM (not the javac launcher), use the
  22.478 -        // platform class path
  22.479 -        if (cp == null && System.getProperty("application.home") == null)
  22.480 -            cp = System.getProperty("java.class.path");
  22.481 -
  22.482 -        // Default to current working directory.
  22.483 -        if (cp == null) cp = ".";
  22.484 -
  22.485 -        return new Path()
  22.486 -            .expandJarClassPaths(true) // Only search user jars for Class-Paths
  22.487 -            .emptyPathDefault(".")     // Empty path elt ==> current directory
  22.488 -            .addFiles(cp);
  22.489 -    }
  22.490 -
  22.491 -    private Path computeSourcePath() {
  22.492 -        String sourcePathArg = options.get(SOURCEPATH);
  22.493 -        if (sourcePathArg == null)
  22.494 -            return null;
  22.495 -
  22.496 -        return new Path().addFiles(sourcePathArg);
  22.497 -    }
  22.498 -
  22.499 -    private Path computeAnnotationProcessorPath() {
  22.500 -        String processorPathArg = options.get(PROCESSORPATH);
  22.501 -        if (processorPathArg == null)
  22.502 -            return null;
  22.503 -
  22.504 -        return new Path().addFiles(processorPathArg);
  22.505 -    }
  22.506 -
  22.507 -    /** The actual effective locations searched for sources */
  22.508 -    private Path sourceSearchPath;
  22.509 -
  22.510 -    public Collection<File> sourceSearchPath() {
  22.511 -        if (sourceSearchPath == null) {
  22.512 -            lazy();
  22.513 -            Path sourcePath = getPathForLocation(SOURCE_PATH);
  22.514 -            Path userClassPath = getPathForLocation(CLASS_PATH);
  22.515 -            sourceSearchPath = sourcePath != null ? sourcePath : userClassPath;
  22.516 -        }
  22.517 -        return Collections.unmodifiableCollection(sourceSearchPath);
  22.518 -    }
  22.519 -
  22.520 -    /** The actual effective locations searched for classes */
  22.521 -    private Path classSearchPath;
  22.522 -
  22.523 -    public Collection<File> classSearchPath() {
  22.524 -        if (classSearchPath == null) {
  22.525 -            lazy();
  22.526 -            Path bootClassPath = getPathForLocation(PLATFORM_CLASS_PATH);
  22.527 -            Path userClassPath = getPathForLocation(CLASS_PATH);
  22.528 -            classSearchPath = new Path();
  22.529 -            classSearchPath.addAll(bootClassPath);
  22.530 -            classSearchPath.addAll(userClassPath);
  22.531 -        }
  22.532 -        return Collections.unmodifiableCollection(classSearchPath);
  22.533 -    }
  22.534 -
  22.535 -    /** The actual effective locations for non-source, non-class files */
  22.536 -    private Path otherSearchPath;
  22.537 -
  22.538 -    Collection<File> otherSearchPath() {
  22.539 -        if (otherSearchPath == null) {
  22.540 -            lazy();
  22.541 -            Path userClassPath = getPathForLocation(CLASS_PATH);
  22.542 -            Path sourcePath = getPathForLocation(SOURCE_PATH);
  22.543 -            if (sourcePath == null)
  22.544 -                otherSearchPath = userClassPath;
  22.545 -            else {
  22.546 -                otherSearchPath = new Path();
  22.547 -                otherSearchPath.addAll(userClassPath);
  22.548 -                otherSearchPath.addAll(sourcePath);
  22.549 -            }
  22.550 -        }
  22.551 -        return Collections.unmodifiableCollection(otherSearchPath);
  22.552 -    }
  22.553 -
  22.554 -    /** Is this the name of an archive file? */
  22.555 -    private static boolean isArchive(File file) {
  22.556 -        String n = file.getName().toLowerCase();
  22.557 -        boolean isFile = false;
  22.558 -        if (!NON_BATCH_MODE) {
  22.559 -            Boolean isf = isDirectory.get(file);
  22.560 -            if (isf == null) {
  22.561 -                isFile = file.isFile();
  22.562 -                isDirectory.put(file, isFile);
  22.563 -            }
  22.564 -            else {
  22.565 -                isFile = isf;
  22.566 -            }
  22.567 -        }
  22.568 -        else {
  22.569 -            isFile = file.isFile();
  22.570 -        }
  22.571 -
  22.572 -        return isFile
  22.573 -            && (n.endsWith(".jar") || n.endsWith(".zip"));
  22.574 -    }
  22.575 -}
    23.1 --- a/src/share/classes/com/sun/tools/javac/zip/ZipFileIndex.java	Fri Jun 06 15:17:35 2008 -0700
    23.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.3 @@ -1,1236 +0,0 @@
    23.4 -/*
    23.5 - * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
    23.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    23.7 - *
    23.8 - * This code is free software; you can redistribute it and/or modify it
    23.9 - * under the terms of the GNU General Public License version 2 only, as
   23.10 - * published by the Free Software Foundation.  Sun designates this
   23.11 - * particular file as subject to the "Classpath" exception as provided
   23.12 - * by Sun in the LICENSE file that accompanied this code.
   23.13 - *
   23.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
   23.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   23.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   23.17 - * version 2 for more details (a copy is included in the LICENSE file that
   23.18 - * accompanied this code).
   23.19 - *
   23.20 - * You should have received a copy of the GNU General Public License version
   23.21 - * 2 along with this work; if not, write to the Free Software Foundation,
   23.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   23.23 - *
   23.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   23.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
   23.26 - * have any questions.
   23.27 - */
   23.28 -
   23.29 -package com.sun.tools.javac.zip;
   23.30 -
   23.31 -import java.io.*;
   23.32 -import java.text.MessageFormat;
   23.33 -import java.util.*;
   23.34 -import java.util.List;
   23.35 -import java.util.concurrent.locks.ReentrantLock;
   23.36 -import java.util.zip.*;
   23.37 -
   23.38 -/** This class implements building of index of a zip archive and access to it's context.
   23.39 - *  It also uses prebuild index if available. It supports invocations where it will
   23.40 - *  serialize an optimized zip index file to disk.
   23.41 - *
   23.42 - *  In oreder to use secondary index file make sure the option "usezipindex" is in the Options object,
   23.43 - *  when JavacFileManager is invoked. (You can pass "-XDusezipindex" on the command line.
   23.44 - *
   23.45 - *  Location where to look for/generate optimized zip index files can be provided using
   23.46 - *  "-XDcachezipindexdir=<directory>". If this flag is not provided, the dfault location is
   23.47 - *  the value of the "java.io.tmpdir" system property.
   23.48 - *
   23.49 - *  If key "-XDwritezipindexfiles" is specified, there will be new optimized index file
   23.50 - *  created for each archive, used by the compiler for compilation, at location,
   23.51 - *  specified by "cachezipindexdir" option.
   23.52 - *
   23.53 - * If nonBatchMode option is specified (-XDnonBatchMode) the compiler will use timestamp
   23.54 - * checking to reindex the zip files if it is needed. In batch mode the timestamps are not checked
   23.55 - * and the compiler uses the cached indexes.
   23.56 - */
   23.57 -public class ZipFileIndex {
   23.58 -    private static final String MIN_CHAR = String.valueOf(Character.MIN_VALUE);
   23.59 -    private static final String MAX_CHAR = String.valueOf(Character.MAX_VALUE);
   23.60 -
   23.61 -    public final static long NOT_MODIFIED = Long.MIN_VALUE;
   23.62 -
   23.63 -    private static Map<File, ZipFileIndex> zipFileIndexCache = new HashMap<File, ZipFileIndex>();
   23.64 -    private static ReentrantLock lock = new ReentrantLock();
   23.65 -
   23.66 -    private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
   23.67 -
   23.68 -    private Map<String, DirectoryEntry> directories = Collections.<String, DirectoryEntry>emptyMap();
   23.69 -    private Set<String> allDirs = Collections.<String>emptySet();
   23.70 -
   23.71 -    // ZipFileIndex data entries
   23.72 -    private File zipFile;
   23.73 -    private long zipFileLastModified = NOT_MODIFIED;
   23.74 -    private RandomAccessFile zipRandomFile;
   23.75 -    private ZipFileIndexEntry[] entries;
   23.76 -
   23.77 -    private boolean readFromIndex = false;
   23.78 -    private File zipIndexFile = null;
   23.79 -    private boolean triedToReadIndex = false;
   23.80 -    private int symbolFilePrefixLength = 0;
   23.81 -    private boolean hasPopulatedData = false;
   23.82 -    private long lastReferenceTimeStamp = NOT_MODIFIED;
   23.83 -
   23.84 -    private boolean usePreindexedCache = false;
   23.85 -    private String preindexedCacheLocation = null;
   23.86 -
   23.87 -    private boolean writeIndex = false;
   23.88 -
   23.89 -    /**
   23.90 -     * Returns a list of all ZipFileIndex entries
   23.91 -     *
   23.92 -     * @return A list of ZipFileIndex entries, or an empty list
   23.93 -     */
   23.94 -    public static List<ZipFileIndex> getZipFileIndexes() {
   23.95 -        return getZipFileIndexes(false);
   23.96 -    }
   23.97 -
   23.98 -    /**
   23.99 -     * Returns a list of all ZipFileIndex entries
  23.100 -     *
  23.101 -     * @param openedOnly If true it returns a list of only opened ZipFileIndex entries, otherwise
  23.102 -     *                   all ZipFileEntry(s) are included into the list.
  23.103 -     * @return A list of ZipFileIndex entries, or an empty list
  23.104 -     */
  23.105 -    public static List<ZipFileIndex> getZipFileIndexes(boolean openedOnly) {
  23.106 -        List<ZipFileIndex> zipFileIndexes = new ArrayList<ZipFileIndex>();
  23.107 -        lock.lock();
  23.108 -        try {
  23.109 -            zipFileIndexes.addAll(zipFileIndexCache.values());
  23.110 -
  23.111 -            if (openedOnly) {
  23.112 -                for(ZipFileIndex elem : zipFileIndexes) {
  23.113 -                    if (!elem.isOpen()) {
  23.114 -                        zipFileIndexes.remove(elem);
  23.115 -                    }
  23.116 -                }
  23.117 -            }
  23.118 -        }
  23.119 -        finally {
  23.120 -            lock.unlock();
  23.121 -        }
  23.122 -        return zipFileIndexes;
  23.123 -    }
  23.124 -
  23.125 -    public boolean isOpen() {
  23.126 -        lock.lock();
  23.127 -        try {
  23.128 -            return zipRandomFile != null;
  23.129 -        }
  23.130 -        finally {
  23.131 -            lock.unlock();
  23.132 -        }
  23.133 -    }
  23.134 -
  23.135 -    public static ZipFileIndex getZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean useCache, String cacheLocation, boolean writeIndex) throws IOException {
  23.136 -        ZipFileIndex zi = null;
  23.137 -        lock.lock();
  23.138 -        try {
  23.139 -            zi = getExistingZipIndex(zipFile);
  23.140 -
  23.141 -            if (zi == null || (zi != null && zipFile.lastModified() != zi.zipFileLastModified)) {
  23.142 -                zi = new ZipFileIndex(zipFile, symbolFilePrefixLen, writeIndex,
  23.143 -                        useCache, cacheLocation);
  23.144 -                zipFileIndexCache.put(zipFile, zi);
  23.145 -            }
  23.146 -        }
  23.147 -        finally {
  23.148 -            lock.unlock();
  23.149 -        }
  23.150 -        return zi;
  23.151 -    }
  23.152 -
  23.153 -    public static ZipFileIndex getExistingZipIndex(File zipFile) {
  23.154 -        lock.lock();
  23.155 -        try {
  23.156 -            return zipFileIndexCache.get(zipFile);
  23.157 -        }
  23.158 -        finally {
  23.159 -            lock.unlock();
  23.160 -        }
  23.161 -    }
  23.162 -
  23.163 -    public static void clearCache() {
  23.164 -        lock.lock();
  23.165 -        try {
  23.166 -            zipFileIndexCache.clear();
  23.167 -        }
  23.168 -        finally {
  23.169 -            lock.unlock();
  23.170 -        }
  23.171 -    }
  23.172 -
  23.173 -    public static void clearCache(long timeNotUsed) {
  23.174 -        lock.lock();
  23.175 -        try {
  23.176 -            Iterator<File> cachedFileIterator = zipFileIndexCache.keySet().iterator();
  23.177 -            while (cachedFileIterator.hasNext()) {
  23.178 -                File cachedFile = cachedFileIterator.next();
  23.179 -                ZipFileIndex cachedZipIndex = zipFileIndexCache.get(cachedFile);
  23.180 -                if (cachedZipIndex != null) {
  23.181 -                    long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed;
  23.182 -                    if (timeToTest < cachedZipIndex.lastReferenceTimeStamp || // Overflow...
  23.183 -                            System.currentTimeMillis() > timeToTest) {
  23.184 -                        zipFileIndexCache.remove(cachedFile);
  23.185 -                    }
  23.186 -                }
  23.187 -            }
  23.188 -        }
  23.189 -        finally {
  23.190 -            lock.unlock();
  23.191 -        }
  23.192 -    }
  23.193 -
  23.194 -    public static void removeFromCache(File file) {
  23.195 -        lock.lock();
  23.196 -        try {
  23.197 -            zipFileIndexCache.remove(file);
  23.198 -        }
  23.199 -        finally {
  23.200 -            lock.unlock();
  23.201 -        }
  23.202 -    }
  23.203 -
  23.204 -    /** Sets already opened list of ZipFileIndexes from an outside client
  23.205 -      * of the compiler. This functionality should be used in a non-batch clients of the compiler.
  23.206 -      */
  23.207 -    public static void setOpenedIndexes(List<ZipFileIndex>indexes) throws IllegalStateException {
  23.208 -        lock.lock();
  23.209 -        try {
  23.210 -            if (zipFileIndexCache.isEmpty()) {
  23.211 -                throw new IllegalStateException("Setting opened indexes should be called only when the ZipFileCache is empty. Call JavacFileManager.flush() before calling this method.");
  23.212 -            }
  23.213 -
  23.214 -            for (ZipFileIndex zfi : indexes) {
  23.215 -                zipFileIndexCache.put(zfi.zipFile, zfi);
  23.216 -            }
  23.217 -        }
  23.218 -        finally {
  23.219 -            lock.unlock();
  23.220 -        }
  23.221 -    }
  23.222 -
  23.223 -    private ZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean writeIndex,
  23.224 -            boolean useCache, String cacheLocation) throws IOException {
  23.225 -        this.zipFile = zipFile;
  23.226 -        this.symbolFilePrefixLength = symbolFilePrefixLen;
  23.227 -        this.writeIndex = writeIndex;
  23.228 -        this.usePreindexedCache = useCache;
  23.229 -        this.preindexedCacheLocation = cacheLocation;
  23.230 -
  23.231 -        if (zipFile != null) {
  23.232 -            this.zipFileLastModified = zipFile.lastModified();
  23.233 -        }
  23.234 -
  23.235 -        // Validate integrity of the zip file
  23.236 -        checkIndex();
  23.237 -    }
  23.238 -
  23.239 -    public String toString() {
  23.240 -        return "ZipFileIndex of file:(" + zipFile + ")";
  23.241 -    }
  23.242 -
  23.243 -    // Just in case...
  23.244 -    protected void finalize() {
  23.245 -        closeFile();
  23.246 -    }
  23.247 -
  23.248 -    private boolean isUpToDate() {
  23.249 -        if (zipFile != null &&
  23.250 -                ((!NON_BATCH_MODE) || zipFileLastModified == zipFile.lastModified()) &&
  23.251 -                hasPopulatedData) {
  23.252 -            return true;
  23.253 -        }
  23.254 -
  23.255 -        return false;
  23.256 -    }
  23.257 -
  23.258 -    /**
  23.259 -     * Here we need to make sure that the ZipFileIndex is valid. Check the timestamp of the file and
  23.260 -     * if its the same as the one at the time the index was build we don't need to reopen anything.
  23.261 -     */
  23.262 -    private void checkIndex() throws IOException {
  23.263 -        boolean isUpToDate = true;
  23.264 -        if (!isUpToDate()) {
  23.265 -            closeFile();
  23.266 -            isUpToDate = false;
  23.267 -        }
  23.268 -
  23.269 -        if (zipRandomFile != null || isUpToDate) {
  23.270 -            lastReferenceTimeStamp = System.currentTimeMillis();
  23.271 -            return;
  23.272 -        }
  23.273 -
  23.274 -        hasPopulatedData = true;
  23.275 -
  23.276 -        if (readIndex()) {
  23.277 -            lastReferenceTimeStamp = System.currentTimeMillis();
  23.278 -            return;
  23.279 -        }
  23.280 -
  23.281 -        directories = Collections.<String, DirectoryEntry>emptyMap();
  23.282 -        allDirs = Collections.<String>emptySet();
  23.283 -
  23.284 -        try {
  23.285 -            openFile();
  23.286 -            long totalLength = zipRandomFile.length();
  23.287 -            ZipDirectory directory = new ZipDirectory(zipRandomFile, 0L, totalLength, this);
  23.288 -            directory.buildIndex();
  23.289 -        } finally {
  23.290 -            if (zipRandomFile != null) {
  23.291 -                closeFile();
  23.292 -            }
  23.293 -        }
  23.294 -
  23.295 -        lastReferenceTimeStamp = System.currentTimeMillis();
  23.296 -    }
  23.297 -
  23.298 -    private void openFile() throws FileNotFoundException {
  23.299 -        if (zipRandomFile == null && zipFile != null) {
  23.300 -            zipRandomFile = new RandomAccessFile(zipFile, "r");
  23.301 -        }
  23.302 -    }
  23.303 -
  23.304 -    private void cleanupState() {
  23.305 -        // Make sure there is a valid but empty index if the file doesn't exist
  23.306 -        entries = ZipFileIndexEntry.EMPTY_ARRAY;
  23.307 -        directories = Collections.<String, DirectoryEntry>emptyMap();
  23.308 -        zipFileLastModified = NOT_MODIFIED;
  23.309 -        allDirs = Collections.<String>emptySet();
  23.310 -    }
  23.311 -
  23.312 -    public void close() {
  23.313 -        lock.lock();
  23.314 -        try {
  23.315 -            writeIndex();
  23.316 -            closeFile();
  23.317 -        }
  23.318 -        finally {
  23.319 -            lock.unlock();
  23.320 -        }
  23.321 -    }
  23.322 -
  23.323 -    private void closeFile() {
  23.324 -        if (zipRandomFile != null) {
  23.325 -            try {
  23.326 -                zipRandomFile.close();
  23.327 -            } catch (IOException ex) {
  23.328 -            }
  23.329 -            zipRandomFile = null;
  23.330 -        }
  23.331 -    }
  23.332 -
  23.333 -    /**
  23.334 -     * Returns the ZipFileIndexEntry for an absolute path, if there is one.
  23.335 -     */
  23.336 -    public ZipFileIndexEntry getZipIndexEntry(String path) {
  23.337 -        if (File.separatorChar != '/') {
  23.338 -            path = path.replace('/', File.separatorChar);
  23.339 -        }
  23.340 -        lock.lock();
  23.341 -        try {
  23.342 -            checkIndex();
  23.343 -            String lookFor = "";
  23.344 -            int lastSepIndex = path.lastIndexOf(File.separatorChar);
  23.345 -            boolean noSeparator = false;
  23.346 -            if (lastSepIndex == -1) {
  23.347 -                noSeparator = true;
  23.348 -            }
  23.349 -
  23.350 -            DirectoryEntry de = directories.get(noSeparator ? "" : path.substring(0, lastSepIndex));
  23.351 -
  23.352 -            lookFor = path.substring(noSeparator ? 0 : lastSepIndex + 1);
  23.353 -
  23.354 -            return de == null ? null : de.getEntry(lookFor);
  23.355 -        }
  23.356 -        catch (IOException e) {
  23.357 -            return null;
  23.358 -        }
  23.359 -        finally {
  23.360 -            lock.unlock();
  23.361 -        }
  23.362 -    }
  23.363 -
  23.364 -    /**
  23.365 -     * Returns a javac List of filenames within an absolute path in the ZipFileIndex.
  23.366 -     */
  23.367 -    public com.sun.tools.javac.util.List<String> getFiles(String path) {
  23.368 -        if (File.separatorChar != '/') {
  23.369 -            path = path.replace('/', File.separatorChar);
  23.370 -        }
  23.371 -
  23.372 -        lock.lock();
  23.373 -        try {
  23.374 -            checkIndex();
  23.375 -
  23.376 -            DirectoryEntry de = directories.get(path);
  23.377 -            com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getFiles();
  23.378 -
  23.379 -            if (ret == null) {
  23.380 -                return com.sun.tools.javac.util.List.<String>nil();
  23.381 -            }
  23.382 -            return ret;
  23.383 -        }
  23.384 -        catch (IOException e) {
  23.385 -            return com.sun.tools.javac.util.List.<String>nil();
  23.386 -        }
  23.387 -        finally {
  23.388 -            lock.unlock();
  23.389 -        }
  23.390 -    }
  23.391 -
  23.392 -    public List<String> getAllDirectories(String path) {
  23.393 -
  23.394 -        if (File.separatorChar != '/') {
  23.395 -            path = path.replace('/', File.separatorChar);
  23.396 -        }
  23.397 -
  23.398 -        lock.lock();
  23.399 -        try {
  23.400 -            checkIndex();
  23.401 -            path = path.intern();
  23.402 -
  23.403 -            DirectoryEntry de = directories.get(path);
  23.404 -            com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getDirectories();
  23.405 -
  23.406 -            if (ret == null) {
  23.407 -                return com.sun.tools.javac.util.List.<String>nil();
  23.408 -            }
  23.409 -
  23.410 -            return ret;
  23.411 -        }
  23.412 -        catch (IOException e) {
  23.413 -            return com.sun.tools.javac.util.List.<String>nil();
  23.414 -        }
  23.415 -        finally {
  23.416 -            lock.unlock();
  23.417 -        }
  23.418 -    }
  23.419 -
  23.420 -    public Set<String> getAllDirectories() {
  23.421 -        lock.lock();
  23.422 -        try {
  23.423 -            checkIndex();
  23.424 -            if (allDirs == Collections.EMPTY_SET) {
  23.425 -                Set<String> alldirs = new HashSet<String>();
  23.426 -                Iterator<String> dirsIter = directories.keySet().iterator();
  23.427 -                while (dirsIter.hasNext()) {
  23.428 -                    alldirs.add(new String(dirsIter.next()));
  23.429 -                }
  23.430 -
  23.431 -                allDirs = alldirs;
  23.432 -            }
  23.433 -
  23.434 -            return allDirs;
  23.435 -        }
  23.436 -        catch (IOException e) {
  23.437 -            return Collections.<String>emptySet();
  23.438 -        }
  23.439 -        finally {
  23.440 -            lock.unlock();
  23.441 -        }
  23.442 -    }
  23.443 -
  23.444 -    /**
  23.445 -     * Tests if a specific path exists in the zip.  This method will return true
  23.446 -     * for file entries and directories.
  23.447 -     *
  23.448 -     * @param path A path within the zip.
  23.449 -     * @return True if the path is a file or dir, false otherwise.
  23.450 -     */
  23.451 -    public boolean contains(String path) {
  23.452 -        lock.lock();
  23.453 -        try {
  23.454 -            checkIndex();
  23.455 -            return getZipIndexEntry(path) != null;
  23.456 -        }
  23.457 -        catch (IOException e) {
  23.458 -            return false;
  23.459 -        }
  23.460 -        finally {
  23.461 -            lock.unlock();
  23.462 -        }
  23.463 -    }
  23.464 -
  23.465 -    public boolean isDirectory(String path) throws IOException {
  23.466 -        lock.lock();
  23.467 -        try {
  23.468 -            // The top level in a zip file is always a directory.
  23.469 -            if (path.length() == 0) {
  23.470 -                lastReferenceTimeStamp = System.currentTimeMillis();
  23.471 -                return true;
  23.472 -            }
  23.473 -
  23.474 -            if (File.separatorChar != '/')
  23.475 -                path = path.replace('/', File.separatorChar);
  23.476 -            checkIndex();
  23.477 -            return directories.get(path) != null;
  23.478 -        }
  23.479 -        finally {
  23.480 -            lock.unlock();
  23.481 -        }
  23.482 -    }
  23.483 -
  23.484 -    public long getLastModified(String path) throws IOException {
  23.485 -        lock.lock();
  23.486 -        try {
  23.487 -            ZipFileIndexEntry entry = getZipIndexEntry(path);
  23.488 -            if (entry == null)
  23.489 -                throw new FileNotFoundException();
  23.490 -            return entry.getLastModified();
  23.491 -        }
  23.492 -        finally {
  23.493 -            lock.unlock();
  23.494 -        }
  23.495 -    }
  23.496 -
  23.497 -    public int length(String path) throws IOException {
  23.498 -        lock.lock();
  23.499 -        try {
  23.500 -            ZipFileIndexEntry entry = getZipIndexEntry(path);
  23.501 -            if (entry == null)
  23.502 -                throw new FileNotFoundException();
  23.503 -
  23.504 -            if (entry.isDir) {
  23.505 -                return 0;
  23.506 -            }
  23.507 -
  23.508 -            byte[] header = getHeader(entry);
  23.509 -            // entry is not compressed?
  23.510 -            if (get2ByteLittleEndian(header, 8) == 0) {
  23.511 -                return entry.compressedSize;
  23.512 -            } else {
  23.513 -                return entry.size;
  23.514 -            }
  23.515 -        }
  23.516 -        finally {
  23.517 -            lock.unlock();
  23.518 -        }
  23.519 -    }
  23.520 -
  23.521 -    public byte[] read(String path) throws IOException {
  23.522 -        lock.lock();
  23.523 -        try {
  23.524 -            ZipFileIndexEntry entry = getZipIndexEntry(path);
  23.525 -            if (entry == null)
  23.526 -                throw new FileNotFoundException(MessageFormat.format("Path not found in ZIP: {0}", path));
  23.527 -            return read(entry);
  23.528 -        }
  23.529 -        finally {
  23.530 -            lock.unlock();
  23.531 -        }
  23.532 -    }
  23.533 -
  23.534 -    public byte[] read(ZipFileIndexEntry entry) throws IOException {
  23.535 -        lock.lock();
  23.536 -        try {
  23.537 -            openFile();
  23.538 -            byte[] result = readBytes(entry);
  23.539 -            closeFile();
  23.540 -            return result;
  23.541 -        }
  23.542 -        finally {
  23.543 -            lock.unlock();
  23.544 -        }
  23.545 -    }
  23.546 -
  23.547 -    public int read(String path, byte[] buffer) throws IOException {
  23.548 -        lock.lock();
  23.549 -        try {
  23.550 -            ZipFileIndexEntry entry = getZipIndexEntry(path);
  23.551 -            if (entry == null)
  23.552 -                throw new FileNotFoundException();
  23.553 -            return read(entry, buffer);
  23.554 -        }
  23.555 -        finally {
  23.556 -            lock.unlock();
  23.557 -        }
  23.558 -    }
  23.559 -
  23.560 -    public int read(ZipFileIndexEntry entry, byte[] buffer)
  23.561 -            throws IOException {
  23.562 -        lock.lock();
  23.563 -        try {
  23.564 -            int result = readBytes(entry, buffer);
  23.565 -            return result;
  23.566 -        }
  23.567 -        finally {
  23.568 -            lock.unlock();
  23.569 -        }
  23.570 -    }
  23.571 -
  23.572 -    private byte[] readBytes(ZipFileIndexEntry entry) throws IOException {
  23.573 -        byte[] header = getHeader(entry);
  23.574 -        int csize = entry.compressedSize;
  23.575 -        byte[] cbuf = new byte[csize];
  23.576 -        zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
  23.577 -        zipRandomFile.readFully(cbuf, 0, csize);
  23.578 -
  23.579 -        // is this compressed - offset 8 in the ZipEntry header
  23.580 -        if (get2ByteLittleEndian(header, 8) == 0)
  23.581 -            return cbuf;
  23.582 -
  23.583 -        int size = entry.size;
  23.584 -        byte[] buf = new byte[size];
  23.585 -        if (inflate(cbuf, buf) != size)
  23.586 -            throw new ZipException("corrupted zip file");
  23.587 -
  23.588 -        return buf;
  23.589 -    }
  23.590 -
  23.591 -    /**
  23.592 -     *
  23.593 -     */
  23.594 -    private int readBytes(ZipFileIndexEntry entry, byte[] buffer) throws IOException {
  23.595 -        byte[] header = getHeader(entry);
  23.596 -
  23.597 -        // entry is not compressed?
  23.598 -        if (get2ByteLittleEndian(header, 8) == 0) {
  23.599 -            zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
  23.600 -            int offset = 0;
  23.601 -            int size = buffer.length;
  23.602 -            while (offset < size) {
  23.603 -                int count = zipRandomFile.read(buffer, offset, size - offset);
  23.604 -                if (count == -1)
  23.605 -                    break;
  23.606 -                offset += count;
  23.607 -            }
  23.608 -            return entry.size;
  23.609 -        }
  23.610 -
  23.611 -        int csize = entry.compressedSize;
  23.612 -        byte[] cbuf = new byte[csize];
  23.613 -        zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
  23.614 -        zipRandomFile.readFully(cbuf, 0, csize);
  23.615 -
  23.616 -        int count = inflate(cbuf, buffer);
  23.617 -        if (count == -1)
  23.618 -            throw new ZipException("corrupted zip file");
  23.619 -
  23.620 -        return entry.size;
  23.621 -    }
  23.622 -
  23.623 -    //----------------------------------------------------------------------------
  23.624 -    // Zip utilities
  23.625 -    //----------------------------------------------------------------------------
  23.626 -
  23.627 -    private byte[] getHeader(ZipFileIndexEntry entry) throws IOException {
  23.628 -        zipRandomFile.seek(entry.offset);
  23.629 -        byte[] header = new byte[30];
  23.630 -        zipRandomFile.readFully(header);
  23.631 -        if (get4ByteLittleEndian(header, 0) != 0x04034b50)
  23.632 -            throw new ZipException("corrupted zip file");
  23.633 -        if ((get2ByteLittleEndian(header, 6) & 1) != 0)
  23.634 -            throw new ZipException("encrypted zip file"); // offset 6 in the header of the ZipFileEntry
  23.635 -        return header;
  23.636 -    }
  23.637 -
  23.638 -  /*
  23.639 -   * Inflate using the java.util.zip.Inflater class
  23.640 -   */
  23.641 -    private static Inflater inflater;
  23.642 -    private int inflate(byte[] src, byte[] dest) {
  23.643 -
  23.644 -        // construct the inflater object or reuse an existing one
  23.645 -        if (inflater == null)
  23.646 -            inflater = new Inflater(true);
  23.647 -
  23.648 -        synchronized (inflater) {
  23.649 -            inflater.reset();
  23.650 -            inflater.setInput(src);
  23.651 -            try {
  23.652 -                return inflater.inflate(dest);
  23.653 -            } catch (DataFormatException ex) {
  23.654 -                return -1;
  23.655 -            }
  23.656 -        }
  23.657 -    }
  23.658 -
  23.659 -    /**
  23.660 -     * return the two bytes buf[pos], buf[pos+1] as an unsigned integer in little
  23.661 -     * endian format.
  23.662 -     */
  23.663 -    private static int get2ByteLittleEndian(byte[] buf, int pos) {
  23.664 -        return (buf[pos] & 0xFF) + ((buf[pos+1] & 0xFF) << 8);
  23.665 -    }
  23.666 -
  23.667 -    /**
  23.668 -     * return the 4 bytes buf[i..i+3] as an integer in little endian format.
  23.669 -     */
  23.670 -    private static int get4ByteLittleEndian(byte[] buf, int pos) {
  23.671 -        return (buf[pos] & 0xFF) + ((buf[pos + 1] & 0xFF) << 8) +
  23.672 -                ((buf[pos + 2] & 0xFF) << 16) + ((buf[pos + 3] & 0xFF) << 24);
  23.673 -    }
  23.674 -
  23.675 -    /* ----------------------------------------------------------------------------
  23.676 -     * ZipDirectory
  23.677 -     * ----------------------------------------------------------------------------*/
  23.678 -
  23.679 -    private class ZipDirectory {
  23.680 -        private String lastDir;
  23.681 -        private int lastStart;
  23.682 -        private int lastLen;
  23.683 -
  23.684 -        byte[] zipDir;
  23.685 -        RandomAccessFile zipRandomFile = null;
  23.686 -        ZipFileIndex zipFileIndex = null;
  23.687 -
  23.688 -        public ZipDirectory(RandomAccessFile zipRandomFile, long start, long end, ZipFileIndex index) throws IOException {
  23.689 -            this.zipRandomFile = zipRandomFile;
  23.690 -            this.zipFileIndex = index;
  23.691 -
  23.692 -            findCENRecord(start, end);
  23.693 -        }
  23.694 -
  23.695 -        /*
  23.696 -         * Reads zip file central directory.
  23.697 -         * For more details see readCEN in zip_util.c from the JDK sources.
  23.698 -         * This is a Java port of that function.
  23.699 -         */
  23.700 -        private void findCENRecord(long start, long end) throws IOException {
  23.701 -            long totalLength = end - start;
  23.702 -            int endbuflen = 1024;
  23.703 -            byte[] endbuf = new byte[endbuflen];
  23.704 -            long endbufend = end - start;
  23.705 -
  23.706 -            // There is a variable-length field after the dir offset record. We need to do consequential search.
  23.707 -            while (endbufend >= 22) {
  23.708 -                if (endbufend < endbuflen)
  23.709 -                    endbuflen = (int)endbufend;
  23.710 -                long endbufpos = endbufend - endbuflen;
  23.711 -                zipRandomFile.seek(start + endbufpos);
  23.712 -                zipRandomFile.readFully(endbuf, 0, endbuflen);
  23.713 -                int i = endbuflen - 22;
  23.714 -                while (i >= 0 &&
  23.715 -                        !(endbuf[i] == 0x50 &&
  23.716 -                        endbuf[i + 1] == 0x4b &&
  23.717 -                        endbuf[i + 2] == 0x05 &&
  23.718 -                        endbuf[i + 3] == 0x06 &&
  23.719 -                        endbufpos + i + 22 +
  23.720 -                        get2ByteLittleEndian(endbuf, i + 20) == totalLength)) {
  23.721 -                    i--;
  23.722 -                }
  23.723 -
  23.724 -                if (i >= 0) {
  23.725 -                    zipDir = new byte[get4ByteLittleEndian(endbuf, i + 12) + 2];
  23.726 -                    zipDir[0] = endbuf[i + 10];
  23.727 -                    zipDir[1] = endbuf[i + 11];
  23.728 -                    zipRandomFile.seek(start + get4ByteLittleEndian(endbuf, i + 16));
  23.729 -                    zipRandomFile.readFully(zipDir, 2, zipDir.length - 2);
  23.730 -                    return;
  23.731 -                } else {
  23.732 -                    endbufend = endbufpos + 21;
  23.733 -                }
  23.734 -            }
  23.735 -            throw new ZipException("cannot read zip file");
  23.736 -        }
  23.737 -        private void buildIndex() throws IOException {
  23.738 -            int entryCount = get2ByteLittleEndian(zipDir, 0);
  23.739 -
  23.740 -            entries = new ZipFileIndexEntry[entryCount];
  23.741 -            // Add each of the files
  23.742 -            if (entryCount > 0) {
  23.743 -                directories = new HashMap<String, DirectoryEntry>();
  23.744 -                ArrayList<ZipFileIndexEntry> entryList = new ArrayList<ZipFileIndexEntry>();
  23.745 -                int pos = 2;
  23.746 -                for (int i = 0; i < entryCount; i++) {
  23.747 -                    pos = readEntry(pos, entryList, directories);
  23.748 -                }
  23.749 -
  23.750 -                // Add the accumulated dirs into the same list
  23.751 -                Iterator i = directories.keySet().iterator();
  23.752 -                while (i.hasNext()) {
  23.753 -                    ZipFileIndexEntry zipFileIndexEntry = new ZipFileIndexEntry( (String) i.next());
  23.754 -                    zipFileIndexEntry.isDir = true;
  23.755 -                    entryList.add(zipFileIndexEntry);
  23.756 -                }
  23.757 -
  23.758 -                entries = entryList.toArray(new ZipFileIndexEntry[entryList.size()]);
  23.759 -                Arrays.sort(entries);
  23.760 -            } else {
  23.761 -                cleanupState();
  23.762 -            }
  23.763 -        }
  23.764 -
  23.765 -        private int readEntry(int pos, List<ZipFileIndexEntry> entryList,
  23.766 -                Map<String, DirectoryEntry> directories) throws IOException {
  23.767 -            if (get4ByteLittleEndian(zipDir, pos) != 0x02014b50) {
  23.768 -                throw new ZipException("cannot read zip file entry");
  23.769 -            }
  23.770 -
  23.771 -            int dirStart = pos + 46;
  23.772 -            int fileStart = dirStart;
  23.773 -            int fileEnd = fileStart + get2ByteLittleEndian(zipDir, pos + 28);
  23.774 -
  23.775 -            if (zipFileIndex.symbolFilePrefixLength != 0 &&
  23.776 -                    ((fileEnd - fileStart) >= symbolFilePrefixLength)) {
  23.777 -                dirStart += zipFileIndex.symbolFilePrefixLength;
  23.778 -               fileStart += zipFileIndex.symbolFilePrefixLength;
  23.779 -            }
  23.780 -
  23.781 -            // Use the OS's path separator. Keep the position of the last one.
  23.782 -            for (int index = fileStart; index < fileEnd; index++) {
  23.783 -                byte nextByte = zipDir[index];
  23.784 -                if (nextByte == (byte)'\\' || nextByte == (byte)'/') {
  23.785 -                    zipDir[index] = (byte)File.separatorChar;
  23.786 -                    fileStart = index + 1;
  23.787 -                }
  23.788 -            }
  23.789 -
  23.790 -            String directory = null;
  23.791 -            if (fileStart == dirStart)
  23.792 -                directory = "";
  23.793 -            else if (lastDir != null && lastLen == fileStart - dirStart - 1) {
  23.794 -                int index = lastLen - 1;
  23.795 -                while (zipDir[lastStart + index] == zipDir[dirStart + index]) {
  23.796 -                    if (index == 0) {
  23.797 -                        directory = lastDir;
  23.798 -                        break;
  23.799 -                    }
  23.800 -                    index--;
  23.801 -                }
  23.802 -            }
  23.803 -
  23.804 -            // Sub directories
  23.805 -            if (directory == null) {
  23.806 -                lastStart = dirStart;
  23.807 -                lastLen = fileStart - dirStart - 1;
  23.808 -
  23.809 -                directory = new String(zipDir, dirStart, lastLen, "UTF-8").intern();
  23.810 -                lastDir = directory;
  23.811 -
  23.812 -                // Enter also all the parent directories
  23.813 -                String tempDirectory = directory;
  23.814 -
  23.815 -                while (directories.get(tempDirectory) == null) {
  23.816 -                    directories.put(tempDirectory, new DirectoryEntry(tempDirectory, zipFileIndex));
  23.817 -                    int separator = tempDirectory.lastIndexOf(File.separatorChar);
  23.818 -                    if (separator == -1)
  23.819 -                        break;
  23.820 -                    tempDirectory = tempDirectory.substring(0, separator);
  23.821 -                }
  23.822 -            }
  23.823 -            else {
  23.824 -                directory = directory.intern();
  23.825 -                if (directories.get(directory) == null) {
  23.826 -                    directories.put(directory, new DirectoryEntry(directory, zipFileIndex));
  23.827 -                }
  23.828 -            }
  23.829 -
  23.830 -            // For each dir create also a file
  23.831 -            if (fileStart != fileEnd) {
  23.832 -                ZipFileIndexEntry entry = new ZipFileIndexEntry(directory,
  23.833 -                        new String(zipDir, fileStart, fileEnd - fileStart, "UTF-8"));
  23.834 -
  23.835 -                entry.setNativeTime(get4ByteLittleEndian(zipDir, pos + 12));
  23.836 -                entry.compressedSize = get4ByteLittleEndian(zipDir, pos + 20);
  23.837 -                entry.size = get4ByteLittleEndian(zipDir, pos + 24);
  23.838 -                entry.offset = get4ByteLittleEndian(zipDir, pos + 42);
  23.839 -                entryList.add(entry);
  23.840 -            }
  23.841 -
  23.842 -            return pos + 46 +
  23.843 -                    get2ByteLittleEndian(zipDir, pos + 28) +
  23.844 -                    get2ByteLittleEndian(zipDir, pos + 30) +
  23.845 -                    get2ByteLittleEndian(zipDir, pos + 32);
  23.846 -        }
  23.847 -    }
  23.848 -
  23.849 -    /**
  23.850 -     * Returns the last modified timestamp of a zip file.
  23.851 -     * @return long
  23.852 -     */
  23.853 -    public long getZipFileLastModified() throws IOException {
  23.854 -        lock.lock();
  23.855 -        try {
  23.856 -            checkIndex();
  23.857 -            return zipFileLastModified;
  23.858 -        }
  23.859 -        finally {
  23.860 -            lock.unlock();
  23.861 -        }
  23.862 -    }
  23.863 -
  23.864 -    /** ------------------------------------------------------------------------
  23.865 -     *  DirectoryEntry class
  23.866 -     * -------------------------------------------------------------------------*/
  23.867 -    static class DirectoryEntry {
  23.868 -        private boolean filesInited;
  23.869 -        private boolean directoriesInited;
  23.870 -        private boolean zipFileEntriesInited;
  23.871 -        private boolean entriesInited;
  23.872 -
  23.873 -        private long writtenOffsetOffset = 0;
  23.874 -
  23.875 -        private String dirName;
  23.876 -
  23.877 -        private com.sun.tools.javac.util.List<String> zipFileEntriesFiles = com.sun.tools.javac.util.List.<String>nil();
  23.878 -        private com.sun.tools.javac.util.List<String> zipFileEntriesDirectories = com.sun.tools.javac.util.List.<String>nil();
  23.879 -        private com.sun.tools.javac.util.List<ZipFileIndexEntry>  zipFileEntries = com.sun.tools.javac.util.List.<ZipFileIndexEntry>nil();
  23.880 -
  23.881 -        private List<ZipFileIndexEntry> entries = new ArrayList<ZipFileIndexEntry>();
  23.882 -
  23.883 -        private ZipFileIndex zipFileIndex;
  23.884 -
  23.885 -        private int numEntries;
  23.886 -
  23.887 -        DirectoryEntry(String dirName, ZipFileIndex index) {
  23.888 -        filesInited = false;
  23.889 -            directoriesInited = false;
  23.890 -            entriesInited = false;
  23.891 -
  23.892 -            if (File.separatorChar == '/') {
  23.893 -                dirName.replace('\\', '/');
  23.894 -            }
  23.895 -            else {
  23.896 -                dirName.replace('/', '\\');
  23.897 -            }
  23.898 -
  23.899 -            this.dirName = dirName.intern();
  23.900 -            this.zipFileIndex = index;
  23.901 -        }
  23.902 -
  23.903 -        private com.sun.tools.javac.util.List<String> getFiles() {
  23.904 -            if (filesInited) {
  23.905 -                return zipFileEntriesFiles;
  23.906 -            }
  23.907 -
  23.908 -            initEntries();
  23.909 -
  23.910 -            for (ZipFileIndexEntry e : entries) {
  23.911 -                if (!e.isDir) {
  23.912 -                    zipFileEntriesFiles = zipFileEntriesFiles.append(e.name);
  23.913 -                }
  23.914 -            }
  23.915 -            filesInited = true;
  23.916 -            return zipFileEntriesFiles;
  23.917 -        }
  23.918 -
  23.919 -        private com.sun.tools.javac.util.List<String> getDirectories() {
  23.920 -            if (directoriesInited) {
  23.921 -                return zipFileEntriesFiles;
  23.922 -            }
  23.923 -
  23.924 -            initEntries();
  23.925 -
  23.926 -            for (ZipFileIndexEntry e : entries) {
  23.927 -                if (e.isDir) {
  23.928 -                    zipFileEntriesDirectories = zipFileEntriesDirectories.append(e.name);
  23.929 -                }
  23.930 -            }
  23.931 -
  23.932 -            directoriesInited = true;
  23.933 -
  23.934 -            return zipFileEntriesDirectories;
  23.935 -        }
  23.936 -
  23.937 -        private com.sun.tools.javac.util.List<ZipFileIndexEntry> getEntries() {
  23.938 -            if (zipFileEntriesInited) {
  23.939 -                return zipFileEntries;
  23.940 -            }
  23.941 -
  23.942 -            initEntries();
  23.943 -
  23.944 -            zipFileEntries = com.sun.tools.javac.util.List.nil();
  23.945 -            for (ZipFileIndexEntry zfie : entries) {
  23.946 -                zipFileEntries = zipFileEntries.append(zfie);
  23.947 -            }
  23.948 -
  23.949 -            zipFileEntriesInited = true;
  23.950 -
  23.951 -            return zipFileEntries;
  23.952 -        }
  23.953 -
  23.954 -        private ZipFileIndexEntry getEntry(String rootName) {
  23.955 -            initEntries();
  23.956 -            int index = Collections.binarySearch(entries, new ZipFileIndexEntry(dirName, rootName));
  23.957 -            if (index < 0) {
  23.958 -                return null;
  23.959 -            }
  23.960 -
  23.961 -            return entries.get(index);
  23.962 -        }
  23.963 -
  23.964 -        private void initEntries() {
  23.965 -            if (entriesInited) {
  23.966 -                return;
  23.967 -            }
  23.968 -
  23.969 -            if (!zipFileIndex.readFromIndex) {
  23.970 -                int from = -Arrays.binarySearch(zipFileIndex.entries,
  23.971 -                        new ZipFileIndexEntry(dirName, ZipFileIndex.MIN_CHAR)) - 1;
  23.972 -                int to = -Arrays.binarySearch(zipFileIndex.entries,
  23.973 -                        new ZipFileIndexEntry(dirName, MAX_CHAR)) - 1;
  23.974 -
  23.975 -                boolean emptyList = false;
  23.976 -
  23.977 -                for (int i = from; i < to; i++) {
  23.978 -                    entries.add(zipFileIndex.entries[i]);
  23.979 -                }
  23.980 -            } else {
  23.981 -                File indexFile = zipFileIndex.getIndexFile();
  23.982 -                if (indexFile != null) {
  23.983 -                    RandomAccessFile raf = null;
  23.984 -                    try {
  23.985 -                        raf = new RandomAccessFile(indexFile, "r");
  23.986 -                        raf.seek(writtenOffsetOffset);
  23.987 -
  23.988 -                        for (int nFiles = 0; nFiles < numEntries; nFiles++) {
  23.989 -                            // Read the name bytes
  23.990 -                            int zfieNameBytesLen = raf.readInt();
  23.991 -                            byte [] zfieNameBytes = new byte[zfieNameBytesLen];
  23.992 -                            raf.read(zfieNameBytes);
  23.993 -                            String eName = new String(zfieNameBytes, "UTF-8");
  23.994 -
  23.995 -                            // Read isDir
  23.996 -                            boolean eIsDir = raf.readByte() == (byte)0 ? false : true;
  23.997 -
  23.998 -                            // Read offset of bytes in the real Jar/Zip file
  23.999 -                            int eOffset = raf.readInt();
 23.1000 -
 23.1001 -                            // Read size of the file in the real Jar/Zip file
 23.1002 -                            int eSize = raf.readInt();
 23.1003 -
 23.1004 -                            // Read compressed size of the file in the real Jar/Zip file
 23.1005 -                            int eCsize = raf.readInt();
 23.1006 -
 23.1007 -                            // Read java time stamp of the file in the real Jar/Zip file
 23.1008 -                            long eJavaTimestamp = raf.readLong();
 23.1009 -
 23.1010 -                            ZipFileIndexEntry rfie = new ZipFileIndexEntry(dirName, eName);
 23.1011 -                            rfie.isDir = eIsDir;
 23.1012 -                            rfie.offset = eOffset;
 23.1013 -                            rfie.size = eSize;
 23.1014 -                            rfie.compressedSize = eCsize;
 23.1015 -                            rfie.javatime = eJavaTimestamp;
 23.1016 -                            entries.add(rfie);
 23.1017 -                        }
 23.1018 -                    } catch (Throwable t) {
 23.1019 -                        // Do nothing
 23.1020 -                    } finally {
 23.1021 -                        try {
 23.1022 -                            if (raf == null) {
 23.1023 -                                raf.close();
 23.1024 -                            }
 23.1025 -                        } catch (Throwable t) {
 23.1026 -                            // Do nothing
 23.1027 -                        }
 23.1028 -                    }
 23.1029 -                }
 23.1030 -            }
 23.1031 -
 23.1032 -            entriesInited = true;
 23.1033 -        }
 23.1034 -
 23.1035 -        List<ZipFileIndexEntry> getEntriesAsCollection() {
 23.1036 -            initEntries();
 23.1037 -
 23.1038 -            return entries;
 23.1039 -        }
 23.1040 -    }
 23.1041 -
 23.1042 -    private boolean readIndex() {
 23.1043 -        if (triedToReadIndex || !usePreindexedCache) {
 23.1044 -            return false;
 23.1045 -        }
 23.1046 -
 23.1047 -        boolean ret = false;
 23.1048 -        lock.lock();
 23.1049 -        try {
 23.1050 -            triedToReadIndex = true;
 23.1051 -            RandomAccessFile raf = null;
 23.1052 -            try {
 23.1053 -                File indexFileName = getIndexFile();
 23.1054 -                raf = new RandomAccessFile(indexFileName, "r");
 23.1055 -
 23.1056 -                long fileStamp = raf.readLong();
 23.1057 -                if (zipFile.lastModified() != fileStamp) {
 23.1058 -                    ret = false;
 23.1059 -                } else {
 23.1060 -                    directories = new HashMap<String, DirectoryEntry>();
 23.1061 -                    int numDirs = raf.readInt();
 23.1062 -                    for (int nDirs = 0; nDirs < numDirs; nDirs++) {
 23.1063 -                        int dirNameBytesLen = raf.readInt();
 23.1064 -                        byte [] dirNameBytes = new byte[dirNameBytesLen];
 23.1065 -                        raf.read(dirNameBytes);
 23.1066 -
 23.1067 -                        String dirNameStr = new String(dirNameBytes, "UTF-8");
 23.1068 -                        DirectoryEntry de = new DirectoryEntry(dirNameStr, this);
 23.1069 -                        de.numEntries = raf.readInt();
 23.1070 -                        de.writtenOffsetOffset = raf.readLong();
 23.1071 -                        directories.put(dirNameStr, de);
 23.1072 -                    }
 23.1073 -                    ret = true;
 23.1074 -                    zipFileLastModified = fileStamp;
 23.1075 -                }
 23.1076 -            } catch (Throwable t) {
 23.1077 -                // Do nothing
 23.1078 -            } finally {
 23.1079 -                if (raf != null) {
 23.1080 -                    try {
 23.1081 -                        raf.close();
 23.1082 -                    } catch (Throwable tt) {
 23.1083 -                        // Do nothing
 23.1084 -                    }
 23.1085 -                }
 23.1086 -            }
 23.1087 -            if (ret == true) {
 23.1088 -                readFromIndex = true;
 23.1089 -            }
 23.1090 -        }
 23.1091 -        finally {
 23.1092 -            lock.unlock();
 23.1093 -        }
 23.1094 -
 23.1095 -        return ret;
 23.1096 -    }
 23.1097 -
 23.1098 -    private boolean writeIndex() {
 23.1099 -        boolean ret = false;
 23.1100 -        if (readFromIndex || !usePreindexedCache) {
 23.1101 -            return true;
 23.1102 -        }
 23.1103 -
 23.1104 -        if (!writeIndex) {
 23.1105 -            return true;
 23.1106 -        }
 23.1107 -
 23.1108 -        File indexFile = getIndexFile();
 23.1109 -        if (indexFile == null) {
 23.1110 -            return false;
 23.1111 -        }
 23.1112 -
 23.1113 -        RandomAccessFile raf = null;
 23.1114 -        long writtenSoFar = 0;
 23.1115 -        try {
 23.1116 -            raf = new RandomAccessFile(indexFile, "rw");
 23.1117 -
 23.1118 -            raf.writeLong(zipFileLastModified);
 23.1119 -            writtenSoFar += 8;
 23.1120 -
 23.1121 -
 23.1122 -            Iterator<String> iterDirName = directories.keySet().iterator();
 23.1123 -            List<DirectoryEntry> directoriesToWrite = new ArrayList<DirectoryEntry>();
 23.1124 -            Map<String, Long> offsets = new HashMap<String, Long>();
 23.1125 -            raf.writeInt(directories.keySet().size());
 23.1126 -            writtenSoFar += 4;
 23.1127 -
 23.1128 -            while(iterDirName.hasNext()) {
 23.1129 -                String dirName = iterDirName.next();
 23.1130 -                DirectoryEntry dirEntry = directories.get(dirName);
 23.1131 -
 23.1132 -                directoriesToWrite.add(dirEntry);
 23.1133 -
 23.1134 -                // Write the dir name bytes
 23.1135 -                byte [] dirNameBytes = dirName.getBytes("UTF-8");
 23.1136 -                int dirNameBytesLen = dirNameBytes.length;
 23.1137 -                raf.writeInt(dirNameBytesLen);
 23.1138 -                writtenSoFar += 4;
 23.1139 -
 23.1140 -                raf.write(dirNameBytes);
 23.1141 -                writtenSoFar += dirNameBytesLen;
 23.1142 -
 23.1143 -                // Write the number of files in the dir
 23.1144 -                List dirEntries = dirEntry.getEntriesAsCollection();
 23.1145 -                raf.writeInt(dirEntries.size());
 23.1146 -                writtenSoFar += 4;
 23.1147 -
 23.1148 -                offsets.put(dirName, new Long(writtenSoFar));
 23.1149 -
 23.1150 -                // Write the offset of the file's data in the dir
 23.1151 -                dirEntry.writtenOffsetOffset = 0L;
 23.1152 -                raf.writeLong(0L);
 23.1153 -                writtenSoFar += 8;
 23.1154 -            }
 23.1155 -
 23.1156 -            for (DirectoryEntry de : directoriesToWrite) {
 23.1157 -                // Fix up the offset in the directory table
 23.1158 -                long currFP = raf.getFilePointer();
 23.1159 -
 23.1160 -                long offsetOffset = offsets.get(de.dirName).longValue();
 23.1161 -                raf.seek(offsetOffset);
 23.1162 -                raf.writeLong(writtenSoFar);
 23.1163 -
 23.1164 -                raf.seek(currFP);
 23.1165 -
 23.1166 -                // Now write each of the files in the DirectoryEntry
 23.1167 -                List<ZipFileIndexEntry> entries = de.getEntriesAsCollection();
 23.1168 -                for (ZipFileIndexEntry zfie : entries) {
 23.1169 -                    // Write the name bytes
 23.1170 -                    byte [] zfieNameBytes = zfie.name.getBytes("UTF-8");
 23.1171 -                    int zfieNameBytesLen = zfieNameBytes.length;
 23.1172 -                    raf.writeInt(zfieNameBytesLen);
 23.1173 -                    writtenSoFar += 4;
 23.1174 -                    raf.write(zfieNameBytes);
 23.1175 -                    writtenSoFar += zfieNameBytesLen;
 23.1176 -
 23.1177 -                    // Write isDir
 23.1178 -                    raf.writeByte(zfie.isDir ? (byte)1 : (byte)0);
 23.1179 -                    writtenSoFar += 1;
 23.1180 -
 23.1181 -                    // Write offset of bytes in the real Jar/Zip file
 23.1182 -                    raf.writeInt(zfie.offset);
 23.1183 -                    writtenSoFar += 4;
 23.1184 -
 23.1185 -                    // Write size of the file in the real Jar/Zip file
 23.1186 -                    raf.writeInt(zfie.size);
 23.1187 -                    writtenSoFar += 4;
 23.1188 -
 23.1189 -                    // Write compressed size of the file in the real Jar/Zip file
 23.1190 -                    raf.writeInt(zfie.compressedSize);
 23.1191 -                    writtenSoFar += 4;
 23.1192 -
 23.1193 -                    // Write java time stamp of the file in the real Jar/Zip file
 23.1194 -                    raf.writeLong(zfie.getLastModified());
 23.1195 -                    writtenSoFar += 8;
 23.1196 -                }
 23.1197 -            }
 23.1198 -        } catch (Throwable t) {
 23.1199 -            // Do nothing
 23.1200 -        } finally {
 23.1201 -            try {
 23.1202 -                if (raf != null) {
 23.1203 -                    raf.close();
 23.1204 -                }
 23.1205 -            } catch(IOException ioe) {
 23.1206 -                // Do nothing
 23.1207 -            }
 23.1208 -        }
 23.1209 -
 23.1210 -        return ret;
 23.1211 -    }
 23.1212 -
 23.1213 -    public boolean writeZipIndex() {
 23.1214 -        lock.lock();
 23.1215 -        try {
 23.1216 -            return writeIndex();
 23.1217 -        }
 23.1218 -        finally {
 23.1219 -            lock.unlock();
 23.1220 -        }
 23.1221 -    }
 23.1222 -
 23.1223 -    private File getIndexFile() {
 23.1224 -        if (zipIndexFile == null) {
 23.1225 -            if (zipFile == null) {
 23.1226 -                return null;
 23.1227 -            }
 23.1228 -
 23.1229 -            zipIndexFile = new File((preindexedCacheLocation == null ? "" : preindexedCacheLocation) +
 23.1230 -                    zipFile.getName() + ".index");
 23.1231 -        }
 23.1232 -
 23.1233 -        return zipIndexFile;
 23.1234 -    }
 23.1235 -
 23.1236 -    public File getZipFile() {
 23.1237 -        return zipFile;
 23.1238 -    }
 23.1239 -}
    24.1 --- a/src/share/classes/com/sun/tools/javac/zip/ZipFileIndexEntry.java	Fri Jun 06 15:17:35 2008 -0700
    24.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.3 @@ -1,116 +0,0 @@
    24.4 -/*
    24.5 - * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
    24.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    24.7 - *
    24.8 - * This code is free software; you can redistribute it and/or modify it
    24.9 - * under the terms of the GNU General Public License version 2 only, as
   24.10 - * published by the Free Software Foundation.  Sun designates this
   24.11 - * particular file as subject to the "Classpath" exception as provided
   24.12 - * by Sun in the LICENSE file that accompanied this code.
   24.13 - *
   24.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
   24.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   24.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   24.17 - * version 2 for more details (a copy is included in the LICENSE file that
   24.18 - * accompanied this code).
   24.19 - *
   24.20 - * You should have received a copy of the GNU General Public License version
   24.21 - * 2 along with this work; if not, write to the Free Software Foundation,
   24.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   24.23 - *
   24.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   24.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
   24.26 - * have any questions.
   24.27 - */
   24.28 -
   24.29 -package com.sun.tools.javac.zip;
   24.30 -
   24.31 -import java.io.File;
   24.32 -
   24.33 -public final class ZipFileIndexEntry implements Comparable<ZipFileIndexEntry> {
   24.34 -    public static final ZipFileIndexEntry[] EMPTY_ARRAY = {};
   24.35 -
   24.36 -    // Directory related
   24.37 -    String dir;
   24.38 -    boolean isDir;
   24.39 -
   24.40 -    // File related
   24.41 -    String name;
   24.42 -
   24.43 -    int offset;
   24.44 -    int size;
   24.45 -    int compressedSize;
   24.46 -    long javatime;
   24.47 -
   24.48 -    private int nativetime;
   24.49 -
   24.50 -    public ZipFileIndexEntry(String path) {
   24.51 -        int separator = path.lastIndexOf(File.separatorChar);
   24.52 -        if (separator == -1) {
   24.53 -            dir = "".intern();
   24.54 -            name = path;
   24.55 -        } else {
   24.56 -            dir = path.substring(0, separator).intern();
   24.57 -            name = path.substring(separator + 1);
   24.58 -        }
   24.59 -    }
   24.60 -
   24.61 -    public ZipFileIndexEntry(String directory, String name) {
   24.62 -        this.dir = directory.intern();
   24.63 -        this.name = name;
   24.64 -    }
   24.65 -
   24.66 -    public String getName() {
   24.67 -        if (dir == null || dir.length() == 0) {
   24.68 -            return name;
   24.69 -        }
   24.70 -
   24.71 -        StringBuilder sb = new StringBuilder();
   24.72 -        sb.append(dir);
   24.73 -        sb.append(File.separatorChar);
   24.74 -        sb.append(name);
   24.75 -        return sb.toString();
   24.76 -    }
   24.77 -
   24.78 -    public String getFileName() {
   24.79 -        return name;
   24.80 -    }
   24.81 -
   24.82 -    public long getLastModified() {
   24.83 -        if (javatime == 0) {
   24.84 -                javatime = dosToJavaTime(nativetime);
   24.85 -        }
   24.86 -        return javatime;
   24.87 -    }
   24.88 -
   24.89 -    // From java.util.zip
   24.90 -    private static long dosToJavaTime(int nativetime) {
   24.91 -        // Bootstrap build problems prevent me from using the code directly
   24.92 -        // Convert the raw/native time to a long for now
   24.93 -        return (long)nativetime;
   24.94 -    }
   24.95 -
   24.96 -    void setNativeTime(int natTime) {
   24.97 -        nativetime = natTime;
   24.98 -    }
   24.99 -
  24.100 -    public boolean isDirectory() {
  24.101 -        return isDir;
  24.102 -    }
  24.103 -
  24.104 -    public int compareTo(ZipFileIndexEntry other) {
  24.105 -        String otherD = other.dir;
  24.106 -        if (dir != otherD) {
  24.107 -            int c = dir.compareTo(otherD);
  24.108 -            if (c != 0)
  24.109 -                return c;
  24.110 -        }
  24.111 -        return name.compareTo(other.name);
  24.112 -    }
  24.113 -
  24.114 -
  24.115 -    public String toString() {
  24.116 -        return isDir ? ("Dir:" + dir + " : " + name) :
  24.117 -            (dir + ":" + name);
  24.118 -    }
  24.119 -}
    25.1 --- a/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java	Fri Jun 06 15:17:35 2008 -0700
    25.2 +++ b/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java	Mon Jun 16 13:28:00 2008 -0700
    25.3 @@ -26,10 +26,10 @@
    25.4  package com.sun.tools.javadoc;
    25.5  
    25.6  import com.sun.tools.javac.code.Symbol.PackageSymbol;
    25.7 +import com.sun.tools.javac.file.JavacFileManager;
    25.8 +import com.sun.tools.javac.file.Old199;
    25.9  import com.sun.tools.javac.jvm.ClassReader;
   25.10  import com.sun.tools.javac.util.Context;
   25.11 -import com.sun.tools.javac.util.JavacFileManager;
   25.12 -import com.sun.tools.javac.util.Old199;
   25.13  
   25.14  import java.io.File;
   25.15  import java.util.EnumSet;
    26.1 --- a/src/share/classes/com/sun/tools/javadoc/JavadocTool.java	Fri Jun 06 15:17:35 2008 -0700
    26.2 +++ b/src/share/classes/com/sun/tools/javadoc/JavadocTool.java	Mon Jun 16 13:28:00 2008 -0700
    26.3 @@ -29,19 +29,14 @@
    26.4  
    26.5  import java.util.Collection;
    26.6  
    26.7 -import com.sun.tools.javac.code.*;
    26.8  import com.sun.tools.javac.code.Symbol.*;
    26.9  import com.sun.tools.javac.comp.*;
   26.10 -import com.sun.tools.javac.jvm.ClassReader;
   26.11 -import com.sun.tools.javac.jvm.ClassWriter;
   26.12 +import com.sun.tools.javac.file.Paths;
   26.13  import com.sun.tools.javac.parser.DocCommentScanner;
   26.14 -import com.sun.tools.javac.util.Paths;
   26.15  import com.sun.tools.javac.tree.*;
   26.16  import com.sun.tools.javac.tree.JCTree.*;
   26.17  import com.sun.tools.javac.util.*;
   26.18  
   26.19 -import com.sun.javadoc.LanguageVersion;
   26.20 -import static com.sun.javadoc.LanguageVersion.*;
   26.21  
   26.22  /**
   26.23   *  This class could be the main entry point for Javadoc when Javadoc is used as a
   26.24 @@ -147,7 +142,7 @@
   26.25                  } else if (isValidPackageName(name)) {
   26.26                      names = names.append(name);
   26.27                  } else if (name.endsWith(".java")) {
   26.28 -                    docenv.error(null, "main.file_not_found", name);;
   26.29 +                    docenv.error(null, "main.file_not_found", name);
   26.30                  } else {
   26.31                      docenv.error(null, "main.illegal_package_name", name);
   26.32                  }
    27.1 --- a/src/share/classes/com/sun/tools/javap/JavapFileManager.java	Fri Jun 06 15:17:35 2008 -0700
    27.2 +++ b/src/share/classes/com/sun/tools/javap/JavapFileManager.java	Mon Jun 16 13:28:00 2008 -0700
    27.3 @@ -32,9 +32,9 @@
    27.4  import javax.tools.DiagnosticListener;
    27.5  import javax.tools.JavaFileObject;
    27.6  
    27.7 +import com.sun.tools.javac.file.JavacFileManager;
    27.8  import com.sun.tools.javac.util.Context;
    27.9  import com.sun.tools.javac.util.JCDiagnostic;
   27.10 -import com.sun.tools.javac.util.JavacFileManager;
   27.11  
   27.12  /**
   27.13   *  javap's implementation of JavaFileManager.
    28.1 --- a/test/tools/javac/6304921/TestLog.java	Fri Jun 06 15:17:35 2008 -0700
    28.2 +++ b/test/tools/javac/6304921/TestLog.java	Mon Jun 16 13:28:00 2008 -0700
    28.3 @@ -32,12 +32,12 @@
    28.4  import java.net.URI;
    28.5  import javax.tools.JavaFileObject;
    28.6  import javax.tools.SimpleJavaFileObject;
    28.7 +import com.sun.tools.javac.file.JavacFileManager;
    28.8  import com.sun.tools.javac.parser.Parser;
    28.9  import com.sun.tools.javac.parser.Scanner;
   28.10  import com.sun.tools.javac.tree.JCTree;
   28.11  import com.sun.tools.javac.tree.TreeScanner;
   28.12  import com.sun.tools.javac.util.Context;
   28.13 -import com.sun.tools.javac.util.JavacFileManager;
   28.14  import com.sun.tools.javac.util.Log;
   28.15  import com.sun.tools.javac.util.JCDiagnostic;
   28.16  import com.sun.tools.javac.util.Options;
    29.1 --- a/test/tools/javac/6589361/T6589361.java	Fri Jun 06 15:17:35 2008 -0700
    29.2 +++ b/test/tools/javac/6589361/T6589361.java	Mon Jun 16 13:28:00 2008 -0700
    29.3 @@ -4,8 +4,8 @@
    29.4   * @summary 6589361:Failing building ct.sym file as part of the control build
    29.5   */
    29.6  
    29.7 +import com.sun.tools.javac.file.JavacFileManager;
    29.8  import com.sun.tools.javac.util.Context;
    29.9 -import com.sun.tools.javac.util.JavacFileManager;
   29.10  import java.io.File;
   29.11  import javax.tools.FileObject;
   29.12  import javax.tools.JavaFileObject;
    30.1 --- a/test/tools/javac/T6358024.java	Fri Jun 06 15:17:35 2008 -0700
    30.2 +++ b/test/tools/javac/T6358024.java	Mon Jun 16 13:28:00 2008 -0700
    30.3 @@ -35,6 +35,7 @@
    30.4  import javax.tools.*;
    30.5  import com.sun.source.util.*;
    30.6  import com.sun.tools.javac.api.*;
    30.7 +import com.sun.tools.javac.file.*;
    30.8  import com.sun.tools.javac.main.*;
    30.9  import com.sun.tools.javac.util.*;
   30.10  
    31.1 --- a/test/tools/javac/T6358166.java	Fri Jun 06 15:17:35 2008 -0700
    31.2 +++ b/test/tools/javac/T6358166.java	Mon Jun 16 13:28:00 2008 -0700
    31.3 @@ -32,6 +32,7 @@
    31.4  import javax.annotation.processing.*;
    31.5  import javax.lang.model.element.*;
    31.6  import javax.tools.*;
    31.7 +import com.sun.tools.javac.file.*;
    31.8  import com.sun.tools.javac.main.JavaCompiler;
    31.9  import com.sun.tools.javac.main.*;
   31.10  import com.sun.tools.javac.util.*;
    32.1 --- a/test/tools/javac/T6358168.java	Fri Jun 06 15:17:35 2008 -0700
    32.2 +++ b/test/tools/javac/T6358168.java	Mon Jun 16 13:28:00 2008 -0700
    32.3 @@ -33,6 +33,7 @@
    32.4  import javax.annotation.processing.*;
    32.5  import javax.lang.model.element.*;
    32.6  import javax.tools.*;
    32.7 +import com.sun.tools.javac.file.*;
    32.8  import com.sun.tools.javac.main.JavaCompiler;
    32.9  import com.sun.tools.javac.main.*;
   32.10  import com.sun.tools.javac.util.*;
    33.1 --- a/test/tools/javac/T6705935.java	Fri Jun 06 15:17:35 2008 -0700
    33.2 +++ b/test/tools/javac/T6705935.java	Mon Jun 16 13:28:00 2008 -0700
    33.3 @@ -30,7 +30,7 @@
    33.4  import java.io.*;
    33.5  import java.util.*;
    33.6  import javax.tools.*;
    33.7 -import com.sun.tools.javac.util.*;
    33.8 +import com.sun.tools.javac.file.*;
    33.9  
   33.10  public class T6705935 {
   33.11      public static void main(String... args) throws Exception {
    34.1 --- a/test/tools/javac/api/T6358786.java	Fri Jun 06 15:17:35 2008 -0700
    34.2 +++ b/test/tools/javac/api/T6358786.java	Mon Jun 16 13:28:00 2008 -0700
    34.3 @@ -30,7 +30,7 @@
    34.4   */
    34.5  
    34.6  import com.sun.tools.javac.api.JavacTaskImpl;
    34.7 -import com.sun.tools.javac.util.JavacFileManager;
    34.8 +import com.sun.tools.javac.file.JavacFileManager;
    34.9  import java.util.Arrays;
   34.10  
   34.11  import javax.lang.model.util.Elements;
    35.1 --- a/test/tools/javac/api/TestResolveIdent.java	Fri Jun 06 15:17:35 2008 -0700
    35.2 +++ b/test/tools/javac/api/TestResolveIdent.java	Mon Jun 16 13:28:00 2008 -0700
    35.3 @@ -30,8 +30,8 @@
    35.4   */
    35.5  
    35.6  import com.sun.tools.javac.api.JavacTaskImpl;
    35.7 +import com.sun.tools.javac.file.JavacFileManager;
    35.8  import com.sun.tools.javac.main.JavaCompiler;
    35.9 -import com.sun.tools.javac.util.JavacFileManager;
   35.10  import java.io.File;
   35.11  import java.io.IOException;
   35.12  import javax.lang.model.element.TypeElement;
    36.1 --- a/test/tools/javac/util/filemanager/TestName.java	Fri Jun 06 15:17:35 2008 -0700
    36.2 +++ b/test/tools/javac/util/filemanager/TestName.java	Mon Jun 16 13:28:00 2008 -0700
    36.3 @@ -29,7 +29,7 @@
    36.4   * @author  Peter von der Ah\u00e9
    36.5   */
    36.6  
    36.7 -import com.sun.tools.javac.util.JavacFileManager;
    36.8 +import com.sun.tools.javac.file.JavacFileManager;
    36.9  
   36.10  public class TestName {
   36.11      public static void main(String... args) {

mercurial