KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > aop > support > AopUtils


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.aop.support;
18
19 import java.lang.reflect.InvocationTargetException JavaDoc;
20 import java.lang.reflect.Method JavaDoc;
21 import java.lang.reflect.Modifier JavaDoc;
22 import java.lang.reflect.Proxy JavaDoc;
23 import java.util.HashSet JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.LinkedList JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Set JavaDoc;
28
29 import org.springframework.aop.Advisor;
30 import org.springframework.aop.AopInvocationException;
31 import org.springframework.aop.IntroductionAdvisor;
32 import org.springframework.aop.IntroductionAwareMethodMatcher;
33 import org.springframework.aop.MethodMatcher;
34 import org.springframework.aop.Pointcut;
35 import org.springframework.aop.PointcutAdvisor;
36 import org.springframework.aop.SpringProxy;
37 import org.springframework.aop.TargetClassAware;
38 import org.springframework.util.Assert;
39 import org.springframework.util.ClassUtils;
40
41 /**
42  * Utility methods for AOP support code.
43  * Mainly for internal use within Spring's AOP support.
44  *
45  * <p>See {@link org.springframework.aop.framework.AopProxyUtils} for a
46  * collection of framework-specific AOP utility methods which depend
47  * on internals of Spring's AOP framework implementation.
48  *
49  * @author Rod Johnson
50  * @author Juergen Hoeller
51  * @author Rob Harrop
52  * @see org.springframework.aop.framework.AopProxyUtils
53  */

