[picocontainer-scm] [5564] java/2.x/trunk/pico/container/src/test/org/picocontainer: start of emjection

paul-yCVjj/[email protected]
Newsgroups gmane.comp.java.picocontainer.cvs
Message-ID <[email protected]>
Revision 5564
Author paul
Date 2009-11-30 13:23:36 -0600 (Mon, 30 Nov 2009)

Log Message

start of emjection

Modified Paths

- java/2.x/trunk/pico/container/src/java/org/picocontainer/Characteristics.java

- java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/ConstructorInjection.java

- java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/ConstructorInjector.java

- java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/Reinjector.java

- java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/AdaptingInjectionTestCase.java

- java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/ReinjectionTestCase.java

Added Paths

- java/2.x/trunk/pico/container/src/java/org/picocontainer/Emjection.java

- java/2.x/trunk/pico/container/src/test/org/picocontainer/foo/

- java/2.x/trunk/pico/container/src/test/org/picocontainer/foo/EmjectionTestCase.java

Diff

Modified: java/2.x/trunk/pico/container/src/java/org/picocontainer/Characteristics.java (5563 => 5564)

--- java/2.x/trunk/pico/container/src/java/org/picocontainer/Characteristics.java 2009-11-04 01:13:42 UTC (rev 5563)
+++ java/2.x/trunk/pico/container/src/java/org/picocontainer/Characteristics.java 2009-11-30 19:23:36 UTC (rev 5564)
@@ -38,6 +38,7 @@
private static final String _USE_NAMES = "use-parameter-names";
private static final String _ENABLE_CIRCULAR = "enable-circular";
private static final String _GUARD = "guard";
+ private static final String _EMJECTION = "emjection_enabled";

