Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.picocontainer.injectors.IterativeInjector Maven / Gradle / Ivy
package org.picocontainer.injectors;
import com.thoughtworks.paranamer.AdaptiveParanamer;
import com.thoughtworks.paranamer.AnnotationParanamer;
import com.thoughtworks.paranamer.CachingParanamer;
import com.thoughtworks.paranamer.Paranamer;
import org.picocontainer.ComponentMonitor;
import org.picocontainer.NameBinding;
import org.picocontainer.Parameter;
import org.picocontainer.PicoCompositionException;
import org.picocontainer.PicoContainer;
import org.picocontainer.annotations.Bind;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Injection will happen iteratively after component instantiation
*/
public abstract class IterativeInjector extends AbstractInjector {
private static final Object[] NONE = new Object[0];
private transient ThreadLocalCyclicDependencyGuard instantiationGuard;
protected transient List injectionMembers;
protected transient Type[] injectionTypes;
protected transient Annotation[] bindings;
private transient Paranamer paranamer;
private transient volatile boolean initialized;
/**
* Constructs a IterativeInjector
*
* @param componentKey the search key for this implementation
* @param componentImplementation the concrete implementation
* @param parameters the parameters to use for the initialization
* @param monitor the component monitor used by this addAdapter
* @param useNames use argument names when looking up dependencies
* @throws org.picocontainer.injectors.AbstractInjector.NotConcreteRegistrationException
* if the implementation is not a concrete class.
* @throws NullPointerException if one of the parameters is null
*/
public IterativeInjector(final Object componentKey, final Class componentImplementation, Parameter[] parameters, ComponentMonitor monitor,
boolean useNames) throws NotConcreteRegistrationException {
super(componentKey, componentImplementation, parameters, monitor, useNames);
}
protected Constructor getConstructor() {
Object retVal = AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
try {
return getComponentImplementation().getConstructor((Class[])null);
} catch (NoSuchMethodException e) {
return new PicoCompositionException(e);
} catch (SecurityException e) {
return new PicoCompositionException(e);
}
}
});
if (retVal instanceof Constructor) {
return (Constructor) retVal;
} else {
throw (PicoCompositionException) retVal;
}
}
private Parameter[] getMatchingParameterListForSetters(PicoContainer container) throws PicoCompositionException {
if (initialized == false) {
synchronized (this) {
if (initialized == false) {
initializeInjectionMembersAndTypeLists();
}
}
}
final List matchingParameterList = new ArrayList(Collections.nCopies(injectionMembers.size(), null));
final Parameter[] currentParameters = parameters != null ? parameters : createDefaultParameters(injectionTypes.length);
final Set nonMatchingParameterPositions = matchParameters(container, matchingParameterList, currentParameters);
final Set unsatisfiableDependencyTypes = new HashSet();
final List unsatisfiableDependencyMembers = new ArrayList();
for (int i = 0; i < matchingParameterList.size(); i++) {
if (matchingParameterList.get(i) == null) {
unsatisfiableDependencyTypes.add(injectionTypes[i]);
unsatisfiableDependencyMembers.add(injectionMembers.get(i));
}
}
if (unsatisfiableDependencyTypes.size() > 0) {
unsatisfiedDependencies(container, unsatisfiableDependencyTypes, unsatisfiableDependencyMembers);
} else if (nonMatchingParameterPositions.size() > 0) {
throw new PicoCompositionException("Following parameters do not match any of the injectionMembers for " + getComponentImplementation() + ": " + nonMatchingParameterPositions.toString());
}
return matchingParameterList.toArray(new Parameter[matchingParameterList.size()]);
}
private Set matchParameters(PicoContainer container, List matchingParameterList, Parameter[] currentParameters) {
Set unmatchedParameters = new HashSet();
for (int i = 0; i < currentParameters.length; i++) {
if (!matchParameter(container, matchingParameterList, currentParameters[i])) {
unmatchedParameters.add(i);
}
}
return unmatchedParameters;
}
private boolean matchParameter(PicoContainer container, List matchingParameterList, Parameter parameter) {
for (int j = 0; j < injectionTypes.length; j++) {
Object o = matchingParameterList.get(j);
try {
if (o == null && parameter.resolve(container, this, null, injectionTypes[j],
makeParameterNameImpl(injectionMembers.get(j)),
useNames(), bindings[j]).isResolved()) {
matchingParameterList.set(j, parameter);
return true;
}
} catch (AmbiguousComponentResolutionException e) {
e.setMember(injectionMembers.get(j));
throw e;
}
}
return false;
}
protected NameBinding makeParameterNameImpl(AccessibleObject member) {
if (paranamer == null) {
paranamer = new CachingParanamer(new AnnotationParanamer(new AdaptiveParanamer()));
}
return new ParameterNameBinding(paranamer, member, 0);
}
protected abstract void unsatisfiedDependencies(PicoContainer container, Set unsatisfiableDependencyTypes, List unsatisfiableDependencyMembers);
public T getComponentInstance(final PicoContainer container, Type into) throws PicoCompositionException {
final Constructor constructor = getConstructor();
if (instantiationGuard == null) {
instantiationGuard = new ThreadLocalCyclicDependencyGuard() {
public Object run(Object instance) {
final Parameter[] matchingParameters = getMatchingParameterListForSetters(guardedContainer);
Object componentInstance = makeInstance(container, constructor, currentMonitor());
return decorateComponentInstance(matchingParameters, currentMonitor(), componentInstance, container, guardedContainer);
}
};
}
instantiationGuard.setGuardedContainer(container);
return (T) instantiationGuard.observe(getComponentImplementation(), null);
}
private Object decorateComponentInstance(Parameter[] matchingParameters, ComponentMonitor componentMonitor, Object componentInstance, PicoContainer container, PicoContainer guardedContainer) {
AccessibleObject member = null;
Object injected[] = new Object[injectionMembers.size()];
Object lastReturn = null;
try {
for (int i = 0; i < injectionMembers.size(); i++) {
member = injectionMembers.get(i);
if (matchingParameters[i] != null) {
Object toInject = matchingParameters[i].resolve(guardedContainer, this, null, injectionTypes[i],
makeParameterNameImpl(injectionMembers.get(i)),
useNames(), bindings[i]).resolveInstance();
Object rv = componentMonitor.invoking(container, this, (Member) member, componentInstance, new Object[] {toInject});
if (rv == ComponentMonitor.KEEP) {
long str = System.currentTimeMillis();
lastReturn = injectIntoMember(member, componentInstance, toInject);
componentMonitor.invoked(container, this, (Member) member, componentInstance, System.currentTimeMillis() - str, new Object[] {toInject}, lastReturn);
} else {
lastReturn = rv;
}
injected[i] = toInject;
}
}
return memberInvocationReturn(lastReturn, member, componentInstance);
} catch (InvocationTargetException e) {
return caughtInvocationTargetException(componentMonitor, (Member) member, componentInstance, e);
} catch (IllegalAccessException e) {
return caughtIllegalAccessException(componentMonitor, (Member) member, componentInstance, e);
}
}
protected abstract Object memberInvocationReturn(Object lastReturn, AccessibleObject member, Object instance);
private Object makeInstance(PicoContainer container, Constructor constructor, ComponentMonitor componentMonitor) {
long startTime = System.currentTimeMillis();
Constructor constructorToUse = componentMonitor.instantiating(container,
IterativeInjector.this, constructor);
Object componentInstance;
try {
componentInstance = newInstance(constructorToUse, null);
} catch (InvocationTargetException e) {
componentMonitor.instantiationFailed(container, IterativeInjector.this, constructorToUse, e);
if (e.getTargetException() instanceof RuntimeException) {
throw (RuntimeException)e.getTargetException();
} else if (e.getTargetException() instanceof Error) {
throw (Error)e.getTargetException();
}
throw new PicoCompositionException(e.getTargetException());
} catch (InstantiationException e) {
return caughtInstantiationException(componentMonitor, constructor, e, container);
} catch (IllegalAccessException e) {
return caughtIllegalAccessException(componentMonitor, constructor, e, container);
}
componentMonitor.instantiated(container,
IterativeInjector.this,
constructorToUse,
componentInstance,
NONE,
System.currentTimeMillis() - startTime);
return componentInstance;
}
@Override
public Object decorateComponentInstance(final PicoContainer container, Type into, final T instance) {
if (instantiationGuard == null) {
instantiationGuard = new ThreadLocalCyclicDependencyGuard() {
public Object run(Object inst) {
final Parameter[] matchingParameters = getMatchingParameterListForSetters(guardedContainer);
return decorateComponentInstance(matchingParameters, currentMonitor(), inst, container, guardedContainer);
}
};
}
instantiationGuard.setGuardedContainer(container);
return instantiationGuard.observe(getComponentImplementation(), instance);
}
protected abstract Object injectIntoMember(AccessibleObject member, Object componentInstance, Object toInject) throws IllegalAccessException, InvocationTargetException;
@Override
public void verify(final PicoContainer container) throws PicoCompositionException {
if (verifyingGuard == null) {
verifyingGuard = new ThreadLocalCyclicDependencyGuard() {
public Object run(Object instance) {
final Parameter[] currentParameters = getMatchingParameterListForSetters(guardedContainer);
for (int i = 0; i < currentParameters.length; i++) {
currentParameters[i].verify(container, IterativeInjector.this, injectionTypes[i],
makeParameterNameImpl(injectionMembers.get(i)), useNames(), bindings[i]);
}
return null;
}
};
}
verifyingGuard.setGuardedContainer(container);
verifyingGuard.observe(getComponentImplementation(), null);
}
protected void initializeInjectionMembersAndTypeLists() {
injectionMembers = new ArrayList();
Set injectionMemberNames = new HashSet();
List bingingIds = new ArrayList();
final List nameList = new ArrayList();
final List typeList = new ArrayList();
final Method[] methods = getMethods();
for (final Method method : methods) {
final Type[] parameterTypes = method.getGenericParameterTypes();
fixGenericParameterTypes(method, parameterTypes);
String methodSignature = crudeMethodSignature(method);
// We're only interested if there is only one parameter ...
if (parameterTypes.length == 1) {
boolean isInjector = isInjectorMethod(method);
// ... and the method name is bean-style.
// We're also not interested in dupes from parent classes (not all JDK impls)
if (isInjector && !injectionMemberNames.contains(methodSignature)) {
injectionMembers.add(method);
injectionMemberNames.add(methodSignature);
nameList.add(getName(method));
typeList.add(box(parameterTypes[0]));
bingingIds.add(getBindings(method, 0));
}
}
}
injectionTypes = typeList.toArray(new Type[0]);
bindings = bingingIds.toArray(new Annotation[0]);
initialized = true;
}
public static String crudeMethodSignature(Method method) {
StringBuilder sb = new StringBuilder();
sb.append(method.getReturnType().getName());
sb.append(method.getName());
for (Class> pType : method.getParameterTypes()) {
sb.append(pType.getName());
}
return sb.toString();
}
protected String getName(Method method) {
return null;
}
private void fixGenericParameterTypes(Method method, Type[] parameterTypes) {
for (int i = 0; i < parameterTypes.length; i++) {
Type parameterType = parameterTypes[i];
if (parameterType instanceof TypeVariable) {
parameterTypes[i] = method.getParameterTypes()[i];
}
}
}
private Annotation getBindings(Method method, int i) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations.length >= i +1 ) {
Annotation[] o = parameterAnnotations[i];
for (Annotation annotation : o) {
if (annotation.annotationType().getAnnotation(Bind.class) != null) {
return annotation;
}
}
return null;
}
//TODO - what's this ?
if (parameterAnnotations != null) {
//return ((Bind) method.getAnnotation(Bind.class)).id();
}
return null;
}
protected boolean isInjectorMethod(Method method) {
return false;
}
private Method[] getMethods() {
return (Method[]) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return getComponentImplementation().getMethods();
}
});
}
}