KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > aspectwerkz > reflect > impl > java > JavaClassInfo


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.aspectwerkz.reflect.impl.java;
5
6 import com.tc.backport175.bytecode.AnnotationElement;
7 import com.tc.backport175.bytecode.AnnotationReader;
8
9 import com.tc.aspectwerkz.reflect.ClassInfo;
10 import com.tc.aspectwerkz.reflect.ConstructorInfo;
11 import com.tc.aspectwerkz.reflect.FieldInfo;
12 import com.tc.aspectwerkz.reflect.MethodInfo;
13 import com.tc.aspectwerkz.reflect.ReflectHelper;
14 import com.tc.aspectwerkz.reflect.StaticInitializationInfo;
15 import com.tc.aspectwerkz.reflect.StaticInitializationInfoImpl;
16 import com.tc.aspectwerkz.reflect.impl.asm.AsmClassInfo;
17 import com.tc.aspectwerkz.transform.TransformationConstants;
18
19 import java.lang.reflect.Constructor JavaDoc;
20 import java.lang.reflect.Field JavaDoc;
21 import java.lang.reflect.Method JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Iterator JavaDoc;
24
25 /**
26  * Implementation of the ClassInfo interface for java.lang.reflect.*.
27  *
28  * @author <a HREF="mailto:jboner@codehaus.org">Jonas BonŽr </a>
29  */