/**
* Since properties use strings, we supply String constants for Boolean conditions.
@@ -152,6 +153,8 @@

public static final Properties USE_NAMES = immutable(_USE_NAMES, TRUE);

+ public static final Properties EMJECTION_ENABLED = immutable(_EMJECTION, TRUE);
+
public static final Properties GUARD = immutable(_GUARD, "guard");

public static final Properties GUARD(String with) {

Added: java/2.x/trunk/pico/container/src/java/org/picocontainer/Emjection.java (0 => 5564)

--- java/2.x/trunk/pico/container/src/java/org/picocontainer/Emjection.java (rev 0)
+++ java/2.x/trunk/pico/container/src/java/org/picocontainer/Emjection.java 2009-11-30 19:23:36 UTC (rev 5564)
@@ -0,0 +1,55 @@
+package org.picocontainer;
+
+import org.picocontainer.containers.ImmutablePicoContainer;
+import org.picocontainer.containers.TransientPicoContainer;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+
+public class Emjection {
+
+ private PicoContainer pico;
+
+ public void setPico(ImmutablePicoContainer container) {
+ if (pico != null) {
+ throw new PicoCompositionException("Emjection can only be setup once per component");
+ }
+ pico = container;
+ }
+
+ public static <T> T neu(Class<T> type, Emjection emjection, Object... args) {
+ if (emjection.pico == null) {
+ throw new PicoCompositionException("blah");
+ }
+ TransientPicoContainer tpc = new TransientPicoContainer(emjection.pico);
+ for (Object arg : args) {
+ tpc.addComponent(arg);
+ }
+ T inst = tpc.getComponent(type);
+ if (inst == null) {
+ tpc.addComponent(type);
+ inst = tpc.getComponent(type);
+ }
+ setPico(inst, tpc);
+ return inst;
+ }
+
+ private static <T> void setPico(Object inst, PicoContainer container) {
+ try {
+ Field field = inst.getClass().getDeclaredField("emjection");
+ field.setAccessible(true);
+ Emjection e2 = (Emjection) field.get(inst);
+ e2.setPico(new ImmutablePicoContainer(container));
+ } catch (NoSuchFieldException e) {
+ throw new PicoCompositionException("Components created via emjection have to have a field 'private Emjection emjection'. " + inst.getClass() + " is missing that field");
+ } catch (IllegalAccessException e) {
+ throw new PicoCompositionException("unable to access field called emjection on " + inst.getClass());
+ }
+ }
+
+ public static void setupEmjection(Object inst, PicoContainer container) {
+ setPico(inst, container);
+ }
+
+
+}

Modified: java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/ConstructorInjection.java (5563 => 5564)

--- java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/ConstructorInjection.java 2009-11-04 01:13:42 UTC (rev 5563)
+++ java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/ConstructorInjection.java 2009-11-30 19:23:36 UTC (rev 5564)
@@ -56,6 +56,8 @@
public <T> ComponentAdapter<T> createComponentAdapter(ComponentMonitor componentMonitor, LifecycleStrategy lifecycleStrategy, Properties properties, Object componentKey,
Class<T> componentImplementation, Parameter... parameters) throws PicoCompositionException {
boolean useNames = AbstractBehaviorFactory.arePropertiesPresent(properties, Characteristics.USE_NAMES, true);
- return componentMonitor.newInjector(new ConstructorInjector(componentKey, componentImplementation, parameters, componentMonitor, lifecycleStrategy, useNames, rememberChosenConstructor));
+ ConstructorInjector injector = new ConstructorInjector(componentKey, componentImplementation, parameters, componentMonitor, lifecycleStrategy, useNames, rememberChosenConstructor);
+ injector.enableEmjection(AbstractBehaviorFactory.removePropertiesIfPresent(properties, Characteristics.EMJECTION_ENABLED));
+ return componentMonitor.newInjector(injector);
}
}

Modified: java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/ConstructorInjector.java (5563 => 5564)

--- java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/ConstructorInjector.java 2009-11-04 01:13:42 UTC (rev 5563)
+++ java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/ConstructorInjector.java 2009-11-30 19:23:36 UTC (rev 5564)
@@ -10,21 +10,12 @@

package org.picocontainer.injectors;

-import org.picocontainer.ComponentMonitor;
-import org.picocontainer.LifecycleStrategy;
-import org.picocontainer.Parameter;
-import org.picocontainer.PicoCompositionException;
-import org.picocontainer.PicoContainer;
-import org.picocontainer.ComponentAdapter;
-import org.picocontainer.NameBinding;
+import org.picocontainer.*;
+import org.picocontainer.containers.ImmutablePicoContainer;
import org.picocontainer.lifecycle.NullLifecycleStrategy;
import org.picocontainer.monitors.NullComponentMonitor;

-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
+import java.lang.reflect.*;
import java.lang.annotation.Annotation;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -55,6 +46,7 @@
private transient ThreadLocalCyclicDependencyGuard<T> instantiationGuard;
private boolean rememberChosenConstructor = true;
private transient CtorAndAdapters<T> chosenConstructor;
+ private boolean enableEmjection = false;

/**
* Constructor injector that uses no monitor and no lifecycle adapter. This is a more
@@ -199,6 +191,10 @@
return new CtorAndAdapters<T>(greediestConstructor, greediestConstructorsParameters, greediestConstructorsParametersComponentAdapters);
}

+ public void enableEmjection(boolean enableEmjection) {
+ this.enableEmjection = enableEmjection;
+ }
+
private static final class ResolverKey {
private final Type expectedType;
private final String pName;
@@ -336,9 +332,17 @@
};
}
instantiationGuard.setGuardedContainer(container);
- return instantiationGuard.observe(getComponentImplementation());
+ T inst = instantiationGuard.observe(getComponentImplementation());
+ decorate(inst, container);
+ return inst;
}

+ private void decorate(T inst, PicoContainer container) {
+ if (enableEmjection) {
+ Emjection.setupEmjection(inst, container);
+ }
+ }
+
private List<Constructor<T>> getSortedMatchingConstructors() {
List<Constructor<T>> matchingConstructors = new ArrayList<Constructor<T>>();
Constructor<T>[] allConstructors = getConstructors();

Modified: java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/Reinjector.java (5563 => 5564)

--- java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/Reinjector.java 2009-11-04 01:13:42 UTC (rev 5563)
+++ java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/Reinjector.java 2009-11-30 19:23:36 UTC (rev 5564)
@@ -8,14 +8,14 @@
*****************************************************************************/
package org.picocontainer.injectors;

