public void configure(final DeploymentPhaseContext context, final ComponentDescription description, final ComponentConfiguration configuration) throws DeploymentUnitProcessingException {
final DeploymentUnit deploymentUnit = context.getDeploymentUnit();
final DeploymentReflectionIndex deploymentReflectionIndex = deploymentUnit.getAttachment(REFLECTION_INDEX);
final Object instanceKey = BasicComponentInstance.INSTANCE_KEY;
final Module module = deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.MODULE);
final EEApplicationClasses applicationClasses = deploymentUnit.getAttachment(Attachments.EE_APPLICATION_CLASSES_DESCRIPTION);
final EEModuleDescription moduleDescription = deploymentUnit.getAttachment(Attachments.EE_MODULE_DESCRIPTION);
final ProxyMetadataSource proxyReflectionIndex = deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.PROXY_REFLECTION_INDEX);
final DeploymentClassIndex classIndex = deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.CLASS_INDEX);
final boolean metadataComplete = MetadataCompleteMarker.isMetadataComplete(deploymentUnit);
// Module stuff
final Deque<InterceptorFactory> instantiators = new ArrayDeque<InterceptorFactory>();
final Deque<InterceptorFactory> injectors = new ArrayDeque<InterceptorFactory>();
final Deque<InterceptorFactory> uninjectors = new ArrayDeque<InterceptorFactory>();
final Deque<InterceptorFactory> destructors = new ArrayDeque<InterceptorFactory>();
final ClassReflectionIndex<?> componentClassIndex = deploymentReflectionIndex.getClassIndex(configuration.getComponentClass());
final List<InterceptorFactory> componentUserAroundInvoke = new ArrayList<InterceptorFactory>();
final List<InterceptorFactory> componentUserAroundTimeout;
final Map<String, List<InterceptorFactory>> userAroundInvokesByInterceptorClass = new HashMap<String, List<InterceptorFactory>>();
final Map<String, List<InterceptorFactory>> userAroundTimeoutsByInterceptorClass;
final Map<String, List<InterceptorFactory>> userPrePassivatesByInterceptorClass;
final Map<String, List<InterceptorFactory>> userPostActivatesByInterceptorClass;
final Map<String, List<InterceptorFactory>> userPostConstructByInterceptorClass = new HashMap<String, List<InterceptorFactory>>();
final Map<String, List<InterceptorFactory>> userPreDestroyByInterceptorClass = new HashMap<String, List<InterceptorFactory>>();
if (description.isTimerServiceApplicable()) {
componentUserAroundTimeout = new ArrayList<InterceptorFactory>();
userAroundTimeoutsByInterceptorClass = new HashMap<String, List<InterceptorFactory>>();
} else {
componentUserAroundTimeout = null;
userAroundTimeoutsByInterceptorClass = null;
}
if (description.isPassivationApplicable()) {
userPrePassivatesByInterceptorClass = new HashMap<String, List<InterceptorFactory>>();
userPostActivatesByInterceptorClass = new HashMap<String, List<InterceptorFactory>>();
} else {
userPrePassivatesByInterceptorClass = null;
userPostActivatesByInterceptorClass = null;
}
// Primary instance
final ManagedReferenceFactory instanceFactory = configuration.getInstanceFactory();
if (instanceFactory != null) {
instantiators.addFirst(new ManagedReferenceInterceptorFactory(instanceFactory, instanceKey));
} else {
//use the default constructor if no instanceFactory has been set
final Constructor<Object> constructor = (Constructor<Object>) componentClassIndex.getConstructor(EMPTY_CLASS_ARRAY);
if (constructor == null) {
throw MESSAGES.defaultConstructorNotFound(configuration.getComponentClass());
}
ValueManagedReferenceFactory factory = new ValueManagedReferenceFactory(new ConstructedValue<Object>(constructor, Collections.<Value<?>>emptyList()));
instantiators.addFirst(new ManagedReferenceInterceptorFactory(factory, instanceKey));
}
destructors.addLast(new ManagedReferenceReleaseInterceptorFactory(instanceKey));
new ClassDescriptionTraversal(configuration.getComponentClass(), applicationClasses) {
@Override
public void handle(Class<?> clazz, EEModuleClassDescription classDescription) throws DeploymentUnitProcessingException {
mergeInjectionsForClass(clazz, classDescription, moduleDescription, description, configuration, context, injectors, instanceKey, uninjectors, metadataComplete);
}
}.run();
//all interceptors with lifecycle callbacks, in the correct order
final List<InterceptorDescription> interceptorWithLifecycleCallbacks = new ArrayList<InterceptorDescription>();
if (!description.isExcludeDefaultInterceptors()) {
interceptorWithLifecycleCallbacks.addAll(description.getDefaultInterceptors());
}
interceptorWithLifecycleCallbacks.addAll(description.getClassInterceptors());
for (final InterceptorDescription interceptorDescription : description.getAllInterceptors()) {
final String interceptorClassName = interceptorDescription.getInterceptorClassName();
final ClassIndex interceptorClass;
try {
interceptorClass = classIndex.classIndex(interceptorClassName);
} catch (ClassNotFoundException e) {
throw MESSAGES.cannotLoadInterceptor(e, interceptorClassName);
}
final InterceptorEnvironment interceptorEnvironment = moduleDescription.getInterceptorEnvironment().get(interceptorClassName);
if (interceptorEnvironment != null) {
//if the interceptor has environment config we merge it into the components environment
description.getBindingConfigurations().addAll(interceptorEnvironment.getBindingConfigurations());
for (final ResourceInjectionConfiguration injection : interceptorEnvironment.getResourceInjections()) {
description.addResourceInjection(injection);
}
}
//we store the interceptor instance under the class key
final Object contextKey = interceptorClass.getModuleClass();
configuration.getInterceptorContextKeys().add(contextKey);
final ClassReflectionIndex<?> interceptorIndex = deploymentReflectionIndex.getClassIndex(interceptorClass.getModuleClass());
final Constructor<?> constructor = interceptorIndex.getConstructor(EMPTY_CLASS_ARRAY);
if (constructor == null) {
throw MESSAGES.defaultConstructorNotFoundOnComponent(interceptorClassName, configuration.getComponentClass());
}
instantiators.addFirst(new ManagedReferenceInterceptorFactory(new ValueManagedReferenceFactory(new ConstructedValue(constructor, Collections.<Value<?>>emptyList())), contextKey));
destructors.addLast(new ManagedReferenceReleaseInterceptorFactory(contextKey));
final boolean interceptorHasLifecycleCallbacks = interceptorWithLifecycleCallbacks.contains(interceptorDescription);
new ClassDescriptionTraversal(interceptorClass.getModuleClass(), applicationClasses) {
@Override
public void handle(final Class<?> clazz, EEModuleClassDescription classDescription) throws DeploymentUnitProcessingException {
mergeInjectionsForClass(clazz, classDescription, moduleDescription, description, configuration, context, injectors, contextKey, uninjectors, metadataComplete);
final InterceptorClassDescription interceptorConfig;
if (classDescription != null && !metadataComplete) {
interceptorConfig = InterceptorClassDescription.merge(classDescription.getInterceptorClassDescription(), moduleDescription.getInterceptorClassOverride(clazz.getName()));
} else {
interceptorConfig = InterceptorClassDescription.merge(null, moduleDescription.getInterceptorClassOverride(clazz.getName()));
}
// Only class level interceptors are processed for postconstruct/predestroy methods.
// Method level interceptors aren't supposed to be processed for postconstruct/predestroy lifecycle
// methods, as per interceptors spec
if (interceptorHasLifecycleCallbacks) {
final MethodIdentifier postConstructMethodIdentifier = interceptorConfig.getPostConstruct();
handleInterceptorClass(clazz, postConstructMethodIdentifier, userPostConstructByInterceptorClass, true, true);
final MethodIdentifier preDestroyMethodIdentifier = interceptorConfig.getPreDestroy();
handleInterceptorClass(clazz, preDestroyMethodIdentifier, userPreDestroyByInterceptorClass, true, true);
}
final MethodIdentifier aroundInvokeMethodIdentifier = interceptorConfig.getAroundInvoke();
handleInterceptorClass(clazz, aroundInvokeMethodIdentifier, userAroundInvokesByInterceptorClass, false, false);
if (description.isTimerServiceApplicable()) {
final MethodIdentifier aroundTimeoutMethodIdentifier = interceptorConfig.getAroundTimeout();
handleInterceptorClass(clazz, aroundTimeoutMethodIdentifier, userAroundTimeoutsByInterceptorClass, false, false);
}
if (description.isPassivationApplicable()) {
handleInterceptorClass(clazz, interceptorConfig.getPrePassivate(), userPrePassivatesByInterceptorClass, false, false);
handleInterceptorClass(clazz, interceptorConfig.getPostActivate(), userPostActivatesByInterceptorClass, false, false);
}
}
private void handleInterceptorClass(final Class<?> clazz, final MethodIdentifier methodIdentifier, final Map<String, List<InterceptorFactory>> classMap, final boolean changeMethod, final boolean lifecycleMethod) throws DeploymentUnitProcessingException {
if (methodIdentifier != null) {
final Method method = ClassReflectionIndexUtil.findRequiredMethod(deploymentReflectionIndex, clazz, methodIdentifier);
if (isNotOverriden(clazz, method, interceptorClass.getModuleClass(), deploymentReflectionIndex)) {
final InterceptorFactory interceptorFactory = new ManagedReferenceLifecycleMethodInterceptorFactory(contextKey, method, changeMethod, lifecycleMethod);
List<InterceptorFactory> factories = classMap.get(interceptorClassName);
if (factories == null) {
classMap.put(interceptorClassName, factories = new ArrayList<InterceptorFactory>());
}
factories.add(interceptorFactory);
}
}
}
}.run();
}
final List<InterceptorFactory> userPostConstruct = new ArrayList<InterceptorFactory>();
final List<InterceptorFactory> userPreDestroy = new ArrayList<InterceptorFactory>();
final List<InterceptorFactory> userPrePassivate = new ArrayList<InterceptorFactory>();
final List<InterceptorFactory> userPostActivate = new ArrayList<InterceptorFactory>();
//now add the lifecycle interceptors in the correct order
for (final InterceptorDescription interceptorClass : interceptorWithLifecycleCallbacks) {
if (userPostConstructByInterceptorClass.containsKey(interceptorClass.getInterceptorClassName())) {
userPostConstruct.addAll(userPostConstructByInterceptorClass.get(interceptorClass.getInterceptorClassName()));
}
if (userPreDestroyByInterceptorClass.containsKey(interceptorClass.getInterceptorClassName())) {
userPreDestroy.addAll(userPreDestroyByInterceptorClass.get(interceptorClass.getInterceptorClassName()));
}
if (description.isPassivationApplicable()) {
if (userPrePassivatesByInterceptorClass.containsKey(interceptorClass.getInterceptorClassName())) {
userPrePassivate.addAll(userPrePassivatesByInterceptorClass.get(interceptorClass.getInterceptorClassName()));
}
if (userPostActivatesByInterceptorClass.containsKey(interceptorClass.getInterceptorClassName())) {
userPostActivate.addAll(userPostActivatesByInterceptorClass.get(interceptorClass.getInterceptorClassName()));
}
}
}
new ClassDescriptionTraversal(configuration.getComponentClass(), applicationClasses) {
@Override
public void handle(final Class<?> clazz, EEModuleClassDescription classDescription) throws DeploymentUnitProcessingException {
final InterceptorClassDescription interceptorConfig = mergeInterceptorConfig(clazz, classDescription, description, metadataComplete);
handleClassMethod(clazz, interceptorConfig.getPostConstruct(), userPostConstruct, true, true);
handleClassMethod(clazz, interceptorConfig.getPreDestroy(), userPreDestroy, true, true);
handleClassMethod(clazz, interceptorConfig.getAroundInvoke(), componentUserAroundInvoke, false, false);
if (description.isTimerServiceApplicable()) {
handleClassMethod(clazz, interceptorConfig.getAroundTimeout(), componentUserAroundTimeout, false, false);
}
if (description.isPassivationApplicable()) {
handleClassMethod(clazz, interceptorConfig.getPrePassivate(), userPrePassivate, false, false);
handleClassMethod(clazz, interceptorConfig.getPostActivate(), userPostActivate, false, false);
}
}
private void handleClassMethod(final Class<?> clazz, final MethodIdentifier methodIdentifier, final List<InterceptorFactory> interceptors, boolean changeMethod, boolean lifecycleMethod) throws DeploymentUnitProcessingException {
if (methodIdentifier != null) {
final Method method = ClassReflectionIndexUtil.findRequiredMethod(deploymentReflectionIndex, clazz, methodIdentifier);
if (isNotOverriden(clazz, method, componentClassIndex.getIndexedClass(), deploymentReflectionIndex)) {
InterceptorFactory interceptorFactory = new ManagedReferenceLifecycleMethodInterceptorFactory(instanceKey, method, changeMethod, lifecycleMethod);
interceptors.add(interceptorFactory);
}
}
}
}.run();
final InterceptorFactory tcclInterceptor = new ImmediateInterceptorFactory(new TCCLInterceptor(module.getClassLoader()));
// Apply post-construct
if (!injectors.isEmpty()) {
configuration.addPostConstructInterceptor(weaved(injectors), InterceptorOrder.ComponentPostConstruct.RESOURCE_INJECTION_INTERCEPTORS);
}
if (!instantiators.isEmpty()) {
configuration.addPostConstructInterceptor(weaved(instantiators), InterceptorOrder.ComponentPostConstruct.INSTANTIATION_INTERCEPTORS);
}
if (!userPostConstruct.isEmpty()) {
configuration.addPostConstructInterceptor(weaved(userPostConstruct), InterceptorOrder.ComponentPostConstruct.USER_INTERCEPTORS);
}
configuration.addPostConstructInterceptor(Interceptors.getTerminalInterceptorFactory(), InterceptorOrder.ComponentPostConstruct.TERMINAL_INTERCEPTOR);
configuration.addPostConstructInterceptor(tcclInterceptor, InterceptorOrder.ComponentPostConstruct.TCCL_INTERCEPTOR);
// Apply pre-destroy
if (!uninjectors.isEmpty()) {
configuration.addPreDestroyInterceptor(weaved(uninjectors), InterceptorOrder.ComponentPreDestroy.UNINJECTION_INTERCEPTORS);
}
if (!destructors.isEmpty()) {
configuration.addPreDestroyInterceptor(weaved(destructors), InterceptorOrder.ComponentPreDestroy.DESTRUCTION_INTERCEPTORS);
}
if (!userPreDestroy.isEmpty()) {
configuration.addPreDestroyInterceptor(weaved(userPreDestroy), InterceptorOrder.ComponentPreDestroy.USER_INTERCEPTORS);
}
configuration.addPreDestroyInterceptor(Interceptors.getTerminalInterceptorFactory(), InterceptorOrder.ComponentPreDestroy.TERMINAL_INTERCEPTOR);
configuration.addPreDestroyInterceptor(tcclInterceptor, InterceptorOrder.ComponentPreDestroy.TCCL_INTERCEPTOR);
if (description.isPassivationApplicable()) {
if (!userPrePassivate.isEmpty()) {
configuration.addPrePassivateInterceptor(weaved(userPrePassivate), InterceptorOrder.ComponentPassivation.USER_INTERCEPTORS);
}
configuration.addPrePassivateInterceptor(Interceptors.getTerminalInterceptorFactory(), InterceptorOrder.ComponentPassivation.TERMINAL_INTERCEPTOR);
configuration.addPrePassivateInterceptor(tcclInterceptor, InterceptorOrder.ComponentPassivation.TCCL_INTERCEPTOR);
if (!userPostActivate.isEmpty()) {
configuration.addPostActivateInterceptor(weaved(userPostActivate), InterceptorOrder.ComponentPassivation.USER_INTERCEPTORS);
}
configuration.addPostActivateInterceptor(Interceptors.getTerminalInterceptorFactory(), InterceptorOrder.ComponentPassivation.TERMINAL_INTERCEPTOR);
configuration.addPostActivateInterceptor(tcclInterceptor, InterceptorOrder.ComponentPassivation.TCCL_INTERCEPTOR);
}
// @AroundInvoke interceptors
final List<InterceptorDescription> classInterceptors = description.getClassInterceptors();
final Map<MethodIdentifier, List<InterceptorDescription>> methodInterceptors = description.getMethodInterceptors();
if (description.isIntercepted()) {
for (final Method method : configuration.getDefinedComponentMethods()) {
//now add the interceptor that initializes and the interceptor that actually invokes to the end of the interceptor chain
configuration.addComponentInterceptor(method, Interceptors.getInitialInterceptorFactory(), InterceptorOrder.Component.INITIAL_INTERCEPTOR);
configuration.addComponentInterceptor(method, new ManagedReferenceMethodInterceptorFactory(instanceKey, method), InterceptorOrder.Component.TERMINAL_INTERCEPTOR);
final MethodIdentifier identifier = MethodIdentifier.getIdentifier(method.getReturnType(), method.getName(), method.getParameterTypes());
final List<InterceptorFactory> userAroundInvokes = new ArrayList<InterceptorFactory>();
final List<InterceptorFactory> userAroundTimeouts = new ArrayList<InterceptorFactory>();
// first add the default interceptors (if not excluded) to the deque
if (!description.isExcludeDefaultInterceptors() && !description.isExcludeDefaultInterceptors(identifier)) {
for (InterceptorDescription interceptorDescription : description.getDefaultInterceptors()) {
String interceptorClassName = interceptorDescription.getInterceptorClassName();
List<InterceptorFactory> aroundInvokes = userAroundInvokesByInterceptorClass.get(interceptorClassName);
if (aroundInvokes != null) {
userAroundInvokes.addAll(aroundInvokes);
}
if (description.isTimerServiceApplicable()) {
List<InterceptorFactory> aroundTimeouts = userAroundTimeoutsByInterceptorClass.get(interceptorClassName);
if (aroundTimeouts != null) {
userAroundTimeouts.addAll(aroundTimeouts);
}
}
}
}
// now add class level interceptors (if not excluded) to the deque
if (!description.isExcludeClassInterceptors(identifier)) {
for (InterceptorDescription interceptorDescription : classInterceptors) {
String interceptorClassName = interceptorDescription.getInterceptorClassName();
List<InterceptorFactory> aroundInvokes = userAroundInvokesByInterceptorClass.get(interceptorClassName);
if (aroundInvokes != null) {
userAroundInvokes.addAll(aroundInvokes);
}
if (description.isTimerServiceApplicable()) {
List<InterceptorFactory> aroundTimeouts = userAroundTimeoutsByInterceptorClass.get(interceptorClassName);
if (aroundTimeouts != null) {
userAroundTimeouts.addAll(aroundTimeouts);
}
}
}
}
// now add method level interceptors for to the deque so that they are triggered after the class interceptors
List<InterceptorDescription> methodLevelInterceptors = methodInterceptors.get(identifier);
if (methodLevelInterceptors != null) {
for (InterceptorDescription methodLevelInterceptor : methodLevelInterceptors) {
String interceptorClassName = methodLevelInterceptor.getInterceptorClassName();
List<InterceptorFactory> aroundInvokes = userAroundInvokesByInterceptorClass.get(interceptorClassName);
if (aroundInvokes != null) {
userAroundInvokes.addAll(aroundInvokes);
}
if (description.isTimerServiceApplicable()) {
List<InterceptorFactory> aroundTimeouts = userAroundTimeoutsByInterceptorClass.get(interceptorClassName);
if (aroundTimeouts != null) {
userAroundTimeouts.addAll(aroundTimeouts);
}
}
}
}
// finally add the component level around invoke to the deque so that it's triggered last
userAroundInvokes.addAll(componentUserAroundInvoke);
if (componentUserAroundTimeout != null) {
userAroundTimeouts.addAll(componentUserAroundTimeout);
}
configuration.addComponentInterceptor(method, new UserInterceptorFactory(weaved(userAroundInvokes), weaved(userAroundTimeouts)), InterceptorOrder.Component.USER_INTERCEPTORS);
}
}
//views
for (ViewDescription view : description.getViews()) {
Class<?> viewClass;
try {
viewClass = module.getClassLoader().loadClass(view.getViewClassName());
} catch (ClassNotFoundException e) {
throw MESSAGES.cannotLoadViewClass(e, view.getViewClassName(), configuration);
}
final ViewConfiguration viewConfiguration;
final ProxyConfiguration proxyConfiguration = new ProxyConfiguration();
proxyConfiguration.setProxyName(viewClass.getName() + "$$$view" + PROXY_ID.incrementAndGet());
proxyConfiguration.setClassLoader(module.getClassLoader());
proxyConfiguration.setProtectionDomain(viewClass.getProtectionDomain());
proxyConfiguration.setMetadataSource(proxyReflectionIndex);
if (view.isSerializable()) {
proxyConfiguration.addAdditionalInterface(Serializable.class);
if (view.isUseWriteReplace()) {