001 /***************************************************************************** 002 * Copyright (c) PicoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 * * 008 * Idea by Rachel Davies, Original code by various * 009 *****************************************************************************/ 010 package org.nanocontainer.aop.dynaop; 011 012 import dynaop.Aspects; 013 import dynaop.Interceptor; 014 import dynaop.InterceptorFactory; 015 import dynaop.ProxyFactory; 016 import dynaop.util.Classes; 017 import org.aopalliance.intercept.MethodInterceptor; 018 import org.nanocontainer.aop.AspectsManager; 019 import org.nanocontainer.aop.ClassPointcut; 020 import org.nanocontainer.aop.ComponentPointcut; 021 import org.nanocontainer.aop.MethodPointcut; 022 import org.nanocontainer.aop.PointcutsFactory; 023 import org.picocontainer.PicoContainer; 024 025 import java.lang.reflect.Method; 026 027 /** 028 * An <code>AspectsManager</code> implemented using dynaop. 029 * 030 * @author Stephen Molitor 031 * @version $Revision: 3144 $ 032 */ 033 public class DynaopAspectsManager implements AspectsManager { 034 035 private final Aspects containerAspects; 036 private final PointcutsFactory pointcutsFactory; 037 private final ContainerLoader containerLoader = new ContainerLoader(); 038 private final PicoContainer container = PicoContainerProxy.create(containerLoader); 039 private final ComponentAspectsCollection componentAspects = new ComponentAspectsCollection(); 040 041 /** 042 * Creates a new <code>DynaopAspectsManager</code> that will used the 043 * given <code>dynaop.Aspects</code> object and pointcuts factory. This 044 * constructor might be useful if the <code>containerAspects</code> object 045 * contains aspects already configured via dynaop's API, perhaps using 046 * dynaop's BeanShell configuration mechanism. 047 * 048 * @param containerAspects the <code>dyanop.Aspects</code> object used to 049 * contain the aspects. 050 * @param pointcutsFactory the pointcuts factory. 051 */ 052 public DynaopAspectsManager(Aspects containerAspects, PointcutsFactory pointcutsFactory) { 053 this.containerAspects = containerAspects; 054 this.pointcutsFactory = pointcutsFactory; 055 } 056 057 /** 058 * Creates a new <code>DynaopAspectsManager</code> that will used the 059 * given <code>dynaop.Aspects</code> object. This constructor might be 060 * useful if the <code>containerAspects</code> object contains aspects 061 * already configured via dynaop's API, perhaps using dynaop's BeanShell 062 * configuration mechanism. 063 * 064 * @param containerAspects the <code>dyanop.Aspects</code> object used to 065 * contain the aspects. 066 */ 067 public DynaopAspectsManager(Aspects containerAspects) { 068 this(containerAspects, new DynaopPointcutsFactory()); 069 } 070 071 /** 072 * Creates a new <code>DynaopAspectsManager</code> that will use the given 073 * pointcuts factory. 074 * 075 * @param pointcutsFactory the pointcuts factory. 076 */ 077 public DynaopAspectsManager(PointcutsFactory pointcutsFactory) { 078 this(new Aspects(), pointcutsFactory); 079 } 080 081 /** 082 * Creates a new <code>DynaopAspectsManager</code>. 083 */ 084 public DynaopAspectsManager() { 085 this(new Aspects()); 086 } 087 088 public void registerInterceptor(ClassPointcut classPointcut, MethodPointcut methodPointcut, 089 Object interceptorComponentKey) { 090 containerAspects.interceptor(getClassPointcut(classPointcut), getMethodPointcut(methodPointcut), 091 createInterceptorFactory(interceptorComponentKey)); 092 } 093 094 public void registerInterceptor(ClassPointcut classPointcut, MethodPointcut methodPointcut, 095 MethodInterceptor interceptor) { 096 containerAspects.interceptor(getClassPointcut(classPointcut), getMethodPointcut(methodPointcut), 097 createInterceptor(interceptor)); 098 } 099 100 public void registerInterceptor(ComponentPointcut componentPointcut, MethodPointcut methodPointcut, 101 Object interceptorComponentKey) { 102 componentAspects.add(new InterceptorComponentAspect(componentPointcut, getMethodPointcut(methodPointcut), 103 createInterceptorFactory(interceptorComponentKey))); 104 } 105 106 public void registerInterceptor(ComponentPointcut componentPointcut, MethodPointcut methodPointcut, 107 MethodInterceptor interceptor) { 108 componentAspects.add(new InterceptorComponentAspect(componentPointcut, getMethodPointcut(methodPointcut), 109 createInterceptor(interceptor))); 110 } 111 112 public void registerMixin(ClassPointcut classPointcut, Class mixinClass) { 113 registerMixin(classPointcut, Classes.getAllInterfaces(mixinClass), mixinClass); 114 } 115 116 public void registerMixin(ClassPointcut classPointcut, Class[] interfaces, Class mixinClass) { 117 containerAspects.mixin(getClassPointcut(classPointcut), interfaces, new ContainerSuppliedMixinFactory(container, mixinClass)); 118 } 119 120 public void registerMixin(ComponentPointcut componentPointcut, Class mixinClass) { 121 registerMixin(componentPointcut, Classes.getAllInterfaces(mixinClass), mixinClass); 122 } 123 124 public void registerMixin(ComponentPointcut componentPointcut, Class[] interfaces, Class mixinClass) { 125 componentAspects.add(new MixinComponentAspect(componentPointcut, interfaces, new ContainerSuppliedMixinFactory(container, mixinClass))); 126 } 127 128 public void registerInterfaces(ClassPointcut classPointcut, Class[] interfaces) { 129 containerAspects.interfaces(getClassPointcut(classPointcut), interfaces); 130 } 131 132 public void registerInterfaces(ComponentPointcut componentPointcut, Class[] interfaces) { 133 componentAspects.add(new InterfacesComponentAspect(componentPointcut, interfaces)); 134 } 135 136 public PointcutsFactory getPointcutsFactory() { 137 return pointcutsFactory; 138 } 139 140 public Object applyAspects(Object componentKey, Object component, PicoContainer container) { 141 containerLoader.setContainer(container); 142 Aspects aspects = componentAspects.registerAspects(componentKey, containerAspects); 143 return ProxyFactory.getInstance(aspects).wrap(component); 144 } 145 146 private dynaop.ClassPointcut getClassPointcut(final ClassPointcut classPointcut) { 147 if (classPointcut instanceof dynaop.ClassPointcut) { 148 return (dynaop.ClassPointcut) classPointcut; 149 } 150 return new dynaop.ClassPointcut() { 151 public boolean picks(Class clazz) { 152 return classPointcut.picks(clazz); 153 } 154 }; 155 } 156 157 private dynaop.MethodPointcut getMethodPointcut(final MethodPointcut methodPointcut) { 158 if (methodPointcut instanceof dynaop.MethodPointcut) { 159 return (dynaop.MethodPointcut) methodPointcut; 160 } 161 return new dynaop.MethodPointcut() { 162 public boolean picks(Method method) { 163 return methodPointcut.picks(method); 164 } 165 }; 166 } 167 168 private Interceptor createInterceptor(MethodInterceptor methodInterceptor) { 169 return new MethodInterceptorAdapter(methodInterceptor); 170 } 171 172 private InterceptorFactory createInterceptorFactory(Object interceptorComponent) { 173 return new ContainerSuppliedInterceptorFactory(container, interceptorComponent); 174 } 175 176 }