Merge jdk7-b79

Sat, 19 Dec 2009 10:26:47 -0800

author
tbell
date
Sat, 19 Dec 2009 10:26:47 -0800
changeset 454
ac5b4c5644ce
parent 448
44022ba69c2f
parent 453
96c71cbc544b
child 455
f0074aa48d4e
child 457
0220a3ab1a40

Merge

src/share/classes/com/sun/tools/javac/file/CloseableURLClassLoader.java file | annotate | diff | comparison | revisions
     1.1 --- a/make/build.properties	Thu Dec 17 14:10:44 2009 -0800
     1.2 +++ b/make/build.properties	Sat Dec 19 10:26:47 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 17 14:10:44 2009 -0800
     2.2 +++ b/make/build.xml	Sat Dec 19 10:26:47 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 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/share/classes/com/sun/tools/classfile/Dependencies.java	Sat Dec 19 10:26:47 2009 -0800
     3.3 @@ -0,0 +1,718 @@
     3.4 +/*
     3.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.  Sun designates this
    3.11 + * particular file as subject to the "Classpath" exception as provided
    3.12 + * by Sun in the LICENSE file that accompanied this code.
    3.13 + *
    3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.17 + * version 2 for more details (a copy is included in the LICENSE file that
    3.18 + * accompanied this code).
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License version
    3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.23 + *
    3.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    3.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    3.26 + * have any questions.
    3.27 + */
    3.28 +package com.sun.tools.classfile;
    3.29 +
    3.30 +import java.util.Deque;
    3.31 +import java.util.HashMap;
    3.32 +import java.util.HashSet;
    3.33 +import java.util.LinkedList;
    3.34 +import java.util.List;
    3.35 +import java.util.Map;
    3.36 +import java.util.Set;
    3.37 +import java.util.regex.Pattern;
    3.38 +
    3.39 +import com.sun.tools.classfile.Dependency.Finder;
    3.40 +import com.sun.tools.classfile.Dependency.Filter;
    3.41 +import com.sun.tools.classfile.Dependency.Location;
    3.42 +import com.sun.tools.classfile.Type.ArrayType;
    3.43 +import com.sun.tools.classfile.Type.ClassSigType;
    3.44 +import com.sun.tools.classfile.Type.ClassType;
    3.45 +import com.sun.tools.classfile.Type.MethodType;
    3.46 +import com.sun.tools.classfile.Type.SimpleType;
    3.47 +import com.sun.tools.classfile.Type.TypeParamType;
    3.48 +import com.sun.tools.classfile.Type.WildcardType;
    3.49 +
    3.50 +import static com.sun.tools.classfile.ConstantPool.*;
    3.51 +
    3.52 +/**
    3.53 + * A framework for determining {@link Dependency dependencies} between class files.
    3.54 + *
    3.55 + * A {@link Dependency.Finder finder} is used to identify the dependencies of
    3.56 + * individual classes. Some finders may return subtypes of {@code Dependency} to
    3.57 + * further characterize the type of dependency, such as a dependency on a
    3.58 + * method within a class.
    3.59 + *
    3.60 + * A {@link Dependency.Filter filter} may be used to restrict the set of
    3.61 + * dependencies found by a finder.
    3.62 + *
    3.63 + * Dependencies that are found may be passed to a {@link Dependencies.Recorder
    3.64 + * recorder} so that the dependencies can be stored in a custom data structure.
    3.65 + */
    3.66 +public class Dependencies {
    3.67 +    /**
    3.68 +     * Thrown when a class file cannot be found.
    3.69 +     */
    3.70 +    public static class ClassFileNotFoundException extends Exception {
    3.71 +        private static final long serialVersionUID = 3632265927794475048L;
    3.72 +
    3.73 +        public ClassFileNotFoundException(String className) {
    3.74 +            super(className);
    3.75 +            this.className = className;
    3.76 +        }
    3.77 +
    3.78 +        public ClassFileNotFoundException(String className, Throwable cause) {
    3.79 +            this(className);
    3.80 +            initCause(cause);
    3.81 +        }
    3.82 +
    3.83 +        public final String className;
    3.84 +    }
    3.85 +
    3.86 +    /**
    3.87 +     * Thrown when an exception is found processing a class file.
    3.88 +     */
    3.89 +    public static class ClassFileError extends Error {
    3.90 +        private static final long serialVersionUID = 4111110813961313203L;
    3.91 +
    3.92 +        public ClassFileError(Throwable cause) {
    3.93 +            initCause(cause);
    3.94 +        }
    3.95 +    }
    3.96 +
    3.97 +    /**
    3.98 +     * Service provider interface to locate and read class files.
    3.99 +     */
   3.100 +    public interface ClassFileReader {
   3.101 +        /**
   3.102 +         * Get the ClassFile object for a specified class.
   3.103 +         * @param className the name of the class to be returned.
   3.104 +         * @return the ClassFile for the given class
   3.105 +         * @throws Dependencies#ClassFileNotFoundException if the classfile cannot be
   3.106 +         *   found
   3.107 +         */
   3.108 +        public ClassFile getClassFile(String className)
   3.109 +                throws ClassFileNotFoundException;
   3.110 +    }
   3.111 +
   3.112 +    /**
   3.113 +     * Service provide interface to handle results.
   3.114 +     */
   3.115 +    public interface Recorder {
   3.116 +        /**
   3.117 +         * Record a dependency that has been found.
   3.118 +         * @param d
   3.119 +         */
   3.120 +        public void addDependency(Dependency d);
   3.121 +    }
   3.122 +
   3.123 +    /**
   3.124 +     * Get the  default finder used to locate the dependencies for a class.
   3.125 +     * @return the default finder
   3.126 +     */
   3.127 +    public static Finder getDefaultFinder() {
   3.128 +        return new APIDependencyFinder(AccessFlags.ACC_PRIVATE);
   3.129 +    }
   3.130 +
   3.131 +    /**
   3.132 +     * Get a finder used to locate the API dependencies for a class.
   3.133 +     * These include the superclass, superinterfaces, and classes referenced in
   3.134 +     * the declarations of fields and methods.  The fields and methods that
   3.135 +     * are checked can be limited according to a specified access.
   3.136 +     * The access parameter must be one of {@link AccessFlags#ACC_PUBLIC ACC_PUBLIC},
   3.137 +     * {@link AccessFlags#ACC_PRIVATE ACC_PRIVATE},
   3.138 +     * {@link AccessFlags#ACC_PROTECTED ACC_PROTECTED}, or 0 for
   3.139 +     * package private access. Members with greater than or equal accessibility
   3.140 +     * to that specified will be searched for dependencies.
   3.141 +     * @param access the access of members to be checked
   3.142 +     * @return an API finder
   3.143 +     */
   3.144 +    public static Finder getAPIFinder(int access) {
   3.145 +        return new APIDependencyFinder(access);
   3.146 +    }
   3.147 +
   3.148 +    /**
   3.149 +     * Get the finder used to locate the dependencies for a class.
   3.150 +     * @return the finder
   3.151 +     */
   3.152 +    public Finder getFinder() {
   3.153 +        if (finder == null)
   3.154 +            finder = getDefaultFinder();
   3.155 +        return finder;
   3.156 +    }
   3.157 +
   3.158 +    /**
   3.159 +     * Set the finder used to locate the dependencies for a class.
   3.160 +     * @param f the finder
   3.161 +     */
   3.162 +    public void setFinder(Finder f) {
   3.163 +        f.getClass(); // null check
   3.164 +        finder = f;
   3.165 +    }
   3.166 +
   3.167 +    /**
   3.168 +     * Get the default filter used to determine included when searching
   3.169 +     * the transitive closure of all the dependencies.
   3.170 +     * Unless overridden, the default filter accepts all dependencies.
   3.171 +     * @return the default filter.
   3.172 +     */
   3.173 +    public static Filter getDefaultFilter() {
   3.174 +        return DefaultFilter.instance();
   3.175 +    }
   3.176 +
   3.177 +    /**
   3.178 +     * Get a filter which uses a regular expression on the target's class name
   3.179 +     * to determine if a dependency is of interest.
   3.180 +     * @param pattern the pattern used to match the target's class name
   3.181 +     * @return a filter for matching the target class name with a regular expression
   3.182 +     */
   3.183 +    public static Filter getRegexFilter(Pattern pattern) {
   3.184 +        return new TargetRegexFilter(pattern);
   3.185 +    }
   3.186 +
   3.187 +    /**
   3.188 +     * Get a filter which checks the package of a target's class name
   3.189 +     * to determine if a dependency is of interest. The filter checks if the
   3.190 +     * package of the target's class matches any of a set of given package
   3.191 +     * names. The match may optionally match subpackages of the given names as well.
   3.192 +     * @param packageNames the package names used to match the target's class name
   3.193 +     * @param matchSubpackages whether or not to match subpackages as well
   3.194 +     * @return a filter for checking the target package name against a list of package names
   3.195 +     */
   3.196 +    public static Filter getPackageFilter(Set<String> packageNames, boolean matchSubpackages) {
   3.197 +        return new TargetPackageFilter(packageNames, matchSubpackages);
   3.198 +    }
   3.199 +
   3.200 +    /**
   3.201 +     * Get the filter used to determine the dependencies included when searching
   3.202 +     * the transitive closure of all the dependencies.
   3.203 +     * Unless overridden, the default filter accepts all dependencies.
   3.204 +     * @return the filter
   3.205 +     */
   3.206 +    public Filter getFilter() {
   3.207 +        if (filter == null)
   3.208 +            filter = getDefaultFilter();
   3.209 +        return filter;
   3.210 +    }
   3.211 +
   3.212 +    /**
   3.213 +     * Set the filter used to determine the dependencies included when searching
   3.214 +     * the transitive closure of all the dependencies.
   3.215 +     * @param f the filter
   3.216 +     */
   3.217 +    public void setFilter(Filter f) {
   3.218 +        f.getClass(); // null check
   3.219 +        filter = f;
   3.220 +    }
   3.221 +
   3.222 +    /**
   3.223 +     * Find the dependencies of a class, using the current
   3.224 +     * {@link Dependencies#getFinder finder} and
   3.225 +     * {@link Dependencies#getFilter filter}.
   3.226 +     * The search may optionally include the transitive closure of all the
   3.227 +     * filtered dependencies, by also searching in the classes named in those
   3.228 +     * dependencies.
   3.229 +     * @param classFinder a finder to locate class files
   3.230 +     * @param rootClassNames the names of the root classes from which to begin
   3.231 +     *      searching
   3.232 +     * @param transitiveClosure whether or not to also search those classes
   3.233 +     *      named in any filtered dependencies that are found.
   3.234 +     * @return the set of dependencies that were found
   3.235 +     * @throws ClassFileNotFoundException if a required class file cannot be found
   3.236 +     * @throws ClassFileError if an error occurs while processing a class file,
   3.237 +     *      such as an error in the internal class file structure.
   3.238 +     */
   3.239 +    public Set<Dependency> findAllDependencies(
   3.240 +            ClassFileReader classFinder, Set<String> rootClassNames,
   3.241 +            boolean transitiveClosure)
   3.242 +            throws ClassFileNotFoundException {
   3.243 +        final Set<Dependency> results = new HashSet<Dependency>();
   3.244 +        Recorder r = new Recorder() {
   3.245 +            public void addDependency(Dependency d) {
   3.246 +                results.add(d);
   3.247 +            }
   3.248 +        };
   3.249 +        findAllDependencies(classFinder, rootClassNames, transitiveClosure, r);
   3.250 +        return results;
   3.251 +    }
   3.252 +
   3.253 +
   3.254 +
   3.255 +    /**
   3.256 +     * Find the dependencies of a class, using the current
   3.257 +     * {@link Dependencies#getFinder finder} and
   3.258 +     * {@link Dependencies#getFilter filter}.
   3.259 +     * The search may optionally include the transitive closure of all the
   3.260 +     * filtered dependencies, by also searching in the classes named in those
   3.261 +     * dependencies.
   3.262 +     * @param classFinder a finder to locate class files
   3.263 +     * @param rootClassNames the names of the root classes from which to begin
   3.264 +     *      searching
   3.265 +     * @param transitiveClosure whether or not to also search those classes
   3.266 +     *      named in any filtered dependencies that are found.
   3.267 +     * @param recorder a recorder for handling the results
   3.268 +     * @throws ClassFileNotFoundException if a required class file cannot be found
   3.269 +     * @throws ClassFileError if an error occurs while processing a class file,
   3.270 +     *      such as an error in the internal class file structure.
   3.271 +     */
   3.272 +    public void findAllDependencies(
   3.273 +            ClassFileReader classFinder, Set<String> rootClassNames,
   3.274 +            boolean transitiveClosure, Recorder recorder)
   3.275 +            throws ClassFileNotFoundException {
   3.276 +        Set<String> doneClasses = new HashSet<String>();
   3.277 +
   3.278 +        getFinder();  // ensure initialized
   3.279 +        getFilter();  // ensure initialized
   3.280 +
   3.281 +        // Work queue of names of classfiles to be searched.
   3.282 +        // Entries will be unique, and for classes that do not yet have
   3.283 +        // dependencies in the results map.
   3.284 +        Deque<String> deque = new LinkedList<String>(rootClassNames);
   3.285 +
   3.286 +        String className;
   3.287 +        while ((className = deque.poll()) != null) {
   3.288 +            assert (!doneClasses.contains(className));
   3.289 +            doneClasses.add(className);
   3.290 +
   3.291 +            ClassFile cf = classFinder.getClassFile(className);
   3.292 +
   3.293 +            // The following code just applies the filter to the dependencies
   3.294 +            // followed for the transitive closure.
   3.295 +            for (Dependency d: finder.findDependencies(cf)) {
   3.296 +                recorder.addDependency(d);
   3.297 +                if (transitiveClosure && filter.accepts(d)) {
   3.298 +                    String cn = d.getTarget().getClassName();
   3.299 +                    if (!doneClasses.contains(cn))
   3.300 +                        deque.add(cn);
   3.301 +                }
   3.302 +            }
   3.303 +        }
   3.304 +    }
   3.305 +
   3.306 +    private Filter filter;
   3.307 +    private Finder finder;
   3.308 +
   3.309 +    /**
   3.310 +     * A location identifying a class.
   3.311 +     */
   3.312 +    static class SimpleLocation implements Location {
   3.313 +        public SimpleLocation(String className) {
   3.314 +            this.className = className;
   3.315 +        }
   3.316 +
   3.317 +        /**
   3.318 +         * Get the name of the class being depended on. This name will be used to
   3.319 +         * locate the class file for transitive dependency analysis.
   3.320 +         * @return the name of the class being depended on
   3.321 +         */
   3.322 +        public String getClassName() {
   3.323 +            return className;
   3.324 +        }
   3.325 +
   3.326 +        @Override
   3.327 +        public boolean equals(Object other) {
   3.328 +            if (this == other)
   3.329 +                return true;
   3.330 +            if (!(other instanceof SimpleLocation))
   3.331 +                return false;
   3.332 +            return (className.equals(((SimpleLocation) other).className));
   3.333 +        }
   3.334 +
   3.335 +        @Override
   3.336 +        public int hashCode() {
   3.337 +            return className.hashCode();
   3.338 +        }
   3.339 +
   3.340 +        @Override
   3.341 +        public String toString() {
   3.342 +            return className;
   3.343 +        }
   3.344 +
   3.345 +        private String className;
   3.346 +    }
   3.347 +
   3.348 +    /**
   3.349 +     * A dependency of one class on another.
   3.350 +     */
   3.351 +    static class SimpleDependency implements Dependency {
   3.352 +        public SimpleDependency(Location origin, Location target) {
   3.353 +            this.origin = origin;
   3.354 +            this.target = target;
   3.355 +        }
   3.356 +
   3.357 +        public Location getOrigin() {
   3.358 +            return origin;
   3.359 +        }
   3.360 +
   3.361 +        public Location getTarget() {
   3.362 +            return target;
   3.363 +        }
   3.364 +
   3.365 +        @Override
   3.366 +        public boolean equals(Object other) {
   3.367 +            if (this == other)
   3.368 +                return true;
   3.369 +            if (!(other instanceof SimpleDependency))
   3.370 +                return false;
   3.371 +            SimpleDependency o = (SimpleDependency) other;
   3.372 +            return (origin.equals(o.origin) && target.equals(o.target));
   3.373 +        }
   3.374 +
   3.375 +        @Override
   3.376 +        public int hashCode() {
   3.377 +            return origin.hashCode() * 31 + target.hashCode();
   3.378 +        }
   3.379 +
   3.380 +        @Override
   3.381 +        public String toString() {
   3.382 +            return origin + ":" + target;
   3.383 +        }
   3.384 +
   3.385 +        private Location origin;
   3.386 +        private Location target;
   3.387 +    }
   3.388 +
   3.389 +
   3.390 +    /**
   3.391 +     * This class accepts all dependencies.
   3.392 +     */
   3.393 +    static class DefaultFilter implements Filter {
   3.394 +        private static DefaultFilter instance;
   3.395 +
   3.396 +        static DefaultFilter instance() {
   3.397 +            if (instance == null)
   3.398 +                instance = new DefaultFilter();
   3.399 +            return instance;
   3.400 +        }
   3.401 +
   3.402 +        public boolean accepts(Dependency dependency) {
   3.403 +            return true;
   3.404 +        }
   3.405 +    }
   3.406 +
   3.407 +    /**
   3.408 +     * This class accepts those dependencies whose target's class name matches a
   3.409 +     * regular expression.
   3.410 +     */
   3.411 +    static class TargetRegexFilter implements Filter {
   3.412 +        TargetRegexFilter(Pattern pattern) {
   3.413 +            this.pattern = pattern;
   3.414 +        }
   3.415 +
   3.416 +        public boolean accepts(Dependency dependency) {
   3.417 +            return pattern.matcher(dependency.getTarget().getClassName()).matches();
   3.418 +        }
   3.419 +
   3.420 +        private final Pattern pattern;
   3.421 +    }
   3.422 +
   3.423 +    /**
   3.424 +     * This class accepts those dependencies whose class name is in a given
   3.425 +     * package.
   3.426 +     */
   3.427 +    static class TargetPackageFilter implements Filter {
   3.428 +        TargetPackageFilter(Set<String> packageNames, boolean matchSubpackages) {
   3.429 +            for (String pn: packageNames) {
   3.430 +                if (pn.length() == 0) // implies null check as well
   3.431 +                    throw new IllegalArgumentException();
   3.432 +            }
   3.433 +            this.packageNames = packageNames;
   3.434 +            this.matchSubpackages = matchSubpackages;
   3.435 +        }
   3.436 +
   3.437 +        public boolean accepts(Dependency dependency) {
   3.438 +            String cn = dependency.getTarget().getClassName();
   3.439 +            int lastSep = cn.lastIndexOf("/");
   3.440 +            String pn = (lastSep == -1 ? "" : cn.substring(0, lastSep));
   3.441 +            if (packageNames.contains(pn))
   3.442 +                return true;
   3.443 +
   3.444 +            if (matchSubpackages) {
   3.445 +                for (String n: packageNames) {
   3.446 +                    if (pn.startsWith(n + "."))
   3.447 +                        return true;
   3.448 +                }
   3.449 +            }
   3.450 +
   3.451 +            return false;
   3.452 +        }
   3.453 +
   3.454 +        private final Set<String> packageNames;
   3.455 +        private final boolean matchSubpackages;
   3.456 +    }
   3.457 +
   3.458 +
   3.459 +
   3.460 +    /**
   3.461 +     * This class identifies class names directly or indirectly in the constant pool.
   3.462 +     */
   3.463 +    static class ClassDependencyFinder extends BasicDependencyFinder {
   3.464 +        public Iterable<? extends Dependency> findDependencies(ClassFile classfile) {
   3.465 +            Visitor v = new Visitor(classfile);
   3.466 +            for (CPInfo cpInfo: classfile.constant_pool.entries()) {
   3.467 +                v.scan(cpInfo);
   3.468 +            }
   3.469 +            return v.deps;
   3.470 +        }
   3.471 +    }
   3.472 +
   3.473 +    /**
   3.474 +     * This class identifies class names in the signatures of classes, fields,
   3.475 +     * and methods in a class.
   3.476 +     */
   3.477 +    static class APIDependencyFinder extends BasicDependencyFinder {
   3.478 +        APIDependencyFinder(int access) {
   3.479 +            switch (access) {
   3.480 +                case AccessFlags.ACC_PUBLIC:
   3.481 +                case AccessFlags.ACC_PROTECTED:
   3.482 +                case AccessFlags.ACC_PRIVATE:
   3.483 +                case 0:
   3.484 +                    showAccess = access;
   3.485 +                    break;
   3.486 +                default:
   3.487 +                    throw new IllegalArgumentException("invalid access 0x"
   3.488 +                            + Integer.toHexString(access));
   3.489 +            }
   3.490 +        }
   3.491 +
   3.492 +        public Iterable<? extends Dependency> findDependencies(ClassFile classfile) {
   3.493 +            try {
   3.494 +                Visitor v = new Visitor(classfile);
   3.495 +                v.addClass(classfile.super_class);
   3.496 +                v.addClasses(classfile.interfaces);
   3.497 +                // inner classes?
   3.498 +                for (Field f : classfile.fields) {
   3.499 +                    if (checkAccess(f.access_flags))
   3.500 +                        v.scan(f.descriptor, f.attributes);
   3.501 +                }
   3.502 +                for (Method m : classfile.methods) {
   3.503 +                    if (checkAccess(m.access_flags)) {
   3.504 +                        v.scan(m.descriptor, m.attributes);
   3.505 +                        Exceptions_attribute e =
   3.506 +                                (Exceptions_attribute) m.attributes.get(Attribute.Exceptions);
   3.507 +                        if (e != null)
   3.508 +                            v.addClasses(e.exception_index_table);
   3.509 +                    }
   3.510 +                }
   3.511 +                return v.deps;
   3.512 +            } catch (ConstantPoolException e) {
   3.513 +                throw new ClassFileError(e);
   3.514 +            }
   3.515 +        }
   3.516 +
   3.517 +        boolean checkAccess(AccessFlags flags) {
   3.518 +            // code copied from javap.Options.checkAccess
   3.519 +            boolean isPublic = flags.is(AccessFlags.ACC_PUBLIC);
   3.520 +            boolean isProtected = flags.is(AccessFlags.ACC_PROTECTED);
   3.521 +            boolean isPrivate = flags.is(AccessFlags.ACC_PRIVATE);
   3.522 +            boolean isPackage = !(isPublic || isProtected || isPrivate);
   3.523 +
   3.524 +            if ((showAccess == AccessFlags.ACC_PUBLIC) && (isProtected || isPrivate || isPackage))
   3.525 +                return false;
   3.526 +            else if ((showAccess == AccessFlags.ACC_PROTECTED) && (isPrivate || isPackage))
   3.527 +                return false;
   3.528 +            else if ((showAccess == 0) && (isPrivate))
   3.529 +                return false;
   3.530 +            else
   3.531 +                return true;
   3.532 +        }
   3.533 +
   3.534 +        private int showAccess;
   3.535 +    }
   3.536 +
   3.537 +    static abstract class BasicDependencyFinder implements Finder {
   3.538 +        private Map<String,Location> locations = new HashMap<String,Location>();
   3.539 +
   3.540 +        Location getLocation(String className) {
   3.541 +            Location l = locations.get(className);
   3.542 +            if (l == null)
   3.543 +                locations.put(className, l = new SimpleLocation(className));
   3.544 +            return l;
   3.545 +        }
   3.546 +
   3.547 +        class Visitor implements ConstantPool.Visitor<Void,Void>, Type.Visitor<Void, Void> {
   3.548 +            private ConstantPool constant_pool;
   3.549 +            private Location origin;
   3.550 +            Set<Dependency> deps;
   3.551 +
   3.552 +            Visitor(ClassFile classFile) {
   3.553 +                try {
   3.554 +                    constant_pool = classFile.constant_pool;
   3.555 +                    origin = getLocation(classFile.getName());
   3.556 +                    deps = new HashSet<Dependency>();
   3.557 +                } catch (ConstantPoolException e) {
   3.558 +                    throw new ClassFileError(e);
   3.559 +                }
   3.560 +            }
   3.561 +
   3.562 +            void scan(Descriptor d, Attributes attrs) {
   3.563 +                try {
   3.564 +                    scan(new Signature(d.index).getType(constant_pool));
   3.565 +                    Signature_attribute sa = (Signature_attribute) attrs.get(Attribute.Signature);
   3.566 +                    if (sa != null)
   3.567 +                        scan(new Signature(sa.signature_index).getType(constant_pool));
   3.568 +                } catch (ConstantPoolException e) {
   3.569 +                    throw new ClassFileError(e);
   3.570 +                }
   3.571 +            }
   3.572 +
   3.573 +            void scan(CPInfo cpInfo) {
   3.574 +                cpInfo.accept(this, null);
   3.575 +            }
   3.576 +
   3.577 +            void scan(Type t) {
   3.578 +                t.accept(this, null);
   3.579 +            }
   3.580 +
   3.581 +            void addClass(int index) throws ConstantPoolException {
   3.582 +                if (index != 0) {
   3.583 +                    String name = constant_pool.getClassInfo(index).getBaseName();
   3.584 +                    if (name != null)
   3.585 +                        addDependency(name);
   3.586 +                }
   3.587 +            }
   3.588 +
   3.589 +            void addClasses(int[] indices) throws ConstantPoolException {
   3.590 +                for (int i: indices)
   3.591 +                    addClass(i);
   3.592 +            }
   3.593 +
   3.594 +            private void addDependency(String name) {
   3.595 +                deps.add(new SimpleDependency(origin, getLocation(name)));
   3.596 +            }
   3.597 +
   3.598 +            // ConstantPool.Visitor methods
   3.599 +
   3.600 +            public Void visitClass(CONSTANT_Class_info info, Void p) {
   3.601 +                try {
   3.602 +                    if (info.getName().startsWith("["))
   3.603 +                        new Signature(info.name_index).getType(constant_pool).accept(this, null);
   3.604 +                    else
   3.605 +                        addDependency(info.getBaseName());
   3.606 +                    return null;
   3.607 +                } catch (ConstantPoolException e) {
   3.608 +                    throw new ClassFileError(e);
   3.609 +                }
   3.610 +            }
   3.611 +
   3.612 +            public Void visitDouble(CONSTANT_Double_info info, Void p) {
   3.613 +                return null;
   3.614 +            }
   3.615 +
   3.616 +            public Void visitFieldref(CONSTANT_Fieldref_info info, Void p) {
   3.617 +                return visitRef(info, p);
   3.618 +            }
   3.619 +
   3.620 +            public Void visitFloat(CONSTANT_Float_info info, Void p) {
   3.621 +                return null;
   3.622 +            }
   3.623 +
   3.624 +            public Void visitInteger(CONSTANT_Integer_info info, Void p) {
   3.625 +                return null;
   3.626 +            }
   3.627 +
   3.628 +            public Void visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
   3.629 +                return visitRef(info, p);
   3.630 +            }
   3.631 +
   3.632 +            public Void visitLong(CONSTANT_Long_info info, Void p) {
   3.633 +                return null;
   3.634 +            }
   3.635 +
   3.636 +            public Void visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
   3.637 +                try {
   3.638 +                    new Signature(info.type_index).getType(constant_pool).accept(this, null);
   3.639 +                    return null;
   3.640 +                } catch (ConstantPoolException e) {
   3.641 +                    throw new ClassFileError(e);
   3.642 +                }
   3.643 +            }
   3.644 +
   3.645 +            public Void visitMethodref(CONSTANT_Methodref_info info, Void p) {
   3.646 +                return visitRef(info, p);
   3.647 +            }
   3.648 +
   3.649 +            public Void visitString(CONSTANT_String_info info, Void p) {
   3.650 +                return null;
   3.651 +            }
   3.652 +
   3.653 +            public Void visitUtf8(CONSTANT_Utf8_info info, Void p) {
   3.654 +                return null;
   3.655 +            }
   3.656 +
   3.657 +            private Void visitRef(CPRefInfo info, Void p) {
   3.658 +                try {
   3.659 +                    visitClass(info.getClassInfo(), p);
   3.660 +                    return null;
   3.661 +                } catch (ConstantPoolException e) {
   3.662 +                    throw new ClassFileError(e);
   3.663 +                }
   3.664 +            }
   3.665 +
   3.666 +            // Type.Visitor methods
   3.667 +
   3.668 +            private void findDependencies(Type t) {
   3.669 +                if (t != null)
   3.670 +                    t.accept(this, null);
   3.671 +            }
   3.672 +
   3.673 +            private void findDependencies(List<? extends Type> ts) {
   3.674 +                if (ts != null) {
   3.675 +                    for (Type t: ts)
   3.676 +                        t.accept(this, null);
   3.677 +                }
   3.678 +            }
   3.679 +
   3.680 +            public Void visitSimpleType(SimpleType type, Void p) {
   3.681 +                return null;
   3.682 +            }
   3.683 +
   3.684 +            public Void visitArrayType(ArrayType type, Void p) {
   3.685 +                findDependencies(type.elemType);
   3.686 +                return null;
   3.687 +            }
   3.688 +
   3.689 +            public Void visitMethodType(MethodType type, Void p) {
   3.690 +                findDependencies(type.paramTypes);
   3.691 +                findDependencies(type.returnType);
   3.692 +                findDependencies(type.throwsTypes);
   3.693 +                return null;
   3.694 +            }
   3.695 +
   3.696 +            public Void visitClassSigType(ClassSigType type, Void p) {
   3.697 +                findDependencies(type.superclassType);
   3.698 +                findDependencies(type.superinterfaceTypes);
   3.699 +                return null;
   3.700 +            }
   3.701 +
   3.702 +            public Void visitClassType(ClassType type, Void p) {
   3.703 +                findDependencies(type.outerType);
   3.704 +                addDependency(type.name);
   3.705 +                findDependencies(type.typeArgs);
   3.706 +                return null;
   3.707 +            }
   3.708 +
   3.709 +            public Void visitTypeParamType(TypeParamType type, Void p) {
   3.710 +                findDependencies(type.classBound);
   3.711 +                findDependencies(type.interfaceBounds);
   3.712 +                return null;
   3.713 +            }
   3.714 +
   3.715 +            public Void visitWildcardType(WildcardType type, Void p) {
   3.716 +                findDependencies(type.boundType);
   3.717 +                return null;
   3.718 +            }
   3.719 +        }
   3.720 +    }
   3.721 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/share/classes/com/sun/tools/classfile/Dependency.java	Sat Dec 19 10:26:47 2009 -0800
     4.3 @@ -0,0 +1,90 @@
     4.4 +/*
     4.5 + * Copyright 2009 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.classfile;
    4.30 +
    4.31 +
    4.32 +/**
    4.33 + * A directed relationship between two {@link Dependency.Location Location}s.
    4.34 + * Subtypes of {@code Dependency} may provide additional detail about the dependency.
    4.35 + *
    4.36 + * @see Dependency.Finder
    4.37 + * @see Dependency.Filter
    4.38 + * @see Dependencies
    4.39 + */
    4.40 +public interface Dependency {
    4.41 +    /**
    4.42 +     * A filter used to select dependencies of interest, and to discard others.
    4.43 +     */
    4.44 +    public interface Filter {
    4.45 +        /**
    4.46 +         * Return true if the dependency is of interest.
    4.47 +         * @param dependency the dependency to be considered
    4.48 +         * @return true if and only if the dependency is of interest.
    4.49 +         */
    4.50 +        boolean accepts(Dependency dependency);
    4.51 +    }
    4.52 +
    4.53 +    /**
    4.54 +     * An interface for finding the immediate dependencies of a given class file.
    4.55 +     */
    4.56 +    public interface Finder {
    4.57 +        /**
    4.58 +         * Find the immediate dependencies of a given class file.
    4.59 +         * @param classfile the class file to be examined
    4.60 +         * @return the dependencies located in the given class file.
    4.61 +         */
    4.62 +        public Iterable<? extends Dependency> findDependencies(ClassFile classfile);
    4.63 +    }
    4.64 +
    4.65 +
    4.66 +    /**
    4.67 +     * A location somewhere within a class. Subtypes of {@code Location}
    4.68 +     * may be used to provide additional detail about the location.
    4.69 +     */
    4.70 +    public interface Location {
    4.71 +        /**
    4.72 +         * Get the name of the class containing the location.
    4.73 +         * This name will be used to locate the class file for transitive
    4.74 +         * dependency analysis.
    4.75 +         * @return the name of the class containing the location.
    4.76 +         */
    4.77 +        String getClassName();
    4.78 +    }
    4.79 +
    4.80 +
    4.81 +    /**
    4.82 +     * Get the location that has the dependency.
    4.83 +     * @return the location that has the dependency.
    4.84 +     */
    4.85 +    Location getOrigin();
    4.86 +
    4.87 +    /**
    4.88 +     * Get the location that is being depended upon.
    4.89 +     * @return the location that is being depended upon.
    4.90 +     */
    4.91 +    Location getTarget();
    4.92 +}
    4.93 +
     5.1 --- a/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java	Thu Dec 17 14:10:44 2009 -0800
     5.2 +++ b/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java	Sat Dec 19 10:26:47 2009 -0800
     5.3 @@ -39,6 +39,8 @@
     5.4  
     5.5  import static javax.tools.JavaFileObject.Kind.*;
     5.6  
     5.7 +import com.sun.tools.javac.util.BaseFileManager;
     5.8 +
     5.9  /**
    5.10   * <p><b>This is NOT part of any API supported by Sun Microsystems.
    5.11   * If you write code that depends on this, you do so at your own risk.
    5.12 @@ -74,14 +76,7 @@
    5.13      protected abstract String inferBinaryName(Iterable<? extends File> path);
    5.14  
    5.15      protected static JavaFileObject.Kind getKind(String filename) {
    5.16 -        if (filename.endsWith(CLASS.extension))
    5.17 -            return CLASS;
    5.18 -        else if (filename.endsWith(SOURCE.extension))
    5.19 -            return SOURCE;
    5.20 -        else if (filename.endsWith(HTML.extension))
    5.21 -            return HTML;
    5.22 -        else
    5.23 -            return OTHER;
    5.24 +        return BaseFileManager.getKind(filename);
    5.25      }
    5.26  
    5.27      protected static String removeExtension(String fileName) {
     6.1 --- a/src/share/classes/com/sun/tools/javac/file/CloseableURLClassLoader.java	Thu Dec 17 14:10:44 2009 -0800
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,107 +0,0 @@
     6.4 -/*
     6.5 - * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
     6.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.7 - *
     6.8 - * This code is free software; you can redistribute it and/or modify it
     6.9 - * under the terms of the GNU General Public License version 2 only, as
    6.10 - * published by the Free Software Foundation.  Sun designates this
    6.11 - * particular file as subject to the "Classpath" exception as provided
    6.12 - * by Sun in the LICENSE file that accompanied this code.
    6.13 - *
    6.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
    6.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    6.17 - * version 2 for more details (a copy is included in the LICENSE file that
    6.18 - * accompanied this code).
    6.19 - *
    6.20 - * You should have received a copy of the GNU General Public License version
    6.21 - * 2 along with this work; if not, write to the Free Software Foundation,
    6.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    6.23 - *
    6.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    6.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
    6.26 - * have any questions.
    6.27 - */
    6.28 -
    6.29 -package com.sun.tools.javac.file;
    6.30 -
    6.31 -import java.io.Closeable;
    6.32 -import java.io.IOException;
    6.33 -import java.lang.reflect.Field;
    6.34 -import java.net.URL;
    6.35 -import java.net.URLClassLoader;
    6.36 -import java.util.ArrayList;
    6.37 -import java.util.jar.JarFile;
    6.38 -
    6.39 -/**
    6.40 - * A URLClassLoader that also implements Closeable.
    6.41 - * Reflection is used to access internal data structures in the URLClassLoader,
    6.42 - * since no public API exists for this purpose. Therefore this code is somewhat
    6.43 - * fragile. Caveat emptor.
    6.44 - * @throws Error if the internal data structures are not as expected.
    6.45 - *
    6.46 - *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    6.47 - *  you write code that depends on this, you do so at your own risk.
    6.48 - *  This code and its internal interfaces are subject to change or
    6.49 - *  deletion without notice.</b>
    6.50 - */
    6.51 -class CloseableURLClassLoader
    6.52 -        extends URLClassLoader implements Closeable {
    6.53 -    CloseableURLClassLoader(URL[] urls, ClassLoader parent) throws Error {
    6.54 -        super(urls, parent);
    6.55 -        try {
    6.56 -            getLoaders(); //proactive check that URLClassLoader is as expected
    6.57 -        } catch (Throwable t) {
    6.58 -            throw new Error("cannot create CloseableURLClassLoader", t);
    6.59 -        }
    6.60 -    }
    6.61 -
    6.62 -    /**
    6.63 -     * Close any jar files that may have been opened by the class loader.
    6.64 -     * Reflection is used to access the jar files in the URLClassLoader's
    6.65 -     * internal data structures.
    6.66 -     * @throws java.io.IOException if the jar files cannot be found for any
    6.67 -     * reson, or if closing the jar file itself causes an IOException.
    6.68 -     */
    6.69 -    public void close() throws IOException {
    6.70 -        try {
    6.71 -            for (Object l: getLoaders()) {
    6.72 -                if (l.getClass().getName().equals("sun.misc.URLClassPath$JarLoader")) {
    6.73 -                    Field jarField = l.getClass().getDeclaredField("jar");
    6.74 -                    JarFile jar = (JarFile) getField(l, jarField);
    6.75 -                    if (jar != null) {
    6.76 -                        //System.err.println("CloseableURLClassLoader: closing " + jar);
    6.77 -                        jar.close();
    6.78 -                    }
    6.79 -                }
    6.80 -            }
    6.81 -        } catch (Throwable t) {
    6.82 -            IOException e = new IOException("cannot close class loader");
    6.83 -            e.initCause(t);
    6.84 -            throw e;
    6.85 -        }
    6.86 -    }
    6.87 -
    6.88 -    private ArrayList<?> getLoaders()
    6.89 -            throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException
    6.90 -    {
    6.91 -        Field ucpField = URLClassLoader.class.getDeclaredField("ucp");
    6.92 -        Object urlClassPath = getField(this, ucpField);
    6.93 -        if (urlClassPath == null)
    6.94 -            throw new AssertionError("urlClassPath not set in URLClassLoader");
    6.95 -        Field loadersField = urlClassPath.getClass().getDeclaredField("loaders");
    6.96 -        return (ArrayList<?>) getField(urlClassPath, loadersField);
    6.97 -    }
    6.98 -
    6.99 -    private Object getField(Object o, Field f)
   6.100 -            throws IllegalArgumentException, IllegalAccessException {
   6.101 -        boolean prev = f.isAccessible();
   6.102 -        try {
   6.103 -            f.setAccessible(true);
   6.104 -            return f.get(o);
   6.105 -        } finally {
   6.106 -            f.setAccessible(prev);
   6.107 -        }
   6.108 -    }
   6.109 -
   6.110 -}
     7.1 --- a/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Thu Dec 17 14:10:44 2009 -0800
     7.2 +++ b/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Sat Dec 19 10:26:47 2009 -0800
     7.3 @@ -26,29 +26,16 @@
     7.4  package com.sun.tools.javac.file;
     7.5  
     7.6  import java.io.ByteArrayOutputStream;
     7.7 -import java.io.Closeable;
     7.8  import java.io.File;
     7.9 -import java.io.FileInputStream;
    7.10  import java.io.FileNotFoundException;
    7.11  import java.io.IOException;
    7.12 -import java.io.InputStream;
    7.13  import java.io.OutputStreamWriter;
    7.14 -import java.lang.ref.SoftReference;
    7.15 -import java.lang.reflect.Constructor;
    7.16  import java.net.MalformedURLException;
    7.17  import java.net.URI;
    7.18  import java.net.URISyntaxException;
    7.19  import java.net.URL;
    7.20 -import java.net.URLClassLoader;
    7.21 -import java.nio.ByteBuffer;
    7.22  import java.nio.CharBuffer;
    7.23 -import java.nio.channels.FileChannel;
    7.24  import java.nio.charset.Charset;
    7.25 -import java.nio.charset.CharsetDecoder;
    7.26 -import java.nio.charset.CoderResult;
    7.27 -import java.nio.charset.CodingErrorAction;
    7.28 -import java.nio.charset.IllegalCharsetNameException;
    7.29 -import java.nio.charset.UnsupportedCharsetException;
    7.30  import java.util.ArrayList;
    7.31  import java.util.Arrays;
    7.32  import java.util.Collection;
    7.33 @@ -66,18 +53,13 @@
    7.34  import javax.tools.JavaFileObject;
    7.35  import javax.tools.StandardJavaFileManager;
    7.36  
    7.37 -import com.sun.tools.javac.code.Source;
    7.38  import com.sun.tools.javac.file.RelativePath.RelativeFile;
    7.39  import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
    7.40 -import com.sun.tools.javac.main.JavacOption;
    7.41  import com.sun.tools.javac.main.OptionName;
    7.42 -import com.sun.tools.javac.main.RecognizedOptions;
    7.43 +import com.sun.tools.javac.util.BaseFileManager;
    7.44  import com.sun.tools.javac.util.Context;
    7.45 -import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
    7.46  import com.sun.tools.javac.util.List;
    7.47  import com.sun.tools.javac.util.ListBuffer;
    7.48 -import com.sun.tools.javac.util.Log;
    7.49 -import com.sun.tools.javac.util.Options;
    7.50  
    7.51  import static javax.tools.StandardLocation.*;
    7.52  import static com.sun.tools.javac.main.OptionName.*;
    7.53 @@ -91,7 +73,7 @@
    7.54   * This code and its internal interfaces are subject to change or
    7.55   * deletion without notice.</b>
    7.56   */
    7.57 -public class JavacFileManager implements StandardJavaFileManager {
    7.58 +public class JavacFileManager extends BaseFileManager implements StandardJavaFileManager {
    7.59  
    7.60      boolean useZipFileIndex;
    7.61  
    7.62 @@ -102,17 +84,10 @@
    7.63              return buffer.toString().toCharArray();
    7.64      }
    7.65  
    7.66 -    /**
    7.67 -     * The log to be used for error reporting.
    7.68 -     */
    7.69 -    protected Log log;
    7.70 -
    7.71      /** Encapsulates knowledge of paths
    7.72       */
    7.73      private Paths paths;
    7.74  
    7.75 -    private Options options;
    7.76 -
    7.77      private FSInfo fsInfo;
    7.78  
    7.79      private final File uninited = new File("U N I N I T E D");
    7.80 @@ -134,12 +109,6 @@
    7.81  
    7.82      protected boolean mmappedIO;
    7.83      protected boolean ignoreSymbolFile;
    7.84 -    protected String classLoaderClass;
    7.85 -
    7.86 -    /**
    7.87 -     * User provided charset (through javax.tools).
    7.88 -     */
    7.89 -    protected Charset charset;
    7.90  
    7.91      /**
    7.92       * Register a Context.Factory to create a JavacFileManager.
    7.93 @@ -157,18 +126,18 @@
    7.94       * it as the JavaFileManager for that context.
    7.95       */
    7.96      public JavacFileManager(Context context, boolean register, Charset charset) {
    7.97 +        super(charset);
    7.98          if (register)
    7.99              context.put(JavaFileManager.class, this);
   7.100 -        byteBufferCache = new ByteBufferCache();
   7.101 -        this.charset = charset;
   7.102          setContext(context);
   7.103      }
   7.104  
   7.105      /**
   7.106       * Set the context for JavacFileManager.
   7.107       */
   7.108 +    @Override
   7.109      public void setContext(Context context) {
   7.110 -        log = Log.instance(context);
   7.111 +        super.setContext(context);
   7.112          if (paths == null) {
   7.113              paths = Paths.instance(context);
   7.114          } else {
   7.115 @@ -177,14 +146,12 @@
   7.116              paths.setContext(context);
   7.117          }
   7.118  
   7.119 -        options = Options.instance(context);
   7.120          fsInfo = FSInfo.instance(context);
   7.121  
   7.122          useZipFileIndex = System.getProperty("useJavaUtilZip") == null;// TODO: options.get("useJavaUtilZip") == null;
   7.123  
   7.124          mmappedIO = options.get("mmappedIO") != null;
   7.125          ignoreSymbolFile = options.get("ignore.symbol.file") != null;
   7.126 -        classLoaderClass = options.get("procloader");
   7.127      }
   7.128  
   7.129      public JavaFileObject getFileForInput(String name) {
   7.130 @@ -214,17 +181,6 @@
   7.131          return getJavaFileObjectsFromStrings(Arrays.asList(nullCheck(names)));
   7.132      }
   7.133  
   7.134 -    protected JavaFileObject.Kind getKind(String extension) {
   7.135 -        if (extension.equals(JavaFileObject.Kind.CLASS.extension))
   7.136 -            return JavaFileObject.Kind.CLASS;
   7.137 -        else if (extension.equals(JavaFileObject.Kind.SOURCE.extension))
   7.138 -            return JavaFileObject.Kind.SOURCE;
   7.139 -        else if (extension.equals(JavaFileObject.Kind.HTML.extension))
   7.140 -            return JavaFileObject.Kind.HTML;
   7.141 -        else
   7.142 -            return JavaFileObject.Kind.OTHER;
   7.143 -    }
   7.144 -
   7.145      private static boolean isValidName(String name) {
   7.146          // Arguably, isValidName should reject keywords (such as in SourceVersion.isName() ),
   7.147          // but the set of keywords depends on the source level, and we don't want
   7.148 @@ -359,9 +315,7 @@
   7.149      }
   7.150  
   7.151      private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
   7.152 -        int lastDot = s.lastIndexOf(".");
   7.153 -        String extn = (lastDot == -1 ? s : s.substring(lastDot));
   7.154 -        JavaFileObject.Kind kind = getKind(extn);
   7.155 +        JavaFileObject.Kind kind = getKind(s);
   7.156          return fileKinds.contains(kind);
   7.157      }
   7.158  
   7.159 @@ -564,18 +518,6 @@
   7.160          }
   7.161      }
   7.162  
   7.163 -    CharBuffer getCachedContent(JavaFileObject file) {
   7.164 -        SoftReference<CharBuffer> r = contentCache.get(file);
   7.165 -        return (r == null ? null : r.get());
   7.166 -    }
   7.167 -
   7.168 -    void cache(JavaFileObject file, CharBuffer cb) {
   7.169 -        contentCache.put(file, new SoftReference<CharBuffer>(cb));
   7.170 -    }
   7.171 -
   7.172 -    private final Map<JavaFileObject, SoftReference<CharBuffer>> contentCache
   7.173 -            = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
   7.174 -
   7.175      private String defaultEncodingName;
   7.176      private String getDefaultEncodingName() {
   7.177          if (defaultEncodingName == null) {
   7.178 @@ -585,161 +527,6 @@
   7.179          return defaultEncodingName;
   7.180      }
   7.181  
   7.182 -    protected String getEncodingName() {
   7.183 -        String encName = options.get(OptionName.ENCODING);
   7.184 -        if (encName == null)
   7.185 -            return getDefaultEncodingName();
   7.186 -        else
   7.187 -            return encName;
   7.188 -    }
   7.189 -
   7.190 -    protected Source getSource() {
   7.191 -        String sourceName = options.get(OptionName.SOURCE);
   7.192 -        Source source = null;
   7.193 -        if (sourceName != null)
   7.194 -            source = Source.lookup(sourceName);
   7.195 -        return (source != null ? source : Source.DEFAULT);
   7.196 -    }
   7.197 -
   7.198 -    /**
   7.199 -     * Make a byte buffer from an input stream.
   7.200 -     */
   7.201 -    ByteBuffer makeByteBuffer(InputStream in)
   7.202 -        throws IOException {
   7.203 -        int limit = in.available();
   7.204 -        if (mmappedIO && in instanceof FileInputStream) {
   7.205 -            // Experimental memory mapped I/O
   7.206 -            FileInputStream fin = (FileInputStream)in;
   7.207 -            return fin.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, limit);
   7.208 -        }
   7.209 -        if (limit < 1024) limit = 1024;
   7.210 -        ByteBuffer result = byteBufferCache.get(limit);
   7.211 -        int position = 0;
   7.212 -        while (in.available() != 0) {
   7.213 -            if (position >= limit)
   7.214 -                // expand buffer
   7.215 -                result = ByteBuffer.
   7.216 -                    allocate(limit <<= 1).
   7.217 -                    put((ByteBuffer)result.flip());
   7.218 -            int count = in.read(result.array(),
   7.219 -                position,
   7.220 -                limit - position);
   7.221 -            if (count < 0) break;
   7.222 -            result.position(position += count);
   7.223 -        }
   7.224 -        return (ByteBuffer)result.flip();
   7.225 -    }
   7.226 -
   7.227 -    void recycleByteBuffer(ByteBuffer bb) {
   7.228 -        byteBufferCache.put(bb);
   7.229 -    }
   7.230 -
   7.231 -    /**
   7.232 -     * A single-element cache of direct byte buffers.
   7.233 -     */
   7.234 -    private static class ByteBufferCache {
   7.235 -        private ByteBuffer cached;
   7.236 -        ByteBuffer get(int capacity) {
   7.237 -            if (capacity < 20480) capacity = 20480;
   7.238 -            ByteBuffer result =
   7.239 -                (cached != null && cached.capacity() >= capacity)
   7.240 -                ? (ByteBuffer)cached.clear()
   7.241 -                : ByteBuffer.allocate(capacity + capacity>>1);
   7.242 -            cached = null;
   7.243 -            return result;
   7.244 -        }
   7.245 -        void put(ByteBuffer x) {
   7.246 -            cached = x;
   7.247 -        }
   7.248 -    }
   7.249 -
   7.250 -    private final ByteBufferCache byteBufferCache;
   7.251 -
   7.252 -    CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
   7.253 -        Charset cs = (this.charset == null)
   7.254 -            ? Charset.forName(encodingName)
   7.255 -            : this.charset;
   7.256 -        CharsetDecoder decoder = cs.newDecoder();
   7.257 -
   7.258 -        CodingErrorAction action;
   7.259 -        if (ignoreEncodingErrors)
   7.260 -            action = CodingErrorAction.REPLACE;
   7.261 -        else
   7.262 -            action = CodingErrorAction.REPORT;
   7.263 -
   7.264 -        return decoder
   7.265 -            .onMalformedInput(action)
   7.266 -            .onUnmappableCharacter(action);
   7.267 -    }
   7.268 -
   7.269 -    /**
   7.270 -     * Decode a ByteBuffer into a CharBuffer.
   7.271 -     */
   7.272 -    CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
   7.273 -        String encodingName = getEncodingName();
   7.274 -        CharsetDecoder decoder;
   7.275 -        try {
   7.276 -            decoder = getDecoder(encodingName, ignoreEncodingErrors);
   7.277 -        } catch (IllegalCharsetNameException e) {
   7.278 -            log.error("unsupported.encoding", encodingName);
   7.279 -            return (CharBuffer)CharBuffer.allocate(1).flip();
   7.280 -        } catch (UnsupportedCharsetException e) {
   7.281 -            log.error("unsupported.encoding", encodingName);
   7.282 -            return (CharBuffer)CharBuffer.allocate(1).flip();
   7.283 -        }
   7.284 -
   7.285 -        // slightly overestimate the buffer size to avoid reallocation.
   7.286 -        float factor =
   7.287 -            decoder.averageCharsPerByte() * 0.8f +
   7.288 -            decoder.maxCharsPerByte() * 0.2f;
   7.289 -        CharBuffer dest = CharBuffer.
   7.290 -            allocate(10 + (int)(inbuf.remaining()*factor));
   7.291 -
   7.292 -        while (true) {
   7.293 -            CoderResult result = decoder.decode(inbuf, dest, true);
   7.294 -            dest.flip();
   7.295 -
   7.296 -            if (result.isUnderflow()) { // done reading
   7.297 -                // make sure there is at least one extra character
   7.298 -                if (dest.limit() == dest.capacity()) {
   7.299 -                    dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
   7.300 -                    dest.flip();
   7.301 -                }
   7.302 -                return dest;
   7.303 -            } else if (result.isOverflow()) { // buffer too small; expand
   7.304 -                int newCapacity =
   7.305 -                    10 + dest.capacity() +
   7.306 -                    (int)(inbuf.remaining()*decoder.maxCharsPerByte());
   7.307 -                dest = CharBuffer.allocate(newCapacity).put(dest);
   7.308 -            } else if (result.isMalformed() || result.isUnmappable()) {
   7.309 -                // bad character in input
   7.310 -
   7.311 -                // report coding error (warn only pre 1.5)
   7.312 -                if (!getSource().allowEncodingErrors()) {
   7.313 -                    log.error(new SimpleDiagnosticPosition(dest.limit()),
   7.314 -                              "illegal.char.for.encoding",
   7.315 -                              charset == null ? encodingName : charset.name());
   7.316 -                } else {
   7.317 -                    log.warning(new SimpleDiagnosticPosition(dest.limit()),
   7.318 -                                "illegal.char.for.encoding",
   7.319 -                                charset == null ? encodingName : charset.name());
   7.320 -                }
   7.321 -
   7.322 -                // skip past the coding error
   7.323 -                inbuf.position(inbuf.position() + result.length());
   7.324 -
   7.325 -                // undo the flip() to prepare the output buffer
   7.326 -                // for more translation
   7.327 -                dest.position(dest.limit());
   7.328 -                dest.limit(dest.capacity());
   7.329 -                dest.put((char)0xfffd); // backward compatible
   7.330 -            } else {
   7.331 -                throw new AssertionError(result);
   7.332 -            }
   7.333 -        }
   7.334 -        // unreached
   7.335 -    }
   7.336 -
   7.337      public ClassLoader getClassLoader(Location location) {
   7.338          nullCheck(location);
   7.339          Iterable<? extends File> path = getLocation(location);
   7.340 @@ -754,39 +541,7 @@
   7.341              }
   7.342          }
   7.343  
   7.344 -        URL[] urls = lb.toArray(new URL[lb.size()]);
   7.345 -        ClassLoader thisClassLoader = getClass().getClassLoader();
   7.346 -
   7.347 -        // Bug: 6558476
   7.348 -        // Ideally, ClassLoader should be Closeable, but before JDK7 it is not.
   7.349 -        // On older versions, try the following, to get a closeable classloader.
   7.350 -
   7.351 -        // 1: Allow client to specify the class to use via hidden option
   7.352 -        if (classLoaderClass != null) {
   7.353 -            try {
   7.354 -                Class<? extends ClassLoader> loader =
   7.355 -                        Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
   7.356 -                Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
   7.357 -                Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
   7.358 -                return constr.newInstance(new Object[] { urls, thisClassLoader });
   7.359 -            } catch (Throwable t) {
   7.360 -                // ignore errors loading user-provided class loader, fall through
   7.361 -            }
   7.362 -        }
   7.363 -
   7.364 -        // 2: If URLClassLoader implements Closeable, use that.
   7.365 -        if (Closeable.class.isAssignableFrom(URLClassLoader.class))
   7.366 -            return new URLClassLoader(urls, thisClassLoader);
   7.367 -
   7.368 -        // 3: Try using private reflection-based CloseableURLClassLoader
   7.369 -        try {
   7.370 -            return new CloseableURLClassLoader(urls, thisClassLoader);
   7.371 -        } catch (Throwable t) {
   7.372 -            // ignore errors loading workaround class loader, fall through
   7.373 -        }
   7.374 -
   7.375 -        // 4: If all else fails, use plain old standard URLClassLoader
   7.376 -        return new URLClassLoader(urls, thisClassLoader);
   7.377 +        return getClassLoader(lb.toArray(new URL[lb.size()]));
   7.378      }
   7.379  
   7.380      public Iterable<JavaFileObject> list(Location location,
   7.381 @@ -836,38 +591,6 @@
   7.382          return a.equals(b);
   7.383      }
   7.384  
   7.385 -    public boolean handleOption(String current, Iterator<String> remaining) {
   7.386 -        for (JavacOption o: javacFileManagerOptions) {
   7.387 -            if (o.matches(current))  {
   7.388 -                if (o.hasArg()) {
   7.389 -                    if (remaining.hasNext()) {
   7.390 -                        if (!o.process(options, current, remaining.next()))
   7.391 -                            return true;
   7.392 -                    }
   7.393 -                } else {
   7.394 -                    if (!o.process(options, current))
   7.395 -                        return true;
   7.396 -                }
   7.397 -                // operand missing, or process returned false
   7.398 -                throw new IllegalArgumentException(current);
   7.399 -            }
   7.400 -        }
   7.401 -
   7.402 -        return false;
   7.403 -    }
   7.404 -    // where
   7.405 -        private static JavacOption[] javacFileManagerOptions =
   7.406 -            RecognizedOptions.getJavacFileManagerOptions(
   7.407 -            new RecognizedOptions.GrumpyHelper());
   7.408 -
   7.409 -    public int isSupportedOption(String option) {
   7.410 -        for (JavacOption o : javacFileManagerOptions) {
   7.411 -            if (o.matches(option))
   7.412 -                return o.hasArg() ? 1 : 0;
   7.413 -        }
   7.414 -        return -1;
   7.415 -    }
   7.416 -
   7.417      public boolean hasLocation(Location location) {
   7.418          return getLocation(location) != null;
   7.419      }
   7.420 @@ -1115,15 +838,4 @@
   7.421          }
   7.422          throw new IllegalArgumentException("Invalid relative path: " + file);
   7.423      }
   7.424 -
   7.425 -    private static <T> T nullCheck(T o) {
   7.426 -        o.getClass(); // null check
   7.427 -        return o;
   7.428 -    }
   7.429 -
   7.430 -    private static <T> Iterable<T> nullCheck(Iterable<T> it) {
   7.431 -        for (T t : it)
   7.432 -            t.getClass(); // null check
   7.433 -        return it;
   7.434 -    }
   7.435  }
     8.1 --- a/src/share/classes/com/sun/tools/javac/file/Paths.java	Thu Dec 17 14:10:44 2009 -0800
     8.2 +++ b/src/share/classes/com/sun/tools/javac/file/Paths.java	Sat Dec 19 10:26:47 2009 -0800
     8.3 @@ -66,7 +66,7 @@
     8.4       *  @param context the context
     8.5       *  @return the Paths instance for this context
     8.6       */
     8.7 -    static Paths instance(Context context) {
     8.8 +    public static Paths instance(Context context) {
     8.9          Paths instance = context.get(pathsKey);
    8.10          if (instance == null)
    8.11              instance = new Paths(context);
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java	Sat Dec 19 10:26:47 2009 -0800
     9.3 @@ -0,0 +1,543 @@
     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 +
    9.32 +import java.io.File;
    9.33 +import java.io.FileNotFoundException;
    9.34 +import java.io.IOException;
    9.35 +import java.net.MalformedURLException;
    9.36 +import java.net.URL;
    9.37 +import java.nio.charset.Charset;
    9.38 +import java.nio.file.Files;
    9.39 +import java.nio.file.FileSystem;
    9.40 +import java.nio.file.FileSystems;
    9.41 +import java.nio.file.FileVisitOption;
    9.42 +import java.nio.file.FileVisitResult;
    9.43 +import java.nio.file.Path;
    9.44 +import java.nio.file.SimpleFileVisitor;
    9.45 +import java.nio.file.attribute.Attributes;
    9.46 +import java.nio.file.attribute.BasicFileAttributes;
    9.47 +import java.util.ArrayList;
    9.48 +import java.util.Arrays;
    9.49 +import java.util.Collection;
    9.50 +import java.util.Collections;
    9.51 +import java.util.EnumSet;
    9.52 +import java.util.HashMap;
    9.53 +import java.util.Iterator;
    9.54 +import java.util.LinkedHashSet;
    9.55 +import java.util.Map;
    9.56 +import java.util.Set;
    9.57 +import javax.lang.model.SourceVersion;
    9.58 +import javax.tools.FileObject;
    9.59 +import javax.tools.JavaFileManager;
    9.60 +import javax.tools.JavaFileObject;
    9.61 +import javax.tools.JavaFileObject.Kind;
    9.62 +import javax.tools.StandardLocation;
    9.63 +
    9.64 +import static java.nio.file.FileVisitOption.*;
    9.65 +import static javax.tools.StandardLocation.*;
    9.66 +
    9.67 +import com.sun.tools.javac.file.Paths;
    9.68 +import com.sun.tools.javac.util.BaseFileManager;
    9.69 +import com.sun.tools.javac.util.Context;
    9.70 +import com.sun.tools.javac.util.List;
    9.71 +import com.sun.tools.javac.util.ListBuffer;
    9.72 +
    9.73 +import static com.sun.tools.javac.main.OptionName.*;
    9.74 +
    9.75 +
    9.76 +// NOTE the imports carefully for this compilation unit.
    9.77 +//
    9.78 +// Path:  java.nio.file.Path -- the new NIO type for which this file manager exists
    9.79 +//
    9.80 +// Paths: com.sun.tools.javac.file.Paths -- legacy javac type for handling path options
    9.81 +//      The other Paths (java.nio.file.Paths) is not used
    9.82 +
    9.83 +// NOTE this and related classes depend on new API in JDK 7.
    9.84 +// This requires special handling while bootstrapping the JDK build,
    9.85 +// when these classes might not yet have been compiled. To workaround
    9.86 +// this, the build arranges to make stubs of these classes available
    9.87 +// when compiling this and related classes. The set of stub files
    9.88 +// is specified in make/build.properties.
    9.89 +
    9.90 +/**
    9.91 + *  Implementation of PathFileManager: a JavaFileManager based on the use
    9.92 + *  of java.nio.file.Path.
    9.93 + *
    9.94 + *  <p>Just as a Path is somewhat analagous to a File, so too is this
    9.95 + *  JavacPathFileManager analogous to JavacFileManager, as it relates to the
    9.96 + *  support of FileObjects based on File objects (i.e. just RegularFileObject,
    9.97 + *  not ZipFileObject and its variants.)
    9.98 + *
    9.99 + *  <p>The default values for the standard locations supported by this file
   9.100 + *  manager are the same as the default values provided by JavacFileManager --
   9.101 + *  i.e. as determined by the javac.file.Paths class. To override these values,
   9.102 + *  call {@link #setLocation}.
   9.103 + *
   9.104 + *  <p>To reduce confusion with Path objects, the locations such as "class path",
   9.105 + *  "source path", etc, are generically referred to here as "search paths".
   9.106 + *
   9.107 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
   9.108 + *  you write code that depends on this, you do so at your own risk.
   9.109 + *  This code and its internal interfaces are subject to change or
   9.110 + *  deletion without notice.</b>
   9.111 + */
   9.112 +public class JavacPathFileManager extends BaseFileManager implements PathFileManager {
   9.113 +    protected FileSystem defaultFileSystem;
   9.114 +
   9.115 +    /**
   9.116 +     * Create a JavacPathFileManager using a given context, optionally registering
   9.117 +     * it as the JavaFileManager for that context.
   9.118 +     */
   9.119 +    public JavacPathFileManager(Context context, boolean register, Charset charset) {
   9.120 +        super(charset);
   9.121 +        if (register)
   9.122 +            context.put(JavaFileManager.class, this);
   9.123 +        pathsForLocation = new HashMap<Location, PathsForLocation>();
   9.124 +        fileSystems = new HashMap<Path,FileSystem>();
   9.125 +        setContext(context);
   9.126 +    }
   9.127 +
   9.128 +    /**
   9.129 +     * Set the context for JavacPathFileManager.
   9.130 +     */
   9.131 +    @Override
   9.132 +    protected void setContext(Context context) {
   9.133 +        super.setContext(context);
   9.134 +        searchPaths = Paths.instance(context);
   9.135 +    }
   9.136 +
   9.137 +    @Override
   9.138 +    public FileSystem getDefaultFileSystem() {
   9.139 +        if (defaultFileSystem == null)
   9.140 +            defaultFileSystem = FileSystems.getDefault();
   9.141 +        return defaultFileSystem;
   9.142 +    }
   9.143 +
   9.144 +    @Override
   9.145 +    public void setDefaultFileSystem(FileSystem fs) {
   9.146 +        defaultFileSystem = fs;
   9.147 +    }
   9.148 +
   9.149 +    @Override
   9.150 +    public void flush() throws IOException {
   9.151 +        contentCache.clear();
   9.152 +    }
   9.153 +
   9.154 +    @Override
   9.155 +    public void close() throws IOException {
   9.156 +        for (FileSystem fs: fileSystems.values())
   9.157 +            fs.close();
   9.158 +    }
   9.159 +
   9.160 +    @Override
   9.161 +    public ClassLoader getClassLoader(Location location) {
   9.162 +        nullCheck(location);
   9.163 +        Iterable<? extends Path> path = getLocation(location);
   9.164 +        if (path == null)
   9.165 +            return null;
   9.166 +        ListBuffer<URL> lb = new ListBuffer<URL>();
   9.167 +        for (Path p: path) {
   9.168 +            try {
   9.169 +                lb.append(p.toUri().toURL());
   9.170 +            } catch (MalformedURLException e) {
   9.171 +                throw new AssertionError(e);
   9.172 +            }
   9.173 +        }
   9.174 +
   9.175 +        return getClassLoader(lb.toArray(new URL[lb.size()]));
   9.176 +    }
   9.177 +
   9.178 +    // <editor-fold defaultstate="collapsed" desc="Location handling">
   9.179 +
   9.180 +    public boolean hasLocation(Location location) {
   9.181 +        return (getLocation(location) != null);
   9.182 +    }
   9.183 +
   9.184 +    public Iterable<? extends Path> getLocation(Location location) {
   9.185 +        nullCheck(location);
   9.186 +        lazyInitSearchPaths();
   9.187 +        PathsForLocation path = pathsForLocation.get(location);
   9.188 +        if (path == null && !pathsForLocation.containsKey(location)) {
   9.189 +            setDefaultForLocation(location);
   9.190 +            path = pathsForLocation.get(location);
   9.191 +        }
   9.192 +        return path;
   9.193 +    }
   9.194 +
   9.195 +    private Path getOutputLocation(Location location) {
   9.196 +        Iterable<? extends Path> paths = getLocation(location);
   9.197 +        return (paths == null ? null : paths.iterator().next());
   9.198 +    }
   9.199 +
   9.200 +    public void setLocation(Location location, Iterable<? extends Path> searchPath)
   9.201 +            throws IOException
   9.202 +    {
   9.203 +        nullCheck(location);
   9.204 +        lazyInitSearchPaths();
   9.205 +        if (searchPath == null) {
   9.206 +            setDefaultForLocation(location);
   9.207 +        } else {
   9.208 +            if (location.isOutputLocation())
   9.209 +                checkOutputPath(searchPath);
   9.210 +            PathsForLocation pl = new PathsForLocation();
   9.211 +            for (Path p: searchPath)
   9.212 +                pl.add(p);  // TODO -Xlint:path warn if path not found
   9.213 +            pathsForLocation.put(location, pl);
   9.214 +        }
   9.215 +    }
   9.216 +
   9.217 +    private void checkOutputPath(Iterable<? extends Path> searchPath) throws IOException {
   9.218 +        Iterator<? extends Path> pathIter = searchPath.iterator();
   9.219 +        if (!pathIter.hasNext())
   9.220 +            throw new IllegalArgumentException("empty path for directory");
   9.221 +        Path path = pathIter.next();
   9.222 +        if (pathIter.hasNext())
   9.223 +            throw new IllegalArgumentException("path too long for directory");
   9.224 +        if (!path.exists())
   9.225 +            throw new FileNotFoundException(path + ": does not exist");
   9.226 +        else if (!isDirectory(path))
   9.227 +            throw new IOException(path + ": not a directory");
   9.228 +    }
   9.229 +
   9.230 +    private void setDefaultForLocation(Location locn) {
   9.231 +        Collection<File> files = null;
   9.232 +        if (locn instanceof StandardLocation) {
   9.233 +            switch ((StandardLocation) locn) {
   9.234 +                case CLASS_PATH:
   9.235 +                    files = searchPaths.userClassPath();
   9.236 +                    break;
   9.237 +                case PLATFORM_CLASS_PATH:
   9.238 +                    files = searchPaths.bootClassPath();
   9.239 +                    break;
   9.240 +                case SOURCE_PATH:
   9.241 +                    files = searchPaths.sourcePath();
   9.242 +                    break;
   9.243 +                case CLASS_OUTPUT: {
   9.244 +                    String arg = options.get(D);
   9.245 +                    files = (arg == null ? null : Collections.singleton(new File(arg)));
   9.246 +                    break;
   9.247 +                }
   9.248 +                case SOURCE_OUTPUT: {
   9.249 +                    String arg = options.get(S);
   9.250 +                    files = (arg == null ? null : Collections.singleton(new File(arg)));
   9.251 +                    break;
   9.252 +                }
   9.253 +            }
   9.254 +        }
   9.255 +
   9.256 +        PathsForLocation pl = new PathsForLocation();
   9.257 +        if (files != null) {
   9.258 +            for (File f: files)
   9.259 +                pl.add(f.toPath());
   9.260 +        }
   9.261 +        pathsForLocation.put(locn, pl);
   9.262 +    }
   9.263 +
   9.264 +    private void lazyInitSearchPaths() {
   9.265 +        if (!inited) {
   9.266 +            setDefaultForLocation(PLATFORM_CLASS_PATH);
   9.267 +            setDefaultForLocation(CLASS_PATH);
   9.268 +            setDefaultForLocation(SOURCE_PATH);
   9.269 +            inited = true;
   9.270 +        }
   9.271 +    }
   9.272 +    // where
   9.273 +        private boolean inited = false;
   9.274 +
   9.275 +    private Map<Location, PathsForLocation> pathsForLocation;
   9.276 +    private Paths searchPaths;
   9.277 +
   9.278 +    private static class PathsForLocation extends LinkedHashSet<Path> {
   9.279 +        private static final long serialVersionUID = 6788510222394486733L;
   9.280 +    }
   9.281 +
   9.282 +    // </editor-fold>
   9.283 +
   9.284 +    // <editor-fold defaultstate="collapsed" desc="FileObject handling">
   9.285 +
   9.286 +    @Override
   9.287 +    public Path getPath(FileObject fo) {
   9.288 +        nullCheck(fo);
   9.289 +        if (!(fo instanceof PathFileObject))
   9.290 +            throw new IllegalArgumentException();
   9.291 +        return ((PathFileObject) fo).getPath();
   9.292 +    }
   9.293 +
   9.294 +    @Override
   9.295 +    public boolean isSameFile(FileObject a, FileObject b) {
   9.296 +        nullCheck(a);
   9.297 +        nullCheck(b);
   9.298 +        if (!(a instanceof PathFileObject))
   9.299 +            throw new IllegalArgumentException("Not supported: " + a);
   9.300 +        if (!(b instanceof PathFileObject))
   9.301 +            throw new IllegalArgumentException("Not supported: " + b);
   9.302 +        return ((PathFileObject) a).isSameFile((PathFileObject) b);
   9.303 +    }
   9.304 +
   9.305 +    @Override
   9.306 +    public Iterable<JavaFileObject> list(Location location,
   9.307 +            String packageName, Set<Kind> kinds, boolean recurse)
   9.308 +            throws IOException {
   9.309 +        // validatePackageName(packageName);
   9.310 +        nullCheck(packageName);
   9.311 +        nullCheck(kinds);
   9.312 +
   9.313 +        Iterable<? extends Path> paths = getLocation(location);
   9.314 +        if (paths == null)
   9.315 +            return List.nil();
   9.316 +        ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
   9.317 +
   9.318 +        for (Path path : paths)
   9.319 +            list(path, packageName, kinds, recurse, results);
   9.320 +
   9.321 +        return results.toList();
   9.322 +    }
   9.323 +
   9.324 +    private void list(Path path, String packageName, final Set<Kind> kinds,
   9.325 +            boolean recurse, final ListBuffer<JavaFileObject> results)
   9.326 +            throws IOException {
   9.327 +        if (!path.exists())
   9.328 +            return;
   9.329 +
   9.330 +        final Path pathDir;
   9.331 +        if (isDirectory(path))
   9.332 +            pathDir = path;
   9.333 +        else {
   9.334 +            FileSystem fs = getFileSystem(path);
   9.335 +            if (fs == null)
   9.336 +                return;
   9.337 +            pathDir = fs.getRootDirectories().iterator().next();
   9.338 +        }
   9.339 +        String sep = path.getFileSystem().getSeparator();
   9.340 +        Path packageDir = packageName.isEmpty() ? pathDir
   9.341 +                : pathDir.resolve(packageName.replace(".", sep));
   9.342 +        if (!packageDir.exists())
   9.343 +            return;
   9.344 +
   9.345 +/* Alternate impl of list, superceded by use of Files.walkFileTree */
   9.346 +//        Deque<Path> queue = new LinkedList<Path>();
   9.347 +//        queue.add(packageDir);
   9.348 +//
   9.349 +//        Path dir;
   9.350 +//        while ((dir = queue.poll()) != null) {
   9.351 +//            DirectoryStream<Path> ds = dir.newDirectoryStream();
   9.352 +//            try {
   9.353 +//                for (Path p: ds) {
   9.354 +//                    String name = p.getName().toString();
   9.355 +//                    if (isDirectory(p)) {
   9.356 +//                        if (recurse && SourceVersion.isIdentifier(name)) {
   9.357 +//                            queue.add(p);
   9.358 +//                        }
   9.359 +//                    } else {
   9.360 +//                        if (kinds.contains(getKind(name))) {
   9.361 +//                            JavaFileObject fe =
   9.362 +//                                PathFileObject.createDirectoryPathFileObject(this, p, pathDir);
   9.363 +//                            results.append(fe);
   9.364 +//                        }
   9.365 +//                    }
   9.366 +//                }
   9.367 +//            } finally {
   9.368 +//                ds.close();
   9.369 +//            }
   9.370 +//        }
   9.371 +        int maxDepth = (recurse ? Integer.MAX_VALUE : 1);
   9.372 +        Set<FileVisitOption> opts = EnumSet.of(DETECT_CYCLES, FOLLOW_LINKS);
   9.373 +        Files.walkFileTree(packageDir, opts, maxDepth,
   9.374 +                new SimpleFileVisitor<Path>() {
   9.375 +            @Override
   9.376 +            public FileVisitResult preVisitDirectory(Path dir) {
   9.377 +                if (SourceVersion.isIdentifier(dir.getName().toString())) // JSR 292?
   9.378 +                    return FileVisitResult.CONTINUE;
   9.379 +                else
   9.380 +                    return FileVisitResult.SKIP_SUBTREE;
   9.381 +            }
   9.382 +
   9.383 +            @Override
   9.384 +            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
   9.385 +                if (attrs.isRegularFile() && kinds.contains(getKind(file.getName().toString()))) {
   9.386 +                    JavaFileObject fe =
   9.387 +                        PathFileObject.createDirectoryPathFileObject(
   9.388 +                            JavacPathFileManager.this, file, pathDir);
   9.389 +                    results.append(fe);
   9.390 +                }
   9.391 +                return FileVisitResult.CONTINUE;
   9.392 +            }
   9.393 +        });
   9.394 +    }
   9.395 +
   9.396 +    @Override
   9.397 +    public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
   9.398 +        Iterable<? extends Path> paths) {
   9.399 +        ArrayList<PathFileObject> result;
   9.400 +        if (paths instanceof Collection<?>)
   9.401 +            result = new ArrayList<PathFileObject>(((Collection<?>)paths).size());
   9.402 +        else
   9.403 +            result = new ArrayList<PathFileObject>();
   9.404 +        for (Path p: paths)
   9.405 +            result.add(PathFileObject.createSimplePathFileObject(this, nullCheck(p)));
   9.406 +        return result;
   9.407 +    }
   9.408 +
   9.409 +    @Override
   9.410 +    public Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths) {
   9.411 +        return getJavaFileObjectsFromPaths(Arrays.asList(nullCheck(paths)));
   9.412 +    }
   9.413 +
   9.414 +    @Override
   9.415 +    public JavaFileObject getJavaFileForInput(Location location,
   9.416 +            String className, Kind kind) throws IOException {
   9.417 +        return getFileForInput(location, getRelativePath(className, kind));
   9.418 +    }
   9.419 +
   9.420 +    @Override
   9.421 +    public FileObject getFileForInput(Location location,
   9.422 +            String packageName, String relativeName) throws IOException {
   9.423 +        return getFileForInput(location, getRelativePath(packageName, relativeName));
   9.424 +    }
   9.425 +
   9.426 +    private JavaFileObject getFileForInput(Location location, String relativePath)
   9.427 +            throws IOException {
   9.428 +        for (Path p: getLocation(location)) {
   9.429 +            if (isDirectory(p)) {
   9.430 +                Path f = resolve(p, relativePath);
   9.431 +                if (f.exists())
   9.432 +                    return PathFileObject.createDirectoryPathFileObject(this, f, p);
   9.433 +            } else {
   9.434 +                FileSystem fs = getFileSystem(p);
   9.435 +                if (fs != null) {
   9.436 +                    Path file = getPath(fs, relativePath);
   9.437 +                    if (file.exists())
   9.438 +                        return PathFileObject.createJarPathFileObject(this, file);
   9.439 +                }
   9.440 +            }
   9.441 +        }
   9.442 +        return null;
   9.443 +    }
   9.444 +
   9.445 +    @Override
   9.446 +    public JavaFileObject getJavaFileForOutput(Location location,
   9.447 +            String className, Kind kind, FileObject sibling) throws IOException {
   9.448 +        return getFileForOutput(location, getRelativePath(className, kind), sibling);
   9.449 +    }
   9.450 +
   9.451 +    @Override
   9.452 +    public FileObject getFileForOutput(Location location, String packageName,
   9.453 +            String relativeName, FileObject sibling)
   9.454 +            throws IOException {
   9.455 +        return getFileForOutput(location, getRelativePath(packageName, relativeName), sibling);
   9.456 +    }
   9.457 +
   9.458 +    private JavaFileObject getFileForOutput(Location location,
   9.459 +            String relativePath, FileObject sibling) {
   9.460 +        Path dir = getOutputLocation(location);
   9.461 +        if (dir == null) {
   9.462 +            if (location == CLASS_OUTPUT) {
   9.463 +                Path siblingDir = null;
   9.464 +                if (sibling != null && sibling instanceof PathFileObject) {
   9.465 +                    siblingDir = ((PathFileObject) sibling).getPath().getParent();
   9.466 +                }
   9.467 +                return PathFileObject.createSiblingPathFileObject(this,
   9.468 +                        siblingDir.resolve(getBaseName(relativePath)),
   9.469 +                        relativePath);
   9.470 +            } else if (location == SOURCE_OUTPUT) {
   9.471 +                dir = getOutputLocation(CLASS_OUTPUT);
   9.472 +            }
   9.473 +        }
   9.474 +
   9.475 +        Path file;
   9.476 +        if (dir != null) {
   9.477 +            file = resolve(dir, relativePath);
   9.478 +            return PathFileObject.createDirectoryPathFileObject(this, file, dir);
   9.479 +        } else {
   9.480 +            file = getPath(getDefaultFileSystem(), relativePath);
   9.481 +            return PathFileObject.createSimplePathFileObject(this, file);
   9.482 +        }
   9.483 +
   9.484 +    }
   9.485 +
   9.486 +    @Override
   9.487 +    public String inferBinaryName(Location location, JavaFileObject fo) {
   9.488 +        nullCheck(fo);
   9.489 +        // Need to match the path semantics of list(location, ...)
   9.490 +        Iterable<? extends Path> paths = getLocation(location);
   9.491 +        if (paths == null) {
   9.492 +            return null;
   9.493 +        }
   9.494 +
   9.495 +        if (!(fo instanceof PathFileObject))
   9.496 +            throw new IllegalArgumentException(fo.getClass().getName());
   9.497 +
   9.498 +        return ((PathFileObject) fo).inferBinaryName(paths);
   9.499 +    }
   9.500 +
   9.501 +    private FileSystem getFileSystem(Path p) throws IOException {
   9.502 +        FileSystem fs = fileSystems.get(p);
   9.503 +        if (fs == null) {
   9.504 +            fs = FileSystems.newFileSystem(p, Collections.<String,Void>emptyMap(), null);
   9.505 +            fileSystems.put(p, fs);
   9.506 +        }
   9.507 +        return fs;
   9.508 +    }
   9.509 +
   9.510 +    private Map<Path,FileSystem> fileSystems;
   9.511 +
   9.512 +    // </editor-fold>
   9.513 +
   9.514 +    // <editor-fold defaultstate="collapsed" desc="Utility methods">
   9.515 +
   9.516 +    private static String getRelativePath(String className, Kind kind) {
   9.517 +        return className.replace(".", "/") + kind.extension;
   9.518 +    }
   9.519 +
   9.520 +    private static String getRelativePath(String packageName, String relativeName) {
   9.521 +        return packageName.replace(".", "/") + relativeName;
   9.522 +    }
   9.523 +
   9.524 +    private static String getBaseName(String relativePath) {
   9.525 +        int lastSep = relativePath.lastIndexOf("/");
   9.526 +        return relativePath.substring(lastSep + 1); // safe if "/" not found
   9.527 +    }
   9.528 +
   9.529 +    private static boolean isDirectory(Path path) throws IOException {
   9.530 +        BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path);
   9.531 +        return attrs.isDirectory();
   9.532 +    }
   9.533 +
   9.534 +    private static Path getPath(FileSystem fs, String relativePath) {
   9.535 +        return fs.getPath(relativePath.replace("/", fs.getSeparator()));
   9.536 +    }
   9.537 +
   9.538 +    private static Path resolve(Path base, String relativePath) {
   9.539 +        FileSystem fs = base.getFileSystem();
   9.540 +        Path rp = fs.getPath(relativePath.replace("/", fs.getSeparator()));
   9.541 +        return base.resolve(rp);
   9.542 +    }
   9.543 +
   9.544 +    // </editor-fold>
   9.545 +
   9.546 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/share/classes/com/sun/tools/javac/nio/PathFileManager.java	Sat Dec 19 10:26:47 2009 -0800
    10.3 @@ -0,0 +1,125 @@
    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.nio;
   10.30 +
   10.31 +import java.io.IOException;
   10.32 +import java.nio.file.FileSystem;
   10.33 +import java.nio.file.Path;
   10.34 +import javax.tools.FileObject;
   10.35 +import javax.tools.JavaFileManager;
   10.36 +import javax.tools.JavaFileObject;
   10.37 +
   10.38 +/**
   10.39 + *  File manager based on {@linkplain File java.nio.file.Path}.
   10.40 + *
   10.41 + *  Eventually, this should be moved to javax.tools.
   10.42 + *  Also, JavaCompiler might reasonably provide a method getPathFileManager,
   10.43 + *  similar to {@link javax.tools.JavaCompiler#getStandardFileManager
   10.44 + *  getStandardFileManager}. However, would need to be handled carefully
   10.45 + *  as another forward reference from langtools to jdk.
   10.46 + *
   10.47 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
   10.48 + *  you write code that depends on this, you do so at your own risk.
   10.49 + *  This code and its internal interfaces are subject to change or
   10.50 + *  deletion without notice.</b>
   10.51 + */
   10.52 +public interface PathFileManager extends JavaFileManager {
   10.53 +    /**
   10.54 +     * Get the default file system used to create paths. If no value has been
   10.55 +     * set, the default file system is {@link FileSystems#getDefault}.
   10.56 +     */
   10.57 +    FileSystem getDefaultFileSystem();
   10.58 +
   10.59 +    /**
   10.60 +     * Set the default file system used to create paths.
   10.61 +     * @param fs the default file system used to create any new paths.
   10.62 +     */
   10.63 +    void setDefaultFileSystem(FileSystem fs);
   10.64 +
   10.65 +    /**
   10.66 +     * Get file objects representing the given files.
   10.67 +     *
   10.68 +     * @param paths a list of paths
   10.69 +     * @return a list of file objects
   10.70 +     * @throws IllegalArgumentException if the list of paths includes
   10.71 +     * a directory
   10.72 +     */
   10.73 +    Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
   10.74 +        Iterable<? extends Path> paths);
   10.75 +
   10.76 +    /**
   10.77 +     * Get file objects representing the given paths.
   10.78 +     * Convenience method equivalent to:
   10.79 +     *
   10.80 +     * <pre>
   10.81 +     *     getJavaFileObjectsFromPaths({@linkplain java.util.Arrays#asList Arrays.asList}(paths))
   10.82 +     * </pre>
   10.83 +     *
   10.84 +     * @param paths an array of paths
   10.85 +     * @return a list of file objects
   10.86 +     * @throws IllegalArgumentException if the array of files includes
   10.87 +     * a directory
   10.88 +     * @throws NullPointerException if the given array contains null
   10.89 +     * elements
   10.90 +     */
   10.91 +    Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths);
   10.92 +
   10.93 +    /**
   10.94 +     * Return the Path for a file object that has been obtained from this
   10.95 +     * file manager.
   10.96 +     *
   10.97 +     * @param fo A file object that has been obtained from this file manager.
   10.98 +     * @return The underlying Path object.
   10.99 +     * @throws IllegalArgumentException is the file object was not obtained from
  10.100 +     * from this file manager.
  10.101 +     */
  10.102 +    Path getPath(FileObject fo);
  10.103 +
  10.104 +    /**
  10.105 +     * Get the search path associated with the given location.
  10.106 +     *
  10.107 +     * @param location a location
  10.108 +     * @return a list of paths or {@code null} if this location has no
  10.109 +     * associated search path
  10.110 +     * @see #setLocation
  10.111 +     */
  10.112 +    Iterable<? extends Path> getLocation(Location location);
  10.113 +
  10.114 +    /**
  10.115 +     * Associate the given search path with the given location.  Any
  10.116 +     * previous value will be discarded.
  10.117 +     *
  10.118 +     * @param location a location
  10.119 +     * @param searchPath a list of files, if {@code null} use the default
  10.120 +     * search path for this location
  10.121 +     * @see #getLocation
  10.122 +     * @throws IllegalArgumentException if location is an output
  10.123 +     * location and searchpath does not contain exactly one element
  10.124 +     * @throws IOException if location is an output location and searchpath
  10.125 +     * does not represent an existing directory
  10.126 +     */
  10.127 +    void setLocation(Location location, Iterable<? extends Path> searchPath) throws IOException;
  10.128 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/share/classes/com/sun/tools/javac/nio/PathFileObject.java	Sat Dec 19 10:26:47 2009 -0800
    11.3 @@ -0,0 +1,319 @@
    11.4 +/*
    11.5 + * Copyright 2009 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.nio;
   11.30 +
   11.31 +import java.io.IOException;
   11.32 +import java.io.InputStream;
   11.33 +import java.io.InputStreamReader;
   11.34 +import java.io.OutputStream;
   11.35 +import java.io.OutputStreamWriter;
   11.36 +import java.io.Reader;
   11.37 +import java.io.Writer;
   11.38 +import java.net.URI;
   11.39 +import java.nio.ByteBuffer;
   11.40 +import java.nio.CharBuffer;
   11.41 +import java.nio.charset.CharsetDecoder;
   11.42 +import java.nio.file.Files;
   11.43 +import java.nio.file.Path;
   11.44 +import java.nio.file.attribute.Attributes;
   11.45 +import java.nio.file.attribute.BasicFileAttributes;
   11.46 +import javax.lang.model.element.Modifier;
   11.47 +import javax.lang.model.element.NestingKind;
   11.48 +import javax.tools.JavaFileObject;
   11.49 +
   11.50 +import com.sun.tools.javac.util.BaseFileManager;
   11.51 +
   11.52 +
   11.53 +/**
   11.54 + *  Implementation of JavaFileObject using java.nio.file API.
   11.55 + *
   11.56 + *  <p>PathFileObjects are, for the most part, straightforward wrappers around
   11.57 + *  Path objects. The primary complexity is the support for "inferBinaryName".
   11.58 + *  This is left as an abstract method, implemented by each of a number of
   11.59 + *  different factory methods, which compute the binary name based on
   11.60 + *  information available at the time the file object is created.
   11.61 + *
   11.62 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
   11.63 + *  you write code that depends on this, you do so at your own risk.
   11.64 + *  This code and its internal interfaces are subject to change or
   11.65 + *  deletion without notice.</b>
   11.66 + */
   11.67 +abstract class PathFileObject implements JavaFileObject {
   11.68 +    private JavacPathFileManager fileManager;
   11.69 +    private Path path;
   11.70 +
   11.71 +    /**
   11.72 +     * Create a PathFileObject within a directory, such that the binary name
   11.73 +     * can be inferred from the relationship to the parent directory.
   11.74 +     */
   11.75 +    static PathFileObject createDirectoryPathFileObject(JavacPathFileManager fileManager,
   11.76 +            final Path path, final Path dir) {
   11.77 +        return new PathFileObject(fileManager, path) {
   11.78 +            @Override
   11.79 +            String inferBinaryName(Iterable<? extends Path> paths) {
   11.80 +                return toBinaryName(dir.relativize(path));
   11.81 +            }
   11.82 +        };
   11.83 +    }
   11.84 +
   11.85 +    /**
   11.86 +     * Create a PathFileObject in a file system such as a jar file, such that
   11.87 +     * the binary name can be inferred from its position within the filesystem.
   11.88 +     */
   11.89 +    static PathFileObject createJarPathFileObject(JavacPathFileManager fileManager,
   11.90 +            final Path path) {
   11.91 +        return new PathFileObject(fileManager, path) {
   11.92 +            @Override
   11.93 +            String inferBinaryName(Iterable<? extends Path> paths) {
   11.94 +                return toBinaryName(path);
   11.95 +            }
   11.96 +        };
   11.97 +    }
   11.98 +
   11.99 +    /**
  11.100 +     * Create a PathFileObject whose binary name can be inferred from the
  11.101 +     * relative path to a sibling.
  11.102 +     */
  11.103 +    static PathFileObject createSiblingPathFileObject(JavacPathFileManager fileManager,
  11.104 +            final Path path, final String relativePath) {
  11.105 +        return new PathFileObject(fileManager, path) {
  11.106 +            @Override
  11.107 +            String inferBinaryName(Iterable<? extends Path> paths) {
  11.108 +                return toBinaryName(relativePath, "/");
  11.109 +            }
  11.110 +        };
  11.111 +    }
  11.112 +
  11.113 +    /**
  11.114 +     * Create a PathFileObject whose binary name might be inferred from its
  11.115 +     * position on a search path.
  11.116 +     */
  11.117 +    static PathFileObject createSimplePathFileObject(JavacPathFileManager fileManager,
  11.118 +            final Path path) {
  11.119 +        return new PathFileObject(fileManager, path) {
  11.120 +            @Override
  11.121 +            String inferBinaryName(Iterable<? extends Path> paths) {
  11.122 +                Path absPath = path.toAbsolutePath();
  11.123 +                for (Path p: paths) {
  11.124 +                    Path ap = p.toAbsolutePath();
  11.125 +                    if (absPath.startsWith(ap)) {
  11.126 +                        try {
  11.127 +                            Path rp = ap.relativize(absPath);
  11.128 +                            if (rp != null) // maybe null if absPath same as ap
  11.129 +                                return toBinaryName(rp);
  11.130 +                        } catch (IllegalArgumentException e) {
  11.131 +                            // ignore this p if cannot relativize path to p
  11.132 +                        }
  11.133 +                    }
  11.134 +                }
  11.135 +                return null;
  11.136 +            }
  11.137 +        };
  11.138 +    }
  11.139 +
  11.140 +    protected PathFileObject(JavacPathFileManager fileManager, Path path) {
  11.141 +        fileManager.getClass(); // null check
  11.142 +        path.getClass();        // null check
  11.143 +        this.fileManager = fileManager;
  11.144 +        this.path = path;
  11.145 +    }
  11.146 +
  11.147 +    abstract String inferBinaryName(Iterable<? extends Path> paths);
  11.148 +
  11.149 +    /**
  11.150 +     * Return the Path for this object.
  11.151 +     * @return the Path for this object.
  11.152 +     */
  11.153 +    Path getPath() {
  11.154 +        return path;
  11.155 +    }
  11.156 +
  11.157 +    @Override
  11.158 +    public Kind getKind() {
  11.159 +        return BaseFileManager.getKind(path.getName().toString());
  11.160 +    }
  11.161 +
  11.162 +    @Override
  11.163 +    public boolean isNameCompatible(String simpleName, Kind kind) {
  11.164 +        simpleName.getClass();
  11.165 +        // null check
  11.166 +        if (kind == Kind.OTHER && getKind() != kind) {
  11.167 +            return false;
  11.168 +        }
  11.169 +        String sn = simpleName + kind.extension;
  11.170 +        String pn = path.getName().toString();
  11.171 +        if (pn.equals(sn)) {
  11.172 +            return true;
  11.173 +        }
  11.174 +        if (pn.equalsIgnoreCase(sn)) {
  11.175 +            try {
  11.176 +                // allow for Windows
  11.177 +                return path.toRealPath(false).getName().toString().equals(sn);
  11.178 +            } catch (IOException e) {
  11.179 +            }
  11.180 +        }
  11.181 +        return false;
  11.182 +    }
  11.183 +
  11.184 +    @Override
  11.185 +    public NestingKind getNestingKind() {
  11.186 +        return null;
  11.187 +    }
  11.188 +
  11.189 +    @Override
  11.190 +    public Modifier getAccessLevel() {
  11.191 +        return null;
  11.192 +    }
  11.193 +
  11.194 +    @Override
  11.195 +    public URI toUri() {
  11.196 +        return path.toUri();
  11.197 +    }
  11.198 +
  11.199 +    @Override
  11.200 +    public String getName() {
  11.201 +        return path.toString();
  11.202 +    }
  11.203 +
  11.204 +    @Override
  11.205 +    public InputStream openInputStream() throws IOException {
  11.206 +        return path.newInputStream();
  11.207 +    }
  11.208 +
  11.209 +    @Override
  11.210 +    public OutputStream openOutputStream() throws IOException {
  11.211 +        ensureParentDirectoriesExist();
  11.212 +        return path.newOutputStream();
  11.213 +    }
  11.214 +
  11.215 +    @Override
  11.216 +    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
  11.217 +        CharsetDecoder decoder = fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
  11.218 +        return new InputStreamReader(openInputStream(), decoder);
  11.219 +    }
  11.220 +
  11.221 +    @Override
  11.222 +    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  11.223 +        CharBuffer cb = fileManager.getCachedContent(this);
  11.224 +        if (cb == null) {
  11.225 +            InputStream in = openInputStream();
  11.226 +            try {
  11.227 +                ByteBuffer bb = fileManager.makeByteBuffer(in);
  11.228 +                JavaFileObject prev = fileManager.log.useSource(this);
  11.229 +                try {
  11.230 +                    cb = fileManager.decode(bb, ignoreEncodingErrors);
  11.231 +                } finally {
  11.232 +                    fileManager.log.useSource(prev);
  11.233 +                }
  11.234 +                fileManager.recycleByteBuffer(bb);
  11.235 +                if (!ignoreEncodingErrors) {
  11.236 +                    fileManager.cache(this, cb);
  11.237 +                }
  11.238 +            } finally {
  11.239 +                in.close();
  11.240 +            }
  11.241 +        }
  11.242 +        return cb;
  11.243 +    }
  11.244 +
  11.245 +    @Override
  11.246 +    public Writer openWriter() throws IOException {
  11.247 +        ensureParentDirectoriesExist();
  11.248 +        return new OutputStreamWriter(path.newOutputStream(), fileManager.getEncodingName());
  11.249 +    }
  11.250 +
  11.251 +    @Override
  11.252 +    public long getLastModified() {
  11.253 +        try {
  11.254 +            BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path);
  11.255 +            return attrs.lastModifiedTime().toMillis();
  11.256 +        } catch (IOException e) {
  11.257 +            return -1;
  11.258 +        }
  11.259 +    }
  11.260 +
  11.261 +    @Override
  11.262 +    public boolean delete() {
  11.263 +        try {
  11.264 +            path.delete();
  11.265 +            return true;
  11.266 +        } catch (IOException e) {
  11.267 +            return false;
  11.268 +        }
  11.269 +    }
  11.270 +
  11.271 +    public boolean isSameFile(PathFileObject other) {
  11.272 +        try {
  11.273 +            return path.isSameFile(other.path);
  11.274 +        } catch (IOException e) {
  11.275 +            return false;
  11.276 +        }
  11.277 +    }
  11.278 +
  11.279 +    @Override
  11.280 +    public boolean equals(Object other) {
  11.281 +        return (other instanceof PathFileObject && path.equals(((PathFileObject) other).path));
  11.282 +    }
  11.283 +
  11.284 +    @Override
  11.285 +    public int hashCode() {
  11.286 +        return path.hashCode();
  11.287 +    }
  11.288 +
  11.289 +    @Override
  11.290 +    public String toString() {
  11.291 +        return getClass().getSimpleName() + "[" + path + "]";
  11.292 +    }
  11.293 +
  11.294 +    private void ensureParentDirectoriesExist() throws IOException {
  11.295 +        Path parent = path.getParent();
  11.296 +        if (parent != null)
  11.297 +            Files.createDirectories(parent);
  11.298 +    }
  11.299 +
  11.300 +    private long size() {
  11.301 +        try {
  11.302 +            BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path);
  11.303 +            return attrs.size();
  11.304 +        } catch (IOException e) {
  11.305 +            return -1;
  11.306 +        }
  11.307 +    }
  11.308 +
  11.309 +    protected static String toBinaryName(Path relativePath) {
  11.310 +        return toBinaryName(relativePath.toString(),
  11.311 +                relativePath.getFileSystem().getSeparator());
  11.312 +    }
  11.313 +
  11.314 +    protected static String toBinaryName(String relativePath, String sep) {
  11.315 +        return removeExtension(relativePath).replaceAll(sep, ".");
  11.316 +    }
  11.317 +
  11.318 +    protected static String removeExtension(String fileName) {
  11.319 +        int lastDot = fileName.lastIndexOf(".");
  11.320 +        return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
  11.321 +    }
  11.322 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java	Sat Dec 19 10:26:47 2009 -0800
    12.3 @@ -0,0 +1,355 @@
    12.4 +/*
    12.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.7 + *
    12.8 + * This code is free software; you can redistribute it and/or modify it
    12.9 + * under the terms of the GNU General Public License version 2 only, as
   12.10 + * published by the Free Software Foundation.  Sun designates this
   12.11 + * particular file as subject to the "Classpath" exception as provided
   12.12 + * by Sun in the LICENSE file that accompanied this code.
   12.13 + *
   12.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   12.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   12.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   12.17 + * version 2 for more details (a copy is included in the LICENSE file that
   12.18 + * accompanied this code).
   12.19 + *
   12.20 + * You should have received a copy of the GNU General Public License version
   12.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   12.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   12.23 + *
   12.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   12.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   12.26 + * have any questions.
   12.27 + */
   12.28 +
   12.29 +package com.sun.tools.javac.util;
   12.30 +
   12.31 +import com.sun.tools.javac.code.Source;
   12.32 +import com.sun.tools.javac.main.JavacOption;
   12.33 +import com.sun.tools.javac.main.OptionName;
   12.34 +import com.sun.tools.javac.main.RecognizedOptions;
   12.35 +import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
   12.36 +import java.io.ByteArrayOutputStream;
   12.37 +import java.io.Closeable;
   12.38 +import java.io.IOException;
   12.39 +import java.io.InputStream;
   12.40 +import java.io.OutputStreamWriter;
   12.41 +import java.lang.ref.SoftReference;
   12.42 +import java.lang.reflect.Constructor;
   12.43 +import java.net.URL;
   12.44 +import java.net.URLClassLoader;
   12.45 +import java.nio.ByteBuffer;
   12.46 +import java.nio.CharBuffer;
   12.47 +import java.nio.charset.Charset;
   12.48 +import java.nio.charset.CharsetDecoder;
   12.49 +import java.nio.charset.CoderResult;
   12.50 +import java.nio.charset.CodingErrorAction;
   12.51 +import java.nio.charset.IllegalCharsetNameException;
   12.52 +import java.nio.charset.UnsupportedCharsetException;
   12.53 +import java.util.Collection;
   12.54 +import java.util.HashMap;
   12.55 +import java.util.Iterator;
   12.56 +import java.util.Map;
   12.57 +import javax.tools.JavaFileObject;
   12.58 +import javax.tools.JavaFileObject.Kind;
   12.59 +
   12.60 +/**
   12.61 + * Utility methods for building a filemanager.
   12.62 + * There are no references here to file-system specific objects such as
   12.63 + * java.io.File or java.nio.file.Path.
   12.64 + */
   12.65 +public class BaseFileManager {
   12.66 +    protected BaseFileManager(Charset charset) {
   12.67 +        this.charset = charset;
   12.68 +        byteBufferCache = new ByteBufferCache();
   12.69 +    }
   12.70 +
   12.71 +    /**
   12.72 +     * Set the context for JavacPathFileManager.
   12.73 +     */
   12.74 +    protected void setContext(Context context) {
   12.75 +        log = Log.instance(context);
   12.76 +        options = Options.instance(context);
   12.77 +        classLoaderClass = options.get("procloader");
   12.78 +    }
   12.79 +
   12.80 +    /**
   12.81 +     * The log to be used for error reporting.
   12.82 +     */
   12.83 +    public Log log;
   12.84 +
   12.85 +    /**
   12.86 +     * User provided charset (through javax.tools).
   12.87 +     */
   12.88 +    protected Charset charset;
   12.89 +
   12.90 +    protected Options options;
   12.91 +
   12.92 +    protected String classLoaderClass;
   12.93 +
   12.94 +    protected Source getSource() {
   12.95 +        String sourceName = options.get(OptionName.SOURCE);
   12.96 +        Source source = null;
   12.97 +        if (sourceName != null)
   12.98 +            source = Source.lookup(sourceName);
   12.99 +        return (source != null ? source : Source.DEFAULT);
  12.100 +    }
  12.101 +
  12.102 +    protected ClassLoader getClassLoader(URL[] urls) {
  12.103 +        ClassLoader thisClassLoader = getClass().getClassLoader();
  12.104 +
  12.105 +        // Bug: 6558476
  12.106 +        // Ideally, ClassLoader should be Closeable, but before JDK7 it is not.
  12.107 +        // On older versions, try the following, to get a closeable classloader.
  12.108 +
  12.109 +        // 1: Allow client to specify the class to use via hidden option
  12.110 +        if (classLoaderClass != null) {
  12.111 +            try {
  12.112 +                Class<? extends ClassLoader> loader =
  12.113 +                        Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
  12.114 +                Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
  12.115 +                Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
  12.116 +                return constr.newInstance(new Object[] { urls, thisClassLoader });
  12.117 +            } catch (Throwable t) {
  12.118 +                // ignore errors loading user-provided class loader, fall through
  12.119 +            }
  12.120 +        }
  12.121 +
  12.122 +        // 2: If URLClassLoader implements Closeable, use that.
  12.123 +        if (Closeable.class.isAssignableFrom(URLClassLoader.class))
  12.124 +            return new URLClassLoader(urls, thisClassLoader);
  12.125 +
  12.126 +        // 3: Try using private reflection-based CloseableURLClassLoader
  12.127 +        try {
  12.128 +            return new CloseableURLClassLoader(urls, thisClassLoader);
  12.129 +        } catch (Throwable t) {
  12.130 +            // ignore errors loading workaround class loader, fall through
  12.131 +        }
  12.132 +
  12.133 +        // 4: If all else fails, use plain old standard URLClassLoader
  12.134 +        return new URLClassLoader(urls, thisClassLoader);
  12.135 +    }
  12.136 +
  12.137 +    // <editor-fold defaultstate="collapsed" desc="Option handling">
  12.138 +    public boolean handleOption(String current, Iterator<String> remaining) {
  12.139 +        for (JavacOption o: javacFileManagerOptions) {
  12.140 +            if (o.matches(current))  {
  12.141 +                if (o.hasArg()) {
  12.142 +                    if (remaining.hasNext()) {
  12.143 +                        if (!o.process(options, current, remaining.next()))
  12.144 +                            return true;
  12.145 +                    }
  12.146 +                } else {
  12.147 +                    if (!o.process(options, current))
  12.148 +                        return true;
  12.149 +                }
  12.150 +                // operand missing, or process returned false
  12.151 +                throw new IllegalArgumentException(current);
  12.152 +            }
  12.153 +        }
  12.154 +
  12.155 +        return false;
  12.156 +    }
  12.157 +    // where
  12.158 +        private static JavacOption[] javacFileManagerOptions =
  12.159 +            RecognizedOptions.getJavacFileManagerOptions(
  12.160 +            new RecognizedOptions.GrumpyHelper());
  12.161 +
  12.162 +    public int isSupportedOption(String option) {
  12.163 +        for (JavacOption o : javacFileManagerOptions) {
  12.164 +            if (o.matches(option))
  12.165 +                return o.hasArg() ? 1 : 0;
  12.166 +        }
  12.167 +        return -1;
  12.168 +    }
  12.169 +    // </editor-fold>
  12.170 +
  12.171 +    // <editor-fold defaultstate="collapsed" desc="Encoding">
  12.172 +    private String defaultEncodingName;
  12.173 +    private String getDefaultEncodingName() {
  12.174 +        if (defaultEncodingName == null) {
  12.175 +            defaultEncodingName =
  12.176 +                new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
  12.177 +        }
  12.178 +        return defaultEncodingName;
  12.179 +    }
  12.180 +
  12.181 +    public String getEncodingName() {
  12.182 +        String encName = options.get(OptionName.ENCODING);
  12.183 +        if (encName == null)
  12.184 +            return getDefaultEncodingName();
  12.185 +        else
  12.186 +            return encName;
  12.187 +    }
  12.188 +
  12.189 +    public CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
  12.190 +        String encodingName = getEncodingName();
  12.191 +        CharsetDecoder decoder;
  12.192 +        try {
  12.193 +            decoder = getDecoder(encodingName, ignoreEncodingErrors);
  12.194 +        } catch (IllegalCharsetNameException e) {
  12.195 +            log.error("unsupported.encoding", encodingName);
  12.196 +            return (CharBuffer)CharBuffer.allocate(1).flip();
  12.197 +        } catch (UnsupportedCharsetException e) {
  12.198 +            log.error("unsupported.encoding", encodingName);
  12.199 +            return (CharBuffer)CharBuffer.allocate(1).flip();
  12.200 +        }
  12.201 +
  12.202 +        // slightly overestimate the buffer size to avoid reallocation.
  12.203 +        float factor =
  12.204 +            decoder.averageCharsPerByte() * 0.8f +
  12.205 +            decoder.maxCharsPerByte() * 0.2f;
  12.206 +        CharBuffer dest = CharBuffer.
  12.207 +            allocate(10 + (int)(inbuf.remaining()*factor));
  12.208 +
  12.209 +        while (true) {
  12.210 +            CoderResult result = decoder.decode(inbuf, dest, true);
  12.211 +            dest.flip();
  12.212 +
  12.213 +            if (result.isUnderflow()) { // done reading
  12.214 +                // make sure there is at least one extra character
  12.215 +                if (dest.limit() == dest.capacity()) {
  12.216 +                    dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
  12.217 +                    dest.flip();
  12.218 +                }
  12.219 +                return dest;
  12.220 +            } else if (result.isOverflow()) { // buffer too small; expand
  12.221 +                int newCapacity =
  12.222 +                    10 + dest.capacity() +
  12.223 +                    (int)(inbuf.remaining()*decoder.maxCharsPerByte());
  12.224 +                dest = CharBuffer.allocate(newCapacity).put(dest);
  12.225 +            } else if (result.isMalformed() || result.isUnmappable()) {
  12.226 +                // bad character in input
  12.227 +
  12.228 +                // report coding error (warn only pre 1.5)
  12.229 +                if (!getSource().allowEncodingErrors()) {
  12.230 +                    log.error(new SimpleDiagnosticPosition(dest.limit()),
  12.231 +                              "illegal.char.for.encoding",
  12.232 +                              charset == null ? encodingName : charset.name());
  12.233 +                } else {
  12.234 +                    log.warning(new SimpleDiagnosticPosition(dest.limit()),
  12.235 +                                "illegal.char.for.encoding",
  12.236 +                                charset == null ? encodingName : charset.name());
  12.237 +                }
  12.238 +
  12.239 +                // skip past the coding error
  12.240 +                inbuf.position(inbuf.position() + result.length());
  12.241 +
  12.242 +                // undo the flip() to prepare the output buffer
  12.243 +                // for more translation
  12.244 +                dest.position(dest.limit());
  12.245 +                dest.limit(dest.capacity());
  12.246 +                dest.put((char)0xfffd); // backward compatible
  12.247 +            } else {
  12.248 +                throw new AssertionError(result);
  12.249 +            }
  12.250 +        }
  12.251 +        // unreached
  12.252 +    }
  12.253 +
  12.254 +    public CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
  12.255 +        Charset cs = (this.charset == null)
  12.256 +            ? Charset.forName(encodingName)
  12.257 +            : this.charset;
  12.258 +        CharsetDecoder decoder = cs.newDecoder();
  12.259 +
  12.260 +        CodingErrorAction action;
  12.261 +        if (ignoreEncodingErrors)
  12.262 +            action = CodingErrorAction.REPLACE;
  12.263 +        else
  12.264 +            action = CodingErrorAction.REPORT;
  12.265 +
  12.266 +        return decoder
  12.267 +            .onMalformedInput(action)
  12.268 +            .onUnmappableCharacter(action);
  12.269 +    }
  12.270 +    // </editor-fold>
  12.271 +
  12.272 +    // <editor-fold defaultstate="collapsed" desc="ByteBuffers">
  12.273 +    /**
  12.274 +     * Make a byte buffer from an input stream.
  12.275 +     */
  12.276 +    public ByteBuffer makeByteBuffer(InputStream in)
  12.277 +        throws IOException {
  12.278 +        int limit = in.available();
  12.279 +        if (limit < 1024) limit = 1024;
  12.280 +        ByteBuffer result = byteBufferCache.get(limit);
  12.281 +        int position = 0;
  12.282 +        while (in.available() != 0) {
  12.283 +            if (position >= limit)
  12.284 +                // expand buffer
  12.285 +                result = ByteBuffer.
  12.286 +                    allocate(limit <<= 1).
  12.287 +                    put((ByteBuffer)result.flip());
  12.288 +            int count = in.read(result.array(),
  12.289 +                position,
  12.290 +                limit - position);
  12.291 +            if (count < 0) break;
  12.292 +            result.position(position += count);
  12.293 +        }
  12.294 +        return (ByteBuffer)result.flip();
  12.295 +    }
  12.296 +
  12.297 +    public void recycleByteBuffer(ByteBuffer bb) {
  12.298 +        byteBufferCache.put(bb);
  12.299 +    }
  12.300 +
  12.301 +    /**
  12.302 +     * A single-element cache of direct byte buffers.
  12.303 +     */
  12.304 +    private static class ByteBufferCache {
  12.305 +        private ByteBuffer cached;
  12.306 +        ByteBuffer get(int capacity) {
  12.307 +            if (capacity < 20480) capacity = 20480;
  12.308 +            ByteBuffer result =
  12.309 +                (cached != null && cached.capacity() >= capacity)
  12.310 +                ? (ByteBuffer)cached.clear()
  12.311 +                : ByteBuffer.allocate(capacity + capacity>>1);
  12.312 +            cached = null;
  12.313 +            return result;
  12.314 +        }
  12.315 +        void put(ByteBuffer x) {
  12.316 +            cached = x;
  12.317 +        }
  12.318 +    }
  12.319 +
  12.320 +    private final ByteBufferCache byteBufferCache;
  12.321 +    // </editor-fold>
  12.322 +
  12.323 +    // <editor-fold defaultstate="collapsed" desc="Content cache">
  12.324 +    public CharBuffer getCachedContent(JavaFileObject file) {
  12.325 +        SoftReference<CharBuffer> r = contentCache.get(file);
  12.326 +        return (r == null ? null : r.get());
  12.327 +    }
  12.328 +
  12.329 +    public void cache(JavaFileObject file, CharBuffer cb) {
  12.330 +        contentCache.put(file, new SoftReference<CharBuffer>(cb));
  12.331 +    }
  12.332 +
  12.333 +    protected final Map<JavaFileObject, SoftReference<CharBuffer>> contentCache
  12.334 +            = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
  12.335 +    // </editor-fold>
  12.336 +
  12.337 +    public static Kind getKind(String name) {
  12.338 +        if (name.endsWith(Kind.CLASS.extension))
  12.339 +            return Kind.CLASS;
  12.340 +        else if (name.endsWith(Kind.SOURCE.extension))
  12.341 +            return Kind.SOURCE;
  12.342 +        else if (name.endsWith(Kind.HTML.extension))
  12.343 +            return Kind.HTML;
  12.344 +        else
  12.345 +            return Kind.OTHER;
  12.346 +    }
  12.347 +
  12.348 +    protected static <T> T nullCheck(T o) {
  12.349 +        o.getClass(); // null check
  12.350 +        return o;
  12.351 +    }
  12.352 +
  12.353 +    protected static <T> Collection<T> nullCheck(Collection<T> it) {
  12.354 +        for (T t : it)
  12.355 +            t.getClass(); // null check
  12.356 +        return it;
  12.357 +    }
  12.358 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/share/classes/com/sun/tools/javac/util/CloseableURLClassLoader.java	Sat Dec 19 10:26:47 2009 -0800
    13.3 @@ -0,0 +1,108 @@
    13.4 +/*
    13.5 + * Copyright 2007 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.  Sun designates this
   13.11 + * particular file as subject to the "Classpath" exception as provided
   13.12 + * by Sun in the LICENSE file that accompanied this code.
   13.13 + *
   13.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   13.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.17 + * version 2 for more details (a copy is included in the LICENSE file that
   13.18 + * accompanied this code).
   13.19 + *
   13.20 + * You should have received a copy of the GNU General Public License version
   13.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   13.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.23 + *
   13.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   13.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   13.26 + * have any questions.
   13.27 + */
   13.28 +
   13.29 +package com.sun.tools.javac.util;
   13.30 +
   13.31 +import java.io.Closeable;
   13.32 +import java.io.IOException;
   13.33 +import java.lang.reflect.Field;
   13.34 +import java.net.URL;
   13.35 +import java.net.URLClassLoader;
   13.36 +import java.util.ArrayList;
   13.37 +import java.util.jar.JarFile;
   13.38 +
   13.39 +/**
   13.40 + * A URLClassLoader that also implements Closeable.
   13.41 + * Reflection is used to access internal data structures in the URLClassLoader,
   13.42 + * since no public API exists for this purpose. Therefore this code is somewhat
   13.43 + * fragile. Caveat emptor.
   13.44 + * @throws Error if the internal data structures are not as expected.
   13.45 + *
   13.46 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
   13.47 + *  you write code that depends on this, you do so at your own risk.
   13.48 + *  This code and its internal interfaces are subject to change or
   13.49 + *  deletion without notice.</b>
   13.50 + */
   13.51 +public class CloseableURLClassLoader
   13.52 +        extends URLClassLoader implements Closeable {
   13.53 +    public CloseableURLClassLoader(URL[] urls, ClassLoader parent) throws Error {
   13.54 +        super(urls, parent);
   13.55 +        try {
   13.56 +            getLoaders(); //proactive check that URLClassLoader is as expected
   13.57 +        } catch (Throwable t) {
   13.58 +            throw new Error("cannot create CloseableURLClassLoader", t);
   13.59 +        }
   13.60 +    }
   13.61 +
   13.62 +    /**
   13.63 +     * Close any jar files that may have been opened by the class loader.
   13.64 +     * Reflection is used to access the jar files in the URLClassLoader's
   13.65 +     * internal data structures.
   13.66 +     * @throws java.io.IOException if the jar files cannot be found for any
   13.67 +     * reson, or if closing the jar file itself causes an IOException.
   13.68 +     */
   13.69 +    @Override
   13.70 +    public void close() throws IOException {
   13.71 +        try {
   13.72 +            for (Object l: getLoaders()) {
   13.73 +                if (l.getClass().getName().equals("sun.misc.URLClassPath$JarLoader")) {
   13.74 +                    Field jarField = l.getClass().getDeclaredField("jar");
   13.75 +                    JarFile jar = (JarFile) getField(l, jarField);
   13.76 +                    if (jar != null) {
   13.77 +                        //System.err.println("CloseableURLClassLoader: closing " + jar);
   13.78 +                        jar.close();
   13.79 +                    }
   13.80 +                }
   13.81 +            }
   13.82 +        } catch (Throwable t) {
   13.83 +            IOException e = new IOException("cannot close class loader");
   13.84 +            e.initCause(t);
   13.85 +            throw e;
   13.86 +        }
   13.87 +    }
   13.88 +
   13.89 +    private ArrayList<?> getLoaders()
   13.90 +            throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException
   13.91 +    {
   13.92 +        Field ucpField = URLClassLoader.class.getDeclaredField("ucp");
   13.93 +        Object urlClassPath = getField(this, ucpField);
   13.94 +        if (urlClassPath == null)
   13.95 +            throw new AssertionError("urlClassPath not set in URLClassLoader");
   13.96 +        Field loadersField = urlClassPath.getClass().getDeclaredField("loaders");
   13.97 +        return (ArrayList<?>) getField(urlClassPath, loadersField);
   13.98 +    }
   13.99 +
  13.100 +    private Object getField(Object o, Field f)
  13.101 +            throws IllegalArgumentException, IllegalAccessException {
  13.102 +        boolean prev = f.isAccessible();
  13.103 +        try {
  13.104 +            f.setAccessible(true);
  13.105 +            return f.get(o);
  13.106 +        } finally {
  13.107 +            f.setAccessible(prev);
  13.108 +        }
  13.109 +    }
  13.110 +
  13.111 +}
    14.1 --- a/src/share/classes/javax/lang/model/element/package-info.java	Thu Dec 17 14:10:44 2009 -0800
    14.2 +++ b/src/share/classes/javax/lang/model/element/package-info.java	Sat Dec 19 10:26:47 2009 -0800
    14.3 @@ -26,6 +26,16 @@
    14.4  /**
    14.5   * Interfaces used to model elements of the Java programming language.
    14.6   *
    14.7 + * The term "element" in this package is used to refer to program
    14.8 + * elements, the declared entities that make up a program.  Elements
    14.9 + * include classes, interfaces, methods, constructors, and fields.
   14.10 + * The interfaces in this package do not model the structure of a
   14.11 + * program inside a method body; for example there is no
   14.12 + * representation of a {@code for} loop or {@code try}-{@code finally}
   14.13 + * block.  However, the interfaces can model some structures only
   14.14 + * appearing inside method bodies, such as local variables and
   14.15 + * anonymous classes.
   14.16 + *
   14.17   * <p>When used in the context of annotation processing, an accurate
   14.18   * model of the element being represented must be returned.  As this
   14.19   * is a language model, the source code provides the fiducial
    15.1 --- a/src/share/classes/javax/tools/StandardJavaFileManager.java	Thu Dec 17 14:10:44 2009 -0800
    15.2 +++ b/src/share/classes/javax/tools/StandardJavaFileManager.java	Sat Dec 19 10:26:47 2009 -0800
    15.3 @@ -28,7 +28,6 @@
    15.4  import java.io.File;
    15.5  import java.io.IOException;
    15.6  import java.util.*;
    15.7 -import java.util.concurrent.*;
    15.8  
    15.9  /**
   15.10   * File manager based on {@linkplain File java.io.File}.  A common way
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/test/tools/javac/nio/compileTest/CompileTest.java	Sat Dec 19 10:26:47 2009 -0800
    16.3 @@ -0,0 +1,165 @@
    16.4 +/*
    16.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    16.7 + *
    16.8 + * This code is free software; you can redistribute it and/or modify it
    16.9 + * under the terms of the GNU General Public License version 2 only, as
   16.10 + * published by the Free Software Foundation.
   16.11 + *
   16.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   16.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   16.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   16.15 + * version 2 for more details (a copy is included in the LICENSE file that
   16.16 + * accompanied this code).
   16.17 + *
   16.18 + * You should have received a copy of the GNU General Public License version
   16.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   16.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   16.21 + *
   16.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   16.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   16.24 + * have any questions.
   16.25 + */
   16.26 +
   16.27 +/**
   16.28 + * @test
   16.29 + * @compile HelloPathWorld.java
   16.30 + * @run main CompileTest
   16.31 + */
   16.32 +
   16.33 +import java.io.*;
   16.34 +import java.nio.file.*;
   16.35 +import java.util.*;
   16.36 +import java.util.jar.*;
   16.37 +import javax.tools.*;
   16.38 +
   16.39 +import com.sun.tools.javac.nio.*;
   16.40 +import com.sun.tools.javac.util.Context;
   16.41 +import java.nio.file.spi.FileSystemProvider;
   16.42 +
   16.43 +
   16.44 +public class CompileTest {
   16.45 +    public static void main(String[] args) throws Exception {
   16.46 +        new CompileTest().run();
   16.47 +    }
   16.48 +
   16.49 +    public void run() throws Exception {
   16.50 +        File rtDir = new File("rt.dir");
   16.51 +        File javaHome = new File(System.getProperty("java.home"));
   16.52 +        if (javaHome.getName().equals("jre"))
   16.53 +            javaHome = javaHome.getParentFile();
   16.54 +        File rtJar = new File(new File(new File(javaHome, "jre"), "lib"), "rt.jar");
   16.55 +        expand(rtJar, rtDir);
   16.56 +
   16.57 +        String[] rtDir_opts = {
   16.58 +            "-bootclasspath", rtDir.toString(),
   16.59 +            "-classpath", "",
   16.60 +            "-sourcepath", "",
   16.61 +            "-extdirs", ""
   16.62 +        };
   16.63 +        test(rtDir_opts, "HelloPathWorld");
   16.64 +
   16.65 +        if (isJarFileSystemAvailable()) {
   16.66 +            String[] rtJar_opts = {
   16.67 +                "-bootclasspath", rtJar.toString(),
   16.68 +                "-classpath", "",
   16.69 +                "-sourcepath", "",
   16.70 +                "-extdirs", ""
   16.71 +            };
   16.72 +            test(rtJar_opts, "HelloPathWorld");
   16.73 +
   16.74 +            String[] default_opts = { };
   16.75 +            test(default_opts, "HelloPathWorld");
   16.76 +
   16.77 +            // finally, a non-trivial program
   16.78 +            test(default_opts, "CompileTest");
   16.79 +        } else
   16.80 +            System.err.println("jar file system not available: test skipped");
   16.81 +    }
   16.82 +
   16.83 +    void test(String[] opts, String className) throws Exception {
   16.84 +        count++;
   16.85 +        System.err.println("Test " + count + " " + Arrays.asList(opts) + " " + className);
   16.86 +        Path testSrcDir = Paths.get(System.getProperty("test.src"));
   16.87 +        Path testClassesDir = Paths.get(System.getProperty("test.classes"));
   16.88 +        Path classes = Paths.get("classes." + count);
   16.89 +        classes.createDirectory();
   16.90 +
   16.91 +        Context ctx = new Context();
   16.92 +        PathFileManager fm = new JavacPathFileManager(ctx, true, null);
   16.93 +        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
   16.94 +        List<String> options = new ArrayList<String>();
   16.95 +        options.addAll(Arrays.asList(opts));
   16.96 +        options.addAll(Arrays.asList(
   16.97 +                "-verbose", "-XDverboseCompilePolicy",
   16.98 +                "-d", classes.toString()
   16.99 +        ));
  16.100 +        Iterable<? extends JavaFileObject> compilationUnits =
  16.101 +                fm.getJavaFileObjects(testSrcDir.resolve(className + ".java"));
  16.102 +        StringWriter sw = new StringWriter();
  16.103 +        PrintWriter out = new PrintWriter(sw);
  16.104 +        JavaCompiler.CompilationTask t =
  16.105 +                compiler.getTask(out, fm, null, options, null, compilationUnits);
  16.106 +        boolean ok = t.call();
  16.107 +        System.err.println(sw.toString());
  16.108 +        if (!ok) {
  16.109 +            throw new Exception("compilation failed");
  16.110 +        }
  16.111 +
  16.112 +        File expect = new File("classes." + count + "/" + className + ".class");
  16.113 +        if (!expect.exists())
  16.114 +            throw new Exception("expected file not found: " + expect);
  16.115 +        long expectedSize = new File(testClassesDir.toString(), className + ".class").length();
  16.116 +        long actualSize = expect.length();
  16.117 +        if (expectedSize != actualSize)
  16.118 +            throw new Exception("wrong size found: " + actualSize + "; expected: " + expectedSize);
  16.119 +    }
  16.120 +
  16.121 +    boolean isJarFileSystemAvailable() {
  16.122 +        boolean result = false;
  16.123 +        for (FileSystemProvider fsp: FileSystemProvider.installedProviders()) {
  16.124 +            String scheme = fsp.getScheme();
  16.125 +            System.err.println("Provider: " + scheme + " " + fsp);
  16.126 +            if (scheme.equalsIgnoreCase("jar") || scheme.equalsIgnoreCase("zip"))
  16.127 +                result = true;
  16.128 +        }
  16.129 +        return result;
  16.130 +    }
  16.131 +
  16.132 +    void expand(File jar, File dir) throws IOException {
  16.133 +        JarFile jarFile = new JarFile(jar);
  16.134 +        try {
  16.135 +            Enumeration<JarEntry> entries = jarFile.entries();
  16.136 +            while (entries.hasMoreElements()) {
  16.137 +                JarEntry je = entries.nextElement();
  16.138 +                if (!je.isDirectory()) {
  16.139 +                    copy(jarFile.getInputStream(je), new File(dir, je.getName()));
  16.140 +                }
  16.141 +            }
  16.142 +        } finally {
  16.143 +            jarFile.close();
  16.144 +        }
  16.145 +    }
  16.146 +
  16.147 +    void copy(InputStream in, File dest) throws IOException {
  16.148 +        dest.getParentFile().mkdirs();
  16.149 +        OutputStream out = new BufferedOutputStream(new FileOutputStream(dest));
  16.150 +        try {
  16.151 +            byte[] data = new byte[8192];
  16.152 +            int n;
  16.153 +            while ((n = in.read(data, 0, data.length)) > 0)
  16.154 +                out.write(data, 0, n);
  16.155 +        } finally {
  16.156 +            out.close();
  16.157 +            in.close();
  16.158 +        }
  16.159 +    }
  16.160 +
  16.161 +    void error(String message) {
  16.162 +        System.err.println("Error: " + message);
  16.163 +        errors++;
  16.164 +    }
  16.165 +
  16.166 +    int errors;
  16.167 +    int count;
  16.168 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/test/tools/javac/nio/compileTest/HelloPathWorld.java	Sat Dec 19 10:26:47 2009 -0800
    17.3 @@ -0,0 +1,28 @@
    17.4 +/*
    17.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    17.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    17.7 + *
    17.8 + * This code is free software; you can redistribute it and/or modify it
    17.9 + * under the terms of the GNU General Public License version 2 only, as
   17.10 + * published by the Free Software Foundation.
   17.11 + *
   17.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   17.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   17.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   17.15 + * version 2 for more details (a copy is included in the LICENSE file that
   17.16 + * accompanied this code).
   17.17 + *
   17.18 + * You should have received a copy of the GNU General Public License version
   17.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   17.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   17.21 + *
   17.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   17.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   17.24 + * have any questions.
   17.25 + */
   17.26 +
   17.27 +class HelloPathWorld {
   17.28 +    public static void main(String... args) {
   17.29 +        System.out.println("Hello World!");
   17.30 +    }
   17.31 +}
    18.1 --- a/test/tools/javac/processing/environment/round/TestElementsAnnotatedWith.java	Thu Dec 17 14:10:44 2009 -0800
    18.2 +++ b/test/tools/javac/processing/environment/round/TestElementsAnnotatedWith.java	Sat Dec 19 10:26:47 2009 -0800
    18.3 @@ -23,7 +23,7 @@
    18.4  
    18.5  /*
    18.6   * @test
    18.7 - * @bug 6397298 6400986 6425592 6449798 6453386 6508401 6498938
    18.8 + * @bug 6397298 6400986 6425592 6449798 6453386 6508401 6498938 6911854
    18.9   * @summary Tests that getElementsAnnotatedWith works properly.
   18.10   * @author  Joseph D. Darcy
   18.11   * @compile TestElementsAnnotatedWith.java
   18.12 @@ -33,8 +33,8 @@
   18.13   * @compile -processor TestElementsAnnotatedWith -proc:only Part1.java Part2.java
   18.14   * @compile -processor TestElementsAnnotatedWith -proc:only C2.java
   18.15   * @compile -processor TestElementsAnnotatedWith -proc:only Foo.java
   18.16 - * @compile -XD-d=. Foo.java
   18.17 - * @compile -processor TestElementsAnnotatedWith -proc:only TestElementsAnnotatedWith.java
   18.18 + * @compile Foo.java
   18.19 + * @compile/process -processor TestElementsAnnotatedWith -proc:only Foo
   18.20   */
   18.21  
   18.22  import java.lang.annotation.Annotation;
   18.23 @@ -89,7 +89,7 @@
   18.24                  // Verify that the annotation information is as
   18.25                  // expected.
   18.26  
   18.27 -                Set<String> expectedNames = new HashSet<String>(Arrays.asList(annotatedElementInfo.names()));
   18.28 +                Set<String> expectedNames = new HashSet<>(Arrays.asList(annotatedElementInfo.names()));
   18.29  
   18.30                  resultsMeta =
   18.31                      roundEnvironment.
   18.32 @@ -126,9 +126,6 @@
   18.33                  System.err.println("AnnotatedElementInfo: " + annotatedElementInfo);
   18.34                  throw new RuntimeException();
   18.35              }
   18.36 -
   18.37 -            if("TestElementsAnnotatedWith".equals(firstType.getSimpleName().toString()))
   18.38 -               writeClassFile(); // Start another round to test class file input
   18.39          } else {
   18.40              // If processing is over without an error, the specified
   18.41              // elements should be empty so an empty set should be returned.
   18.42 @@ -163,48 +160,14 @@
   18.43          } catch(IllegalArgumentException iae) {}
   18.44  
   18.45          try {
   18.46 -            Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(processingEnv.
   18.47 -                                                                                        getElementUtils().
   18.48 -                                                                                        getTypeElement("java.lang.Object") );
   18.49 +            Set<? extends Element> elements =
   18.50 +                roundEnvironment.getElementsAnnotatedWith(processingEnv.
   18.51 +                                                          getElementUtils().
   18.52 +                                                          getTypeElement("java.lang.Object") );
   18.53              throw new RuntimeException("Illegal argument exception not thrown");
   18.54          } catch(IllegalArgumentException iae) {}
   18.55      }
   18.56  
   18.57 -    /*
   18.58 -     * Hack alert!  The class file read below is generated by the
   18.59 -     * "@compile -XD-d=. Foo.java" directive above.  This sneakily
   18.60 -     * overrides the output location to the current directory where a
   18.61 -     * subsequent @compile can read the file.  This could be improved
   18.62 -     * if either a new directive like @process accepted class file
   18.63 -     * arguments (the javac command accepts such arguments but
   18.64 -     * @compile does not) or the test.src and test.classes properties
   18.65 -     * were set to be read with @compile jobs.
   18.66 -     */
   18.67 -    private void writeClassFile() {
   18.68 -        try {
   18.69 -            Filer filer = processingEnv.getFiler();
   18.70 -            JavaFileObject jfo = filer.createClassFile("Foo");
   18.71 -            OutputStream os = jfo.openOutputStream();
   18.72 -            // Copy the bytes over
   18.73 -            System.out.println((new File(".")).getAbsolutePath());
   18.74 -            InputStream io = new BufferedInputStream(new FileInputStream(new File(".", "Foo.class")));
   18.75 -            try {
   18.76 -                int datum = io.read();
   18.77 -                while(datum != -1) {
   18.78 -                    os.write(datum);
   18.79 -                    datum = io.read();
   18.80 -                }
   18.81 -            } finally {
   18.82 -                io.close();
   18.83 -            }
   18.84 -            os.close();
   18.85 -        } catch (IOException ioe) {
   18.86 -            throw new RuntimeException(ioe);
   18.87 -        }
   18.88 -
   18.89 -
   18.90 -    }
   18.91 -
   18.92      @Override
   18.93      public SourceVersion getSupportedSourceVersion() {
   18.94          return SourceVersion.latest();
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/test/tools/javap/classfile/deps/GetDeps.java	Sat Dec 19 10:26:47 2009 -0800
    19.3 @@ -0,0 +1,211 @@
    19.4 +/*
    19.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.7 + *
    19.8 + * This code is free software; you can redistribute it and/or modify it
    19.9 + * under the terms of the GNU General Public License version 2 only, as
   19.10 + * published by the Free Software Foundation.  Sun designates this
   19.11 + * particular file as subject to the "Classpath" exception as provided
   19.12 + * by Sun in the LICENSE file that accompanied this code.
   19.13 + *
   19.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   19.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   19.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   19.17 + * version 2 for more details (a copy is included in the LICENSE file that
   19.18 + * accompanied this code).
   19.19 + *
   19.20 + * You should have received a copy of the GNU General Public License version
   19.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   19.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   19.23 + *
   19.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   19.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   19.26 + * have any questions.
   19.27 + */
   19.28 +
   19.29 +import java.io.*;
   19.30 +import java.util.*;
   19.31 +import java.util.regex.Pattern;
   19.32 +import javax.tools.*;
   19.33 +
   19.34 +import com.sun.tools.classfile.*;
   19.35 +import com.sun.tools.classfile.Dependencies.*;
   19.36 +import com.sun.tools.classfile.Dependency.Location;
   19.37 +import com.sun.tools.javac.file.JavacFileManager;
   19.38 +import com.sun.tools.javac.util.Context;
   19.39 +
   19.40 +/**
   19.41 + * Demo utility for using the classfile dependency analysis API framework.
   19.42 + *
   19.43 + * Usage:
   19.44 + *    getdeps [options] classes
   19.45 + * where options include:
   19.46 + *    -classpath path   where to find classes to analyze
   19.47 + *    -p package-name   restrict analysis to classes in this package
   19.48 + *                      (may be given multiple times)
   19.49 + *    -r regex          restrict analysis to packages matching pattern
   19.50 + *                      (-p and -r are exclusive)
   19.51 + *    -rev              invert the dependencies in the output
   19.52 + *    -t                transitive closure of dependencies
   19.53 + */
   19.54 +public class GetDeps {
   19.55 +    public static void main(String... args) throws Exception {
   19.56 +        new GetDeps().run(args);
   19.57 +    }
   19.58 +
   19.59 +    void run(String... args) throws IOException, ClassFileNotFoundException {
   19.60 +        PrintWriter pw = new PrintWriter(System.out);
   19.61 +        try {
   19.62 +            run(pw, args);
   19.63 +        } finally {
   19.64 +            pw.flush();
   19.65 +        }
   19.66 +    }
   19.67 +
   19.68 +    void run(PrintWriter out, String... args) throws IOException, ClassFileNotFoundException {
   19.69 +        decodeArgs(args);
   19.70 +
   19.71 +        final StandardJavaFileManager fm = new JavacFileManager(new Context(), false, null);
   19.72 +        if (classpath != null)
   19.73 +            fm.setLocation(StandardLocation.CLASS_PATH, classpath);
   19.74 +
   19.75 +        ClassFileReader reader = new ClassFileReader(fm);
   19.76 +
   19.77 +        Dependencies d = new Dependencies();
   19.78 +
   19.79 +        if (regex != null)
   19.80 +            d.setFilter(Dependencies.getRegexFilter(Pattern.compile(regex)));
   19.81 +
   19.82 +        if (packageNames.size() > 0)
   19.83 +            d.setFilter(Dependencies.getPackageFilter(packageNames, false));
   19.84 +
   19.85 +        SortedRecorder r = new SortedRecorder(reverse);
   19.86 +
   19.87 +        d.findAllDependencies(reader, rootClassNames, transitiveClosure, r);
   19.88 +
   19.89 +        SortedMap<Location,SortedSet<Dependency>> deps = r.getMap();
   19.90 +        for (Map.Entry<Location, SortedSet<Dependency>> e: deps.entrySet()) {
   19.91 +            out.println(e.getKey());
   19.92 +            for (Dependency dep: e.getValue()) {
   19.93 +                out.println("    " + dep.getTarget());
   19.94 +            }
   19.95 +        }
   19.96 +    }
   19.97 +
   19.98 +    void decodeArgs(String... args) {
   19.99 +        rootClassNames = new TreeSet<String>();
  19.100 +        packageNames = new TreeSet<String>();
  19.101 +
  19.102 +        for (int i = 0; i < args.length; i++) {
  19.103 +            String arg = args[i];
  19.104 +            if (arg.equals("-classpath") && (i + 1 < args.length))
  19.105 +                classpath = getPathFiles(args[++i]);
  19.106 +            else if (arg.equals("-p") && (i + 1 < args.length))
  19.107 +                packageNames.add(args[++i]);
  19.108 +            else if (arg.equals("-r") && (i + 1 < args.length))
  19.109 +                regex = args[++i];
  19.110 +            else if (arg.equals("-rev"))
  19.111 +                reverse = true;
  19.112 +            else if (arg.equals("-t"))
  19.113 +                transitiveClosure = true;
  19.114 +            else if (arg.startsWith("-"))
  19.115 +                throw new Error(arg);
  19.116 +            else {
  19.117 +                for ( ; i < args.length; i++)
  19.118 +                    rootClassNames.add(args[i]);
  19.119 +            }
  19.120 +        }
  19.121 +    }
  19.122 +
  19.123 +    List<File> getPathFiles(String path) {
  19.124 +        List<File> files = new ArrayList<File>();
  19.125 +        for (String p: path.split(File.pathSeparator)) {
  19.126 +            if (p.length() > 0)
  19.127 +                files.add(new File(p));
  19.128 +        }
  19.129 +        return files;
  19.130 +    }
  19.131 +
  19.132 +    boolean transitiveClosure;
  19.133 +    List<File> classpath;
  19.134 +    Set<String> rootClassNames;
  19.135 +    Set<String> packageNames;
  19.136 +    String regex;
  19.137 +    boolean reverse;
  19.138 +
  19.139 +
  19.140 +    static class ClassFileReader implements Dependencies.ClassFileReader {
  19.141 +        private JavaFileManager fm;
  19.142 +
  19.143 +        ClassFileReader(JavaFileManager fm) {
  19.144 +            this.fm = fm;
  19.145 +        }
  19.146 +
  19.147 +        @Override
  19.148 +        public ClassFile getClassFile(String className) throws ClassFileNotFoundException {
  19.149 +            try {
  19.150 +                JavaFileObject fo = fm.getJavaFileForInput(
  19.151 +                        StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
  19.152 +                if (fo == null)
  19.153 +                    fo = fm.getJavaFileForInput(
  19.154 +                        StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
  19.155 +                if (fo == null)
  19.156 +                    throw new ClassFileNotFoundException(className);
  19.157 +                InputStream in = fo.openInputStream();
  19.158 +                try {
  19.159 +                    return ClassFile.read(in);
  19.160 +                } finally {
  19.161 +                    in.close();
  19.162 +                }
  19.163 +            } catch (ConstantPoolException e) {
  19.164 +                throw new ClassFileNotFoundException(className, e);
  19.165 +            } catch (IOException e) {
  19.166 +                throw new ClassFileNotFoundException(className, e);
  19.167 +            }
  19.168 +        }
  19.169 +    };
  19.170 +
  19.171 +    static class SortedRecorder implements Recorder {
  19.172 +        public SortedRecorder(boolean reverse) {
  19.173 +            this.reverse = reverse;
  19.174 +        }
  19.175 +
  19.176 +        public void addDependency(Dependency d) {
  19.177 +            Location o = (reverse ? d.getTarget() : d.getOrigin());
  19.178 +            SortedSet<Dependency> odeps = map.get(o);
  19.179 +            if (odeps == null) {
  19.180 +                Comparator<Dependency> c = (reverse ? originComparator : targetComparator);
  19.181 +                map.put(o, odeps = new TreeSet<Dependency>(c));
  19.182 +            }
  19.183 +            odeps.add(d);
  19.184 +        }
  19.185 +
  19.186 +        public SortedMap<Location, SortedSet<Dependency>> getMap() {
  19.187 +            return map;
  19.188 +        }
  19.189 +
  19.190 +        private Comparator<Dependency> originComparator = new Comparator<Dependency>() {
  19.191 +            public int compare(Dependency o1, Dependency o2) {
  19.192 +                return o1.getOrigin().toString().compareTo(o2.getOrigin().toString());
  19.193 +            }
  19.194 +        };
  19.195 +
  19.196 +        private Comparator<Dependency> targetComparator = new Comparator<Dependency>() {
  19.197 +            public int compare(Dependency o1, Dependency o2) {
  19.198 +                return o1.getTarget().toString().compareTo(o2.getTarget().toString());
  19.199 +            }
  19.200 +        };
  19.201 +
  19.202 +        private Comparator<Location> locationComparator = new Comparator<Location>() {
  19.203 +            public int compare(Location o1, Location o2) {
  19.204 +                return o1.toString().compareTo(o2.toString());
  19.205 +            }
  19.206 +        };
  19.207 +
  19.208 +        private final SortedMap<Location, SortedSet<Dependency>> map =
  19.209 +                new TreeMap<Location, SortedSet<Dependency>>(locationComparator);
  19.210 +
  19.211 +        boolean reverse;
  19.212 +    }
  19.213 +
  19.214 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/test/tools/javap/classfile/deps/T6907575.java	Sat Dec 19 10:26:47 2009 -0800
    20.3 @@ -0,0 +1,71 @@
    20.4 +/*
    20.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    20.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    20.7 + *
    20.8 + * This code is free software; you can redistribute it and/or modify it
    20.9 + * under the terms of the GNU General Public License version 2 only, as
   20.10 + * published by the Free Software Foundation.  Sun designates this
   20.11 + * particular file as subject to the "Classpath" exception as provided
   20.12 + * by Sun in the LICENSE file that accompanied this code.
   20.13 + *
   20.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   20.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   20.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   20.17 + * version 2 for more details (a copy is included in the LICENSE file that
   20.18 + * accompanied this code).
   20.19 + *
   20.20 + * You should have received a copy of the GNU General Public License version
   20.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   20.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20.23 + *
   20.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   20.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   20.26 + * have any questions.
   20.27 + */
   20.28 +
   20.29 +/*
   20.30 + * @test
   20.31 + * @bug 6907575
   20.32 + * @build GetDeps p.C1
   20.33 + * @run main T6907575
   20.34 + */
   20.35 +
   20.36 +import java.io.*;
   20.37 +
   20.38 +public class T6907575 {
   20.39 +    public static void main(String... args) throws Exception {
   20.40 +        new T6907575().run();
   20.41 +    }
   20.42 +
   20.43 +    void run() throws Exception {
   20.44 +        String testSrc = System.getProperty("test.src");
   20.45 +        String testClasses = System.getProperty("test.classes");
   20.46 +
   20.47 +        StringWriter sw = new StringWriter();
   20.48 +        PrintWriter pw = new PrintWriter(sw);
   20.49 +        GetDeps gd = new GetDeps();
   20.50 +        gd.run(pw, "-classpath", testClasses, "-t", "-p", "p", "p/C1");
   20.51 +        pw.close();
   20.52 +        System.out.println(sw);
   20.53 +
   20.54 +        String ref = readFile(new File(testSrc, "T6907575.out"));
   20.55 +        diff(sw.toString().replaceAll("[\r\n]+", "\n"), ref);
   20.56 +    }
   20.57 +
   20.58 +    void diff(String actual, String ref) throws Exception {
   20.59 +        System.out.println("EXPECT:>>>" + ref + "<<<");
   20.60 +        System.out.println("ACTUAL:>>>" + actual + "<<<");
   20.61 +        if (!actual.equals(ref))
   20.62 +            throw new Exception("output not as expected");
   20.63 +    }
   20.64 +
   20.65 +    String readFile(File f) throws IOException {
   20.66 +        Reader r = new FileReader(f);
   20.67 +        char[] buf = new char[(int) f.length()];
   20.68 +        int offset = 0;
   20.69 +        int n;
   20.70 +        while (offset < buf.length && (n = r.read(buf, offset, buf.length - offset)) != -1)
   20.71 +            offset += n;
   20.72 +        return new String(buf, 0, offset);
   20.73 +    }
   20.74 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/test/tools/javap/classfile/deps/T6907575.out	Sat Dec 19 10:26:47 2009 -0800
    21.3 @@ -0,0 +1,8 @@
    21.4 +p/C1
    21.5 +    java/lang/Object
    21.6 +    p/C2
    21.7 +p/C2
    21.8 +    java/lang/Object
    21.9 +    p/C3
   21.10 +p/C3
   21.11 +    java/lang/Object
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/test/tools/javap/classfile/deps/p/C1.java	Sat Dec 19 10:26:47 2009 -0800
    22.3 @@ -0,0 +1,37 @@
    22.4 +/*
    22.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    22.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    22.7 + *
    22.8 + * This code is free software; you can redistribute it and/or modify it
    22.9 + * under the terms of the GNU General Public License version 2 only, as
   22.10 + * published by the Free Software Foundation.  Sun designates this
   22.11 + * particular file as subject to the "Classpath" exception as provided
   22.12 + * by Sun in the LICENSE file that accompanied this code.
   22.13 + *
   22.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   22.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   22.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   22.17 + * version 2 for more details (a copy is included in the LICENSE file that
   22.18 + * accompanied this code).
   22.19 + *
   22.20 + * You should have received a copy of the GNU General Public License version
   22.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   22.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   22.23 + *
   22.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   22.26 + * have any questions.
   22.27 + */
   22.28 +
   22.29 +package p;
   22.30 +
   22.31 +public class C1 {
   22.32 +    C2 c2;
   22.33 +}
   22.34 +
   22.35 +class C2 {
   22.36 +    C3 c3;
   22.37 +}
   22.38 +
   22.39 +class C3 {
   22.40 +}

mercurial