langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
changeset 24604 7f68545b5128
parent 24403 f2ce14657001
child 24606 12c0ca21f8dc
equal deleted inserted replaced
24603:43e7e44d63da 24604:7f68545b5128
    33 import java.util.EnumSet;
    33 import java.util.EnumSet;
    34 import java.util.HashMap;
    34 import java.util.HashMap;
    35 import java.util.HashSet;
    35 import java.util.HashSet;
    36 import java.util.Map;
    36 import java.util.Map;
    37 import java.util.Set;
    37 import java.util.Set;
    38 import javax.lang.model.SourceVersion;
       
    39 import javax.tools.JavaFileObject;
    38 import javax.tools.JavaFileObject;
    40 import javax.tools.JavaFileManager;
    39 import javax.tools.JavaFileManager;
    41 import javax.tools.JavaFileManager.Location;
       
    42 import javax.tools.StandardJavaFileManager;
       
    43 
       
    44 import static javax.tools.StandardLocation.*;
       
    45 
    40 
    46 import com.sun.tools.javac.comp.Annotate;
    41 import com.sun.tools.javac.comp.Annotate;
    47 import com.sun.tools.javac.code.*;
    42 import com.sun.tools.javac.code.*;
    48 import com.sun.tools.javac.code.Lint.LintCategory;
    43 import com.sun.tools.javac.code.Lint.LintCategory;
    49 import com.sun.tools.javac.code.Type.*;
    44 import com.sun.tools.javac.code.Type.*;
   118     /** Switch: preserve parameter names from the variable table.
   113     /** Switch: preserve parameter names from the variable table.
   119      */
   114      */
   120     public boolean saveParameterNames;
   115     public boolean saveParameterNames;
   121 
   116 
   122     /**
   117     /**
   123      * Switch: cache completion failures unless -XDdev is used
       
   124      */
       
   125     private boolean cacheCompletionFailure;
       
   126 
       
   127     /**
       
   128      * Switch: prefer source files instead of newer when both source
       
   129      * and class are available
       
   130      **/
       
   131     public boolean preferSource;
       
   132 
       
   133     /**
       
   134      * Switch: Search classpath and sourcepath for classes before the
       
   135      * bootclasspath
       
   136      */
       
   137     public boolean userPathsFirst;
       
   138 
       
   139     /**
       
   140      * The currently selected profile.
   118      * The currently selected profile.
   141      */
   119      */
   142     public final Profile profile;
   120     public final Profile profile;
   143 
   121 
   144     /** The log to use for verbose output
   122     /** The log to use for verbose output
   151     Types types;
   129     Types types;
   152 
   130 
   153     /** The name table. */
   131     /** The name table. */
   154     final Names names;
   132     final Names names;
   155 
   133 
   156     /** Force a completion failure on this name
       
   157      */
       
   158     final Name completionFailureName;
       
   159 
       
   160     /** Access to files
   134     /** Access to files
   161      */
   135      */
   162     private final JavaFileManager fileManager;
   136     private final JavaFileManager fileManager;
   163 
   137 
   164     /** Factory for diagnostics
   138     /** Factory for diagnostics
   165      */
   139      */
   166     JCDiagnostic.Factory diagFactory;
   140     JCDiagnostic.Factory diagFactory;
   167 
       
   168     /** Can be reassigned from outside:
       
   169      *  the completer to be used for ".java" files. If this remains unassigned
       
   170      *  ".java" files will not be loaded.
       
   171      */
       
   172     public SourceCompleter sourceCompleter = null;
       
   173 
   141 
   174     /** The current scope where type variables are entered.
   142     /** The current scope where type variables are entered.
   175      */
   143      */
   176     protected Scope typevars;
   144     protected Scope typevars;
   177 
   145 
   224 
   192 
   225     /**
   193     /**
   226      * The set of attribute names for which warnings have been generated for the current class
   194      * The set of attribute names for which warnings have been generated for the current class
   227      */
   195      */
   228     Set<Name> warnedAttrs = new HashSet<>();
   196     Set<Name> warnedAttrs = new HashSet<>();
   229 
       
   230     /**
       
   231      * Completer that delegates to the complete-method of this class.
       
   232      */
       
   233     private final Completer thisCompleter = new Completer() {
       
   234         @Override
       
   235         public void complete(Symbol sym) throws CompletionFailure {
       
   236             ClassReader.this.complete(sym);
       
   237         }
       
   238     };
       
   239 
       
   240     public Completer getCompleter() {
       
   241         return thisCompleter;
       
   242     }
       
   243 
   197 
   244     /** Get the ClassReader instance for this invocation. */
   198     /** Get the ClassReader instance for this invocation. */
   245     public static ClassReader instance(Context context) {
   199     public static ClassReader instance(Context context) {
   246         ClassReader instance = context.get(classReaderKey);
   200         ClassReader instance = context.get(classReaderKey);
   247         if (instance == null)
   201         if (instance == null)
   272         allowVarargs     = source.allowVarargs();
   226         allowVarargs     = source.allowVarargs();
   273         allowAnnotations = source.allowAnnotations();
   227         allowAnnotations = source.allowAnnotations();
   274         allowSimplifiedVarargs = source.allowSimplifiedVarargs();
   228         allowSimplifiedVarargs = source.allowSimplifiedVarargs();
   275 
   229 
   276         saveParameterNames = options.isSet("save-parameter-names");
   230         saveParameterNames = options.isSet("save-parameter-names");
   277         cacheCompletionFailure = options.isUnset("dev");
       
   278         preferSource = "source".equals(options.get("-Xprefer"));
       
   279         userPathsFirst = options.isSet(XXUSERPATHSFIRST);
       
   280 
   231 
   281         profile = Profile.instance(context);
   232         profile = Profile.instance(context);
   282 
       
   283         completionFailureName =
       
   284             options.isSet("failcomplete")
       
   285             ? names.fromString(options.get("failcomplete"))
       
   286             : null;
       
   287 
   233 
   288         typevars = new Scope(syms.noSymbol);
   234         typevars = new Scope(syms.noSymbol);
   289 
   235 
   290         lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
   236         lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
   291 
   237 
   303 
   249 
   304 /************************************************************************
   250 /************************************************************************
   305  * Error Diagnoses
   251  * Error Diagnoses
   306  ***********************************************************************/
   252  ***********************************************************************/
   307 
   253 
   308 
   254     public ClassFinder.BadClassFile badClassFile(String key, Object... args) {
   309     public class BadClassFile extends CompletionFailure {
   255         return new ClassFinder.BadClassFile (
   310         private static final long serialVersionUID = 0;
       
   311 
       
   312         public BadClassFile(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag) {
       
   313             super(sym, createBadClassFileDiagnostic(file, diag));
       
   314         }
       
   315     }
       
   316     // where
       
   317     private JCDiagnostic createBadClassFileDiagnostic(JavaFileObject file, JCDiagnostic diag) {
       
   318         String key = (file.getKind() == JavaFileObject.Kind.SOURCE
       
   319                     ? "bad.source.file.header" : "bad.class.file.header");
       
   320         return diagFactory.fragment(key, file, diag);
       
   321     }
       
   322 
       
   323     public BadClassFile badClassFile(String key, Object... args) {
       
   324         return new BadClassFile (
       
   325             currentOwner.enclClass(),
   256             currentOwner.enclClass(),
   326             currentClassFile,
   257             currentClassFile,
   327             diagFactory.fragment(key, args));
   258             diagFactory.fragment(key, args),
       
   259             diagFactory);
   328     }
   260     }
   329 
   261 
   330 /************************************************************************
   262 /************************************************************************
   331  * Buffer Access
   263  * Buffer Access
   332  ***********************************************************************/
   264  ***********************************************************************/
  1499 
  1431 
  1500     TypeAnnotationPosition readPosition() {
  1432     TypeAnnotationPosition readPosition() {
  1501         int tag = nextByte(); // TargetType tag is a byte
  1433         int tag = nextByte(); // TargetType tag is a byte
  1502 
  1434 
  1503         if (!TargetType.isValidTargetTypeValue(tag))
  1435         if (!TargetType.isValidTargetTypeValue(tag))
  1504             throw this.badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
  1436             throw badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
  1505 
  1437 
  1506         TargetType type = TargetType.fromTargetTypeValue(tag);
  1438         TargetType type = TargetType.fromTargetTypeValue(tag);
  1507 
  1439 
  1508         switch (type) {
  1440         switch (type) {
  1509         // instanceof
  1441         // instanceof
  2351                 }
  2283                 }
  2352             }
  2284             }
  2353         }
  2285         }
  2354     }
  2286     }
  2355 
  2287 
  2356     /** Read a class file.
  2288     /** Read a class definition from the bytes in buf.
  2357      */
  2289      */
  2358     private void readClassFile(ClassSymbol c) throws IOException {
  2290     private void readClassBuffer(ClassSymbol c) throws IOException {
  2359         int magic = nextInt();
  2291         int magic = nextInt();
  2360         if (magic != JAVA_MAGIC)
  2292         if (magic != JAVA_MAGIC)
  2361             throw badClassFile("illegal.start.of.class.file");
  2293             throw badClassFile("illegal.start.of.class.file");
  2362 
  2294 
  2363         minorVersion = nextChar();
  2295         minorVersion = nextChar();
  2393             signatureBuffer = new byte[ns];
  2325             signatureBuffer = new byte[ns];
  2394         }
  2326         }
  2395         readClass(c);
  2327         readClass(c);
  2396     }
  2328     }
  2397 
  2329 
  2398 /************************************************************************
  2330     public void readClassFile(ClassSymbol c) {
  2399  * Adjusting flags
       
  2400  ***********************************************************************/
       
  2401 
       
  2402     long adjustFieldFlags(long flags) {
       
  2403         return flags;
       
  2404     }
       
  2405     long adjustMethodFlags(long flags) {
       
  2406         if ((flags & ACC_BRIDGE) != 0) {
       
  2407             flags &= ~ACC_BRIDGE;
       
  2408             flags |= BRIDGE;
       
  2409             if (!allowGenerics)
       
  2410                 flags &= ~SYNTHETIC;
       
  2411         }
       
  2412         if ((flags & ACC_VARARGS) != 0) {
       
  2413             flags &= ~ACC_VARARGS;
       
  2414             flags |= VARARGS;
       
  2415         }
       
  2416         return flags;
       
  2417     }
       
  2418     long adjustClassFlags(long flags) {
       
  2419         return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
       
  2420     }
       
  2421 
       
  2422 /************************************************************************
       
  2423  * Loading Classes
       
  2424  ***********************************************************************/
       
  2425 
       
  2426     /** Completion for classes to be loaded. Before a class is loaded
       
  2427      *  we make sure its enclosing class (if any) is loaded.
       
  2428      */
       
  2429     private void complete(Symbol sym) throws CompletionFailure {
       
  2430         if (sym.kind == TYP) {
       
  2431             ClassSymbol c = (ClassSymbol)sym;
       
  2432             c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
       
  2433             annotate.enterStart();
       
  2434             try {
       
  2435                 completeOwners(c.owner);
       
  2436                 completeEnclosing(c);
       
  2437             } finally {
       
  2438                 // The flush needs to happen only after annotations
       
  2439                 // are filled in.
       
  2440                 annotate.enterDoneWithoutFlush();
       
  2441             }
       
  2442             fillIn(c);
       
  2443         } else if (sym.kind == PCK) {
       
  2444             PackageSymbol p = (PackageSymbol)sym;
       
  2445             try {
       
  2446                 fillIn(p);
       
  2447             } catch (IOException ex) {
       
  2448                 throw new CompletionFailure(sym, ex.getLocalizedMessage()).initCause(ex);
       
  2449             }
       
  2450         }
       
  2451         if (!filling)
       
  2452             annotate.flush(); // finish attaching annotations
       
  2453     }
       
  2454 
       
  2455     /** complete up through the enclosing package. */
       
  2456     private void completeOwners(Symbol o) {
       
  2457         if (o.kind != PCK) completeOwners(o.owner);
       
  2458         o.complete();
       
  2459     }
       
  2460 
       
  2461     /**
       
  2462      * Tries to complete lexically enclosing classes if c looks like a
       
  2463      * nested class.  This is similar to completeOwners but handles
       
  2464      * the situation when a nested class is accessed directly as it is
       
  2465      * possible with the Tree API or javax.lang.model.*.
       
  2466      */
       
  2467     private void completeEnclosing(ClassSymbol c) {
       
  2468         if (c.owner.kind == PCK) {
       
  2469             Symbol owner = c.owner;
       
  2470             for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) {
       
  2471                 Symbol encl = owner.members().lookup(name).sym;
       
  2472                 if (encl == null)
       
  2473                     encl = syms.classes.get(TypeSymbol.formFlatName(name, owner));
       
  2474                 if (encl != null)
       
  2475                     encl.complete();
       
  2476             }
       
  2477         }
       
  2478     }
       
  2479 
       
  2480     /** We can only read a single class file at a time; this
       
  2481      *  flag keeps track of when we are currently reading a class
       
  2482      *  file.
       
  2483      */
       
  2484     private boolean filling = false;
       
  2485 
       
  2486     /** Fill in definition of class `c' from corresponding class or
       
  2487      *  source file.
       
  2488      */
       
  2489     private void fillIn(ClassSymbol c) {
       
  2490         if (completionFailureName == c.fullname) {
       
  2491             throw new CompletionFailure(c, "user-selected completion failure by class name");
       
  2492         }
       
  2493         currentOwner = c;
  2331         currentOwner = c;
       
  2332         currentClassFile = c.classfile;
  2494         warnedAttrs.clear();
  2333         warnedAttrs.clear();
  2495         JavaFileObject classfile = c.classfile;
  2334         filling = true;
  2496         if (classfile != null) {
  2335         try {
  2497             JavaFileObject previousClassFile = currentClassFile;
  2336             bp = 0;
  2498             try {
  2337             buf = readInputStream(buf, c.classfile.openInputStream());
  2499                 if (filling) {
  2338             readClassBuffer(c);
  2500                     Assert.error("Filling " + classfile.toUri() + " during " + previousClassFile);
  2339             if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
  2501                 }
  2340                 List<Type> missing = missingTypeVariables;
  2502                 currentClassFile = classfile;
  2341                 List<Type> found = foundTypeVariables;
  2503                 if (verbose) {
  2342                 missingTypeVariables = List.nil();
  2504                     log.printVerbose("loading", currentClassFile.toString());
  2343                 foundTypeVariables = List.nil();
  2505                 }
  2344                 filling = false;
  2506                 if (classfile.getKind() == JavaFileObject.Kind.CLASS) {
  2345                 ClassType ct = (ClassType)currentOwner.type;
  2507                     filling = true;
  2346                 ct.supertype_field =
  2508                     try {
  2347                     types.subst(ct.supertype_field, missing, found);
  2509                         bp = 0;
  2348                 ct.interfaces_field =
  2510                         buf = readInputStream(buf, classfile.openInputStream());
  2349                     types.subst(ct.interfaces_field, missing, found);
  2511                         readClassFile(c);
  2350             } else if (missingTypeVariables.isEmpty() !=
  2512                         if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
  2351                        foundTypeVariables.isEmpty()) {
  2513                             List<Type> missing = missingTypeVariables;
  2352                 Name name = missingTypeVariables.head.tsym.name;
  2514                             List<Type> found = foundTypeVariables;
  2353                 throw badClassFile("undecl.type.var", name);
  2515                             missingTypeVariables = List.nil();
  2354             }
  2516                             foundTypeVariables = List.nil();
  2355         } catch (IOException ex) {
  2517                             filling = false;
  2356             throw badClassFile("unable.to.access.file", ex.getMessage());
  2518                             ClassType ct = (ClassType)currentOwner.type;
  2357         } catch (ArrayIndexOutOfBoundsException ex) {
  2519                             ct.supertype_field =
  2358             throw badClassFile("bad.class.file", c.flatname);
  2520                                 types.subst(ct.supertype_field, missing, found);
  2359         } finally {
  2521                             ct.interfaces_field =
  2360             missingTypeVariables = List.nil();
  2522                                 types.subst(ct.interfaces_field, missing, found);
  2361             foundTypeVariables = List.nil();
  2523                         } else if (missingTypeVariables.isEmpty() !=
  2362             filling = false;
  2524                                    foundTypeVariables.isEmpty()) {
       
  2525                             Name name = missingTypeVariables.head.tsym.name;
       
  2526                             throw badClassFile("undecl.type.var", name);
       
  2527                         }
       
  2528                     } finally {
       
  2529                         missingTypeVariables = List.nil();
       
  2530                         foundTypeVariables = List.nil();
       
  2531                         filling = false;
       
  2532                     }
       
  2533                 } else {
       
  2534                     if (sourceCompleter != null) {
       
  2535                         sourceCompleter.complete(c);
       
  2536                     } else {
       
  2537                         throw new IllegalStateException("Source completer required to read "
       
  2538                                                         + classfile.toUri());
       
  2539                     }
       
  2540                 }
       
  2541                 return;
       
  2542             } catch (IOException ex) {
       
  2543                 throw badClassFile("unable.to.access.file", ex.getMessage());
       
  2544             } catch (ArrayIndexOutOfBoundsException ex) {
       
  2545                 throw badClassFile("bad.class.file", c.flatname);
       
  2546             } finally {
       
  2547                 currentClassFile = previousClassFile;
       
  2548             }
       
  2549         } else {
       
  2550             JCDiagnostic diag =
       
  2551                 diagFactory.fragment("class.file.not.found", c.flatname);
       
  2552             throw
       
  2553                 newCompletionFailure(c, diag);
       
  2554         }
  2363         }
  2555     }
  2364     }
  2556     // where
  2365     // where
  2557         private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
  2366         private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
  2558             try {
  2367             try {
  2588                 buf = new byte[Integer.highestOneBit(needed) << 1];
  2397                 buf = new byte[Integer.highestOneBit(needed) << 1];
  2589                 System.arraycopy(old, 0, buf, 0, old.length);
  2398                 System.arraycopy(old, 0, buf, 0, old.length);
  2590             }
  2399             }
  2591             return buf;
  2400             return buf;
  2592         }
  2401         }
  2593         /** Static factory for CompletionFailure objects.
  2402 
  2594          *  In practice, only one can be used at a time, so we share one
  2403     /** We can only read a single class file at a time; this
  2595          *  to reduce the expense of allocating new exception objects.
  2404      *  flag keeps track of when we are currently reading a class
  2596          */
  2405      *  file.
  2597         private CompletionFailure newCompletionFailure(TypeSymbol c,
  2406      */
  2598                                                        JCDiagnostic diag) {
  2407     public boolean filling = false;
  2599             if (!cacheCompletionFailure) {
       
  2600                 // log.warning("proc.messager",
       
  2601                 //             Log.getLocalizedString("class.file.not.found", c.flatname));
       
  2602                 // c.debug.printStackTrace();
       
  2603                 return new CompletionFailure(c, diag);
       
  2604             } else {
       
  2605                 CompletionFailure result = cachedCompletionFailure;
       
  2606                 result.sym = c;
       
  2607                 result.diag = diag;
       
  2608                 return result;
       
  2609             }
       
  2610         }
       
  2611         private CompletionFailure cachedCompletionFailure =
       
  2612             new CompletionFailure(null, (JCDiagnostic) null);
       
  2613         {
       
  2614             cachedCompletionFailure.setStackTrace(new StackTraceElement[0]);
       
  2615         }
       
  2616 
       
  2617 
       
  2618     /** Load a toplevel class with given fully qualified name
       
  2619      *  The class is entered into `classes' only if load was successful.
       
  2620      */
       
  2621     public ClassSymbol loadClass(Name flatname) throws CompletionFailure {
       
  2622         boolean absent = syms.classes.get(flatname) == null;
       
  2623         ClassSymbol c = syms.enterClass(flatname);
       
  2624         if (c.members_field == null && c.completer != null) {
       
  2625             try {
       
  2626                 c.complete();
       
  2627             } catch (CompletionFailure ex) {
       
  2628                 if (absent) syms.classes.remove(flatname);
       
  2629                 throw ex;
       
  2630             }
       
  2631         }
       
  2632         return c;
       
  2633     }
       
  2634 
  2408 
  2635 /************************************************************************
  2409 /************************************************************************
  2636  * Loading Packages
  2410  * Adjusting flags
  2637  ***********************************************************************/
  2411  ***********************************************************************/
  2638 
  2412 
  2639     /** Include class corresponding to given class file in package,
  2413     long adjustFieldFlags(long flags) {
  2640      *  unless (1) we already have one the same kind (.class or .java), or
  2414         return flags;
  2641      *         (2) we have one of the other kind, and the given class file
  2415     }
  2642      *             is older.
  2416 
  2643      */
  2417     long adjustMethodFlags(long flags) {
  2644     protected void includeClassFile(PackageSymbol p, JavaFileObject file) {
  2418         if ((flags & ACC_BRIDGE) != 0) {
  2645         if ((p.flags_field & EXISTS) == 0)
  2419             flags &= ~ACC_BRIDGE;
  2646             for (Symbol q = p; q != null && q.kind == PCK; q = q.owner)
  2420             flags |= BRIDGE;
  2647                 q.flags_field |= EXISTS;
  2421             if (!allowGenerics)
  2648         JavaFileObject.Kind kind = file.getKind();
  2422                 flags &= ~SYNTHETIC;
  2649         int seen;
  2423         }
  2650         if (kind == JavaFileObject.Kind.CLASS)
  2424         if ((flags & ACC_VARARGS) != 0) {
  2651             seen = CLASS_SEEN;
  2425             flags &= ~ACC_VARARGS;
  2652         else
  2426             flags |= VARARGS;
  2653             seen = SOURCE_SEEN;
  2427         }
  2654         String binaryName = fileManager.inferBinaryName(currentLoc, file);
  2428         return flags;
  2655         int lastDot = binaryName.lastIndexOf(".");
  2429     }
  2656         Name classname = names.fromString(binaryName.substring(lastDot + 1));
  2430 
  2657         boolean isPkgInfo = classname == names.package_info;
  2431     long adjustClassFlags(long flags) {
  2658         ClassSymbol c = isPkgInfo
  2432         return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
  2659             ? p.package_info
  2433     }
  2660             : (ClassSymbol) p.members_field.lookup(classname).sym;
       
  2661         if (c == null) {
       
  2662             c = syms.enterClass(classname, p);
       
  2663             if (c.classfile == null) // only update the file if's it's newly created
       
  2664                 c.classfile = file;
       
  2665             if (isPkgInfo) {
       
  2666                 p.package_info = c;
       
  2667             } else {
       
  2668                 if (c.owner == p)  // it might be an inner class
       
  2669                     p.members_field.enter(c);
       
  2670             }
       
  2671         } else if (!preferCurrent && c.classfile != null && (c.flags_field & seen) == 0) {
       
  2672             // if c.classfile == null, we are currently compiling this class
       
  2673             // and no further action is necessary.
       
  2674             // if (c.flags_field & seen) != 0, we have already encountered
       
  2675             // a file of the same kind; again no further action is necessary.
       
  2676             if ((c.flags_field & (CLASS_SEEN | SOURCE_SEEN)) != 0)
       
  2677                 c.classfile = preferredFileObject(file, c.classfile);
       
  2678         }
       
  2679         c.flags_field |= seen;
       
  2680     }
       
  2681 
       
  2682     /** Implement policy to choose to derive information from a source
       
  2683      *  file or a class file when both are present.  May be overridden
       
  2684      *  by subclasses.
       
  2685      */
       
  2686     protected JavaFileObject preferredFileObject(JavaFileObject a,
       
  2687                                            JavaFileObject b) {
       
  2688 
       
  2689         if (preferSource)
       
  2690             return (a.getKind() == JavaFileObject.Kind.SOURCE) ? a : b;
       
  2691         else {
       
  2692             long adate = a.getLastModified();
       
  2693             long bdate = b.getLastModified();
       
  2694             // 6449326: policy for bad lastModifiedTime in ClassReader
       
  2695             //assert adate >= 0 && bdate >= 0;
       
  2696             return (adate > bdate) ? a : b;
       
  2697         }
       
  2698     }
       
  2699 
       
  2700     /**
       
  2701      * specifies types of files to be read when filling in a package symbol
       
  2702      */
       
  2703     protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() {
       
  2704         return EnumSet.of(JavaFileObject.Kind.CLASS, JavaFileObject.Kind.SOURCE);
       
  2705     }
       
  2706 
       
  2707     /**
       
  2708      * this is used to support javadoc
       
  2709      */
       
  2710     protected void extraFileActions(PackageSymbol pack, JavaFileObject fe) {
       
  2711     }
       
  2712 
       
  2713     protected Location currentLoc; // FIXME
       
  2714 
       
  2715     private boolean verbosePath = true;
       
  2716 
       
  2717     // Set to true when the currently selected file should be kept
       
  2718     private boolean preferCurrent;
       
  2719 
       
  2720     /** Load directory of package into members scope.
       
  2721      */
       
  2722     private void fillIn(PackageSymbol p) throws IOException {
       
  2723         if (p.members_field == null)
       
  2724             p.members_field = new Scope(p);
       
  2725 
       
  2726         preferCurrent = false;
       
  2727         if (userPathsFirst) {
       
  2728             scanUserPaths(p);
       
  2729             preferCurrent = true;
       
  2730             scanPlatformPath(p);
       
  2731         } else {
       
  2732             scanPlatformPath(p);
       
  2733             scanUserPaths(p);
       
  2734         }
       
  2735         verbosePath = false;
       
  2736     }
       
  2737 
       
  2738     /**
       
  2739      * Scans class path and source path for files in given package.
       
  2740      */
       
  2741     private void scanUserPaths(PackageSymbol p) throws IOException {
       
  2742         Set<JavaFileObject.Kind> kinds = getPackageFileKinds();
       
  2743 
       
  2744         Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds);
       
  2745         classKinds.remove(JavaFileObject.Kind.SOURCE);
       
  2746         boolean wantClassFiles = !classKinds.isEmpty();
       
  2747 
       
  2748         Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds);
       
  2749         sourceKinds.remove(JavaFileObject.Kind.CLASS);
       
  2750         boolean wantSourceFiles = !sourceKinds.isEmpty();
       
  2751 
       
  2752         boolean haveSourcePath = fileManager.hasLocation(SOURCE_PATH);
       
  2753 
       
  2754         if (verbose && verbosePath) {
       
  2755             if (fileManager instanceof StandardJavaFileManager) {
       
  2756                 StandardJavaFileManager fm = (StandardJavaFileManager)fileManager;
       
  2757                 if (haveSourcePath && wantSourceFiles) {
       
  2758                     List<File> path = List.nil();
       
  2759                     for (File file : fm.getLocation(SOURCE_PATH)) {
       
  2760                         path = path.prepend(file);
       
  2761                     }
       
  2762                     log.printVerbose("sourcepath", path.reverse().toString());
       
  2763                 } else if (wantSourceFiles) {
       
  2764                     List<File> path = List.nil();
       
  2765                     for (File file : fm.getLocation(CLASS_PATH)) {
       
  2766                         path = path.prepend(file);
       
  2767                     }
       
  2768                     log.printVerbose("sourcepath", path.reverse().toString());
       
  2769                 }
       
  2770                 if (wantClassFiles) {
       
  2771                     List<File> path = List.nil();
       
  2772                     for (File file : fm.getLocation(PLATFORM_CLASS_PATH)) {
       
  2773                         path = path.prepend(file);
       
  2774                     }
       
  2775                     for (File file : fm.getLocation(CLASS_PATH)) {
       
  2776                         path = path.prepend(file);
       
  2777                     }
       
  2778                     log.printVerbose("classpath",  path.reverse().toString());
       
  2779                 }
       
  2780             }
       
  2781         }
       
  2782 
       
  2783         String packageName = p.fullname.toString();
       
  2784         if (wantSourceFiles && !haveSourcePath) {
       
  2785             fillIn(p, CLASS_PATH,
       
  2786                    fileManager.list(CLASS_PATH,
       
  2787                                     packageName,
       
  2788                                     kinds,
       
  2789                                     false));
       
  2790         } else {
       
  2791             if (wantClassFiles)
       
  2792                 fillIn(p, CLASS_PATH,
       
  2793                        fileManager.list(CLASS_PATH,
       
  2794                                         packageName,
       
  2795                                         classKinds,
       
  2796                                         false));
       
  2797             if (wantSourceFiles)
       
  2798                 fillIn(p, SOURCE_PATH,
       
  2799                        fileManager.list(SOURCE_PATH,
       
  2800                                         packageName,
       
  2801                                         sourceKinds,
       
  2802                                         false));
       
  2803         }
       
  2804     }
       
  2805 
       
  2806     /**
       
  2807      * Scans platform class path for files in given package.
       
  2808      */
       
  2809     private void scanPlatformPath(PackageSymbol p) throws IOException {
       
  2810         fillIn(p, PLATFORM_CLASS_PATH,
       
  2811                fileManager.list(PLATFORM_CLASS_PATH,
       
  2812                                 p.fullname.toString(),
       
  2813                                 EnumSet.of(JavaFileObject.Kind.CLASS),
       
  2814                                 false));
       
  2815     }
       
  2816     // where
       
  2817         private void fillIn(PackageSymbol p,
       
  2818                             Location location,
       
  2819                             Iterable<JavaFileObject> files)
       
  2820         {
       
  2821             currentLoc = location;
       
  2822             for (JavaFileObject fo : files) {
       
  2823                 switch (fo.getKind()) {
       
  2824                 case CLASS:
       
  2825                 case SOURCE: {
       
  2826                     // TODO pass binaryName to includeClassFile
       
  2827                     String binaryName = fileManager.inferBinaryName(currentLoc, fo);
       
  2828                     String simpleName = binaryName.substring(binaryName.lastIndexOf(".") + 1);
       
  2829                     if (SourceVersion.isIdentifier(simpleName) ||
       
  2830                         simpleName.equals("package-info"))
       
  2831                         includeClassFile(p, fo);
       
  2832                     break;
       
  2833                 }
       
  2834                 default:
       
  2835                     extraFileActions(p, fo);
       
  2836                 }
       
  2837             }
       
  2838         }
       
  2839 
  2434 
  2840     /** Output for "-checkclassfile" option.
  2435     /** Output for "-checkclassfile" option.
  2841      *  @param key The key to look up the correct internationalized string.
  2436      *  @param key The key to look up the correct internationalized string.
  2842      *  @param arg An argument for substitution into the output string.
  2437      *  @param arg An argument for substitution into the output string.
  2843      */
  2438      */
  2844     private void printCCF(String key, Object arg) {
  2439     private void printCCF(String key, Object arg) {
  2845         log.printLines(key, arg);
  2440         log.printLines(key, arg);
  2846     }
       
  2847 
       
  2848 
       
  2849     public interface SourceCompleter {
       
  2850         void complete(ClassSymbol sym)
       
  2851             throws CompletionFailure;
       
  2852     }
  2441     }
  2853 
  2442 
  2854     /**
  2443     /**
  2855      * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
  2444      * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
  2856      * The attribute is only the last component of the original filename, so is unlikely
  2445      * The attribute is only the last component of the original filename, so is unlikely