KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > dynaop > Pointcuts


1 package dynaop;
2
3 import java.lang.reflect.Method JavaDoc;
4 import java.util.Collections JavaDoc;
5 import java.util.Map JavaDoc;
6 import java.util.WeakHashMap JavaDoc;
7
8 import org.apache.oro.text.regex.MalformedPatternException;
9 import org.apache.oro.text.regex.Pattern;
10 import org.apache.oro.text.regex.Perl5Compiler;
11 import org.apache.oro.text.regex.Perl5Matcher;
12
13 /**
14  * Creates class and method pointcuts.
15  *
16  * @author Bob Lee (crazybob@crazybob.org)
17  */

18 public class Pointcuts {
19
20     Pointcuts() {}
21     
22     /**
23      * Picks all classes.
24      */

25     public static final ClassPointcut ALL_CLASSES = new ClassPointcut() {
26         public boolean picks(Class JavaDoc clazz) {
27             return true;
28         }
29     };
30     
31     /**
32      * Picks all methods.
33      */

34     public static final MethodPointcut ALL_METHODS = new MethodPointcut() {
35         public boolean picks(Method JavaDoc method) {
36             return true;
37         }
38     };
39     
40     /**
41      * Picks <code>equals()</code>, <code>hashCode()</code>, and
42      * <code>toString()</code>.
43      */

44     public static final MethodPointcut OBJECT_METHODS = declaringClass(
45         singleton(Object JavaDoc.class));
46     
47     /**
48      * Picks getXxx() methods.
49      */

50     public static final MethodPointcut GET_METHODS =
51         new PropertyMethodPointcut("get");
52
53     /**
54      * Picks isXxx() methods.
55      */

56     public static final MethodPointcut IS_METHODS =
57         new PropertyMethodPointcut("is");
58
59     /**
60      * Picks setXxx() methods.
61      */

62     public static final MethodPointcut SET_METHODS =
63         new PropertyMethodPointcut("set");
64
65     /**
66      * Picks all classes in package.
67      */

68     public static ClassPointcut packageName(final String JavaDoc packageName) {
69         return new ClassPointcut() {
70             public boolean picks(Class JavaDoc clazz) {
71                 return clazz.getPackage().getName().equals(packageName);
72             }
73         };
74     }
75     
76     /**
77      * Union of two class pointcuts.
78      */

79     public static ClassPointcut union(final ClassPointcut a,
80             final ClassPointcut b) {
81         return new ClassPointcut() {
82             public boolean picks(Class JavaDoc clazz) {
83                 return a.picks(clazz) || b.picks(clazz);
84             }
85         };
86     }
87     
88     /**
89      * Union of two method pointcuts.
90      */

91     public static MethodPointcut union(final MethodPointcut a,
92                                       final MethodPointcut b) {
93         return new MethodPointcut() {
94             public boolean picks(Method JavaDoc method) {
95                 return a.picks(method) || b.picks(method);
96             }
97         };
98     }
99     
100     /**
101      * Intersection of two class pointcuts.
102      */

103     public static ClassPointcut intersection(final ClassPointcut a,
104                                       final ClassPointcut b) {
105         return new ClassPointcut() {
106             public boolean picks(Class JavaDoc clazz) {
107                 return a.picks(clazz) && b.picks(clazz);
108             }
109         };
110     }
111     
112     /**
113      * Intersection of two method pointcuts.
114      */

115     public static MethodPointcut intersection(final MethodPointcut a,
116             final MethodPointcut b) {
117         return new MethodPointcut() {
118             public boolean picks(Method JavaDoc method) {
119                 return a.picks(method) && b.picks(method);
120             }
121         };
122     }
123     
124     /**
125      * Matches class names with a regular expression.
126      * Uses ORO (http://jakarta.apache.org/oro/index.html).
127      */

128     public static ClassPointcut className(String JavaDoc regex)
129             throws MalformedPatternException {
130         Perl5Compiler compiler = new Perl5Compiler();
131         final Pattern compiled = compiler.compile(regex);
132         final Perl5Matcher matcher = new Perl5Matcher();
133         return new ClassPointcut() {
134             public boolean picks(Class JavaDoc clazz) {
135                 return matcher.contains(clazz.getName(), compiled);
136             }
137         };
138     }
139     
140     /**
141      * Matches method signatures with a regular expression. Method signatures
142      * follow this pattern:
143      *
144      * <pre>
145      * ReturnType methodName(ArgumentType, ArgumentType, ...)
146      * throws ExceptionType, ExceptionType
147      * </pre>
148      *
149      * Omits "java.lang." from classes in <code>java.lang</code> package.
150      * Uses ORO (http://jakarta.apache.org/oro/index.html).
151      */

152     public static MethodPointcut signature(String JavaDoc regex)
153             throws MalformedPatternException {
154         Perl5Compiler compiler = new Perl5Compiler();
155         final Pattern compiled = compiler.compile(regex);
156         final Perl5Matcher matcher = new Perl5Matcher();
157         return new MethodPointcut() {
158             public boolean picks(Method JavaDoc method) {
159                 return matcher.contains(methodToString(method), compiled);
160             }
161         };
162     }
163     
164     /**
165      * Picks classes that are an instance of the parent class or interface.
166      */

167     public static ClassPointcut instancesOf(final Class JavaDoc parent) {
168         return new ClassPointcut() {
169             public boolean picks(Class JavaDoc clazz) {
170                 return parent.isAssignableFrom(clazz);
171             }
172         };
173     }
174     
175     /**
176      * Picks one class.
177      */

178     public static ClassPointcut singleton(final Class JavaDoc c) {
179         return new ClassPointcut() {
180             public boolean picks(Class JavaDoc clazz) {
181                 return clazz.equals(c);
182             }
183         };
184     }
185     
186     /**
187      * Picks one method.
188      */

189     public static MethodPointcut singleton(final Method JavaDoc m) {
190         return new MethodPointcut() {
191             public boolean picks(Method JavaDoc method) {
192                 return method.equals(m);
193             }
194         };
195     }
196     
197     /**
198      * Inverts pointcut.
199      */

200     public static ClassPointcut not(final ClassPointcut a) {
201         return new ClassPointcut() {
202             public boolean picks(Class JavaDoc clazz) {
203                 return !a.picks(clazz);
204             }
205         };
206     }
207     
208     /**
209      * Inverts pointcut.
210      */

211     public static MethodPointcut not(final MethodPointcut a) {
212         return new MethodPointcut() {
213             public boolean picks(Method JavaDoc method) {
214                 return !a.picks(method);
215             }
216         };
217     }
218     
219     /**
220      * Picks method if the given class pointcut picks the method's
221      * declaring class.
222      */

223     public static MethodPointcut declaringClass(
224             final ClassPointcut classPointcut) {
225         return new MethodPointcut() {
226             public boolean picks(Method JavaDoc method) {
227                 return classPointcut.picks(method.getDeclaringClass());
228             }
229         };
230     }
231     
232     /**
233      * Picks method if the given class pointcut picks the method's
234      * return type.
235      */

236     public static MethodPointcut returnType(
237             final ClassPointcut classPointcut) {
238         return new MethodPointcut() {
239             public boolean picks(Method JavaDoc method) {
240                 return classPointcut.picks(method.getReturnType());
241             }
242         };
243     }
244     
245     /**
246      * Picks methods that are members of the given class (whether or not the
247      * method's actual declaring class is an instance of the given class).
248      */

249     public static MethodPointcut membersOf(final Class JavaDoc clazz) {
250         return new MethodPointcut() {
251             public boolean picks(Method JavaDoc method) {
252                 try {
253                     clazz.getMethod(method.getName(),
254                             method.getParameterTypes());
255                     return true;
256                 }
257                 catch (NoSuchMethodException JavaDoc e) {
258                     return false;
259                 }
260             }
261         };
262     }
263     
264     static String JavaDoc getTypeName(Class JavaDoc clazz) {
265         String JavaDoc name = clazz.getName();
266         return (name.startsWith("java.lang.")) ? name.substring(10) : name;
267     }
268     
269     static Map JavaDoc methodSignatureCache =
270         Collections.synchronizedMap(new WeakHashMap JavaDoc());
271     
272     static String JavaDoc methodToString(Method JavaDoc method) {
273         String JavaDoc signature = (String JavaDoc) methodSignatureCache.get(method);
274         if (signature != null)
275             return signature;
276         
277         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
278         buffer.append(getTypeName(method.getReturnType()));
279         buffer.append(' ');
280         buffer.append(method.getName());
281         
282         buffer.append('(');
283         boolean first = true;
284         Class JavaDoc[] types = method.getParameterTypes();
285         for (int i = 0; i < types.length; i++) {
286             if (!first)
287                 buffer.append(", ");
288             first = false;
289             buffer.append(getTypeName(types[i]));
290         }
291         buffer.append(')');
292
293         Class JavaDoc[] exceptions = method.getExceptionTypes();
294         if (exceptions.length > 0) {
295             first = true;
296             buffer.append(" throws ");
297             for (int i = 0; i < exceptions.length; i++) {
298                 if (!first)
299                     buffer.append(", ");
300                 first = false;
301                 buffer.append(getTypeName(exceptions[i]));
302             }
303         }
304         
305         signature = buffer.toString();
306         methodSignatureCache.put(method, signature);
307         return signature;
308     }
309     
310     static class PropertyMethodPointcut implements MethodPointcut {
311         
312         private String JavaDoc prefix;
313         
314         PropertyMethodPointcut(String JavaDoc prefix) {
315             this.prefix = prefix;
316         }
317         
318         public boolean picks(Method JavaDoc method) {
319             String JavaDoc name = method.getName();
320             return (name.length() > prefix.length() &&
321                     Character.isUpperCase(name.charAt(prefix.length())) &&
322                     name.startsWith(prefix));
323         }
324     }
325 }
326
Popular Tags