7026941: 199: path options ignored when reusing filemanager across tasks
authorjjg
Sun, 08 Jun 2014 15:02:34 -0700
changeset 24897 655b72d7b96e
parent 24896 986d876a9121
child 24898 88fa65d2ac87
7026941: 199: path options ignored when reusing filemanager across tasks Reviewed-by: jlahoda, jfranck
langtools/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java
langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java
langtools/src/share/classes/com/sun/tools/javac/file/Locations.java
langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java
langtools/src/share/classes/com/sun/tools/javac/main/Main.java
langtools/src/share/classes/com/sun/tools/javac/main/Option.java
langtools/src/share/classes/com/sun/tools/javac/main/OptionHelper.java
langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java
langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java
langtools/src/share/classes/com/sun/tools/javadoc/Start.java
langtools/src/share/classes/com/sun/tools/javadoc/ToolOption.java
langtools/test/tools/javac/T6358166.java
langtools/test/tools/javac/T6358168.java
langtools/test/tools/javac/api/TestSearchPaths.java
langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java
langtools/test/tools/javac/processing/6430209/T6430209.java
--- a/langtools/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java	Sun Jun 08 15:02:34 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -202,9 +202,6 @@
 
     // <editor-fold defaultstate="collapsed" desc="Wrapper classes">
 
-    // FIXME: all these classes should be converted to use multi-catch when
-    // that is available in the bootstrap compiler.
-
     protected class WrappedJavaFileManager implements JavaFileManager {
         protected JavaFileManager clientJavaFileManager;
         WrappedJavaFileManager(JavaFileManager clientJavaFileManager) {
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Sun Jun 08 15:02:34 2014 -0700
@@ -161,6 +161,15 @@
             compilerMain.log = Log.instance(context);
             compilerMain.setOptions(Options.instance(context));
             compilerMain.filenames = new LinkedHashSet<>();
+            compilerMain.deferredFileManagerOptions = new LinkedHashMap<>();
+            // The following line is conceptually wrong. It should not refer to args
+            // which may include inappropriate file manager options.
+            // (Ideally, args should not even be passed into JavacTaskImpl at all.)
+            // The "no filenames in args" check should have been handled by the use of
+            // the GrumpyHelper in JavacTool.getTask, but processArgs also has some
+            // additional checking, which should be factored out and called separately.
+            // If we fix this, then filenames and deferredFileManagerOptions in Main
+            // can revert to being protected or private, not public.
             Collection<File> filenames = compilerMain.processArgs(CommandLine.parse(args), classNames);
             if (filenames != null && !filenames.isEmpty())
                 throw new IllegalArgumentException("Malformed arguments " + toString(filenames, " "));
--- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Sun Jun 08 15:02:34 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -158,11 +158,6 @@
         symbolFileEnabled = b;
     }
 
-    @Override
-    public boolean isDefaultBootClassPath() {
-        return locations.isDefaultBootClassPath();
-    }
-
     public JavaFileObject getFileForInput(String name) {
         return getRegularFile(new File(name));
     }
@@ -579,15 +574,6 @@
         }
     }
 
