1 /*************************************************
2 * Copyright (c) Shen Li. All rights reserved. *
3 * http://joyaop.sourceforge.net *
4 * -------------------------------------------- *
5 * Distributable under LGPL license. *
6 * See terms of license at gnu.org. *
7 ************************************************/
8 package net.sf.joyaop.impl;
9
10 import net.sf.joyaop.framework.Pointcut;
11 import net.sf.joyaop.util.ClassUtils;
12
13 import java.lang.reflect.Method;
14 import java.util.regex.Pattern;
15
16 /***
17 * @author Shen Li
18 */
19 public abstract class Pointcuts {
20 public static Pointcut byRegexp(String classRegexp, String methodRegexp) {
21 return new Regexp(classRegexp, methodRegexp);
22 }
23
24 public static Pointcut byInterface(Class interfaceClass) {
25 return new Interface(interfaceClass);
26 }
27
28 public static Pointcut byInterface(String interfaceName) {
29 return byInterface(ClassUtils.loadClass(interfaceName));
30 }
31
32 public static Pointcut byAnnotation(Class annotationClass) {
33 return new Annotation(annotationClass);
34 }
35
36 public static Pointcut byAnnotation(String annotationClassName) {
37 return byAnnotation(ClassUtils.loadClass(annotationClassName));
38 }
39
40 public static Pointcut and(Pointcut p1, Pointcut p2) {
41 return new And(p1, p2);
42 }
43
44 public static Pointcut or(Pointcut p1, Pointcut p2) {
45 return new Or(p1, p2);
46 }
47
48 public static Pointcut not(Pointcut p) {
49 return new Not(p);
50 }
51
52 public static class And implements Pointcut {
53 private final Pointcut p1;
54 private final Pointcut p2;
55
56 public And(Pointcut p1, Pointcut p2) {
57 this.p1 = p1;
58 this.p2 = p2;
59 }
60
61 public boolean matches(Class clazz) {
62 return p1.matches(clazz) && p2.matches(clazz);
63 }
64
65 public boolean matches(Class clazz, Method method) {
66 return p1.matches(clazz, method) && p2.matches(clazz, method);
67 }
68
69 public boolean equals(Object object) {
70 if (this == object) {
71 return true;
72 }
73 if (!(object instanceof And)) {
74 return false;
75 }
76 And and = (And) object;
77 if (p1.equals(and.p1) && p2.equals(and.p2) || p1.equals(and.p2) && p2.equals(and.p1)) {
78 return true;
79 }
80 return false;
81 }
82
83 public int hashCode() {
84 return p1.hashCode() * 31 + p2.hashCode();
85 }
86 }
87
88 public static class Interface implements Pointcut {
89 private final Class interfaceClass;
90
91 public Interface(Class interfaceClass) {
92 this.interfaceClass = interfaceClass;
93 }
94
95 public boolean matches(Class clazz) {
96 return (interfaceClass.isAssignableFrom(clazz));
97 }
98
99 public boolean matches(Class clazz, Method method) {
100 if (!matches(clazz)) {
101 return false;
102 }
103 if (method.getDeclaringClass() == interfaceClass) {
104 return true;
105 }
106 try {
107 interfaceClass.getMethod(method.getName(), method.getParameterTypes());
108 } catch (NoSuchMethodException e) {
109 return false;
110 }
111 return true;
112 }
113
114 public boolean equals(Object object) {
115 if (this == object) {
116 return true;
117 }
118 if (!(object instanceof Interface)) {
119 return false;
120 }
121 Interface intf = (Interface) object;
122 if (interfaceClass == intf.interfaceClass) {
123 return true;
124 }
125 return false;
126 }
127
128 public int hashCode() {
129 return interfaceClass.hashCode();
130 }
131 }
132
133 public static class Not implements Pointcut {
134 private final Pointcut pointcut;
135
136 public Not(Pointcut pointcut) {
137 this.pointcut = pointcut;
138 }
139
140 public boolean matches(Class clazz) {
141 return !pointcut.matches(clazz);
142 }
143
144 public boolean matches(Class clazz, Method method) {
145 return !pointcut.matches(clazz, method);
146 }
147
148 public boolean equals(Object object) {
149 if (this == object) {
150 return true;
151 }
152 if (!(object instanceof Not)) {
153 return false;
154 }
155 Not not = (Not) object;
156 if (pointcut.equals(not.pointcut)) {
157 return true;
158 }
159 return false;
160 }
161
162 public int hashCode() {
163 return pointcut.hashCode();
164 }
165 }
166
167 public static class Or implements Pointcut {
168 private final Pointcut p1;
169 private final Pointcut p2;
170
171 public Or(Pointcut p1, Pointcut p2) {
172 this.p1 = p1;
173 this.p2 = p2;
174 }
175
176 public boolean matches(Class clazz) {
177 return p1.matches(clazz) || p2.matches(clazz);
178 }
179
180 public boolean matches(Class clazz, Method method) {
181 return p1.matches(clazz, method) || p2.matches(clazz, method);
182 }
183
184 public boolean equals(Object object) {
185 if (this == object) {
186 return true;
187 }
188 if (!(object instanceof Or)) {
189 return false;
190 }
191 Or or = (Or) object;
192 if (p1.equals(or.p1) && p2.equals(or.p2) || p1.equals(or.p2) && p2.equals(or.p1)) {
193 return true;
194 }
195 return false;
196 }
197
198 public int hashCode() {
199 return p1.hashCode() * 31 + p2.hashCode();
200 }
201 }
202
203 public static class Regexp implements Pointcut {
204 private Pattern classPattern;
205 private Pattern methodPattern;
206
207 public Regexp(String classRegexp, String methodRegexp) {
208 if (classRegexp == null) {
209 classRegexp = ".*";
210 }
211 if (methodRegexp == null) {
212 methodRegexp = ".*";
213 }
214 this.classPattern = Pattern.compile(classRegexp);
215 this.methodPattern = Pattern.compile(methodRegexp);
216 }
217
218 public boolean matches(Class clazz, Method method) {
219 return (matches(clazz) && methodPattern.matcher(method.getName()).matches());
220 }
221
222 public boolean matches(Class clazz) {
223 return classPattern.matcher(clazz.getName()).matches();
224 }
225
226 public boolean equals(Object object) {
227 if (this == object) {
228 return true;
229 }
230 if (!(object instanceof Regexp)) {
231 return false;
232 }
233 Regexp regexp = (Regexp) object;
234 if (classPattern.pattern().equals(regexp.classPattern.pattern())
235 && methodPattern.pattern().equals(regexp.methodPattern.pattern())) {
236 return true;
237 }
238 return false;
239 }
240
241 public int hashCode() {
242 return classPattern.pattern().hashCode() * 31 + methodPattern.hashCode();
243 }
244 }
245
246 /***
247 * It's method annotaion actually
248 */
249 public static class Annotation implements Pointcut {
250 private Class annotationClass;
251
252 public Annotation(Class annotationClass) {
253 this.annotationClass = annotationClass;
254 }
255
256 public boolean matches(Class clazz, Method method) {
257 return (method.getAnnotation(annotationClass) == null ? false : true);
258 }
259
260 public boolean matches(Class clazz) {
261 return true;
262 }
263
264 public boolean equals(Object object) {
265 if (this == object) {
266 return true;
267 }
268 if (!(object instanceof Annotation)) {
269 return false;
270 }
271 if (annotationClass == ((Annotation) object).annotationClass) {
272 return true;
273 }
274 return false;
275 }
276
277 public int hashCode() {
278 return annotationClass.hashCode();
279 }
280 }
281 }