View Javadoc
1 /* 2 * JoinPoint.java 3 * Created on August 30, 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.sys; 27 28 import java.lang.reflect.Method; 29 30 import java.util.Iterator; 31 import java.util.LinkedList; 32 import java.util.List; 33 34 import com.lonniepryor.blues.aop.After; 35 import com.lonniepryor.blues.aop.AfterReturning; 36 import com.lonniepryor.blues.aop.AfterThrowing; 37 import com.lonniepryor.blues.aop.Around; 38 import com.lonniepryor.blues.aop.Before; 39 import com.lonniepryor.blues.aop.Imposter; 40 import com.lonniepryor.blues.util.Types; 41 42 import net.sf.cglib.MethodProxy; 43 44 /*** 45 * Models the interception logic for a single service method. 46 * 47 * @author Lonnie Pryor 48 * @version $Revision: 1.1 $ 49 */ 50 public final class Interceptor { 51 /*** The method to intercept. */ 52 private final Method method; 53 /*** The target we're pointing at. */ 54 private Target interceptorTarget; 55 56 /*** 57 * Creates a new JoinPoint object. 58 * 59 * @param method The method to intercept. 60 */ 61 Interceptor (Method method) { 62 this.method = method; 63 interceptorTarget = isRequired() ? new InvokeImposterTarget() 64 : (Target)new InvokeSuperTarget(); 65 } 66 67 /*** 68 * Returns true if this interceptor invokes an introduced method. 69 * 70 * @return True if this interceptor invokes an introduced method. 71 */ 72 boolean isRequired () { 73 return Types.interfaces().isSatisfiedBy(method.getDeclaringClass()); 74 } 75 76 /*** 77 * Returns the method to intercept. 78 * 79 * @return The method to intercept. 80 */ 81 Method getMethod () { 82 return method; 83 } 84 85 /*** 86 * Allows this interceptor a chance to control the execution of its method. 87 * 88 * @param target The target object that was invoked. 89 * @param parameters The parameters to the target. 90 * @param proxy The method proxy. 91 * 92 * @return The return value for the intercepted method invocation. 93 */ 94 Object interceptInvocation ( 95 Object target, Object[] parameters, MethodProxy proxy) 96 throws Throwable { 97 return interceptorTarget.process(target, parameters, proxy); 98 } 99 100 /*** 101 * Binds the supplied advice to this interceptor. 102 * 103 * @param allAdvice All instances of Advice to bind. 104 */ 105 void bindAdvice (List allAdvice) { 106 if (allAdvice.isEmpty()) 107 return; 108 List beforeAdvice = new LinkedList(); 109 List afterAdvice = new LinkedList(); 110 List afterReturningAdvice = new LinkedList(); 111 List afterThrowingAdvice = new LinkedList(); 112 List aroundAdvice = new LinkedList(); 113 for (Iterator iter = allAdvice.iterator(); iter.hasNext();) { 114 Object adviceInstance = ((Advice)iter.next()).getComponentInstance(); 115 if (adviceInstance instanceof Before) 116 beforeAdvice.add(adviceInstance); 117 if (adviceInstance instanceof After) 118 afterAdvice.add(adviceInstance); 119 if (adviceInstance instanceof AfterReturning) 120 afterReturningAdvice.add(adviceInstance); 121 if (adviceInstance instanceof AfterThrowing) 122 afterThrowingAdvice.add(adviceInstance); 123 if (adviceInstance instanceof Around) 124 aroundAdvice.add(adviceInstance); 125 } 126 if (!aroundAdvice.isEmpty()) 127 interceptorTarget = new AroundAdviceTarget( 128 (Around[])aroundAdvice.toArray(new Around[aroundAdvice.size()]), 129 interceptorTarget); 130 if (!afterThrowingAdvice.isEmpty()) 131 interceptorTarget = new AfterThrowingAdviceTarget( 132 (AfterThrowing[])afterThrowingAdvice.toArray( 133 new AfterThrowing[afterThrowingAdvice.size()]), interceptorTarget); 134 if (!afterReturningAdvice.isEmpty()) 135 interceptorTarget = new AfterReturningAdviceTarget( 136 (AfterReturning[])afterReturningAdvice.toArray( 137 new AfterReturning[afterReturningAdvice.size()]), interceptorTarget); 138 if (!afterAdvice.isEmpty()) 139 interceptorTarget = new AfterAdviceTarget( 140 (After[])afterAdvice.toArray(new After[afterAdvice.size()]), 141 interceptorTarget); 142 if (!beforeAdvice.isEmpty()) 143 interceptorTarget = new BeforeAdviceTarget( 144 (Before[])beforeAdvice.toArray(new Before[beforeAdvice.size()]), 145 interceptorTarget); 146 } 147 148 /*** 149 * Represents an invokable target of an interceptor. 150 * 151 * @author Lonnie Pryor 152 * @version $Revision: 1.1 $ 153 */ 154 private interface Target { 155 /*** 156 * Allows this target a chance to control the execution of this interceptor's 157 * method. 158 * 159 * @param target The target object that was invoked. 160 * @param parameters The parameters to the target. 161 * @param proxy The method proxy. 162 * 163 * @return The return value for the intercepted method invocation. 164 */ 165 Object process (Object target, Object[] parameters, MethodProxy proxy) 166 throws Throwable; 167 } 168 169 /*** 170 * Target that invokes the concrete method on the instance. 171 * 172 * @author Lonnie Pryor 173 * @version $Revision: 1.1 $ 174 */ 175 private final class InvokeSuperTarget implements Target { 176 /* (non-Javadoc) 177 * @see com.lonniepryor.blues.sys.Interceptor.Target#process(java.lang.Object, 178 * java.lang.Object[], net.sf.cglib.MethodProxy) 179 */ 180 public Object process (Object target, Object[] parameters, MethodProxy proxy) 181 throws Throwable { 182 return proxy.invokeSuper(target, parameters); 183 } 184 } 185 186 /*** 187 * Target that invokes the Imposter method on the instance. 188 * 189 * @author Lonnie Pryor 190 * @version $Revision: 1.1 $ 191 */ 192 private final class InvokeImposterTarget implements Target { 193 /* (non-Javadoc) 194 * @see com.lonniepryor.blues.sys.Interceptor.Target#process(java.lang.Object, 195 * java.lang.Object[], net.sf.cglib.MethodProxy) 196 */ 197 public Object process (Object target, Object[] parameters, MethodProxy proxy) 198 throws Throwable { 199 return ((Imposter)target).process(method, parameters); 200 } 201 } 202 203 /*** 204 * Target that invokes before advice. 205 * 206 * @author Lonnie Pryor 207 * @version $Revision: 1.1 $ 208 */ 209 private final class BeforeAdviceTarget implements Target { 210 /*** The advice to invoke. */ 211 private final Before[] advice; 212 /*** The next target in the chain. */ 213 private final Target next; 214 215 /*** 216 * Creates a new BeforeAdviceTarget object. 217 * 218 * @param advice The advice to invoke. 219 * @param next The next target in the chain. 220 */ 221 BeforeAdviceTarget (Before[] advice, Target next) { 222 this.advice = advice; 223 this.next = next; 224 } 225 226 /* (non-Javadoc) 227 * @see com.lonniepryor.blues.sys.Interceptor.Target#process(java.lang.Object, 228 * java.lang.Object[], net.sf.cglib.MethodProxy) 229 */ 230 public Object process (Object target, Object[] parameters, MethodProxy proxy) 231 throws Throwable { 232 for (int i = 0; i < advice.length; ++i) 233 advice[i].before(target, method, parameters); 234 return next.process(target, parameters, proxy); 235 } 236 } 237 238 /*** 239 * Target that invokes after advice. 240 * 241 * @author Lonnie Pryor 242 * @version $Revision: 1.1 $ 243 */ 244 private final class AfterAdviceTarget implements Target { 245 /*** The advice to invoke. */ 246 private final After[] advice; 247 /*** The next target in the chain. */ 248 private final Target next; 249 250 /*** 251 * Creates a new AfterAdviceTarget object. 252 * 253 * @param advice The advice to invoke. 254 * @param next The next target in the chain. 255 */ 256 AfterAdviceTarget (After[] advice, Target next) { 257 this.advice = advice; 258 this.next = next; 259 } 260 261 /* (non-Javadoc) 262 * @see com.lonniepryor.blues.sys.Interceptor.Target#process(java.lang.Object, 263 * java.lang.Object[], net.sf.cglib.MethodProxy) 264 */ 265 public Object process (Object target, Object[] parameters, MethodProxy proxy) 266 throws Throwable { 267 try { 268 return next.process(target, parameters, proxy); 269 } finally { 270 for (int i = 0; i < advice.length; ++i) 271 advice[i].after(target, method, parameters); 272 } 273 } 274 } 275 276 /*** 277 * Target that invokes after returning advice. 278 * 279 * @author Lonnie Pryor 280 * @version $Revision: 1.1 $ 281 */ 282 private final class AfterReturningAdviceTarget implements Target { 283 /*** The advice to invoke. */ 284 private final AfterReturning[] advice; 285 /*** The next target in the chain. */ 286 private final Target next; 287 288 /*** 289 * Creates a new AfterReturningAdviceTarget object. 290 * 291 * @param advice The advice to invoke. 292 * @param next The next target in the chain. 293 */ 294 AfterReturningAdviceTarget (AfterReturning[] advice, Target next) { 295 this.advice = advice; 296 this.next = next; 297 } 298 299 /* (non-Javadoc) 300 * @see com.lonniepryor.blues.sys.Interceptor.Target#process(java.lang.Object, 301 * java.lang.Object[], net.sf.cglib.MethodProxy) 302 */ 303 public Object process (Object target, Object[] parameters, MethodProxy proxy) 304 throws Throwable { 305 Object result = next.process(target, parameters, proxy); 306 for (int i = 0; i < advice.length; ++i) 307 advice[i].afterReturning(target, method, parameters, result); 308 return result; 309 } 310 } 311 312 /*** 313 * Target that invokes after returning advice. 314 * 315 * @author Lonnie Pryor 316 * @version $Revision: 1.1 $ 317 */ 318 private final class AfterThrowingAdviceTarget implements Target { 319 /*** The advice to invoke. */ 320 private final AfterThrowing[] advice; 321 /*** The next target in the chain. */ 322 private final Target next; 323 324 /*** 325 * Creates a new AfterThrowingAdviceTarget object. 326 * 327 * @param advice The advice to invoke. 328 * @param next The next target in the chain. 329 */ 330 AfterThrowingAdviceTarget (AfterThrowing[] advice, Target next) { 331 this.advice = advice; 332 this.next = next; 333 } 334 335 /* (non-Javadoc) 336 * @see com.lonniepryor.blues.sys.Interceptor.Target#process(java.lang.Object, 337 * java.lang.Object[], net.sf.cglib.MethodProxy) 338 */ 339 public Object process (Object target, Object[] parameters, MethodProxy proxy) 340 throws Throwable { 341 try { 342 return next.process(target, parameters, proxy); 343 } catch (Throwable thrown) { 344 for (int i = 0; i < advice.length; ++i) 345 advice[i].afterThrowing(target, method, parameters, thrown); 346 throw thrown; 347 } 348 } 349 } 350 351 /*** 352 * Target that invokes around advice. 353 * 354 * @author Lonnie Pryor 355 * @version $Revision: 1.1 $ 356 */ 357 private final class AroundAdviceTarget implements Target { 358 /*** The advice to invoke. */ 359 private final Around[] advice; 360 /*** The next target in the chain. */ 361 private final Target next; 362 363 /*** 364 * Creates a new AroundAdviceTarget object. 365 * 366 * @param advice The advice to invoke. 367 * @param next The next target in the chain. 368 */ 369 AroundAdviceTarget (Around[] advice, Target next) { 370 this.advice = advice; 371 this.next = next; 372 } 373 374 /* (non-Javadoc) 375 * @see com.lonniepryor.blues.sys.Interceptor.Target#process(java.lang.Object, 376 * java.lang.Object[], net.sf.cglib.MethodProxy) 377 */ 378 public Object process ( 379 final Object target, final Object[] parameters, final MethodProxy proxy) 380 throws Throwable { 381 return advice[0].around( 382 target, method, parameters, 383 new Around.InvoctionChain() { 384 int index = 0; 385 386 public Object invokeNext () 387 throws Throwable { 388 ++index; 389 return (index < advice.length) 390 ? advice[index].around(target, method, parameters, this) 391 : next.process(target, parameters, proxy); 392 } 393 }); 394 } 395 } 396 }

This page was automatically generated by Maven