KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > aspectwerkz > reflect > ClassInfoHelper


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;
5
6
7 import com.tc.aspectwerkz.reflect.impl.asm.AsmClassInfo;
8 import com.tc.aspectwerkz.transform.TransformationConstants;
9
10 import java.util.ArrayList JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.HashSet JavaDoc;
13 import java.util.Iterator JavaDoc;
14 import java.util.List JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.Set JavaDoc;
17
18 /**
19  * Utility method for manipulating and managing ClassInfo hierarchies.
20  *
21  * @author <a HREF="mailto:jboner@codehaus.org">Jonas BonŽr </a>
22  * @author <a HREF="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
23  */

24 public class ClassInfoHelper {
25   private static final List JavaDoc EMPTY_ARRAY_LIST = new ArrayList JavaDoc();
26   private static final String JavaDoc OBJECT_CLASS_NAME = "java.lang.Object";
27
28   /**
29    * Checks if a class has a certain class as super class or interface, somewhere up in the class hierarchy.
30    *
31    * @param classInfo the meta-data for the class to parse
32    * @param superclassName the name of the super class or interface
33    * @return true if we have a parse else false
34    */

35   public static boolean instanceOf(final ClassInfo classInfo, final String JavaDoc superclassName) {
36     return implementsInterface(classInfo, superclassName) || extendsSuperClass(classInfo, superclassName);
37   }
38
39   /**
40    * Checks if a class implements a certain inteface, somewhere up in the class hierarchy, excluding
41    * itself.
42    *
43    * @param classInfo
44    * @param interfaceName
45    * @return true if we have a parse else false
46    */

47   public static boolean implementsInterface(final ClassInfo classInfo, final String JavaDoc interfaceName) {
48     if ((classInfo == null) || (interfaceName == null)) {
49       return false;
50     } else {
51       //TODO: we could lookup in names onlny FIRST to not trigger lazy getInterfaces() stuff
52
ClassInfo[] interfaces = classInfo.getInterfaces();
53       for (int i = 0; i < interfaces.length; i++) {
54         ClassInfo anInterface = interfaces[i];
55         if (interfaceName.equals(anInterface.getName())) {
56           return true;
57         } else if (ClassInfoHelper.implementsInterface(anInterface, interfaceName)) {
58           return true;
59         }
60       }
61       return ClassInfoHelper.implementsInterface(classInfo.getSuperclass(), interfaceName);
62     }
63   }
64
65   /**
66    * Checks if a class has a certain class as super class, somewhere up in the class hierarchy.
67    *
68    * @param classInfo the meta-data for the class to parse
69    * @param className the name of the super class
70    * @return true if we have a parse else false
71    */

72   public static boolean extendsSuperClass(final ClassInfo classInfo, final String JavaDoc className) {
73     if ((classInfo == null) || (className == null)) {
74       return false;
75       // TODO odd comparison
76
// } else if (classInfo.getName().equals(null)) {
77
// return true;
78
} else if (className.equals(classInfo.getName())) {
79       return true;
80     } else {
81       return ClassInfoHelper.extendsSuperClass(classInfo.getSuperclass(), className);
82     }
83   }
84
85   /**
86    * Creates a method list of all the methods in the class and super classes, including package private ones.
87    * Inherited methods are last in the list.
88    *
89    * @param klass the class with the methods
90    * @return the sorted method list
91    */

92   public static List JavaDoc createMethodList(final ClassInfo klass) {
93     if (klass == null) {
94       return EMPTY_ARRAY_LIST;
95     }
96
97     // getDefault this klass methods
98
List JavaDoc methods = new ArrayList JavaDoc();
99     MethodInfo[] methodInfos = klass.getMethods();
100     for (int i = 0; i < methodInfos.length; i++) {
101       MethodInfo methodInfo = methodInfos[i];
102       if (isUserDefinedMethod(methodInfo)) {
103         methods.add(methodInfo);
104       }
105     }
106
107     // get all the inherited methods, as long as they are user defined ones
108
ClassInfo superClass = klass.getSuperclass();
109     if (superClass != null && !superClass.getName().equals(OBJECT_CLASS_NAME)) {
110       List JavaDoc parentMethods = createMethodList(superClass);
111       // merge the method list (parent discovered methods are not added if overrided in this klass)
112
for (Iterator JavaDoc iterator = parentMethods.iterator(); iterator.hasNext();) {
113         MethodInfo parentMethod = (MethodInfo) iterator.next();
114         if (!methods.contains(parentMethod)) { // TODO seems to work but ? since tied to declaringTypeName
115
methods.add(parentMethod);
116         }
117       }
118     }
119     return methods;
120   }
121
122   /**
123    * Collects the methods from all the interface and its super interfaces.
124    *
125    * @param interfaceClassInfo
126    * @return list of methods declared in given class interfaces
127    */

128   public static List JavaDoc collectMethodsFromInterface(final ClassInfo interfaceClassInfo) {
129     final List JavaDoc interfaceDeclaredMethods = new ArrayList JavaDoc();
130     final List JavaDoc sortedMethodList = createMethodList(interfaceClassInfo);
131     for (Iterator JavaDoc it = sortedMethodList.iterator(); it.hasNext();) {
132       MethodInfo methodInfo = (MethodInfo) it.next();
133       if (methodInfo.getDeclaringType().getName().equals(OBJECT_CLASS_NAME)) {
134         continue;
135       }
136       interfaceDeclaredMethods.add(methodInfo);
137     }
138     // grab methods from all super classes' interfaces
139
ClassInfo superClass = interfaceClassInfo.getSuperclass();
140     if (superClass != null && !superClass.getName().equals(OBJECT_CLASS_NAME)) {
141       interfaceDeclaredMethods.addAll(collectMethodsFromInterfacesImplementedBy(superClass));
142     }
143     return interfaceDeclaredMethods;
144   }
145
146   /**
147    * Collects the methods from all the interfaces of the class and its super interfaces.
148    *
149    * @param classInfo
150    * @return list of methods declared in given class interfaces
151    */

152   public static List JavaDoc collectMethodsFromInterfacesImplementedBy(final ClassInfo classInfo) {
153     final List JavaDoc interfaceDeclaredMethods = new ArrayList JavaDoc();
154     ClassInfo[] interfaces = classInfo.getInterfaces();
155
156     // grab methods from all interfaces and their super interfaces
157
for (int i = 0; i < interfaces.length; i++) {
158       final List JavaDoc sortedMethodList = createMethodList(interfaces[i]);
159       for (Iterator JavaDoc it = sortedMethodList.iterator(); it.hasNext();) {
160         MethodInfo methodInfo = (MethodInfo) it.next();
161         if (methodInfo.getDeclaringType().getName().equals(OBJECT_CLASS_NAME)) {
162           continue;
163         }
164         interfaceDeclaredMethods.add(methodInfo);
165       }
166     }
167     // grab methods from all super classes' interfaces
168
ClassInfo superClass = classInfo.getSuperclass();
169     if (superClass != null && !superClass.getName().equals(OBJECT_CLASS_NAME)) {
170       interfaceDeclaredMethods.addAll(collectMethodsFromInterfacesImplementedBy(superClass));
171     }
172     return interfaceDeclaredMethods;
173   }
174
175   /**
176    * Creates a method list of all the methods in the class and super classes, if and only
177    * if those are part of the given list of interfaces declared methods.
178    *
179    * @param klass the class with the methods
180    * @param interfaceDeclaredMethods the list of interface declared methods
181    * @return the sorted method list
182    */

183   public static List JavaDoc createInterfaceDefinedMethodList(final ClassInfo klass,
184                                                       final List JavaDoc interfaceDeclaredMethods) {
185     if (klass == null) {
186       throw new IllegalArgumentException JavaDoc("class to sort method on can not be null");
187     }
188     // getDefault all methods including the inherited methods
189
List JavaDoc methodList = new ArrayList JavaDoc();
190     for (Iterator JavaDoc iterator = createMethodList(klass).iterator(); iterator.hasNext();) {
191       MethodInfo methodInfo = (MethodInfo) iterator.next();
192       if (isDeclaredByInterface(methodInfo, interfaceDeclaredMethods)) {
193         methodList.add(methodInfo);
194       }
195     }
196     return methodList;
197   }
198
199   /**
200    * Returns true if the method is not of on java.lang.Object and is not an AW generated one
201    *
202    * @param method
203    * @return bool
204    */

205   private static boolean isUserDefinedMethod(final MethodInfo method) {
206     if (!method.getName().startsWith(TransformationConstants.SYNTHETIC_MEMBER_PREFIX)
207             && !method.getName().startsWith(TransformationConstants.ORIGINAL_METHOD_PREFIX)
208             && !method.getName().startsWith(TransformationConstants.ASPECTWERKZ_PREFIX)) {
209       return true;
210     } else {
211       return false;
212     }
213   }
214
215   /**
216    * Returns true if the method is declared by one of the given method declared in an interface class
217    *
218    * @param method
219    * @param interfaceDeclaredMethods
220    * @return bool
221    */

222   private static boolean isDeclaredByInterface(final MethodInfo method, final List JavaDoc interfaceDeclaredMethods) {
223     boolean match = false;
224     for (Iterator JavaDoc iterator = interfaceDeclaredMethods.iterator(); iterator.hasNext();) {
225       MethodInfo methodIt = (MethodInfo) iterator.next();
226       if (method.getName().equals(methodIt.getName())) {
227         // TODO - using param type NAME should be enough - optimize
228
if (method.getParameterTypes().length == methodIt.getParameterTypes().length) {
229           boolean matchArgs = true;
230           for (int i = 0; i < method.getParameterTypes().length; i++) {
231             ClassInfo parameterType = method.getParameterTypes()[i];
232             if (parameterType.getName().equals(methodIt.getParameterTypes()[i].getName())) {
233               ;
234             } else {
235               matchArgs = false;
236               break;
237             }
238           }
239           if (matchArgs) {
240             match = true;
241             break;
242           }
243         }
244       }
245     }
246     return match;
247   }
248
249   /**
250    * Collects all the interface from the given class including the one from its super class.
251    *
252    * @param classInfo
253    * @return list of interface classInfo declared in given class and its hierarchy in correct order
254    */

255   public static List JavaDoc collectInterfaces(final ClassInfo classInfo) {
256     final List JavaDoc interfaceList = new ArrayList JavaDoc();
257     final Set JavaDoc interfaceNames = new HashSet JavaDoc();
258     for (int i = 0; i < classInfo.getInterfaces().length; i++) {
259       ClassInfo interfaceInfo = classInfo.getInterfaces()[i];
260       interfaceList.add(interfaceInfo);
261       interfaceNames.add(interfaceInfo.getName());
262     }
263     for (ClassInfo superClass = classInfo.getSuperclass(); superClass != null; superClass =
264             superClass.getSuperclass()) {
265       for (int i = 0; i < superClass.getInterfaces().length; i++) {
266         ClassInfo interfaceInfo = superClass.getInterfaces()[i];
267         if (!interfaceNames.contains(interfaceInfo.getName())) {
268           interfaceList.add(interfaceInfo);
269           interfaceNames.add(interfaceInfo.getName());
270         }
271       }
272     }
273     return interfaceList;
274   }
275
276   /**
277    * Checks if a set of interfaces has any clashes, meaning any methods with the same name and signature.
278    *
279    * @param interfacesToAdd
280    * @param loader
281    * @return boolean
282    */

283   public static boolean hasMethodClash(final Set JavaDoc interfacesToAdd, final ClassLoader JavaDoc loader) {
284     // build up the validation structure
285
Map JavaDoc methodMap = new HashMap JavaDoc();
286     for (Iterator JavaDoc it = interfacesToAdd.iterator(); it.hasNext();) {
287       ClassInfo classInfo = AsmClassInfo.getClassInfo((String JavaDoc) it.next(), loader);
288
289       List JavaDoc methods = collectMethodsFromInterface(classInfo);
290
291       for (Iterator JavaDoc it2 = methods.iterator(); it2.hasNext();) {
292         MethodInfo methodInfo = (MethodInfo) it2.next();
293         String JavaDoc key = methodInfo.getName() + ':' + methodInfo.getSignature();
294         if (!methodMap.containsKey(key)) {
295           methodMap.put(key, new ArrayList JavaDoc());
296         }
297         ((List JavaDoc) methodMap.get(key)).add(classInfo.getName());
298       }
299     }
300
301     // validate the structure
302
for (Iterator JavaDoc it = methodMap.entrySet().iterator(); it.hasNext();) {
303       Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
304       String JavaDoc key = (String JavaDoc) entry.getKey();
305       List JavaDoc interfaceNames = (List JavaDoc) entry.getValue();
306       if (interfaceNames.size() > 1) {
307         StringBuffer JavaDoc msg = new StringBuffer JavaDoc();
308         msg.append("can not add interfaces [");
309         for (Iterator JavaDoc it2 = interfaceNames.iterator(); it2.hasNext();) {
310           String JavaDoc interfaceName = (String JavaDoc) it2.next();
311           msg.append(interfaceName);
312           if (it2.hasNext()) {
313             msg.append(',');
314           }
315         }
316         msg.append("] since they all have method [");
317         msg.append(key);
318         msg.append(']');
319         System.out.println("AW::WARNING - " + msg.toString());
320         return true;
321       }
322     }
323     return false;
324   }
325 }
Popular Tags