54 public abstract class AopUtils {
55     
56     /**
57      * Check whether the given object is a JDK dynamic proxy or a CGLIB proxy.
58      * @param object the object to check
59      * @see #isJdkDynamicProxy
60      * @see #isCglibProxy
61      */

62     public static boolean isAopProxy(Object JavaDoc object) {
63         return (object instanceof SpringProxy &&
64                 (Proxy.isProxyClass(object.getClass()) || isCglibProxyClass(object.getClass())));
65     }
66
67     /**
68      * Check whether the given object is a JDK dynamic proxy.
69      * @param object the object to check
70      * @see java.lang.reflect.Proxy#isProxyClass
71      */

72     public static boolean isJdkDynamicProxy(Object JavaDoc object) {
73         return (object instanceof SpringProxy && Proxy.isProxyClass(object.getClass()));
74     }
75
76     /**
77      * Check whether the given object is a CGLIB proxy.
78      * @param object the object to check
79      */

80     public static boolean isCglibProxy(Object JavaDoc object) {
81         return (object instanceof SpringProxy && isCglibProxyClass(object.getClass()));
82     }
83
84     /**
85      * Check whether the specified class is a CGLIB-generated class.
86      * @param clazz the class to check
87      */

88     public static boolean isCglibProxyClass(Class JavaDoc clazz) {
89         return (clazz != null && clazz.getName().indexOf("$$") != -1);
90     }
91
92     /**
93      * Determine the target class of the given bean instance,
94      * which might be an AOP proxy.
95      * <p>Returns the target class for an AOP proxy and the plain class else.
96      * @param candidate the instance to check (might be an AOP proxy)
97      * @return the target class (or the plain class of the given object as fallback)
98      * @see org.springframework.aop.TargetClassAware#getTargetClass()
99      */

100     public static Class JavaDoc getTargetClass(Object JavaDoc candidate) {
101         Assert.notNull(candidate, "Candidate object must not be null");
102         if (candidate instanceof TargetClassAware) {
103             return ((TargetClassAware) candidate).getTargetClass();
104         }
105         if (isCglibProxyClass(candidate.getClass())) {
106             return candidate.getClass().getSuperclass();
107         }
108         return candidate.getClass();
109     }
110
111     /**
112      * Determine whether the given method is an "equals" method.
113      * @see java.lang.Object#equals
114      */

115     public static boolean isEqualsMethod(Method JavaDoc method) {
116         return (method != null && method.getName().equals("equals") &&
117                 method.getParameterTypes().length == 1 && method.getParameterTypes()[0] == Object JavaDoc.class);
118     }
119
120     /**
121      * Determine whether the given method is a "hashCode" method.
122      * @see java.lang.Object#hashCode
123      */

124     public static boolean isHashCodeMethod(Method JavaDoc method) {
125         return (method != null && method.getName().equals("hashCode") &&
126                 method.getParameterTypes().length == 0);
127     }
128
129     /**
130      * Determine whether the given method is a "toString" method.
131      * @see java.lang.Object#toString()
132      */

133     public static boolean isToStringMethod(Method JavaDoc method) {
134         return (method != null && method.getName().equals("toString") &&
135                 method.getParameterTypes().length == 0);
136     }
137
138     /**
139      * Given a method, which may come from an interface, and a target class used
140      * in the current AOP invocation, find the corresponding target method if there
141      * is one. E.g. the method may be <code>IFoo.bar()</code> and the target class
142      * may be <code>DefaultFoo</code>. In this case, the method may be
143      * <code>DefaultFoo.bar()</code>. This enables attributes on that method to be found.
144      * @param method the method to be invoked, which may come from an interface
145      * @param targetClass the target class for the current invocation.
146      * May be <code>null</code> or may not even implement the method.
147      * @return the specific target method, or the original method if the
148      * <code>targetClass</code> doesn't implement it or is <code>null</code>
149      */

150     public static Method JavaDoc getMostSpecificMethod(Method JavaDoc method, Class JavaDoc targetClass) {
151         if (method != null && targetClass != null) {
152             try {
153                 method = targetClass.getMethod(method.getName(), method.getParameterTypes());
154             }
155             catch (NoSuchMethodException JavaDoc ex) {
156                 // Perhaps the target class doesn't implement this method:
157
// that's fine, just use the original method.
158
}
159         }
160         return method;
161     }
162
163
164     /**
165      * Can the given pointcut apply at all on the given class?
166      * <p>This is an important test as it can be used to optimize
167      * out a pointcut for a class.
168      * @param pc the static or dynamic pointcut to check
169      * @param targetClass the class to test
170      * @return whether the pointcut can apply on any method
171      */

172     public static boolean canApply(Pointcut pc, Class JavaDoc targetClass) {
173         return canApply(pc, targetClass, false);
174     }
175
176     /**
177      * Can the given pointcut apply at all on the given class?
178      * <p>This is an important test as it can be used to optimize
179      * out a pointcut for a class.
180      * @param pc the static or dynamic pointcut to check
181      * @param targetClass the class to test
182      * @param hasIntroductions whether or not the advisor chain
183      * for this bean includes any introductions
184      * @return whether the pointcut can apply on any method
185      */

186     public static boolean canApply(Pointcut pc, Class JavaDoc targetClass, boolean hasIntroductions) {
187         if (!pc.getClassFilter().matches(targetClass)) {
188             return false;
189         }
190
191         MethodMatcher methodMatcher = pc.getMethodMatcher();
192         IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
193         if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
194             introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
195         }
196
197         Set JavaDoc classes = new HashSet JavaDoc(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
198         classes.add(targetClass);
199         for (Iterator JavaDoc it = classes.iterator(); it.hasNext();) {
200             Class JavaDoc clazz = (Class JavaDoc) it.next();
201             Method JavaDoc[] methods = clazz.getMethods();
202             for (int j = 0; j < methods.length; j++) {
203                 if ((introductionAwareMethodMatcher != null &&
204                         introductionAwareMethodMatcher.matches(methods[j], targetClass, hasIntroductions)) ||
205                         methodMatcher.matches(methods[j], targetClass)) {
206                     return true;
207                 }
208             }
209         }
210
211         return false;
212     }
213
214     /**
215      * Can the given advisor apply at all on the given class?
216      * This is an important test as it can be used to optimize
217      * out a advisor for a class.
218      * @param advisor the advisor to check
219      * @param targetClass class we're testing
220      * @return whether the pointcut can apply on any method
221      */

222     public static boolean canApply(Advisor advisor, Class JavaDoc targetClass) {
223         return canApply(advisor, targetClass, false);
224     }
225     
226     /**
227      * Can the given advisor apply at all on the given class?
228      * This is an important test as it can be used to optimize
229      * out a advisor for a class.
230      * This version also takes into account introductions, for
231      * IntroductionAwareMethodMatchers
232      * @param advisor the advisor to check
233      * @param targetClass class we're testing
234      * @param hasIntroductions whether or not the advisor chain for this bean includes
235      * any introductions
236      * @return whether the pointcut can apply on any method
237      */

238     public static boolean canApply(Advisor advisor, Class JavaDoc targetClass, boolean hasIntroductions) {
239         if (advisor instanceof IntroductionAdvisor) {
240             return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
241         }
242         else if (advisor instanceof PointcutAdvisor) {
243             PointcutAdvisor pca = (PointcutAdvisor) advisor;
244             return canApply(pca.getPointcut(), targetClass, hasIntroductions);
245         }
246         else {
247             // It doesn't have a pointcut so we assume it applies
248
return true;
249         }
250     }
251
252     /**
253      * Determine the sublist of the <code>candidateAdvisors</code> list
254      * that is applicable to the given class.
255      * @param candidateAdvisors the Advisors to evaluate
256      * @param clazz the target class
257      * @return sublist of Advisors that can apply to an object of the given class
258      */

259     public static List JavaDoc findAdvisorsThatCanApply(List JavaDoc candidateAdvisors, Class JavaDoc clazz) {
260         List JavaDoc eligibleAdvisors = new LinkedList JavaDoc();
261         for (Iterator JavaDoc it = candidateAdvisors.iterator(); it.hasNext();) {
262             Advisor candidate = (Advisor) it.next();
263             if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
264                 eligibleAdvisors.add(candidate);
265             }
266         }
267         boolean hasIntroductions = !eligibleAdvisors.isEmpty();
268         for (Iterator JavaDoc it = candidateAdvisors.iterator(); it.hasNext();) {
269             Advisor candidate = (Advisor) it.next();
270             if (candidate instanceof IntroductionAdvisor) {
271                 // already processed
272
continue;
273             }
274             if (canApply(candidate, clazz, hasIntroductions)) {
275                 eligibleAdvisors.add(candidate);
276             }
277         }
278         return eligibleAdvisors;
279     }
280
281
282     /**
283      * Invoke the given target via reflection, as part of an AOP method invocation.
284      * @param target the target object
285      * @param method the method to invoke
286      * @param args the arguments for the method
287      * @throws Throwable if thrown by the target method
288      * @throws org.springframework.aop.AopInvocationException in case of a reflection error
289      */

290     public static Object JavaDoc invokeJoinpointUsingReflection(Object JavaDoc target, Method JavaDoc method, Object JavaDoc[] args)
291         throws Throwable JavaDoc {
292
293         // Use reflection to invoke the method.
294
try {
295             if (!Modifier.isPublic(method.getModifiers()) ||
296                     !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
297                 method.setAccessible(true);
298             }
299             return method.invoke(target, args);
300         }
301         catch (InvocationTargetException JavaDoc ex) {
302             // Invoked method threw a checked exception.
303
// We must rethrow it. The client won't see the interceptor.
304
throw ex.getTargetException();
305         }
306         catch (IllegalArgumentException JavaDoc ex) {
307             throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
308                     method + "] on target [" + target + "]", ex);
309         }
310         catch (IllegalAccessException JavaDoc ex) {
311             throw new AopInvocationException("Could not access method [" + method + "]", ex);
312         }
313     }
314
315 }
316
Popular Tags