    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     *****************************************************************************/
    009    package org.picocontainer.injectors;
    010
    011    import org.picocontainer.PicoContainer;
    012    import org.picocontainer.ComponentMonitor;
    013    import org.picocontainer.ComponentMonitorStrategy;
    014    import org.picocontainer.InjectionFactory;
    015    import org.picocontainer.lifecycle.NullLifecycleStrategy;
    016    import org.picocontainer.monitors.NullComponentMonitor;
    017
    018    import java.lang.reflect.Method;
    019    import java.util.Properties;
    020
    021    /**
    022     * A Reinjector allows methods on pre-instantiated classes to be invoked,
    023     * with appropriately scoped parameters.
    024     */
    025    public class Reinjector {
    026
    027        private final PicoContainer parent;
    028        private final ComponentMonitor monitor;
    029        private static NullLifecycleStrategy NO_LIFECYCLE = new NullLifecycleStrategy();
    030        private static Properties NO_PROPERTIES = new Properties();
    031
    032        /**
    033         * Make a reinjector with a parent container from which to pull components to be reinjected to.
    034         * With this constructor, a NullComponentMonitor is used.
    035         * @param parentContainer the parent container
    036         */
    037        public Reinjector(PicoContainer parentContainer) {
    038            this(parentContainer, parentContainer instanceof ComponentMonitorStrategy
    039                    ? ((ComponentMonitorStrategy) parentContainer).currentMonitor()
    040                    : new NullComponentMonitor());
    041        }
    042
    043        /**
    044         * Make a reinjector with a parent container from which to pull components to be reinjected to
    045         * @param parentContainer the parent container
    046         * @param monitor the monitor to use for 'instantiating' events
    047         */
    048        public Reinjector(PicoContainer parentContainer, ComponentMonitor monitor) {
    049            this.parent = parentContainer;
    050            this.monitor = monitor;
    051        }
    052
    053        /**
    054         * Reinjecting into a method.
    055         * @param key the component-key from the parent set of components to inject into
    056         * @param reinjectionMethod the reflection method to use for injection.
    057         * @return the result of the reinjection-method invocation.
    058         */
    059        public Object reinject(Class<?> key, Method reinjectionMethod) {
    060            return reinject(key, key, parent.getComponent(key), NO_PROPERTIES, new MethodInjection(reinjectionMethod));
    061        }
    062
    063        /**
    064         * Reinjecting into a method.
    065         * @param key the component-key from the parent set of components to inject into (key and impl are the same)
    066         * @param reinjectionFactory the InjectionFactory to use for reinjection.
    067         * @return the result of the reinjection-method invocation.
    068         */
    069        public Object reinject(Class<?> key, InjectionFactory reinjectionFactory) {
    070            Object o = reinject(key, key, parent.getComponent(key), NO_PROPERTIES, reinjectionFactory);
    071            return o;
    072        }
    073
    074        /**
    075         * Reinjecting into a method.
    076         * @param key the component-key from the parent set of components to inject into
    077         * @param implementation the implementation of the component that is going to result.
    078         * @param reinjectionFactory the InjectionFactory to use for reinjection.
    079         * @return
    080         */
    081        public Object reinject(Class<?> key, Class<?> impl, InjectionFactory reinjectionFactory) {
    082            return reinject(key, impl, parent.getComponent(key), NO_PROPERTIES, reinjectionFactory);
    083        }
    084
    085        /**
    086         * Reinjecting into a method.
    087         * @param key the component-key from the parent set of components to inject into
    088         * @param implementation the implementation of the component that is going to result.
    089         * @param instance the object that has the provider method to be invoked
    090         * @param reinjectionFactory the InjectionFactory to use for reinjection.
    091         * @return the result of the reinjection-method invocation.
    092         */
    093        public Object reinject(Class<?> key, Class implementation, Object instance, InjectionFactory reinjectionFactory) {
    094            return reinject(key, implementation, instance, NO_PROPERTIES, reinjectionFactory);
    095        }
    096
    097        /**
    098         * Reinjecting into a method.
    099         * @param key the component-key from the parent set of components to inject into
    100         * @param implementation the implementation of the component that is going to result.
    101         * @param instance the object that has the provider method to be invoked
    102         * @param properties for reinjection
    103         * @param reinjectionFactory the InjectionFactory to use for reinjection.
    104         * @return the result of the reinjection-method invocation.
    105         */
    106        public Object reinject(Class<?> key, Class implementation, Object instance, Properties properties,
    107                               InjectionFactory reinjectionFactory) {
    108            Reinjection reinjection = new Reinjection(reinjectionFactory, parent);
    109            org.picocontainer.Injector injector = (org.picocontainer.Injector) reinjection.createComponentAdapter(
    110                    monitor, NO_LIFECYCLE, properties, key, implementation, null);
    111            return injector.decorateComponentInstance(parent, null, instance);
    112        }
    113
    114    }