-import org.picocontainer.PicoContainer;
-import org.picocontainer.ComponentMonitor;
-import org.picocontainer.ComponentMonitorStrategy;
-import org.picocontainer.InjectionFactory;
+import org.picocontainer.*;
import org.picocontainer.lifecycle.NullLifecycleStrategy;
import org.picocontainer.monitors.NullComponentMonitor;

+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Properties;

/**
@@ -62,6 +62,37 @@

/**
* Reinjecting into a method.
+ * @param key the component-key from the parent set of components to inject into
+ * @param reinjectionMethodEnum the enum for the reflection method to use for injection.
+ * @return the result of the reinjection-method invocation.
+ */
+ public Object reinject(Class<?> key, Enum reinjectionMethodEnum) {
+ return reinject(key, key, parent.getComponent(key), NO_PROPERTIES, new MethodInjection(toMethod(reinjectionMethodEnum)));
+ }
+
+ private Method toMethod(final Enum reinjectionMethodEnum) {
+ Object methodOrException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ try {
+ return reinjectionMethodEnum.getClass().getMethod("toMethod").invoke(reinjectionMethodEnum);
+ } catch (IllegalAccessException e) {
+ return new PicoCompositionException("Illegal access to " + reinjectionMethodEnum.name());
+ } catch (InvocationTargetException e) {
+ return new PicoCompositionException("Invocation Target Exception " + reinjectionMethodEnum.name(), e.getCause());
+ } catch (NoSuchMethodException e) {
+ return new PicoCompositionException("Expected generated method toMethod() on enum");
+ }
+ }
+ });
+ if (methodOrException instanceof Method) {
+ return (Method) methodOrException;
+ } else {
+ throw (PicoCompositionException) methodOrException;
+ }
+ }
+
+ /**
+ * Reinjecting into a method.
* @param key the component-key from the parent set of components to inject into (key and impl are the same)
* @param reinjectionFactory the InjectionFactory to use for reinjection.
* @return the result of the reinjection-method invocation.
@@ -74,7 +105,7 @@
/**
* Reinjecting into a method.
* @param key the component-key from the parent set of components to inject into
- * @param implementation the implementation of the component that is going to result.
+ * @param impl the implementation of the component that is going to result.
* @param reinjectionFactory the InjectionFactory to use for reinjection.
* @return
*/

Added: java/2.x/trunk/pico/container/src/test/org/picocontainer/foo/EmjectionTestCase.java (0 => 5564)

--- java/2.x/trunk/pico/container/src/test/org/picocontainer/foo/EmjectionTestCase.java (rev 0)
+++ java/2.x/trunk/pico/container/src/test/org/picocontainer/foo/EmjectionTestCase.java 2009-11-30 19:23:36 UTC (rev 5564)
@@ -0,0 +1,70 @@
+package org.picocontainer.foo;
+
+import org.junit.Test;
+import org.picocontainer.Characteristics;
+import org.picocontainer.DefaultPicoContainer;
+import org.picocontainer.Emjection;
+import org.picocontainer.MutablePicoContainer;
+
+import static junit.framework.Assert.assertEquals;
+
+public class EmjectionTestCase {
+
+ @Test
+ public void basicEmjection() {
+
+ StringBuilder sb = new StringBuilder();
+ MutablePicoContainer pico = new DefaultPicoContainer();
+ pico.addComponent(Antelope.class);
+ pico.as(Characteristics.EMJECTION_ENABLED).addComponent(ZooKeeper.class);
+ pico.addComponent(sb);
+ ZooKeeper zooKeeper = pico.getComponent(ZooKeeper.class);
+ zooKeeper.doHeadCount();
+
+ assertEquals("giraffe=true, antelope=true", sb.toString());
+
+ }
+
+
+ public static class Zoo {
+ private final Emjection emjection = new Emjection();
+
+ private Giraffe giraffe;
+ private Antelope antelope;
+ private StringBuilder sb;
+
+ public Zoo(Giraffe giraffe, Antelope antelope, StringBuilder sb) {
+ this.giraffe = giraffe;
+ this.antelope = antelope;
+ this.sb = sb;
+ }
+
+ public void headCount() {
+ sb.append("giraffe=").append(giraffe != null);
+ sb.append(", antelope=").append(antelope != null);
+ }
+ }
+
+
+ public static class ZooKeeper {
+
+ private final Emjection emjection = new Emjection();
+
+ public void doHeadCount() {
+ Zoo zoo = neu(Zoo.class, this, new Giraffe());
+ zoo.headCount();
+ }
+
+ <T> T neu(Class<T> type, Object... args) {
+ return Emjection.neu(type, emjection, args);
+ }
+
+ }
+
+ public static class Giraffe {
+ }
+ public static class Antelope {
+ }
+
+
+}

