KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > reflect > impl > java > JavaClassInfo


1 /**************************************************************************************
2  * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
3  * http://aspectwerkz.codehaus.org *
4  * ---------------------------------------------------------------------------------- *
5  * The software in this package is published under the terms of the LGPL license *
6  * a copy of which has been included with this distribution in the license.txt file. *
7  **************************************************************************************/

8 package org.codehaus.aspectwerkz.reflect.impl.java;
9
10 import gnu.trove.TIntObjectHashMap;
11 import org.codehaus.aspectwerkz.annotation.Annotations;
12 import org.codehaus.aspectwerkz.reflect.ClassInfo;
13 import org.codehaus.aspectwerkz.reflect.ConstructorInfo;
14 import org.codehaus.aspectwerkz.reflect.FieldInfo;
15 import org.codehaus.aspectwerkz.reflect.MethodInfo;
16 import org.codehaus.aspectwerkz.reflect.ReflectHelper;
17 import org.codehaus.aspectwerkz.reflect.ReflectHelper;
18 import org.codehaus.aspectwerkz.reflect.StaticInitializationInfo;
19 import org.codehaus.aspectwerkz.reflect.StaticInitializationInfoImpl;
20 import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo;
21 import org.codehaus.aspectwerkz.transform.TransformationConstants;
22
23 import java.lang.reflect.Constructor JavaDoc;
24 import java.lang.reflect.Field JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.util.List JavaDoc;
27
28 /**
29  * Implementation of the ClassInfo interface for java.lang.reflect.*.
30  *
31  * @author <a HREF="mailto:jboner@codehaus.org">Jonas Bonér </a>
32  */

