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.log.Logger;
29 import net.sf.jour.util.RegExUtil;
30
31
32
33
34 public class Pointcut extends MatchStringFilter {
35
36 protected static final Logger log = Logger.getLogger();
37
38 private static String modifierKeywords = "((final)|(static)|(native)|(synchronized)|(private)|(public)|(protected))";
39
40 private static String modifierListPattern = "(" + modifierKeywords + "(([;,]!?)" + modifierKeywords + ")*)";
41
42 private static String interfaceMethodsPattern = "(\\S*)\\s*(\\S*)\\s*->\\s*(\\S*)\\s*\\((.*)\\)";
43
44 private static String classMethodsPattern = "(\\S*)\\s*(\\S*)\\s*=>\\s*(\\S*)\\s*\\((.*)\\)";
45
46 private static String methodPattern = "\\s*(\\S*)\\s*(\\S*)\\s*\\((.*)\\)";
47
48 private String retType = "";
49
50 private MatchStringListFilter retTypeFilter = new MatchStringListFilter();
51
52 private PointcutModifierListFiler modifierListFiler = new PointcutModifierListFiler();
53
54 private String classType = "*";
55
56 private String interfaceType;
57
58 private String classMethodsType;
59
60 private CtClass filterCtClass;
61
62 private String methodName = "";
63
64 PointcutParamsFilter paramsFilter = new PointcutParamsFilter();
65
66
67
68
69 public Pointcut(String expr) {
70 String mod = RegExUtil.getParen(expr, modifierListPattern);
71 if (mod != null) {
72 if (debug) {
73 log.debug("modexpr: " + expr);
74 log.debug("mod: " + mod);
75 }
76 modifierListFiler.addPatterns(mod);
77 expr = expr.substring(mod.length());
78 }
79 String[] interfaceResult = RegExUtil.match(expr, interfaceMethodsPattern);
80 if ((debug) && (interfaceResult.length != 0)) {
81 log.debug("interface expr: " + expr);
82 for (int i = 0; i < interfaceResult.length; i++) {
83 log.debug(i + " " + interfaceResult[i]);
84 }
85 }
86 if (interfaceResult.length == 4) {
87 log.debug("use interface expr: " + expr);
88 interfaceType = interfaceResult[1];
89 } else {
90 interfaceResult = RegExUtil.match(expr, classMethodsPattern);
91 if (interfaceResult.length == 4) {
92 log.debug("use classMethods as filter expr: " + expr);
93 classMethodsType = interfaceResult[1];
94 }
95 }
96
97 if (interfaceResult.length == 4) {
98 retType = interfaceResult[0];
99 retTypeFilter.addPatterns(retType);
100
101 methodName = interfaceResult[2];
102 super.setPattern(methodName);
103 paramsFilter.setParams(interfaceResult[3]);
104
105 modifierListFiler.initialized();
106 } else {
107 String[] result = RegExUtil.match(expr, methodPattern);
108 if (debug) {
109 log.debug("expr: " + expr);
110 for (int i = 0; i < result.length; i++) {
111 log.debug(i + " " + result[i]);
112 }
113 }
114
115 if (result.length == 3) {
116 retType = result[0];
117 retTypeFilter.addPatterns(retType);
118 methodName = result[1];
119 super.setPattern(methodName);
120 paramsFilter.setParams(result[2]);
121 modifierListFiler.initialized();
122 } else {
123 log.error("wrong pointcut expr \"" + expr + "\"");
124 }
125 }
126 }
127
128 public int matchState(Object obj) {
129 if (obj instanceof CtClass) {
130 return b2Match(acceptClass((CtClass) obj));
131 } else if (obj instanceof CtMethod) {
132 return b2Match(acceptMethod((CtMethod) obj));
133 } else {
134 return super.matchState(obj);
135 }
136 }
137
138 private CtClass getclassAsMethodsFilter(ClassPool pool) {
139 if (this.filterCtClass != null) {
140 return this.filterCtClass;
141 }
142
143 if (this.interfaceType != null) {
144 return loadFilterClass(pool, this.interfaceType);
145 } else if (this.classMethodsType != null) {
146 return loadFilterClass(pool, this.classMethodsType);
147 } else {
148 return null;
149 }
150 }
151
152 private CtClass loadFilterClass(ClassPool pool, String className) {
153 if (className == null) {
154 return null;
155 }
156 try {
157 this.filterCtClass = pool.get(className);
158 } catch (NotFoundException nfe) {
159 log.error("Error ", nfe);
160 throw new Error(nfe.getMessage());
161 }
162 return this.filterCtClass;
163 }
164
165 public boolean acceptClass(CtClass clazz) {
166 return acceptClass(clazz.getName()) && acceptImplements(clazz);
167 }
168
169 public boolean acceptImplements(CtClass clazz) {
170 if (this.interfaceType == null) {
171 return true;
172 }
173 CtClass ka[];
174 try {
175 ka = clazz.getInterfaces();
176 } catch (NotFoundException e) {
177 log.error("Error", e);
178 throw new Error(e.getMessage());
179 }
180 for (int i = 0; i < ka.length; i++) {
181 String name = ka[i].getName();
182 if (name.equals(interfaceType)) {
183 return true;
184 }
185 }
186 return false;
187 }
188
189 protected boolean acceptClass(String clazz) {
190 return super.accept(getGlobPattern(classType), clazz);
191 }
192
193 public boolean acceptMethod(CtMethod method) {
194 try {
195 String name = method.getName();
196 CtClass[] paramTypes = method.getParameterTypes();
197
198 CtClass mFilterClass = getclassAsMethodsFilter(method.getDeclaringClass().getClassPool());
199 if (mFilterClass != null) {
200 CtMethod has = null;
201 try {
202
203 has = mFilterClass.getDeclaredMethod(name, paramTypes);
204 } catch (NotFoundException e) {
205 return false;
206 }
207 if (has == null) {
208 return false;
209 }
210 }
211
212 String[] params = new String[paramTypes.length];
213 for (int i = 0; i < paramTypes.length; i++) {
214 params[i] = paramTypes[i].getName();
215 }
216
217 String retType = method.getReturnType().getName();
218
219 return super.match(name) && retTypeFilter.match(retType) && paramsFilter.match(params)
220 && modifierListFiler.match(method.getModifiers());
221
222 } catch (NotFoundException nfe) {
223 log.error("Error", nfe);
224 return false;
225 }
226 }
227
228 boolean acceptMethod(String method, String[] params, String retType) {
229
230
231 return super.match(method) && retTypeFilter.match(retType) && paramsFilter.match(params);
232 }
233
234 public boolean acceptConstr(CtConstructor constr) {
235 try {
236 CtClass[] paramTypes = constr.getParameterTypes();
237 String[] params = new String[paramTypes.length];
238 for (int i = 0; i < paramTypes.length; i++) {
239 params[i] = paramTypes[i].getName();
240 }
241 return acceptConstr(params);
242 } catch (NotFoundException nfe) {
243 nfe.printStackTrace();
244 return false;
245 }
246 }
247
248 protected boolean acceptConstr(String[] params) {
249
250
251 return super.match("new");
252 }
253
254 public String getMethodName() {
255 return methodName;
256 }
257
258 public String getRetType() {
259 return retType;
260 }
261
262 }