KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > reflect > ReflectHelper


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;
9
10 import java.lang.reflect.Constructor JavaDoc;
11 import java.lang.reflect.Field JavaDoc;
12 import java.lang.reflect.Modifier JavaDoc;
13 import java.lang.reflect.Method JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collections JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Iterator JavaDoc;
18
19 import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
20 import org.codehaus.aspectwerkz.transform.TransformationConstants;
21
22 /**
23  * Helper class with utility methods for working with the java.lang.reflect.* package.
24  *
25  * @author <a HREF="mailto:jboner@codehaus.org">Jonas Bonér </a>
26  */

27 public class ReflectHelper {
28
29     private final static Method JavaDoc OBJECT_EQUALS;
30     private final static Method JavaDoc OBJECT_HASH_CODE;
31     private final static Method JavaDoc OBJECT_GET_CLASS;
32     private final static Method JavaDoc OBJECT_TO_STRING;
33     private final static Method JavaDoc OBJECT_CLONE;
34     private final static Method JavaDoc OBJECT_WAIT_1;
35     private final static Method JavaDoc OBJECT_WAIT_2;
36     private final static Method JavaDoc OBJECT_WAIT_3;
37     private final static Method JavaDoc OBJECT_NOTIFY;
38     private final static Method JavaDoc OBJECT_NOTIFY_ALL;
39     private final static Method JavaDoc OBJECT_FINALIZE;
40
41     static {
42         Class JavaDoc clazz = Object JavaDoc.class;
43         try {
44             OBJECT_EQUALS = clazz.getDeclaredMethod("equals", new Class JavaDoc[]{clazz});
45             OBJECT_HASH_CODE = clazz.getDeclaredMethod("hashCode", new Class JavaDoc[]{});
46             OBJECT_GET_CLASS = clazz.getDeclaredMethod("getClass", new Class JavaDoc[]{});
47             OBJECT_CLONE = clazz.getDeclaredMethod("clone", new Class JavaDoc[]{});
48             OBJECT_TO_STRING = clazz.getDeclaredMethod("toString", new Class JavaDoc[]{});
49             OBJECT_WAIT_1 = clazz.getDeclaredMethod("wait", new Class JavaDoc[]{});
50             OBJECT_WAIT_2 = clazz.getDeclaredMethod("wait", new Class JavaDoc[]{long.class});
51             OBJECT_WAIT_3 = clazz.getDeclaredMethod("wait", new Class JavaDoc[]{long.class, int.class});
52             OBJECT_NOTIFY = clazz.getDeclaredMethod("notify", new Class JavaDoc[]{});
53             OBJECT_NOTIFY_ALL = clazz.getDeclaredMethod("notifyAll", new Class JavaDoc[]{});
54             OBJECT_FINALIZE = clazz.getDeclaredMethod("finalize", new Class JavaDoc[]{});
55         } catch (NoSuchMethodException JavaDoc e) {
56             throw new WrappedRuntimeException(e);
57         }
58     }
59
60 // /**
61
// * Creates a sorted method list of all the methods in the class and super classes, including package private ones.
62
// *
63
// * @param klass the class with the methods
64
// * @return the sorted method list
65
// */
66
// public static List createSortedMethodList(final Class klass) {
67
// if (klass == null) {
68
// throw new IllegalArgumentException("class to sort method on can not be null");
69
// }
70
//
71
// // get all public methods including the inherited methods
72
// java.lang.reflect.Method[] methods = klass.getMethods();
73
// java.lang.reflect.Method[] privateMethods = klass.getDeclaredMethods();
74
// List methodList = new ArrayList(methods.length);
75
// for (int i = 0; i < methods.length; i++) {
76
// Method method = methods[i];
77
// if (ReflectHelper.isUserDefinedMethod(method)) {
78
// methodList.add(method);
79
// }
80
// }
81
// // lookup in declared method to add "package private" method (which can be Pointcut with signatures)
82
// for (int i = 0; i < privateMethods.length; i++) {
83
// Method method = privateMethods[i];
84
// if (ReflectHelper.isUserDefinedMethod(method) && !methodList.contains(method)) {
85
// methodList.add(method);
86
// }
87
// }
88
//
89
// Collections.sort(methodList, MethodComparator.getInstance(MethodComparator.NORMAL_METHOD));
90
// return methodList;
91
// }
92

93 // /**
94
// * Creates a sorted method list of all the methods in the class and super classes, if and only
95
// * if those are part of the given list of interfaces declared method
96
// *
97
// * @param klass the class with the methods
98
// * @param interfaceDeclaredMethods the list of interface declared methods
99
// * @return the sorted method list
100
// */
101
// public static List createInterfaceDefinedSortedMethodList(final Class klass, List interfaceDeclaredMethods) {
102
// if (klass == null) {
103
// throw new IllegalArgumentException("class to sort method on can not be null");
104
// }
105
//
106
// // get all public methods including the inherited methods
107
// java.lang.reflect.Method[] methods = klass.getMethods();
108
// java.lang.reflect.Method[] privateMethods = klass.getDeclaredMethods();
109
// List methodList = new ArrayList(methods.length);
110
// for (int i = 0; i < methods.length; i++) {
111
// Method method = methods[i];
112
// if (ReflectHelper.isUserDefinedMethod(method) && isDeclaredByInterface(method, interfaceDeclaredMethods)) {
113
// methodList.add(method);
114
// }
115
// }
116
// // lookup in declared method to add "package private" method (which can be Pointcut with signatures)
117
// for (int i = 0; i < privateMethods.length; i++) {
118
// Method method = privateMethods[i];
119
// if (ReflectHelper.isUserDefinedMethod(method) && isDeclaredByInterface(method, interfaceDeclaredMethods)
120
// && !methodList.contains(method)) {
121
// methodList.add(method);
122
// }
123
// }
124
//
125
// Collections.sort(methodList, MethodComparator.getInstance(MethodComparator.NORMAL_METHOD));
126
// return methodList;
127
// }
128

129     /**
130      * Returns true if the method is declared by one of the given method declared in an interface class
131      *
132      * @param method
133      * @param interfaceDeclaredMethods
134      * @return
135      */

136     private static boolean isDeclaredByInterface(Method JavaDoc method, List JavaDoc interfaceDeclaredMethods) {
137         boolean match = false;
138         for (Iterator JavaDoc iterator = interfaceDeclaredMethods.iterator(); iterator.hasNext();) {
139             Method JavaDoc methodIt = (Method JavaDoc) iterator.next();
140             if (method.getName().equals(methodIt.getName())) {
141                 if (method.getParameterTypes().length == methodIt.getParameterTypes().length) {
142                     boolean matchArgs = true;
143                     for (int i = 0; i < method.getParameterTypes().length; i++) {
144                         // BAD ! will lead to nested loading while system not ready
145
// => if introduced method has target class in its signature weaving will not occur
146
// properly
147
// ?? should we use ASMInfo ?
148
Class JavaDoc parameterType = method.getParameterTypes()[i];
149                         if (parameterType.getName().equals(methodIt.getParameterTypes()[i].getName())) {
150                             ;
151                         } else {
152                             matchArgs = false;
153                             break;
154                         }
155                     }
156                     if (matchArgs) {
157                         match = true;
158                         break;
159                     }
160                 }
161             }
162         }
163         return match;
164     }
165
166     /**
167      * Returns true if the method is not of on java.lang.Object and is not an AW generated one
168      *
169      * @param method
170      * @return
171      */

172     private static boolean isUserDefinedMethod(final Method JavaDoc method) {
173         if (!method.equals(OBJECT_EQUALS)
174             && !method.equals(OBJECT_HASH_CODE)
175             && !method.equals(OBJECT_GET_CLASS)
176             && !method.equals(OBJECT_TO_STRING)
177             && !method.equals(OBJECT_CLONE)
178             && !method.equals(OBJECT_WAIT_1)
179             && !method.equals(OBJECT_WAIT_2)
180             && !method.equals(OBJECT_WAIT_3)
181             && !method.equals(OBJECT_NOTIFY)
182             && !method.equals(OBJECT_NOTIFY_ALL)
183             && !method.getName().startsWith(TransformationConstants.SYNTHETIC_MEMBER_PREFIX)
184             && !method.getName().startsWith(TransformationConstants.ORIGINAL_METHOD_PREFIX)
185             && !method.getName().startsWith(TransformationConstants.ASPECTWERKZ_PREFIX)) {
186             return true;
187         } else {
188             return false;
189         }
190     }
191
192     /**
193      * Converts modifiers represented in a string array to an int.
194      *
195      * @param modifiers the modifiers as strings
196      * @return the modifiers as an int
197      */

198     public static int getModifiersAsInt(final String JavaDoc[] modifiers) {
199         int accessFlags = 0;
200         for (int i = 0; i < modifiers.length; i++) {
201             if (modifiers[i].equals("abstract")) {
202                 accessFlags |= Modifier.ABSTRACT;
203             } else if (modifiers[i].equals("final")) {
204                 accessFlags |= Modifier.FINAL;
205             } else if (modifiers[i].equals("interface")) {
206                 accessFlags |= Modifier.INTERFACE;
207             } else if (modifiers[i].equals("native")) {
208                 accessFlags |= Modifier.NATIVE;
209             } else if (modifiers[i].equals("private")) {
210                 accessFlags |= Modifier.PRIVATE;
211             } else if (modifiers[i].equals("protected")) {
212                 accessFlags |= Modifier.PROTECTED;
213             } else if (modifiers[i].equals("public")) {
214                 accessFlags |= Modifier.PUBLIC;
215             } else if (modifiers[i].equals("static")) {
216                 accessFlags |= Modifier.STATIC;
217             } else if (modifiers[i].equals("strict")) {
218                 accessFlags |= Modifier.STRICT;
219             } else if (modifiers[i].equals("synchronized")) {
220                 accessFlags |= Modifier.SYNCHRONIZED;
221             } else if (modifiers[i].equals("transient")) {
222                 accessFlags |= Modifier.TRANSIENT;
223             } else if (modifiers[i].equals("volatile")) {
224                 accessFlags |= Modifier.VOLATILE;
225             }
226         }
227         return accessFlags;
228     }
229
230     /**
231      * Calculate the hash for a class.
232      *
233      * @param klass the class
234      * @return the hash
235      */

236     public static int calculateHash(final Class JavaDoc klass) {
237         return klass.getName().hashCode();
238     }
239
240     /**
241      * Calculate the hash for a method.
242      *
243      * @param method the method
244      * @return the hash
245      */

246     public static int calculateHash(final java.lang.reflect.Method JavaDoc method) {
247         int hash = 17;
248         hash = (37 * hash) + method.getName().hashCode();
249         for (int i = 0; i < method.getParameterTypes().length; i++) {
250             Class JavaDoc type = method.getParameterTypes()[i];
251             hash = (37 * hash) + type.getName().hashCode();
252         }
253         return hash;
254     }
255
256     /**
257      * Calculate the hash for a constructor.
258      *
259      * @param constructor the constructor
260      * @return the hash
261      */

262     public static int calculateHash(final Constructor JavaDoc constructor) {
263         int hash = 17;
264         hash = (37 * hash) + TransformationConstants.INIT_METHOD_NAME.hashCode();
265         for (int i = 0; i < constructor.getParameterTypes().length; i++) {
266             Class JavaDoc type = constructor.getParameterTypes()[i];
267             hash = (37 * hash) + type.getName().replace('/', '.').hashCode();
268         }
269         return hash;
270     }
271
272     /**
273      * Calculate the hash for a field.
274      *
275      * @param field the field
276      * @return the hash
277      */

278     public static int calculateHash(final Field JavaDoc field) {
279         int hash = 17;
280         hash = (37 * hash) + field.getName().hashCode();
281         Class JavaDoc type = field.getType();
282         hash = (37 * hash) + type.getName().hashCode();
283         return hash;
284     }
285
286     /**
287      * Checks if the class is a of a primitive type, if so create and return the class for the type else return null.
288      *
289      * @param className
290      * @return the class for the primitive type or null
291      */

292     public static Class JavaDoc getPrimitiveClass(final String JavaDoc className) {
293         if (className.equals("void")) {
294             return void.class;
295         } else if (className.equals("long")) {
296             return long.class;
297         } else if (className.equals("int")) {
298             return int.class;
299         } else if (className.equals("short")) {
300             return short.class;
301         } else if (className.equals("double")) {
302             return double.class;
303         } else if (className.equals("float")) {
304             return float.class;
305         } else if (className.equals("byte")) {
306             return byte.class;
307         } else if (className.equals("boolean")) {
308             return boolean.class;
309         } else if (className.equals("char")) {
310             return char.class;
311         } else {
312             return null;
313         }
314     }
315
316     /**
317      * Returns JVM type signature for given class.
318      *
319      * @param cl
320      * @return
321      */

322     public static String JavaDoc getClassSignature(Class JavaDoc cl) {
323         StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
324         while (cl.isArray()) {
325             sbuf.append('[');
326             cl = cl.getComponentType();
327         }
328         if (cl.isPrimitive()) {
329             if (cl == Integer.TYPE) {
330                 sbuf.append('I');
331             } else if (cl == Byte.TYPE) {
332                 sbuf.append('B');
333             } else if (cl == Long.TYPE) {
334                 sbuf.append('J');
335             } else if (cl == Float.TYPE) {
336                 sbuf.append('F');
337             } else if (cl == Double.TYPE) {
338                 sbuf.append('D');
339             } else if (cl == Short.TYPE) {
340                 sbuf.append('S');
341             } else if (cl == Character.TYPE) {
342                 sbuf.append('C');
343             } else if (cl == Boolean.TYPE) {
344                 sbuf.append('Z');
345             } else if (cl == Void.TYPE) {
346                 sbuf.append('V');
347             } else {
348                 throw new InternalError JavaDoc();
349             }
350         } else {
351             sbuf.append('L' + cl.getName().replace('.', '/') + ';');
352         }
353         return sbuf.toString();
354     }
355
356     /**
357      * Returns JVM type signature for a constructor.
358      *
359      * @param constructor
360      * @return
361      */

362     public static String JavaDoc getConstructorSignature(final Constructor JavaDoc constructor) {
363         return getMethodSignature(constructor.getParameterTypes(), Void.TYPE);
364     }
365
366     /**
367      * Returns JVM type signature for a field.
368      *
369      * @param field
370      * @return
371      */

372     public static String JavaDoc getFieldSignature(final Field JavaDoc field) {
373         return getClassSignature(field.getType());
374     }
375
376     /**
377      * Returns JVM type signature for a method.
378      *
379      * @param method
380      * @return
381      */

382     public static String JavaDoc getMethodSignature(final Method JavaDoc method) {
383         return getMethodSignature(method.getParameterTypes(), method.getReturnType());
384     }
385
386     /**
387      * Returns JVM type signature for given list of parameters and return type.
388      *
389      * @param paramTypes
390      * @param retType
391      * @return
392      */

393     private static String JavaDoc getMethodSignature(Class JavaDoc[] paramTypes, Class JavaDoc retType) {
394         StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
395         sbuf.append('(');
396         for (int i = 0; i < paramTypes.length; i++) {
397             sbuf.append(getClassSignature(paramTypes[i]));
398         }
399         sbuf.append(')');
400         sbuf.append(getClassSignature(retType));
401         return sbuf.toString();
402     }
403 }
Popular Tags