Modified: java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/AdaptingInjectionTestCase.java (5563 => 5564)

--- java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/AdaptingInjectionTestCase.java 2009-11-04 01:13:42 UTC (rev 5563)
+++ java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/AdaptingInjectionTestCase.java 2009-11-30 19:23:36 UTC (rev 5564)
@@ -125,6 +125,7 @@
" <lifecycleStrategy class=RLS/>\n" +
" <useNames>false</useNames>\n" +
" <rememberChosenConstructor>true</rememberChosenConstructor>\n" +
+ " <enableEmjection>false</enableEmjection>\n" +
"</Constructor-Injection>", foo);

Modified: java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/ReinjectionTestCase.java (5563 => 5564)

--- java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/ReinjectionTestCase.java 2009-11-04 01:13:42 UTC (rev 5563)
+++ java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/ReinjectionTestCase.java 2009-11-30 19:23:36 UTC (rev 5564)
@@ -77,6 +77,21 @@
public Object getString() {
return string;
}
+ public static enum M {
+ doIt("doIt", String.class);
+ private Method method;
+
+ M(String s, Class... paramTypes) {
+ try {
+ method = NeedsShoe.class.getMethod(s, paramTypes);
+ } catch (NoSuchMethodException e) {
+ throw new UnsupportedOperationException(e);
+ }
+ }
+ public Method toMethod() {
+ return method;
+ }
+ }
}

public static class Shoe {
@@ -228,12 +243,26 @@
final ComponentMonitor cm = new NullComponentMonitor();
Reinjector reinjector = new Reinjector(parent, cm);

- int result = (Integer) reinjector.reinject(NeedsShoe.class, DOIT_METHOD);
+ //int result = (Integer) reinjector.reinject(NeedsShoe.class, DOIT_METHOD);
assertEquals(6, (int) (Integer) reinjector.reinject(NeedsShoe.class, DOIT_METHOD));
assertEquals(6, (int) (Integer) reinjector.reinject(NeedsShoe.class, new MethodInjection(DOIT_METHOD)));

}

+ @Test public void testOverloadedReinjectMethodsAreIdentical2() {
+ final DefaultPicoContainer parent = new DefaultPicoContainer(new Caching().wrap(new ConstructorInjection()));
+ parent.addComponent(INeedsShoe.class, NeedsShoe.class);
+ parent.addComponent(Shoe.class);
+ parent.addComponent("12");
+
+ final ComponentMonitor cm = new NullComponentMonitor();
+ Reinjector reinjector = new Reinjector(parent, cm);
+
+ assertEquals(6, (int) (Integer) reinjector.reinject(NeedsShoe.class, NeedsShoe.M.doIt));
+ assertEquals(6, (int) (Integer) reinjector.reinject(NeedsShoe.class, new MethodInjection(DOIT_METHOD)));
+
+ }
+
@Test public void testReinjectorCanBeOverridenByComponentMonitor() {
final DefaultPicoContainer parent = new DefaultPicoContainer(new Caching().wrap(new ConstructorInjection()));
parent.addComponent(INeedsShoe.class, NeedsShoe.class);
@@ -247,7 +276,6 @@
};
Reinjector reinjector = new Reinjector(parent, cm);

- int result = (Integer) reinjector.reinject(NeedsShoe.class, DOIT_METHOD);
assertEquals(4444, (int) (Integer) reinjector.reinject(NeedsShoe.class, DOIT_METHOD));

}
@@ -265,7 +293,6 @@
};
Reinjector reinjector = new Reinjector(parent, cm);

- int result = (Integer) reinjector.reinject(NeedsShoe.class, DOIT_METHOD);
assertEquals(6, (int) (Integer) reinjector.reinject(NeedsShoe.class, DOIT_METHOD));

}

----------

To unsubscribe from this list please visit:

http://xircles.codehaus.org/manage_email
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.