    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    }