KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > types > LoadedClassResolver


1 package polyglot.types;
2
3 import java.io.InvalidClassException JavaDoc;
4 import java.util.Collection JavaDoc;
5 import java.util.HashSet JavaDoc;
6 import java.util.Set JavaDoc;
7 import java.util.StringTokenizer JavaDoc;
8
9 import polyglot.main.Report;
10 import polyglot.main.Version;
11 import polyglot.types.reflect.ClassFile;
12 import polyglot.types.reflect.ClassFileLoader;
13 import polyglot.types.reflect.ClassPathLoader;
14 import polyglot.util.CollectionUtil;
15 import polyglot.util.TypeEncoder;
16
17 /**
18  * Loads class information from class files, or serialized class infomation
19  * from within class files. It does not load from source files.
20  */

21 public class LoadedClassResolver extends ClassResolver implements TopLevelResolver
22 {
23   protected final static int NOT_COMPATIBLE = -1;
24   protected final static int MINOR_NOT_COMPATIBLE = 1;
25   protected final static int COMPATIBLE = 0;
26
27   TypeSystem ts;
28   TypeEncoder te;
29   ClassPathLoader loader;
30   Version version;
31   Set JavaDoc nocache;
32   boolean allowRawClasses;
33
34   final static Collection JavaDoc report_topics = CollectionUtil.list(
35     Report.types, Report.resolver, Report.loader);
36
37   /**
38    * Create a loaded class resolver.
39    * @param ts The type system
40    * @param classpath The class path
41    * @param loader The class file loader to use.
42    * @param version The version of classes to load.
43    * @param allowRawClasses allow class files without encoded type information
44    */

45   public LoadedClassResolver(TypeSystem ts, String JavaDoc classpath,
46                              ClassFileLoader loader, Version version,
47                              boolean allowRawClasses)
48   {
49     this.ts = ts;
50     this.te = new TypeEncoder(ts);
51     this.loader = new ClassPathLoader(classpath, loader);
52     this.version = version;
53     this.nocache = new HashSet JavaDoc();
54     this.allowRawClasses = allowRawClasses;
55   }
56
57   public boolean packageExists(String JavaDoc name) {
58     return loader.packageExists(name);
59   }
60
61   /**
62    * Load a class file for class <code>name</code>.
63    */

64   protected ClassFile loadFile(String JavaDoc name) {
65     if (nocache.contains(name)) {
66         return null;
67     }
68     
69     try {
70         ClassFile clazz = loader.loadClass(name);
71
72         if (clazz == null) {
73             if (Report.should_report(report_topics, 4)) {
74                 Report.report(4, "Class " + name + " not found in classpath "
75                         + loader.classpath());
76             }
77         }
78         else {
79             if (Report.should_report(report_topics, 4)) {
80                 Report.report(4, "Class " + name + " found in classpath "
81                         + loader.classpath());
82             }
83             return clazz;
84         }
85     }
86     catch (ClassFormatError JavaDoc e) {
87         if (Report.should_report(report_topics, 4))
88             Report.report(4, "Class " + name + " format error");
89     }
90
91     nocache.add(name);
92
93     return null;
94   }
95
96   /**
97    * Find a type by name.
98    */

99   public Named find(String JavaDoc name) throws SemanticException {
100     if (Report.should_report(report_topics, 3))
101       Report.report(3, "LoadedCR.find(" + name + ")");
102
103     // First try the class file.
104
ClassFile clazz = loadFile(name);
105     if (clazz == null) {
106         throw new NoClassException(name);
107     }
108
109     // Check for encoded type information.
110
if (clazz.encodedClassType(version.name()) != null) {
111       if (Report.should_report(report_topics, 4))
112     Report.report(4, "Using encoded class type for " + name);
113       return getEncodedType(clazz, name);
114     }
115     
116     if (allowRawClasses) {
117       if (Report.should_report(report_topics, 4))
118     Report.report(4, "Using raw class file for " + name);
119       return clazz.type(ts);
120     }
121
122     // We have a raw class, but are not allowed to use it, and
123
// cannot find appropriate encoded info.
124
throw new SemanticException("Unable to find a suitable definition of \""
125         + name +"\". A class file was found,"
126         + " but it did not contain appropriate information for this"
127         + " language extension. If the source for this file is written"
128         + " in the language extension, try recompiling the source code.");
129     
130   }
131
132   /**
133    * Extract an encoded type from a class file.
134    */

135   protected ClassType getEncodedType(ClassFile clazz, String JavaDoc name)
136     throws SemanticException
137   {
138     // At this point we've decided to go with the Class. So if something
139
// goes wrong here, we have only one choice, to throw an exception.
140

141     // Check to see if it has serialized info. If so then check the
142
// version.
143
FieldInstance field;
144     
145     int comp = checkCompilerVersion(clazz.compilerVersion(version.name()));
146
147     if (comp == NOT_COMPATIBLE) {
148       throw new SemanticException("Unable to find a suitable definition of "
149                                   + clazz.name()
150                                   + ". Try recompiling or obtaining "
151                                   + " a newer version of the class file.");
152     }
153
154     // Alright, go with it!
155
ClassType dt;
156     
157     try {
158         dt = (ClassType) te.decode(clazz.encodedClassType(version.name()));
159     }
160     catch (InvalidClassException JavaDoc e) {
161         throw new BadSerializationException(clazz.name());
162     }
163
164     // Put the decoded type into the resolver to avoid circular resolving.
165
((CachingResolver) ts.systemResolver()).addNamed(name, dt);
166
167     if (Report.should_report(report_topics, 2))
168       Report.report(2, "Returning serialized ClassType for " +
169                     clazz.name() + ".");
170
171     return (ClassType) dt;
172   }
173
174   /**
175    * Compare the encoded type's version against the loader's version.
176    */

177   protected int checkCompilerVersion(String JavaDoc clazzVersion) {
178     if (clazzVersion == null) {
179       return NOT_COMPATIBLE;
180     }
181
182     StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(clazzVersion, ".");
183
184     try {
185       int v;
186       v = Integer.parseInt(st.nextToken());
187       Version version = this.version;
188
189       if (v != version.major()) {
190     // Incompatible.
191
return NOT_COMPATIBLE;
192       }
193
194       v = Integer.parseInt(st.nextToken());
195
196       if (v != version.minor()) {
197     // Not the best option, but will work if its the only one.
198
return MINOR_NOT_COMPATIBLE;
199       }
200     }
201     catch (NumberFormatException JavaDoc e) {
202       return NOT_COMPATIBLE;
203     }
204
205     // Everything is way cool.
206
return COMPATIBLE;
207   }
208 }
209
Popular Tags