View Javadoc

1   // Class.java, created Thu Jul  4  4:50:03 2002 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.ClassLib.Common.java.lang;
5   
6   import joeq.Class.jq_Array;
7   import joeq.Class.jq_Class;
8   import joeq.Class.jq_ClassFileConstants;
9   import joeq.Class.jq_ClassInitializer;
10  import joeq.Class.jq_Field;
11  import joeq.Class.jq_Initializer;
12  import joeq.Class.jq_InstanceField;
13  import joeq.Class.jq_InstanceMethod;
14  import joeq.Class.jq_Method;
15  import joeq.Class.jq_NameAndDesc;
16  import joeq.Class.jq_Primitive;
17  import joeq.Class.jq_Reference;
18  import joeq.Class.jq_StaticField;
19  import joeq.Class.jq_StaticMethod;
20  import joeq.Class.jq_Type;
21  import joeq.ClassLib.Common.ClassUtils;
22  import joeq.Runtime.Reflection;
23  import joeq.Runtime.TypeCheck;
24  import joeq.UTF.Utf8;
25  import jwutil.util.Assert;
26  
27  /***
28   * Class
29   *
30   * @author  John Whaley <jwhaley@alum.mit.edu>
31   * @version $Id: Class.java 1941 2004-09-30 03:37:06Z joewhaley $
32   */
33  public class Class {
34      
35      // additional instance fields.
36      public final jq_Type jq_type;
37      private java.lang.Object[] signers;
38      private java.security.ProtectionDomain protection_domain;
39      
40      private Class(jq_Type t) {
41          this.jq_type = t;
42          //joeq.Runtime.SystemInterface.debugmsg("Created new Class object for "+t.getName());
43      }
44      
45      // native method implementations.
46      private static void registerNatives() { }
47      private static Class forName0(java.lang.String name, boolean initialize,
48                                    ClassLoader loader)
49          throws java.lang.ClassNotFoundException
50      {
51          Class k = loader.loadClass(name);
52          if (initialize) {
53              jq_Type t = k.jq_type;
54              Assert._assert(t.isLoaded());
55              t.cls_initialize();
56          }
57          return k;
58      }
59  
60      private java.lang.Object newInstance0()
61          throws java.lang.InstantiationException, java.lang.IllegalAccessException
62      {
63          jq_Type jq_type = this.jq_type;
64          if (!jq_type.isClassType())
65              throw new java.lang.InstantiationException(jq_type.getDesc()+" is not a class type");
66          jq_Class jq_class = (jq_Class)jq_type;
67          jq_class.load();
68          if (jq_class.isAbstract())
69              throw new java.lang.InstantiationException("cannot instantiate abstract "+this);
70          jq_Initializer i = jq_class.getInitializer(new jq_NameAndDesc(Utf8.get("<init>"), Utf8.get("()V")));
71          if (i == null)
72              throw new java.lang.InstantiationException("no empty arg initializer in "+this);
73          ClassUtils.checkCallerAccess(i, 3);
74          jq_class.cls_initialize(); 
75          java.lang.Object o = jq_class.newInstance();
76          try {
77              Reflection.invokeinstance_V(i, o);
78          } catch (java.lang.Error x) {
79              throw x;
80          } catch (java.lang.Throwable x) {
81              throw new java.lang.ExceptionInInitializerError(x);
82          }
83          return o;
84      }
85  
86      public boolean isInstance(java.lang.Object obj) {
87          if (obj == null) return false;
88          jq_Reference t = jq_Reference.getTypeOf(obj);
89          jq_Type jq_type = this.jq_type;
90          jq_type.prepare();
91          return TypeCheck.isAssignable(t, jq_type);
92      }
93      
94      public boolean isAssignableFrom(Class cls) {
95          jq_Type jq_type = this.jq_type;
96          jq_type.prepare();
97          jq_Type cls_jq_type = cls.jq_type;
98          cls_jq_type.prepare();
99          return TypeCheck.isAssignable(cls_jq_type, jq_type);
100     }
101     
102     public boolean isInterface() {
103         jq_Type jq_type = this.jq_type;
104         jq_type.load();
105         return jq_type.isClassType() && ((jq_Class)jq_type).isInterface();
106     }
107     
108     public boolean isArray() {
109         jq_Type jq_type = this.jq_type;
110         return jq_type.isArrayType();
111     }
112     
113     public boolean isPrimitive() {
114         jq_Type jq_type = this.jq_type;
115         return jq_type.isPrimitiveType();
116     }
117     
118     public java.lang.String getName() {
119         jq_Type jq_type = this.jq_type;
120         if (jq_type.isArrayType()) return jq_type.getDesc().toString().replace('/','.');
121         else return jq_type.getName().toString();
122     }
123     
124     java.lang.ClassLoader getClassLoader0() {
125         jq_Type jq_type = this.jq_type;
126         return (java.lang.ClassLoader)jq_type.getClassLoader();
127     }
128     
129     public java.lang.Class getSuperclass() {
130         jq_Type jq_type = this.jq_type;
131         if (!jq_type.isClassType()) return null;
132         jq_Class k = (jq_Class)jq_type;
133         k.prepare();
134         if (k.getSuperclass() == null) return null;
135         return Reflection.getJDKType(k.getSuperclass());
136     }
137     
138     public java.lang.Class[] getInterfaces() {
139         jq_Type jq_type = this.jq_type;
140         if (jq_type.isPrimitiveType()) return new java.lang.Class[0];
141         jq_Class[] ins;
142         jq_type.load();
143         if (jq_type.isArrayType()) ins = jq_Array.array_interfaces;
144         else ins = ((jq_Class)jq_type).getDeclaredInterfaces();
145         java.lang.Class[] c = new java.lang.Class[ins.length];
146         for (int i=0; i<ins.length; ++i) {
147             c[i] = Reflection.getJDKType(ins[i]);
148         }
149         return c;
150     }
151     
152     public java.lang.Class getComponentType() {
153         jq_Type jq_type = this.jq_type;
154         if (!jq_type.isArrayType()) return null;
155         return Reflection.getJDKType(((jq_Array)jq_type).getElementType());
156     }
157     
158     public int getModifiers() {
159         jq_Type jq_type = this.jq_type;
160         jq_type.load();
161         if (jq_type.isPrimitiveType()) return jq_ClassFileConstants.ACC_PUBLIC | jq_ClassFileConstants.ACC_FINAL;
162         if (jq_type.isArrayType()) return Reflection.getJDKType(((jq_Array)jq_type).getElementType()).getModifiers() | jq_ClassFileConstants.ACC_FINAL & ~jq_ClassFileConstants.ACC_INTERFACE;
163         return (int)((jq_Class)jq_type).getAccessFlags();
164     }
165 
166     public java.lang.Object[] getSigners() {
167         // TODO: correct handling of signers
168         return this.signers;
169     }
170     void setSigners(java.lang.Object[] signers) {
171         // TODO: correct handling of signers
172         this.signers = signers;
173     }
174     
175     public java.lang.Class getDeclaringClass() {
176         // TODO: handling of declaring class
177         return null;
178     }
179     
180     private java.security.ProtectionDomain getProtectionDomain0() {
181         // TODO: correct handling of ProtectionDomain
182         return this.protection_domain;
183     }
184     void setProtectionDomain0(java.security.ProtectionDomain pd) {
185         // TODO: correct handling of ProtectionDomain
186         this.protection_domain = pd;
187     }
188 
189     static java.lang.Class getPrimitiveClass(java.lang.String name) {
190         if (name.equals("int")) return Reflection.getJDKType(jq_Primitive.INT);
191         if (name.equals("float")) return Reflection.getJDKType(jq_Primitive.FLOAT);
192         if (name.equals("long")) return Reflection.getJDKType(jq_Primitive.LONG);
193         if (name.equals("double")) return Reflection.getJDKType(jq_Primitive.DOUBLE);
194         if (name.equals("boolean")) return Reflection.getJDKType(jq_Primitive.BOOLEAN);
195         if (name.equals("byte")) return Reflection.getJDKType(jq_Primitive.BYTE);
196         if (name.equals("char")) return Reflection.getJDKType(jq_Primitive.CHAR);
197         if (name.equals("short")) return Reflection.getJDKType(jq_Primitive.SHORT);
198         if (name.equals("void")) return Reflection.getJDKType(jq_Primitive.VOID);
199         throw new java.lang.InternalError("no such primitive type: "+name);
200     }
201     
202     private java.lang.reflect.Field[] getFields0(int which) {
203         jq_Type jq_type = this.jq_type;
204         if (!jq_type.isClassType()) return new java.lang.reflect.Field[0];
205         jq_Class c = (jq_Class)jq_type;
206         c.load();
207         if (which == java.lang.reflect.Member.DECLARED) {
208             jq_StaticField[] sfs = c.getDeclaredStaticFields();
209             jq_InstanceField[] ifs = c.getDeclaredInstanceFields();
210             int size = sfs.length + ifs.length;
211             java.lang.reflect.Field[] fs = new java.lang.reflect.Field[size];
212             for (int j=0; j<sfs.length; ++j) {
213                 fs[j] = (java.lang.reflect.Field)sfs[j].getJavaLangReflectMemberObject();
214             }
215             for (int j=0; j<ifs.length; ++j) {
216                 fs[sfs.length+j] = (java.lang.reflect.Field)ifs[j].getJavaLangReflectMemberObject();
217             }
218             return fs;
219         } else {
220             Assert._assert(which == java.lang.reflect.Member.PUBLIC);
221             c.prepare();
222             int size = 0;
223             jq_StaticField[] sfs = c.getStaticFields();
224             jq_InstanceField[] ifs = c.getInstanceFields();
225             for (int j=0; j<sfs.length; ++j) {
226                 if (sfs[j].isPublic()) ++size;
227             }
228             for (int j=0; j<ifs.length; ++j) {
229                 if (ifs[j].isPublic()) ++size;
230             }
231             java.lang.reflect.Field[] fs = new java.lang.reflect.Field[size];
232             int current = -1;
233             for (int j=0; j<sfs.length; ++j) {
234                 if (sfs[j].isPublic())
235                     fs[++current] = (java.lang.reflect.Field)sfs[j].getJavaLangReflectMemberObject();
236             }
237             for (int j=0; j<ifs.length; ++j) {
238                 if (ifs[j].isPublic())
239                     fs[++current] = (java.lang.reflect.Field)ifs[j].getJavaLangReflectMemberObject();
240             }
241             Assert._assert(current+1 == fs.length);
242             return fs;
243         }
244     }
245     private java.lang.reflect.Method[] getMethods0(int which) {
246         jq_Type jq_type = this.jq_type;
247         if (!jq_type.isClassType()) return new java.lang.reflect.Method[0];
248         jq_Class c = (jq_Class)jq_type;
249         c.load();
250         if (which == java.lang.reflect.Member.DECLARED) {
251             jq_StaticMethod[] sfs = c.getDeclaredStaticMethods();
252             jq_InstanceMethod[] ifs = c.getDeclaredInstanceMethods();
253             int size = sfs.length + ifs.length;
254             for (int j=0; j<sfs.length; ++j) {
255                 if (sfs[j] instanceof jq_ClassInitializer) --size;
256             }
257             for (int j=0; j<ifs.length; ++j) {
258                 if (ifs[j] instanceof jq_Initializer) --size;
259             }
260             java.lang.reflect.Method[] fs = new java.lang.reflect.Method[size];
261             int k = -1;
262             for (int j=0; j<sfs.length; ++j) {
263                 if (sfs[j] instanceof jq_ClassInitializer) continue;
264                 fs[++k] = (java.lang.reflect.Method)sfs[j].getJavaLangReflectMemberObject();
265             }
266             for (int j=0; j<ifs.length; ++j) {
267                 if (ifs[j] instanceof jq_Initializer) continue;
268                 fs[++k] = (java.lang.reflect.Method)ifs[j].getJavaLangReflectMemberObject();
269             }
270             Assert._assert(k == fs.length-1);
271             return fs;
272         } else {
273             Assert._assert(which == java.lang.reflect.Member.PUBLIC);
274             c.prepare();
275             int size = 0;
276             jq_StaticMethod[] sfs = c.getStaticMethods();
277             jq_InstanceMethod[] ifs = c.getVirtualMethods();
278             for (int j=0; j<sfs.length; ++j) {
279                 if (sfs[j] instanceof jq_ClassInitializer) continue;
280                 if (sfs[j].isPublic()) ++size;
281             }
282             for (int j=0; j<ifs.length; ++j) {
283                 if (ifs[j] instanceof jq_Initializer) continue;
284                 if (ifs[j].isPublic()) ++size;
285             }
286             java.lang.reflect.Method[] fs = new java.lang.reflect.Method[size];
287             int k = -1;
288             for (int j=0; j<sfs.length; ++j) {
289                 if (sfs[j] instanceof jq_ClassInitializer) continue;
290                 if (sfs[j].isPublic())
291                     fs[++k] = (java.lang.reflect.Method)sfs[j].getJavaLangReflectMemberObject();
292             }
293             for (int j=0; j<ifs.length; ++j) {
294                 if (ifs[j] instanceof jq_Initializer) continue;
295                 if (ifs[j].isPublic())
296                     fs[++k] = (java.lang.reflect.Method)ifs[j].getJavaLangReflectMemberObject();
297             }
298             Assert._assert(k == fs.length-1);
299             return fs;
300         }
301     }
302     private java.lang.reflect.Constructor[] getConstructors0(int which) {
303         jq_Type jq_type = this.jq_type;
304         if (!jq_type.isClassType()) return new java.lang.reflect.Constructor[0];
305         jq_Class c = (jq_Class)jq_type;
306         c.load();
307         jq_InstanceMethod[] ifs = c.getDeclaredInstanceMethods();
308         int size = 0;
309         for (int j=0; j<ifs.length; ++j) {
310             if (which == java.lang.reflect.Member.PUBLIC && !ifs[j].isPublic())
311                 continue;
312             if (ifs[j] instanceof jq_Initializer) ++size;
313         }
314         java.lang.reflect.Constructor[] fs = new java.lang.reflect.Constructor[size];
315         
316         int k = -1;
317         for (int j=0; j<ifs.length; ++j) {
318             if (which == java.lang.reflect.Member.PUBLIC && !ifs[j].isPublic())
319                 continue;
320             if (ifs[j] instanceof jq_Initializer) {
321                 fs[++k] = (java.lang.reflect.Constructor)ifs[j].getJavaLangReflectMemberObject();
322             }
323         }
324         Assert._assert(k == fs.length-1);
325         return fs;
326     }
327     private java.lang.reflect.Field getField0(java.lang.String name, int which)
328         throws java.lang.NoSuchFieldException
329     {
330         jq_Type jq_type = this.jq_type;
331         if (!jq_type.isClassType())
332             throw new java.lang.NoSuchFieldException(jq_type.getJDKDesc());
333         jq_Class c = (jq_Class)jq_type;
334         c.load();
335         Utf8 utf8name = Utf8.get(name);
336         jq_Field[] sms;
337         if (which == java.lang.reflect.Member.DECLARED) {
338             sms = c.getDeclaredStaticFields();
339         } else {
340             Assert._assert(which == java.lang.reflect.Member.PUBLIC);
341             sms = c.getStaticFields();
342         }
343         for (int i=0; i<sms.length; ++i) {
344             if (sms[i].getName() == utf8name) {
345                 if (which == java.lang.reflect.Member.PUBLIC && !sms[i].isPublic())
346                     continue;
347                 return (java.lang.reflect.Field)sms[i].getJavaLangReflectMemberObject();
348             }
349         }
350         if (which == java.lang.reflect.Member.DECLARED) {
351             sms = c.getDeclaredInstanceFields();
352         } else {
353             Assert._assert(which == java.lang.reflect.Member.PUBLIC);
354             c.prepare();
355             sms = c.getInstanceFields();
356         }
357         for (int i=0; i<sms.length; ++i) {
358             if (sms[i].getName() == utf8name) {
359                 if (which == java.lang.reflect.Member.PUBLIC && !sms[i].isPublic())
360                     continue;
361                 return (java.lang.reflect.Field)sms[i].getJavaLangReflectMemberObject();
362             }
363         }
364         throw new java.lang.NoSuchFieldException(c.getJDKName()+"."+name);
365     }
366     private java.lang.reflect.Method getMethod0(java.lang.String name, java.lang.Class[] parameterTypes, int which)
367         throws java.lang.NoSuchMethodException
368     {
369         jq_Type jq_type = this.jq_type;
370         if (!jq_type.isClassType())
371             throw new java.lang.NoSuchMethodException(jq_type.getJDKDesc());
372         if (name.equals("<init>") || name.equals("<clinit>"))
373             throw new java.lang.NoSuchMethodException(name+" is an illegal method name");
374         jq_Class c = (jq_Class)jq_type;
375         java.lang.StringBuffer sb = new java.lang.StringBuffer();
376         sb.append('(');
377         for (int i=0; i<parameterTypes.length; ++i) {
378             sb.append(Reflection.getJQType(parameterTypes[i]).getDesc().toString());
379         }
380         sb.append(')');
381         java.lang.String args = sb.toString();
382         c.load();
383         Utf8 utf8name = Utf8.get(name);
384         jq_Method[] sms;
385         if (which == java.lang.reflect.Member.DECLARED) {
386             sms = c.getDeclaredStaticMethods();
387         } else {
388             Assert._assert(which == java.lang.reflect.Member.PUBLIC);
389             sms = c.getStaticMethods();
390         }
391         for (int i=0; i<sms.length; ++i) {
392             if (sms[i].getName() == utf8name) {
393                 if (which == java.lang.reflect.Member.PUBLIC && !sms[i].isPublic())
394                     continue;
395                 if (sms[i].getDesc().toString().startsWith(args))
396                     return (java.lang.reflect.Method)sms[i].getJavaLangReflectMemberObject();
397             }
398         }
399         if (which == java.lang.reflect.Member.DECLARED) {
400             sms = c.getDeclaredInstanceMethods();
401         } else {
402             Assert._assert(which == java.lang.reflect.Member.PUBLIC);
403             c.prepare();
404             sms = c.getVirtualMethods();
405         }
406         for (int i=0; i<sms.length; ++i) {
407             if (sms[i].getName() == utf8name) {
408                 if (which == java.lang.reflect.Member.PUBLIC && !sms[i].isPublic())
409                     continue;
410                 if (sms[i].getDesc().toString().startsWith(args))
411                     return (java.lang.reflect.Method)sms[i].getJavaLangReflectMemberObject();
412             }
413         }
414         throw new java.lang.NoSuchMethodException(c.getJDKName()+"."+name+args);
415     }
416     private java.lang.reflect.Constructor getConstructor0(java.lang.Class[] parameterTypes, int which)
417         throws java.lang.NoSuchMethodException
418     {
419         jq_Type jq_type = this.jq_type;
420         if (!jq_type.isClassType())
421             throw new java.lang.NoSuchMethodException(jq_type.getJDKDesc());
422         jq_Class c = (jq_Class)jq_type;
423         Utf8 utf8desc = buildMethodDescriptor(parameterTypes, null);
424         jq_NameAndDesc nd = new jq_NameAndDesc(Utf8.get("<init>"), utf8desc);
425         jq_Initializer i = c.getInitializer(nd);
426         if (i == null || (which == java.lang.reflect.Member.PUBLIC && !i.isPublic()))
427             throw new java.lang.NoSuchMethodException(c.getJDKName()+utf8desc);
428         return (java.lang.reflect.Constructor)i.getJavaLangReflectMemberObject();
429     }
430     private java.lang.Class[] getDeclaredClasses0() {
431         // TODO: handle declared classes
432         return new java.lang.Class[0];
433     }
434     
435     // additional methods.
436     // ONLY TO BE CALLED BY jq_Class CONSTRUCTOR!!!
437     public static java.lang.Class createNewClass(jq_Type jq_type) {
438         java.lang.Object o = new Class(jq_type);
439         return (java.lang.Class)o;
440     }
441     
442     public static jq_Type getJQType(java.lang.Class f) {
443         java.lang.Object o = f;
444         return ((Class)o).jq_type;
445     }
446     
447     public static Utf8 buildMethodDescriptor(java.lang.Class[] args, java.lang.Class returnType) {
448         java.lang.StringBuffer sb = new java.lang.StringBuffer();
449         sb.append('(');
450         for (int i=0; i<args.length; ++i) {
451             sb.append(Reflection.getJQType(args[i]).getDesc().toString());
452         }
453         sb.append(')');
454         if (returnType == null) sb.append('V');
455         else sb.append(Reflection.getJQType(returnType).getDesc().toString());
456         return Utf8.get(sb.toString());
457     }
458 }