View Javadoc
1 /* 2 * Pointcut.java 3 * Created on September 12, 2003 4 * 5 * The Blues Framework - A lightweight application framework 6 * Copyright (C) 2003 Lonnie Pryor 7 * http://blues.lonniepryor.com 8 * 9 * This library is free software; you can redistribute it and/or modify it under the 10 * terms of the GNU Lesser General Public License as published by the Free Software 11 * Foundation; either version 2.1 of the License, or (at your option) any later 12 * version. 13 * 14 * This library is distributed in the hope that it will be useful, but WITHOUT ANY 15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 16 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License along 19 * with this library; if not, write to: 20 * 21 * The Free Software Foundation, Inc. 22 * 59 Temple Place, Suite 330 23 * Boston, MA 02111-1307 USA 24 * 25 */ 26 package com.lonniepryor.blues.aop; 27 28 import com.lonniepryor.blues.util.Expression; 29 import com.lonniepryor.blues.util.Methods; 30 import com.lonniepryor.blues.util.ParseException; 31 import com.lonniepryor.blues.util.Strings; 32 import com.lonniepryor.blues.util.TokenizedStrings; 33 34 /*** 35 * Specification interface for identifying JoinPoints. Instances of this class may 36 * be logically combined using the AND, OR, and NOT operations. Many common 37 * use-cases are supplied via static accessor methods. 38 * 39 * @author Lonnie Pryor 40 * @version $Revision: 1.1 $ 41 */ 42 public abstract class Pointcut { 43 /*** 44 * Creates a new Pointcut object. 45 */ 46 protected Pointcut () { 47 } 48 49 /*** 50 * Creates a new specification satisified by join points whose instance name 51 * satisfy the supplied specification. 52 * 53 * @param specification The specification to test instance names with. 54 * 55 * @return A new specification satisified by join points whose instance name 56 * satisfy the supplied specification. 57 */ 58 public static Pointcut invokeInstance (final Strings specification) { 59 return new Pointcut() { 60 protected boolean evaluate (Aspect aspect, JoinPoint joinPoint) { 61 return specification.isSatisfiedBy(joinPoint.getInstanceName()); 62 } 63 }; 64 } 65 66 /*** 67 * Creates a new specification satisified by join points whose target method 68 * satisfy the supplied specification. 69 * 70 * @param specification The specification to test target methods with. 71 * 72 * @return A new specification satisified by join points whose target method 73 * satisfy the supplied specification. 74 */ 75 public static Pointcut invokeMethod (final Methods specification) { 76 return new Pointcut() { 77 protected boolean evaluate (Aspect aspect, JoinPoint joinPoint) { 78 return specification.isSatisfiedBy(joinPoint.getTargetMethod()); 79 } 80 }; 81 } 82 83 /*** 84 * Creates a new specification satisified by join points that satisfy the named 85 * pointcut. 86 * 87 * @param poincutName The name of the pointcut to evaluate. 88 * 89 * @return A new specification satisified by join points that satisfy the named 90 * pointcut. 91 */ 92 public static Pointcut refrence (final String poincutName) { 93 return new Pointcut() { 94 protected boolean evaluate (Aspect aspect, JoinPoint joinPoint) { 95 return aspect.callPointcut(poincutName, joinPoint); 96 } 97 }; 98 } 99 100 /*** 101 * Parses a pattern consisting of a pointcut declaration. Format: 102 * <pre> 103 * pointcut ::= invoke-pointcut | named-pointcut 104 * invoke-pointcut ::= "invoke" "(" invoke-params ")" 105 * invoke-params ::= [ "[" instance-pattern "]" ] method-pattern. 106 * instance-pattern ::= A '/'-delimeted {@link com.lonniepryor.blues.util.TokenizedStrings} pattern expression. 107 * method-pattern ::= A {@link com.lonniepryor.blues.util.Methods} pattern. 108 * named-pointcut ::= name "(" ")" 109 * name ::= Any valid Java name except "invoke". 110 * </pre> 111 * Example: 112 * <pre> 113 * invoke([aService || anotherService] void *(int, ..)) 114 * </pre> 115 * The above creates a specification satisified by join points on instances named 116 * 'aService' or 'anotherService', with a target method that returns void and 117 * takes an int as its first parameter. 118 * 119 * @param pointcutPattern The pattern definition string. 120 * 121 * @return A specification matching the pattern. 122 * 123 * @throws ParseException if the pattern is invalid. 124 * 125 * @see com.lonniepryor.blues.util.Methods#parse(String) 126 * @see com.lonniepryor.blues.util.TokenizedStrings#parseExpression(String, char) 127 */ 128 public static Pointcut parse (String pointcutPattern) { 129 int nameStart = Expression.ltrim(pointcutPattern, 0, pointcutPattern.length()); 130 if (nameStart == pointcutPattern.length()) 131 throw new ParseException("Illegal empty pointcut pattern"); 132 int firstParen = pointcutPattern.indexOf('(', nameStart + 1); 133 if (firstParen < 0) 134 throw new ParseException( 135 "Opening parenthesis not found in '" + pointcutPattern + "'"); 136 int nameEnd = Expression.rtrim(pointcutPattern, nameStart, firstParen); 137 if (nameEnd == nameStart) 138 throw new ParseException( 139 "No pointcut name found in '" + pointcutPattern + "'"); 140 int lastParen = pointcutPattern.lastIndexOf(')'); 141 if (lastParen < 0) 142 throw new ParseException( 143 "Unmatched parenthesis in '" + pointcutPattern + "'"); 144 int paramsStart = Expression.ltrim(pointcutPattern, firstParen + 1, lastParen); 145 int paramsEnd = Expression.rtrim(pointcutPattern, paramsStart, lastParen); 146 if ("invoke".regionMatches(0, pointcutPattern, nameStart, nameEnd)) { 147 if (paramsStart == paramsEnd) 148 throw new ParseException( 149 "Illegal empty parameters for invoke() in '" + pointcutPattern + "'"); 150 return readInvokeParams(pointcutPattern, paramsStart, paramsEnd); 151 } 152 if (paramsStart != paramsEnd) 153 throw new ParseException( 154 "Cannot pass parameters to refrenced pointcuts in '" + pointcutPattern 155 + "'"); 156 return refrence(pointcutPattern.substring(nameStart, nameEnd)); 157 } 158 159 /*** 160 * Reads the parameters for an 'invoke' pointcut definition. 161 * 162 * @param pointcutPattern The pattern definition string. 163 * @param start The start of the parameters section. 164 * @param end The end of the parameters section. 165 * 166 * @return A specification matching the 'invoke' pointcut definition. 167 * 168 * @throws ParseException if the pattern is invalid. 169 */ 170 private static Pointcut readInvokeParams ( 171 String pointcutPattern, int start, int end) { 172 Pointcut spec = null; 173 if (pointcutPattern.charAt(start) == '[') { 174 int instanceNameEnd = pointcutPattern.indexOf(']', start); 175 if (instanceNameEnd < 0) 176 throw new ParseException( 177 "No closing instance name bracket found in '" + pointcutPattern + "'"); 178 spec = invokeInstance( 179 TokenizedStrings.parseExpression( 180 pointcutPattern.substring(start + 1, instanceNameEnd), '/')); 181 start = Expression.ltrim(pointcutPattern, instanceNameEnd + 1, end); 182 } 183 if (start == end) 184 throw new ParseException( 185 "Method pattern not found in '" + pointcutPattern + "'"); 186 Methods methodsSpec = Methods.parse(pointcutPattern.substring(start, end)); 187 return (spec == null) ? invokeMethod(methodsSpec) 188 : invokeMethod(methodsSpec).and(spec); 189 } 190 191 /*** 192 * Parses a logical expression as described in the Expression class, using this 193 * class's parse() method for creating values. 194 * 195 * @param pointcutPatternExpr The pattern expression definition string. 196 * 197 * @return A specification matching the pattern expression. 198 * 199 * @throws ParseException if the pattern expression is invalid. 200 * 201 * @see com.lonniepryor.blues.util.Expression 202 * @see Pointcut#parse(String) 203 */ 204 public static Pointcut parseExpression (String pointcutPatternExpr) { 205 return (Pointcut)Expression.parse( 206 pointcutPatternExpr, 207 new Expression.Builder() { 208 public Object or (Object left, Object right) { 209 return ((Pointcut)left).or((Pointcut)right); 210 } 211 212 public Object and (Object left, Object right) { 213 return ((Pointcut)left).and((Pointcut)right); 214 } 215 216 public Object not (Object value) { 217 return ((Pointcut)value).not(); 218 } 219 220 public Object create (String pointcutPattern) { 221 return parse(pointcutPattern); 222 } 223 }); 224 } 225 226 /*** 227 * Returns true if the parameters are not null and the supplied join point 228 * satisfies this pointcut. 229 * 230 * @param aspect The aspect to lookup refrenced pointcuts on. 231 * @param joinPoint The join point to evaluate. 232 * 233 * @return True if the parameters are not null and the supplied join point 234 * satisfies this pointcut. 235 */ 236 public final boolean isSatisfiedBy (Aspect aspect, JoinPoint joinPoint) { 237 return (aspect != null) && (joinPoint != null) && evaluate(aspect, joinPoint); 238 } 239 240 /*** 241 * Returns true if the supplied join point satisfies this pointcut. 242 * 243 * @param aspect The aspect to lookup refrenced pointcuts on. 244 * @param joinPoint The join point to evaluate. 245 * 246 * @return True if the supplied join point satisfies this pointcut. 247 */ 248 protected abstract boolean evaluate (Aspect aspect, JoinPoint joinPoint); 249 250 /*** 251 * Returns a specification representing a logical AND of this specification on 252 * the left and the supplied specification on the right. 253 * 254 * @param specification The specification to AND with. 255 * 256 * @return A specification representing a logical AND of this specification on 257 * the left and the supplied specification on the right. 258 */ 259 public final Pointcut and (final Pointcut specification) { 260 return new Pointcut() { 261 public boolean evaluate (Aspect aspect, JoinPoint joinPoint) { 262 return Pointcut.this.evaluate(aspect, joinPoint) 263 && specification.evaluate(aspect, joinPoint); 264 } 265 }; 266 } 267 268 /*** 269 * Returns a specification representing a logical OR of this specification on the 270 * left and the supplied specification on the right. 271 * 272 * @param specification The specification to OR with. 273 * 274 * @return A specification representing a logical OR of this specification on the 275 * left and the supplied specification on the right. 276 */ 277 public final Pointcut or (final Pointcut specification) { 278 return new Pointcut() { 279 public boolean evaluate (Aspect aspect, JoinPoint joinPoint) { 280 return Pointcut.this.evaluate(aspect, joinPoint) 281 || specification.evaluate(aspect, joinPoint); 282 } 283 }; 284 } 285 286 /*** 287 * Returns a specification representing a logical NOT of this specification. 288 * 289 * @return A specification representing a logical NOT of this specification. 290 */ 291 public final Pointcut not () { 292 return new Pointcut() { 293 public boolean evaluate (Aspect aspect, JoinPoint joinPoint) { 294 return !Pointcut.this.evaluate(aspect, joinPoint); 295 } 296 }; 297 } 298 }

This page was automatically generated by Maven