1 package dynaop; 2 3 import java.io.Serializable ; 4 import java.util.ArrayList ; 5 import java.util.Arrays ; 6 import java.util.Iterator ; 7 import java.util.List ; 8 import java.util.Properties ; 9 10 import net.sf.cglib.Factory; 11 12 import dynaop.ClassPointcut; 13 import dynaop.ConfigurationException; 14 import dynaop.MethodPointcut; 15 import dynaop.ProxyType; 16 import dynaop.ProxyTypeBuilder; 17 import dynaop.util.Classes; 18 import dynaop.util.Closure; 19 import dynaop.util.NestedException; 20 21 30 public class Aspects { 31 32 static String DEFAULT_ASPECTS = "dynaop.bsh.BshAspects"; 33 34 static List IGNORED_INTERFACES = Arrays.asList( 36 new Class [] { Serializable .class, Proxy.class, ProxyAware.class, 37 Factory.class, Cloneable .class }); 38 39 List interfaceAspects = new ArrayList (); 40 List interceptionAspects = new ArrayList ();; 41 List mixinAspects = new ArrayList (); 42 43 public Aspects() {} 44 45 Aspects(Aspects aspects) { 46 this.interfaceAspects = new ArrayList (aspects.interfaceAspects); 47 this.mixinAspects = new ArrayList (aspects.mixinAspects); 48 this.interceptionAspects = new ArrayList (aspects.interceptionAspects); 49 } 50 51 void execute(List aspects, ProxyTypeBuilder builder) { 52 for (Iterator iterator = aspects.iterator(); iterator.hasNext();) 53 ((Closure) iterator.next()).execute(builder); 54 } 55 56 60 ProxyType createProxyType(Class targetClass, 61 ProxyTypeBuilder builder) { 62 execute(this.interfaceAspects, builder); 63 execute(this.interceptionAspects, builder); 64 execute(this.mixinAspects, builder); 65 66 return (builder.isEmpty()) ? null : builder.createProxyType(); 67 } 68 69 73 79 public void interfaces(ClassPointcut classPointcut, 80 final Class [] interfaces) 81 throws ConfigurationException { 82 if (interfaces == null) 83 throw new ConfigurationException("Interface array is null."); 84 85 Closure interfaceAspect = new Closure() { 86 public void execute(Object o) { 87 ((ProxyTypeBuilder) o).addInterfaces(interfaces); 88 } 89 }; 90 91 interfaceAspects.add( 92 new ClassPointcutAspect(classPointcut, interfaceAspect)); 93 } 94 95 99 111 public void mixin(ClassPointcut classPointcut, 112 final Class [] interfaces, Class mixinClass, Closure initializer) 113 throws ConfigurationException { 114 if (!Classes.implementsInterfaces(mixinClass, interfaces)) { 115 throw new ConfigurationException(mixinClass + 116 " must implement each of " + Arrays.asList(interfaces) + "."); 117 } 118 119 interfaces(classPointcut, interfaces); 120 121 final InterceptorFactory factory = 122 new MixinInterceptorFactory(mixinClass, initializer); 123 Closure mixinAspect = new Closure() { 124 public void execute(Object o) { 125 ((ProxyTypeBuilder) o).addInterceptorFactory(interfaces, 126 factory); 127 } 128 }; 129 130 mixinAspects.add(new ClassPointcutAspect(classPointcut, mixinAspect)); 131 } 132 133 136 public void mixin(ClassPointcut classPointcut, Class mixinClass, 137 Closure initializer) 138 throws ConfigurationException { 139 List classes = Classes.getAllInterfacesAsList(mixinClass); 140 classes.removeAll(IGNORED_INTERFACES); 141 mixin(classPointcut, 142 (Class []) classes.toArray(new Class [classes.size()]), 143 mixinClass, initializer); 144 } 145 146 149 public void mixin(ClassPointcut classPointcut, final Class [] interfaces, 150 MixinFactory mixinFactory) 151 throws ConfigurationException { 152 interfaces(classPointcut, interfaces); 153 154 final InterceptorFactory factory = 155 new MixinFactoryInterceptorFactory(mixinFactory); 156 Closure mixinAspect = new Closure() { 157 public void execute(Object o) { 158 ((ProxyTypeBuilder) o).addInterceptorFactory(interfaces, 159 factory); 160 } 161 }; 162 163 mixinAspects.add(new ClassPointcutAspect(classPointcut, mixinAspect)); 164 } 165 166 170 179 public void interceptor(ClassPointcut classPointcut, 180 final MethodPointcut methodPointcut, Interceptor interceptor) 181 throws ConfigurationException { 182 interceptor(classPointcut, methodPointcut, 183 new SingletonInterceptorFactory(interceptor)); 184 } 185 186 199 public void interceptor(ClassPointcut classPointcut, 200 MethodPointcut methodPointcut, Class interceptorClass, 201 Closure initializer) 202 throws ConfigurationException { 203 interceptor(classPointcut, methodPointcut, 204 new PerInstanceInterceptorFactory(interceptorClass, initializer)); 205 } 206 207 214 public void interceptor(ClassPointcut classPointcut, 215 final MethodPointcut methodPointcut, 216 final InterceptorFactory factory) 217 throws ConfigurationException { 218 if (methodPointcut == null) 219 throw new ConfigurationException("Method set is null."); 220 221 Closure interceptionAspect = new Closure() { 222 public void execute(Object o) { 223 ((ProxyTypeBuilder) o).addInterceptorFactory( 224 methodPointcut, factory); 225 } 226 }; 227 228 this.interceptionAspects.add( 229 new ClassPointcutAspect(classPointcut, interceptionAspect)); 230 } 231 232 235 static void handleProxyAware(Object o, Proxy proxy) { 236 if (o instanceof ProxyAware) 237 ((ProxyAware) o).setProxy(proxy); 238 } 239 240 static class ClassPointcutAspect implements Closure { 241 242 private ClassPointcut classPointcut; 243 private Closure aspect; 244 245 ClassPointcutAspect(ClassPointcut classPointcut, Closure aspect) { 246 if (classPointcut == null) 247 throw new ConfigurationException("ClassPointcut is null."); 248 if (aspect == null) 249 throw new ConfigurationException("Aspect is null."); 250 251 this.classPointcut = classPointcut; 252 this.aspect = aspect; 253 } 254 255 public void execute(Object o) { 256 ProxyTypeBuilder builder = (ProxyTypeBuilder) o; 257 if (this.classPointcut.picks(builder.getProxiedClass())) 258 this.aspect.execute(builder); 259 } 260 } 261 262 266 static class SingletonInterceptorFactory implements InterceptorFactory, 267 Serializable { 268 269 static long serialVersionUID = 0; 270 271 Interceptor interceptor; 272 273 SingletonInterceptorFactory(Interceptor interceptor) { 274 this.interceptor = interceptor; 275 } 276 277 public Interceptor create(Proxy proxy) { 278 handleProxyAware(this.interceptor, proxy); 279 return this.interceptor; 280 } 281 282 public Properties getProperties() { 283 Properties properties = new Properties (); 284 properties.setProperty("advice", "method interceptor"); 285 properties.setProperty("scope", "global"); 286 properties.setProperty("class", 287 this.interceptor.getClass().getName()); 288 return properties; 289 } 290 } 291 292 static class PerInstanceInterceptorFactory implements InterceptorFactory, 293 Serializable { 294 295 static long serialVersionUID = 0; 296 297 Class clazz; 298 Closure initializer; 299 300 PerInstanceInterceptorFactory(Class clazz, Closure initializer) { 301 if (!Interceptor.class.isAssignableFrom(clazz)) 302 throw new ConfigurationException(clazz.getName() + 303 " must implement " + Interceptor.class.getName() + "."); 304 305 this.clazz = clazz; 306 this.initializer = initializer; 307 } 308 309 public Interceptor create(Proxy proxy) { 310 Interceptor interceptor = (Interceptor) Classes.newInstance(clazz); 311 handleProxyAware(interceptor, proxy); 312 if (this.initializer != null) 313 this.initializer.execute(interceptor); 314 return interceptor; 315 } 316 317 public Properties getProperties() { 318 Properties properties = new Properties (); 319 properties.setProperty("advice", "method interceptor"); 320 properties.setProperty("scope", "per-instance"); 321 properties.setProperty("class", this.clazz.getName()); 322 if (this.initializer != null) 323 properties.setProperty("initializer", 324 this.initializer.toString()); 325 326 return properties; 327 } 328 } 329 330 static class MixinInterceptorFactory implements InterceptorFactory, 331 Serializable { 332 333 static long serialVersionUID = 0; 334 335 Class clazz; 336 Closure initializer; 337 338 MixinInterceptorFactory(Class clazz, Closure initializer) { 339 this.clazz = clazz; 340 } 341 342 public Interceptor create(Proxy proxy) { 343 try { 344 Object mixin = this.clazz.newInstance(); 345 346 handleProxyAware(mixin, proxy); 348 349 if (this.initializer != null) 351 this.initializer.execute(mixin); 352 353 return new MixinInterceptor(mixin); 354 } 355 catch (Exception e) { 356 throw NestedException.wrap(e); 357 } 358 } 359 360 public Properties getProperties() { 361 Properties properties = new Properties (); 362 properties.setProperty("advice", "mixin"); 363 properties.setProperty("class", this.clazz.getName()); 364 if (this.initializer != null) 365 properties.setProperty("initializer", 366 this.initializer.toString()); 367 368 return properties; 369 } 370 } 371 372 static class MixinInterceptor implements Interceptor, Serializable { 373 374 static long serialVersionUID = 0; 375 376 Object mixin; 377 378 MixinInterceptor(Object mixin) { 379 this.mixin = mixin; 380 } 381 382 public Object intercept(Invocation invocation) throws Throwable { 383 return Classes.invoke(this.mixin, invocation.getMethod(), 384 invocation.getArguments()); 385 } 386 } 387 388 static class MixinFactoryInterceptorFactory implements InterceptorFactory, 389 Serializable { 390 391 static long serialVersionUID = 0; 392 393 MixinFactory mixinFactory; 394 395 MixinFactoryInterceptorFactory(MixinFactory mixinFactory) { 396 this.mixinFactory = mixinFactory; 397 } 398 399 public Interceptor create(Proxy proxy) { 400 try { 401 Object mixin = this.mixinFactory.create(proxy); 402 return new MixinInterceptor(mixin); 403 } 404 catch (Exception e) { 405 throw NestedException.wrap(e); 406 } 407 } 408 409 public Properties getProperties() { 410 Properties properties = new Properties (); 411 properties.putAll(this.mixinFactory.getProperties()); 412 properties.setProperty("advice", "mixin"); 413 properties.setProperty("mixinFactory", 414 this.mixinFactory.getClass().getName()); 415 416 return properties; 417 } 418 } 419 420 static Aspects defaultInstance; 421 422 431 public static synchronized Aspects getInstance() { 432 if (defaultInstance == null) { 433 String className = System.getProperty("dynaop.aspects", 434 DEFAULT_ASPECTS); 435 try { 436 defaultInstance = 437 (Aspects) Classes.forName(className).newInstance(); 438 } 439 catch (Exception e) { 440 throw NestedException.wrap(e); 441 } 442 } 443 444 return defaultInstance; 445 } 446 } 447 | Popular Tags |