View Javadoc

1   /*
2    * Jour - java profiler and monitoring library
3    *
4    * Copyright (C) 2004 Jour team
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Library General Public
8    * License as published by the Free Software Foundation; either
9    * version 2 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Library General Public License for more details.
15   *
16   * You should have received a copy of the GNU Library General Public
17   * License along with this library; if not, write to the
18   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19   * Boston, MA  02111-1307, USA.
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                     // this method does not search the superclasses
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         //was TODO to add check for retType and params
272         //return super.accept(getGlobPattern(methodName), method);
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         //TODO to add check for params
301         //return super.accept(getGlobPattern(methodName), "new");
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 }