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 }