KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > types > SourceClassResolver


1 package polyglot.types;
2
3 import polyglot.frontend.Compiler;
4 import polyglot.frontend.ExtensionInfo;
5 import polyglot.frontend.FileSource;
6 import polyglot.main.Report;
7 import polyglot.types.reflect.ClassFile;
8 import polyglot.types.reflect.ClassFileLoader;
9
10 /**
11  * Loads class information from source files, class files, or serialized
12  * class infomation from within class files. An outline of the steps is
13  * given below.
14  *
15  * <ol>
16  * <li> When the polyglot translator looks for a class by the name
17  * "foo.bar.Quux" it first searches for that class in any file given
18  * on the command line. If the class is found one of these files, then
19  * this definition is used and the remainder of the steps are
20  * skipped.
21  *
22  * <li>If none of these files contain the desired class, then the source
23  * path is searched next. For example, if the source extension is
24  * ".jl" and the source path is "mydir:." then the translator looks
25  * for files "mydir/foo/bar/Quux.jl" and "./foo/bar/Quux.jl".
26  *
27  * <li> Regardless of whether or not a source file is found, the translator
28  * searches the classpath (defined as normal through the environment
29  * and command-line options to the interpreter) for the desired class.
30  *
31  * <li>If no source file exists, and no class is found then an error is
32  * reported (skipping the rest of the steps below).
33  *
34  * <li>If a source file is found, but no class, then the source file is
35  * parsed. If it contains the desired class definition (which it
36  * should) then that definition is used and the remainder of the steps
37  * are skipped. (If it does not contain this definition, an error is
38  * reported and the remainder of the steps are skipped.
39  *
40  * <li>If a class is found but no source file, then the class is examined
41  * for jlc class type information. If the class contains no class type
42  * information (this is the case if the class file was compiled from
43  * raw Java source rather than jlc translated output) then this class
44  * is used as the desired class definition (skipping all steps below).
45  *
46  * <li>(class, but no still no source) If the class does contain jlc class
47  * type information, then the version number of translator used to
48  * translate the source which created the given class file is compared
49  * against the version of the current instantiation of the translator.
50  * If the versions are compatible, then the jlc class type information
51  * is used as the desired definiton. If the versions are incompatible
52  * (see the documentation in Compiler.java) then an error is reported.
53  * In either case, all remaining steps are skipped.
54  *
55  * <li>If both a suitable source file and class are found then we have a
56  * choice. If the class definition does not contain jlc class type
57  * information then the source file is parsed as the definition found
58  * in this file is used as desired definiton and we stop here. If the
59  * class does contain jlc class type information, then continue.
60  *
61  * <li>(source and class with jlc info) Next the last modification date of
62  * the source file is compared to the last modification date of the
63  * source file used to generate the class file. If the source file is
64  * more recent, the it is parsed as used as the desired definition and
65  * all remaining steps are skipped.
66  *
67  * <li>(source and class with jlc info) Next the jlc version of the class
68  * and of the current translator are compared (as in 7.). If the
69  * verisions are incompatible, then we use the definition from the
70  * parsed source file. If the versions are compatible, then we use
71  * the definition given by the jlc class type information.
72  * </ol>
73  * Finally, if at any point an error occurs while reading jlc class type
74  * information (e.g. if this information exists but is corrupted), then
75  * an error is reported.
76  */

