You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by jo...@apache.org on 2014/11/04 14:05:38 UTC

svn commit: r1636573 [2/2] - in /commons/sandbox/commons-inject/trunk: ./ .settings/ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/commons/ src/main/java/org/apache/commons/inject/ src/main/java/org...

Added: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/Introspector.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/Introspector.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/Introspector.java (added)
+++ commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/Introspector.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,184 @@
+package org.apache.commons.inject.impl;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+
+import org.apache.commons.inject.api.IBinding;
+import org.apache.commons.inject.api.IInjector;
+import org.apache.commons.inject.api.IKey;
+import org.apache.commons.inject.api.IPoint;
+import org.apache.commons.inject.api.IProvider;
+import org.apache.commons.inject.api.Key;
+import org.apache.commons.inject.impl.bind.DefaultBinding;
+import org.apache.commons.inject.util.Generics;
+
+public class Introspector {
+	private static final Introspector introspector = new Introspector();
+	private static final Class<Object> PROVIDER_CLASS = Generics.cast(Provider.class);
+
+	// Private constructor, to avoid accidental instantiation.
+	private Introspector() {
+	}
+
+	public static Introspector getInstance() {
+		return introspector;
+	}
+
+	public <T> AbstractBaseProvider<T> getProvider(Class<T> pType, IPoint<T> pPoint, IMutableBindingSource pBindings) {
+		@SuppressWarnings("unchecked")
+		final Constructor<T>[] constructors = (Constructor<T>[]) pType.getDeclaredConstructors();
+		for (Constructor<T> constructor : constructors) {
+			if (constructor.isAnnotationPresent(Inject.class)) {
+				return getProvider(constructor, pBindings);
+			}
+		}
+		return new DefaultProvider<T>(pType, pPoint);
+	}
+
+	public <T> AbstractBaseProvider<T> getProvider(Constructor<? extends T> pConstructor, IMutableBindingSource pBindings) {
+		@SuppressWarnings("unchecked")
+		final Class<Object>[] parameterClasses = (Class<Object>[]) pConstructor.getParameterTypes();
+		final Type[] parameterTypes = pConstructor.getGenericParameterTypes();
+		final Annotation[][] parameterAnnotations = pConstructor.getParameterAnnotations();
+		final IBinding<Object>[] parameterBindings = getBindings(parameterClasses, parameterTypes,
+				parameterAnnotations, pBindings,
+				"Required to invoke the constructor " + pConstructor);
+		@SuppressWarnings("unchecked")
+		final Constructor<T> constructor = (Constructor<T>) pConstructor;
+		return new FactoryMethodProvider<T>(constructor,
+											getPoint(constructor.getDeclaringClass(), pBindings),
+											parameterBindings);
+	}
+
+	public <T> AbstractBaseProvider<T> getProvider(Method pMethod, IMutableBindingSource pBindings) {
+		@SuppressWarnings("unchecked")
+		final Class<Object>[] parameterClasses = (Class<Object>[]) pMethod.getParameterTypes();
+		final Type[] parameterTypes = pMethod.getGenericParameterTypes();
+		final Annotation[][] parameterAnnotations = pMethod.getParameterAnnotations();
+		final IBinding<Object>[] parameterBindings = getBindings(parameterClasses, parameterTypes, parameterAnnotations, pBindings,
+			"Required to invoke the method " + pMethod);
+		@SuppressWarnings("unchecked")
+		final Class<T> cl = (Class<T>) pMethod.getReturnType();
+		final IPoint<T> point = getPoint(cl, pBindings);
+		return new FactoryMethodProvider<T>(pMethod, parameterBindings, point);
+	}
+
+	private IBinding<Object>[] getBindings(Class<Object>[] pParameterClasses, Type[] pParameterTypes, Annotation[][] pParameterAnnotations, IMutableBindingSource pBindings,
+			String pCause) {
+		@SuppressWarnings("unchecked")
+		final IBinding<Object>[] bindings = (IBinding<Object>[]) Array.newInstance(IBinding.class, pParameterTypes.length);
+		for (int i = 0;  i < bindings.length;  i++) {
+			final Class<Object> cl = pParameterClasses[i];
+			final Annotation[] annotations = pParameterAnnotations[i];
+			bindings[i] = getBinding(cl, pParameterTypes[i], annotations, pBindings, pCause);
+		}
+		return bindings;
+	}
+
+	private IBinding<Object> getBinding(Class<Object> pClass, Type pType, Annotation[] pAnnotations, IMutableBindingSource pBindings, String pCause) {
+		String name = Key.NO_NAME;
+		for (Annotation annotation : pAnnotations) {
+			if (annotation instanceof Named) {
+				name = ((Named) annotation).value();
+				break;
+			}
+		}
+		if (pClass == PROVIDER_CLASS  &&  pType != null  &&  pType instanceof ParameterizedType) {
+			final ParameterizedType ptype = (ParameterizedType) pType;
+			final Type[] typeArgs = ptype.getActualTypeArguments();
+			if (typeArgs != null  &&  typeArgs.length == 1) {
+				final Type typeArg = typeArgs[0];
+				if (typeArg instanceof Class<?>) {
+					@SuppressWarnings("unchecked")
+					final Class<Object> cl = (Class<Object>) typeArg;
+					final IKey<Object> key = new Key<Object>(cl, name);
+					final IBinding<Object> binding1 = pBindings.requireBinding(key, pCause);
+					final IProvider<Object> provider = new IProvider<Object>(){
+						@Override
+						public Object get() {
+							return new Provider<Object>(){
+								@Override
+								public Object get() {
+									return binding1.getProvider().get();
+								}
+							};
+						}
+
+						@Override
+						public Class<? extends Object> getType() {
+							return Provider.class;
+						}
+
+						@Override
+						public Object get(IInjector pInjector) {
+							return get();
+						}
+					};
+					final IPoint<Object> point = new IPoint<Object>(){
+						@Override
+						public void injectTo(Object pInstance,
+								IInjector pInjector) {
+							// Does nothing.
+						}
+					};
+					final IBinding<Object> binding2 = new DefaultBinding<Object>(provider, point);
+					return binding2;
+				}
+			}
+		}
+		final IKey<Object> key = new Key<Object>(pClass, name);
+		return pBindings.requireBinding(key, pCause);
+	}
+
+	public <T> ListPoint<T> getPoint(Class<T> pType, IMutableBindingSource pBindings) {
+		final List<IPoint<T>> points = new ArrayList<IPoint<T>>();
+		final Field[] fields = pType.getDeclaredFields();
+		for (final Field f : fields) {
+			if (Modifier.isStatic(f.getModifiers())) {
+				continue;
+			}
+			if (!f.isAnnotationPresent(Inject.class)) {
+				continue;
+			}
+			@SuppressWarnings("unchecked")
+			Class<Object> type = (Class<Object>) f.getType();
+			Type genericType = f.getGenericType();
+			IBinding<Object> binding = null;
+			Annotation[] annotations = f.getAnnotations();
+			binding = getBinding(type, genericType, annotations, pBindings,
+					"Required to inject to an instance of " + pType.getName());
+			final IPoint<T> point = new FieldPoint<T>(binding, f);
+			points.add(point);
+		}
+		final Method[] methods = pType.getDeclaredMethods();
+		for (final Method m : methods) {
+			if (Modifier.isStatic(m.getModifiers())) {
+				continue;
+			}
+			if (!m.isAnnotationPresent(Inject.class)) {
+				continue;
+			}
+			@SuppressWarnings("unchecked")
+			Class<Object>[] parameterClasses = (Class<Object>[]) m.getParameterTypes();
+			Type[] parameterTypes = m.getGenericParameterTypes();
+			Annotation[][] annotations = m.getParameterAnnotations();
+			final IBinding<Object>[] bindings = getBindings(parameterClasses, parameterTypes, annotations, pBindings,
+					"Required to inject to an instance of " + pType.getName());
+			final IPoint<T> point = new MethodPoint<T>(bindings, m);
+			points.add(point);
+		}
+		return new ListPoint<T>(points);
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/Introspector.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/ListPoint.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/ListPoint.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/ListPoint.java (added)
+++ commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/ListPoint.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,27 @@
+package org.apache.commons.inject.impl;
+
+import java.util.List;
+
+import org.apache.commons.inject.api.IInjector;
+import org.apache.commons.inject.api.IPoint;
+
+public class ListPoint<T> implements IPoint<T> {
+	private final List<IPoint<T>> list;
+	
+	public ListPoint(List<IPoint<T>> pPoints) {
+		list = pPoints;
+	}
+
+
+	public void add(IPoint<T> pPoint) {
+		list.add(pPoint);
+	}
+
+	@Override
+	public void injectTo(T pInstance, IInjector pInjector) {
+		for (IPoint<T> point : list) {
+			point.injectTo(pInstance, pInjector);
+		}
+	}
+
+}

Propchange: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/ListPoint.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/MethodPoint.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/MethodPoint.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/MethodPoint.java (added)
+++ commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/MethodPoint.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,34 @@
+package org.apache.commons.inject.impl;
+
+import java.lang.reflect.Method;
+
+import org.apache.commons.inject.api.IBinding;
+import org.apache.commons.inject.api.IInjector;
+import org.apache.commons.inject.api.IPoint;
+import org.apache.commons.inject.util.Exceptions;
+
+public class MethodPoint<T> implements IPoint<T> {
+	private final IBinding<Object>[] bindings;
+	private final Method method;
+
+	public MethodPoint(IBinding<Object>[] pBindings, Method pMethod) {
+		bindings = pBindings;
+		method = pMethod;
+	}
+
+	@Override
+	public void injectTo(T pInstance, IInjector pInjector) {
+		try {
+			final Object[] args = new Object[bindings.length];
+			for (int i = 0;  i < args.length;  i++) {
+				args[i] = bindings[i].getProvider().get();
+			}
+			if (!method.isAccessible()) {
+				method.setAccessible(true);
+			}
+			method.invoke(pInstance, args);
+		} catch (Throwable t) {
+			throw Exceptions.show(t);
+		}
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/MethodPoint.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/MutableBindingSet.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/MutableBindingSet.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/MutableBindingSet.java (added)
+++ commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/MutableBindingSet.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,36 @@
+package org.apache.commons.inject.impl;
+
+import java.util.List;
+
+import org.apache.commons.inject.api.IBinding;
+import org.apache.commons.inject.api.IKey;
+
+
+public class MutableBindingSet extends AbstractBindingSet implements IMutableBindingSource {
+	public MutableBindingSet() {
+		super();
+	}
+
+	public <T> void add(MappedKey<T> pKey, IBinding<T> pBinding) {
+		final ReducedKey<T> rkey = newReducedKey(pKey);
+		final List<BindingAndKey<?>> list = findOrCreateList(rkey);
+		list.add(new BindingAndKey<T>(pBinding, pKey));
+	}
+
+	@Override
+	public <T> IBinding<T> requireBinding(IKey<T> pKey, String pCause) {
+		final MappedKey<T> mkey = new MappedKey<T>(pKey.getType(), pKey.getName(), pKey.getAnnotations(), null);
+		final ReducedKey<T> rkey = newReducedKey(pKey);
+		final List<BindingAndKey<?>> list = findOrCreateList(rkey);
+		for (BindingAndKey<?> bak : list) {
+			if (isMatching(pKey, bak.getKey())) {
+				@SuppressWarnings("unchecked")
+				final IBinding<T> binding = (IBinding<T>) bak.getBinding();
+				return binding;
+			}
+		}
+		final IBinding<T> binding = new BindingProxy<T>(pCause);
+		list.add(new BindingAndKey<T>(binding, mkey));
+		return binding;
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/MutableBindingSet.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/ResolvableBindingSet.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/ResolvableBindingSet.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/ResolvableBindingSet.java (added)
+++ commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/ResolvableBindingSet.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,48 @@
+package org.apache.commons.inject.impl;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.inject.api.IBinding;
+import org.apache.commons.inject.api.Key;
+import org.apache.commons.inject.api.NoSuchBindingException;
+
+public class ResolvableBindingSet extends AbstractBindingSet {
+	public ResolvableBindingSet(MutableBindingSet pMutableBindings) {
+		super(pMutableBindings.map);
+	}
+
+	public void resolve() {
+		for (Map.Entry<ReducedKey<?>, List<BindingAndKey<?>>> en : map.entrySet()) {
+			List<BindingAndKey<?>> list = en.getValue();
+			for (BindingAndKey<?> bak : list) {
+				final IBinding<?> binding = bak.getBinding();
+				if (binding instanceof BindingProxy) {
+					@SuppressWarnings("unchecked")
+					final BindingProxy<Object> bnd = (BindingProxy<Object>) binding;
+					@SuppressWarnings("unchecked")
+					final IBinding<Object> realBinding = (IBinding<Object>) findRealBinding(list, bak.getKey());
+					if (realBinding == null) {
+						throw new NoSuchBindingException("No Binding has been registered for key "
+								+ Key.toString(bak.getKey()) + ". " + ((BindingProxy<?>) binding).getCause());
+					}
+					bnd.setBinding(realBinding);
+				}
+			}
+		}
+	}
+
+	private IBinding<?> findRealBinding(List<BindingAndKey<?>> pList,
+			MappedKey<?> pKey) {
+		for (BindingAndKey<?> bak : pList) {
+			if (bak.getKey() == pKey) {
+				continue;
+			}
+			if (!isMatching(bak.getKey(), pKey)) {
+				continue;
+			}
+			return bak.getBinding();
+		}
+		return null;
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/ResolvableBindingSet.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/DefaultBinding.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/DefaultBinding.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/DefaultBinding.java (added)
+++ commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/DefaultBinding.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,39 @@
+package org.apache.commons.inject.impl.bind;
+
+import org.apache.commons.inject.api.IBinding;
+import org.apache.commons.inject.api.IInjector;
+import org.apache.commons.inject.api.IPoint;
+import org.apache.commons.inject.api.IProvider;
+import org.apache.commons.inject.impl.IInjectorAware;
+
+public class DefaultBinding<T> implements IBinding<T>, IInjectorAware {
+	private final IProvider<T> provider;
+	private final IPoint<T> point;
+	
+	public DefaultBinding(IProvider<T> pProvider, IPoint<T> pPoint) {
+		super();
+		provider = pProvider;
+		point = pPoint;
+	}
+
+	@Override
+	public IProvider<T> getProvider() {
+		return provider;
+	}
+
+	@Override
+	public IPoint<T> getPoint() {
+		return point;
+	}
+
+	@Override
+	public void init(IInjector pInjector) {
+		if (provider instanceof IInjectorAware) {
+			((IInjectorAware) provider).init(pInjector);
+		}
+		if (point instanceof IInjectorAware) {
+			((IInjectorAware) point).init(pInjector);
+		}
+	}
+
+}

Propchange: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/DefaultBinding.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/DefaultBindingBuilder.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/DefaultBindingBuilder.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/DefaultBindingBuilder.java (added)
+++ commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/DefaultBindingBuilder.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,351 @@
+package org.apache.commons.inject.impl.bind;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.List;
+
+import org.apache.commons.inject.api.IBinding;
+import org.apache.commons.inject.api.IInjector;
+import org.apache.commons.inject.api.IKey;
+import org.apache.commons.inject.api.IPoint;
+import org.apache.commons.inject.api.IProvider;
+import org.apache.commons.inject.api.Key;
+import org.apache.commons.inject.api.bind.IAnnotatedBindingBuilder;
+import org.apache.commons.inject.api.bind.ILinkedBindingBuilder;
+import org.apache.commons.inject.api.bind.IScopedBindingBuilder;
+import org.apache.commons.inject.api.bind.Scopes;
+import org.apache.commons.inject.api.bind.IBinder.IInjectionListener;
+import org.apache.commons.inject.api.bind.IBinder.IInjectionParticipator;
+import org.apache.commons.inject.impl.AbstractBaseProvider;
+import org.apache.commons.inject.impl.AbstractScopedProvider;
+import org.apache.commons.inject.impl.Introspector;
+import org.apache.commons.inject.impl.ListPoint;
+import org.apache.commons.inject.impl.MutableBindingSet;
+import org.apache.commons.inject.impl.AbstractBindingSet.MappedKey;
+
+import com.google.inject.Provider;
+
+public class DefaultBindingBuilder<T> implements IAnnotatedBindingBuilder<T> {
+	private final Class<T> sourceType;
+	private final IKey<T> sourceKey;
+	private Annotation sourceAnnotation;
+	private Class<? extends Annotation> sourceAnnotationType;
+	private T targetInstance;
+	private Class<? extends T> targetType;
+	private Constructor<? extends T> targetConstructor;
+	private Method targetMethod;
+	private Provider<? extends T> targetProvider;
+	private IProvider<? extends T> targetIProvider;
+	private Scopes scope;
+
+	public DefaultBindingBuilder(Class<T> pType) {
+		this(pType, Key.NO_NAME);
+	}
+
+	public DefaultBindingBuilder(Class<T> pType, String pName) {
+		sourceKey = new Key<T>(pType, pName);
+		sourceType = pType;
+	}
+
+	public DefaultBindingBuilder(IKey<T> pKey) {
+		sourceKey = pKey;
+		sourceType = null;
+	}
+	
+	@Override
+	public void toInstance(T pInstance) {
+		if (pInstance == null) {
+			throw new NullPointerException("The target instance must not be null.");
+		}
+		checkNoTarget();
+		targetInstance = pInstance;
+		asEagerSingleton();
+	}
+
+	private void checkNoTarget() {
+		if (targetInstance != null
+			||  targetType != null
+			||  targetConstructor != null
+			||  targetMethod != null
+			||  targetProvider != null
+			||  targetIProvider != null) {
+			throw new IllegalStateException("The methods " + TARGET_METHOD_LIST
+					+ " are mutually exclusive, and may be invoked only once.");
+		}
+	}
+
+	private static final String SCOPE_METHOD_LIST
+		= "toInstance(Object), scope(Scopes), asEagerSingleton(), and asLazySingleton()";
+	private static final String TARGET_METHOD_LIST
+		= "toInstance(Object), to(Class), to(Constructor), to(Method),"
+		+ " to(Provider, Class), to(IProvider)";
+	
+	@Override
+	public IScopedBindingBuilder<T> to(Class<? extends T> pImplClass) {
+		if (pImplClass == null) {
+			throw new NullPointerException("The target class must not be null.");
+		}
+		checkNoTarget();
+		targetType = pImplClass;
+		return this;
+	}
+
+	@Override
+	public IScopedBindingBuilder<T> to(Constructor<? extends T> pConstructor) {
+		if (pConstructor == null) {
+			throw new NullPointerException("The target constructor must not be null.");
+		}
+		checkNoTarget();
+		targetConstructor = pConstructor;
+		return this;
+	}
+
+	@Override
+	public IScopedBindingBuilder<T> to(Method pFactoryMethod) {
+		if (pFactoryMethod == null) {
+			throw new NullPointerException("The target constructor must not be null.");
+		}
+		if (!Modifier.isStatic(pFactoryMethod.getModifiers())) {
+			throw new IllegalStateException("The target method must be static.");
+		}
+		if (pFactoryMethod.getReturnType().isPrimitive()) {
+			throw new IllegalStateException("The target method must return a non-primitive result.");
+		}
+		if (pFactoryMethod.getReturnType().isArray()) {
+			throw new IllegalStateException("The target method must return a single object, and not an array.");
+		}
+		if (Void.TYPE == pFactoryMethod.getReturnType()) {
+			throw new IllegalStateException("The target method must return a non-void result.");
+		}
+		checkNoTarget();
+		targetMethod = pFactoryMethod;
+		return this;
+	}
+
+	@Override
+	public <S extends T> IScopedBindingBuilder<T> to(Class<S> pType,
+			Provider<S> pProvider) {
+		if (pType == null) {
+			throw new NullPointerException("The target type must not be null.");
+		}
+		if (pProvider == null) {
+			throw new NullPointerException("The target provider must not be null.");
+		}
+		checkNoTarget();
+		targetType = pType;
+		targetProvider = pProvider;
+		return this;
+	}
+
+	@Override
+	public IScopedBindingBuilder<T> to(IProvider<? extends T> pProvider) {
+		if (pProvider == null) {
+			throw new NullPointerException("The target provider must not be null.");
+		}
+		checkNoTarget();
+		targetIProvider = pProvider;
+		return this;
+	}
+
+	@Override
+	public void scope(Scopes pScope) {
+		if (pScope == null) {
+			throw new NullPointerException("The target scope must not be null.");
+		}
+		if (scope != null) {
+			throw new IllegalStateException("The methods " + SCOPE_METHOD_LIST
+					+ " are mutually exclusive, and may be invoked only once.");
+		}
+		scope = pScope;
+	}
+
+	@Override
+	public void asEagerSingleton() {
+		scope(Scopes.EAGER_SINGLETON);
+	}
+
+	@Override
+	public void asLazySingleton() {
+		scope(Scopes.LAZY_SINGLETON);
+	}
+
+	@Override
+	public ILinkedBindingBuilder<T> annotatedWith(Annotation pAnnotation) {
+		if (pAnnotation == null) {
+			throw new NullPointerException("The annotation must not be null.");
+		}
+		if (sourceAnnotation != null) {
+			throw new IllegalStateException("The method annotatedWith(Annotation) must not be invoked twice.");
+		}
+		sourceAnnotation = pAnnotation;
+		return this;
+	}
+
+	@Override
+	public ILinkedBindingBuilder<T> annotatedWith(
+			Class<? extends Annotation> pAnnotationType) {
+		if (pAnnotationType == null) {
+			throw new NullPointerException("The annotation type must not be null.");
+		}
+		if (sourceAnnotationType != null) {
+			throw new IllegalStateException("The method annotatedWith(Class) must not be invoked twice.");
+		}
+		sourceAnnotationType = pAnnotationType;
+		return this;
+	}
+
+	public void build(MutableBindingSet pBindings, final List<IInjectionListener> pListeners,
+			final List<IInjectionParticipator> pParticipators) {
+		final Class<T> baseType = getBaseType();
+		ListPoint<T> point = Introspector.getInstance().getPoint(baseType, pBindings);
+		final IKey<T> key = sourceKey;
+		if (pParticipators != null) {
+			for (IInjectionParticipator participator : pParticipators) {
+				final List<IPoint<Object>> points = participator.getPoints(key, baseType);
+				if (points != null) {
+					for (IPoint<Object> p : points) {
+						@SuppressWarnings("unchecked")
+						final IPoint<T> pnt = (IPoint<T>) p;
+						point.add(pnt);
+					}
+				}
+			}
+		}
+		if (pListeners != null  &&  !pListeners.isEmpty()) {
+			point.add(new IPoint<T>(){
+				@Override
+				public void injectTo(T pInstance, IInjector pInjector) {
+					for (IInjectionListener listener : pListeners) {
+						listener.initialized(key, pInstance);
+					}
+				}
+			});
+		}
+		final IProvider<T> baseProvider = getBaseProvider(baseType, point, pBindings);
+		final IProvider<T> scopedProvider = getScopedProvider(baseProvider);
+		final IBinding<T> binding = new DefaultBinding<T>(scopedProvider, point);
+		final Annotation[] annotations;
+		if (sourceAnnotation == null) {
+			annotations = Key.NO_ANNOTATIONS;
+		} else {
+			annotations = new Annotation[]{ sourceAnnotation };
+		}
+		final MappedKey<T> mkey = new MappedKey<T>(sourceKey.getType(), sourceKey.getName(),
+				annotations, sourceAnnotationType);
+				
+		pBindings.add(mkey, binding);
+	}
+
+	private Class<T> getBaseType() {
+		if (targetInstance != null) {
+			@SuppressWarnings("unchecked")
+			final Class<T> cl = (Class<T>) targetInstance.getClass();
+			return cl;
+		}
+		if (targetProvider != null) {
+			@SuppressWarnings("unchecked")
+			final Class<T> cl = (Class<T>) targetType;
+			return cl;
+		}
+		if (targetIProvider != null) {
+			@SuppressWarnings("unchecked")
+			final Class<T> cl = (Class<T>) targetIProvider.getType();
+			return cl;
+		}
+		if (targetType != null) {
+			@SuppressWarnings("unchecked")
+			final Class<T> cl = (Class<T>) targetType;
+			return cl;
+		}
+		if (targetConstructor != null) {
+			@SuppressWarnings("unchecked")
+			final Class<T> cl = (Class<T>) targetConstructor.getDeclaringClass();
+			return cl;
+		}
+		if (targetMethod != null) {
+			@SuppressWarnings("unchecked")
+			final Class<T> cl = (Class<T>) targetMethod.getReturnType();
+			return cl;
+		}
+		if (sourceType == null) {
+			throw new IllegalStateException("Neither of the methods "
+					+ TARGET_METHOD_LIST + " has been invoked on this binding builder,"
+					+ " which is required when binding a key.");
+		}
+		if (sourceType.isInterface()  ||  Modifier.isAbstract(sourceType.getModifiers())) {
+			throw new IllegalStateException("Neither of the methods "
+					+ TARGET_METHOD_LIST + " has been invoked on this binding builder, "
+					+ " but cannot bind " + sourceType.getName()
+					+ " as target type, because it is an interface, or an abstract class.");
+		}
+		return sourceType;
+	}
+	private AbstractBaseProvider<T> getBaseProvider(Class<T> pType, IPoint<T> pPoint, MutableBindingSet pBindings) {
+		if (targetInstance != null) {
+			return new AbstractBaseProvider<T>(pType, pPoint){
+				@Override
+				public T get() {
+					return targetInstance;
+				}
+			};
+		}
+		if (targetProvider != null) {
+			return new AbstractBaseProvider<T>(pType, pPoint){
+				@Override
+				public T get() {
+					return (T) targetProvider.get();
+				}
+			};
+		}
+		if (targetIProvider != null) {
+			return new AbstractBaseProvider<T>(pType, pPoint){
+				@Override
+				public T get() {
+					return (T) targetIProvider.get();
+				}
+				
+			};
+		}
+		if (targetType != null) {
+			@SuppressWarnings("unchecked")
+			final Class<T> cl = (Class<T>) targetType;
+			final AbstractBaseProvider<T> abp = (AbstractBaseProvider<T>) Introspector.getInstance().getProvider(cl, pPoint, pBindings);
+			return abp;
+		}
+		if (targetConstructor != null) {
+			final AbstractBaseProvider<T> abp = (AbstractBaseProvider<T>) Introspector.getInstance().getProvider(targetConstructor, pBindings);
+			return abp;
+		}
+		if (targetMethod != null) {
+			@SuppressWarnings("unchecked")
+			final AbstractBaseProvider<T> abp = (AbstractBaseProvider<T>) Introspector.getInstance().getProvider(targetMethod, pBindings);
+			return abp;
+		}
+		if (sourceType != null) {
+			final AbstractBaseProvider<T> abp = (AbstractBaseProvider<T>) Introspector.getInstance().getProvider(sourceType, pPoint, pBindings);
+			return abp;
+		}
+		throw new IllegalStateException("Neither of the methods "
+				+ TARGET_METHOD_LIST + " has been invoked on this binding builder.");
+	}
+
+	public AbstractScopedProvider<T> getScopedProvider(IProvider<T> pBaseProvider) {
+		if (scope == null) {
+			throw new IllegalStateException("Neither of the methods "
+					+ SCOPE_METHOD_LIST + " has been invoked on this binding builder.");
+			
+		}
+		switch(scope) {
+		case PER_CALL:
+			return new PerCallProvider<T>(pBaseProvider);
+		case EAGER_SINGLETON:
+			return new EagerSingletonProvider<T>(pBaseProvider);
+		case LAZY_SINGLETON:
+			return new LazySingletonProvider<T>(pBaseProvider);
+		default:
+			throw new IllegalStateException("Invalid scope: " + scope);
+		}
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/DefaultBindingBuilder.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/EagerSingletonProvider.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/EagerSingletonProvider.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/EagerSingletonProvider.java (added)
+++ commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/EagerSingletonProvider.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,30 @@
+package org.apache.commons.inject.impl.bind;
+
+import org.apache.commons.inject.api.IInjector;
+import org.apache.commons.inject.api.IProvider;
+import org.apache.commons.inject.impl.AbstractScopedProvider;
+
+public class EagerSingletonProvider<T> extends AbstractScopedProvider<T> {
+	private T instance;
+
+	public EagerSingletonProvider(IProvider<T> pBaseProvider) {
+		super(pBaseProvider);
+	}
+
+	@Override
+	public void init(IInjector pInjector) {
+		super.init(pInjector);
+		instance = super.get();
+	}
+
+
+	@Override
+	public T get() {
+		return instance;
+	}
+
+	@Override
+	public T get(IInjector pInjector) {
+		return instance;
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/EagerSingletonProvider.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/LazySingletonProvider.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/LazySingletonProvider.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/LazySingletonProvider.java (added)
+++ commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/LazySingletonProvider.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,20 @@
+package org.apache.commons.inject.impl.bind;
+
+import org.apache.commons.inject.api.IProvider;
+import org.apache.commons.inject.impl.AbstractScopedProvider;
+
+public class LazySingletonProvider<T> extends AbstractScopedProvider<T> {
+	private T instance;
+
+	public LazySingletonProvider(IProvider<T> pBaseProvider) {
+		super(pBaseProvider);
+	}
+
+	@Override
+	public synchronized T get() {
+		if (instance == null) {
+			instance = super.get();
+		}
+		return instance;
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/LazySingletonProvider.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/PerCallProvider.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/PerCallProvider.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/PerCallProvider.java (added)
+++ commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/PerCallProvider.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,10 @@
+package org.apache.commons.inject.impl.bind;
+
+import org.apache.commons.inject.api.IProvider;
+import org.apache.commons.inject.impl.AbstractScopedProvider;
+
+public class PerCallProvider<T> extends AbstractScopedProvider<T> {
+	public PerCallProvider(IProvider<T> pBaseProvider) {
+		super(pBaseProvider);
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/impl/bind/PerCallProvider.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/util/Exceptions.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/util/Exceptions.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/util/Exceptions.java (added)
+++ commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/util/Exceptions.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,17 @@
+package org.apache.commons.inject.util;
+
+import java.lang.reflect.UndeclaredThrowableException;
+
+public class Exceptions {
+	public static RuntimeException show(Throwable pTh) {
+		if (pTh == null) {
+			return new NullPointerException("The Throwable to show must not be null.");
+		} else if (pTh instanceof RuntimeException) {
+			return (RuntimeException) pTh;
+		} else if (pTh instanceof Error) {
+			throw (Error) pTh;
+		} else {
+			return new UndeclaredThrowableException(pTh);
+		}
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/util/Exceptions.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/util/Generics.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/util/Generics.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/util/Generics.java (added)
+++ commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/util/Generics.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,9 @@
+package org.apache.commons.inject.util;
+
+public class Generics {
+	public static <T> T cast(Object pObject) {
+		@SuppressWarnings("unchecked")
+		final T t = (T) pObject;
+		return t;
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/main/java/org/apache/commons/inject/util/Generics.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/ListenerTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/ListenerTest.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/ListenerTest.java (added)
+++ commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/ListenerTest.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,136 @@
+package org.apache.commons.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import junit.framework.Assert;
+
+import org.apache.commons.inject.api.CommonsInject;
+import org.apache.commons.inject.api.IInjector;
+import org.apache.commons.inject.api.IKey;
+import org.apache.commons.inject.api.ILifecycleController;
+import org.apache.commons.inject.api.PostConstructModule;
+import org.apache.commons.inject.api.bind.IBinder;
+import org.apache.commons.inject.api.bind.IModule;
+import org.apache.commons.inject.api.bind.Scopes;
+import org.junit.Test;
+
+public class ListenerTest {
+	private static class ListenerModule implements IModule {
+		private boolean injectorBuilListenerCalled;
+		private final List<Object> initializedObjects  = new ArrayList<Object>();
+		@Override
+		public void configure(IBinder pBinder) {
+			pBinder.add(new IBinder.IInjectorBuildListener() {
+				@Override
+				public void created(IInjector pInjector) {
+					injectorBuilListenerCalled = true;
+				}
+			});
+			pBinder.add(new IBinder.IInjectionListener() {
+				@Override
+				public void initialized(IKey<?> pKey, Object pObject) {
+					initializedObjects.add(pObject);
+				}
+			});
+			pBinder.bind(TimeRecordingObject.class, "perCall").scope(Scopes.PER_CALL);
+			pBinder.bind(TimeRecordingObject.class, "lazy").asLazySingleton();
+			pBinder.bind(TimeRecordingObject.class, "eager").asEagerSingleton();
+		}
+
+		boolean isInitialized() {
+			return injectorBuilListenerCalled;
+		}
+		List<Object> getInitializedObjects(){
+			return initializedObjects;
+		}
+	}
+	public static class InitializableObject {
+		private final long timeOfCreation = System.currentTimeMillis();
+		private long timeOfInitialization, timeOfShutdown;
+		private int state;
+
+		@PostConstruct
+		public void start() {
+			state = 1;
+			timeOfInitialization = System.currentTimeMillis();
+		}
+
+		@PreDestroy
+		public void shutdown() {
+			state = 2;
+			timeOfShutdown = System.currentTimeMillis();
+		}
+
+		public void assertStarted() {
+			Assert.assertTrue(state > 0);
+			Assert.assertTrue(timeOfInitialization >= timeOfCreation);
+		}
+
+		public void assertTerminated() {
+			assertStarted();
+			Assert.assertTrue(state > 1);
+			Assert.assertTrue(timeOfShutdown >= timeOfInitialization);
+			
+		}
+	}
+
+	@Test
+	public void testListeners() {
+		final ListenerModule module = new ListenerModule();
+		final IInjector injector = CommonsInject.build(module);
+		Assert.assertTrue(module.isInitialized());
+		final Object perCall1 = injector.requireInstance(TimeRecordingObject.class, "perCall");
+		final Object perCall2 = injector.requireInstance(TimeRecordingObject.class, "perCall");
+		final Object lazy1 = injector.requireInstance(TimeRecordingObject.class, "lazy");
+		final Object lazy2 = injector.requireInstance(TimeRecordingObject.class, "lazy");
+		final Object eager1 = injector.requireInstance(TimeRecordingObject.class, "eager");
+		final Object eager2 = injector.requireInstance(TimeRecordingObject.class, "eager");
+		Assert.assertSame(eager1, eager2);
+		Assert.assertSame(lazy1, lazy2);
+		Assert.assertNotSame(perCall1, perCall2);
+		List<Object> initializedObjects = module.getInitializedObjects();
+		Assert.assertEquals(4, initializedObjects.size());
+		Assert.assertSame(eager1, initializedObjects.get(0));
+		Assert.assertSame(perCall1, initializedObjects.get(1));
+		Assert.assertSame(perCall2, initializedObjects.get(2));
+		Assert.assertSame(lazy1, initializedObjects.get(3));
+	}
+
+	@Test
+	public void testPostConstruct() {
+		final PostConstructModule module0 = new PostConstructModule();
+		final IModule module1 = new IModule(){
+			@Override
+			public void configure(IBinder pBinder) {
+				pBinder.bind(InitializableObject.class, "perCall").scope(Scopes.PER_CALL);
+				pBinder.bind(InitializableObject.class, "lazy").asLazySingleton();
+				pBinder.bind(InitializableObject.class, "eager").asEagerSingleton();
+			}
+		};
+		final ILifecycleController controller = module0.getLifecycleController();
+		controller.start();
+		final IInjector injector = CommonsInject.build(module0, module1);
+		final InitializableObject perCall1 = injector.requireInstance(InitializableObject.class, "perCall");
+		final InitializableObject perCall2 = injector.requireInstance(InitializableObject.class, "perCall");
+		final InitializableObject lazy1 = injector.requireInstance(InitializableObject.class, "lazy");
+		final InitializableObject lazy2 = injector.requireInstance(InitializableObject.class, "lazy");
+		final InitializableObject eager1 = injector.requireInstance(InitializableObject.class, "eager");
+		final InitializableObject eager2 = injector.requireInstance(InitializableObject.class, "eager");
+		Assert.assertSame(eager1, eager2);
+		Assert.assertSame(lazy1, lazy2);
+		Assert.assertNotSame(perCall1, perCall2);
+		perCall1.assertStarted();
+		perCall2.assertStarted();
+		eager1.assertStarted();
+		lazy1.assertStarted();
+		controller.shutdown();
+		perCall1.assertTerminated();
+		perCall2.assertTerminated();
+		eager1.assertTerminated();
+		lazy1.assertTerminated();
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/ListenerTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/Log4jLoggerModuleTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/Log4jLoggerModuleTest.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/Log4jLoggerModuleTest.java (added)
+++ commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/Log4jLoggerModuleTest.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,96 @@
+package org.apache.commons.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.inject.api.CommonsInject;
+import org.apache.commons.inject.api.IInjector;
+import org.apache.commons.inject.api.ILifecycleController;
+import org.apache.commons.inject.api.ILifecycleListener;
+import org.apache.commons.inject.api.InjLogger;
+import org.apache.commons.inject.api.Log4jLoggerModule;
+import org.apache.commons.inject.api.PostConstructModule;
+import org.apache.commons.inject.api.bind.IBinder;
+import org.apache.commons.inject.api.bind.IModule;
+import org.apache.commons.inject.api.bind.Scopes;
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.spi.LoggingEvent;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class Log4jLoggerModuleTest {
+	private final List<String> messages = new ArrayList<String>();
+	private void configureLog4j() {
+		BasicConfigurator.configure();
+		final Logger root = Logger.getRootLogger();
+		root.removeAllAppenders();
+		root.addAppender(new AppenderSkeleton(true) {
+			
+			@Override
+			public boolean requiresLayout() {
+				// TODO Auto-generated method stub
+				return false;
+			}
+			
+			@Override
+			public void close() {
+				// TODO Auto-generated method stub
+				
+			}
+			
+			@Override
+			protected void append(LoggingEvent pEvent) {
+				final Level level = pEvent.getLevel();
+				messages.add(level.toString() + "; " + pEvent.getMessage());
+			}
+		});
+	}
+
+	public static class InitializableObject implements ILifecycleListener {
+		@InjLogger(id="MyLogger") private Logger log;
+
+		@Override
+		public void start() {
+			log.debug("start: ->");
+			log.debug("start: <-");
+		}
+
+		public void run() {
+			log.debug("run: Running");
+		}
+		
+		@Override
+		public void shutdown() {
+			log.debug("shutdown: ->");
+			log.debug("shutdown: <-");
+		}
+	}
+
+	@Test
+	public void testLoggerModule() {
+		configureLog4j();
+		final PostConstructModule module0 = new PostConstructModule();
+		final IModule module1 = new Log4jLoggerModule();
+		final IModule module2 = new IModule(){
+			@Override
+			public void configure(IBinder pBinder) {
+				pBinder.bind(InitializableObject.class).scope(Scopes.PER_CALL);
+			}
+		};
+		final ILifecycleController controller = module0.getLifecycleController();
+		final IInjector injector = CommonsInject.build(module0, module1, module2);
+		final InitializableObject io = injector.getInstance(InitializableObject.class);
+		controller.start();
+		io.run();
+		controller.shutdown();
+		Assert.assertEquals(5, messages.size());
+		Assert.assertEquals("DEBUG; start: ->", messages.get(0));
+		Assert.assertEquals("DEBUG; start: ->", messages.get(1));
+		Assert.assertEquals("DEBUG; run: Running", messages.get(2));
+		Assert.assertEquals("DEBUG; shutdown: ->", messages.get(3));
+		Assert.assertEquals("DEBUG; shutdown: ->", messages.get(4));
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/Log4jLoggerModuleTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/SimpleInjectorTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/SimpleInjectorTest.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/SimpleInjectorTest.java (added)
+++ commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/SimpleInjectorTest.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,128 @@
+package org.apache.commons.impl;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.inject.api.CommonsInject;
+import org.apache.commons.inject.api.IInjector;
+import org.apache.commons.inject.api.IKey;
+import org.apache.commons.inject.api.Key;
+import org.apache.commons.inject.api.NoSuchBindingException;
+import org.apache.commons.inject.api.bind.IBinder;
+import org.apache.commons.inject.api.bind.IModule;
+import org.apache.commons.inject.api.bind.Scopes;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class SimpleInjectorTest {
+	private static final List<Object> FOO_LIST = new ArrayList<Object>();
+	private static final List<Object> BAR_LIST = new ArrayList<Object>();
+
+	private IInjector newInjector() {
+		final IModule module = new IModule(){
+			@Override
+			public void configure(IBinder pBinder) {
+				pBinder.bind(List.class).to(ArrayList.class).scope(Scopes.PER_CALL);
+				pBinder.bind(List.class, "foo").toInstance(FOO_LIST);
+				pBinder.bind(List.class, "bar").toInstance(BAR_LIST);
+				
+			}
+		};
+		return CommonsInject.build(module);
+	}
+
+	@Test
+	public void testSimpleInjector() throws Exception {
+		final IInjector injector = newInjector();
+		final List<?> fooList = injector.requireInstance(List.class, "foo");
+		Assert.assertNotNull(fooList);
+		Assert.assertSame(FOO_LIST, fooList);
+		final List<?> barList = injector.requireInstance(List.class, "bar");
+		Assert.assertNotNull(barList);
+		Assert.assertSame(BAR_LIST, barList);
+		final List<?> someList1 = injector.requireInstance(List.class);
+		Assert.assertNotNull(someList1);
+		Assert.assertNotSame(FOO_LIST, someList1);
+		Assert.assertNotSame(BAR_LIST, someList1);
+		final List<?> someList2 = injector.requireInstance(List.class);
+		Assert.assertNotNull(someList2);
+		Assert.assertNotSame(FOO_LIST, someList2);
+		Assert.assertNotSame(BAR_LIST, someList2);
+		Assert.assertNotSame(someList1, someList2);
+	}
+
+	@Test
+	public void testNoBinding() throws Exception {
+		final IInjector injector = newInjector();
+		{
+			boolean haveException = false;
+			try {
+				injector.requireInstance(Map.class);
+				Assert.fail("Expected exception");
+			} catch (NoSuchBindingException e) {
+				Assert.assertEquals("No binding registered for key: Type=java.util.Map", e.getMessage());
+				haveException = true;
+			}
+			Assert.assertTrue(haveException);
+		}
+		{
+			boolean haveException = false;
+			try {
+				injector.requireInstance(List.class, "foobar");
+				Assert.fail("Expected exception");
+			} catch (NoSuchBindingException e) {
+				Assert.assertEquals("No binding registered for key: Type=java.util.List, Name=foobar", e.getMessage());
+				haveException = true;
+			}
+			Assert.assertTrue(haveException);
+		}
+		{
+			boolean haveException = false;
+			try {
+				final Annotation[] annotations = new Annotation[]{getTestAnnotation()};
+				@SuppressWarnings("rawtypes")
+				final IKey<List> key = new Key<List>(List.class, "foo", annotations);
+				injector.requireInstance(key);
+				Assert.fail("Expected exception");
+			} catch (NoSuchBindingException e) {
+				Assert.assertTrue(e.getMessage().startsWith("No binding registered for key: Type=java.util.List, Name=foo, Annotations=["));
+				haveException = true;
+			}
+			Assert.assertTrue(haveException);
+		}
+	}
+	
+	private Annotation getTestAnnotation() throws Exception {
+		final Class<?> cl = SimpleInjectorTest.class;
+		final Method method = cl.getMethod("testScopes");
+		return method.getAnnotation(Test.class);
+	}
+
+	@Test
+	public void testScopes() throws Exception {
+		final IModule module = new IModule(){
+			@Override
+			public void configure(IBinder pBinder) {
+				pBinder.bind(TimeRecordingObject.class, "eager").asEagerSingleton();
+				pBinder.bind(TimeRecordingObject.class, "lazy").asLazySingleton();
+			}
+		};
+		long time0 = System.currentTimeMillis();
+		final IInjector injector = CommonsInject.build(module);
+		long time1 = System.currentTimeMillis();
+		final TimeRecordingObject lazy0 = injector.getInstance(TimeRecordingObject.class, "lazy");
+		final TimeRecordingObject lazy1 = injector.getInstance(TimeRecordingObject.class, "lazy");
+		final TimeRecordingObject eager0 = injector.getInstance(TimeRecordingObject.class, "eager");
+		final TimeRecordingObject eager1 = injector.getInstance(TimeRecordingObject.class, "eager");
+		long time2 = System.currentTimeMillis();
+		Assert.assertSame(eager0, eager1);
+		Assert.assertSame(lazy0, lazy1);
+		long eager0Time = eager0.getTimeOfCreation();
+		long lazy0Time = lazy0.getTimeOfCreation();
+		Assert.assertTrue(time0 <= eager0Time &&  eager0Time <= time1 &&  eager0Time <= time2);
+		Assert.assertTrue(time0 <= lazy0Time &&  time1 <= lazy0Time &&  lazy0Time <= time2);
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/SimpleInjectorTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/TckTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/TckTest.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/TckTest.java (added)
+++ commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/TckTest.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,54 @@
+package org.apache.commons.impl;
+
+import org.apache.commons.inject.api.CommonsInject;
+import org.apache.commons.inject.api.IInjector;
+import org.apache.commons.inject.api.bind.IBinder;
+import org.apache.commons.inject.api.bind.IModule;
+import org.apache.commons.inject.api.bind.Scopes;
+import org.atinject.tck.Tck;
+import org.atinject.tck.auto.Car;
+import org.atinject.tck.auto.Convertible;
+import org.atinject.tck.auto.Drivers;
+import org.atinject.tck.auto.DriversSeat;
+import org.atinject.tck.auto.Engine;
+import org.atinject.tck.auto.FuelTank;
+import org.atinject.tck.auto.Seat;
+import org.atinject.tck.auto.Tire;
+import org.atinject.tck.auto.V8Engine;
+import org.atinject.tck.auto.accessories.Cupholder;
+import org.atinject.tck.auto.accessories.SpareTire;
+import org.junit.Test;
+
+public class TckTest {
+	@Test
+	public void testTckWithStaticInjection() throws Exception {
+		final IInjector injector = newInjector(true);
+		final Car car = injector.requireInstance(Car.class);
+		Tck.testsFor(car, true, true);
+	}
+
+	@Test
+	public void testTckWithoutStaticInjection() throws Exception {
+		final IInjector injector = newInjector(false);
+		final Car car = injector.requireInstance(Car.class);
+		Tck.testsFor(car, false, true);
+	}
+
+	private IInjector newInjector(boolean pWithStaticInjection) {
+		final IModule module = new IModule(){
+			@Override
+			public void configure(IBinder pBinder) {
+				pBinder.bind(Car.class).to(Convertible.class).scope(Scopes.PER_CALL);;
+				pBinder.bind(Seat.class).annotatedWith(Drivers.class).to(DriversSeat.class).scope(Scopes.PER_CALL);
+				pBinder.bind(Engine.class).to(V8Engine.class).scope(Scopes.PER_CALL);
+				pBinder.bind(Tire.class, "spare").to(SpareTire.class).scope(Scopes.PER_CALL);
+				pBinder.bind(SpareTire.class).scope(Scopes.PER_CALL);
+				pBinder.bind(Cupholder.class).scope(Scopes.PER_CALL);
+				pBinder.bind(Tire.class).scope(Scopes.PER_CALL);
+				pBinder.bind(FuelTank.class).scope(Scopes.PER_CALL);
+			}
+		};
+		return CommonsInject.build(module);
+	}
+
+}

Propchange: commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/TckTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/TimeRecordingObject.java
URL: http://svn.apache.org/viewvc/commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/TimeRecordingObject.java?rev=1636573&view=auto
==============================================================================
--- commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/TimeRecordingObject.java (added)
+++ commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/TimeRecordingObject.java Tue Nov  4 13:05:37 2014
@@ -0,0 +1,13 @@
+package org.apache.commons.impl;
+
+public class TimeRecordingObject {
+	private final long timeOfCreation;
+
+	public TimeRecordingObject() {
+		timeOfCreation = System.currentTimeMillis();
+	}
+
+	public long getTimeOfCreation() {
+		return timeOfCreation;
+	}
+}

Propchange: commons/sandbox/commons-inject/trunk/src/test/java/org/apache/commons/impl/TimeRecordingObject.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain