1 10 11 package org.nanocontainer.aop.defaults; 12 13 import dynaop.Aspects; 14 import dynaop.Pointcuts; 15 import dynaop.ProxyFactory; 16 import org.aopalliance.intercept.MethodInterceptor; 17 import org.nanocontainer.aop.AspectablePicoContainer; 18 import org.nanocontainer.aop.AspectsApplicator; 19 import org.nanocontainer.aop.AspectsContainer; 20 import org.nanocontainer.aop.AspectsManager; 21 import org.nanocontainer.aop.ClassPointcut; 22 import org.nanocontainer.aop.ComponentPointcut; 23 import org.nanocontainer.aop.MethodPointcut; 24 import org.nanocontainer.aop.dynaop.InstanceMixinFactory; 25 import org.nanocontainer.script.NodeBuilderDecorationDelegate; 26 import org.nanocontainer.script.NanoContainerMarkupException; 27 import org.picocontainer.MutablePicoContainer; 28 import org.picocontainer.defaults.ComponentAdapterFactory; 29 30 import java.util.List ; 31 import java.util.Map ; 32 33 38 public class AopNodeBuilderDecorationDelegate implements NodeBuilderDecorationDelegate { 39 40 private final AspectsManager aspectsManager; 41 private Object currentKey; 42 private AspectablePicoContainer currentPico; 43 private ClassPointcut currentClassCut; 44 private MethodPointcut currentMethodCut; 45 46 public AopNodeBuilderDecorationDelegate(AspectsManager aspectsManager) { 47 this.aspectsManager = aspectsManager; 48 } 49 50 public ComponentAdapterFactory decorate(ComponentAdapterFactory componentAdapterFactory, Map attributes) { 51 AspectsComponentAdapterFactory aspectsComponentAdapterFactory = createAdapterFactory(aspectsManager, componentAdapterFactory); 52 return aspectsComponentAdapterFactory; 53 } 54 55 public MutablePicoContainer decorate(MutablePicoContainer picoContainer) { 56 currentPico = mixinAspectablePicoContainer(aspectsManager, picoContainer); 57 return currentPico; 58 } 59 60 public Object createNode(Object name, Map attributes, Object parentElement) { 61 if (name.equals("aspect")) { 62 return createAspectNode(attributes, name); 63 } else if (name.equals("pointcut")) { 64 return createPointcutNode(attributes, name); 65 } else { 66 throw new NanoContainerMarkupException("Don't know how to create a '" + name + "' child of a '" + parentElement.toString() + "' element"); 67 } 68 } 69 70 private Object createPointcutNode(Map attributes, Object name) { 71 currentClassCut = (ClassPointcut) attributes.remove("classCut"); 72 currentMethodCut = (MethodPointcut) attributes.remove("methodCut"); 73 return name; 74 } 75 76 private Object createAspectNode(Map attributes, Object name) { 77 ClassPointcut classCut = (ClassPointcut) attributes.remove("classCut"); 78 if(classCut != null) { 79 currentClassCut = classCut; 80 } 81 MethodPointcut methodCut = (MethodPointcut) attributes.remove("methodCut"); 82 if(methodCut != null) { 83 currentMethodCut = methodCut; 84 } 85 86 MethodInterceptor interceptor = (MethodInterceptor) attributes.remove("interceptor"); 87 Object interceptorKey = attributes.remove("interceptorKey"); 88 Class mixinClass = (Class ) attributes.remove("mixinClass"); 89 List mixinInterfaces = (List ) attributes.remove("mixinInterfaces"); 90 91 ComponentPointcut componentCut = (ComponentPointcut) attributes.remove("componentCut"); 92 if (componentCut == null && currentKey != null) { 93 componentCut = currentPico.getPointcutsFactory().component(currentKey); 94 } 95 96 if (interceptor != null || interceptorKey != null) { 97 registerInterceptor(currentPico, currentClassCut, componentCut, currentMethodCut, interceptor, interceptorKey); 98 } else if (mixinClass != null) { 99 registerMixin(currentPico, currentClassCut, componentCut, toClassArray(mixinInterfaces), mixinClass); 100 } else { 101 throw new NanoContainerMarkupException("No advice specified - must specify one of interceptor, interceptorKey, mixinClass, or mixinKey"); 102 } 103 104 return name; 105 } 106 107 108 private AspectsComponentAdapterFactory createAdapterFactory(AspectsApplicator aspectsApplicator, 109 ComponentAdapterFactory delegateAdapterFactory) { 110 if (delegateAdapterFactory != null) { 111 return new AspectsComponentAdapterFactory(aspectsApplicator, delegateAdapterFactory); 112 } else { 113 return new AspectsComponentAdapterFactory(aspectsApplicator); 114 } 115 } 116 117 private AspectablePicoContainer mixinAspectablePicoContainer(AspectsManager aspectsManager, 118 MutablePicoContainer pico) { 119 Aspects aspects = new Aspects(); 120 aspects.mixin(Pointcuts.ALL_CLASSES, new Class []{AspectsContainer.class}, new InstanceMixinFactory(aspectsManager)); 121 aspects.interfaces(Pointcuts.ALL_CLASSES, new Class []{AspectablePicoContainer.class}); 122 return (AspectablePicoContainer) ProxyFactory.getInstance(aspects).wrap(pico); 123 } 124 125 private void registerInterceptor(AspectablePicoContainer pico, ClassPointcut classCut, 126 ComponentPointcut componentCut, MethodPointcut methodCut, MethodInterceptor interceptor, 127 Object interceptorKey) { 128 if (interceptor == null && interceptorKey == null) { 130 throw new RuntimeException ("assertion failed -- non-null interceptor or interceptorKey expected"); 131 } 132 133 if (classCut == null && componentCut == null) { 135 throw new NanoContainerMarkupException("currentClassCut or componentCut required for interceptor advice"); 136 } 137 if (methodCut == null) { 138 throw new NanoContainerMarkupException("currentMethodCut required for interceptor advice"); 139 } 140 141 if (classCut != null) { 142 if (interceptor != null) { 143 pico.registerInterceptor(classCut, methodCut, interceptor); 144 } else { 145 pico.registerInterceptor(classCut, methodCut, interceptorKey); 146 } 147 } else { 148 if (interceptor != null) { 149 pico.registerInterceptor(componentCut, methodCut, interceptor); 150 } else { 151 pico.registerInterceptor(componentCut, methodCut, interceptorKey); 152 } 153 } 154 } 155 156 private void registerMixin(AspectablePicoContainer pico, ClassPointcut classCut, ComponentPointcut componentCut, 157 Class [] mixinInterfaces, Class mixinClass) { 158 if (mixinClass == null) { 160 throw new RuntimeException ("assertion failed -- mixinClass required"); 161 } 162 163 if (classCut == null && componentCut == null) { 165 throw new NanoContainerMarkupException("currentClassCut or componentCut required for mixin advice"); 166 } 167 168 if (classCut != null) { 169 if (mixinInterfaces != null) { 170 pico.registerMixin(classCut, mixinInterfaces, mixinClass); 171 } else { 172 pico.registerMixin(classCut, mixinClass); 173 } 174 } else { 175 if (mixinInterfaces != null) { 176 pico.registerMixin(componentCut, mixinInterfaces, mixinClass); 177 } else { 178 pico.registerMixin(componentCut, mixinClass); 179 } 180 } 181 } 182 183 private Class [] toClassArray(List l) { 184 if (l == null) { 185 return null; 186 } 187 return (Class []) l.toArray(new Class [l.size()]); 188 } 189 190 public void rememberComponentKey(Map attributes) { 191 Object key = attributes.get("key"); 192 Object clazz = attributes.get("class"); 193 if (key != null) { 194 currentKey = key; 195 } else { 196 currentKey = clazz; 197 } 198 } 199 } 200 | Popular Tags |