-    private String defaultEncodingName;
-    private String getDefaultEncodingName() {
-        if (defaultEncodingName == null) {
-            defaultEncodingName =
-                new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
-        }
-        return defaultEncodingName;
-    }
-
     public ClassLoader getClassLoader(Location location) {
         nullCheck(location);
         Iterable<? extends File> path = getLocation(location);
--- a/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java	Sun Jun 08 15:02:34 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,12 +22,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package com.sun.tools.javac.file;
 
+import java.io.File;
 import java.io.FileNotFoundException;
-import java.util.Iterator;
-import java.io.File;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -38,64 +36,72 @@
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.zip.ZipFile;
+
+import javax.tools.JavaFileManager;
 import javax.tools.JavaFileManager.Location;
+import javax.tools.StandardJavaFileManager;
 import javax.tools.StandardLocation;
 
 import com.sun.tools.javac.code.Lint;
 import com.sun.tools.javac.main.Option;
 import com.sun.tools.javac.util.ListBuffer;
 import com.sun.tools.javac.util.Log;
-import com.sun.tools.javac.util.Options;
 import com.sun.tools.javac.util.StringUtils;
 
-import javax.tools.JavaFileManager;
-import javax.tools.StandardJavaFileManager;
-import static javax.tools.StandardLocation.*;
-import static com.sun.tools.javac.main.Option.*;
+import static javax.tools.StandardLocation.CLASS_PATH;
+import static javax.tools.StandardLocation.PLATFORM_CLASS_PATH;
+import static javax.tools.StandardLocation.SOURCE_PATH;
 
-/** This class converts command line arguments, environment variables
- *  and system properties (in File.pathSeparator-separated String form)
- *  into a boot class path, user class path, and source path (in
- *  {@code Collection<String>} form).
+import static com.sun.tools.javac.main.Option.BOOTCLASSPATH;
+import static com.sun.tools.javac.main.Option.DJAVA_ENDORSED_DIRS;
+import static com.sun.tools.javac.main.Option.DJAVA_EXT_DIRS;
+import static com.sun.tools.javac.main.Option.ENDORSEDDIRS;
+import static com.sun.tools.javac.main.Option.EXTDIRS;
+import static com.sun.tools.javac.main.Option.XBOOTCLASSPATH;
+import static com.sun.tools.javac.main.Option.XBOOTCLASSPATH_APPEND;
+import static com.sun.tools.javac.main.Option.XBOOTCLASSPATH_PREPEND;
+
+/**
+ * This class converts command line arguments, environment variables and system properties (in
+ * File.pathSeparator-separated String form) into a boot class path, user class path, and source
+ * path (in {@code Collection<String>} form).
  *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
+ * <p>
+ * <b>This is NOT part of any supported API. If you write code that depends on this, you do so at
+ * your own risk. This code and its internal interfaces are subject to change or deletion without
+ * notice.</b>
  */
 public class Locations {
 
-    /** The log to use for warning output */
+    /**
+     * The log to use for warning output
+     */
     private Log log;
 
-    /** Collection of command-line options */
-    private Options options;
-
-    /** Handler for -Xlint options */
-    private Lint lint;
-
-    /** Access to (possibly cached) file info */
+    /**
+     * Access to (possibly cached) file info
+     */
     private FSInfo fsInfo;
 
-    /** Whether to warn about non-existent path elements */
+    /**
+     * Whether to warn about non-existent path elements
+     */
     private boolean warn;
 
-    // TODO: remove need for this
-    private boolean inited = false; // TODO? caching bad?
-
     public Locations() {
         initHandlers();
     }
 
-    public void update(Log log, Options options, Lint lint, FSInfo fsInfo) {
+    // could replace Lint by "boolean warn"
+    public void update(Log log, Lint lint, FSInfo fsInfo) {
         this.log = log;
-        this.options = options;
-        this.lint = lint;
+        warn = lint.isEnabled(Lint.LintCategory.PATH);
         this.fsInfo = fsInfo;
     }
 
@@ -104,14 +110,14 @@
     }
 
     public boolean isDefaultBootClassPath() {
-        BootClassPathLocationHandler h =
-                (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
+        BootClassPathLocationHandler h
+                = (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
         return h.isDefault();
     }
 
     boolean isDefaultBootClassPathRtJar(File file) {
-        BootClassPathLocationHandler h =
-                (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
+        BootClassPathLocationHandler h
+                = (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
         return h.isDefaultRtJar(file);
     }
 
@@ -127,6 +133,7 @@
 
     /**
      * Split a path into its elements. Empty path elements will be ignored.
+     *
      * @param path The path to be split
      * @return The elements of the path
      */
@@ -135,12 +142,13 @@
     }
 
     /**
-     * Split a path into its elements. If emptyPathDefault is not null, all
-     * empty elements in the path, including empty elements at either end of
-     * the path, will be replaced with the value of emptyPathDefault.
+     * Split a path into its elements. If emptyPathDefault is not null, all empty elements in the
+     * path, including empty elements at either end of the path, will be replaced with the value of
+     * emptyPathDefault.
+     *
      * @param path The path to be split
-     * @param emptyPathDefault The value to substitute for empty path elements,
-     *  or null, to ignore empty path elements
+     * @param emptyPathDefault The value to substitute for empty path elements, or null, to ignore
+     * empty path elements
      * @return The elements of the path
      */
     private static Iterable<File> getPathEntries(String path, File emptyPathDefault) {
@@ -148,33 +156,38 @@
         int start = 0;
         while (start <= path.length()) {
             int sep = path.indexOf(File.pathSeparatorChar, start);
-            if (sep == -1)
+            if (sep == -1) {
                 sep = path.length();
-            if (start < sep)
+            }
+            if (start < sep) {
                 entries.add(new File(path.substring(start, sep)));
-            else if (emptyPathDefault != null)
+            } else if (emptyPathDefault != null) {
                 entries.add(emptyPathDefault);
+            }
             start = sep + 1;
         }
         return entries;
     }
 
     /**
-     * Utility class to help evaluate a path option.
-     * Duplicate entries are ignored, jar class paths can be expanded.
+     * Utility class to help evaluate a path option. Duplicate entries are ignored, jar class paths
+     * can be expanded.
      */
     private class Path extends LinkedHashSet<File> {
+
         private static final long serialVersionUID = 0;
 
         private boolean expandJarClassPaths = false;
-        private Set<File> canonicalValues = new HashSet<>();
+        private final Set<File> canonicalValues = new HashSet<>();
 
         public Path expandJarClassPaths(boolean x) {
             expandJarClassPaths = x;
             return this;
         }
 
-        /** What to use when path element is the empty string */
+        /**
+         * What to use when path element is the empty string
+         */
         private File emptyPathDefault = null;
 
         public Path emptyPathDefault(File x) {
@@ -182,15 +195,15 @@
             return this;
         }
 
-        public Path() { super(); }
-
         public Path addDirectories(String dirs, boolean warn) {
             boolean prev = expandJarClassPaths;
             expandJarClassPaths = true;
             try {
-                if (dirs != null)
-                    for (File dir : getPathEntries(dirs))
+                if (dirs != null) {
+                    for (File dir : getPathEntries(dirs)) {
                         addDirectory(dir, warn);
+                    }
+                }
                 return this;
             } finally {
                 expandJarClassPaths = prev;
@@ -203,19 +216,22 @@
 
         private void addDirectory(File dir, boolean warn) {
             if (!dir.isDirectory()) {
-                if (warn)
+                if (warn) {
                     log.warning(Lint.LintCategory.PATH,
                             "dir.path.element.not.found", dir);
+                }
                 return;
             }
 
             File[] files = dir.listFiles();
-            if (files == null)
+            if (files == null) {
                 return;
+            }
 
             for (File direntry : files) {
-                if (isArchive(direntry))
+                if (isArchive(direntry)) {
                     addFile(direntry, warn);
+                }
             }
         }
 
@@ -232,8 +248,9 @@
 
         public Path addFiles(Iterable<? extends File> files, boolean warn) {
             if (files != null) {
-                for (File file: files)
+                for (File file : files) {
                     addFile(file, warn);
+                }
             }
             return this;
         }
@@ -248,7 +265,7 @@
                 return;
             }
 
-            if (! fsInfo.exists(file)) {
+            if (!fsInfo.exists(file)) {
                 /* No such file or directory exists */
                 if (warn) {
                     log.warning(Lint.LintCategory.PATH,
@@ -288,12 +305,13 @@
             }
 
             /* Now what we have left is either a directory or a file name
-               conforming to archive naming convention */
+             conforming to archive naming convention */
             super.add(file);
             canonicalValues.add(canonFile);
 
-            if (expandJarClassPaths && fsInfo.isFile(file))
+            if (expandJarClassPaths && fsInfo.isFile(file)) {
                 addJarClassPath(file, warn);
+            }
         }
 
         // Adds referenced classpath elements from a jar's Class-Path
@@ -302,7 +320,7 @@
         // filenames, but if we do, we should redo all path-related code.
         private void addJarClassPath(File jarFile, boolean warn) {
             try {
-                for (File f: fsInfo.getJarClassPath(jarFile)) {
+                for (File f : fsInfo.getJarClassPath(jarFile)) {
                     addFile(f, warn);
                 }
             } catch (IOException e) {
@@ -312,53 +330,56 @@
     }
 
     /**
-     * Base class for handling support for the representation of Locations.
-     * Implementations are responsible for handling the interactions between
-     * the command line options for a location, and API access via setLocation.
+     * Base class for handling support for the representation of Locations. Implementations are
+     * responsible for handling the interactions between the command line options for a location,
+     * and API access via setLocation.
+     *
      * @see #initHandlers
      * @see #getHandler
      */
     protected abstract class LocationHandler {
+
         final Location location;
         final Set<Option> options;
 
         /**
-         * Create a handler. The location and options provide a way to map
-         * from a location or an option to the corresponding handler.
+         * Create a handler. The location and options provide a way to map from a location or an
+         * option to the corresponding handler.
+         *
+         * @param location the location for which this is the handler
+         * @param options the options affecting this location
          * @see #initHandlers
          */
         protected LocationHandler(Location location, Option... options) {
             this.location = location;
-            this.options = options.length == 0 ?
-                EnumSet.noneOf(Option.class):
-                EnumSet.copyOf(Arrays.asList(options));
+            this.options = options.length == 0
+                    ? EnumSet.noneOf(Option.class)
+                    : EnumSet.copyOf(Arrays.asList(options));
         }
 
-        // TODO: TEMPORARY, while Options still used for command line options
-        void update(Options optionTable) {
-            for (Option o: options) {
-                String v = optionTable.get(o);
-                if (v != null) {
-                    handleOption(o, v);
-                }
-            }
-        }
+        /**
+         * @see JavaFileManager#handleOption
+         */
+        abstract boolean handleOption(Option option, String value);
 
-        /** @see JavaFileManager#handleOption */
-        abstract boolean handleOption(Option option, String value);
-        /** @see StandardJavaFileManager#getLocation */
+        /**
+         * @see StandardJavaFileManager#getLocation
+         */
         abstract Collection<File> getLocation();
-        /** @see StandardJavaFileManager#setLocation */
+
+        /**
+         * @see StandardJavaFileManager#setLocation
+         */
         abstract void setLocation(Iterable<? extends File> files) throws IOException;
     }
 
     /**
-     * General purpose implementation for output locations,
-     * such as -d/CLASS_OUTPUT and -s/SOURCE_OUTPUT.
-     * All options are treated as equivalent (i.e. aliases.)
-     * The value is a single file, possibly null.
+     * General purpose implementation for output locations, such as -d/CLASS_OUTPUT and
+     * -s/SOURCE_OUTPUT. All options are treated as equivalent (i.e. aliases.) The value is a single
+     * file, possibly null.
      */
     private class OutputLocationHandler extends LocationHandler {
+
         private File outputDir;
 
         OutputLocationHandler(Location location, Option... options) {
@@ -367,14 +388,15 @@
 
         @Override
         boolean handleOption(Option option, String value) {
-            if (!options.contains(option))
+            if (!options.contains(option)) {
                 return false;
+            }
 
             // TODO: could/should validate outputDir exists and is a directory
             // need to decide how best to report issue for benefit of
             // direct API call on JavaFileManager.handleOption(specifies IAE)
             // vs. command line decoding.
-            outputDir = new File(value);
+            outputDir = (value == null) ? null : new File(value);
             return true;
         }
 
@@ -389,27 +411,30 @@
                 outputDir = null;
             } else {
                 Iterator<? extends File> pathIter = files.iterator();
-                if (!pathIter.hasNext())
+                if (!pathIter.hasNext()) {
                     throw new IllegalArgumentException("empty path for directory");
+                }
                 File dir = pathIter.next();
-                if (pathIter.hasNext())
+                if (pathIter.hasNext()) {
                     throw new IllegalArgumentException("path too long for directory");
-                if (!dir.exists())
+                }
+                if (!dir.exists()) {
                     throw new FileNotFoundException(dir + ": does not exist");
-                else if (!dir.isDirectory())
+                } else if (!dir.isDirectory()) {
                     throw new IOException(dir + ": not a directory");
+                }
                 outputDir = dir;
             }
         }
     }
 
     /**
-     * General purpose implementation for search path locations,
-     * such as -sourcepath/SOURCE_PATH and -processorPath/ANNOTATION_PROCESS_PATH.
-     * All options are treated as equivalent (i.e. aliases.)
+     * General purpose implementation for search path locations, such as -sourcepath/SOURCE_PATH and
+     * -processorPath/ANNOTATION_PROCESS_PATH. All options are treated as equivalent (i.e. aliases.)
      * The value is an ordered set of files and/or directories.
      */
     private class SimpleLocationHandler extends LocationHandler {
+
         protected Collection<File> searchPath;
 
         SimpleLocationHandler(Location location, Option... options) {
@@ -418,10 +443,11 @@
 
         @Override
         boolean handleOption(Option option, String value) {
-            if (!options.contains(option))
+            if (!options.contains(option)) {
                 return false;
-            searchPath = value == null ? null :
-                    Collections.unmodifiableCollection(createPath().addFiles(value));
+            }
+            searchPath = value == null ? null
+                    : Collections.unmodifiableCollection(createPath().addFiles(value));
             return true;
         }
 
@@ -451,11 +477,11 @@
     }
 
     /**
-     * Subtype of SimpleLocationHandler for -classpath/CLASS_PATH.
-     * If no value is given, a default is provided, based on system properties
-     * and other values.
+     * Subtype of SimpleLocationHandler for -classpath/CLASS_PATH. If no value is given, a default
+     * is provided, based on system properties and other values.
      */
     private class ClassPathLocationHandler extends SimpleLocationHandler {
+
         ClassPathLocationHandler() {
             super(StandardLocation.CLASS_PATH,
                     Option.CLASSPATH, Option.CP);
@@ -472,15 +498,20 @@
             String cp = value;
 
             // CLASSPATH environment variable when run from `javac'.
-            if (cp == null) cp = System.getProperty("env.class.path");
+            if (cp == null) {
+                cp = System.getProperty("env.class.path");
+            }
 
             // If invoked via a java VM (not the javac launcher), use the
             // platform class path
-            if (cp == null && System.getProperty("application.home") == null)
+            if (cp == null && System.getProperty("application.home") == null) {
                 cp = System.getProperty("java.class.path");
+            }
 
             // Default to current working directory.
-            if (cp == null) cp = ".";
+            if (cp == null) {
+                cp = ".";
+            }
 
             return createPath().addFiles(cp);
         }
@@ -488,38 +519,37 @@
         @Override
         protected Path createPath() {
             return new Path()
-                .expandJarClassPaths(true)         // Only search user jars for Class-Paths
-                .emptyPathDefault(new File("."));  // Empty path elt ==> current directory
+                    .expandJarClassPaths(true) // Only search user jars for Class-Paths
+                    .emptyPathDefault(new File("."));  // Empty path elt ==> current directory
         }
 
         private void lazy() {
-            if (searchPath == null)
+            if (searchPath == null) {
                 setLocation(null);
+            }
         }
     }
 
     /**
-     * Custom subtype of LocationHandler for PLATFORM_CLASS_PATH.
-     * Various options are supported for different components of the
-     * platform class path.
-     * Setting a value with setLocation overrides all existing option values.
-     * Setting any option overrides any value set with setLocation, and reverts
-     * to using default values for options that have not been set.
-     * Setting -bootclasspath or -Xbootclasspath overrides any existing
-     * value for -Xbootclasspath/p: and -Xbootclasspath/a:.
+     * Custom subtype of LocationHandler for PLATFORM_CLASS_PATH. Various options are supported for
+     * different components of the platform class path. Setting a value with setLocation overrides
+     * all existing option values. Setting any option overrides any value set with setLocation, and
+     * reverts to using default values for options that have not been set. Setting -bootclasspath or
+     * -Xbootclasspath overrides any existing value for -Xbootclasspath/p: and -Xbootclasspath/a:.
      */
     private class BootClassPathLocationHandler extends LocationHandler {
+
         private Collection<File> searchPath;
         final Map<Option, String> optionValues = new EnumMap<>(Option.class);
 
         /**
-         * rt.jar as found on the default bootclasspath.
-         * If the user specified a bootclasspath, null is used.
+         * rt.jar as found on the default bootclasspath. If the user specified a bootclasspath, null
+         * is used.
          */
         private File defaultBootClassPathRtJar = null;
 
         /**
-         *  Is bootclasspath the default?
+         * Is bootclasspath the default?
          */
         private boolean isDefaultBootClassPath;
 
@@ -544,8 +574,9 @@
 
         @Override
         boolean handleOption(Option option, String value) {
-            if (!options.contains(option))
+            if (!options.contains(option)) {
                 return false;
+            }
 
             option = canonicalize(option);
             optionValues.put(option, value);
@@ -557,20 +588,20 @@
             return true;
         }
         // where
-            // TODO: would be better if option aliasing was handled at a higher
-            // level
-            private Option canonicalize(Option option) {
-                switch (option) {
-                    case XBOOTCLASSPATH:
-                        return Option.BOOTCLASSPATH;
-                    case DJAVA_ENDORSED_DIRS:
-                        return Option.ENDORSEDDIRS;
-                    case DJAVA_EXT_DIRS:
-                        return Option.EXTDIRS;
-                    default:
-                        return option;
-                }
+        // TODO: would be better if option aliasing was handled at a higher
+        // level
+        private Option canonicalize(Option option) {
+            switch (option) {
+                case XBOOTCLASSPATH:
+                    return Option.BOOTCLASSPATH;
+                case DJAVA_ENDORSED_DIRS:
+                    return Option.ENDORSEDDIRS;
+                case DJAVA_EXT_DIRS:
+                    return Option.EXTDIRS;
+                default:
+                    return option;
             }
+        }
 
         @Override
         Collection<File> getLocation() {
@@ -602,10 +633,11 @@
             String xbootclasspathAppendOpt = optionValues.get(XBOOTCLASSPATH_APPEND);
             path.addFiles(xbootclasspathPrependOpt);
 
-            if (endorseddirsOpt != null)
+            if (endorseddirsOpt != null) {
                 path.addDirectories(endorseddirsOpt);
-            else
+            } else {
                 path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
+            }
 
             if (bootclasspathOpt != null) {
                 path.addFiles(bootclasspathOpt);
@@ -615,8 +647,9 @@
                 path.addFiles(files, false);
                 File rt_jar = new File("rt.jar");
                 for (File file : getPathEntries(files)) {
-                    if (new File(file.getName()).equals(rt_jar))
+                    if (new File(file.getName()).equals(rt_jar)) {
                         defaultBootClassPathRtJar = file;
+                    }
                 }
             }
 
@@ -625,22 +658,24 @@
             // Strictly speaking, standard extensions are not bootstrap
             // classes, but we treat them identically, so we'll pretend
             // that they are.
-            if (extdirsOpt != null)
+            if (extdirsOpt != null) {
                 path.addDirectories(extdirsOpt);
-            else
+            } else {
                 path.addDirectories(System.getProperty("java.ext.dirs"), false);
+            }
 
-            isDefaultBootClassPath =
-                    (xbootclasspathPrependOpt == null) &&
-                    (bootclasspathOpt == null) &&
-                    (xbootclasspathAppendOpt == null);
+            isDefaultBootClassPath
+                    = (xbootclasspathPrependOpt == null)
+                    && (bootclasspathOpt == null)
+                    && (xbootclasspathAppendOpt == null);
 
             return path;
         }
 
         private void lazy() {
-            if (searchPath == null)
+            if (searchPath == null) {
                 searchPath = Collections.unmodifiableCollection(computePath());
+            }
         }
     }
 
@@ -661,14 +696,15 @@
             new OutputLocationHandler((StandardLocation.NATIVE_HEADER_OUTPUT), Option.H)
         };
 
-        for (LocationHandler h: handlers) {
+        for (LocationHandler h : handlers) {
             handlersForLocation.put(h.location, h);
-            for (Option o: h.options)
+            for (Option o : h.options) {
                 handlersForOption.put(o, h);
+            }
         }
     }
 
-    boolean handleOption(Option option, String value) {
+    public boolean handleOption(Option option, String value) {
         LocationHandler h = handlersForOption.get(option);
         return (h == null ? false : h.handleOption(option, value));
     }
@@ -679,8 +715,9 @@
     }
 
     File getOutputLocation(Location location) {
-        if (!location.isOutputLocation())
+        if (!location.isOutputLocation()) {
             throw new IllegalArgumentException();
+        }
         LocationHandler h = getHandler(location);
         return ((OutputLocationHandler) h).outputDir;
     }
@@ -688,10 +725,11 @@
     void setLocation(Location location, Iterable<? extends File> files) throws IOException {
         LocationHandler h = getHandler(location);
         if (h == null) {
-            if (location.isOutputLocation())
+            if (location.isOutputLocation()) {
                 h = new OutputLocationHandler(location);
-            else
+            } else {
                 h = new SimpleLocationHandler(location);
+            }
             handlersForLocation.put(location, h);
         }
         h.setLocation(files);
@@ -699,33 +737,21 @@
 
     protected LocationHandler getHandler(Location location) {
         location.getClass(); // null check
-        lazy();
         return handlersForLocation.get(location);
     }
 
-// TOGO
-    protected void lazy() {
-        if (!inited) {
-            warn = lint.isEnabled(Lint.LintCategory.PATH);
-
-            for (LocationHandler h: handlersForLocation.values()) {
-                h.update(options);
-            }
-
-            inited = true;
-        }
-    }
-
-    /** Is this the name of an archive file? */
+    /**
+     * Is this the name of an archive file?
+     */
     private boolean isArchive(File file) {
         String n = StringUtils.toLowerCase(file.getName());
         return fsInfo.isFile(file)
-            && (n.endsWith(".jar") || n.endsWith(".zip"));
+                && (n.endsWith(".jar") || n.endsWith(".zip"));
     }
 
     /**
-     * Utility method for converting a search path string to an array
-     * of directory and JAR file URLs.
+     * Utility method for converting a search path string to an array of directory and JAR file
+     * URLs.
      *
      * Note that this method is called by apt and the DocletInvoker.
      *
@@ -747,8 +773,7 @@
     }
 
     /**
-     * Returns the directory or JAR file URL corresponding to the specified
-     * local file name.
+     * Returns the directory or JAR file URL corresponding to the specified local file name.
      *
      * @param file the File object
      * @return the resulting directory or JAR file URL, or null if unknown
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Sun Jun 08 15:02:34 2014 -0700
@@ -394,6 +394,7 @@
         processPcks   = options.isSet("process.packages");
         werror        = options.isSet(WERROR);
 
+        // Should this be with other option checking, in Main
         if (source.compareTo(Source.DEFAULT) < 0) {
             if (options.isUnset(XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option)) {
                 if (fileManager instanceof BaseFileManager) {
@@ -403,6 +404,7 @@
             }
         }
 
+        // Should this be with other option checking, in Main
         checkForObsoleteOptions(target);
 
         verboseCompilePolicy = options.isSet("verboseCompilePolicy");
@@ -434,6 +436,7 @@
             log.setDiagnosticFormatter(RichDiagnosticFormatter.instance(context));
     }
 
+    // Should this be with other option checking, in Main
     private void checkForObsoleteOptions(Target target) {
         // Unless lint checking on options is disabled, check for
         // obsolete source and target options.
--- a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java	Sun Jun 08 15:02:34 2014 -0700
@@ -33,8 +33,9 @@
 import java.security.MessageDigest;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
+import java.util.Map;
 import java.util.Set;
 
 import javax.annotation.processing.Processor;
@@ -56,6 +57,7 @@
 import com.sun.tools.javac.util.Log.PrefixKind;
 import com.sun.tools.javac.util.Log.WriterKind;
 import com.sun.tools.javac.util.ServiceLoader;
+
 import static com.sun.tools.javac.main.Option.*;
 
 /** This class provides a command line interface to the javac compiler.
@@ -121,6 +123,13 @@
         }
 
         @Override
+        public boolean handleFileManagerOption(Option option, String value) {
+            options.put(option.getText(), value);
+            deferredFileManagerOptions.put(option, value);
+            return true;
+        }
+
+        @Override
         public void remove(String name) {
             options.remove(name);
         }
@@ -172,11 +181,13 @@
 
     /** The list of source files to process
      */
-    public Set<File> filenames = null; // XXX sb protected
+    public Set<File> filenames = null; // XXX should be protected or private
 
     /** List of class files names passed on the command line
      */
-    public ListBuffer<String> classnames = null; // XXX sb protected
+    protected ListBuffer<String> classnames = null;
+
+    public Map<Option, String> deferredFileManagerOptions; // XXX should be protected or private
 
     /** Report a usage error.
      */
@@ -395,6 +406,7 @@
 
         filenames = new LinkedHashSet<>();
         classnames = new ListBuffer<>();
+        deferredFileManagerOptions = new LinkedHashMap<>();
         JavaCompiler comp = null;
         /*
          * TODO: Logic below about what is an acceptable command line
@@ -446,6 +458,11 @@
             if (batchMode)
                 CacheFSInfo.preRegister(context);
 
+            fileManager = context.get(JavaFileManager.class);
+            if (fileManager instanceof BaseFileManager) {
+                ((BaseFileManager) fileManager).handleOptions(deferredFileManagerOptions);
+            }
+
             // FIXME: this code will not be invoked if using JavacTask.parse/analyze/generate
             // invoke any available plugins
             String plugins = options.get(PLUGIN);
@@ -511,8 +528,6 @@
                 comp.closeables = comp.closeables.prepend(log.getWriter(WriterKind.NOTICE));
             }
 
-            fileManager = context.get(JavaFileManager.class);
-
             if (!files.isEmpty()) {
                 // add filenames to fileObjects
                 comp = JavaCompiler.instance(context);
--- a/langtools/src/share/classes/com/sun/tools/javac/main/Option.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/Option.java	Sun Jun 08 15:02:34 2014 -0700
@@ -83,6 +83,7 @@
 
     XLINT_CUSTOM("-Xlint:", EXTENDED, BASIC, ANYOF, getXLintChoices()) {
         private static final String LINT_KEY_FORMAT = "         %-19s %s";
+        @Override
         void help(Log log, OptionKind kind) {
             if (this.kind != kind)
                 return;
@@ -667,6 +668,8 @@
             }
         }
         helper.put(option, arg);
+        if (group == OptionGroup.FILEMANAGER)
+            helper.handleFileManagerOption(this, arg);
         return false;
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/main/OptionHelper.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/OptionHelper.java	Sun Jun 08 15:02:34 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,6 +50,9 @@
     /** Remove any prior value for an option. */
     public abstract void remove(String name);
 
+    /** Handle a file manager option. */
+    public abstract boolean handleFileManagerOption(Option option, String value);
+
     /** Get access to the Log for the compilation. */
     public abstract Log getLog();
 
@@ -99,6 +102,11 @@
         }
 
         @Override
+        public boolean handleFileManagerOption(Option option, String value) {
+            throw new IllegalArgumentException();
+        }
+
+        @Override
         void error(String key, Object... args) {
             throw new IllegalArgumentException(log.localize(PrefixKind.JAVAC, key, args));
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java	Sun Jun 08 15:02:34 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -167,11 +167,6 @@
         return getClassLoader(lb.toArray(new URL[lb.size()]));
     }
 
-    @Override
-    public boolean isDefaultBootClassPath() {
-        return locations.isDefaultBootClassPath();
-    }
-
     // <editor-fold defaultstate="collapsed" desc="Location handling">
 
     public boolean hasLocation(Location location) {
--- a/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java	Sun Jun 08 15:02:34 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
 package com.sun.tools.javac.util;
 
 import java.io.ByteArrayOutputStream;
-import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStreamWriter;
@@ -47,6 +46,8 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
+
+import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 import javax.tools.JavaFileObject.Kind;
 
@@ -64,7 +65,7 @@
  * There are no references here to file-system specific objects such as
  * java.io.File or java.nio.file.Path.
  */
-public abstract class BaseFileManager {
+public abstract class BaseFileManager implements JavaFileManager {
     protected BaseFileManager(Charset charset) {
         this.charset = charset;
         byteBufferCache = new ByteBufferCache();
@@ -73,12 +74,13 @@
 
     /**
      * Set the context for JavacPathFileManager.
+     * @param context the context containing items to be associated with the file manager
      */
     public void setContext(Context context) {
         log = Log.instance(context);
         options = Options.instance(context);
         classLoaderClass = options.get("procloader");
-        locations.update(log, options, Lint.instance(context), FSInfo.instance(context));
+        locations.update(log, Lint.instance(context), FSInfo.instance(context));
     }
 
     protected Locations createLocations() {
@@ -123,14 +125,19 @@
                 Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
                 Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
                 return constr.newInstance(urls, thisClassLoader);
-            } catch (Throwable t) {
+            } catch (ReflectiveOperationException t) {
                 // ignore errors loading user-provided class loader, fall through
             }
         }
         return new URLClassLoader(urls, thisClassLoader);
     }
 
+    public boolean isDefaultBootClassPath() {
+        return locations.isDefaultBootClassPath();
+    }
+
     // <editor-fold defaultstate="collapsed" desc="Option handling">
+    @Override
     public boolean handleOption(String current, Iterator<String> remaining) {
         OptionHelper helper = new GrumpyHelper(log) {
             @Override
@@ -147,7 +154,13 @@
             public void remove(String name) {
                 options.remove(name);
             }
+
+            @Override
+            public boolean handleFileManagerOption(Option option, String value) {
+                return handleOption(option, value);
+            }
         };
+
         for (Option o: javacFileManagerOptions) {
             if (o.matches(current))  {
                 if (o.hasArg()) {
@@ -159,7 +172,7 @@
                     if (!o.process(helper, current))
                         return true;
                 }
-                // operand missing, or process returned false
+                // operand missing, or process returned true
                 throw new IllegalArgumentException(current);
             }
         }
@@ -170,6 +183,7 @@
         private static final Set<Option> javacFileManagerOptions =
             Option.getJavacFileManagerOptions();
 
+    @Override
     public int isSupportedOption(String option) {
         for (Option o : javacFileManagerOptions) {
             if (o.matches(option))
@@ -178,7 +192,27 @@
         return -1;
     }
 
-    public abstract boolean isDefaultBootClassPath();
+    /**
+     * Common back end for OptionHelper handleFileManagerOption.
+     * @param option the option whose value to be set
+     * @param value the value for the option
+     * @return true if successful, and false otherwise
+     */
+    public boolean handleOption(Option option, String value) {
+        return locations.handleOption(option, value);
+    }
+
+    /**
+     * Call handleOption for collection of options and corresponding values.
+     * @param map a collection of options and corresponding values
+     * @return true if all the calls are successful
+     */
+    public boolean handleOptions(Map<Option, String> map) {
+        boolean ok = true;
+        for (Map.Entry<Option, String> e: map.entrySet())
+            ok = ok & handleOption(e.getKey(), e.getValue());
+        return ok;
+    }
 
     // </editor-fold>
 
@@ -205,10 +239,7 @@
         CharsetDecoder decoder;
         try {
             decoder = getDecoder(encodingName, ignoreEncodingErrors);
-        } catch (IllegalCharsetNameException e) {
-            log.error("unsupported.encoding", encodingName);
-            return (CharBuffer)CharBuffer.allocate(1).flip();
-        } catch (UnsupportedCharsetException e) {
+        } catch (IllegalCharsetNameException | UnsupportedCharsetException e) {
             log.error("unsupported.encoding", encodingName);
             return (CharBuffer)CharBuffer.allocate(1).flip();
         }
@@ -286,6 +317,9 @@
     // <editor-fold defaultstate="collapsed" desc="ByteBuffers">
     /**
      * Make a byte buffer from an input stream.
+     * @param in the stream
+     * @return a byte buffer containing the contents of the stream
+     * @throws IOException if an error occurred while reading the stream
      */
     public ByteBuffer makeByteBuffer(InputStream in)
         throws IOException {
--- a/langtools/src/share/classes/com/sun/tools/javadoc/Start.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/Start.java	Sun Jun 08 15:02:34 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,18 +32,23 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Map;
 
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 
 import com.sun.javadoc.*;
+import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.main.CommandLine;
+import com.sun.tools.javac.main.Option;
+import com.sun.tools.javac.util.BaseFileManager;
 import com.sun.tools.javac.util.ClientCodeException;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.Options;
+
 import static com.sun.tools.javac.code.Flags.*;
 
 /**
@@ -71,7 +76,7 @@
     private static final String standardDocletClassName =
         "com.sun.tools.doclets.standard.Standard";
 
-    private long defaultFilter = PUBLIC | PROTECTED;
+    private final long defaultFilter = PUBLIC | PROTECTED;
 
     private final Messager messager;
 
@@ -324,6 +329,15 @@
                 javaNames.append(arg);
             }
         }
+
+        if (fileManager == null) {
+            JavacFileManager.preRegister(context);
+            fileManager = context.get(JavaFileManager.class);
+        }
+        if (fileManager instanceof BaseFileManager) {
+            ((BaseFileManager) fileManager).handleOptions(fileManagerOpts);
+        }
+
         compOpts.notifyListeners();
 
         if (javaNames.isEmpty() && subPackages.isEmpty() && isEmpty(fileObjects)) {
--- a/langtools/src/share/classes/com/sun/tools/javadoc/ToolOption.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/ToolOption.java	Sun Jun 08 15:02:34 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,14 @@
 
 package com.sun.tools.javadoc;
 
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
 import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.main.Option;
 import com.sun.tools.javac.util.ListBuffer;
 import com.sun.tools.javac.util.Options;
-import java.util.StringTokenizer;
 
 
 /**
@@ -45,42 +49,42 @@
     BOOTCLASSPATH("-bootclasspath", true) {
         @Override
         public void process(Helper helper, String arg) {
-            helper.setCompilerOpt(opt, arg);
+            helper.setFileManagerOpt(Option.BOOTCLASSPATH, arg);
         }
     },
 
     CLASSPATH("-classpath", true) {
         @Override
         public void process(Helper helper, String arg) {
-            helper.setCompilerOpt(opt, arg);
+            helper.setFileManagerOpt(Option.CLASSPATH, arg);
         }
     },
 
     CP("-cp", true) {
         @Override
         public void process(Helper helper, String arg) {
-            helper.setCompilerOpt(opt, arg);
+            helper.setFileManagerOpt(Option.CP, arg);
         }
     },
 
     EXTDIRS("-extdirs", true) {
         @Override
         public void process(Helper helper, String arg) {
-            helper.setCompilerOpt(opt, arg);
+            helper.setFileManagerOpt(Option.EXTDIRS, arg);
         }
     },
 
     SOURCEPATH("-sourcepath", true) {
         @Override
         public void process(Helper helper, String arg) {
-            helper.setCompilerOpt(opt, arg);
+            helper.setFileManagerOpt(Option.SOURCEPATH, arg);
         }
     },
 
     SYSCLASSPATH("-sysclasspath", true) {
         @Override
         public void process(Helper helper, String arg) {
-            helper.setCompilerOpt("-bootclasspath", arg);
+            helper.setFileManagerOpt(Option.BOOTCLASSPATH, arg);
         }
     },
 
@@ -274,6 +278,9 @@
         /** Excluded packages, from -exclude. */
         final ListBuffer<String> excludedPackages = new ListBuffer<>();
 
+        // File manager options
+        final Map<Option, String> fileManagerOpts = new LinkedHashMap<>();
+
         /** javac options, set by various options. */
         Options compOpts; // = Options.instance(context)
 
@@ -306,7 +313,7 @@
 
         abstract void usageError(String msg, Object... args);
 
-        protected void addToList(ListBuffer<String> list, String str){
+        void addToList(ListBuffer<String> list, String str){
             StringTokenizer st = new StringTokenizer(str, ":");
             String current;
             while(st.hasMoreTokens()){
@@ -315,18 +322,22 @@
             }
         }
 
-        protected void setFilter(long filterBits) {
+        void setFilter(long filterBits) {
             if (showAccess != null) {
                 usageError("main.incompatible.access.flags");
             }
             showAccess = new ModifierFilter(filterBits);
         }
 
-        private void setCompilerOpt(String opt, String arg) {
+        void setCompilerOpt(String opt, String arg) {
             if (compOpts.get(opt) != null) {
                 usageError("main.option.already.seen", opt);
             }
             compOpts.put(opt, arg);
         }
+
+        void setFileManagerOpt(Option opt, String arg) {
+            fileManagerOpts.put(opt, arg);
+        }
     }
 }
--- a/langtools/test/tools/javac/T6358166.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/test/tools/javac/T6358166.java	Sun Jun 08 15:02:34 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,12 +57,8 @@
 
     static void test(JavacFileManager fm, JavaFileObject f, String... args) throws Throwable {
         Context context = new Context();
-        fm.setContext(context);
 
-        Main compilerMain = new Main("javac", new PrintWriter(System.err, true));
-        compilerMain.setOptions(Options.instance(context));
-        compilerMain.filenames = new LinkedHashSet<File>();
-        compilerMain.processArgs(args);
+        Main compilerMain = initCompilerMain(context, fm, args);
 
         JavaCompiler c = JavaCompiler.instance(context);
 
@@ -76,6 +72,19 @@
             throw new AssertionError("elapsed time is suspect: " + msec);
     }
 
+    static Main initCompilerMain(Context context, JavacFileManager fm, String... args) {
+        fm.setContext(context);
+        context.put(JavaFileManager.class, fm);
+
+        Main compilerMain = new Main("javac", new PrintWriter(System.err, true));
+        compilerMain.setOptions(Options.instance(context));
+        compilerMain.filenames = new LinkedHashSet<File>();
+        compilerMain.deferredFileManagerOptions = new LinkedHashMap<>();
+        compilerMain.processArgs(args);
+        fm.handleOptions(compilerMain.deferredFileManagerOptions);
+        return compilerMain;
+    }
+
     public boolean process(Set<? extends TypeElement> tes, RoundEnvironment renv) {
         return true;
     }
--- a/langtools/test/tools/javac/T6358168.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/test/tools/javac/T6358168.java	Sun Jun 08 15:02:34 2014 -0700
@@ -68,12 +68,9 @@
 
     static void testNoAnnotationProcessing(JavacFileManager fm, JavaFileObject f) throws Throwable {
         Context context = new Context();
-        fm.setContext(context);
 
-        Main compilerMain = new Main("javac", new PrintWriter(System.err, true));
-        compilerMain.setOptions(Options.instance(context));
-        compilerMain.filenames = new LinkedHashSet<File>();
-        compilerMain.processArgs(new String[] { "-d", "." });
+        String[] args = { "-d", "." };
+        Main compilerMain = initCompilerMain(context, fm, args);
 
         JavaCompiler compiler = JavaCompiler.instance(context);
         compiler.compile(List.of(f));
@@ -87,16 +84,14 @@
 
     static void testAnnotationProcessing(JavacFileManager fm, JavaFileObject f) throws Throwable {
         Context context = new Context();
-        fm.setContext(context);
 
-        Main compilerMain = new Main("javac", new PrintWriter(System.err, true));
-        compilerMain.setOptions(Options.instance(context));
-        compilerMain.filenames = new LinkedHashSet<File>();
-        compilerMain.processArgs(new String[] {
-                                     "-XprintRounds",
-                                     "-processorpath", testClasses,
-                                     "-processor", self,
-                                     "-d", "."});
+        String[] args = {
+                "-XprintRounds",
+                "-processorpath", testClasses,
+                "-processor", self,
+                "-d", "."
+        };
+        Main compilerMain = initCompilerMain(context, fm, args);
 
         JavaCompiler compiler = JavaCompiler.instance(context);
         compiler.compile(List.of(f));
@@ -108,6 +103,19 @@
         }
     }
 
+    static Main initCompilerMain(Context context, JavacFileManager fm, String... args) {
+        fm.setContext(context);
+        context.put(JavaFileManager.class, fm);
+
+        Main compilerMain = new Main("javac", new PrintWriter(System.err, true));
+        compilerMain.setOptions(Options.instance(context));
+        compilerMain.filenames = new LinkedHashSet<File>();
+        compilerMain.deferredFileManagerOptions = new LinkedHashMap<>();
+        compilerMain.processArgs(args);
+        fm.handleOptions(compilerMain.deferredFileManagerOptions);
+        return compilerMain;
+    }
+
     public boolean process(Set<? extends TypeElement> tes, RoundEnvironment renv) {
         return true;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/api/TestSearchPaths.java	Sun Jun 08 15:02:34 2014 -0700
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7026941
+ * @summary path options ignored when reusing filemanager across tasks
+ */
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URI;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.tools.JavaCompiler;
+import javax.tools.JavaCompiler.CompilationTask;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+import static javax.tools.StandardLocation.*;
+
+/**
+ * Test for combinations of using javac command-line options and fileManager setLocation
+ * calls to affect the locations available in the fileManager.
+ *
+ * Using a single Java compiler and file manager, for each of the standard locations,
+ * a series of operations is performed, using either compiler options or setLocation
+ * calls. Each operation includes a compilation, and then a check for the value of
+ * the standard location available in the file manager.
+ *
+ * The operations generate and use unique files to minimize the possibility of false
+ * positive results.
+ */
+public class TestSearchPaths {
+
+    public static void main(String... args) throws Exception {
+        TestSearchPaths t = new TestSearchPaths();
+        t.run();
+    }
+
+    void run() throws Exception {
+        compiler = ToolProvider.getSystemJavaCompiler();
+        fileManager = compiler.getStandardFileManager(null, null, null);
+
+        // basic output path
+        testClassOutput();
+
+        // basic search paths
+        testClassPath();
+        testSourcePath();
+        testPlatformClassPath();
+
+        // annotation processing
+        testAnnotationProcessorPath();
+        testSourceOutput();
+
+        // javah equivalent
+        testNativeHeaderOutput();
+
+        // future-proof: guard against new StandardLocations being added
+        if (!tested.equals(EnumSet.allOf(StandardLocation.class))) {
+            error("not all standard locations have been tested");
+            out.println("not yet tested: " + EnumSet.complementOf(tested));
+        }
+
+        if (errors > 0) {
+            throw new Exception(errors + " errors occurred");
+        }
+    }
+
+    void testClassOutput() throws IOException {
+        String test = "testClassOutput";
+
+        for (int i = 1; i <= 5; i++) {
+            File classes = createDir(test + "/" + i + "/classes");
+            List<String> options;
+            switch (i) {
+                default:
+                    options = getOptions("-d", classes.getPath());
+                    break;
+
+                case 3:
+                    setLocation(CLASS_OUTPUT, classes);
+                    options = null;
+                    break;
+            }
+            List<JavaFileObject> sources = getSources("class C" + i + " { }");
+            callTask(options, sources);
+            checkPath(CLASS_OUTPUT, Mode.EQUALS, classes);
+            checkFile(CLASS_OUTPUT, "C" + i + ".class");
+        }
+
+        tested.add(CLASS_OUTPUT);
+    }
+
+    void testClassPath() throws IOException {
+        String test = "testClassPath";
+
+        for (int i = 1; i <= 5; i++) {
+            File classes = createDir(test + "/" + i + "/classes");
+            File classpath = new File("testClassOutput/" + i + "/classes");
+            List<String> options;
+            switch (i) {
+                default:
+                    options = getOptions("-d", classes.getPath(), "-classpath", classpath.getPath());
+                    break;
+
+                case 3:
+                    setLocation(CLASS_PATH, classpath);
+                    options = getOptions("-d", classes.getPath());
+                    break;
+
+                case 4:
+                    options = getOptions("-d", classes.getPath(), "-cp", classpath.getPath());
+                    break;
+            }
+            List<JavaFileObject> sources = getSources("class D" + i + " { C" + i + " c; }");
+            callTask(options, sources);
+            checkPath(CLASS_PATH, Mode.EQUALS, classpath);
+            checkFile(CLASS_OUTPUT, "D" + i + ".class");
+        }
+
+        tested.add(CLASS_PATH);
+    }
+
+    void testSourcePath() throws IOException {
+        String test = "testSourcePath";
+        setLocation(CLASS_PATH); // empty
+
+        for (int i = 1; i <= 5; i++) {
+            File src = createDir(test + "/" + i + "/src");
+            writeFile(src, "C" + i + ".java", "class C" + i + "{ }");
+            File classes = createDir(test + "/" + i + "/classes");
+            File srcpath = src;
+            List<String> options;
+            switch (i) {
+                default:
+                    options = getOptions("-d", classes.getPath(), "-sourcepath", srcpath.getPath());
+                    break;
+
+                case 3:
+                    setLocation(SOURCE_PATH, srcpath);
+                    options = getOptions("-d", classes.getPath());
+                    break;
+            }
+            List<JavaFileObject> sources = getSources("class D" + i + " { C" + i + " c; }");
+            callTask(options, sources);
+            checkPath(SOURCE_PATH, Mode.EQUALS, srcpath);
+            checkFile(CLASS_OUTPUT, "D" + i + ".class");
+        }
+
+        tested.add(SOURCE_PATH);
+    }
+
+    void testPlatformClassPath() throws IOException {
+        String test = "testPlatformClassPath";
+
+        List<File> defaultPath = getLocation(PLATFORM_CLASS_PATH);
+        StringBuilder sb = new StringBuilder();
+        for (File f: defaultPath) {
+            if (sb.length() > 0)
+                sb.append(File.pathSeparator);
+            sb.append(f);
+        }
+        String defaultPathString = sb.toString();
+
+        setLocation(CLASS_PATH); // empty
+        setLocation(SOURCE_PATH); // empty
+
+        for (int i = 1; i <= 10; i++) {
+            File classes = createDir(test + "/" + i + "/classes");
+            File testJars = createDir(test + "/" + i + "/testJars");
+            File testClasses = createDir(test + "/" + i + "/testClasses");
+            callTask(getOptions("-d", testClasses.getPath()), getSources("class C" + i + " { }"));
+
+            List<String> options;
+            Mode mode;
+            List<File> match;
+            String reference = "C" + i + " c;";
+
+            File jar;
+
+            switch (i) {
+                case 1:
+                    options = getOptions("-d", classes.getPath(), "-Xbootclasspath/p:" + testClasses);
+                    mode = Mode.STARTS_WITH;
+                    match = Arrays.asList(testClasses);
+                    break;
+
+                case 2:
+                    // the default values for -extdirs and -endorseddirs come after the bootclasspath;
+                    // so to check -Xbootclasspath/a: we specify empty values for those options.
+                    options = getOptions("-d", classes.getPath(),
+                            "-Xbootclasspath/a:" + testClasses,
+                            "-extdirs", "",
+                            "-endorseddirs", "");
+                    mode = Mode.ENDS_WITH;
+                    match = Arrays.asList(testClasses);
+                    break;
+
+                case 3:
+                    options = getOptions("-d", classes.getPath(), "-Xbootclasspath:" + defaultPathString);
+                    mode = Mode.EQUALS;
+                    match = defaultPath;
+                    reference = "";
+                    break;
+
+                case 4:
+                    fileManager.setLocation(PLATFORM_CLASS_PATH, null);
+                    jar = new File(testJars, "j" + i + ".jar");
+                    writeJar(jar, testClasses, "C" + i + ".class");
+                    options = getOptions("-d", classes.getPath(), "-endorseddirs", testJars.getPath());
+                    mode = Mode.CONTAINS;
+                    match = Arrays.asList(jar);
+                    break;
+
+                case 5:
+                    fileManager.setLocation(PLATFORM_CLASS_PATH, null);
+                    jar = new File(testJars, "j" + i + ".jar");
+                    writeJar(jar, testClasses, "C" + i + ".class");
+                    options = getOptions("-d", classes.getPath(), "-Djava.endorsed.dirs=" + testJars.getPath());
+                    mode = Mode.CONTAINS;
+                    match = Arrays.asList(jar);
+                    break;
+
+                case 6:
+                    fileManager.setLocation(PLATFORM_CLASS_PATH, null);
+                    jar = new File(testJars, "j" + i + ".jar");
+                    writeJar(jar, testClasses, "C" + i + ".class");
+                    options = getOptions("-d", classes.getPath(), "-extdirs", testJars.getPath());
+                    mode = Mode.CONTAINS;
+                    match = Arrays.asList(jar);
+                    break;
+
+                case 7:
+                    fileManager.setLocation(PLATFORM_CLASS_PATH, null);
+                    jar = new File(testJars, "j" + i + ".jar");
+                    writeJar(jar, testClasses, "C" + i + ".class");
+                    options = getOptions("-d", classes.getPath(), "-Djava.ext.dirs=" + testJars.getPath());
+                    mode = Mode.CONTAINS;
+                    match = Arrays.asList(jar);
+                    break;
+
+                case 8:
+                    setLocation(PLATFORM_CLASS_PATH, defaultPath);
+                    options = getOptions("-d", classes.getPath());
+                    mode = Mode.EQUALS;
+                    match = defaultPath;
+                    reference = "";
+                    break;
+
+                default:
+                    options = getOptions("-d", classes.getPath(), "-bootclasspath", defaultPathString);
+                    mode = Mode.EQUALS;
+                    match = defaultPath;
+                    reference = "";
+                    break;
+            }
+            List<JavaFileObject> sources = getSources("class D" + i + " { " + reference + " }");
+
+            callTask(options, sources);
+            checkPath(PLATFORM_CLASS_PATH, mode, match);
+            checkFile(CLASS_OUTPUT, "D" + i + ".class");
+        }
+
+        tested.add(PLATFORM_CLASS_PATH);
+    }
+
+    void testAnnotationProcessorPath() throws IOException {
+        String test = "testAnnotationProcessorPath";
+
+        String template =
+                "import java.util.*;\n"
+                + "import javax.annotation.processing.*;\n"
+                + "import javax.lang.model.*;\n"
+                + "import javax.lang.model.element.*;\n"
+                + "@SupportedAnnotationTypes(\"*\")\n"
+                + "public class A%d extends AbstractProcessor {\n"
+                + "    public boolean process(Set<? extends TypeElement> annos, RoundEnvironment rEnv) {\n"
+                + "        return true;\n"
+                + "    }\n"
+                + "    public SourceVersion getSupportedSourceVersion() {\n"
+                + "        return SourceVersion.latest();\n"
+                + "    }\n"
+                + "}";
+
+        for (int i = 1; i <= 5; i++) {
+            File classes = createDir(test + "/" + i + "/classes");
+            File annodir = createDir(test + "/" + i + "/processors");
+            callTask(getOptions("-d", annodir.getPath()), getSources(String.format(template, i)));
+            File annopath = annodir;
+            List<String> options;
+            switch (i) {
+                default:
+                    options = getOptions("-d", classes.getPath(),
+                            "-processorpath", annopath.getPath(),
+                            "-processor", "A" + i);
+                    break;
+
+                case 3:
+                    setLocation(ANNOTATION_PROCESSOR_PATH, annopath);
+                    options = getOptions("-d", classes.getPath(),
+                            "-processor", "A" + i);
+                    break;
+            }
+            List<JavaFileObject> sources = getSources("class D" + i + " { }");
+            callTask(options, sources);
+            checkPath(ANNOTATION_PROCESSOR_PATH, Mode.EQUALS, annopath);
+            checkFile(CLASS_OUTPUT, "D" + i + ".class");
+        }
+
+        tested.add(ANNOTATION_PROCESSOR_PATH);
+    }
+
+    void testSourceOutput() throws IOException {
+        String test = "testAnnotationProcessorPath";
+
+        String source =
+                "import java.io.*;\n"
+                + "import java.util.*;\n"
+                + "import javax.annotation.processing.*;\n"
+                + "import javax.lang.model.*;\n"
+                + "import javax.lang.model.element.*;\n"
+                + "import javax.tools.*;\n"
+                + "@SupportedOptions(\"name\")\n"
+                + "@SupportedAnnotationTypes(\"*\")\n"
+                + "public class A extends AbstractProcessor {\n"
+                + "    int round = 0;\n"
+                + "    public boolean process(Set<? extends TypeElement> annos, RoundEnvironment rEnv) {\n"
+                + "        if (round++ == 0) try {\n"
+                + "            String name = processingEnv.getOptions().get(\"name\");\n"
+                + "            JavaFileObject fo = processingEnv.getFiler().createSourceFile(name);\n"
+                + "            try (Writer out = fo.openWriter()) {\n"
+                + "                out.write(\"class \" + name + \" { }\");\n"
+                + "            }\n"
+                + "        } catch (IOException e) { throw new Error(e); }\n"
+                + "        return true;\n"
+                + "    }\n"
+                + "    public SourceVersion getSupportedSourceVersion() {\n"
+                + "        return SourceVersion.latest();\n"
+                + "    }\n"
+                + "}";
+
+        File annodir = createDir(test + "/processors");
+        callTask(getOptions("-d", annodir.getPath()), getSources(source));
+        setLocation(ANNOTATION_PROCESSOR_PATH, annodir);
+
+        for (int i = 1; i <= 5; i++) {
+            File classes = createDir(test + "/" + i + "/classes");
+            File genSrc = createDir(test + "/" + "/genSrc");
+            List<String> options;
+            switch (i) {
+                default:
+                    options = getOptions("-d", classes.getPath(),
+                            "-processor", "A", "-Aname=G" + i,
+                            "-s", genSrc.getPath());
+                    break;
+
+                case 3:
+                    setLocation(SOURCE_OUTPUT, genSrc);
+                    options = getOptions("-d", classes.getPath(),
+                            "-processor", "A", "-Aname=G" + i);
+                    break;
+            }
+            List<JavaFileObject> sources = getSources("class D" + i + " { }");
+            callTask(options, sources);
+            checkPath(SOURCE_OUTPUT, Mode.EQUALS, genSrc);
+            checkFile(CLASS_OUTPUT, "D" + i + ".class");
+            checkFile(CLASS_OUTPUT, "G" + i + ".class");
+        }
+        tested.add(SOURCE_OUTPUT);
+    }
+
+    void testNativeHeaderOutput() throws IOException {
+        String test = "testNativeHeaderOutput";
+
+        for (int i = 1; i <= 5; i++) {
+            File classes = createDir(test + "/" + i + "/classes");
+            File headers = createDir(test + "/" + i + "/hdrs");
+            List<String> options;
+            switch (i) {
+                default:
+                    options = getOptions("-d", classes.getPath(), "-h", headers.getPath());
+                    break;
+
+                case 3:
+                    setLocation(NATIVE_HEADER_OUTPUT, headers);
+                    options = getOptions("-d", classes.getPath());
+                    break;
+            }
+            List<JavaFileObject> sources = getSources("class C" + i + " { native void m(); }");
+            callTask(options, sources);
+            checkPath(NATIVE_HEADER_OUTPUT, Mode.EQUALS, headers);
+            checkFile(NATIVE_HEADER_OUTPUT, "C" + i + ".h");
+        }
+
+        tested.add(StandardLocation.NATIVE_HEADER_OUTPUT);
+    }
+
+    List<String> getOptions(String... args) {
+        return Arrays.asList(args);
+    }
+
+    List<JavaFileObject> getSources(String... sources) {
+        List<JavaFileObject> list = new ArrayList<>();
+        for (String s: sources)
+            list.add(getSource(s));
+        return list;
+    }
+
+    JavaFileObject getSource(final String source) {
+        return new SimpleJavaFileObject(getURIFromSource(source), JavaFileObject.Kind.SOURCE) {
+            @Override
+            public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+                return source;
+            }
+        };
+    }
+
+    void callTask(List<String> options, List<JavaFileObject> files) {
+        out.print("compile: ");
+        if (options != null) {
+            for (String o: options) {
+                if (o.length() > 64) {
+                    o = o.substring(0, 32) + "..." + o.substring(o.length() - 32);
+                }
+                out.print(" " + o);
+            }
+        }
+        for (JavaFileObject f: files)
+            out.print(" " + f.getName());
+        out.println();
+        CompilationTask t = compiler.getTask(out, fileManager, null, options, null, files);
+        boolean ok = t.call();
+        if (!ok)
+            error("compilation failed");
+    }
+
+    enum Mode { EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH };
+
+    void checkFile(StandardLocation l, String path) {
+        if (!l.isOutputLocation()) {
+            error("Not an output location: " + l);
+            return;
+        }
+
+        List<File> files = getLocation(l);
+        if (files == null) {
+            error("location is unset: " + l);
+            return;
+        }
+
+        if (files.size() != 1)
+            error("unexpected number of entries on " + l + ": " + files.size());
+
+        File f = new File(files.get(0), path);
+        if (!f.exists())
+            error("file not found: " + f);
+    }
+
+    void checkPath(StandardLocation l, Mode m, File expect) {
+        checkPath(l, m, Arrays.asList(expect));
+    }
+
+    void checkPath(StandardLocation l, Mode m, List<File> expect) {
+        List<File> files = getLocation(l);
+        if (files == null) {
+            error("location is unset: " + l);
+            return;
+        }
+
+        switch (m) {
+            case EQUALS:
+                if (!Objects.equals(files, expect)) {
+                    error("location does not match the expected files: " + l);
+                    out.println("found:  " + files);
+                    out.println("expect: " + expect);
+                }
+                break;
+
+            case CONTAINS:
+                int containsIndex = Collections.indexOfSubList(files, expect);
+                if (containsIndex == -1) {
+                    error("location does not contain the expected files: " + l);
+                    out.println("found:  " + files);
+                    out.println("expect: " + expect);
+                }
+            break;
+
+            case STARTS_WITH:
+                int startsIndex = Collections.indexOfSubList(files, expect);
+                if (startsIndex != 0) {
+                    error("location does not start with the expected files: " + l);
+                    out.println("found:  " + files);
+                    out.println("expect: " + expect);
+                }
+            break;
+
+            case ENDS_WITH:
+                int endsIndex = Collections.lastIndexOfSubList(files, expect);
+                if (endsIndex != files.size() - expect.size()) {
+                    error("location does not end with the expected files: " + l);
+                    out.println("found:  " + files);
+                    out.println("expect: " + expect);
+                }
+            break;
+
+        }
+    }
+
+    List<File> getLocation(StandardLocation l) {
+        Iterable<? extends File> iter = fileManager.getLocation(l);
+        if (iter == null)
+            return null;
+        List<File> files = new ArrayList<>();
+        for (File f: iter)
+            files.add(f);
+        return files;
+    }
+
+    void setLocation(StandardLocation l, File... files) throws IOException {
+        fileManager.setLocation(l, Arrays.asList(files));
+    }
+
+    void setLocation(StandardLocation l, List<File> files) throws IOException {
+        fileManager.setLocation(l, files);
+    }
+
+    void writeFile(File dir, String path, String body) throws IOException {
+        try (FileWriter w = new FileWriter(new File(dir, path))) {
+            w.write(body);
+        }
+    }
+
+    void writeJar(File jar, File dir, String... entries) throws IOException {
+        try (JarOutputStream j = new JarOutputStream(Files.newOutputStream(jar.toPath()))) {
+            for (String entry: entries) {
+                j.putNextEntry(new JarEntry(entry));
+                j.write(Files.readAllBytes(dir.toPath().resolve(entry)));
+            }
+        }
+    }
+
+    private static final Pattern packagePattern
+            = Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))");
+    private static final Pattern classPattern
+            = Pattern.compile("(?:public\\s+)?(?:class|enum|interface)\\s+(\\w+)");
+
+
+    private static URI getURIFromSource(String source) {
+        String packageName = null;
+
+        Matcher matcher = packagePattern.matcher(source);
+        if (matcher.find()) {
+            packageName = matcher.group(1).replace(".", "/");
+        }
+
+        matcher = classPattern.matcher(source);
+        if (matcher.find()) {
+            String className = matcher.group(1);
+            String path = ((packageName == null) ? "" : packageName + "/") + className + ".java";
+            return URI.create("myfo:///" + path);
+        } else {
+            throw new Error("Could not extract the java class "
+                    + "name from the provided source");
+        }
+    }
+
+    File createDir(String path) {
+        File dir = new File(path);
+        dir.mkdirs();
+        return dir;
+    }
+
+    JavaCompiler compiler;
+    StandardJavaFileManager fileManager;
+
+    /**
+     * Map for recording which standard locations have been tested.
+     */
+    EnumSet<StandardLocation> tested = EnumSet.noneOf(StandardLocation.class);
+
+    /**
+     * Logging stream. Used directly with test and for getTask calls.
+     */
+    final PrintWriter out = new PrintWriter(System.err, true);
+
+    /**
+     * Count of errors so far.
+     */
+    int errors;
+
+    void error(String message) {
+        errors++;
+        out.println("Error: " + message);
+    }
+}
--- a/langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java	Sun Jun 08 15:02:34 2014 -0700
@@ -105,14 +105,13 @@
 
             Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files);
 
-            Context c = new Context();
-            ArgTypeMessages.preRegister(c);
-            ArgTypeJavaCompiler.preRegister(c);
+            Context c = initContext();
             JavacTaskImpl t = (JavacTaskImpl) tool.getTask(out, fm, null, opts, null, fos, c);
             return t.call();
         }
     }
 
+
     /**
      * Run the test using the standard simple entry point.
      */
@@ -135,10 +134,8 @@
                 args.add(f.getPath());
 
             Main main = new Main("javac", out);
-            Context c = new Context();
+            Context c = initContext();
             JavacFileManager.preRegister(c); // can't create it until Log has been set up
-            ArgTypeJavaCompiler.preRegister(c);
-            ArgTypeMessages.preRegister(c);
             Main.Result result = main.compile(args.toArray(new String[args.size()]), c);
 
             return result.isOK();
@@ -161,18 +158,25 @@
             for (File f: files)
                 args.add(f.getPath());
 
-            Context c = new Context();
+            Context c = initContext();
             JavacFileManager.preRegister(c); // can't create it until Log has been set up
-            ArgTypeJavaCompiler.preRegister(c);
-            ArgTypeMessages.preRegister(c);
             Main m = new Main("javac", out);
             Main.Result result = m.compile(args.toArray(new String[args.size()]), c);
 
             return result.isOK();
         }
-
     }
 
+    private static Context initContext() {
+        Context context = new Context();
+        ArgTypeMessages.preRegister(context);
+        Options options = Options.instance(context);
+        options.addListener(() -> {
+            Log log = Log.instance(context);
+            log.setDiagnosticFormatter(new ArgTypeDiagnosticFormatter(options));
+        });
+        return context;
+    }
 
     // <editor-fold defaultstate="collapsed" desc="Custom Javac components">
 
@@ -228,29 +232,6 @@
     }
 
     /**
-     * Trivial subtype of JavaCompiler to get access to the protected compilerKey field.
-     * The factory is used to ensure that the log is initialized with an instance of
-     * ArgTypeDiagnosticFormatter before we create the required JavaCompiler.
-     */
-    static class ArgTypeJavaCompiler extends JavaCompiler {
-        static void preRegister(Context context) {
-            context.put(compilerKey, new Context.Factory<JavaCompiler>() {
-                public JavaCompiler make(Context c) {
-                    Log log = Log.instance(c);
-                    Options options = Options.instance(c);
-                    log.setDiagnosticFormatter(new ArgTypeDiagnosticFormatter(options));
-                    return new JavaCompiler(c);
-                }
-            });
-        }
-
-        // not used
-        private ArgTypeJavaCompiler() {
-            super(null);
-        }
-    }
-
-    /**
      * Diagnostic formatter which "localizes" a message as a line
      * containing a key, and a possibly empty set of descriptive strings for the
      * arg types.
--- a/langtools/test/tools/javac/processing/6430209/T6430209.java	Fri Jun 06 16:08:46 2014 -0400
+++ b/langtools/test/tools/javac/processing/6430209/T6430209.java	Sun Jun 08 15:02:34 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,7 +55,7 @@
         // run annotation processor b6341534 so we can check diagnostics
         // -proc:only -processor b6341534 -cp . ./src/*.java
         String testSrc = System.getProperty("test.src", ".");
-        String testClasses = System.getProperty("test.classes") + System.getProperty("path.separator") + "../../lib";
+        String testClassPath = System.getProperty("test.class.path");
         JavacTool tool = JavacTool.create();
         MyDiagListener dl = new MyDiagListener();
         StandardJavaFileManager fm = tool.getStandardFileManager(dl, null, null);
@@ -64,7 +64,7 @@
             new File(testSrc, "test0.java"), new File(testSrc, "test1.java")));
         Iterable<String> opts = Arrays.asList("-proc:only",
                                               "-processor", "b6341534",
-                                              "-processorpath", testClasses);
+                                              "-processorpath", testClassPath);
         StringWriter out = new StringWriter();
         JavacTask task = tool.getTask(out, fm, dl, opts, null, files);
         task.call();