package org.jboss.as.ee.component;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.jboss.as.naming.ManagedReferenceFactory;
import org.jboss.as.server.deployment.DeploymentPhaseContext;
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
import org.jboss.as.server.deployment.reflect.ClassReflectionIndexUtil;
import org.jboss.as.server.deployment.reflect.DeploymentReflectionIndex;
import org.jboss.invocation.ImmediateInterceptorFactory;
import org.jboss.invocation.Interceptor;
import org.jboss.invocation.InterceptorFactory;
import org.jboss.invocation.InterceptorFactoryContext;
import org.jboss.invocation.Interceptors;
import org.jboss.msc.value.InjectedValue;
import static org.jboss.as.ee.logging.EeLogger.ROOT_LOGGER;
/**
* @author Stuart Douglas
*/
public class AbstractComponentConfigurator {
/**
* The weaved interceptor factory results in a lot of runtime allocations, and should not be used
* @param interceptorFactories The interceptor factories
* @return
*/
@Deprecated
protected static InterceptorFactory weaved(final Collection<InterceptorFactory> interceptorFactories) {
if(interceptorFactories == null) {
return null;
}
return new InterceptorFactory() {
@Override
public Interceptor create(InterceptorFactoryContext context) {
final Interceptor[] interceptors = new Interceptor[interceptorFactories.size()];
final Iterator<InterceptorFactory> factories = interceptorFactories.iterator();
for (int i = 0; i < interceptors.length; i++) {
interceptors[i] = factories.next().create(context);
}
return Interceptors.getWeavedInterceptor(interceptors);
}
};
}
/**
* Sets up all resource injections for a class. This takes into account injections that have been specified in the module and component deployment descriptors
* <p/>
* Note that this does not take superclasses into consideration, only injections on the current class
*
* @param clazz The class or superclass to perform injection for
* @param actualClass The actual component or interceptor class
* @param classDescription The class description, may be null
* @param moduleDescription The module description
* @param description The component description
* @param configuration The component configuration
* @param context The phase context
* @param injectors The list of injectors for the current component
* @param instanceKey The key that identifies the instance to inject in the interceptor context
* @param uninjectors The list of uninjections for the current component
* @throws org.jboss.as.server.deployment.DeploymentUnitProcessingException
*
*/
protected void mergeInjectionsForClass(final Class<?> clazz, final Class<?> actualClass, final EEModuleClassDescription classDescription, final EEModuleDescription moduleDescription, final DeploymentReflectionIndex deploymentReflectionIndex, final ComponentDescription description, final ComponentConfiguration configuration, final DeploymentPhaseContext context, final Deque<InterceptorFactory> injectors, final Object instanceKey, final Deque<InterceptorFactory> uninjectors, boolean metadataComplete) throws DeploymentUnitProcessingException {
final Map<InjectionTarget, ResourceInjectionConfiguration> mergedInjections = new HashMap<InjectionTarget, ResourceInjectionConfiguration>();
if (classDescription != null && !metadataComplete) {
mergedInjections.putAll(classDescription.getInjectionConfigurations());
}
mergedInjections.putAll(moduleDescription.getResourceInjections(clazz.getName()));
mergedInjections.putAll(description.getResourceInjections(clazz.getName()));
for (final ResourceInjectionConfiguration injectionConfiguration : mergedInjections.values()) {
if(!moduleDescription.isAppClient() && injectionConfiguration.getTarget().isStatic(context.getDeploymentUnit())) {
ROOT_LOGGER.debugf("Injection for a member with static modifier is only acceptable on application clients, ignoring injection for target %s",injectionConfiguration.getTarget());
continue;
}
if(injectionConfiguration.getTarget() instanceof MethodInjectionTarget) {
//we need to make sure that if this is a method injection it has not been overriden
final MethodInjectionTarget mt = (MethodInjectionTarget)injectionConfiguration.getTarget();
Method method = mt.getMethod(deploymentReflectionIndex, clazz);
if(!isNotOverriden(clazz, method, actualClass, deploymentReflectionIndex)) {
continue;
}
}
final Object valueContextKey = new Object();
final InjectedValue<ManagedReferenceFactory> managedReferenceFactoryValue = new InjectedValue<ManagedReferenceFactory>();
configuration.getStartDependencies().add(new ComponentDescription.InjectedConfigurator(injectionConfiguration, configuration, context, managedReferenceFactoryValue));
injectors.addFirst(injectionConfiguration.getTarget().createInjectionInterceptorFactory(instanceKey, valueContextKey, managedReferenceFactoryValue, context.getDeploymentUnit(), injectionConfiguration.isOptional()));
uninjectors.addLast(new ImmediateInterceptorFactory(new ManagedReferenceReleaseInterceptor(valueContextKey)));
}
}
protected boolean isNotOverriden(final Class<?> clazz, final Method method, final Class<?> actualClass, final DeploymentReflectionIndex deploymentReflectionIndex) throws DeploymentUnitProcessingException {
return Modifier.isPrivate(method.getModifiers()) || ClassReflectionIndexUtil.findRequiredMethod(deploymentReflectionIndex, actualClass, method).getDeclaringClass() == clazz;
}
}