langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java
changeset 27858 443efec4bf09
parent 27579 d1a63c99cdd5
parent 27852 2e6ad0e4fe20
child 28332 cd3ea1087d2b
equal deleted inserted replaced
27581:9fffb959eb41 27858:443efec4bf09
    32 import java.net.URI;
    32 import java.net.URI;
    33 import java.net.URISyntaxException;
    33 import java.net.URISyntaxException;
    34 import java.net.URL;
    34 import java.net.URL;
    35 import java.nio.CharBuffer;
    35 import java.nio.CharBuffer;
    36 import java.nio.charset.Charset;
    36 import java.nio.charset.Charset;
       
    37 import java.nio.file.Files;
       
    38 import java.nio.file.InvalidPathException;
       
    39 import java.nio.file.LinkOption;
       
    40 import java.nio.file.NoSuchFileException;
    37 import java.nio.file.Path;
    41 import java.nio.file.Path;
       
    42 import java.nio.file.Paths;
    38 import java.util.ArrayList;
    43 import java.util.ArrayList;
    39 import java.util.Arrays;
    44 import java.util.Arrays;
    40 import java.util.Collection;
    45 import java.util.Collection;
    41 import java.util.Collections;
    46 import java.util.Collections;
    42 import java.util.Comparator;
    47 import java.util.Comparator;
    43 import java.util.EnumSet;
    48 import java.util.EnumSet;
    44 import java.util.HashMap;
    49 import java.util.HashMap;
    45 import java.util.Iterator;
    50 import java.util.Iterator;
    46 import java.util.Map;
    51 import java.util.Map;
    47 import java.util.Set;
    52 import java.util.Set;
       
    53 import java.util.stream.Collectors;
       
    54 import java.util.stream.Stream;
    48 import java.util.zip.ZipFile;
    55 import java.util.zip.ZipFile;
    49 
    56 
    50 import javax.lang.model.SourceVersion;
    57 import javax.lang.model.SourceVersion;
    51 import javax.tools.FileObject;
    58 import javax.tools.FileObject;
    52 import javax.tools.JavaFileManager;
    59 import javax.tools.JavaFileManager;
    95         EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS);
   102         EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS);
    96 
   103 
    97     protected boolean mmappedIO;
   104     protected boolean mmappedIO;
    98     protected boolean symbolFileEnabled;
   105     protected boolean symbolFileEnabled;
    99 
   106 
   100     protected enum SortFiles implements Comparator<File> {
   107     protected enum SortFiles implements Comparator<Path> {
   101         FORWARD {
   108         FORWARD {
   102             @Override
   109             @Override
   103             public int compare(File f1, File f2) {
   110             public int compare(Path f1, Path f2) {
   104                 return f1.getName().compareTo(f2.getName());
   111                 return f1.getFileName().compareTo(f2.getFileName());
   105             }
   112             }
   106         },
   113         },
   107         REVERSE {
   114         REVERSE {
   108             @Override
   115             @Override
   109             public int compare(File f1, File f2) {
   116             public int compare(Path f1, Path f2) {
   110                 return -f1.getName().compareTo(f2.getName());
   117                 return -f1.getFileName().compareTo(f2.getFileName());
   111             }
   118             }
   112         }
   119         }
   113     }
   120     }
   114 
   121 
   115     protected SortFiles sortFiles;
   122     protected SortFiles sortFiles;
   169     public boolean isSymbolFileEnabled() {
   176     public boolean isSymbolFileEnabled() {
   170         return symbolFileEnabled;
   177         return symbolFileEnabled;
   171     }
   178     }
   172 
   179 
   173     public JavaFileObject getFileForInput(String name) {
   180     public JavaFileObject getFileForInput(String name) {
   174         return getRegularFile(new File(name));
   181         return getRegularFile(Paths.get(name));
   175     }
   182     }
   176 
   183 
   177     public JavaFileObject getRegularFile(File file) {
   184     public JavaFileObject getRegularFile(Path file) {
   178         return new RegularFileObject(this, file);
   185         return new RegularFileObject(this, file);
   179     }
   186     }
   180 
   187 
   181     public JavaFileObject getFileForOutput(String classname,
   188     public JavaFileObject getFileForOutput(String classname,
   182                                            JavaFileObject.Kind kind,
   189                                            JavaFileObject.Kind kind,
   296 
   303 
   297     /**
   304     /**
   298      * Insert all files in subdirectory subdirectory of directory directory
   305      * Insert all files in subdirectory subdirectory of directory directory
   299      * which match fileKinds into resultList
   306      * which match fileKinds into resultList
   300      */
   307      */
   301     private void listDirectory(File directory,
   308     private void listDirectory(Path directory,
   302                                RelativeDirectory subdirectory,
   309                                RelativeDirectory subdirectory,
   303                                Set<JavaFileObject.Kind> fileKinds,
   310                                Set<JavaFileObject.Kind> fileKinds,
   304                                boolean recurse,
   311                                boolean recurse,
   305                                ListBuffer<JavaFileObject> resultList) {
   312                                ListBuffer<JavaFileObject> resultList) {
   306         File d = subdirectory.getFile(directory);
   313         Path d;
   307         if (!caseMapCheck(d, subdirectory))
   314         try {
       
   315             d = subdirectory.getFile(directory);
       
   316         } catch (InvalidPathException ignore) {
   308             return;
   317             return;
   309 
   318         }
   310         File[] files = d.listFiles();
   319 
   311         if (files == null)
   320         if (!Files.exists(d)) {
       
   321            return;
       
   322         }
       
   323 
       
   324         if (!caseMapCheck(d, subdirectory)) {
   312             return;
   325             return;
   313 
   326         }
   314         if (sortFiles != null)
   327 
   315             Arrays.sort(files, sortFiles);
   328         java.util.List<Path> files;
   316 
   329         try (Stream<Path> s = Files.list(d)) {
   317         for (File f: files) {
   330             files = (sortFiles == null ? s : s.sorted(sortFiles)).collect(Collectors.toList());
   318             String fname = f.getName();
   331         } catch (IOException ignore) {
   319             if (f.isDirectory()) {
   332             return;
       
   333         }
       
   334 
       
   335         for (Path f: files) {
       
   336             String fname = f.getFileName().toString();
       
   337             if (Files.isDirectory(f)) {
   320                 if (recurse && SourceVersion.isIdentifier(fname)) {
   338                 if (recurse && SourceVersion.isIdentifier(fname)) {
   321                     listDirectory(directory,
   339                     listDirectory(directory,
   322                                   new RelativeDirectory(subdirectory, fname),
   340                                   new RelativeDirectory(subdirectory, fname),
   323                                   fileKinds,
   341                                   fileKinds,
   324                                   recurse,
   342                                   recurse,
   325                                   resultList);
   343                                   resultList);
   326                 }
   344                 }
   327             } else {
   345             } else {
   328                 if (isValidFile(fname, fileKinds)) {
   346                 if (isValidFile(fname, fileKinds)) {
   329                     JavaFileObject fe =
   347                     JavaFileObject fe =
   330                         new RegularFileObject(this, fname, new File(d, fname));
   348                         new RegularFileObject(this, fname, d.resolve(fname));
   331                     resultList.append(fe);
   349                     resultList.append(fe);
   332                 }
   350                 }
   333             }
   351             }
   334         }
   352         }
   335     }
   353     }
   368     /**
   386     /**
   369      * container is a directory, a zip file, or a non-existant path.
   387      * container is a directory, a zip file, or a non-existant path.
   370      * Insert all files in subdirectory subdirectory of container which
   388      * Insert all files in subdirectory subdirectory of container which
   371      * match fileKinds into resultList
   389      * match fileKinds into resultList
   372      */
   390      */
   373     private void listContainer(File container,
   391     private void listContainer(Path container,
   374                                RelativeDirectory subdirectory,
   392                                RelativeDirectory subdirectory,
   375                                Set<JavaFileObject.Kind> fileKinds,
   393                                Set<JavaFileObject.Kind> fileKinds,
   376                                boolean recurse,
   394                                boolean recurse,
   377                                ListBuffer<JavaFileObject> resultList) {
   395                                ListBuffer<JavaFileObject> resultList) {
   378         Archive archive = archives.get(container);
   396         Archive archive = archives.get(container);
   379         if (archive == null) {
   397         if (archive == null) {
   380             // Very temporary and obnoxious interim hack
   398             // Very temporary and obnoxious interim hack
   381             if (container.getName().equals("bootmodules.jimage")) {
   399             if (container.endsWith("bootmodules.jimage")) {
   382                 System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:");
   400                 System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:");
   383                 container = Locations.JRT_MARKER_FILE;
   401                 container = Locations.JRT_MARKER_FILE;
   384             } else if (container.getName().endsWith(".jimage")) {
   402             } else if (container.getFileName().toString().endsWith(".jimage")) {
   385                 System.err.println("Warning: reference to " + container + " ignored");
   403                 System.err.println("Warning: reference to " + container + " ignored");
   386                 return;
   404                 return;
   387             }
   405             }
   388 
   406 
   389             // archives are not created for directories or jrt: images
   407             // archives are not created for directories or jrt: images
   434 
   452 
   435     /** Hack to make Windows case sensitive. Test whether given path
   453     /** Hack to make Windows case sensitive. Test whether given path
   436      *  ends in a string of characters with the same case as given name.
   454      *  ends in a string of characters with the same case as given name.
   437      *  Ignore file separators in both path and name.
   455      *  Ignore file separators in both path and name.
   438      */
   456      */
   439     private boolean caseMapCheck(File f, RelativePath name) {
   457     private boolean caseMapCheck(Path f, RelativePath name) {
   440         if (fileSystemIsCaseSensitive) return true;
   458         if (fileSystemIsCaseSensitive) return true;
   441         // Note that getCanonicalPath() returns the case-sensitive
   459         // Note that toRealPath() returns the case-sensitive
   442         // spelled file name.
   460         // spelled file name.
   443         String path;
   461         String path;
       
   462         char sep;
   444         try {
   463         try {
   445             path = f.getCanonicalPath();
   464             path = f.toRealPath(LinkOption.NOFOLLOW_LINKS).toString();
       
   465             sep = f.getFileSystem().getSeparator().charAt(0);
   446         } catch (IOException ex) {
   466         } catch (IOException ex) {
   447             return false;
   467             return false;
   448         }
   468         }
   449         char[] pcs = path.toCharArray();
   469         char[] pcs = path.toCharArray();
   450         char[] ncs = name.path.toCharArray();
   470         char[] ncs = name.path.toCharArray();
   451         int i = pcs.length - 1;
   471         int i = pcs.length - 1;
   452         int j = ncs.length - 1;
   472         int j = ncs.length - 1;
   453         while (i >= 0 && j >= 0) {
   473         while (i >= 0 && j >= 0) {
   454             while (i >= 0 && pcs[i] == File.separatorChar) i--;
   474             while (i >= 0 && pcs[i] == sep) i--;
   455             while (j >= 0 && ncs[j] == '/') j--;
   475             while (j >= 0 && ncs[j] == '/') j--;
   456             if (i >= 0 && j >= 0) {
   476             if (i >= 0 && j >= 0) {
   457                 if (pcs[i] != ncs[j]) return false;
   477                 if (pcs[i] != ncs[j]) return false;
   458                 i--;
   478                 i--;
   459                 j--;
   479                 j--;
   477 
   497 
   478         Set<RelativeDirectory> getSubdirectories();
   498         Set<RelativeDirectory> getSubdirectories();
   479     }
   499     }
   480 
   500 
   481     public class MissingArchive implements Archive {
   501     public class MissingArchive implements Archive {
   482         final File zipFileName;
   502         final Path zipFileName;
   483         public MissingArchive(File name) {
   503         public MissingArchive(Path name) {
   484             zipFileName = name;
   504             zipFileName = name;
   485         }
   505         }
   486         @Override
   506         @Override
   487         public boolean contains(RelativePath name) {
   507         public boolean contains(RelativePath name) {
   488             return false;
   508             return false;
   513         }
   533         }
   514     }
   534     }
   515 
   535 
   516     /** A directory of zip files already opened.
   536     /** A directory of zip files already opened.
   517      */
   537      */
   518     Map<File, Archive> archives = new HashMap<>();
   538     Map<Path, Archive> archives = new HashMap<>();
   519 
   539 
   520     /*
   540     /*
   521      * This method looks for a ZipFormatException and takes appropriate
   541      * This method looks for a ZipFormatException and takes appropriate
   522      * evasive action. If there is a failure in the fast mode then we
   542      * evasive action. If there is a failure in the fast mode then we
   523      * fail over to the platform zip, and allow it to deal with a potentially
   543      * fail over to the platform zip, and allow it to deal with a potentially
   524      * non compliant zip file.
   544      * non compliant zip file.
   525      */
   545      */
   526     protected Archive openArchive(File zipFilename) throws IOException {
   546     protected Archive openArchive(Path zipFilename) throws IOException {
   527         try {
   547         try {
   528             return openArchive(zipFilename, contextUseOptimizedZip);
   548             return openArchive(zipFilename, contextUseOptimizedZip);
   529         } catch (IOException ioe) {
   549         } catch (IOException ioe) {
   530             if (ioe instanceof ZipFileIndex.ZipFormatException) {
   550             if (ioe instanceof ZipFileIndex.ZipFormatException) {
   531                 return openArchive(zipFilename, false);
   551                 return openArchive(zipFilename, false);
   535         }
   555         }
   536     }
   556     }
   537 
   557 
   538     /** Open a new zip file directory, and cache it.
   558     /** Open a new zip file directory, and cache it.
   539      */
   559      */
   540     private Archive openArchive(File zipFileName, boolean useOptimizedZip) throws IOException {
   560     private Archive openArchive(Path zipFileName, boolean useOptimizedZip) throws IOException {
   541         Archive archive;
   561         Archive archive;
   542         try {
   562         try {
   543 
   563 
   544             ZipFile zdir = null;
   564             ZipFile zdir = null;
   545 
   565 
   546             boolean usePreindexedCache = false;
   566             boolean usePreindexedCache = false;
   547             String preindexCacheLocation = null;
   567             String preindexCacheLocation = null;
   548 
   568 
   549             if (!useOptimizedZip) {
   569             if (!useOptimizedZip) {
   550                 zdir = new ZipFile(zipFileName);
   570                 zdir = new ZipFile(zipFileName.toFile());
   551             } else {
   571             } else {
   552                 usePreindexedCache = options.isSet("usezipindex");
   572                 usePreindexedCache = options.isSet("usezipindex");
   553                 preindexCacheLocation = options.get("java.io.tmpdir");
   573                 preindexCacheLocation = options.get("java.io.tmpdir");
   554                 String optCacheLoc = options.get("cachezipindexdir");
   574                 String optCacheLoc = options.get("cachezipindexdir");
   555 
   575 
   582                                     null,
   602                                     null,
   583                                     usePreindexedCache,
   603                                     usePreindexedCache,
   584                                     preindexCacheLocation,
   604                                     preindexCacheLocation,
   585                                     options.isSet("writezipindexfiles")));
   605                                     options.isSet("writezipindexfiles")));
   586                 }
   606                 }
   587         } catch (FileNotFoundException ex) {
   607         } catch (FileNotFoundException | NoSuchFileException ex) {
   588             archive = new MissingArchive(zipFileName);
   608             archive = new MissingArchive(zipFileName);
   589         } catch (ZipFileIndex.ZipFormatException zfe) {
   609         } catch (ZipFileIndex.ZipFormatException zfe) {
   590             throw zfe;
   610             throw zfe;
   591         } catch (IOException ex) {
   611         } catch (IOException ex) {
   592             if (zipFileName.exists())
   612             if (Files.exists(zipFileName))
   593                 log.error("error.reading.file", zipFileName, getMessage(ex));
   613                 log.error("error.reading.file", zipFileName, getMessage(ex));
   594             archive = new MissingArchive(zipFileName);
   614             archive = new MissingArchive(zipFileName);
   595         }
   615         }
   596 
   616 
   597         archives.put(zipFileName, archive);
   617         archives.put(zipFileName, archive);
   647     {
   667     {
   648         // validatePackageName(packageName);
   668         // validatePackageName(packageName);
   649         nullCheck(packageName);
   669         nullCheck(packageName);
   650         nullCheck(kinds);
   670         nullCheck(kinds);
   651 
   671 
   652         Iterable<? extends File> path = getLocation(location);
   672         Iterable<? extends Path> path = getLocationAsPaths(location);
   653         if (path == null)
   673         if (path == null)
   654             return List.nil();
   674             return List.nil();
   655         RelativeDirectory subdirectory = RelativeDirectory.forPackage(packageName);
   675         RelativeDirectory subdirectory = RelativeDirectory.forPackage(packageName);
   656         ListBuffer<JavaFileObject> results = new ListBuffer<>();
   676         ListBuffer<JavaFileObject> results = new ListBuffer<>();
   657 
   677 
   658         for (File directory : path)
   678         for (Path directory : path)
   659             listContainer(directory, subdirectory, kinds, recurse, results);
   679             listContainer(directory, subdirectory, kinds, recurse, results);
   660         return results.toList();
   680         return results.toList();
   661     }
   681     }
   662 
   682 
   663     @Override @DefinedBy(Api.COMPILER)
   683     @Override @DefinedBy(Api.COMPILER)
   664     public String inferBinaryName(Location location, JavaFileObject file) {
   684     public String inferBinaryName(Location location, JavaFileObject file) {
   665         file.getClass(); // null check
   685         file.getClass(); // null check
   666         location.getClass(); // null check
   686         location.getClass(); // null check
   667         // Need to match the path semantics of list(location, ...)
   687         // Need to match the path semantics of list(location, ...)
   668         Iterable<? extends File> path = getLocation(location);
   688         Iterable<? extends Path> path = getLocationAsPaths(location);
   669         if (path == null) {
   689         if (path == null) {
   670             return null;
   690             return null;
   671         }
   691         }
   672 
   692 
   673         if (file instanceof BaseFileObject) {
   693         if (file instanceof BaseFileObject) {
   728             : new RelativeFile(RelativeDirectory.forPackage(packageName), relativeName);
   748             : new RelativeFile(RelativeDirectory.forPackage(packageName), relativeName);
   729         return getFileForInput(location, name);
   749         return getFileForInput(location, name);
   730     }
   750     }
   731 
   751 
   732     private JavaFileObject getFileForInput(Location location, RelativeFile name) throws IOException {
   752     private JavaFileObject getFileForInput(Location location, RelativeFile name) throws IOException {
   733         Iterable<? extends File> path = getLocation(location);
   753         Iterable<? extends Path> path = getLocationAsPaths(location);
   734         if (path == null)
   754         if (path == null)
   735             return null;
   755             return null;
   736 
   756 
   737         for (File file: path) {
   757         for (Path file: path) {
   738             Archive a = archives.get(file);
   758             Archive a = archives.get(file);
   739             if (a == null) {
   759             if (a == null) {
   740                 // archives are not created for directories or jrt: images
   760                 // archives are not created for directories or jrt: images
   741                 if (file == Locations.JRT_MARKER_FILE) {
   761                 if (file == Locations.JRT_MARKER_FILE) {
   742                     JRTIndex.Entry e = getJRTIndex().getEntry(name.dirname());
   762                     JRTIndex.Entry e = getJRTIndex().getEntry(name.dirname());
   745                     Path p = e.files.get(name.basename());
   765                     Path p = e.files.get(name.basename());
   746                     if (p != null)
   766                     if (p != null)
   747                         return PathFileObject.createJRTPathFileObject(this, p);
   767                         return PathFileObject.createJRTPathFileObject(this, p);
   748                     continue;
   768                     continue;
   749                 } else if (fsInfo.isDirectory(file)) {
   769                 } else if (fsInfo.isDirectory(file)) {
   750                     File f = name.getFile(file);
   770                     try {
   751                     if (f.exists())
   771                         Path f = name.getFile(file);
   752                         return new RegularFileObject(this, f);
   772                         if (Files.exists(f))
       
   773                             return new RegularFileObject(this, f);
       
   774                     } catch (InvalidPathException ignore) {
       
   775                     }
   753                     continue;
   776                     continue;
   754                 }
   777                 }
   755                 // Not a directory, create the archive
   778                 // Not a directory, create the archive
   756                 a = openArchive(file);
   779                 a = openArchive(file);
   757             }
   780             }
   800     private JavaFileObject getFileForOutput(Location location,
   823     private JavaFileObject getFileForOutput(Location location,
   801                                             RelativeFile fileName,
   824                                             RelativeFile fileName,
   802                                             FileObject sibling)
   825                                             FileObject sibling)
   803         throws IOException
   826         throws IOException
   804     {
   827     {
   805         File dir;
   828         Path dir;
   806         if (location == CLASS_OUTPUT) {
   829         if (location == CLASS_OUTPUT) {
   807             if (getClassOutDir() != null) {
   830             if (getClassOutDir() != null) {
   808                 dir = getClassOutDir();
   831                 dir = getClassOutDir();
   809             } else {
   832             } else {
   810                 File siblingDir = null;
   833                 Path siblingDir = null;
   811                 if (sibling != null && sibling instanceof RegularFileObject) {
   834                 if (sibling != null && sibling instanceof RegularFileObject) {
   812                     siblingDir = ((RegularFileObject)sibling).file.getParentFile();
   835                     siblingDir = ((RegularFileObject)sibling).file.getParent();
   813                 }
   836                 }
   814                 return new RegularFileObject(this, new File(siblingDir, fileName.basename()));
   837                 if (siblingDir == null)
       
   838                     return new RegularFileObject(this, Paths.get(fileName.basename()));
       
   839                 else
       
   840                     return new RegularFileObject(this, siblingDir.resolve(fileName.basename()));
   815             }
   841             }
   816         } else if (location == SOURCE_OUTPUT) {
   842         } else if (location == SOURCE_OUTPUT) {
   817             dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
   843             dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
   818         } else {
   844         } else {
   819             Iterable<? extends File> path = locations.getLocation(location);
   845             Iterable<? extends Path> path = locations.getLocation(location);
   820             dir = null;
   846             dir = null;
   821             for (File f: path) {
   847             for (Path f: path) {
   822                 dir = f;
   848                 dir = f;
   823                 break;
   849                 break;
   824             }
   850             }
   825         }
   851         }
   826 
   852 
   827         File file = fileName.getFile(dir); // null-safe
   853         try {
   828         return new RegularFileObject(this, file);
   854             Path file = fileName.getFile(dir); // null-safe
   829 
   855             return new RegularFileObject(this, file);
       
   856         } catch (InvalidPathException e) {
       
   857             throw new IOException("bad filename " + fileName, e);
       
   858         }
   830     }
   859     }
   831 
   860 
   832     @Override @DefinedBy(Api.COMPILER)
   861     @Override @DefinedBy(Api.COMPILER)
   833     public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(
   862     public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(
   834         Iterable<? extends File> files)
   863         Iterable<? extends File> files)
   837         if (files instanceof Collection<?>)
   866         if (files instanceof Collection<?>)
   838             result = new ArrayList<>(((Collection<?>)files).size());
   867             result = new ArrayList<>(((Collection<?>)files).size());
   839         else
   868         else
   840             result = new ArrayList<>();
   869             result = new ArrayList<>();
   841         for (File f: files)
   870         for (File f: files)
   842             result.add(new RegularFileObject(this, nullCheck(f)));
   871             result.add(new RegularFileObject(this, nullCheck(f).toPath()));
   843         return result;
   872         return result;
   844     }
   873     }
   845 
   874 
   846     @Override @DefinedBy(Api.COMPILER)
   875     @Override @DefinedBy(Api.COMPILER)
   847     public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
   876     public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
   848         return getJavaFileObjectsFromFiles(Arrays.asList(nullCheck(files)));
   877         return getJavaFileObjectsFromFiles(Arrays.asList(nullCheck(files)));
   849     }
   878     }
   850 
   879 
   851     @Override @DefinedBy(Api.COMPILER)
   880     @Override @DefinedBy(Api.COMPILER)
   852     public void setLocation(Location location,
   881     public void setLocation(Location location,
   853                             Iterable<? extends File> path)
   882                             Iterable<? extends File> searchpath)
   854         throws IOException
   883         throws IOException
   855     {
   884     {
   856         nullCheck(location);
   885         nullCheck(location);
   857         locations.setLocation(location, path);
   886         locations.setLocation(location, asPaths(searchpath));
   858     }
   887     }
   859 
   888 
   860     @Override @DefinedBy(Api.COMPILER)
   889     @Override @DefinedBy(Api.COMPILER)
   861     public Iterable<? extends File> getLocation(Location location) {
   890     public Iterable<? extends File> getLocation(Location location) {
   862         nullCheck(location);
   891         nullCheck(location);
       
   892         return asFiles(locations.getLocation(location));
       
   893     }
       
   894 
       
   895     private Iterable<? extends Path> getLocationAsPaths(Location location) {
       
   896         nullCheck(location);
   863         return locations.getLocation(location);
   897         return locations.getLocation(location);
   864     }
   898     }
   865 
   899 
   866     private File getClassOutDir() {
   900     private Path getClassOutDir() {
   867         return locations.getOutputLocation(CLASS_OUTPUT);
   901         return locations.getOutputLocation(CLASS_OUTPUT);
   868     }
   902     }
   869 
   903 
   870     private File getSourceOutDir() {
   904     private Path getSourceOutDir() {
   871         return locations.getOutputLocation(SOURCE_OUTPUT);
   905         return locations.getOutputLocation(SOURCE_OUTPUT);
   872     }
   906     }
   873 
   907 
   874     /**
   908     /**
   875      * Enforces the specification of a "relative" name as used in
   909      * Enforces the specification of a "relative" name as used in
   936         s = e.getMessage();
   970         s = e.getMessage();
   937         if (s != null)
   971         if (s != null)
   938             return s;
   972             return s;
   939         return e.toString();
   973         return e.toString();
   940     }
   974     }
       
   975 
       
   976     /* Converters between files and paths.
       
   977      * These are temporary until we can update the StandardJavaFileManager API.
       
   978      */
       
   979 
       
   980     private static Iterable<Path> asPaths(final Iterable<? extends File> files) {
       
   981         if (files == null)
       
   982             return null;
       
   983 
       
   984         return () -> new Iterator<Path>() {
       
   985             Iterator<? extends File> iter = files.iterator();
       
   986 
       
   987             @Override
       
   988             public boolean hasNext() {
       
   989                 return iter.hasNext();
       
   990             }
       
   991 
       
   992             @Override
       
   993             public Path next() {
       
   994                 return iter.next().toPath();
       
   995             }
       
   996         };
       
   997     }
       
   998 
       
   999     private static Iterable<File> asFiles(final Iterable<? extends Path> paths) {
       
  1000         if (paths == null)
       
  1001             return null;
       
  1002 
       
  1003         return () -> new Iterator<File>() {
       
  1004             Iterator<? extends Path> iter = paths.iterator();
       
  1005 
       
  1006             @Override
       
  1007             public boolean hasNext() {
       
  1008                 return iter.hasNext();
       
  1009             }
       
  1010 
       
  1011             @Override
       
  1012             public File next() {
       
  1013                 return iter.next().toFile();
       
  1014             }
       
  1015         };
       
  1016     }
       
  1017 
       
  1018     private static File asFile(Path path) {
       
  1019         return path == null ? null : path.toFile();
       
  1020     }
   941 }
  1021 }