package com.blazebit.cdi.exclude;
import static org.apache.deltaspike.core.util.ReflectionUtils.invokeMethod;
import java.lang.reflect.Method;
import java.util.List;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionPoint;
public class InjectableMethod {
private final CreationalContext<?> creationalContext;
private final BeanManager beanManager;
/** Injectable method */
protected Method method;
/** Bean parent instance that owns the method */
protected Object ownerInstance;
/** If this method is dispose method */
private boolean disposable;
/** Used in dispose method, represents produces method parameter instance */
private Object producerMethodInstance = null;
private List<InjectionPoint> injectionPoints;
public InjectableMethod(AnnotatedMethod<?> annotatedMethod, Object instance, Bean<?> declaringBean, CreationalContext<?> creationalContext, BeanManager beanManager, List<InjectionPoint> injectionPoints) {
this.method = annotatedMethod.getJavaMember();
this.ownerInstance = instance;
this.creationalContext = creationalContext;
this.beanManager = beanManager;
this.injectionPoints = injectionPoints;
}
public Object doInjection() {
Object[] parameterValues = new Object[injectionPoints.size()];
for (int i = 0; i < injectionPoints.size(); i++) {
parameterValues[i] = beanManager.getInjectableReference(injectionPoints.get(i), creationalContext);
}
for (int i = 0; i < injectionPoints.size(); i++) {
for (InjectionPoint point : injectionPoints) {
AnnotatedParameter<?> parameter = (AnnotatedParameter<?>) point.getAnnotated();
if (isDisposable() && parameter.getAnnotation(Disposes.class) != null) {
parameterValues[i] = producerMethodInstance;
} else {
parameterValues[i] = beanManager.getInjectableReference(point, creationalContext);
}
}
}
try {
return invokeMethod(ownerInstance, method, Object.class, true, parameterValues);
} catch (RuntimeException e) {
//X TODO check if it is compatible with Weld
//workaround for OWB which wraps InvocationTargetException the original exception
//see ReflectionUtils#invokeMethod
if (RuntimeException.class.getName().equals(e.getClass().getName()) && e.getCause() instanceof RuntimeException) {
throw (RuntimeException) e.getCause();
}
throw e;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
private boolean isDisposable() {
return disposable;
}
public void setDisposable(boolean disposable) {
this.disposable = disposable;
}
public void setProducerMethodInstance(Object instance) {
producerMethodInstance = instance;
}
}