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