View Javadoc

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              // TODO: matching on methods ONLY in base type needs to be completed
42              // TODO: needs to work together with the method and field matching somehow
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          // parse the class/super class
63          if (pattern.matches(classInfo.getName())) {
64              return true;
65          } else {
66              // parse the interfaces for the class
67              if (matchInterfaces(classInfo.getInterfaces(), classInfo, pattern)) {
68                  return true;
69              }
70  
71              // no parse; getClass the next superclass
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         // AW-272, call within constructor
124         // Note: in 1.0, within info comes from CtBehavior in Javassist, and thus ctor
125         // is not named <init> but the FQN of its declaring class
126         // see ConstructorCallTF and MethodCallTF
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             // TODO odd comparison
200 //        } else if (classInfo.getName().equals(null)) {
201 //            return true;
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             // TODO odd comparison
225 //        } else if (classInfo.getName().equals(null)) {
226 //            return true;
227         } else if (className.equals(classInfo.getName())) {
228             return true;
229         } else {
230             return ClassInfoHelper.extendsSuperClass(classInfo.getSuperClass(), className);
231         }
232     }
233 }