30 public class JavaClassInfo implements ClassInfo {
31   /**
32    * The class.
33    */

34   // TODO might be safer to wrap this member in a weak ref
35
private final Class JavaDoc m_class;
36
37   /**
38    * The name of the class.
39    */

40   private String JavaDoc m_name;
41
42   /**
43    * The signature of the class.
44    */

45   private String JavaDoc m_signature;
46
47   /**
48    * Is the class an interface.
49    */

50   private boolean m_isInterface = false;
51
52   /**
53    * Is the class a primitive type.
54    */

55   private boolean m_isPrimitive = false;
56
57   /**
58    * Is the class of type array.
59    */

60   private boolean m_isArray = false;
61
62   /**
63    * A list with the <code>ConstructorInfo</code> instances.
64    */

65   private final HashMap JavaDoc m_constructors = new HashMap JavaDoc();
66
67   /**
68    * A list with the <code>MethodInfo</code> instances.
69    */

70   private final HashMap JavaDoc m_methods = new HashMap JavaDoc();
71
72   /**
73    * A list with the <code>FieldInfo</code> instances.
74    */

75   private final HashMap JavaDoc m_fields = new HashMap JavaDoc();
76
77   /**
78    * A list with the interfaces.
79    */

80   private ClassInfo[] m_interfaces = null;
81
82   /**
83    * The super class.
84    */

85   private ClassInfo m_superClass = null;
86
87   /**
88    * The component type if array type.
89    */

90   private ClassInfo m_componentType = null;
91
92   /**
93    * The class info repository.
94    */

95   private final JavaClassInfoRepository m_classInfoRepository;
96
97   /**
98    * Lazy, the static initializer info or null if not present
99    */

100   private StaticInitializationInfo m_staticInitializer = null;
101
102   /**
103    * Creates a new class meta data instance.
104    *
105    * @param klass
106    */

107   JavaClassInfo(final Class JavaDoc klass) {
108     if (klass == null) {
109       throw new IllegalArgumentException JavaDoc("class can not be null");
110     }
111     m_class = klass;
112
113     m_signature = ReflectHelper.getClassSignature(klass);
114
115     m_classInfoRepository = JavaClassInfoRepository.getRepository(klass.getClassLoader());
116     m_isInterface = klass.isInterface();
117     if (klass.isPrimitive()) {
118       m_name = klass.getName();
119       m_isPrimitive = true;
120     } else if (klass.getComponentType() != null) {
121       m_name = convertJavaArrayTypeNameToHumanTypeName(klass.getName());
122       m_isArray = true;
123       m_interfaces = new ClassInfo[0];
124     } else {
125       m_name = klass.getName();
126       Method JavaDoc[] methods = m_class.getDeclaredMethods();
127       for (int i = 0; i < methods.length; i++) {
128         Method JavaDoc method = methods[i];
129         m_methods.put(new Integer JavaDoc(ReflectHelper.calculateHash(method)), new JavaMethodInfo(method, this));
130       }
131       Constructor JavaDoc[] constructors = m_class.getDeclaredConstructors();
132       for (int i = 0; i < constructors.length; i++) {
133         Constructor JavaDoc constructor = constructors[i];
134         m_constructors.put(new Integer JavaDoc(ReflectHelper.calculateHash(constructor)), //
135
new JavaConstructorInfo(constructor, this));
136       }
137       Field JavaDoc[] fields = m_class.getDeclaredFields();
138       for (int i = 0; i < fields.length; i++) {
139         if (fields[i].getName().startsWith(TransformationConstants.ASPECTWERKZ_PREFIX)) {
140           continue;
141         }
142         Field JavaDoc field = fields[i];
143         m_fields.put(new Integer JavaDoc(ReflectHelper.calculateHash(field)), new JavaFieldInfo(field, this));
144       }
145     }
146     m_classInfoRepository.addClassInfo(this);
147   }
148
149   /**
150    * Returns the class info for a specific class.
151    *
152    * @return the class info
153    */

154   public static ClassInfo getClassInfo(final Class JavaDoc clazz) {
155     JavaClassInfoRepository repository = JavaClassInfoRepository.getRepository(clazz.getClassLoader());
156     ClassInfo classInfo = repository.getClassInfo(clazz.getName());
157     if (classInfo == null) {
158       classInfo = new JavaClassInfo(clazz);
159     }
160     return classInfo;
161   }
162
163   /**
164    * Returns the annotations.
165    *
166    * @return the annotations
167    */

168   public AnnotationElement.Annotation[] getAnnotations() {
169     return getAnnotationReader().getAnnotationElements();
170   }
171
172   /**
173    * Returns the name of the class.
174    *
175    * @return the name of the class
176    */

177   public String JavaDoc getName() {
178     return m_name.replace('/', '.');
179   }
180
181   /**
182    * Checks if the class has a static initalizer.
183    *
184    * @return
185    */

186   public boolean hasStaticInitializer() {
187     ClassInfo classInfo = AsmClassInfo.getClassInfo(getName(), getClassLoader());
188     return classInfo.hasStaticInitializer();
189   }
190
191   /**
192    * Returns the static initializer info of the current underlying class if any.
193    *
194    * @see ClassInfo#staticInitializer()
195    */

196   public StaticInitializationInfo staticInitializer() {
197     if (hasStaticInitializer() && m_staticInitializer == null) {
198       m_staticInitializer = new StaticInitializationInfoImpl(this);
199     }
200     return m_staticInitializer;
201   }
202
203   /**
204    * Returns the signature for the element.
205    *
206    * @return the signature for the element
207    */

208   public String JavaDoc getSignature() {
209     return m_signature;
210   }
211
212   public String JavaDoc getGenericsSignature() {
213     // ClassInfo classInfo = AsmClassInfo.getClassInfo(getName(), getClassLoader());
214
return null;
215   }
216
217   /**
218    * Returns the class modifiers.
219    *
220    * @return the class modifiers
221    */

222   public int getModifiers() {
223     return m_class.getModifiers();
224   }
225
226   /**
227    * Returns the class loader that loaded this class.
228    *
229    * @return the class loader
230    */

231   public ClassLoader JavaDoc getClassLoader() {
232     return m_class.getClassLoader();
233   }
234
235   /**
236    * Returns a constructor info by its hash.
237    *
238    * @param hash
239    * @return
240    */

241   public ConstructorInfo getConstructor(final int hash) {
242     ConstructorInfo constructor = (ConstructorInfo) m_constructors.get(new Integer JavaDoc(hash));
243     if (constructor == null && getSuperclass() != null) {
244       constructor = getSuperclass().getConstructor(hash);
245     }
246     return constructor;
247   }
248
249   /**
250    * Returns a list with all the constructors info.
251    *
252    * @return the constructors info
253    */

254   public ConstructorInfo[] getConstructors() {
255     ConstructorInfo[] methodInfos = new ConstructorInfo[m_constructors.size()];
256 // Object[] values = m_constructors.getValues();
257
// for (int i = 0; i < values.length; i++) {
258
// methodInfos[i] = (ConstructorInfo) values[i];
259
int i = 0;
260     for (Iterator JavaDoc it = m_constructors.values().iterator(); it.hasNext();) {
261       methodInfos[i++] = (ConstructorInfo) it.next();
262     }
263     return methodInfos;
264   }
265
266   /**
267    * Returns a method info by its hash.
268    *
269    * @param hash
270    * @return
271    */

272   public MethodInfo getMethod(final int hash) {
273     MethodInfo method = (MethodInfo) m_methods.get(new Integer JavaDoc(hash));
274     if (method == null) {
275       for (int i = 0; i < getInterfaces().length; i++) {
276         method = getInterfaces()[i].getMethod(hash);
277         if (method != null) {
278           break;
279         }
280       }
281     }
282     if (method == null && getSuperclass() != null) {
283       method = getSuperclass().getMethod(hash);
284     }
285     return method;
286   }
287
288   /**
289    * Returns a list with all the methods info.
290    *
291    * @return the methods info
292    */

293   public MethodInfo[] getMethods() {
294     MethodInfo[] methodInfos = new MethodInfo[m_methods.size()];
295 // Object[] values = m_methods.getValues();
296
// for (int i = 0; i < values.length; i++) {
297
// methodInfos[i] = (MethodInfo) values[i];
298
int i = 0;
299     for (Iterator JavaDoc it = m_methods.values().iterator(); it.hasNext();) {
300       methodInfos[i++] = (MethodInfo) it.next();
301     }
302     return methodInfos;
303   }
304
305   /**
306    * Returns a field info by its hash.
307    *
308    * @param hash
309    * @return
310    */

311   public FieldInfo getField(final int hash) {
312     FieldInfo field = (FieldInfo) m_fields.get(new Integer JavaDoc(hash));
313     if (field == null && getSuperclass() != null) {
314       field = getSuperclass().getField(hash);
315     }
316     if (field == null) {
317       // Trying to find constants in Interfaces
318
ClassInfo[] interfaces = getInterfaces();
319       for (int i = 0; i < interfaces.length; i++) {
320         ClassInfo ifc = interfaces[i];
321         field = ifc.getField(hash);
322         if (field != null)
323           break;
324       }
325     }
326     return field;
327   }
328
329   /**
330    * Returns a list with all the field info.
331    *
332    * @return the field info
333    */

334   public FieldInfo[] getFields() {
335     FieldInfo[] fieldInfos = new FieldInfo[m_fields.size()];
336 // Object[] values = m_fields.getValues();
337
// for (int i = 0; i < values.length; i++) {
338
// fieldInfos[i] = (FieldInfo) values[i];
339
int i = 0;
340     for (Iterator JavaDoc it = m_methods.values().iterator(); it.hasNext();) {
341       fieldInfos[i++] = (FieldInfo) it.next();
342     }
343     return fieldInfos;
344   }
345
346   /**
347    * Returns the interfaces.
348    *
349    * @return the interfaces
350    */

351   public synchronized ClassInfo[] getInterfaces() {
352     if (m_interfaces == null) {
353       Class JavaDoc[] interfaces = m_class.getInterfaces();
354       m_interfaces = new ClassInfo[interfaces.length];
355       for (int i = 0; i < interfaces.length; i++) {
356         Class JavaDoc anInterface = interfaces[i];
357         ClassInfo classInfo = JavaClassInfo.getClassInfo(anInterface);
358         m_interfaces[i] = classInfo;
359         if (!m_classInfoRepository.hasClassInfo(anInterface.getName())) {
360           m_classInfoRepository.addClassInfo(classInfo);
361         }
362       }
363     }
364     return m_interfaces;
365   }
366
367   /**
368    * Returns the super class.
369    *
370    * @return the super class
371    */

372   public ClassInfo getSuperclass() {
373     if (m_superClass == null) {
374       Class JavaDoc superclass = m_class.getSuperclass();
375       if (superclass != null) {
376         if (m_classInfoRepository.hasClassInfo(superclass.getName())) {
377           m_superClass = m_classInfoRepository.getClassInfo(superclass.getName());
378         } else {
379           m_superClass = JavaClassInfo.getClassInfo(superclass);
380           m_classInfoRepository.addClassInfo(m_superClass);
381         }
382       }
383     }
384     return m_superClass;
385   }
386
387   /**
388    * Returns the component type if array type else null.
389    *
390    * @return the component type
391    */

392   public ClassInfo getComponentType() {
393     if (isArray() && (m_componentType == null)) {
394       Class JavaDoc componentType = m_class.getComponentType();
395       if (m_classInfoRepository.hasClassInfo(componentType.getName())) {
396         m_componentType = m_classInfoRepository.getClassInfo(componentType.getName());
397       } else {
398         m_componentType = JavaClassInfo.getClassInfo(componentType);
399         m_classInfoRepository.addClassInfo(m_componentType);
400       }
401     }
402     return m_componentType;
403   }
404
405   /**
406    * Is the class an interface.
407    *
408    * @return
409    */

410   public boolean isInterface() {
411     return m_isInterface;
412   }
413
414   /**
415    * Is the class a primitive type.
416    *
417    * @return
418    */

419   public boolean isPrimitive() {
420     return m_isPrimitive;
421   }
422
423   /**
424    * Is the class an array type.
425    *
426    * @return
427    */

428   public boolean isArray() {
429     return m_isArray;
430   }
431
432   /**
433    * Converts an internal Java array type name ([Lblabla) to the a the format used by the expression matcher
434    * (blabla[])
435    *
436    * @param typeName is type name
437    * @return
438    */

439   public static String JavaDoc convertJavaArrayTypeNameToHumanTypeName(final String JavaDoc typeName) {
440     int index = typeName.lastIndexOf('[');
441     if (index != -1) {
442       StringBuffer JavaDoc arrayType = new StringBuffer JavaDoc();
443       if (typeName.endsWith("I")) {
444         arrayType.append("int");
445       } else if (typeName.endsWith("J")) {
446         arrayType.append("long");
447       } else if (typeName.endsWith("S")) {
448         arrayType.append("short");
449       } else if (typeName.endsWith("F")) {
450         arrayType.append("float");
451       } else if (typeName.endsWith("D")) {
452         arrayType.append("double");
453       } else if (typeName.endsWith("Z")) {
454         arrayType.append("boolean");
455       } else if (typeName.endsWith("C")) {
456         arrayType.append("char");
457       } else if (typeName.endsWith("B")) {
458         arrayType.append("byte");
459       } else {
460         arrayType.append(typeName.substring(index + 2, typeName.length() - 1));
461       }
462       for (int i = 0; i < (index + 1); i++) {
463         arrayType.append("[]");
464       }
465       return arrayType.toString();
466     } else {
467       return typeName;
468     }
469   }
470
471   public boolean equals(Object JavaDoc o) {
472     if (this == o) {
473       return true;
474     }
475     if (!(o instanceof ClassInfo)) {
476       return false;
477     }
478     ClassInfo classInfo = (ClassInfo) o;
479     return m_class.getName().toString().equals(classInfo.getName().toString());
480   }
481
482   public int hashCode() {
483     return m_class.getName().toString().hashCode();
484   }
485
486   public String JavaDoc toString() {
487     return getName();
488   }
489
490   public AnnotationReader getAnnotationReader() {
491     return AnnotationReader.getReaderFor(m_class);
492   }
493 }
Popular Tags