1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package net.sf.jour.filter;
22
23 import javassist.ClassPool;
24 import javassist.CtClass;
25 import javassist.CtConstructor;
26 import javassist.CtMethod;
27 import javassist.NotFoundException;
28 import net.sf.jour.util.RegExUtil;
29
30 import org.apache.log4j.Logger;
31 import org.apache.regexp.RE;
32
33
34 /***
35 * @author michaellif TODO To change the template for this generated type
36 * comment go to Window - Preferences - Java - Code Style - Code
37 * Templates
38 */
39 public class Pointcut extends MatchStringFilter {
40
41 protected static final Logger log = Logger.getLogger(Pointcut.class);
42
43 /*** DOCUMENT ME! */
44 private static String modifierKeywords = "((final)|(static)|(native)|(synchronized)|(private)|(public)|(protected))";
45 private static String modifierListPattern = "(" + modifierKeywords + "(([;,]!?)" + modifierKeywords + ")*)";
46
47 private static String interfaceMethodsPattern = "(//S*)//s*(//S*)//s*->//s*(//S*)//s*//((.*)//)";
48 private static String classMethodsPattern = "(//S*)//s*(//S*)//s*=>//s*(//S*)//s*//((.*)//)";
49
50 private static String methodPattern = "(//S*)//s*(//S*)//s*//((.*)//)";
51
52 /*** DOCUMENT ME! */
53 private String retType = "";
54 private MatchStringListFilter retTypeFilter = new MatchStringListFilter();
55
56 private PointcutModifierListFiler modifierListFiler = new PointcutModifierListFiler();
57
58 /*** DOCUMENT ME! */
59 private String classType = "*";
60
61 private String interfaceType;
62 private String classMethodsType;
63
64 private CtClass filterCtClass;
65
66 /*** DOCUMENT ME! */
67 private String methodName = "";
68
69 /*** DOCUMENT ME! */
70 PointcutParamsFilter paramsFilter = new PointcutParamsFilter();
71
72 /***
73 * Creates a new Pointcut object.
74 *
75 * @param expr DOCUMENT ME!
76 */
77 public Pointcut(String expr) {
78 RE regex = new RE(modifierListPattern);
79 if (regex.match(expr)) {
80 String mod = regex.getParen(0);
81 if (debug) {
82 log.debug("modexpr: " + expr);
83 log.debug("mod: " + mod);
84 }
85 modifierListFiler.addPatterns(mod);
86 expr = expr.substring(mod.length());
87 }
88 String[] interfaceResult = RegExUtil.match(expr, interfaceMethodsPattern);
89 if ((debug) && (interfaceResult.length != 0)) {
90 log.debug("interface expr: " + expr);
91 for(int i = 0; i < interfaceResult.length; i ++) {
92 log.debug(i + " " + interfaceResult[i]);
93 }
94 }
95 if (interfaceResult.length == 4) {
96 log.debug("use interface expr: " + expr);
97 interfaceType = interfaceResult[1];
98 } else {
99 interfaceResult = RegExUtil.match(expr, classMethodsPattern);
100 if (interfaceResult.length == 4) {
101 log.debug("use classMethods as filter expr: " + expr);
102 classMethodsType = interfaceResult[1];
103 }
104 }
105
106 if (interfaceResult.length == 4) {
107 retType = interfaceResult[0];
108 retTypeFilter.addPatterns(retType);
109
110 methodName = interfaceResult[2];
111 super.setPattern(methodName);
112 paramsFilter.setParams(interfaceResult[3]);
113
114 modifierListFiler.initialized();
115 } else {
116 String[] result = RegExUtil.match(expr, methodPattern);
117 if (debug) {
118 log.debug("expr: " + expr);
119 for (int i = 0; i < result.length; i++) {
120 log.debug(i + " " + result[i]);
121 }
122 }
123
124 if (result.length == 3) {
125 retType = result[0];
126 retTypeFilter.addPatterns(retType);
127 methodName = result[1];
128 super.setPattern(methodName);
129 paramsFilter.setParams(result[2]);
130 modifierListFiler.initialized();
131 } else {
132 log.error("wrong pointcut expr \"" + expr + "\"");
133 }
134 }
135 }
136
137 public int matchState(Object obj) {
138 if (obj instanceof CtClass) {
139 return b2Match(acceptClass((CtClass)obj));
140 } else if (obj instanceof CtMethod) {
141 return b2Match(acceptMethod((CtMethod)obj));
142 } else {
143 return super.matchState(obj);
144 }
145 }
146
147 private CtClass getclassAsMethodsFilter() {
148 if (this.filterCtClass != null) {
149 return this.filterCtClass;
150 }
151
152 if (this.interfaceType != null) {
153 return loadFilterClass(this.interfaceType);
154 } else if (this.classMethodsType != null) {
155 return loadFilterClass(this.classMethodsType);
156 } else {
157 return null;
158 }
159 }
160
161 private CtClass loadFilterClass(String className) {
162 if (className == null) {
163 return null;
164 }
165 ClassPool pool = ClassPool.getDefault();
166 try {
167 this.filterCtClass = pool.get(className);
168 } catch (NotFoundException nfe) {
169 log.error("Error ", nfe);
170 throw new Error(nfe.getMessage());
171 }
172 return this.filterCtClass;
173 }
174
175 /***
176 * DOCUMENT ME!
177 *
178 * @param clazz DOCUMENT ME!
179 *
180 * @return DOCUMENT ME!
181 */
182 public boolean acceptClass(CtClass clazz) {
183 return acceptClass(clazz.getName()) && acceptImplements(clazz);
184 }
185
186 public boolean acceptImplements(CtClass clazz) {
187 if (this.interfaceType == null) {
188 return true;
189 }
190 CtClass ka[];
191 try {
192 ka = clazz.getInterfaces();
193 } catch (NotFoundException e) {
194 log.error("Error", e);
195 throw new Error(e.getMessage());
196 }
197 for(int i =0; i < ka.length; i ++) {
198 String name = ka[i].getName();
199 if (name.equals(interfaceType)) {
200 return true;
201 }
202 }
203 return false;
204 }
205
206 /***
207 * DOCUMENT ME!
208 *
209 * @param clazz DOCUMENT ME!
210 *
211 * @return DOCUMENT ME!
212 */
213 protected boolean acceptClass(String clazz) {
214 return super.accept(getGlobPattern(classType), clazz);
215 }
216
217 /***
218 * DOCUMENT ME!
219 *
220 * @param method DOCUMENT ME!
221 *
222 * @return DOCUMENT ME!
223 */
224 public boolean acceptMethod(CtMethod method) {
225 try {
226 String name = method.getName();
227 CtClass[] paramTypes = method.getParameterTypes();
228
229 CtClass mFilterClass = getclassAsMethodsFilter();
230 if (mFilterClass != null) {
231 CtMethod has = null;
232 try {
233
234 has = mFilterClass.getDeclaredMethod(name, paramTypes);
235 } catch (NotFoundException e) {
236 return false;
237 }
238 if (has == null) {
239 return false;
240 }
241 }
242
243 String[] params = new String[paramTypes.length];
244 for (int i = 0; i < paramTypes.length; i++) {
245 params[i] = paramTypes[i].getName();
246 }
247
248 String retType = method.getReturnType().getName();
249
250 return super.match(name)
251 && retTypeFilter.match(retType)
252 && paramsFilter.match(params)
253 && modifierListFiler.match(method.getModifiers());
254
255 } catch (NotFoundException nfe) {
256 log.error("Error", nfe);
257 return false;
258 }
259 }
260
261 /***
262 * DOCUMENT ME!
263 *
264 * @param method DOCUMENT ME!
265 * @param params DOCUMENT ME!
266 * @param retType DOCUMENT ME!
267 *
268 * @return DOCUMENT ME!
269 */
270 boolean acceptMethod(String method, String[] params, String retType) {
271
272
273 return super.match(method) && retTypeFilter.match(retType) && paramsFilter.match(params);
274 }
275
276 public boolean acceptConstr(CtConstructor constr) {
277 try {
278 CtClass[] paramTypes = constr.getParameterTypes();
279 String[] params = new String[paramTypes.length];
280 for (int i = 0; i < paramTypes.length; i++) {
281 params[i] = paramTypes[i].getName();
282 }
283 return acceptConstr(params);
284 } catch (NotFoundException nfe) {
285 nfe.printStackTrace();
286 return false;
287 }
288 }
289
290
291 /***
292 * DOCUMENT ME!
293 *
294 * @param constr DOCUMENT ME!
295 * @param params DOCUMENT ME!
296 *
297 * @return DOCUMENT ME!
298 */
299 protected boolean acceptConstr(String[] params) {
300
301
302 return super.match("new");
303 }
304 /***
305 * @return
306 */
307 public String getMethodName() {
308 return methodName;
309 }
310
311 /***
312 * @return
313 */
314 public String getRetType() {
315 return retType;
316 }
317
318 }