6906175: bridge JSR199 and JSR 203 APIs

Fri, 11 Dec 2009 14:26:27 -0800

author
jjg
date
Fri, 11 Dec 2009 14:26:27 -0800
changeset 450
4011f49b4af8
parent 449
ff823a039e16
child 451
fbeb560f39e7

6906175: bridge JSR199 and JSR 203 APIs
Reviewed-by: darcy, alanb

make/build.properties file | annotate | diff | comparison | revisions
make/build.xml 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/CloseableURLClassLoader.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/Paths.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/nio/PathFileManager.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/nio/PathFileObject.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/BaseFileManager.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/CloseableURLClassLoader.java file | annotate | diff | comparison | revisions
src/share/classes/javax/tools/StandardJavaFileManager.java file | annotate | diff | comparison | revisions
test/tools/javac/nio/compileTest/CompileTest.java file | annotate | diff | comparison | revisions
test/tools/javac/nio/compileTest/HelloPathWorld.java file | annotate | diff | comparison | revisions
     1.1 --- a/make/build.properties	Thu Dec 10 20:35:31 2009 -0800
     1.2 +++ b/make/build.properties	Fri Dec 11 14:26:27 2009 -0800
     1.3 @@ -149,11 +149,26 @@
     1.4  #
     1.5  
     1.6  # The following files require the import JDK to be available
     1.7 -require.import.jdk.files =
     1.8 +require.import.jdk.files = \
     1.9 +    com/sun/tools/javac/nio/*.java
    1.10  
    1.11  # The following files in the import jdk source directory are required
    1.12  # in order to compile the files defined in ${require.import.jdk.files}
    1.13 -import.jdk.stub.files =
    1.14 +#
    1.15 +# For NIO, the list of stub files is defined by the contents of the primary
    1.16 +# API packages, together with such types that may be required in order to
    1.17 +# compile the stubs. Some of these dependencies would go away if the stub
    1.18 +# generator were to be improved -- e.g. by removing unnecessary imports.
    1.19 +#
    1.20 +import.jdk.stub.files = \
    1.21 +    java/io/File.java \
    1.22 +    java/nio/file/**.java \
    1.23 +    java/nio/file/attribute/**.java \
    1.24 +    java/nio/file/spi/**.java \
    1.25 +    java/nio/channels/AsynchronousChannel.java \
    1.26 +    java/nio/channels/AsynchronousFileChannel.java \
    1.27 +    java/nio/channels/CompletionHandler.java \
    1.28 +    java/nio/channels/SeekableByteChannel.java
    1.29  
    1.30  # The following value is used by the main jtreg target.
    1.31  # An empty value means all tests
     2.1 --- a/make/build.xml	Thu Dec 10 20:35:31 2009 -0800
     2.2 +++ b/make/build.xml	Fri Dec 11 14:26:27 2009 -0800
     2.3 @@ -98,7 +98,7 @@
     2.4          import.jdk should be unset, or set to jdk home (to use rt.jar)
     2.5          or to jdk repo (to use src/share/classes).
     2.6          Based on the value, if any, set up default values for javac's sourcepath,
     2.7 -        classpath and bootclasspath. Note: the default values are overridden 
     2.8 +        classpath and bootclasspath. Note: the default values are overridden
     2.9          in the build-bootstrap-classes macro. -->
    2.10  
    2.11      <available property="import.jdk.src.dir" value="${import.jdk}/src/share/classes"
    2.12 @@ -552,8 +552,8 @@
    2.13                      <compilerarg line="${javac.version.opt}"/>
    2.14                      <compilerarg line="${javac.lint.opts}"/>
    2.15                  </javac>
    2.16 -                <copy todir="@{classes.dir}">
    2.17 -                    <fileset dir="${src.classes.dir}" includes="@{includes}">
    2.18 +                <copy todir="@{classes.dir}" includeemptydirs="false">
    2.19 +                    <fileset dir="${src.classes.dir}" includes="@{includes}" excludes="@{excludes}">
    2.20                          <exclude name="**/*.java"/>
    2.21                          <exclude name="**/*.properties"/>
    2.22                          <exclude name="**/*-template"/>
     3.1 --- a/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java	Thu Dec 10 20:35:31 2009 -0800
     3.2 +++ b/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java	Fri Dec 11 14:26:27 2009 -0800
     3.3 @@ -39,6 +39,8 @@
     3.4  
     3.5  import static javax.tools.JavaFileObject.Kind.*;
     3.6  
     3.7 +import com.sun.tools.javac.util.BaseFileManager;
     3.8 +
     3.9  /**
    3.10   * <p><b>This is NOT part of any API supported by Sun Microsystems.
    3.11   * If you write code that depends on this, you do so at your own risk.
    3.12 @@ -74,14 +76,7 @@
    3.13      protected abstract String inferBinaryName(Iterable<? extends File> path);
    3.14  
    3.15      protected static JavaFileObject.Kind getKind(String filename) {
    3.16 -        if (filename.endsWith(CLASS.extension))
    3.17 -            return CLASS;
    3.18 -        else if (filename.endsWith(SOURCE.extension))
    3.19 -            return SOURCE;
    3.20 -        else if (filename.endsWith(HTML.extension))
    3.21 -            return HTML;
    3.22 -        else
    3.23 -            return OTHER;
    3.24 +        return BaseFileManager.getKind(filename);
    3.25      }
    3.26  
    3.27      protected static String removeExtension(String fileName) {
     4.1 --- a/src/share/classes/com/sun/tools/javac/file/CloseableURLClassLoader.java	Thu Dec 10 20:35:31 2009 -0800
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,107 +0,0 @@
     4.4 -/*
     4.5 - * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
     4.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 - *
     4.8 - * This code is free software; you can redistribute it and/or modify it
     4.9 - * under the terms of the GNU General Public License version 2 only, as
    4.10 - * published by the Free Software Foundation.  Sun designates this
    4.11 - * particular file as subject to the "Classpath" exception as provided
    4.12 - * by Sun in the LICENSE file that accompanied this code.
    4.13 - *
    4.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
    4.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.17 - * version 2 for more details (a copy is included in the LICENSE file that
    4.18 - * accompanied this code).
    4.19 - *
    4.20 - * You should have received a copy of the GNU General Public License version
    4.21 - * 2 along with this work; if not, write to the Free Software Foundation,
    4.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.23 - *
    4.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    4.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
    4.26 - * have any questions.
    4.27 - */
    4.28 -
    4.29 -package com.sun.tools.javac.file;
    4.30 -
    4.31 -import java.io.Closeable;
    4.32 -import java.io.IOException;
    4.33 -import java.lang.reflect.Field;
    4.34 -import java.net.URL;
    4.35 -import java.net.URLClassLoader;
    4.36 -import java.util.ArrayList;
    4.37 -import java.util.jar.JarFile;
    4.38 -
    4.39 -/**
    4.40 - * A URLClassLoader that also implements Closeable.
    4.41 - * Reflection is used to access internal data structures in the URLClassLoader,
    4.42 - * since no public API exists for this purpose. Therefore this code is somewhat
    4.43 - * fragile. Caveat emptor.
    4.44 - * @throws Error if the internal data structures are not as expected.
    4.45 - *
    4.46 - *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    4.47 - *  you write code that depends on this, you do so at your own risk.
    4.48 - *  This code and its internal interfaces are subject to change or
    4.49 - *  deletion without notice.</b>
    4.50 - */
    4.51 -class CloseableURLClassLoader
    4.52 -        extends URLClassLoader implements Closeable {
    4.53 -    CloseableURLClassLoader(URL[] urls, ClassLoader parent) throws Error {
    4.54 -        super(urls, parent);
    4.55 -        try {
    4.56 -            getLoaders(); //proactive check that URLClassLoader is as expected
    4.57 -        } catch (Throwable t) {
    4.58 -            throw new Error("cannot create CloseableURLClassLoader", t);
    4.59 -        }
    4.60 -    }
    4.61 -
    4.62 -    /**
    4.63 -     * Close any jar files that may have been opened by the class loader.
    4.64 -     * Reflection is used to access the jar files in the URLClassLoader's
    4.65 -     * internal data structures.
    4.66 -     * @throws java.io.IOException if the jar files cannot be found for any
    4.67 -     * reson, or if closing the jar file itself causes an IOException.
    4.68 -     */
    4.69 -    public void close() throws IOException {
    4.70 -        try {
    4.71 -            for (Object l: getLoaders()) {
    4.72 -                if (l.getClass().getName().equals("sun.misc.URLClassPath$JarLoader")) {
    4.73 -                    Field jarField = l.getClass().getDeclaredField("jar");
    4.74 -                    JarFile jar = (JarFile) getField(l, jarField);
    4.75 -                    if (jar != null) {
    4.76 -                        //System.err.println("CloseableURLClassLoader: closing " + jar);
    4.77 -                        jar.close();
    4.78 -                    }
    4.79 -                }
    4.80 -            }
    4.81 -        } catch (Throwable t) {
    4.82 -            IOException e = new IOException("cannot close class loader");
    4.83 -            e.initCause(t);
    4.84 -            throw e;
    4.85 -        }
    4.86 -    }
    4.87 -
    4.88 -    private ArrayList<?> getLoaders()
    4.89 -            throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException
    4.90 -    {
    4.91 -        Field ucpField = URLClassLoader.class.getDeclaredField("ucp");
    4.92 -        Object urlClassPath = getField(this, ucpField);
    4.93 -        if (urlClassPath == null)
    4.94 -            throw new AssertionError("urlClassPath not set in URLClassLoader");
    4.95 -        Field loadersField = urlClassPath.getClass().getDeclaredField("loaders");
    4.96 -        return (ArrayList<?>) getField(urlClassPath, loadersField);
    4.97 -    }
    4.98 -
    4.99 -    private Object getField(Object o, Field f)
   4.100 -            throws IllegalArgumentException, IllegalAccessException {
   4.101 -        boolean prev = f.isAccessible();
   4.102 -        try {
   4.103 -            f.setAccessible(true);
   4.104 -            return f.get(o);
   4.105 -        } finally {
   4.106 -            f.setAccessible(prev);
   4.107 -        }
   4.108 -    }
   4.109 -
   4.110 -}
     5.1 --- a/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Thu Dec 10 20:35:31 2009 -0800
     5.2 +++ b/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Fri Dec 11 14:26:27 2009 -0800
     5.3 @@ -26,29 +26,16 @@
     5.4  package com.sun.tools.javac.file;
     5.5  
     5.6  import java.io.ByteArrayOutputStream;
     5.7 -import java.io.Closeable;
     5.8  import java.io.File;
     5.9 -import java.io.FileInputStream;
    5.10  import java.io.FileNotFoundException;
    5.11  import java.io.IOException;
    5.12 -import java.io.InputStream;
    5.13  import java.io.OutputStreamWriter;
    5.14 -import java.lang.ref.SoftReference;
    5.15 -import java.lang.reflect.Constructor;
    5.16  import java.net.MalformedURLException;
    5.17  import java.net.URI;
    5.18  import java.net.URISyntaxException;
    5.19  import java.net.URL;
    5.20 -import java.net.URLClassLoader;
    5.21 -import java.nio.ByteBuffer;
    5.22  import java.nio.CharBuffer;
    5.23 -import java.nio.channels.FileChannel;
    5.24  import java.nio.charset.Charset;
    5.25 -import java.nio.charset.CharsetDecoder;
    5.26 -import java.nio.charset.CoderResult;
    5.27 -import java.nio.charset.CodingErrorAction;
    5.28 -import java.nio.charset.IllegalCharsetNameException;
    5.29 -import java.nio.charset.UnsupportedCharsetException;
    5.30  import java.util.ArrayList;
    5.31  import java.util.Arrays;
    5.32  import java.util.Collection;
    5.33 @@ -66,18 +53,13 @@
    5.34  import javax.tools.JavaFileObject;
    5.35  import javax.tools.StandardJavaFileManager;
    5.36  
    5.37 -import com.sun.tools.javac.code.Source;
    5.38  import com.sun.tools.javac.file.RelativePath.RelativeFile;
    5.39  import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
    5.40 -import com.sun.tools.javac.main.JavacOption;
    5.41  import com.sun.tools.javac.main.OptionName;
    5.42 -import com.sun.tools.javac.main.RecognizedOptions;
    5.43 +import com.sun.tools.javac.util.BaseFileManager;
    5.44  import com.sun.tools.javac.util.Context;
    5.45 -import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
    5.46  import com.sun.tools.javac.util.List;
    5.47  import com.sun.tools.javac.util.ListBuffer;
    5.48 -import com.sun.tools.javac.util.Log;
    5.49 -import com.sun.tools.javac.util.Options;
    5.50  
    5.51  import static javax.tools.StandardLocation.*;
    5.52  import static com.sun.tools.javac.main.OptionName.*;
    5.53 @@ -91,7 +73,7 @@
    5.54   * This code and its internal interfaces are subject to change or
    5.55   * deletion without notice.</b>
    5.56   */
    5.57 -public class JavacFileManager implements StandardJavaFileManager {
    5.58 +public class JavacFileManager extends BaseFileManager implements StandardJavaFileManager {
    5.59  
    5.60      boolean useZipFileIndex;
    5.61  
    5.62 @@ -102,17 +84,10 @@
    5.63              return buffer.toString().toCharArray();
    5.64      }
    5.65  
    5.66 -    /**
    5.67 -     * The log to be used for error reporting.
    5.68 -     */
    5.69 -    protected Log log;
    5.70 -
    5.71      /** Encapsulates knowledge of paths
    5.72       */
    5.73      private Paths paths;
    5.74  
    5.75 -    private Options options;
    5.76 -
    5.77      private FSInfo fsInfo;
    5.78  
    5.79      private final File uninited = new File("U N I N I T E D");
    5.80 @@ -134,12 +109,6 @@
    5.81  
    5.82      protected boolean mmappedIO;
    5.83      protected boolean ignoreSymbolFile;
    5.84 -    protected String classLoaderClass;
    5.85 -
    5.86 -    /**
    5.87 -     * User provided charset (through javax.tools).
    5.88 -     */
    5.89 -    protected Charset charset;
    5.90  
    5.91      /**
    5.92       * Register a Context.Factory to create a JavacFileManager.
    5.93 @@ -157,18 +126,18 @@
    5.94       * it as the JavaFileManager for that context.
    5.95       */
    5.96      public JavacFileManager(Context context, boolean register, Charset charset) {
    5.97 +        super(charset);
    5.98          if (register)
    5.99              context.put(JavaFileManager.class, this);
   5.100 -        byteBufferCache = new ByteBufferCache();
   5.101 -        this.charset = charset;
   5.102          setContext(context);
   5.103      }
   5.104  
   5.105      /**
   5.106       * Set the context for JavacFileManager.
   5.107       */
   5.108 +    @Override
   5.109      public void setContext(Context context) {
   5.110 -        log = Log.instance(context);
   5.111 +        super.setContext(context);
   5.112          if (paths == null) {
   5.113              paths = Paths.instance(context);
   5.114          } else {
   5.115 @@ -177,14 +146,12 @@
   5.116              paths.setContext(context);
   5.117          }
   5.118  
   5.119 -        options = Options.instance(context);
   5.120          fsInfo = FSInfo.instance(context);
   5.121  
   5.122          useZipFileIndex = System.getProperty("useJavaUtilZip") == null;// TODO: options.get("useJavaUtilZip") == null;
   5.123  
   5.124          mmappedIO = options.get("mmappedIO") != null;
   5.125          ignoreSymbolFile = options.get("ignore.symbol.file") != null;
   5.126 -        classLoaderClass = options.get("procloader");
   5.127      }
   5.128  
   5.129      public JavaFileObject getFileForInput(String name) {
   5.130 @@ -214,17 +181,6 @@
   5.131          return getJavaFileObjectsFromStrings(Arrays.asList(nullCheck(names)));
   5.132      }
   5.133  
   5.134 -    protected JavaFileObject.Kind getKind(String extension) {
   5.135 -        if (extension.equals(JavaFileObject.Kind.CLASS.extension))
   5.136 -            return JavaFileObject.Kind.CLASS;
   5.137 -        else if (extension.equals(JavaFileObject.Kind.SOURCE.extension))
   5.138 -            return JavaFileObject.Kind.SOURCE;
   5.139 -        else if (extension.equals(JavaFileObject.Kind.HTML.extension))
   5.140 -            return JavaFileObject.Kind.HTML;
   5.141 -        else
   5.142 -            return JavaFileObject.Kind.OTHER;
   5.143 -    }
   5.144 -
   5.145      private static boolean isValidName(String name) {
   5.146          // Arguably, isValidName should reject keywords (such as in SourceVersion.isName() ),
   5.147          // but the set of keywords depends on the source level, and we don't want
   5.148 @@ -359,9 +315,7 @@
   5.149      }
   5.150  
   5.151      private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
   5.152 -        int lastDot = s.lastIndexOf(".");
   5.153 -        String extn = (lastDot == -1 ? s : s.substring(lastDot));
   5.154 -        JavaFileObject.Kind kind = getKind(extn);
   5.155 +        JavaFileObject.Kind kind = getKind(s);
   5.156          return fileKinds.contains(kind);
   5.157      }
   5.158  
   5.159 @@ -564,18 +518,6 @@
   5.160          }
   5.161      }
   5.162  
   5.163 -    CharBuffer getCachedContent(JavaFileObject file) {
   5.164 -        SoftReference<CharBuffer> r = contentCache.get(file);
   5.165 -        return (r == null ? null : r.get());
   5.166 -    }
   5.167 -
   5.168 -    void cache(JavaFileObject file, CharBuffer cb) {
   5.169 -        contentCache.put(file, new SoftReference<CharBuffer>(cb));
   5.170 -    }
   5.171 -
   5.172 -    private final Map<JavaFileObject, SoftReference<CharBuffer>> contentCache
   5.173 -            = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
   5.174 -
   5.175      private String defaultEncodingName;
   5.176      private String getDefaultEncodingName() {
   5.177          if (defaultEncodingName == null) {
   5.178 @@ -585,161 +527,6 @@
   5.179          return defaultEncodingName;
   5.180      }
   5.181  
   5.182 -    protected String getEncodingName() {
   5.183 -        String encName = options.get(OptionName.ENCODING);
   5.184 -        if (encName == null)
   5.185 -            return getDefaultEncodingName();
   5.186 -        else
   5.187 -            return encName;
   5.188 -    }
   5.189 -
   5.190 -    protected Source getSource() {
   5.191 -        String sourceName = options.get(OptionName.SOURCE);
   5.192 -        Source source = null;
   5.193 -        if (sourceName != null)
   5.194 -            source = Source.lookup(sourceName);
   5.195 -        return (source != null ? source : Source.DEFAULT);
   5.196 -    }
   5.197 -
   5.198 -    /**
   5.199 -     * Make a byte buffer from an input stream.
   5.200 -     */
   5.201 -    ByteBuffer makeByteBuffer(InputStream in)
   5.202 -        throws IOException {
   5.203 -        int limit = in.available();
   5.204 -        if (mmappedIO && in instanceof FileInputStream) {
   5.205 -            // Experimental memory mapped I/O
   5.206 -            FileInputStream fin = (FileInputStream)in;
   5.207 -            return fin.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, limit);
   5.208 -        }
   5.209 -        if (limit < 1024) limit = 1024;
   5.210 -        ByteBuffer result = byteBufferCache.get(limit);
   5.211 -        int position = 0;
   5.212 -        while (in.available() != 0) {
   5.213 -            if (position >= limit)
   5.214 -                // expand buffer
   5.215 -                result = ByteBuffer.
   5.216 -                    allocate(limit <<= 1).
   5.217 -                    put((ByteBuffer)result.flip());
   5.218 -            int count = in.read(result.array(),
   5.219 -                position,
   5.220 -                limit - position);
   5.221 -            if (count < 0) break;
   5.222 -            result.position(position += count);
   5.223 -        }
   5.224 -        return (ByteBuffer)result.flip();
   5.225 -    }
   5.226 -
   5.227 -    void recycleByteBuffer(ByteBuffer bb) {
   5.228 -        byteBufferCache.put(bb);
   5.229 -    }
   5.230 -
   5.231 -    /**
   5.232 -     * A single-element cache of direct byte buffers.
   5.233 -     */
   5.234 -    private static class ByteBufferCache {
   5.235 -        private ByteBuffer cached;
   5.236 -        ByteBuffer get(int capacity) {
   5.237 -            if (capacity < 20480) capacity = 20480;
   5.238 -            ByteBuffer result =
   5.239 -                (cached != null && cached.capacity() >= capacity)
   5.240 -                ? (ByteBuffer)cached.clear()
   5.241 -                : ByteBuffer.allocate(capacity + capacity>>1);
   5.242 -            cached = null;
   5.243 -            return result;
   5.244 -        }
   5.245 -        void put(ByteBuffer x) {
   5.246 -            cached = x;
   5.247 -        }
   5.248 -    }
   5.249 -
   5.250 -    private final ByteBufferCache byteBufferCache;
   5.251 -
   5.252 -    CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
   5.253 -        Charset cs = (this.charset == null)
   5.254 -            ? Charset.forName(encodingName)
   5.255 -            : this.charset;
   5.256 -        CharsetDecoder decoder = cs.newDecoder();
   5.257 -
   5.258 -        CodingErrorAction action;
   5.259 -        if (ignoreEncodingErrors)
   5.260 -            action = CodingErrorAction.REPLACE;
   5.261 -        else
   5.262 -            action = CodingErrorAction.REPORT;
   5.263 -
   5.264 -        return decoder
   5.265 -            .onMalformedInput(action)
   5.266 -            .onUnmappableCharacter(action);
   5.267 -    }
   5.268 -
   5.269 -    /**
   5.270 -     * Decode a ByteBuffer into a CharBuffer.
   5.271 -     */
   5.272 -    CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
   5.273 -        String encodingName = getEncodingName();
   5.274 -        CharsetDecoder decoder;
   5.275 -        try {
   5.276 -            decoder = getDecoder(encodingName, ignoreEncodingErrors);
   5.277 -        } catch (IllegalCharsetNameException e) {
   5.278 -            log.error("unsupported.encoding", encodingName);
   5.279 -            return (CharBuffer)CharBuffer.allocate(1).flip();
   5.280 -        } catch (UnsupportedCharsetException e) {
   5.281 -            log.error("unsupported.encoding", encodingName);
   5.282 -            return (CharBuffer)CharBuffer.allocate(1).flip();
   5.283 -        }
   5.284 -
   5.285 -        // slightly overestimate the buffer size to avoid reallocation.
   5.286 -        float factor =
   5.287 -            decoder.averageCharsPerByte() * 0.8f +
   5.288 -            decoder.maxCharsPerByte() * 0.2f;
   5.289 -        CharBuffer dest = CharBuffer.
   5.290 -            allocate(10 + (int)(inbuf.remaining()*factor));
   5.291 -
   5.292 -        while (true) {
   5.293 -            CoderResult result = decoder.decode(inbuf, dest, true);
   5.294 -            dest.flip();
   5.295 -
   5.296 -            if (result.isUnderflow()) { // done reading
   5.297 -                // make sure there is at least one extra character
   5.298 -                if (dest.limit() == dest.capacity()) {
   5.299 -                    dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
   5.300 -                    dest.flip();
   5.301 -                }
   5.302 -                return dest;
   5.303 -            } else if (result.isOverflow()) { // buffer too small; expand
   5.304 -                int newCapacity =
   5.305 -                    10 + dest.capacity() +
   5.306 -                    (int)(inbuf.remaining()*decoder.maxCharsPerByte());
   5.307 -                dest = CharBuffer.allocate(newCapacity).put(dest);
   5.308 -            } else if (result.isMalformed() || result.isUnmappable()) {
   5.309 -                // bad character in input
   5.310 -
   5.311 -                // report coding error (warn only pre 1.5)
   5.312 -                if (!getSource().allowEncodingErrors()) {
   5.313 -                    log.error(new SimpleDiagnosticPosition(dest.limit()),
   5.314 -                              "illegal.char.for.encoding",
   5.315 -                              charset == null ? encodingName : charset.name());
   5.316 -                } else {
   5.317 -                    log.warning(new SimpleDiagnosticPosition(dest.limit()),
   5.318 -                                "illegal.char.for.encoding",
   5.319 -                                charset == null ? encodingName : charset.name());
   5.320 -                }
   5.321 -
   5.322 -                // skip past the coding error
   5.323 -                inbuf.position(inbuf.position() + result.length());
   5.324 -
   5.325 -                // undo the flip() to prepare the output buffer
   5.326 -                // for more translation
   5.327 -                dest.position(dest.limit());
   5.328 -                dest.limit(dest.capacity());
   5.329 -                dest.put((char)0xfffd); // backward compatible
   5.330 -            } else {
   5.331 -                throw new AssertionError(result);
   5.332 -            }
   5.333 -        }
   5.334 -        // unreached
   5.335 -    }
   5.336 -
   5.337      public ClassLoader getClassLoader(Location location) {
   5.338          nullCheck(location);
   5.339          Iterable<? extends File> path = getLocation(location);
   5.340 @@ -754,39 +541,7 @@
   5.341              }
   5.342          }
   5.343  
   5.344 -        URL[] urls = lb.toArray(new URL[lb.size()]);
   5.345 -        ClassLoader thisClassLoader = getClass().getClassLoader();
   5.346 -
   5.347 -        // Bug: 6558476
   5.348 -        // Ideally, ClassLoader should be Closeable, but before JDK7 it is not.
   5.349 -        // On older versions, try the following, to get a closeable classloader.
   5.350 -
   5.351 -        // 1: Allow client to specify the class to use via hidden option
   5.352 -        if (classLoaderClass != null) {
   5.353 -            try {
   5.354 -                Class<? extends ClassLoader> loader =
   5.355 -                        Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
   5.356 -                Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
   5.357 -                Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
   5.358 -                return constr.newInstance(new Object[] { urls, thisClassLoader });
   5.359 -            } catch (Throwable t) {
   5.360 -                // ignore errors loading user-provided class loader, fall through
   5.361 -            }
   5.362 -        }
   5.363 -
   5.364 -        // 2: If URLClassLoader implements Closeable, use that.
   5.365 -        if (Closeable.class.isAssignableFrom(URLClassLoader.class))
   5.366 -            return new URLClassLoader(urls, thisClassLoader);
   5.367 -
   5.368 -        // 3: Try using private reflection-based CloseableURLClassLoader
   5.369 -        try {
   5.370 -            return new CloseableURLClassLoader(urls, thisClassLoader);
   5.371 -        } catch (Throwable t) {
   5.372 -            // ignore errors loading workaround class loader, fall through
   5.373 -        }
   5.374 -
   5.375 -        // 4: If all else fails, use plain old standard URLClassLoader
   5.376 -        return new URLClassLoader(urls, thisClassLoader);
   5.377 +        return getClassLoader(lb.toArray(new URL[lb.size()]));
   5.378      }
   5.379  
   5.380      public Iterable<JavaFileObject> list(Location location,
   5.381 @@ -836,38 +591,6 @@
   5.382          return a.equals(b);
   5.383      }
   5.384  
   5.385 -    public boolean handleOption(String current, Iterator<String> remaining) {
   5.386 -        for (JavacOption o: javacFileManagerOptions) {
   5.387 -            if (o.matches(current))  {
   5.388 -                if (o.hasArg()) {
   5.389 -                    if (remaining.hasNext()) {
   5.390 -                        if (!o.process(options, current, remaining.next()))
   5.391 -                            return true;
   5.392 -                    }
   5.393 -                } else {
   5.394 -                    if (!o.process(options, current))
   5.395 -                        return true;
   5.396 -                }
   5.397 -                // operand missing, or process returned false
   5.398 -                throw new IllegalArgumentException(current);
   5.399 -            }
   5.400 -        }
   5.401 -
   5.402 -        return false;
   5.403 -    }
   5.404 -    // where
   5.405 -        private static JavacOption[] javacFileManagerOptions =
   5.406 -            RecognizedOptions.getJavacFileManagerOptions(
   5.407 -            new RecognizedOptions.GrumpyHelper());
   5.408 -
   5.409 -    public int isSupportedOption(String option) {
   5.410 -        for (JavacOption o : javacFileManagerOptions) {
   5.411 -            if (o.matches(option))
   5.412 -                return o.hasArg() ? 1 : 0;
   5.413 -        }
   5.414 -        return -1;
   5.415 -    }
   5.416 -
   5.417      public boolean hasLocation(Location location) {
   5.418          return getLocation(location) != null;
   5.419      }
   5.420 @@ -1115,15 +838,4 @@
   5.421          }
   5.422          throw new IllegalArgumentException("Invalid relative path: " + file);
   5.423      }
   5.424 -
   5.425 -    private static <T> T nullCheck(T o) {
   5.426 -        o.getClass(); // null check
   5.427 -        return o;
   5.428 -    }
   5.429 -
   5.430 -    private static <T> Iterable<T> nullCheck(Iterable<T> it) {
   5.431 -        for (T t : it)
   5.432 -            t.getClass(); // null check
   5.433 -        return it;
   5.434 -    }
   5.435  }
     6.1 --- a/src/share/classes/com/sun/tools/javac/file/Paths.java	Thu Dec 10 20:35:31 2009 -0800
     6.2 +++ b/src/share/classes/com/sun/tools/javac/file/Paths.java	Fri Dec 11 14:26:27 2009 -0800
     6.3 @@ -66,7 +66,7 @@
     6.4       *  @param context the context
     6.5       *  @return the Paths instance for this context
     6.6       */
     6.7 -    static Paths instance(Context context) {
     6.8 +    public static Paths instance(Context context) {
     6.9          Paths instance = context.get(pathsKey);
    6.10          if (instance == null)
    6.11              instance = new Paths(context);
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java	Fri Dec 11 14:26:27 2009 -0800
     7.3 @@ -0,0 +1,543 @@
     7.4 +/*
     7.5 + * Copyright 2009 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.nio;
    7.30 +
    7.31 +
    7.32 +import java.io.File;
    7.33 +import java.io.FileNotFoundException;
    7.34 +import java.io.IOException;
    7.35 +import java.net.MalformedURLException;
    7.36 +import java.net.URL;
    7.37 +import java.nio.charset.Charset;
    7.38 +import java.nio.file.Files;
    7.39 +import java.nio.file.FileSystem;
    7.40 +import java.nio.file.FileSystems;
    7.41 +import java.nio.file.FileVisitOption;
    7.42 +import java.nio.file.FileVisitResult;
    7.43 +import java.nio.file.Path;
    7.44 +import java.nio.file.SimpleFileVisitor;
    7.45 +import java.nio.file.attribute.Attributes;
    7.46 +import java.nio.file.attribute.BasicFileAttributes;
    7.47 +import java.util.ArrayList;
    7.48 +import java.util.Arrays;
    7.49 +import java.util.Collection;
    7.50 +import java.util.Collections;
    7.51 +import java.util.EnumSet;
    7.52 +import java.util.HashMap;
    7.53 +import java.util.Iterator;
    7.54 +import java.util.LinkedHashSet;
    7.55 +import java.util.Map;
    7.56 +import java.util.Set;
    7.57 +import javax.lang.model.SourceVersion;
    7.58 +import javax.tools.FileObject;
    7.59 +import javax.tools.JavaFileManager;
    7.60 +import javax.tools.JavaFileObject;
    7.61 +import javax.tools.JavaFileObject.Kind;
    7.62 +import javax.tools.StandardLocation;
    7.63 +
    7.64 +import static java.nio.file.FileVisitOption.*;
    7.65 +import static javax.tools.StandardLocation.*;
    7.66 +
    7.67 +import com.sun.tools.javac.file.Paths;
    7.68 +import com.sun.tools.javac.util.BaseFileManager;
    7.69 +import com.sun.tools.javac.util.Context;
    7.70 +import com.sun.tools.javac.util.List;
    7.71 +import com.sun.tools.javac.util.ListBuffer;
    7.72 +
    7.73 +import static com.sun.tools.javac.main.OptionName.*;
    7.74 +
    7.75 +
    7.76 +// NOTE the imports carefully for this compilation unit.
    7.77 +//
    7.78 +// Path:  java.nio.file.Path -- the new NIO type for which this file manager exists
    7.79 +//
    7.80 +// Paths: com.sun.tools.javac.file.Paths -- legacy javac type for handling path options
    7.81 +//      The other Paths (java.nio.file.Paths) is not used
    7.82 +
    7.83 +// NOTE this and related classes depend on new API in JDK 7.
    7.84 +// This requires special handling while bootstrapping the JDK build,
    7.85 +// when these classes might not yet have been compiled. To workaround
    7.86 +// this, the build arranges to make stubs of these classes available
    7.87 +// when compiling this and related classes. The set of stub files
    7.88 +// is specified in make/build.properties.
    7.89 +
    7.90 +/**
    7.91 + *  Implementation of PathFileManager: a JavaFileManager based on the use
    7.92 + *  of java.nio.file.Path.
    7.93 + *
    7.94 + *  <p>Just as a Path is somewhat analagous to a File, so too is this
    7.95 + *  JavacPathFileManager analogous to JavacFileManager, as it relates to the
    7.96 + *  support of FileObjects based on File objects (i.e. just RegularFileObject,
    7.97 + *  not ZipFileObject and its variants.)
    7.98 + *
    7.99 + *  <p>The default values for the standard locations supported by this file
   7.100 + *  manager are the same as the default values provided by JavacFileManager --
   7.101 + *  i.e. as determined by the javac.file.Paths class. To override these values,
   7.102 + *  call {@link #setLocation}.
   7.103 + *
   7.104 + *  <p>To reduce confusion with Path objects, the locations such as "class path",
   7.105 + *  "source path", etc, are generically referred to here as "search paths".
   7.106 + *
   7.107 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
   7.108 + *  you write code that depends on this, you do so at your own risk.
   7.109 + *  This code and its internal interfaces are subject to change or
   7.110 + *  deletion without notice.</b>
   7.111 + */
   7.112 +public class JavacPathFileManager extends BaseFileManager implements PathFileManager {
   7.113 +    protected FileSystem defaultFileSystem;
   7.114 +
   7.115 +    /**
   7.116 +     * Create a JavacPathFileManager using a given context, optionally registering
   7.117 +     * it as the JavaFileManager for that context.
   7.118 +     */
   7.119 +    public JavacPathFileManager(Context context, boolean register, Charset charset) {
   7.120 +        super(charset);
   7.121 +        if (register)
   7.122 +            context.put(JavaFileManager.class, this);
   7.123 +        pathsForLocation = new HashMap<Location, PathsForLocation>();
   7.124 +        fileSystems = new HashMap<Path,FileSystem>();
   7.125 +        setContext(context);
   7.126 +    }
   7.127 +
   7.128 +    /**
   7.129 +     * Set the context for JavacPathFileManager.
   7.130 +     */
   7.131 +    @Override
   7.132 +    protected void setContext(Context context) {
   7.133 +        super.setContext(context);
   7.134 +        searchPaths = Paths.instance(context);
   7.135 +    }
   7.136 +
   7.137 +    @Override
   7.138 +    public FileSystem getDefaultFileSystem() {
   7.139 +        if (defaultFileSystem == null)
   7.140 +            defaultFileSystem = FileSystems.getDefault();
   7.141 +        return defaultFileSystem;
   7.142 +    }
   7.143 +
   7.144 +    @Override
   7.145 +    public void setDefaultFileSystem(FileSystem fs) {
   7.146 +        defaultFileSystem = fs;
   7.147 +    }
   7.148 +
   7.149 +    @Override
   7.150 +    public void flush() throws IOException {
   7.151 +        contentCache.clear();
   7.152 +    }
   7.153 +
   7.154 +    @Override
   7.155 +    public void close() throws IOException {
   7.156 +        for (FileSystem fs: fileSystems.values())
   7.157 +            fs.close();
   7.158 +    }
   7.159 +
   7.160 +    @Override
   7.161 +    public ClassLoader getClassLoader(Location location) {
   7.162 +        nullCheck(location);
   7.163 +        Iterable<? extends Path> path = getLocation(location);
   7.164 +        if (path == null)
   7.165 +            return null;
   7.166 +        ListBuffer<URL> lb = new ListBuffer<URL>();
   7.167 +        for (Path p: path) {
   7.168 +            try {
   7.169 +                lb.append(p.toUri().toURL());
   7.170 +            } catch (MalformedURLException e) {
   7.171 +                throw new AssertionError(e);
   7.172 +            }
   7.173 +        }
   7.174 +
   7.175 +        return getClassLoader(lb.toArray(new URL[lb.size()]));
   7.176 +    }
   7.177 +
   7.178 +    // <editor-fold defaultstate="collapsed" desc="Location handling">
   7.179 +
   7.180 +    public boolean hasLocation(Location location) {
   7.181 +        return (getLocation(location) != null);
   7.182 +    }
   7.183 +
   7.184 +    public Iterable<? extends Path> getLocation(Location location) {
   7.185 +        nullCheck(location);
   7.186 +        lazyInitSearchPaths();
   7.187 +        PathsForLocation path = pathsForLocation.get(location);
   7.188 +        if (path == null && !pathsForLocation.containsKey(location)) {
   7.189 +            setDefaultForLocation(location);
   7.190 +            path = pathsForLocation.get(location);
   7.191 +        }
   7.192 +        return path;
   7.193 +    }
   7.194 +
   7.195 +    private Path getOutputLocation(Location location) {
   7.196 +        Iterable<? extends Path> paths = getLocation(location);
   7.197 +        return (paths == null ? null : paths.iterator().next());
   7.198 +    }
   7.199 +
   7.200 +    public void setLocation(Location location, Iterable<? extends Path> searchPath)
   7.201 +            throws IOException
   7.202 +    {
   7.203 +        nullCheck(location);
   7.204 +        lazyInitSearchPaths();
   7.205 +        if (searchPath == null) {
   7.206 +            setDefaultForLocation(location);
   7.207 +        } else {
   7.208 +            if (location.isOutputLocation())
   7.209 +                checkOutputPath(searchPath);
   7.210 +            PathsForLocation pl = new PathsForLocation();
   7.211 +            for (Path p: searchPath)
   7.212 +                pl.add(p);  // TODO -Xlint:path warn if path not found
   7.213 +            pathsForLocation.put(location, pl);
   7.214 +        }
   7.215 +    }
   7.216 +
   7.217 +    private void checkOutputPath(Iterable<? extends Path> searchPath) throws IOException {
   7.218 +        Iterator<? extends Path> pathIter = searchPath.iterator();
   7.219 +        if (!pathIter.hasNext())
   7.220 +            throw new IllegalArgumentException("empty path for directory");
   7.221 +        Path path = pathIter.next();
   7.222 +        if (pathIter.hasNext())
   7.223 +            throw new IllegalArgumentException("path too long for directory");
   7.224 +        if (!path.exists())
   7.225 +            throw new FileNotFoundException(path + ": does not exist");
   7.226 +        else if (!isDirectory(path))
   7.227 +            throw new IOException(path + ": not a directory");
   7.228 +    }
   7.229 +
   7.230 +    private void setDefaultForLocation(Location locn) {
   7.231 +        Collection<File> files = null;
   7.232 +        if (locn instanceof StandardLocation) {
   7.233 +            switch ((StandardLocation) locn) {
   7.234 +                case CLASS_PATH:
   7.235 +                    files = searchPaths.userClassPath();
   7.236 +                    break;
   7.237 +                case PLATFORM_CLASS_PATH:
   7.238 +                    files = searchPaths.bootClassPath();
   7.239 +                    break;
   7.240 +                case SOURCE_PATH:
   7.241 +                    files = searchPaths.sourcePath();
   7.242 +                    break;
   7.243 +                case CLASS_OUTPUT: {
   7.244 +                    String arg = options.get(D);
   7.245 +                    files = (arg == null ? null : Collections.singleton(new File(arg)));
   7.246 +                    break;
   7.247 +                }
   7.248 +                case SOURCE_OUTPUT: {
   7.249 +                    String arg = options.get(S);
   7.250 +                    files = (arg == null ? null : Collections.singleton(new File(arg)));
   7.251 +                    break;
   7.252 +                }
   7.253 +            }
   7.254 +        }
   7.255 +
   7.256 +        PathsForLocation pl = new PathsForLocation();
   7.257 +        if (files != null) {
   7.258 +            for (File f: files)
   7.259 +                pl.add(f.toPath());
   7.260 +        }
   7.261 +        pathsForLocation.put(locn, pl);
   7.262 +    }
   7.263 +
   7.264 +    private void lazyInitSearchPaths() {
   7.265 +        if (!inited) {
   7.266 +            setDefaultForLocation(PLATFORM_CLASS_PATH);
   7.267 +            setDefaultForLocation(CLASS_PATH);
   7.268 +            setDefaultForLocation(SOURCE_PATH);
   7.269 +            inited = true;
   7.270 +        }
   7.271 +    }
   7.272 +    // where
   7.273 +        private boolean inited = false;
   7.274 +
   7.275 +    private Map<Location, PathsForLocation> pathsForLocation;
   7.276 +    private Paths searchPaths;
   7.277 +
   7.278 +    private static class PathsForLocation extends LinkedHashSet<Path> {
   7.279 +        private static final long serialVersionUID = 6788510222394486733L;
   7.280 +    }
   7.281 +
   7.282 +    // </editor-fold>
   7.283 +
   7.284 +    // <editor-fold defaultstate="collapsed" desc="FileObject handling">
   7.285 +
   7.286 +    @Override
   7.287 +    public Path getPath(FileObject fo) {
   7.288 +        nullCheck(fo);
   7.289 +        if (!(fo instanceof PathFileObject))
   7.290 +            throw new IllegalArgumentException();
   7.291 +        return ((PathFileObject) fo).getPath();
   7.292 +    }
   7.293 +
   7.294 +    @Override
   7.295 +    public boolean isSameFile(FileObject a, FileObject b) {
   7.296 +        nullCheck(a);
   7.297 +        nullCheck(b);
   7.298 +        if (!(a instanceof PathFileObject))
   7.299 +            throw new IllegalArgumentException("Not supported: " + a);
   7.300 +        if (!(b instanceof PathFileObject))
   7.301 +            throw new IllegalArgumentException("Not supported: " + b);
   7.302 +        return ((PathFileObject) a).isSameFile((PathFileObject) b);
   7.303 +    }
   7.304 +
   7.305 +    @Override
   7.306 +    public Iterable<JavaFileObject> list(Location location,
   7.307 +            String packageName, Set<Kind> kinds, boolean recurse)
   7.308 +            throws IOException {
   7.309 +        // validatePackageName(packageName);
   7.310 +        nullCheck(packageName);
   7.311 +        nullCheck(kinds);
   7.312 +
   7.313 +        Iterable<? extends Path> paths = getLocation(location);
   7.314 +        if (paths == null)
   7.315 +            return List.nil();
   7.316 +        ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
   7.317 +
   7.318 +        for (Path path : paths)
   7.319 +            list(path, packageName, kinds, recurse, results);
   7.320 +
   7.321 +        return results.toList();
   7.322 +    }
   7.323 +
   7.324 +    private void list(Path path, String packageName, final Set<Kind> kinds,
   7.325 +            boolean recurse, final ListBuffer<JavaFileObject> results)
   7.326 +            throws IOException {
   7.327 +        if (!path.exists())
   7.328 +            return;
   7.329 +
   7.330 +        final Path pathDir;
   7.331 +        if (isDirectory(path))
   7.332 +            pathDir = path;
   7.333 +        else {
   7.334 +            FileSystem fs = getFileSystem(path);
   7.335 +            if (fs == null)
   7.336 +                return;
   7.337 +            pathDir = fs.getRootDirectories().iterator().next();
   7.338 +        }
   7.339 +        String sep = path.getFileSystem().getSeparator();
   7.340 +        Path packageDir = packageName.isEmpty() ? pathDir
   7.341 +                : pathDir.resolve(packageName.replace(".", sep));
   7.342 +        if (!packageDir.exists())
   7.343 +            return;
   7.344 +
   7.345 +/* Alternate impl of list, superceded by use of Files.walkFileTree */
   7.346 +//        Deque<Path> queue = new LinkedList<Path>();
   7.347 +//        queue.add(packageDir);
   7.348 +//
   7.349 +//        Path dir;
   7.350 +//        while ((dir = queue.poll()) != null) {
   7.351 +//            DirectoryStream<Path> ds = dir.newDirectoryStream();
   7.352 +//            try {
   7.353 +//                for (Path p: ds) {
   7.354 +//                    String name = p.getName().toString();
   7.355 +//                    if (isDirectory(p)) {
   7.356 +//                        if (recurse && SourceVersion.isIdentifier(name)) {
   7.357 +//                            queue.add(p);
   7.358 +//                        }
   7.359 +//                    } else {
   7.360 +//                        if (kinds.contains(getKind(name))) {
   7.361 +//                            JavaFileObject fe =
   7.362 +//                                PathFileObject.createDirectoryPathFileObject(this, p, pathDir);
   7.363 +//                            results.append(fe);
   7.364 +//                        }
   7.365 +//                    }
   7.366 +//                }
   7.367 +//            } finally {
   7.368 +//                ds.close();
   7.369 +//            }
   7.370 +//        }
   7.371 +        int maxDepth = (recurse ? Integer.MAX_VALUE : 1);
   7.372 +        Set<FileVisitOption> opts = EnumSet.of(DETECT_CYCLES, FOLLOW_LINKS);
   7.373 +        Files.walkFileTree(packageDir, opts, maxDepth,
   7.374 +                new SimpleFileVisitor<Path>() {
   7.375 +            @Override
   7.376 +            public FileVisitResult preVisitDirectory(Path dir) {
   7.377 +                if (SourceVersion.isIdentifier(dir.getName().toString())) // JSR 292?
   7.378 +                    return FileVisitResult.CONTINUE;
   7.379 +                else
   7.380 +                    return FileVisitResult.SKIP_SUBTREE;
   7.381 +            }
   7.382 +
   7.383 +            @Override
   7.384 +            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
   7.385 +                if (attrs.isRegularFile() && kinds.contains(getKind(file.getName().toString()))) {
   7.386 +                    JavaFileObject fe =
   7.387 +                        PathFileObject.createDirectoryPathFileObject(
   7.388 +                            JavacPathFileManager.this, file, pathDir);
   7.389 +                    results.append(fe);
   7.390 +                }
   7.391 +                return FileVisitResult.CONTINUE;
   7.392 +            }
   7.393 +        });
   7.394 +    }
   7.395 +
   7.396 +    @Override
   7.397 +    public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
   7.398 +        Iterable<? extends Path> paths) {
   7.399 +        ArrayList<PathFileObject> result;
   7.400 +        if (paths instanceof Collection<?>)
   7.401 +            result = new ArrayList<PathFileObject>(((Collection<?>)paths).size());
   7.402 +        else
   7.403 +            result = new ArrayList<PathFileObject>();
   7.404 +        for (Path p: paths)
   7.405 +            result.add(PathFileObject.createSimplePathFileObject(this, nullCheck(p)));
   7.406 +        return result;
   7.407 +    }
   7.408 +
   7.409 +    @Override
   7.410 +    public Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths) {
   7.411 +        return getJavaFileObjectsFromPaths(Arrays.asList(nullCheck(paths)));
   7.412 +    }
   7.413 +
   7.414 +    @Override
   7.415 +    public JavaFileObject getJavaFileForInput(Location location,
   7.416 +            String className, Kind kind) throws IOException {
   7.417 +        return getFileForInput(location, getRelativePath(className, kind));
   7.418 +    }
   7.419 +
   7.420 +    @Override
   7.421 +    public FileObject getFileForInput(Location location,
   7.422 +            String packageName, String relativeName) throws IOException {
   7.423 +        return getFileForInput(location, getRelativePath(packageName, relativeName));
   7.424 +    }
   7.425 +
   7.426 +    private JavaFileObject getFileForInput(Location location, String relativePath)
   7.427 +            throws IOException {
   7.428 +        for (Path p: getLocation(location)) {
   7.429 +            if (isDirectory(p)) {
   7.430 +                Path f = resolve(p, relativePath);
   7.431 +                if (f.exists())
   7.432 +                    return PathFileObject.createDirectoryPathFileObject(this, f, p);
   7.433 +            } else {
   7.434 +                FileSystem fs = getFileSystem(p);
   7.435 +                if (fs != null) {
   7.436 +                    Path file = getPath(fs, relativePath);
   7.437 +                    if (file.exists())
   7.438 +                        return PathFileObject.createJarPathFileObject(this, file);
   7.439 +                }
   7.440 +            }
   7.441 +        }
   7.442 +        return null;
   7.443 +    }
   7.444 +
   7.445 +    @Override
   7.446 +    public JavaFileObject getJavaFileForOutput(Location location,
   7.447 +            String className, Kind kind, FileObject sibling) throws IOException {
   7.448 +        return getFileForOutput(location, getRelativePath(className, kind), sibling);
   7.449 +    }
   7.450 +
   7.451 +    @Override
   7.452 +    public FileObject getFileForOutput(Location location, String packageName,
   7.453 +            String relativeName, FileObject sibling)
   7.454 +            throws IOException {
   7.455 +        return getFileForOutput(location, getRelativePath(packageName, relativeName), sibling);
   7.456 +    }
   7.457 +
   7.458 +    private JavaFileObject getFileForOutput(Location location,
   7.459 +            String relativePath, FileObject sibling) {
   7.460 +        Path dir = getOutputLocation(location);
   7.461 +        if (dir == null) {
   7.462 +            if (location == CLASS_OUTPUT) {
   7.463 +                Path siblingDir = null;
   7.464 +                if (sibling != null && sibling instanceof PathFileObject) {
   7.465 +                    siblingDir = ((PathFileObject) sibling).getPath().getParent();
   7.466 +                }
   7.467 +                return PathFileObject.createSiblingPathFileObject(this,
   7.468 +                        siblingDir.resolve(getBaseName(relativePath)),
   7.469 +                        relativePath);
   7.470 +            } else if (location == SOURCE_OUTPUT) {
   7.471 +                dir = getOutputLocation(CLASS_OUTPUT);
   7.472 +            }
   7.473 +        }
   7.474 +
   7.475 +        Path file;
   7.476 +        if (dir != null) {
   7.477 +            file = resolve(dir, relativePath);
   7.478 +            return PathFileObject.createDirectoryPathFileObject(this, file, dir);
   7.479 +        } else {
   7.480 +            file = getPath(getDefaultFileSystem(), relativePath);
   7.481 +            return PathFileObject.createSimplePathFileObject(this, file);
   7.482 +        }
   7.483 +
   7.484 +    }
   7.485 +
   7.486 +    @Override
   7.487 +    public String inferBinaryName(Location location, JavaFileObject fo) {
   7.488 +        nullCheck(fo);
   7.489 +        // Need to match the path semantics of list(location, ...)
   7.490 +        Iterable<? extends Path> paths = getLocation(location);
   7.491 +        if (paths == null) {
   7.492 +            return null;
   7.493 +        }
   7.494 +
   7.495 +        if (!(fo instanceof PathFileObject))
   7.496 +            throw new IllegalArgumentException(fo.getClass().getName());
   7.497 +
   7.498 +        return ((PathFileObject) fo).inferBinaryName(paths);
   7.499 +    }
   7.500 +
   7.501 +    private FileSystem getFileSystem(Path p) throws IOException {
   7.502 +        FileSystem fs = fileSystems.get(p);
   7.503 +        if (fs == null) {
   7.504 +            fs = FileSystems.newFileSystem(p, Collections.<String,Void>emptyMap(), null);
   7.505 +            fileSystems.put(p, fs);
   7.506 +        }
   7.507 +        return fs;
   7.508 +    }
   7.509 +
   7.510 +    private Map<Path,FileSystem> fileSystems;
   7.511 +
   7.512 +    // </editor-fold>
   7.513 +
   7.514 +    // <editor-fold defaultstate="collapsed" desc="Utility methods">
   7.515 +
   7.516 +    private static String getRelativePath(String className, Kind kind) {
   7.517 +        return className.replace(".", "/") + kind.extension;
   7.518 +    }
   7.519 +
   7.520 +    private static String getRelativePath(String packageName, String relativeName) {
   7.521 +        return packageName.replace(".", "/") + relativeName;
   7.522 +    }
   7.523 +
   7.524 +    private static String getBaseName(String relativePath) {
   7.525 +        int lastSep = relativePath.lastIndexOf("/");
   7.526 +        return relativePath.substring(lastSep + 1); // safe if "/" not found
   7.527 +    }
   7.528 +
   7.529 +    private static boolean isDirectory(Path path) throws IOException {
   7.530 +        BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path);
   7.531 +        return attrs.isDirectory();
   7.532 +    }
   7.533 +
   7.534 +    private static Path getPath(FileSystem fs, String relativePath) {
   7.535 +        return fs.getPath(relativePath.replace("/", fs.getSeparator()));
   7.536 +    }
   7.537 +
   7.538 +    private static Path resolve(Path base, String relativePath) {
   7.539 +        FileSystem fs = base.getFileSystem();
   7.540 +        Path rp = fs.getPath(relativePath.replace("/", fs.getSeparator()));
   7.541 +        return base.resolve(rp);
   7.542 +    }
   7.543 +
   7.544 +    // </editor-fold>
   7.545 +
   7.546 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/share/classes/com/sun/tools/javac/nio/PathFileManager.java	Fri Dec 11 14:26:27 2009 -0800
     8.3 @@ -0,0 +1,125 @@
     8.4 +/*
     8.5 + * Copyright 2009 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.nio;
    8.30 +
    8.31 +import java.io.IOException;
    8.32 +import java.nio.file.FileSystem;
    8.33 +import java.nio.file.Path;
    8.34 +import javax.tools.FileObject;
    8.35 +import javax.tools.JavaFileManager;
    8.36 +import javax.tools.JavaFileObject;
    8.37 +
    8.38 +/**
    8.39 + *  File manager based on {@linkplain File java.nio.file.Path}.
    8.40 + *
    8.41 + *  Eventually, this should be moved to javax.tools.
    8.42 + *  Also, JavaCompiler might reasonably provide a method getPathFileManager,
    8.43 + *  similar to {@link javax.tools.JavaCompiler#getStandardFileManager
    8.44 + *  getStandardFileManager}. However, would need to be handled carefully
    8.45 + *  as another forward reference from langtools to jdk.
    8.46 + *
    8.47 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    8.48 + *  you write code that depends on this, you do so at your own risk.
    8.49 + *  This code and its internal interfaces are subject to change or
    8.50 + *  deletion without notice.</b>
    8.51 + */
    8.52 +public interface PathFileManager extends JavaFileManager {
    8.53 +    /**
    8.54 +     * Get the default file system used to create paths. If no value has been
    8.55 +     * set, the default file system is {@link FileSystems#getDefault}.
    8.56 +     */
    8.57 +    FileSystem getDefaultFileSystem();
    8.58 +
    8.59 +    /**
    8.60 +     * Set the default file system used to create paths.
    8.61 +     * @param fs the default file system used to create any new paths.
    8.62 +     */
    8.63 +    void setDefaultFileSystem(FileSystem fs);
    8.64 +
    8.65 +    /**
    8.66 +     * Get file objects representing the given files.
    8.67 +     *
    8.68 +     * @param paths a list of paths
    8.69 +     * @return a list of file objects
    8.70 +     * @throws IllegalArgumentException if the list of paths includes
    8.71 +     * a directory
    8.72 +     */
    8.73 +    Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
    8.74 +        Iterable<? extends Path> paths);
    8.75 +
    8.76 +    /**
    8.77 +     * Get file objects representing the given paths.
    8.78 +     * Convenience method equivalent to:
    8.79 +     *
    8.80 +     * <pre>
    8.81 +     *     getJavaFileObjectsFromPaths({@linkplain java.util.Arrays#asList Arrays.asList}(paths))
    8.82 +     * </pre>
    8.83 +     *
    8.84 +     * @param paths an array of paths
    8.85 +     * @return a list of file objects
    8.86 +     * @throws IllegalArgumentException if the array of files includes
    8.87 +     * a directory
    8.88 +     * @throws NullPointerException if the given array contains null
    8.89 +     * elements
    8.90 +     */
    8.91 +    Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths);
    8.92 +
    8.93 +    /**
    8.94 +     * Return the Path for a file object that has been obtained from this
    8.95 +     * file manager.
    8.96 +     *
    8.97 +     * @param fo A file object that has been obtained from this file manager.
    8.98 +     * @return The underlying Path object.
    8.99 +     * @throws IllegalArgumentException is the file object was not obtained from
   8.100 +     * from this file manager.
   8.101 +     */
   8.102 +    Path getPath(FileObject fo);
   8.103 +
   8.104 +    /**
   8.105 +     * Get the search path associated with the given location.
   8.106 +     *
   8.107 +     * @param location a location
   8.108 +     * @return a list of paths or {@code null} if this location has no
   8.109 +     * associated search path
   8.110 +     * @see #setLocation
   8.111 +     */
   8.112 +    Iterable<? extends Path> getLocation(Location location);
   8.113 +
   8.114 +    /**
   8.115 +     * Associate the given search path with the given location.  Any
   8.116 +     * previous value will be discarded.
   8.117 +     *
   8.118 +     * @param location a location
   8.119 +     * @param searchPath a list of files, if {@code null} use the default
   8.120 +     * search path for this location
   8.121 +     * @see #getLocation
   8.122 +     * @throws IllegalArgumentException if location is an output
   8.123 +     * location and searchpath does not contain exactly one element
   8.124 +     * @throws IOException if location is an output location and searchpath
   8.125 +     * does not represent an existing directory
   8.126 +     */
   8.127 +    void setLocation(Location location, Iterable<? extends Path> searchPath) throws IOException;
   8.128 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/share/classes/com/sun/tools/javac/nio/PathFileObject.java	Fri Dec 11 14:26:27 2009 -0800
     9.3 @@ -0,0 +1,319 @@
     9.4 +/*
     9.5 + * Copyright 2009 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.nio;
    9.30 +
    9.31 +import java.io.IOException;
    9.32 +import java.io.InputStream;
    9.33 +import java.io.InputStreamReader;
    9.34 +import java.io.OutputStream;
    9.35 +import java.io.OutputStreamWriter;
    9.36 +import java.io.Reader;
    9.37 +import java.io.Writer;
    9.38 +import java.net.URI;
    9.39 +import java.nio.ByteBuffer;
    9.40 +import java.nio.CharBuffer;
    9.41 +import java.nio.charset.CharsetDecoder;
    9.42 +import java.nio.file.Files;
    9.43 +import java.nio.file.Path;
    9.44 +import java.nio.file.attribute.Attributes;
    9.45 +import java.nio.file.attribute.BasicFileAttributes;
    9.46 +import javax.lang.model.element.Modifier;
    9.47 +import javax.lang.model.element.NestingKind;
    9.48 +import javax.tools.JavaFileObject;
    9.49 +
    9.50 +import com.sun.tools.javac.util.BaseFileManager;
    9.51 +
    9.52 +
    9.53 +/**
    9.54 + *  Implementation of JavaFileObject using java.nio.file API.
    9.55 + *
    9.56 + *  <p>PathFileObjects are, for the most part, straightforward wrappers around
    9.57 + *  Path objects. The primary complexity is the support for "inferBinaryName".
    9.58 + *  This is left as an abstract method, implemented by each of a number of
    9.59 + *  different factory methods, which compute the binary name based on
    9.60 + *  information available at the time the file object is created.
    9.61 + *
    9.62 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    9.63 + *  you write code that depends on this, you do so at your own risk.
    9.64 + *  This code and its internal interfaces are subject to change or
    9.65 + *  deletion without notice.</b>
    9.66 + */
    9.67 +abstract class PathFileObject implements JavaFileObject {
    9.68 +    private JavacPathFileManager fileManager;
    9.69 +    private Path path;
    9.70 +
    9.71 +    /**
    9.72 +     * Create a PathFileObject within a directory, such that the binary name
    9.73 +     * can be inferred from the relationship to the parent directory.
    9.74 +     */
    9.75 +    static PathFileObject createDirectoryPathFileObject(JavacPathFileManager fileManager,
    9.76 +            final Path path, final Path dir) {
    9.77 +        return new PathFileObject(fileManager, path) {
    9.78 +            @Override
    9.79 +            String inferBinaryName(Iterable<? extends Path> paths) {
    9.80 +                return toBinaryName(dir.relativize(path));
    9.81 +            }
    9.82 +        };
    9.83 +    }
    9.84 +
    9.85 +    /**
    9.86 +     * Create a PathFileObject in a file system such as a jar file, such that
    9.87 +     * the binary name can be inferred from its position within the filesystem.
    9.88 +     */
    9.89 +    static PathFileObject createJarPathFileObject(JavacPathFileManager fileManager,
    9.90 +            final Path path) {
    9.91 +        return new PathFileObject(fileManager, path) {
    9.92 +            @Override
    9.93 +            String inferBinaryName(Iterable<? extends Path> paths) {
    9.94 +                return toBinaryName(path);
    9.95 +            }
    9.96 +        };
    9.97 +    }
    9.98 +
    9.99 +    /**
   9.100 +     * Create a PathFileObject whose binary name can be inferred from the
   9.101 +     * relative path to a sibling.
   9.102 +     */
   9.103 +    static PathFileObject createSiblingPathFileObject(JavacPathFileManager fileManager,
   9.104 +            final Path path, final String relativePath) {
   9.105 +        return new PathFileObject(fileManager, path) {
   9.106 +            @Override
   9.107 +            String inferBinaryName(Iterable<? extends Path> paths) {
   9.108 +                return toBinaryName(relativePath, "/");
   9.109 +            }
   9.110 +        };
   9.111 +    }
   9.112 +
   9.113 +    /**
   9.114 +     * Create a PathFileObject whose binary name might be inferred from its
   9.115 +     * position on a search path.
   9.116 +     */
   9.117 +    static PathFileObject createSimplePathFileObject(JavacPathFileManager fileManager,
   9.118 +            final Path path) {
   9.119 +        return new PathFileObject(fileManager, path) {
   9.120 +            @Override
   9.121 +            String inferBinaryName(Iterable<? extends Path> paths) {
   9.122 +                Path absPath = path.toAbsolutePath();
   9.123 +                for (Path p: paths) {
   9.124 +                    Path ap = p.toAbsolutePath();
   9.125 +                    if (absPath.startsWith(ap)) {
   9.126 +                        try {
   9.127 +                            Path rp = ap.relativize(absPath);
   9.128 +                            if (rp != null) // maybe null if absPath same as ap
   9.129 +                                return toBinaryName(rp);
   9.130 +                        } catch (IllegalArgumentException e) {
   9.131 +                            // ignore this p if cannot relativize path to p
   9.132 +                        }
   9.133 +                    }
   9.134 +                }
   9.135 +                return null;
   9.136 +            }
   9.137 +        };
   9.138 +    }
   9.139 +
   9.140 +    protected PathFileObject(JavacPathFileManager fileManager, Path path) {
   9.141 +        fileManager.getClass(); // null check
   9.142 +        path.getClass();        // null check
   9.143 +        this.fileManager = fileManager;
   9.144 +        this.path = path;
   9.145 +    }
   9.146 +
   9.147 +    abstract String inferBinaryName(Iterable<? extends Path> paths);
   9.148 +
   9.149 +    /**
   9.150 +     * Return the Path for this object.
   9.151 +     * @return the Path for this object.
   9.152 +     */
   9.153 +    Path getPath() {
   9.154 +        return path;
   9.155 +    }
   9.156 +
   9.157 +    @Override
   9.158 +    public Kind getKind() {
   9.159 +        return BaseFileManager.getKind(path.getName().toString());
   9.160 +    }
   9.161 +
   9.162 +    @Override
   9.163 +    public boolean isNameCompatible(String simpleName, Kind kind) {
   9.164 +        simpleName.getClass();
   9.165 +        // null check
   9.166 +        if (kind == Kind.OTHER && getKind() != kind) {
   9.167 +            return false;
   9.168 +        }
   9.169 +        String sn = simpleName + kind.extension;
   9.170 +        String pn = path.getName().toString();
   9.171 +        if (pn.equals(sn)) {
   9.172 +            return true;
   9.173 +        }
   9.174 +        if (pn.equalsIgnoreCase(sn)) {
   9.175 +            try {
   9.176 +                // allow for Windows
   9.177 +                return path.toRealPath(false).getName().toString().equals(sn);
   9.178 +            } catch (IOException e) {
   9.179 +            }
   9.180 +        }
   9.181 +        return false;
   9.182 +    }
   9.183 +
   9.184 +    @Override
   9.185 +    public NestingKind getNestingKind() {
   9.186 +        return null;
   9.187 +    }
   9.188 +
   9.189 +    @Override
   9.190 +    public Modifier getAccessLevel() {
   9.191 +        return null;
   9.192 +    }
   9.193 +
   9.194 +    @Override
   9.195 +    public URI toUri() {
   9.196 +        return path.toUri();
   9.197 +    }
   9.198 +
   9.199 +    @Override
   9.200 +    public String getName() {
   9.201 +        return path.toString();
   9.202 +    }
   9.203 +
   9.204 +    @Override
   9.205 +    public InputStream openInputStream() throws IOException {
   9.206 +        return path.newInputStream();
   9.207 +    }
   9.208 +
   9.209 +    @Override
   9.210 +    public OutputStream openOutputStream() throws IOException {
   9.211 +        ensureParentDirectoriesExist();
   9.212 +        return path.newOutputStream();
   9.213 +    }
   9.214 +
   9.215 +    @Override
   9.216 +    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
   9.217 +        CharsetDecoder decoder = fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
   9.218 +        return new InputStreamReader(openInputStream(), decoder);
   9.219 +    }
   9.220 +
   9.221 +    @Override
   9.222 +    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   9.223 +        CharBuffer cb = fileManager.getCachedContent(this);
   9.224 +        if (cb == null) {
   9.225 +            InputStream in = openInputStream();
   9.226 +            try {
   9.227 +                ByteBuffer bb = fileManager.makeByteBuffer(in);
   9.228 +                JavaFileObject prev = fileManager.log.useSource(this);
   9.229 +                try {
   9.230 +                    cb = fileManager.decode(bb, ignoreEncodingErrors);
   9.231 +                } finally {
   9.232 +                    fileManager.log.useSource(prev);
   9.233 +                }
   9.234 +                fileManager.recycleByteBuffer(bb);
   9.235 +                if (!ignoreEncodingErrors) {
   9.236 +                    fileManager.cache(this, cb);
   9.237 +                }
   9.238 +            } finally {
   9.239 +                in.close();
   9.240 +            }
   9.241 +        }
   9.242 +        return cb;
   9.243 +    }
   9.244 +
   9.245 +    @Override
   9.246 +    public Writer openWriter() throws IOException {
   9.247 +        ensureParentDirectoriesExist();
   9.248 +        return new OutputStreamWriter(path.newOutputStream(), fileManager.getEncodingName());
   9.249 +    }
   9.250 +
   9.251 +    @Override
   9.252 +    public long getLastModified() {
   9.253 +        try {
   9.254 +            BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path);
   9.255 +            return attrs.lastModifiedTime().toMillis();
   9.256 +        } catch (IOException e) {
   9.257 +            return -1;
   9.258 +        }
   9.259 +    }
   9.260 +
   9.261 +    @Override
   9.262 +    public boolean delete() {
   9.263 +        try {
   9.264 +            path.delete();
   9.265 +            return true;
   9.266 +        } catch (IOException e) {
   9.267 +            return false;
   9.268 +        }
   9.269 +    }
   9.270 +
   9.271 +    public boolean isSameFile(PathFileObject other) {
   9.272 +        try {
   9.273 +            return path.isSameFile(other.path);
   9.274 +        } catch (IOException e) {
   9.275 +            return false;
   9.276 +        }
   9.277 +    }
   9.278 +
   9.279 +    @Override
   9.280 +    public boolean equals(Object other) {
   9.281 +        return (other instanceof PathFileObject && path.equals(((PathFileObject) other).path));
   9.282 +    }
   9.283 +
   9.284 +    @Override
   9.285 +    public int hashCode() {
   9.286 +        return path.hashCode();
   9.287 +    }
   9.288 +
   9.289 +    @Override
   9.290 +    public String toString() {
   9.291 +        return getClass().getSimpleName() + "[" + path + "]";
   9.292 +    }
   9.293 +
   9.294 +    private void ensureParentDirectoriesExist() throws IOException {
   9.295 +        Path parent = path.getParent();
   9.296 +        if (parent != null)
   9.297 +            Files.createDirectories(parent);
   9.298 +    }
   9.299 +
   9.300 +    private long size() {
   9.301 +        try {
   9.302 +            BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path);
   9.303 +            return attrs.size();
   9.304 +        } catch (IOException e) {
   9.305 +            return -1;
   9.306 +        }
   9.307 +    }
   9.308 +
   9.309 +    protected static String toBinaryName(Path relativePath) {
   9.310 +        return toBinaryName(relativePath.toString(),
   9.311 +                relativePath.getFileSystem().getSeparator());
   9.312 +    }
   9.313 +
   9.314 +    protected static String toBinaryName(String relativePath, String sep) {
   9.315 +        return removeExtension(relativePath).replaceAll(sep, ".");
   9.316 +    }
   9.317 +
   9.318 +    protected static String removeExtension(String fileName) {
   9.319 +        int lastDot = fileName.lastIndexOf(".");
   9.320 +        return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
   9.321 +    }
   9.322 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java	Fri Dec 11 14:26:27 2009 -0800
    10.3 @@ -0,0 +1,355 @@
    10.4 +/*
    10.5 + * Copyright 2009 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.util;
   10.30 +
   10.31 +import com.sun.tools.javac.code.Source;
   10.32 +import com.sun.tools.javac.main.JavacOption;
   10.33 +import com.sun.tools.javac.main.OptionName;
   10.34 +import com.sun.tools.javac.main.RecognizedOptions;
   10.35 +import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
   10.36 +import java.io.ByteArrayOutputStream;
   10.37 +import java.io.Closeable;
   10.38 +import java.io.IOException;
   10.39 +import java.io.InputStream;
   10.40 +import java.io.OutputStreamWriter;
   10.41 +import java.lang.ref.SoftReference;
   10.42 +import java.lang.reflect.Constructor;
   10.43 +import java.net.URL;
   10.44 +import java.net.URLClassLoader;
   10.45 +import java.nio.ByteBuffer;
   10.46 +import java.nio.CharBuffer;
   10.47 +import java.nio.charset.Charset;
   10.48 +import java.nio.charset.CharsetDecoder;
   10.49 +import java.nio.charset.CoderResult;
   10.50 +import java.nio.charset.CodingErrorAction;
   10.51 +import java.nio.charset.IllegalCharsetNameException;
   10.52 +import java.nio.charset.UnsupportedCharsetException;
   10.53 +import java.util.Collection;
   10.54 +import java.util.HashMap;
   10.55 +import java.util.Iterator;
   10.56 +import java.util.Map;
   10.57 +import javax.tools.JavaFileObject;
   10.58 +import javax.tools.JavaFileObject.Kind;
   10.59 +
   10.60 +/**
   10.61 + * Utility methods for building a filemanager.
   10.62 + * There are no references here to file-system specific objects such as
   10.63 + * java.io.File or java.nio.file.Path.
   10.64 + */
   10.65 +public class BaseFileManager {
   10.66 +    protected BaseFileManager(Charset charset) {
   10.67 +        this.charset = charset;
   10.68 +        byteBufferCache = new ByteBufferCache();
   10.69 +    }
   10.70 +
   10.71 +    /**
   10.72 +     * Set the context for JavacPathFileManager.
   10.73 +     */
   10.74 +    protected void setContext(Context context) {
   10.75 +        log = Log.instance(context);
   10.76 +        options = Options.instance(context);
   10.77 +        classLoaderClass = options.get("procloader");
   10.78 +    }
   10.79 +
   10.80 +    /**
   10.81 +     * The log to be used for error reporting.
   10.82 +     */
   10.83 +    public Log log;
   10.84 +
   10.85 +    /**
   10.86 +     * User provided charset (through javax.tools).
   10.87 +     */
   10.88 +    protected Charset charset;
   10.89 +
   10.90 +    protected Options options;
   10.91 +
   10.92 +    protected String classLoaderClass;
   10.93 +
   10.94 +    protected Source getSource() {
   10.95 +        String sourceName = options.get(OptionName.SOURCE);
   10.96 +        Source source = null;
   10.97 +        if (sourceName != null)
   10.98 +            source = Source.lookup(sourceName);
   10.99 +        return (source != null ? source : Source.DEFAULT);
  10.100 +    }
  10.101 +
  10.102 +    protected ClassLoader getClassLoader(URL[] urls) {
  10.103 +        ClassLoader thisClassLoader = getClass().getClassLoader();
  10.104 +
  10.105 +        // Bug: 6558476
  10.106 +        // Ideally, ClassLoader should be Closeable, but before JDK7 it is not.
  10.107 +        // On older versions, try the following, to get a closeable classloader.
  10.108 +
  10.109 +        // 1: Allow client to specify the class to use via hidden option
  10.110 +        if (classLoaderClass != null) {
  10.111 +            try {
  10.112 +                Class<? extends ClassLoader> loader =
  10.113 +                        Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
  10.114 +                Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
  10.115 +                Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
  10.116 +                return constr.newInstance(new Object[] { urls, thisClassLoader });
  10.117 +            } catch (Throwable t) {
  10.118 +                // ignore errors loading user-provided class loader, fall through
  10.119 +            }
  10.120 +        }
  10.121 +
  10.122 +        // 2: If URLClassLoader implements Closeable, use that.
  10.123 +        if (Closeable.class.isAssignableFrom(URLClassLoader.class))
  10.124 +            return new URLClassLoader(urls, thisClassLoader);
  10.125 +
  10.126 +        // 3: Try using private reflection-based CloseableURLClassLoader
  10.127 +        try {
  10.128 +            return new CloseableURLClassLoader(urls, thisClassLoader);
  10.129 +        } catch (Throwable t) {
  10.130 +            // ignore errors loading workaround class loader, fall through
  10.131 +        }
  10.132 +
  10.133 +        // 4: If all else fails, use plain old standard URLClassLoader
  10.134 +        return new URLClassLoader(urls, thisClassLoader);
  10.135 +    }
  10.136 +
  10.137 +    // <editor-fold defaultstate="collapsed" desc="Option handling">
  10.138 +    public boolean handleOption(String current, Iterator<String> remaining) {
  10.139 +        for (JavacOption o: javacFileManagerOptions) {
  10.140 +            if (o.matches(current))  {
  10.141 +                if (o.hasArg()) {
  10.142 +                    if (remaining.hasNext()) {
  10.143 +                        if (!o.process(options, current, remaining.next()))
  10.144 +                            return true;
  10.145 +                    }
  10.146 +                } else {
  10.147 +                    if (!o.process(options, current))
  10.148 +                        return true;
  10.149 +                }
  10.150 +                // operand missing, or process returned false
  10.151 +                throw new IllegalArgumentException(current);
  10.152 +            }
  10.153 +        }
  10.154 +
  10.155 +        return false;
  10.156 +    }
  10.157 +    // where
  10.158 +        private static JavacOption[] javacFileManagerOptions =
  10.159 +            RecognizedOptions.getJavacFileManagerOptions(
  10.160 +            new RecognizedOptions.GrumpyHelper());
  10.161 +
  10.162 +    public int isSupportedOption(String option) {
  10.163 +        for (JavacOption o : javacFileManagerOptions) {
  10.164 +            if (o.matches(option))
  10.165 +                return o.hasArg() ? 1 : 0;
  10.166 +        }
  10.167 +        return -1;
  10.168 +    }
  10.169 +    // </editor-fold>
  10.170 +
  10.171 +    // <editor-fold defaultstate="collapsed" desc="Encoding">
  10.172 +    private String defaultEncodingName;
  10.173 +    private String getDefaultEncodingName() {
  10.174 +        if (defaultEncodingName == null) {
  10.175 +            defaultEncodingName =
  10.176 +                new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
  10.177 +        }
  10.178 +        return defaultEncodingName;
  10.179 +    }
  10.180 +
  10.181 +    public String getEncodingName() {
  10.182 +        String encName = options.get(OptionName.ENCODING);
  10.183 +        if (encName == null)
  10.184 +            return getDefaultEncodingName();
  10.185 +        else
  10.186 +            return encName;
  10.187 +    }
  10.188 +
  10.189 +    public CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
  10.190 +        String encodingName = getEncodingName();
  10.191 +        CharsetDecoder decoder;
  10.192 +        try {
  10.193 +            decoder = getDecoder(encodingName, ignoreEncodingErrors);
  10.194 +        } catch (IllegalCharsetNameException e) {
  10.195 +            log.error("unsupported.encoding", encodingName);
  10.196 +            return (CharBuffer)CharBuffer.allocate(1).flip();
  10.197 +        } catch (UnsupportedCharsetException e) {
  10.198 +            log.error("unsupported.encoding", encodingName);
  10.199 +            return (CharBuffer)CharBuffer.allocate(1).flip();
  10.200 +        }
  10.201 +
  10.202 +        // slightly overestimate the buffer size to avoid reallocation.
  10.203 +        float factor =
  10.204 +            decoder.averageCharsPerByte() * 0.8f +
  10.205 +            decoder.maxCharsPerByte() * 0.2f;
  10.206 +        CharBuffer dest = CharBuffer.
  10.207 +            allocate(10 + (int)(inbuf.remaining()*factor));
  10.208 +
  10.209 +        while (true) {
  10.210 +            CoderResult result = decoder.decode(inbuf, dest, true);
  10.211 +            dest.flip();
  10.212 +
  10.213 +            if (result.isUnderflow()) { // done reading
  10.214 +                // make sure there is at least one extra character
  10.215 +                if (dest.limit() == dest.capacity()) {
  10.216 +                    dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
  10.217 +                    dest.flip();
  10.218 +                }
  10.219 +                return dest;
  10.220 +            } else if (result.isOverflow()) { // buffer too small; expand
  10.221 +                int newCapacity =
  10.222 +                    10 + dest.capacity() +
  10.223 +                    (int)(inbuf.remaining()*decoder.maxCharsPerByte());
  10.224 +                dest = CharBuffer.allocate(newCapacity).put(dest);
  10.225 +            } else if (result.isMalformed() || result.isUnmappable()) {
  10.226 +                // bad character in input
  10.227 +
  10.228 +                // report coding error (warn only pre 1.5)
  10.229 +                if (!getSource().allowEncodingErrors()) {
  10.230 +                    log.error(new SimpleDiagnosticPosition(dest.limit()),
  10.231 +                              "illegal.char.for.encoding",
  10.232 +                              charset == null ? encodingName : charset.name());
  10.233 +                } else {
  10.234 +                    log.warning(new SimpleDiagnosticPosition(dest.limit()),
  10.235 +                                "illegal.char.for.encoding",
  10.236 +                                charset == null ? encodingName : charset.name());
  10.237 +                }
  10.238 +
  10.239 +                // skip past the coding error
  10.240 +                inbuf.position(inbuf.position() + result.length());
  10.241 +
  10.242 +                // undo the flip() to prepare the output buffer
  10.243 +                // for more translation
  10.244 +                dest.position(dest.limit());
  10.245 +                dest.limit(dest.capacity());
  10.246 +                dest.put((char)0xfffd); // backward compatible
  10.247 +            } else {
  10.248 +                throw new AssertionError(result);
  10.249 +            }
  10.250 +        }
  10.251 +        // unreached
  10.252 +    }
  10.253 +
  10.254 +    public CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
  10.255 +        Charset cs = (this.charset == null)
  10.256 +            ? Charset.forName(encodingName)
  10.257 +            : this.charset;
  10.258 +        CharsetDecoder decoder = cs.newDecoder();
  10.259 +
  10.260 +        CodingErrorAction action;
  10.261 +        if (ignoreEncodingErrors)
  10.262 +            action = CodingErrorAction.REPLACE;
  10.263 +        else
  10.264 +            action = CodingErrorAction.REPORT;
  10.265 +
  10.266 +        return decoder
  10.267 +            .onMalformedInput(action)
  10.268 +            .onUnmappableCharacter(action);
  10.269 +    }
  10.270 +    // </editor-fold>
  10.271 +
  10.272 +    // <editor-fold defaultstate="collapsed" desc="ByteBuffers">
  10.273 +    /**
  10.274 +     * Make a byte buffer from an input stream.
  10.275 +     */
  10.276 +    public ByteBuffer makeByteBuffer(InputStream in)
  10.277 +        throws IOException {
  10.278 +        int limit = in.available();
  10.279 +        if (limit < 1024) limit = 1024;
  10.280 +        ByteBuffer result = byteBufferCache.get(limit);
  10.281 +        int position = 0;
  10.282 +        while (in.available() != 0) {
  10.283 +            if (position >= limit)
  10.284 +                // expand buffer
  10.285 +                result = ByteBuffer.
  10.286 +                    allocate(limit <<= 1).
  10.287 +                    put((ByteBuffer)result.flip());
  10.288 +            int count = in.read(result.array(),
  10.289 +                position,
  10.290 +                limit - position);
  10.291 +            if (count < 0) break;
  10.292 +            result.position(position += count);
  10.293 +        }
  10.294 +        return (ByteBuffer)result.flip();
  10.295 +    }
  10.296 +
  10.297 +    public void recycleByteBuffer(ByteBuffer bb) {
  10.298 +        byteBufferCache.put(bb);
  10.299 +    }
  10.300 +
  10.301 +    /**
  10.302 +     * A single-element cache of direct byte buffers.
  10.303 +     */
  10.304 +    private static class ByteBufferCache {
  10.305 +        private ByteBuffer cached;
  10.306 +        ByteBuffer get(int capacity) {
  10.307 +            if (capacity < 20480) capacity = 20480;
  10.308 +            ByteBuffer result =
  10.309 +                (cached != null && cached.capacity() >= capacity)
  10.310 +                ? (ByteBuffer)cached.clear()
  10.311 +                : ByteBuffer.allocate(capacity + capacity>>1);
  10.312 +            cached = null;
  10.313 +            return result;
  10.314 +        }
  10.315 +        void put(ByteBuffer x) {
  10.316 +            cached = x;
  10.317 +        }
  10.318 +    }
  10.319 +
  10.320 +    private final ByteBufferCache byteBufferCache;
  10.321 +    // </editor-fold>
  10.322 +
  10.323 +    // <editor-fold defaultstate="collapsed" desc="Content cache">
  10.324 +    public CharBuffer getCachedContent(JavaFileObject file) {
  10.325 +        SoftReference<CharBuffer> r = contentCache.get(file);
  10.326 +        return (r == null ? null : r.get());
  10.327 +    }
  10.328 +
  10.329 +    public void cache(JavaFileObject file, CharBuffer cb) {
  10.330 +        contentCache.put(file, new SoftReference<CharBuffer>(cb));
  10.331 +    }
  10.332 +
  10.333 +    protected final Map<JavaFileObject, SoftReference<CharBuffer>> contentCache
  10.334 +            = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
  10.335 +    // </editor-fold>
  10.336 +
  10.337 +    public static Kind getKind(String name) {
  10.338 +        if (name.endsWith(Kind.CLASS.extension))
  10.339 +            return Kind.CLASS;
  10.340 +        else if (name.endsWith(Kind.SOURCE.extension))
  10.341 +            return Kind.SOURCE;
  10.342 +        else if (name.endsWith(Kind.HTML.extension))
  10.343 +            return Kind.HTML;
  10.344 +        else
  10.345 +            return Kind.OTHER;
  10.346 +    }
  10.347 +
  10.348 +    protected static <T> T nullCheck(T o) {
  10.349 +        o.getClass(); // null check
  10.350 +        return o;
  10.351 +    }
  10.352 +
  10.353 +    protected static <T> Collection<T> nullCheck(Collection<T> it) {
  10.354 +        for (T t : it)
  10.355 +            t.getClass(); // null check
  10.356 +        return it;
  10.357 +    }
  10.358 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/share/classes/com/sun/tools/javac/util/CloseableURLClassLoader.java	Fri Dec 11 14:26:27 2009 -0800
    11.3 @@ -0,0 +1,108 @@
    11.4 +/*
    11.5 + * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
    11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.7 + *
    11.8 + * This code is free software; you can redistribute it and/or modify it
    11.9 + * under the terms of the GNU General Public License version 2 only, as
   11.10 + * published by the Free Software Foundation.  Sun designates this
   11.11 + * particular file as subject to the "Classpath" exception as provided
   11.12 + * by Sun in the LICENSE file that accompanied this code.
   11.13 + *
   11.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   11.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   11.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   11.17 + * version 2 for more details (a copy is included in the LICENSE file that
   11.18 + * accompanied this code).
   11.19 + *
   11.20 + * You should have received a copy of the GNU General Public License version
   11.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   11.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   11.23 + *
   11.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   11.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   11.26 + * have any questions.
   11.27 + */
   11.28 +
   11.29 +package com.sun.tools.javac.util;
   11.30 +
   11.31 +import java.io.Closeable;
   11.32 +import java.io.IOException;
   11.33 +import java.lang.reflect.Field;
   11.34 +import java.net.URL;
   11.35 +import java.net.URLClassLoader;
   11.36 +import java.util.ArrayList;
   11.37 +import java.util.jar.JarFile;
   11.38 +
   11.39 +/**
   11.40 + * A URLClassLoader that also implements Closeable.
   11.41 + * Reflection is used to access internal data structures in the URLClassLoader,
   11.42 + * since no public API exists for this purpose. Therefore this code is somewhat
   11.43 + * fragile. Caveat emptor.
   11.44 + * @throws Error if the internal data structures are not as expected.
   11.45 + *
   11.46 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
   11.47 + *  you write code that depends on this, you do so at your own risk.
   11.48 + *  This code and its internal interfaces are subject to change or
   11.49 + *  deletion without notice.</b>
   11.50 + */
   11.51 +public class CloseableURLClassLoader
   11.52 +        extends URLClassLoader implements Closeable {
   11.53 +    public CloseableURLClassLoader(URL[] urls, ClassLoader parent) throws Error {
   11.54 +        super(urls, parent);
   11.55 +        try {
   11.56 +            getLoaders(); //proactive check that URLClassLoader is as expected
   11.57 +        } catch (Throwable t) {
   11.58 +            throw new Error("cannot create CloseableURLClassLoader", t);
   11.59 +        }
   11.60 +    }
   11.61 +
   11.62 +    /**
   11.63 +     * Close any jar files that may have been opened by the class loader.
   11.64 +     * Reflection is used to access the jar files in the URLClassLoader's
   11.65 +     * internal data structures.
   11.66 +     * @throws java.io.IOException if the jar files cannot be found for any
   11.67 +     * reson, or if closing the jar file itself causes an IOException.
   11.68 +     */
   11.69 +    @Override
   11.70 +    public void close() throws IOException {
   11.71 +        try {
   11.72 +            for (Object l: getLoaders()) {
   11.73 +                if (l.getClass().getName().equals("sun.misc.URLClassPath$JarLoader")) {
   11.74 +                    Field jarField = l.getClass().getDeclaredField("jar");
   11.75 +                    JarFile jar = (JarFile) getField(l, jarField);
   11.76 +                    if (jar != null) {
   11.77 +                        //System.err.println("CloseableURLClassLoader: closing " + jar);
   11.78 +                        jar.close();
   11.79 +                    }
   11.80 +                }
   11.81 +            }
   11.82 +        } catch (Throwable t) {
   11.83 +            IOException e = new IOException("cannot close class loader");
   11.84 +            e.initCause(t);
   11.85 +            throw e;
   11.86 +        }
   11.87 +    }
   11.88 +
   11.89 +    private ArrayList<?> getLoaders()
   11.90 +            throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException
   11.91 +    {
   11.92 +        Field ucpField = URLClassLoader.class.getDeclaredField("ucp");
   11.93 +        Object urlClassPath = getField(this, ucpField);
   11.94 +        if (urlClassPath == null)
   11.95 +            throw new AssertionError("urlClassPath not set in URLClassLoader");
   11.96 +        Field loadersField = urlClassPath.getClass().getDeclaredField("loaders");
   11.97 +        return (ArrayList<?>) getField(urlClassPath, loadersField);
   11.98 +    }
   11.99 +
  11.100 +    private Object getField(Object o, Field f)
  11.101 +            throws IllegalArgumentException, IllegalAccessException {
  11.102 +        boolean prev = f.isAccessible();
  11.103 +        try {
  11.104 +            f.setAccessible(true);
  11.105 +            return f.get(o);
  11.106 +        } finally {
  11.107 +            f.setAccessible(prev);
  11.108 +        }
  11.109 +    }
  11.110 +
  11.111 +}
    12.1 --- a/src/share/classes/javax/tools/StandardJavaFileManager.java	Thu Dec 10 20:35:31 2009 -0800
    12.2 +++ b/src/share/classes/javax/tools/StandardJavaFileManager.java	Fri Dec 11 14:26:27 2009 -0800
    12.3 @@ -28,7 +28,6 @@
    12.4  import java.io.File;
    12.5  import java.io.IOException;
    12.6  import java.util.*;
    12.7 -import java.util.concurrent.*;
    12.8  
    12.9  /**
   12.10   * File manager based on {@linkplain File java.io.File}.  A common way
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/test/tools/javac/nio/compileTest/CompileTest.java	Fri Dec 11 14:26:27 2009 -0800
    13.3 @@ -0,0 +1,165 @@
    13.4 +/*
    13.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.7 + *
    13.8 + * This code is free software; you can redistribute it and/or modify it
    13.9 + * under the terms of the GNU General Public License version 2 only, as
   13.10 + * published by the Free Software Foundation.
   13.11 + *
   13.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   13.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.15 + * version 2 for more details (a copy is included in the LICENSE file that
   13.16 + * accompanied this code).
   13.17 + *
   13.18 + * You should have received a copy of the GNU General Public License version
   13.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   13.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.21 + *
   13.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   13.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   13.24 + * have any questions.
   13.25 + */
   13.26 +
   13.27 +/**
   13.28 + * @test
   13.29 + * @compile HelloPathWorld.java
   13.30 + * @run main CompileTest
   13.31 + */
   13.32 +
   13.33 +import java.io.*;
   13.34 +import java.nio.file.*;
   13.35 +import java.util.*;
   13.36 +import java.util.jar.*;
   13.37 +import javax.tools.*;
   13.38 +
   13.39 +import com.sun.tools.javac.nio.*;
   13.40 +import com.sun.tools.javac.util.Context;
   13.41 +import java.nio.file.spi.FileSystemProvider;
   13.42 +
   13.43 +
   13.44 +public class CompileTest {
   13.45 +    public static void main(String[] args) throws Exception {
   13.46 +        new CompileTest().run();
   13.47 +    }
   13.48 +
   13.49 +    public void run() throws Exception {
   13.50 +        File rtDir = new File("rt.dir");
   13.51 +        File javaHome = new File(System.getProperty("java.home"));
   13.52 +        if (javaHome.getName().equals("jre"))
   13.53 +            javaHome = javaHome.getParentFile();
   13.54 +        File rtJar = new File(new File(new File(javaHome, "jre"), "lib"), "rt.jar");
   13.55 +        expand(rtJar, rtDir);
   13.56 +
   13.57 +        String[] rtDir_opts = {
   13.58 +            "-bootclasspath", rtDir.toString(),
   13.59 +            "-classpath", "",
   13.60 +            "-sourcepath", "",
   13.61 +            "-extdirs", ""
   13.62 +        };
   13.63 +        test(rtDir_opts, "HelloPathWorld");
   13.64 +
   13.65 +        if (isJarFileSystemAvailable()) {
   13.66 +            String[] rtJar_opts = {
   13.67 +                "-bootclasspath", rtJar.toString(),
   13.68 +                "-classpath", "",
   13.69 +                "-sourcepath", "",
   13.70 +                "-extdirs", ""
   13.71 +            };
   13.72 +            test(rtJar_opts, "HelloPathWorld");
   13.73 +
   13.74 +            String[] default_opts = { };
   13.75 +            test(default_opts, "HelloPathWorld");
   13.76 +
   13.77 +            // finally, a non-trivial program
   13.78 +            test(default_opts, "CompileTest");
   13.79 +        } else
   13.80 +            System.err.println("jar file system not available: test skipped");
   13.81 +    }
   13.82 +
   13.83 +    void test(String[] opts, String className) throws Exception {
   13.84 +        count++;
   13.85 +        System.err.println("Test " + count + " " + Arrays.asList(opts) + " " + className);
   13.86 +        Path testSrcDir = Paths.get(System.getProperty("test.src"));
   13.87 +        Path testClassesDir = Paths.get(System.getProperty("test.classes"));
   13.88 +        Path classes = Paths.get("classes." + count);
   13.89 +        classes.createDirectory();
   13.90 +
   13.91 +        Context ctx = new Context();
   13.92 +        PathFileManager fm = new JavacPathFileManager(ctx, true, null);
   13.93 +        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
   13.94 +        List<String> options = new ArrayList<String>();
   13.95 +        options.addAll(Arrays.asList(opts));
   13.96 +        options.addAll(Arrays.asList(
   13.97 +                "-verbose", "-XDverboseCompilePolicy",
   13.98 +                "-d", classes.toString()
   13.99 +        ));
  13.100 +        Iterable<? extends JavaFileObject> compilationUnits =
  13.101 +                fm.getJavaFileObjects(testSrcDir.resolve(className + ".java"));
  13.102 +        StringWriter sw = new StringWriter();
  13.103 +        PrintWriter out = new PrintWriter(sw);
  13.104 +        JavaCompiler.CompilationTask t =
  13.105 +                compiler.getTask(out, fm, null, options, null, compilationUnits);
  13.106 +        boolean ok = t.call();
  13.107 +        System.err.println(sw.toString());
  13.108 +        if (!ok) {
  13.109 +            throw new Exception("compilation failed");
  13.110 +        }
  13.111 +
  13.112 +        File expect = new File("classes." + count + "/" + className + ".class");
  13.113 +        if (!expect.exists())
  13.114 +            throw new Exception("expected file not found: " + expect);
  13.115 +        long expectedSize = new File(testClassesDir.toString(), className + ".class").length();
  13.116 +        long actualSize = expect.length();
  13.117 +        if (expectedSize != actualSize)
  13.118 +            throw new Exception("wrong size found: " + actualSize + "; expected: " + expectedSize);
  13.119 +    }
  13.120 +
  13.121 +    boolean isJarFileSystemAvailable() {
  13.122 +        boolean result = false;
  13.123 +        for (FileSystemProvider fsp: FileSystemProvider.installedProviders()) {
  13.124 +            String scheme = fsp.getScheme();
  13.125 +            System.err.println("Provider: " + scheme + " " + fsp);
  13.126 +            if (scheme.equalsIgnoreCase("jar") || scheme.equalsIgnoreCase("zip"))
  13.127 +                result = true;
  13.128 +        }
  13.129 +        return result;
  13.130 +    }
  13.131 +
  13.132 +    void expand(File jar, File dir) throws IOException {
  13.133 +        JarFile jarFile = new JarFile(jar);
  13.134 +        try {
  13.135 +            Enumeration<JarEntry> entries = jarFile.entries();
  13.136 +            while (entries.hasMoreElements()) {
  13.137 +                JarEntry je = entries.nextElement();
  13.138 +                if (!je.isDirectory()) {
  13.139 +                    copy(jarFile.getInputStream(je), new File(dir, je.getName()));
  13.140 +                }
  13.141 +            }
  13.142 +        } finally {
  13.143 +            jarFile.close();
  13.144 +        }
  13.145 +    }
  13.146 +
  13.147 +    void copy(InputStream in, File dest) throws IOException {
  13.148 +        dest.getParentFile().mkdirs();
  13.149 +        OutputStream out = new BufferedOutputStream(new FileOutputStream(dest));
  13.150 +        try {
  13.151 +            byte[] data = new byte[8192];
  13.152 +            int n;
  13.153 +            while ((n = in.read(data, 0, data.length)) > 0)
  13.154 +                out.write(data, 0, n);
  13.155 +        } finally {
  13.156 +            out.close();
  13.157 +            in.close();
  13.158 +        }
  13.159 +    }
  13.160 +
  13.161 +    void error(String message) {
  13.162 +        System.err.println("Error: " + message);
  13.163 +        errors++;
  13.164 +    }
  13.165 +
  13.166 +    int errors;
  13.167 +    int count;
  13.168 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/test/tools/javac/nio/compileTest/HelloPathWorld.java	Fri Dec 11 14:26:27 2009 -0800
    14.3 @@ -0,0 +1,28 @@
    14.4 +/*
    14.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.7 + *
    14.8 + * This code is free software; you can redistribute it and/or modify it
    14.9 + * under the terms of the GNU General Public License version 2 only, as
   14.10 + * published by the Free Software Foundation.
   14.11 + *
   14.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   14.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14.15 + * version 2 for more details (a copy is included in the LICENSE file that
   14.16 + * accompanied this code).
   14.17 + *
   14.18 + * You should have received a copy of the GNU General Public License version
   14.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   14.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   14.21 + *
   14.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   14.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   14.24 + * have any questions.
   14.25 + */
   14.26 +
   14.27 +class HelloPathWorld {
   14.28 +    public static void main(String... args) {
   14.29 +        System.out.println("Hello World!");
   14.30 +    }
   14.31 +}

mercurial