33 public class JavaClassInfo implements ClassInfo {
34     /**
35      * The class.
36      */

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

43     private String JavaDoc m_name;
44
45     /**
46      * The signature of the class.
47      */

48     private String JavaDoc m_signature;
49
50     /**
51      * Is the class an interface.
52      */

53     private boolean m_isInterface = false;
54
55     /**
56      * Is the class a primitive type.
57      */

58     private boolean m_isPrimitive = false;
59
60     /**
61      * Is the class of type array.
62      */

63     private boolean m_isArray = false;
64
65     /**
66      * A list with the <code>ConstructorInfo</code> instances.
67      */

68     private final TIntObjectHashMap m_constructors = new TIntObjectHashMap();
69
70     /**
71      * A list with the <code>MethodInfo</code> instances.
72      */

73     private final TIntObjectHashMap m_methods = new TIntObjectHashMap();
74
75     /**
76      * A list with the <code>FieldInfo</code> instances.
77      */

78     private final TIntObjectHashMap m_fields = new TIntObjectHashMap();
79
80     /**
81      * A list with the interfaces.
82      */

83     private ClassInfo[] m_interfaces = null;
84
85     /**
86      * The super class.
87      */

88     private ClassInfo m_superClass = null;
89
90     /**
91      * The annotations.
92      */

93     private List JavaDoc m_annotations = null;
94
95     /**
96      * The component type if array type.
97      */

98     private ClassInfo m_componentType = null;
99
100     /**
101      * The class info repository.
102      */

103     private final JavaClassInfoRepository m_classInfoRepository;
104
105     /**
106      * Lazy, the static initializer info or null if not present
107      */

108     private StaticInitializationInfo m_staticInitializer = null;
109
110     /**
111      * Creates a new class meta data instance.
112      *
113      * @param klass
114      */

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

166     public static ClassInfo getClassInfo(final Class JavaDoc clazz) {
167         JavaClassInfoRepository repository = JavaClassInfoRepository.getRepository(clazz.getClassLoader());
168         ClassInfo classInfo = repository.getClassInfo(clazz.getName());
169         if (classInfo == null) {
170             classInfo = new JavaClassInfo(clazz);
171         }
172         return classInfo;
173     }
174
175     /**
176      * Returns the annotations infos.
177      *
178      * @return the annotations infos
179      */

180     public List JavaDoc getAnnotations() {
181         if (m_annotations == null) {
182             // TODO this means that JavaClassInfo is always using AsmClassInfo to get that annotations
183
// TODO should optimize for Java5
184
m_annotations = Annotations.getAnnotationInfos(m_class);
185         }
186         return m_annotations;
187     }
188
189     /**
190      * Returns the name of the class.
191      *
192      * @return the name of the class
193      */

194     public String JavaDoc getName() {
195         return m_name.replace('/', '.');
196     }
197
198     /**
199      * Checks if the class has a static initalizer.
200      *
201      * @return
202      */

203     public boolean hasStaticInitializer() {
204         ClassInfo classInfo = AsmClassInfo.getClassInfo(getName(), getClassLoader());
205         return classInfo.hasStaticInitializer();
206     }
207
208     /**
209      * Returns the static initializer info of the current underlying class if any.
210      *
211      * @see org.codehaus.aspectwerkz.reflect.ClassInfo#staticInitializer()
212      */

213     public StaticInitializationInfo staticInitializer() {
214         if(hasStaticInitializer() && m_staticInitializer == null) {
215             m_staticInitializer = new StaticInitializationInfoImpl(this);
216         }
217         return m_staticInitializer;
218     }
219     
220     /**
221      * Returns the signature for the element.
222      *
223      * @return the signature for the element
224      */

225     public String JavaDoc getSignature() {
226         return m_signature;
227     }
228
229     /**
230      * Returns the class modifiers.
231      *
232      * @return the class modifiers
233      */

234     public int getModifiers() {
235         return m_class.getModifiers();
236     }
237
238     /**
239      * Returns the class loader that loaded this class.
240      *
241      * @return the class loader
242      */

243     public ClassLoader JavaDoc getClassLoader() {
244         return m_class.getClassLoader();
245     }
246
247     /**
248      * Returns a constructor info by its hash.
249      *
250      * @param hash
251      * @return
252      */

253     public ConstructorInfo getConstructor(final int hash) {
254         ConstructorInfo constructor = (ConstructorInfo) m_constructors.get(hash);
255         if (constructor == null && getSuperclass() != null) {
256             constructor = getSuperclass().getConstructor(hash);
257         }
258         return constructor;
259     }
260
261     /**
262      * Returns a list with all the constructors info.
263      *
264      * @return the constructors info
265      */

266     public ConstructorInfo[] getConstructors() {
267         Object JavaDoc[] values = m_constructors.getValues();
268         ConstructorInfo[] methodInfos = new ConstructorInfo[values.length];
269         for (int i = 0; i < values.length; i++) {
270             methodInfos[i] = (ConstructorInfo) values[i];
271         }
272         return methodInfos;
273     }
274
275     /**
276      * Returns a method info by its hash.
277      *
278      * @param hash
279      * @return
280      */

281     public MethodInfo getMethod(final int hash) {
282         MethodInfo method = (MethodInfo) m_methods.get(hash);
283         if (method == null) {
284             for (int i = 0; i < getInterfaces().length; i++) {
285                 method = getInterfaces()[i].getMethod(hash);
286                 if (method != null) {
287                     break;
288                 }
289             }
290         }
291         if (method == null && getSuperclass() != null) {
292             method = getSuperclass().getMethod(hash);
293         }
294         return method;
295     }
296
297     /**
298      * Returns a list with all the methods info.
299      *
300      * @return the methods info
301      */

302     public MethodInfo[] getMethods() {
303         Object JavaDoc[] values = m_methods.getValues();
304         MethodInfo[] methodInfos = new MethodInfo[values.length];
305         for (int i = 0; i < values.length; i++) {
306             methodInfos[i] = (MethodInfo) values[i];
307         }
308         return methodInfos;
309     }
310
311     /**
312      * Returns a field info by its hash.
313      *
314      * @param hash
315      * @return
316      */

317     public FieldInfo getField(final int hash) {
318         FieldInfo field = (FieldInfo) m_fields.get(hash);
319         if (field == null && getSuperclass() != null) {
320             field = getSuperclass().getField(hash);
321         }
322         return field;
323     }
324
325     /**
326      * Returns a list with all the field info.
327      *
328      * @return the field info
329      */

330     public FieldInfo[] getFields() {
331         Object JavaDoc[] values = m_fields.getValues();
332         FieldInfo[] fieldInfos = new FieldInfo[values.length];
333         for (int i = 0; i < values.length; i++) {
334             fieldInfos[i] = (FieldInfo) values[i];
335         }
336         return fieldInfos;
337     }
338
339     /**
340      * Returns the interfaces.
341      *
342      * @return the interfaces
343      */

344     public ClassInfo[] getInterfaces() {
345         if (m_interfaces == null) {
346             Class JavaDoc[] interfaces = m_class.getInterfaces();
347             m_interfaces = new ClassInfo[interfaces.length];
348             for (int i = 0; i < interfaces.length; i++) {
349                 Class JavaDoc anInterface = interfaces[i];
350                 ClassInfo classInfo = JavaClassInfo.getClassInfo(anInterface);
351                 m_interfaces[i] = classInfo;
352                 if (!m_classInfoRepository.hasClassInfo(anInterface.getName())) {
353                     m_classInfoRepository.addClassInfo(classInfo);
354                 }
355             }
356         }
357         return m_interfaces;
358     }
359
360     /**
361      * Returns the super class.
362      *
363      * @return the super class
364      */

365     public ClassInfo getSuperclass() {
366         if (m_superClass == null) {
367             Class JavaDoc superclass = m_class.getSuperclass();
368             if (superclass != null) {
369                 if (m_classInfoRepository.hasClassInfo(superclass.getName())) {
370                     m_superClass = m_classInfoRepository.getClassInfo(superclass.getName());
371                 } else {
372                     m_superClass = JavaClassInfo.getClassInfo(superclass);
373                     m_classInfoRepository.addClassInfo(m_superClass);
374                 }
375             }
376         }
377         return m_superClass;
378     }
379
380     /**
381      * Returns the component type if array type else null.
382      *
383      * @return the component type
384      */

385     public ClassInfo getComponentType() {
386         if (isArray() && (m_componentType == null)) {
387             Class JavaDoc componentType = m_class.getComponentType();
388             if (m_classInfoRepository.hasClassInfo(componentType.getName())) {
389                 m_componentType = m_classInfoRepository.getClassInfo(componentType.getName());
390             } else {
391                 m_componentType = JavaClassInfo.getClassInfo(componentType);
392                 m_classInfoRepository.addClassInfo(m_componentType);
393             }
394         }
395         return m_componentType;
396     }
397
398     /**
399      * Is the class an interface.
400      *
401      * @return
402      */

403     public boolean isInterface() {
404         return m_isInterface;
405     }
406
407     /**
408      * Is the class a primitive type.
409      *
410      * @return
411      */

412     public boolean isPrimitive() {
413         return m_isPrimitive;
414     }
415
416     /**
417      * Is the class an array type.
418      *
419      * @return
420      */

421     public boolean isArray() {
422         return m_isArray;
423     }
424
425     /**
426      * Converts an internal Java array type name ([Lblabla) to the a the format used by the expression matcher
427      * (blabla[])
428      *
429      * @param typeName is type name
430      * @return
431      */

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