77 public class SourceClassResolver extends LoadedClassResolver
78 {
79   Compiler JavaDoc compiler;
80   ExtensionInfo ext;
81
82   /**
83    * Create a loaded class resolver.
84    * @param compiler The compiler.
85    * @param ext The extension to load sources for.
86    * @param classpath The class path.
87    * @param loader The class file loader to use.
88    * @param allowRawClasses True if vanilla Java class files without
89    * Polyglot-embedded type information should be
90    * allowed.
91    */

92   public SourceClassResolver(Compiler JavaDoc compiler, ExtensionInfo ext,
93                              String JavaDoc classpath, ClassFileLoader loader,
94                              boolean allowRawClasses)
95   {
96     super(ext.typeSystem(), classpath, loader, ext.version(), allowRawClasses);
97     this.compiler = compiler;
98     this.ext = ext;
99   }
100
101   public boolean packageExists(String JavaDoc name) {
102     if (super.packageExists(name)) {
103         return true;
104     }
105     /*
106     if (ext.sourceLoader().packageExists(name)) {
107         return true;
108     }
109     */

110     return false;
111   }
112
113   /**
114    * Find a type by name.
115    */

116   public Named find(String JavaDoc name) throws SemanticException {
117     if (Report.should_report(report_topics, 3))
118     Report.report(3, "SourceCR.find(" + name + ")");
119
120     ClassFile clazz = null;
121     ClassFile encodedClazz = null;
122     FileSource source = null;
123
124     // First try the class file.
125
clazz = loadFile(name);
126     if (clazz != null) {
127       // Check for encoded type information.
128
if (clazz.encodedClassType(version.name()) != null) {
129         if (Report.should_report(report_topics, 4))
130           Report.report(4, "Class " + name + " has encoded type info");
131         encodedClazz = clazz;
132       }
133     }
134
135     if (clazz != null && ! this.allowRawClasses) {
136       clazz = null;
137     }
138
139     // Now, try and find the source file.
140
source = ext.sourceLoader().classSource(name);
141     if (Report.should_report(report_topics, 4)) {
142         if (source == null)
143             Report.report(4, "Class " + name + " not found in source file");
144         else
145             Report.report(4, "Class " + name + " found in source " + source);
146     }
147
148     // Don't use the raw class if the encoded class is available.
149
if (encodedClazz != null) {
150       if (Report.should_report(report_topics, 4))
151     Report.report(4, "Not using raw class file for " + name);
152       clazz = null;
153     }
154
155     // If both the source and class are available, we decide which to
156
// use based on compiler compatibility and modification times.
157
if (clazz != null && source != null) {
158       long classModTime = clazz.rawSourceLastModified();
159       long sourceModTime = source.lastModified().getTime();
160
161       if (classModTime < sourceModTime) {
162         if (Report.should_report(report_topics, 3))
163         Report.report(3, "Source file version is newer than compiled for " +
164                       name + ".");
165         clazz = null;
166       }
167       else {
168         source = null;
169       }
170     }
171
172     if (encodedClazz != null && source != null) {
173       long classModTime = encodedClazz.sourceLastModified(version.name());
174       long sourceModTime = source.lastModified().getTime();
175
176       int comp = checkCompilerVersion(encodedClazz.compilerVersion(version.name()));
177
178       if (classModTime < sourceModTime) {
179         if (Report.should_report(report_topics, 3))
180         Report.report(3, "Source file version is newer than compiled for " +
181                       name + ".");
182         encodedClazz = null;
183       }
184       else if (comp != COMPATIBLE) {
185         // Incompatible or older version, so go with the source.
186
if (Report.should_report(report_topics, 3))
187         Report.report(3, "Incompatible source file version for " + name + ".");
188         encodedClazz = null;
189       }
190     }
191
192     if (encodedClazz != null) {
193       if (Report.should_report(report_topics, 4))
194     Report.report(4, "Using encoded class type for " + name);
195       try {
196         return getEncodedType(encodedClazz, name);
197       }
198       catch (BadSerializationException e) {
199         throw e;
200       }
201       catch (SemanticException e) {
202         if (Report.should_report(report_topics, 4))
203           Report.report(4, "Could not load encoded class " + name);
204         encodedClazz = null;
205       }
206     }
207
208     // At this point, at most one of clazz and source should be set.
209

210     if (clazz != null) {
211       if (Report.should_report(report_topics, 4))
212     Report.report(4, "Using raw class file for " + name);
213       return clazz.type(ts);
214     }
215
216     if (source != null) {
217       if (Report.should_report(report_topics, 4))
218     Report.report(4, "Using source file for " + name);
219       return getTypeFromSource(source, name);
220     }
221
222     if (clazz != null && !this.allowRawClasses) {
223         // We have a raw class only. We do not have the source code,
224
// or encoded class information.
225
throw new SemanticException("Class \"" + name + "\" not found."
226             + " A class file was found, but it did not contain appropriate"
227             + " information for the Polyglot-based compiler " +
228             ext.compilerName() + ". Try using " + ext.compilerName()
229             + " to recompile the source code.");
230     }
231     throw new NoClassException(name);
232   }
233
234   /**
235    * Get a type from a source file.
236    */

237   protected Named getTypeFromSource(FileSource source, String JavaDoc name)
238     throws SemanticException
239   {
240     // Compile the source file just enough to get the type information out.
241
ext.readSource(source);
242     
243     // Even if there was an error when compiling the source file, we may
244
// as well keep trying to compile the current class, as the error may
245
// have been with something source depended on, that we do not.
246
return ts.parsedResolver().find(name);
247   }
248 }
249
Popular Tags