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 }