KickJava   Java API By Example, From Geeks To Geeks.

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


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.io.Serializable JavaDoc;
20 import java.lang.reflect.Method JavaDoc;
21
22 import org.springframework.aop.ClassFilter;
23 import org.springframework.aop.IntroductionAwareMethodMatcher;
24 import org.springframework.aop.MethodMatcher;
25 import org.springframework.util.Assert;
26
27 /**
28  * Static utility methods for composing
29  * {@link org.springframework.aop.MethodMatcher MethodMatchers}.
30  *
31  * <p>A MethodMatcher may be evaluated statically (based on method
32  * and target class) or need further evaluation dynamically
33  * (based on arguments at the time of method invocation).
34  *
35  * @author Rod Johnson
36  * @author Rob Harrop
37  * @author Juergen Hoeller
38  * @since 11.11.2003
39  * @see ClassFilters
40  * @see Pointcuts
41  */

42 public abstract class MethodMatchers {
43
44     /**
45      * Match all methods that <i>either</i> (or both) of the given MethodMatchers matches.
46      * @param mm1 the first MethodMatcher
47      * @param mm2 the second MethodMatcher
48      * @return a distinct MethodMatcher that matches all methods that either
49      * of the given MethodMatchers matches
50      */

51     public static MethodMatcher union(MethodMatcher mm1, MethodMatcher mm2) {
52         return new UnionMethodMatcher(mm1, mm2);
53     }
54
55     /**
56      * Match all methods that <i>either</i> (or both) of the given MethodMatchers matches.
57      * @param mm1 the first MethodMatcher
58      * @param cf1 the corresponding ClassFilter for the first MethodMatcher
59      * @param mm2 the second MethodMatcher
60      * @param cf2 the corresponding ClassFilter for the second MethodMatcher
61      * @return a distinct MethodMatcher that matches all methods that either
62      * of the given MethodMatchers matches
63      */

64     static MethodMatcher union(MethodMatcher mm1, ClassFilter cf1, MethodMatcher mm2, ClassFilter cf2) {
65         return new ClassFilterAwareUnionMethodMatcher(mm1, cf1, mm2, cf2);
66     }
67
68     /**
69      * Match all methods that <i>both</i> of the given MethodMatchers match.
70      * @param mm1 the first MethodMatcher
71      * @param mm2 the second MethodMatcher
72      * @return a distinct MethodMatcher that matches all methods that both
73      * of the given MethodMatchers match
74      */

75     public static MethodMatcher intersection(MethodMatcher mm1, MethodMatcher mm2) {
76         return new IntersectionMethodMatcher(mm1, mm2);
77     }
78
79     /**
80      * Apply the given MethodMatcher to the given Method, supporting an
81      * {@link org.springframework.aop.IntroductionAwareMethodMatcher}
82      * (if applicable).
83      * @param mm the MethodMatcher to apply (may be an IntroductionAwareMethodMatcher)
84      * @param method the candidate method
85      * @param targetClass the target class (may be <code>null</code>, in which case
86      * the candidate class must be taken to be the method's declaring class)
87      * @param hasIntroductions <code>true</code> if the object on whose behalf we are
88      * asking is the subject on one or more introductions; <code>false</code> otherwise
89      * @return whether or not this method matches statically
90      */

91     public static boolean matches(MethodMatcher mm, Method JavaDoc method, Class JavaDoc targetClass, boolean hasIntroductions) {
92         Assert.notNull(mm, "MethodMatcher must not be null");
93         return ((mm instanceof IntroductionAwareMethodMatcher &&
94                 ((IntroductionAwareMethodMatcher) mm).matches(method, targetClass, hasIntroductions)) ||
95                 mm.matches(method, targetClass));
96     }
97
98
99     /**
100      * MethodMatcher implementation for a union of two given MethodMatchers.
101      */

102     private static class UnionMethodMatcher implements IntroductionAwareMethodMatcher, Serializable JavaDoc {
103
104         private MethodMatcher mm1;
105         private MethodMatcher mm2;
106
107         public UnionMethodMatcher(MethodMatcher mm1, MethodMatcher mm2) {
108             Assert.notNull(mm1, "First MethodMatcher must not be null");
109             Assert.notNull(mm2, "Second MethodMatcher must not be null");
110             this.mm1 = mm1;
111             this.mm2 = mm2;
112         }
113
114         public boolean matches(Method JavaDoc method, Class JavaDoc targetClass, boolean hasIntroductions) {
115             return (matchesClass1(targetClass) && MethodMatchers.matches(this.mm1, method, targetClass, hasIntroductions)) ||
116                     (matchesClass2(targetClass) && MethodMatchers.matches(this.mm2, method, targetClass, hasIntroductions));
117         }
118
119         public boolean matches(Method JavaDoc method, Class JavaDoc targetClass) {
120             return (matchesClass1(targetClass) && this.mm1.matches(method, targetClass)) ||
121                     (matchesClass2(targetClass) && this.mm2.matches(method, targetClass));
122         }
123
124         protected boolean matchesClass1(Class JavaDoc targetClass) {
125             return true;
126         }
127
128         protected boolean matchesClass2(Class JavaDoc targetClass) {
129             return true;
130         }
131
132         public boolean isRuntime() {
133             return this.mm1.isRuntime() || this.mm2.isRuntime();
134         }
135
136         public boolean matches(Method JavaDoc method, Class JavaDoc targetClass, Object JavaDoc[] args) {
137             return this.mm1.matches(method, targetClass, args) || this.mm2.matches(method, targetClass, args);
138         }
139
140         public boolean equals(Object JavaDoc obj) {
141             if (this == obj) {
142                 return true;
143             }
144             if (!(obj instanceof UnionMethodMatcher)) {
145                 return false;
146             }
147             UnionMethodMatcher that = (UnionMethodMatcher) obj;
148             return (this.mm1.equals(that.mm1) && this.mm2.equals(that.mm2));
149         }
150
151         public int hashCode() {
152             int hashCode = 17;
153             hashCode = 37 * hashCode + this.mm1.hashCode();
154             hashCode = 37 * hashCode + this.mm2.hashCode();
155             return hashCode;
156         }
157     }
158
159
160     /**
161      * MethodMatcher implementation for a union of two given MethodMatchers,
162      * supporting an associated ClassFilter per MethodMatcher.
163      */

164     private static class ClassFilterAwareUnionMethodMatcher extends UnionMethodMatcher {
165
166         private final ClassFilter cf1;
167         private final ClassFilter cf2;
168
169         public ClassFilterAwareUnionMethodMatcher(MethodMatcher mm1, ClassFilter cf1, MethodMatcher mm2, ClassFilter cf2) {
170             super(mm1, mm2);
171             this.cf1 = cf1;
172             this.cf2 = cf2;
173         }
174
175         protected boolean matchesClass1(Class JavaDoc targetClass) {
176             return this.cf1.matches(targetClass);
177         }
178
179         protected boolean matchesClass2(Class JavaDoc targetClass) {
180             return this.cf2.matches(targetClass);
181         }
182
183         public boolean equals(Object JavaDoc other) {
184             if (this == other) {
185                 return true;
186             }
187             if (!(other instanceof ClassFilterAwareUnionMethodMatcher)) {
188                 return false;
189             }
190             ClassFilterAwareUnionMethodMatcher that = (ClassFilterAwareUnionMethodMatcher) other;
191             return (this.cf1.equals(that.cf1) && this.cf2.equals(that.cf2) && super.equals(other));
192         }
193     }
194
195
196     /**
197      * MethodMatcher implementation for an intersection of two given MethodMatchers.
198      */

199     private static class IntersectionMethodMatcher implements IntroductionAwareMethodMatcher, Serializable JavaDoc {
200
201         private MethodMatcher mm1;
202         private MethodMatcher mm2;
203
204         public IntersectionMethodMatcher(MethodMatcher mm1, MethodMatcher mm2) {
205             Assert.notNull(mm1, "First MethodMatcher must not be null");
206             Assert.notNull(mm2, "Second MethodMatcher must not be null");
207             this.mm1 = mm1;
208             this.mm2 = mm2;
209         }
210
211         public boolean matches(Method JavaDoc method, Class JavaDoc targetClass, boolean hasIntroductions) {
212             return MethodMatchers.matches(this.mm1, method, targetClass, hasIntroductions) &&
213                     MethodMatchers.matches(this.mm2, method, targetClass, hasIntroductions);
214         }
215
216         public boolean matches(Method JavaDoc method, Class JavaDoc targetClass) {
217             return this.mm1.matches(method, targetClass) && this.mm2.matches(method, targetClass);
218         }
219
220         public boolean isRuntime() {
221             return this.mm1.isRuntime() || this.mm2.isRuntime();
222         }
223
224         public boolean matches(Method JavaDoc method, Class JavaDoc targetClass, Object JavaDoc[] args) {
225             // Because a dynamic intersection may be composed of a static and dynamic part,
226
// we must avoid calling the 3-arg matches method on a dynamic matcher, as
227
// it will probably be an unsupported operation.
228
boolean aMatches = this.mm1.isRuntime() ?
229                     this.mm1.matches(method, targetClass, args) : this.mm1.matches(method, targetClass);
230             boolean bMatches = this.mm2.isRuntime() ?
231                     this.mm2.matches(method, targetClass, args) : this.mm2.matches(method, targetClass);
232             return aMatches && bMatches;
233         }
234
235         public boolean equals(Object JavaDoc other) {
236             if (this == other) {
237                 return true;
238             }
239             if (!(other instanceof IntersectionMethodMatcher)) {
240                 return false;
241             }
242             IntersectionMethodMatcher that = (IntersectionMethodMatcher) other;
243             return (this.mm1.equals(that.mm1) && this.mm2.equals(that.mm2));
244         }
245
246         public int hashCode() {
247             int hashCode = 17;
248             hashCode = 37 * hashCode + this.mm1.hashCode();
249             hashCode = 37 * hashCode + this.mm2.hashCode();
250             return hashCode;
251         }
252     }
253
254 }
255
Popular Tags