5353import java .util .jar .Manifest ;
5454import java .util .Enumeration ;
5555import java .io .IOException ;
56+ import java .io .FileNotFoundException ;
5657
57- import edu .rice .cs .plt .iter .IterUtil ;
5858import edu .rice .cs .plt .io .IOUtil ;
59- import edu .rice .cs .plt .lambda .Lambda3 ;
59+ import edu .rice .cs .plt .iter .IterUtil ;
60+ import edu .rice .cs .plt .lambda .Lambda ;
6061import edu .rice .cs .plt .lambda .LambdaUtil ;
6162import edu .rice .cs .plt .lambda .Predicate ;
6263import edu .rice .cs .plt .reflect .ReflectUtil ;
@@ -153,8 +154,16 @@ public static JarJDKToolsLibrary makeFromFile(File f, GlobalModel model, JDKDesc
153154 JDKToolsLibrary .msg ("\t desc = " +desc );
154155
155156 boolean isSupported = JavaVersion .CURRENT .supports (version .majorVersion ());
157+ Iterable <File > additionalCompilerFiles = IterUtil .empty ();
156158 if (desc !=null ) {
157159 isSupported |= JavaVersion .CURRENT .supports (desc .getMinimumMajorVersion ());
160+ try {
161+ additionalCompilerFiles = desc .getAdditionalCompilerFiles (f );
162+ }
163+ catch (FileNotFoundException fnfe ) {
164+ // not all additional compiler files were found
165+ isSupported = false ;
166+ }
158167 }
159168
160169 // We can't execute code that was possibly compiled for a later Java API version.
@@ -163,7 +172,9 @@ public static JarJDKToolsLibrary makeFromFile(File f, GlobalModel model, JDKDesc
163172 // block tools.jar classes, so that references don't point to a different version of the classes
164173 ClassLoader loader =
165174 new ShadowingClassLoader (JarJDKToolsLibrary .class .getClassLoader (), true , TOOLS_PACKAGES , true );
166- Iterable <File > path = IterUtil .singleton (IOUtil .attemptAbsoluteFile (f ));
175+ Iterable <File > path = IterUtil .map (IterUtil .compose (additionalCompilerFiles , f ), new Lambda <File ,File >() {
176+ public File value (File arg ) { return IOUtil .attemptAbsoluteFile (arg ); }
177+ });
167178
168179 String compilerAdapter = adapterForCompiler (version );
169180 if (desc !=null ) {
@@ -335,12 +346,13 @@ else if (jf.getJarEntry("com/sun/tools/javac/util/DefaultFileManager.class")!=nu
335346 return result ;
336347 }
337348
338- /** Produce a list of tools libraries discovered on the file system. A variety of locations are searched;
339- * only those files that can produce a valid library (see {@link #isValid} are returned. The result is
340- * sorted by version. Where one library of the same version might be preferred over another, the preferred
341- * library appears earlier in the result list.
342- */
343- public static Iterable <JarJDKToolsLibrary > search (GlobalModel model ) {
349+ /** return a collection with the default roots. */
350+ protected static LinkedHashMap <File ,Set <JDKDescriptor >> getDefaultSearchRoots () {
351+ /* roots is a list of possible parent directories of Java installations; we want to eliminate duplicates &
352+ * remember insertion order
353+ */
354+ LinkedHashMap <File ,Set <JDKDescriptor >> roots = new LinkedHashMap <File ,Set <JDKDescriptor >>();
355+
344356 String javaHome = System .getProperty ("java.home" );
345357 String envJavaHome = null ;
346358 String programFiles = null ;
@@ -352,12 +364,7 @@ public static Iterable<JarJDKToolsLibrary> search(GlobalModel model) {
352364 programFiles = System .getenv ("ProgramFiles" );
353365 systemDrive = System .getenv ("SystemDrive" );
354366 }
355-
356- /* roots is a list of possible parent directories of Java installations; we want to eliminate duplicates &
357- * remember insertion order
358- */
359- LinkedHashMap <File ,Set <JDKDescriptor >> roots = new LinkedHashMap <File ,Set <JDKDescriptor >>();
360-
367+
361368 if (javaHome != null ) {
362369 addIfDir (new File (javaHome ), null , roots );
363370 addIfDir (new File (javaHome , ".." ), null , roots );
@@ -398,22 +405,13 @@ public static Iterable<JarJDKToolsLibrary> search(GlobalModel model) {
398405 addIfDir (new File ("/usr/lib/jvm/java-6-openjdk" ), null , roots );
399406
400407 addIfDir (new File ("/home/javaplt/java/Linux-i686" ), null , roots );
401-
402- /* jars is a list of possible tools.jar (or classes.jar) files; we want to eliminate duplicates &
403- * remember insertion order
404- */
405- LinkedHashMap <File ,Set <JDKDescriptor >> jars = new LinkedHashMap <File ,Set <JDKDescriptor >>();
406-
407- // Search for all compound JDK descriptors in the drjava.jar file
408- Iterable <JDKDescriptor > descriptors = searchForJDKDescriptors ();
409- for (JDKDescriptor desc : descriptors ) {
410- // add the specific search directories and files
411- for (File f : desc .getSearchDirectories ()) { addIfDir (f , desc , roots ); }
412- for (File f : desc .getSearchFiles ()) { addIfFile (f , desc , jars ); }
413- // add to the set of packages that need to be shadowed
414- TOOLS_PACKAGES .addAll (desc .getToolsPackages ());
415- }
416408
409+ return roots ;
410+ }
411+
412+ /* Search for jar files in roots and, if found, transfer them to the jars collection. */
413+ protected static void searchRootsForJars (LinkedHashMap <File ,Set <JDKDescriptor >> roots ,
414+ LinkedHashMap <File ,Set <JDKDescriptor >> jars ) {
417415 // matches: starts with "j2sdk", starts with "jdk", has form "[number].[number].[number]" (OS X), or
418416 // starts with "java-" (Linux)
419417 Predicate <File > subdirFilter = LambdaUtil .or (IOUtil .regexCanonicalCaseFilePredicate ("j2sdk.*" ),
@@ -426,13 +424,13 @@ public static Iterable<JarJDKToolsLibrary> search(GlobalModel model) {
426424 addIfFile (new File (subdir , "Classes/classes.jar" ), root .getValue (), jars );
427425 }
428426 }
429-
430- // We store everything in reverse order, since that's the natural order of the versions
431- Map < FullVersion , Iterable < JarJDKToolsLibrary >> results =
432- new TreeMap < FullVersion , Iterable < JarJDKToolsLibrary >>();
433- Map < FullVersion , Iterable < JarJDKToolsLibrary >> compoundResults =
434- new TreeMap <FullVersion , Iterable <JarJDKToolsLibrary >>();
435-
427+ }
428+
429+ /** Check which jars are valid JDKs, and determine if they are compound or full (non-compound) JDKs. */
430+ protected static void collectValidResults ( GlobalModel model ,
431+ LinkedHashMap < File , Set < JDKDescriptor >> jars ,
432+ Map <FullVersion , Iterable <JarJDKToolsLibrary >> results ,
433+ Map < FullVersion , Iterable < JarJDKToolsLibrary >> compoundResults ) {
436434 for (Map .Entry <File ,Set <JDKDescriptor >> jar : jars .entrySet ()) {
437435 for (JDKDescriptor desc : jar .getValue ()) {
438436 if (desc !=null ) {
@@ -456,12 +454,17 @@ public static Iterable<JarJDKToolsLibrary> search(GlobalModel model) {
456454 }
457455 }
458456 }
459-
460- Iterable <JarJDKToolsLibrary > collapsed = IterUtil .reverse (IterUtil .collapse (results .values ()));
461- Iterable <JarJDKToolsLibrary > compoundCollapsed = IterUtil .reverse (IterUtil .collapse (compoundResults .values ()));
462-
463- Map <FullVersion , Iterable <JarJDKToolsLibrary >> allResults =
457+ }
458+
459+ /** Get completed compound JDKs by going through the list of compound JDKs and finding full JDKs that
460+ * complete them. */
461+ protected static Map <FullVersion , Iterable <JarJDKToolsLibrary >>
462+ getCompletedCompoundResults (GlobalModel model ,
463+ Iterable <JarJDKToolsLibrary > collapsed ,
464+ Iterable <JarJDKToolsLibrary > compoundCollapsed ) {
465+ Map <FullVersion , Iterable <JarJDKToolsLibrary >> completedResults =
464466 new TreeMap <FullVersion , Iterable <JarJDKToolsLibrary >>();
467+
465468 // now we have the JDK libraries in collapsed and the compound libraries in compoundCollapsed
466469 for (JarJDKToolsLibrary compoundLib : compoundCollapsed ) {
467470 JDKToolsLibrary .msg ("compoundLib: " +compoundLib .version ());
@@ -502,17 +505,71 @@ public static Iterable<JarJDKToolsLibrary> search(GlobalModel model) {
502505 if (lib .isValid ()) {
503506 JDKToolsLibrary .msg ("\t ==> " +lib .version ());
504507 FullVersion v = lib .version ();
505- if (allResults .containsKey (v )) { allResults .put (v , IterUtil .compose (lib , allResults .get (v ))); }
506- else { allResults .put (v , IterUtil .singleton (lib )); }
508+ if (completedResults .containsKey (v )) {
509+ completedResults .put (v , IterUtil .compose (lib , completedResults .get (v )));
510+ }
511+ else {
512+ completedResults .put (v , IterUtil .singleton (lib ));
513+ }
507514 }
508515 }
509516 }
517+ return completedResults ;
518+ }
519+
520+ /** Produce a list of tools libraries discovered on the file system. A variety of locations are searched;
521+ * only those files that can produce a valid library (see {@link #isValid} are returned. The result is
522+ * sorted by version. Where one library of the same version might be preferred over another, the preferred
523+ * library appears earlier in the result list.
524+ */
525+ public static Iterable <JarJDKToolsLibrary > search (GlobalModel model ) {
526+ /* roots is a list of possible parent directories of Java installations; we want to eliminate duplicates &
527+ * remember insertion order
528+ */
529+ LinkedHashMap <File ,Set <JDKDescriptor >> roots = getDefaultSearchRoots ();
530+
531+ /* jars is a list of possible tools.jar (or classes.jar) files; we want to eliminate duplicates &
532+ * remember insertion order
533+ */
534+ LinkedHashMap <File ,Set <JDKDescriptor >> jars = new LinkedHashMap <File ,Set <JDKDescriptor >>();
535+
536+ // Search for all compound JDK descriptors in the drjava.jar file
537+ Iterable <JDKDescriptor > descriptors = searchForJDKDescriptors ();
538+ for (JDKDescriptor desc : descriptors ) {
539+ // add the specific search directories and files
540+ for (File f : desc .getSearchDirectories ()) { addIfDir (f , desc , roots ); }
541+ for (File f : desc .getSearchFiles ()) { addIfFile (f , desc , jars ); }
542+ // add to the set of packages that need to be shadowed
543+ TOOLS_PACKAGES .addAll (desc .getToolsPackages ());
544+ }
545+
546+ // search for jar files in roots and, if found, transfer them to the jars collection
547+ searchRootsForJars (roots , jars );
548+
549+ // check which jars are valid JDKs, and determine if they are compound or full (non-compound) JDKs
550+ Map <FullVersion , Iterable <JarJDKToolsLibrary >> results =
551+ new TreeMap <FullVersion , Iterable <JarJDKToolsLibrary >>();
552+ Map <FullVersion , Iterable <JarJDKToolsLibrary >> compoundResults =
553+ new TreeMap <FullVersion , Iterable <JarJDKToolsLibrary >>();
554+
555+ collectValidResults (model , jars , results , compoundResults );
556+
557+ // We store everything in reverse order, since that's the natural order of the versions
558+ Iterable <JarJDKToolsLibrary > collapsed = IterUtil .reverse (IterUtil .collapse (results .values ()));
559+ Iterable <JarJDKToolsLibrary > compoundCollapsed = IterUtil .reverse (IterUtil .collapse (compoundResults .values ()));
560+
561+ // Get completed compound JDKs by going through the list of compound JDKs and finding full JDKs that
562+ // complete them
563+ Map <FullVersion , Iterable <JarJDKToolsLibrary >> completedResults =
564+ getCompletedCompoundResults (model , collapsed , compoundCollapsed );
565+
510566 JDKToolsLibrary .msg ("Result:" );
511567 Iterable <JarJDKToolsLibrary > result = IterUtil .
512- compose (collapsed ,IterUtil .reverse (IterUtil .collapse (allResults .values ())));
568+ compose (collapsed ,IterUtil .reverse (IterUtil .collapse (completedResults .values ())));
513569 for (JarJDKToolsLibrary lib : result ) {
514570 JDKToolsLibrary .msg ("Found library: " +lib );
515571 }
572+
516573 return result ;
517574 }
518575
0 commit comments