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.Method;
11 import java.lang.reflect.Modifier;
12 import java.lang.reflect.Constructor;
13
14 import org.codehaus.aspectwerkz.definition.DescriptorUtil;
15 import org.codehaus.aspectwerkz.expression.SubtypePatternType;
16 import org.codehaus.aspectwerkz.expression.regexp.TypePattern;
17 import org.codehaus.aspectwerkz.reflect.impl.java.JavaMethodInfo;
18 import org.codehaus.aspectwerkz.reflect.impl.java.JavaConstructorInfo;
19 import org.codehaus.aspectwerkz.transform.TransformationUtil;
20 import org.codehaus.aspectwerkz.transform.delegation.JavassistHelper;
21
22 /***
23 * Utility method for manipulating and managing ClassInfo hierarchies.
24 *
25 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
26 * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
27 */
28 public class ClassInfoHelper {
29 /***
30 * Matches a type.
31 *
32 * @param typePattern the pattern to try to parse against
33 * @param classInfo the info of the class
34 * @return
35 */
36 public static boolean matchType(final TypePattern typePattern, final ClassInfo classInfo) {
37 SubtypePatternType type = typePattern.getSubtypePatternType();
38 if (type.equals(SubtypePatternType.MATCH_ON_ALL_METHODS)) {
39 return matchSuperClasses(classInfo, typePattern);
40 } else if (type.equals(SubtypePatternType.MATCH_ON_BASE_TYPE_METHODS_ONLY)) {
41
42
43 return matchSuperClasses(classInfo, typePattern);
44 } else {
45 return typePattern.matches(classInfo.getName());
46 }
47 }
48
49 /***
50 * Tries to finds a parse at some superclass in the hierarchy. <p/>Only checks for a class parse to allow early
51 * filtering. <p/>Recursive.
52 *
53 * @param classInfo the class info
54 * @param pattern the type pattern
55 * @return boolean
56 */
57 public static boolean matchSuperClasses(final ClassInfo classInfo, final TypePattern pattern) {
58 if ((classInfo == null) || (pattern == null)) {
59 return false;
60 }
61
62
63 if (pattern.matches(classInfo.getName())) {
64 return true;
65 } else {
66
67 if (matchInterfaces(classInfo.getInterfaces(), classInfo, pattern)) {
68 return true;
69 }
70
71
72 return matchSuperClasses(classInfo.getSuperClass(), pattern);
73 }
74 }
75
76 /***
77 * Tries to finds a parse at some interface in the hierarchy. <p/>Only checks for a class parse to allow early
78 * filtering. <p/>Recursive.
79 *
80 * @param interfaces the interfaces
81 * @param classInfo the class info
82 * @param pattern the type pattern
83 * @return boolean
84 */
85 public static boolean matchInterfaces(
86 final ClassInfo[] interfaces,
87 final ClassInfo classInfo,
88 final TypePattern pattern) {
89 if ((interfaces.length == 0) || (classInfo == null) || (pattern == null)) {
90 return false;
91 }
92 for (int i = 0; i < interfaces.length; i++) {
93 ClassInfo anInterface = interfaces[i];
94 if (pattern.matches(anInterface.getName())) {
95 return true;
96 } else {
97 if (matchInterfaces(anInterface.getInterfaces(), classInfo, pattern)) {
98 return true;
99 } else {
100 continue;
101 }
102 }
103 }
104 return false;
105 }
106
107 /***
108 * Creates a member info instance based on the signature etc.
109 *
110 * @param targetClass
111 * @param withinMethodName
112 * @param withinMethodSignature
113 * @return a member info instance
114 * @TODO: check if we have a constructor and not a method
115 */
116 public static MemberInfo createMemberInfo(
117 final Class targetClass,
118 final String withinMethodName,
119 final String withinMethodSignature) {
120 MemberInfo withinMemberInfo = null;
121 String[] withinMethodParameterNames = DescriptorUtil.getParameters(withinMethodSignature);
122
123
124
125
126
127 if (targetClass.getName().equals(withinMethodName)) {
128 Constructor[] targetConstructors = targetClass.getDeclaredConstructors();
129 for (int i = 0; i < targetConstructors.length; i++) {
130 Constructor constructor = targetConstructors[i];
131 Class[] parameterTypes = constructor.getParameterTypes();
132 if (withinMethodParameterNames.length == parameterTypes.length) {
133 boolean match = true;
134 for (int j = 0; j < parameterTypes.length; j++) {
135 String withinCtorParameterName = JavassistHelper
136 .convertJavassistTypeSignatureToReflectTypeSignature(withinMethodParameterNames[j]);
137 if (!parameterTypes[j].getName().equals(withinCtorParameterName)) {
138 match = false;
139 break;
140 }
141 }
142 if (match) {
143 withinMemberInfo = JavaConstructorInfo.getConstructorInfo(constructor);
144 break;
145 }
146 }
147 }
148 } else {
149 Method[] targetMethods = targetClass.getDeclaredMethods();
150 for (int i = 0; i < targetMethods.length; i++) {
151 Method method = targetMethods[i];
152 Class[] parameterTypes = method.getParameterTypes();
153 if (method.getName().equals(withinMethodName)
154 && (withinMethodParameterNames.length == parameterTypes.length)) {
155 boolean match = true;
156 for (int j = 0; j < parameterTypes.length; j++) {
157 String withinMethodParameterName = JavassistHelper
158 .convertJavassistTypeSignatureToReflectTypeSignature(withinMethodParameterNames[j]);
159 if (!parameterTypes[j].getName().equals(withinMethodParameterName)) {
160 match = false;
161 break;
162 }
163 }
164 if (match) {
165 withinMemberInfo = JavaMethodInfo.getMethodInfo(method);
166 break;
167 }
168 }
169 }
170 }
171 return withinMemberInfo;
172 }
173
174 /***
175 * Checks if a method is static or not.
176 *
177 * @param methodInfo the info for the method
178 * @return boolean
179 */
180 public static boolean isMethodStatic(final MethodInfo methodInfo) {
181 int modifiers = methodInfo.getModifiers();
182 if ((modifiers & Modifier.STATIC) != 0) {
183 return true;
184 } else {
185 return false;
186 }
187 }
188
189 /***
190 * Checks if a class implements a certain inteface, somewhere up in the class hierarchy.
191 *
192 * @param classInfo
193 * @param interfaceName
194 * @return true if we have a parse else false
195 */
196 public static boolean implementsInterface(final ClassInfo classInfo, final String interfaceName) {
197 if ((classInfo == null) || (interfaceName == null)) {
198 return false;
199
200
201
202 } else {
203 ClassInfo[] interfaces = classInfo.getInterfaces();
204 for (int i = 0; i < interfaces.length; i++) {
205 ClassInfo anInterface = interfaces[i];
206 if (ClassInfoHelper.implementsInterface(anInterface, interfaceName)) {
207 return true;
208 }
209 }
210 return ClassInfoHelper.implementsInterface(classInfo.getSuperClass(), interfaceName);
211 }
212 }
213
214 /***
215 * Checks if a class has a certain class as super class, somewhere up in the class hierarchy.
216 *
217 * @param classInfo the meta-data for the class to parse
218 * @param className the name of the super class
219 * @return true if we have a parse else false
220 */
221 public static boolean extendsSuperClass(final ClassInfo classInfo, final String className) {
222 if ((classInfo == null) || (className == null)) {
223 return false;
224
225
226
227 } else if (className.equals(classInfo.getName())) {
228 return true;
229 } else {
230 return ClassInfoHelper.extendsSuperClass(classInfo.getSuperClass(), className);
231 }
232 }
233 }