langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java
changeset 1205 b316e32eb90c
parent 815 bcb5c0d7c1ab
child 1208 5072b0dd3d52
equal deleted inserted replaced
1109:853d8c191eac 1205:b316e32eb90c
    63 import javax.tools.JavaFileManager;
    63 import javax.tools.JavaFileManager;
    64 import javax.tools.JavaFileObject;
    64 import javax.tools.JavaFileObject;
    65 import javax.tools.StandardJavaFileManager;
    65 import javax.tools.StandardJavaFileManager;
    66 
    66 
    67 import com.sun.tools.javac.code.Source;
    67 import com.sun.tools.javac.code.Source;
       
    68 import com.sun.tools.javac.file.RelativePath.RelativeFile;
       
    69 import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
    68 import com.sun.tools.javac.main.JavacOption;
    70 import com.sun.tools.javac.main.JavacOption;
    69 import com.sun.tools.javac.main.OptionName;
    71 import com.sun.tools.javac.main.OptionName;
    70 import com.sun.tools.javac.main.RecognizedOptions;
    72 import com.sun.tools.javac.main.RecognizedOptions;
    71 import com.sun.tools.javac.util.Context;
    73 import com.sun.tools.javac.util.Context;
    72 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
    74 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
    73 import com.sun.tools.javac.util.List;
    75 import com.sun.tools.javac.util.List;
    74 import com.sun.tools.javac.util.ListBuffer;
    76 import com.sun.tools.javac.util.ListBuffer;
    75 import com.sun.tools.javac.util.Log;
    77 import com.sun.tools.javac.util.Log;
    76 import com.sun.tools.javac.util.Options;
    78 import com.sun.tools.javac.util.Options;
    77 
    79 
       
    80 import static javax.tools.StandardLocation.*;
    78 import static com.sun.tools.javac.main.OptionName.*;
    81 import static com.sun.tools.javac.main.OptionName.*;
    79 import static javax.tools.StandardLocation.*;
       
    80 
    82 
    81 /**
    83 /**
    82  * This class provides access to the source, class and other files
    84  * This class provides access to the source, class and other files
    83  * used by the compiler and related tools.
    85  * used by the compiler and related tools.
    84  */
    86  */
    85 public class JavacFileManager implements StandardJavaFileManager {
    87 public class JavacFileManager implements StandardJavaFileManager {
    86 
       
    87     private static final String[] symbolFileLocation = { "lib", "ct.sym" };
       
    88     private static final String symbolFilePrefix = "META-INF/sym/rt.jar/";
       
    89 
    88 
    90     boolean useZipFileIndex;
    89     boolean useZipFileIndex;
    91 
    90 
    92     private static boolean CHECK_ZIP_TIMESTAMP = false;
    91     private static boolean CHECK_ZIP_TIMESTAMP = false;
    93     private static Map<File, Boolean> isDirectory = new ConcurrentHashMap<File, Boolean>();
    92     private static Map<File, Boolean> isDirectory = new ConcurrentHashMap<File, Boolean>();
   265             if (isValidClassName)
   264             if (isValidClassName)
   266                 throw new AssertionError("Valid class name rejected: " + name);
   265                 throw new AssertionError("Valid class name rejected: " + name);
   267             printAscii("Invalid class name: \"%s\"", name);
   266             printAscii("Invalid class name: \"%s\"", name);
   268         }
   267         }
   269     }
   268     }
       
   269 
   270     private static void printAscii(String format, Object... args) {
   270     private static void printAscii(String format, Object... args) {
   271         String message;
   271         String message;
   272         try {
   272         try {
   273             final String ascii = "US-ASCII";
   273             final String ascii = "US-ASCII";
   274             message = new String(String.format(null, format, args).getBytes(ascii), ascii);
   274             message = new String(String.format(null, format, args).getBytes(ascii), ascii);
   276             throw new AssertionError(ex);
   276             throw new AssertionError(ex);
   277         }
   277         }
   278         System.out.println(message);
   278         System.out.println(message);
   279     }
   279     }
   280 
   280 
   281     /** Return external representation of name,
       
   282      *  converting '.' to File.separatorChar.
       
   283      */
       
   284     private static String externalizeFileName(CharSequence name) {
       
   285         return name.toString().replace('.', File.separatorChar);
       
   286     }
       
   287 
       
   288     private static String externalizeFileName(CharSequence n, JavaFileObject.Kind kind) {
       
   289         return externalizeFileName(n) + kind.extension;
       
   290     }
       
   291 
       
   292     private static String baseName(String fileName) {
       
   293         return fileName.substring(fileName.lastIndexOf(File.separatorChar) + 1);
       
   294     }
       
   295 
       
   296     /**
   281     /**
   297      * Insert all files in subdirectory `subdirectory' of `directory' which end
   282      * Insert all files in subdirectory `subdirectory' of `directory' which end
   298      * in one of the extensions in `extensions' into packageSym.
   283      * in one of the extensions in `extensions' into packageSym.
   299      */
   284      */
   300     private void listDirectory(File directory,
   285     private void listDirectory(File directory,
   301                                String subdirectory,
   286                                RelativeDirectory subdirectory,
   302                                Set<JavaFileObject.Kind> fileKinds,
   287                                Set<JavaFileObject.Kind> fileKinds,
   303                                boolean recurse,
   288                                boolean recurse,
   304                                ListBuffer<JavaFileObject> l) {
   289                                ListBuffer<JavaFileObject> l) {
   305         Archive archive = archives.get(directory);
   290         Archive archive = archives.get(directory);
   306 
   291 
   327                     log.error("error.reading.file",
   312                     log.error("error.reading.file",
   328                        directory, ex.getLocalizedMessage());
   313                        directory, ex.getLocalizedMessage());
   329                     return;
   314                     return;
   330                 }
   315                 }
   331             }
   316             }
   332             if (subdirectory.length() != 0) {
       
   333                 if (!useZipFileIndex) {
       
   334                     subdirectory = subdirectory.replace('\\', '/');
       
   335                     if (!subdirectory.endsWith("/")) subdirectory = subdirectory + "/";
       
   336                 }
       
   337                 else {
       
   338                     if (File.separatorChar == '/') {
       
   339                         subdirectory = subdirectory.replace('\\', '/');
       
   340                     }
       
   341                     else {
       
   342                         subdirectory = subdirectory.replace('/', '\\');
       
   343                     }
       
   344 
       
   345                     if (!subdirectory.endsWith(File.separator)) subdirectory = subdirectory + File.separator;
       
   346                 }
       
   347             }
       
   348 
   317 
   349             List<String> files = archive.getFiles(subdirectory);
   318             List<String> files = archive.getFiles(subdirectory);
   350             if (files != null) {
   319             if (files != null) {
   351                 for (String file; !files.isEmpty(); files = files.tail) {
   320                 for (String file; !files.isEmpty(); files = files.tail) {
   352                     file = files.head;
   321                     file = files.head;
   354                         l.append(archive.getFileObject(subdirectory, file));
   323                         l.append(archive.getFileObject(subdirectory, file));
   355                     }
   324                     }
   356                 }
   325                 }
   357             }
   326             }
   358             if (recurse) {
   327             if (recurse) {
   359                 for (String s: archive.getSubdirectories()) {
   328                 for (RelativeDirectory s: archive.getSubdirectories()) {
   360                     if (s.startsWith(subdirectory) && !s.equals(subdirectory)) {
   329                     if (subdirectory.contains(s)) {
   361                         // Because the archive map is a flat list of directories,
   330                         // Because the archive map is a flat list of directories,
   362                         // the enclosing loop will pick up all child subdirectories.
   331                         // the enclosing loop will pick up all child subdirectories.
   363                         // Therefore, there is no need to recurse deeper.
   332                         // Therefore, there is no need to recurse deeper.
   364                         listDirectory(directory, s, fileKinds, false, l);
   333                         listDirectory(directory, s, fileKinds, false, l);
   365                     }
   334                     }
   366                 }
   335                 }
   367             }
   336             }
   368         } else {
   337         } else {
   369             File d = subdirectory.length() != 0
   338             File d = subdirectory.getFile(directory);
   370                 ? new File(directory, subdirectory)
       
   371                 : directory;
       
   372             if (!caseMapCheck(d, subdirectory))
   339             if (!caseMapCheck(d, subdirectory))
   373                 return;
   340                 return;
   374 
   341 
   375             File[] files = d.listFiles();
   342             File[] files = d.listFiles();
   376             if (files == null)
   343             if (files == null)
   379             for (File f: files) {
   346             for (File f: files) {
   380                 String fname = f.getName();
   347                 String fname = f.getName();
   381                 if (f.isDirectory()) {
   348                 if (f.isDirectory()) {
   382                     if (recurse && SourceVersion.isIdentifier(fname)) {
   349                     if (recurse && SourceVersion.isIdentifier(fname)) {
   383                         listDirectory(directory,
   350                         listDirectory(directory,
   384                                       subdirectory + File.separator + fname,
   351                                       new RelativeDirectory(subdirectory, fname),
   385                                       fileKinds,
   352                                       fileKinds,
   386                                       recurse,
   353                                       recurse,
   387                                       l);
   354                                       l);
   388                     }
   355                     }
   389                 } else {
   356                 } else {
   409 
   376 
   410     /** Hack to make Windows case sensitive. Test whether given path
   377     /** Hack to make Windows case sensitive. Test whether given path
   411      *  ends in a string of characters with the same case as given name.
   378      *  ends in a string of characters with the same case as given name.
   412      *  Ignore file separators in both path and name.
   379      *  Ignore file separators in both path and name.
   413      */
   380      */
   414     private boolean caseMapCheck(File f, String name) {
   381     private boolean caseMapCheck(File f, RelativePath name) {
   415         if (fileSystemIsCaseSensitive) return true;
   382         if (fileSystemIsCaseSensitive) return true;
   416         // Note that getCanonicalPath() returns the case-sensitive
   383         // Note that getCanonicalPath() returns the case-sensitive
   417         // spelled file name.
   384         // spelled file name.
   418         String path;
   385         String path;
   419         try {
   386         try {
   420             path = f.getCanonicalPath();
   387             path = f.getCanonicalPath();
   421         } catch (IOException ex) {
   388         } catch (IOException ex) {
   422             return false;
   389             return false;
   423         }
   390         }
   424         char[] pcs = path.toCharArray();
   391         char[] pcs = path.toCharArray();
   425         char[] ncs = name.toCharArray();
   392         char[] ncs = name.path.toCharArray();
   426         int i = pcs.length - 1;
   393         int i = pcs.length - 1;
   427         int j = ncs.length - 1;
   394         int j = ncs.length - 1;
   428         while (i >= 0 && j >= 0) {
   395         while (i >= 0 && j >= 0) {
   429             while (i >= 0 && pcs[i] == File.separatorChar) i--;
   396             while (i >= 0 && pcs[i] == File.separatorChar) i--;
   430             while (j >= 0 && ncs[j] == File.separatorChar) j--;
   397             while (j >= 0 && ncs[j] == '/') j--;
   431             if (i >= 0 && j >= 0) {
   398             if (i >= 0 && j >= 0) {
   432                 if (pcs[i] != ncs[j]) return false;
   399                 if (pcs[i] != ncs[j]) return false;
   433                 i--;
   400                 i--;
   434                 j--;
   401                 j--;
   435             }
   402             }
   442      * mapping directory names to lists of files (basenames).
   409      * mapping directory names to lists of files (basenames).
   443      */
   410      */
   444     public interface Archive {
   411     public interface Archive {
   445         void close() throws IOException;
   412         void close() throws IOException;
   446 
   413 
   447         boolean contains(String name);
   414         boolean contains(RelativePath name);
   448 
   415 
   449         JavaFileObject getFileObject(String subdirectory, String file);
   416         JavaFileObject getFileObject(RelativeDirectory subdirectory, String file);
   450 
   417 
   451         List<String> getFiles(String subdirectory);
   418         List<String> getFiles(RelativeDirectory subdirectory);
   452 
   419 
   453         Set<String> getSubdirectories();
   420         Set<RelativeDirectory> getSubdirectories();
   454     }
   421     }
   455 
   422 
   456     public class MissingArchive implements Archive {
   423     public class MissingArchive implements Archive {
   457         final File zipFileName;
   424         final File zipFileName;
   458         public MissingArchive(File name) {
   425         public MissingArchive(File name) {
   459             zipFileName = name;
   426             zipFileName = name;
   460         }
   427         }
   461         public boolean contains(String name) {
   428         public boolean contains(RelativePath name) {
   462             return false;
   429             return false;
   463         }
   430         }
   464 
   431 
   465         public void close() {
   432         public void close() {
   466         }
   433         }
   467 
   434 
   468         public JavaFileObject getFileObject(String subdirectory, String file) {
   435         public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
   469             return null;
   436             return null;
   470         }
   437         }
   471 
   438 
   472         public List<String> getFiles(String subdirectory) {
   439         public List<String> getFiles(RelativeDirectory subdirectory) {
   473             return List.nil();
   440             return List.nil();
   474         }
   441         }
   475 
   442 
   476         public Set<String> getSubdirectories() {
   443         public Set<RelativeDirectory> getSubdirectories() {
   477             return Collections.emptySet();
   444             return Collections.emptySet();
   478         }
   445         }
       
   446 
       
   447         public String toString() {
       
   448             return "MissingArchive[" + zipFileName + "]";
       
   449         }
   479     }
   450     }
   480 
   451 
   481     /** A directory of zip files already opened.
   452     /** A directory of zip files already opened.
   482      */
   453      */
   483     Map<File, Archive> archives = new HashMap<File,Archive>();
   454     Map<File, Archive> archives = new HashMap<File,Archive>();
       
   455 
       
   456     private static final String[] symbolFileLocation = { "lib", "ct.sym" };
       
   457     private static final RelativeDirectory symbolFilePrefix
       
   458             = new RelativeDirectory("META-INF/sym/rt.jar/");
   484 
   459 
   485     /** Open a new zip file directory.
   460     /** Open a new zip file directory.
   486      */
   461      */
   487     protected Archive openArchive(File zipFileName) throws IOException {
   462     protected Archive openArchive(File zipFileName) throws IOException {
   488         Archive archive = archives.get(zipFileName);
   463         Archive archive = archives.get(zipFileName);
   538 
   513 
   539                 if (origZipFileName == zipFileName) {
   514                 if (origZipFileName == zipFileName) {
   540                     if (!useZipFileIndex) {
   515                     if (!useZipFileIndex) {
   541                         archive = new ZipArchive(this, zdir);
   516                         archive = new ZipArchive(this, zdir);
   542                     } else {
   517                     } else {
   543                         archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, null,
   518                         archive = new ZipFileIndexArchive(this,
   544                                 usePreindexedCache, preindexCacheLocation, options.get("writezipindexfiles") != null));
   519                                 ZipFileIndex.getZipFileIndex(zipFileName,
       
   520                                     null,
       
   521                                     usePreindexedCache,
       
   522                                     preindexCacheLocation,
       
   523                                     options.get("writezipindexfiles") != null));
   545                     }
   524                     }
   546                 }
   525                 }
   547                 else {
   526                 else {
   548                     if (!useZipFileIndex) {
   527                     if (!useZipFileIndex) {
   549                         archive = new SymbolArchive(this, origZipFileName, zdir, symbolFilePrefix);
   528                         archive = new SymbolArchive(this, origZipFileName, zdir, symbolFilePrefix);
   550                     }
   529                     }
   551                     else {
   530                     else {
   552                         archive = new ZipFileIndexArchive(this,
   531                         archive = new ZipFileIndexArchive(this,
   553                                 ZipFileIndex.getZipFileIndex(zipFileName,
   532                                 ZipFileIndex.getZipFileIndex(zipFileName,
   554                                 symbolFilePrefix,
   533                                     symbolFilePrefix,
   555                                 usePreindexedCache,
   534                                     usePreindexedCache,
   556                                 preindexCacheLocation,
   535                                     preindexCacheLocation,
   557                                 options.get("writezipindexfiles") != null));
   536                                     options.get("writezipindexfiles") != null));
   558                     }
   537                     }
   559                 }
   538                 }
   560             } catch (FileNotFoundException ex) {
   539             } catch (FileNotFoundException ex) {
   561                 archive = new MissingArchive(zipFileName);
   540                 archive = new MissingArchive(zipFileName);
   562             } catch (IOException ex) {
   541             } catch (IOException ex) {
   794         nullCheck(kinds);
   773         nullCheck(kinds);
   795 
   774 
   796         Iterable<? extends File> path = getLocation(location);
   775         Iterable<? extends File> path = getLocation(location);
   797         if (path == null)
   776         if (path == null)
   798             return List.nil();
   777             return List.nil();
   799         String subdirectory = externalizeFileName(packageName);
   778         RelativeDirectory subdirectory = RelativeDirectory.forPackage(packageName);
   800         ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
   779         ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
   801 
   780 
   802         for (File directory : path)
   781         for (File directory : path)
   803             listDirectory(directory, subdirectory, kinds, recurse, results);
   782             listDirectory(directory, subdirectory, kinds, recurse, results);
   804 
   783 
   875         // validateClassName(className);
   854         // validateClassName(className);
   876         nullCheck(className);
   855         nullCheck(className);
   877         nullCheck(kind);
   856         nullCheck(kind);
   878         if (!sourceOrClass.contains(kind))
   857         if (!sourceOrClass.contains(kind))
   879             throw new IllegalArgumentException("Invalid kind " + kind);
   858             throw new IllegalArgumentException("Invalid kind " + kind);
   880         return getFileForInput(location, externalizeFileName(className, kind));
   859         return getFileForInput(location, RelativeFile.forClass(className, kind));
   881     }
   860     }
   882 
   861 
   883     public FileObject getFileForInput(Location location,
   862     public FileObject getFileForInput(Location location,
   884                                       String packageName,
   863                                       String packageName,
   885                                       String relativeName)
   864                                       String relativeName)
   888         nullCheck(location);
   867         nullCheck(location);
   889         // validatePackageName(packageName);
   868         // validatePackageName(packageName);
   890         nullCheck(packageName);
   869         nullCheck(packageName);
   891         if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
   870         if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
   892             throw new IllegalArgumentException("Invalid relative name: " + relativeName);
   871             throw new IllegalArgumentException("Invalid relative name: " + relativeName);
   893         String name = packageName.length() == 0
   872         RelativeFile name = packageName.length() == 0
   894             ? relativeName
   873             ? new RelativeFile(relativeName)
   895             : new File(externalizeFileName(packageName), relativeName).getPath();
   874             : new RelativeFile(RelativeDirectory.forPackage(packageName), relativeName);
   896         return getFileForInput(location, name);
   875         return getFileForInput(location, name);
   897     }
   876     }
   898 
   877 
   899     private JavaFileObject getFileForInput(Location location, String name) throws IOException {
   878     private JavaFileObject getFileForInput(Location location, RelativeFile name) throws IOException {
   900         Iterable<? extends File> path = getLocation(location);
   879         Iterable<? extends File> path = getLocation(location);
   901         if (path == null)
   880         if (path == null)
   902             return null;
   881             return null;
   903 
   882 
   904         for (File dir: path) {
   883         for (File dir: path) {
   905             if (dir.isDirectory()) {
   884             if (dir.isDirectory()) {
   906                 File f = new File(dir, name.replace('/', File.separatorChar));
   885                 File f = name.getFile(dir);
   907                 if (f.exists())
   886                 if (f.exists())
   908                     return new RegularFileObject(this, f);
   887                     return new RegularFileObject(this, f);
   909             } else {
   888             } else {
   910                 Archive a = openArchive(dir);
   889                 Archive a = openArchive(dir);
   911                 if (a.contains(name)) {
   890                 if (a.contains(name)) {
   912                     int i = name.lastIndexOf('/');
   891                     return a.getFileObject(name.dirname(), name.basename());
   913                     String dirname = name.substring(0, i+1);
   892                 }
   914                     String basename = name.substring(i+1);
   893 
   915                     return a.getFileObject(dirname, basename);
   894             }
   916                 }
   895         }
   917 
   896 
   918             }
       
   919         }
       
   920         return null;
   897         return null;
   921 
       
   922     }
   898     }
   923 
   899 
   924     public JavaFileObject getJavaFileForOutput(Location location,
   900     public JavaFileObject getJavaFileForOutput(Location location,
   925                                                String className,
   901                                                String className,
   926                                                JavaFileObject.Kind kind,
   902                                                JavaFileObject.Kind kind,
   931         // validateClassName(className);
   907         // validateClassName(className);
   932         nullCheck(className);
   908         nullCheck(className);
   933         nullCheck(kind);
   909         nullCheck(kind);
   934         if (!sourceOrClass.contains(kind))
   910         if (!sourceOrClass.contains(kind))
   935             throw new IllegalArgumentException("Invalid kind " + kind);
   911             throw new IllegalArgumentException("Invalid kind " + kind);
   936         return getFileForOutput(location, externalizeFileName(className, kind), sibling);
   912         return getFileForOutput(location, RelativeFile.forClass(className, kind), sibling);
   937     }
   913     }
   938 
   914 
   939     public FileObject getFileForOutput(Location location,
   915     public FileObject getFileForOutput(Location location,
   940                                        String packageName,
   916                                        String packageName,
   941                                        String relativeName,
   917                                        String relativeName,
   945         nullCheck(location);
   921         nullCheck(location);
   946         // validatePackageName(packageName);
   922         // validatePackageName(packageName);
   947         nullCheck(packageName);
   923         nullCheck(packageName);
   948         if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
   924         if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
   949             throw new IllegalArgumentException("relativeName is invalid");
   925             throw new IllegalArgumentException("relativeName is invalid");
   950         String name = packageName.length() == 0
   926         RelativeFile name = packageName.length() == 0
   951             ? relativeName
   927             ? new RelativeFile(relativeName)
   952             : new File(externalizeFileName(packageName), relativeName).getPath();
   928             : new RelativeFile(RelativeDirectory.forPackage(packageName), relativeName);
   953         return getFileForOutput(location, name, sibling);
   929         return getFileForOutput(location, name, sibling);
   954     }
   930     }
   955 
   931 
   956     private JavaFileObject getFileForOutput(Location location,
   932     private JavaFileObject getFileForOutput(Location location,
   957                                             String fileName,
   933                                             RelativeFile fileName,
   958                                             FileObject sibling)
   934                                             FileObject sibling)
   959         throws IOException
   935         throws IOException
   960     {
   936     {
   961         File dir;
   937         File dir;
   962         if (location == CLASS_OUTPUT) {
   938         if (location == CLASS_OUTPUT) {
   965             } else {
   941             } else {
   966                 File siblingDir = null;
   942                 File siblingDir = null;
   967                 if (sibling != null && sibling instanceof RegularFileObject) {
   943                 if (sibling != null && sibling instanceof RegularFileObject) {
   968                     siblingDir = ((RegularFileObject)sibling).f.getParentFile();
   944                     siblingDir = ((RegularFileObject)sibling).f.getParentFile();
   969                 }
   945                 }
   970                 return new RegularFileObject(this, new File(siblingDir, baseName(fileName)));
   946                 return new RegularFileObject(this, new File(siblingDir, fileName.basename()));
   971             }
   947             }
   972         } else if (location == SOURCE_OUTPUT) {
   948         } else if (location == SOURCE_OUTPUT) {
   973             dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
   949             dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
   974         } else {
   950         } else {
   975             Iterable<? extends File> path = paths.getPathForLocation(location);
   951             Iterable<? extends File> path = paths.getPathForLocation(location);
   978                 dir = f;
   954                 dir = f;
   979                 break;
   955                 break;
   980             }
   956             }
   981         }
   957         }
   982 
   958 
   983         File file = (dir == null ? new File(fileName) : new File(dir, fileName));
   959         File file = fileName.getFile(dir); // null-safe
   984         return new RegularFileObject(this, file);
   960         return new RegularFileObject(this, file);
   985 
   961 
   986     }
   962     }
   987 
   963 
   988     public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(
   964     public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(