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.Pointcuts;
014    import dynaop.ProxyFactory;
015    import org.nanocontainer.aop.AspectablePicoContainer;
016    import org.nanocontainer.aop.AspectablePicoContainerFactory;
017    import org.nanocontainer.aop.AspectsContainer;
018    import org.nanocontainer.aop.AspectsManager;
019    import org.nanocontainer.aop.defaults.AspectsComponentAdapterFactory;
020    import org.picocontainer.MutablePicoContainer;
021    import org.picocontainer.PicoContainer;
022    import org.picocontainer.defaults.ComponentAdapterFactory;
023    import org.picocontainer.defaults.DefaultComponentAdapterFactory;
024    import org.picocontainer.defaults.DefaultPicoContainer;
025    
026    /**
027     * Uses dynaop to create <code>AspectablePicoContainer</code> objects.
028     *
029     * @author Stephen Molitor
030     * @author Mauro Talevi
031     * @version $Revision: 3144 $
032     */
033    public class DynaopAspectablePicoContainerFactory implements AspectablePicoContainerFactory {
034    
035        public AspectablePicoContainer createContainer(Class containerClass, AspectsManager aspectsManager,
036                                                       ComponentAdapterFactory componentAdapterFactory, PicoContainer parent) {
037    
038            ComponentAdapterFactory aspectsComponentAdapterFactory = new AspectsComponentAdapterFactory(aspectsManager,
039                    componentAdapterFactory);
040            MutablePicoContainer pico = createMutablePicoContainer(containerClass, aspectsComponentAdapterFactory, parent);
041            return mixinAspectablePicoContainer(aspectsManager, pico);
042        }
043    
044        public AspectablePicoContainer createContainer(Class containerClass,
045                                                       ComponentAdapterFactory componentAdapterFactory, PicoContainer parent) {
046            return createContainer(containerClass, new DynaopAspectsManager(), componentAdapterFactory, parent);
047        }
048    
049        public AspectablePicoContainer createContainer(ComponentAdapterFactory componentAdapterFactory, PicoContainer parent) {
050            return createContainer(DefaultPicoContainer.class, componentAdapterFactory, parent);
051        }
052    
053        public AspectablePicoContainer createContainer(ComponentAdapterFactory componentAdapterFactory) {
054            return createContainer(componentAdapterFactory, null);
055        }
056    
057        public AspectablePicoContainer createContainer(PicoContainer parent) {
058            return createContainer(new DefaultComponentAdapterFactory(), parent);
059        }
060    
061        public AspectablePicoContainer createContainer() {
062            return createContainer(new DefaultComponentAdapterFactory());
063        }
064    
065        public AspectablePicoContainer makeChildContainer(AspectsManager aspectsManager, AspectablePicoContainer parent) {
066            return mixinAspectablePicoContainer(aspectsManager, parent.makeChildContainer());
067        }
068    
069        public AspectablePicoContainer makeChildContainer(AspectablePicoContainer parent) {
070            return makeChildContainer(new DynaopAspectsManager(), parent);
071        }
072        
073        private MutablePicoContainer createMutablePicoContainer(Class containerClass, ComponentAdapterFactory caFactory,
074                                                          PicoContainer parent) {
075            MutablePicoContainer temp = new DefaultPicoContainer();
076            temp.registerComponentImplementation(containerClass);
077            temp.registerComponentInstance(ComponentAdapterFactory.class, caFactory);
078            if (parent != null) {
079                temp.registerComponentInstance(PicoContainer.class, parent);
080            }
081            return (MutablePicoContainer) temp.getComponentInstance(containerClass);
082        }
083    
084        private AspectablePicoContainer mixinAspectablePicoContainer(AspectsManager aspectsManager,
085                MutablePicoContainer pico) {
086            Aspects aspects = new Aspects();
087            aspects.mixin(Pointcuts.ALL_CLASSES, new Class[]{AspectsContainer.class}, new InstanceMixinFactory(aspectsManager));
088            aspects.interfaces(Pointcuts.ALL_CLASSES, new Class[]{AspectablePicoContainer.class});
089            return (AspectablePicoContainer) ProxyFactory.getInstance(aspects).wrap(pico);
090        }
091    
092    }