    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 Aslak Hellesoy and Paul Hammant   *
    009     *****************************************************************************/
    010    package org.picocontainer.injectors;
    011
    012    import org.picocontainer.ComponentAdapter;
    013    import org.picocontainer.ComponentMonitor;
    014    import org.picocontainer.LifecycleStrategy;
    015    import org.picocontainer.Parameter;
    016    import org.picocontainer.PicoCompositionException;
    017    import org.picocontainer.Characteristics;
    018    import org.picocontainer.behaviors.AbstractBehaviorFactory;
    019
    020    import java.util.Properties;
    021    import java.lang.reflect.Method;
    022
    023    /**
    024     * A {@link org.picocontainer.InjectionFactory} for methods.
    025     * The factory creates {@link MethodInjector}.
    026     *
    027     *  @author Paul Hammant
    028     */
    029    @SuppressWarnings("serial")
    030    public class MethodInjection extends AbstractInjectionFactory {
    031
    032        private final AbstractInjectionFactory delegate;
    033
    034        public MethodInjection(String injectionMethodName) {
    035            delegate = new MethodInjectionByName(injectionMethodName);
    036        }
    037
    038        public MethodInjection() {
    039            this("inject");
    040        }
    041
    042        public MethodInjection(Method injectionMethod) {
    043            delegate = new MethodInjectionByReflectionMethod(injectionMethod);
    044        }
    045
    046        public <T> ComponentAdapter<T> createComponentAdapter(ComponentMonitor componentMonitor, LifecycleStrategy lifecycleStrategy, Properties componentProperties, Object componentKey,
    047                                                       Class<T> componentImplementation, Parameter... parameters) throws PicoCompositionException {
    048            return delegate.createComponentAdapter(componentMonitor, lifecycleStrategy, componentProperties, componentKey, componentImplementation, parameters);
    049        }
    050
    051        public class MethodInjectionByName extends AbstractInjectionFactory {
    052            private final String injectionMethodName;
    053
    054            public MethodInjectionByName(String injectionMethodName) {
    055                this.injectionMethodName = injectionMethodName;
    056            }
    057
    058            public <T> ComponentAdapter<T> createComponentAdapter(ComponentMonitor componentMonitor, LifecycleStrategy lifecycleStrategy, Properties componentProperties, Object componentKey, Class<T> componentImplementation, Parameter... parameters) throws PicoCompositionException {
    059                boolean useNames = AbstractBehaviorFactory.arePropertiesPresent(componentProperties, Characteristics.USE_NAMES, true);
    060                return new MethodInjector(componentKey, componentImplementation, parameters, componentMonitor, lifecycleStrategy, injectionMethodName, useNames);
    061            }
    062        }
    063
    064        public class MethodInjectionByReflectionMethod extends AbstractInjectionFactory {
    065            private final Method injectionMethod;
    066
    067            public MethodInjectionByReflectionMethod(Method injectionMethod) {
    068                this.injectionMethod = injectionMethod;
    069            }
    070
    071            public <T> ComponentAdapter<T> createComponentAdapter(ComponentMonitor componentMonitor, LifecycleStrategy lifecycleStrategy, Properties componentProperties, Object componentKey, Class<T> componentImplementation, Parameter... parameters) throws PicoCompositionException {
    072                boolean useNames = AbstractBehaviorFactory.arePropertiesPresent(componentProperties, Characteristics.USE_NAMES, true);
    073                if (injectionMethod.getDeclaringClass().isAssignableFrom(componentImplementation)) {
    074                    return componentMonitor.newInjector(new MethodInjector.ByReflectionMethod(componentKey, componentImplementation, parameters, componentMonitor, lifecycleStrategy, injectionMethod, useNames));
    075                } else {
    076                    throw new PicoCompositionException("method [" + injectionMethod + "] not on impl " + componentImplementation.getName());
    077                }
    078            }
    079        }
    080
    081    }