/*
* JBoss, Home of Professional Open Source
* Copyright 2015, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.weld.module.ejb;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Set;
import javax.ejb.Timeout;
import javax.enterprise.inject.spi.BeanAttributes;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType;
import org.jboss.weld.annotated.slim.SlimAnnotatedType;
import org.jboss.weld.annotated.slim.SlimAnnotatedTypeStore;
import org.jboss.weld.bean.SessionBean;
import org.jboss.weld.bean.interceptor.InterceptorBindingsAdapter;
import org.jboss.weld.bootstrap.BeanDeployerEnvironment;
import org.jboss.weld.ejb.spi.EjbDescriptor;
import org.jboss.weld.ejb.spi.EjbServices;
import org.jboss.weld.injection.producer.AbstractInstantiator;
import org.jboss.weld.injection.producer.BasicInjectionTarget;
import org.jboss.weld.injection.producer.DefaultInstantiator;
import org.jboss.weld.injection.producer.InterceptionModelInitializer;
import org.jboss.weld.injection.producer.SubclassedComponentInstantiator;
import org.jboss.weld.interceptor.spi.model.InterceptionModel;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.module.EjbSupport;
import org.jboss.weld.resources.ClassTransformer;
import org.jboss.weld.util.Beans;
import org.jboss.weld.util.Preconditions;
import org.jboss.weld.util.collections.SetMultimap;
import org.jboss.weld.util.reflection.Reflections;
class EjbSupportImpl implements EjbSupport {
private final EjbServices ejbServices;
private final EjbDescriptors ejbDescriptors;
EjbSupportImpl(EjbServices ejbServices, Collection<EjbDescriptor<?>> descriptors) {
this.ejbServices = ejbServices;
this.ejbDescriptors = new EjbDescriptors(descriptors);
}
@Override
public void cleanup() {
}
@Override
public <T> BasicInjectionTarget<T> createSessionBeanInjectionTarget(EnhancedAnnotatedType<T> type, SessionBean<T> bean, BeanManagerImpl beanManager) {
return SessionBeanInjectionTarget.of(type, bean, beanManager);
}
@Override
public <T> BasicInjectionTarget<T> createMessageDrivenInjectionTarget(EnhancedAnnotatedType<T> type, EjbDescriptor<T> d, BeanManagerImpl manager) {
InternalEjbDescriptor<T> descriptor = InternalEjbDescriptor.of(d);
EnhancedAnnotatedType<T> implementationClass = SessionBeans.getEjbImplementationClass(descriptor, manager, type);
AbstractInstantiator<T> instantiator = null;
if (type.equals(implementationClass)) {
instantiator = new DefaultInstantiator<T>(type, null, manager);
} else {
// Session bean subclassed by the EJB container
instantiator = SubclassedComponentInstantiator.forSubclassedEjb(type, implementationClass, null, manager);
}
return BasicInjectionTarget.createDefault(type, null, manager, instantiator);
}
@Override
public <T> BeanAttributes<T> createSessionBeanAttributes(EnhancedAnnotatedType<T> annotated, BeanManagerImpl manager) {
final InternalEjbDescriptor<?> descriptor = ejbDescriptors.getUnique(annotated.getJavaClass());
Preconditions.checkArgument(descriptor != null, annotated.getJavaClass() + " is not an EJB.");
return createSessionBeanAttributes(annotated, descriptor, manager);
}
private <T> BeanAttributes<T> createSessionBeanAttributes(EnhancedAnnotatedType<T> annotated, InternalEjbDescriptor<?> descriptor, BeanManagerImpl manager) {
return SessionBeans.createBeanAttributes(annotated, descriptor, manager);
}
@Override
public void createSessionBeans(BeanDeployerEnvironment environment, SetMultimap<Class<?>, SlimAnnotatedType<?>> types, BeanManagerImpl manager) {
final ClassTransformer transformer = manager.getServices().get(ClassTransformer.class);
for (InternalEjbDescriptor<?> ejbDescriptor : getEjbDescriptors()) {
if (environment.isVetoed(ejbDescriptor.getBeanClass()) || Beans.isVetoed(ejbDescriptor.getBeanClass())) {
continue;
}
if (ejbDescriptor.isSingleton() || ejbDescriptor.isStateful() || ejbDescriptor.isStateless()) {
Set<SlimAnnotatedType<?>> classes = types.get(ejbDescriptor.getBeanClass());
if (!classes.isEmpty()) {
for (SlimAnnotatedType<?> annotatedType : classes) {
createSessionBean(ejbDescriptor, annotatedType, environment, manager, transformer);
}
} else {
createSessionBean(ejbDescriptor, environment, manager, transformer);
}
}
}
}
private <T> SessionBean<T> createSessionBean(InternalEjbDescriptor<?> descriptor, SlimAnnotatedType<T> slimType, BeanDeployerEnvironment environment, BeanManagerImpl manager, ClassTransformer transformer) {
final EnhancedAnnotatedType<T> type = transformer.getEnhancedAnnotatedType(slimType);
final BeanAttributes<T> attributes = createSessionBeanAttributes(type, descriptor, manager);
final SessionBean<T> bean = SessionBeanImpl.of(attributes, Reflections.<InternalEjbDescriptor<T>>cast(descriptor), manager, type);
environment.addSessionBean(bean);
return bean;
}
protected <T> SessionBean<T> createSessionBean(InternalEjbDescriptor<T> descriptor, BeanDeployerEnvironment environment, BeanManagerImpl manager, ClassTransformer transformer) {
final SlimAnnotatedType<T> type = transformer.getBackedAnnotatedType(descriptor.getBeanClass(), manager.getId());
manager.getServices().get(SlimAnnotatedTypeStore.class).put(type);
return createSessionBean(descriptor, type, environment, manager, transformer);
}
@Override
public void createNewSessionBeans(BeanDeployerEnvironment environment, BeanManagerImpl manager) {
final SlimAnnotatedTypeStore store = manager.getServices().get(SlimAnnotatedTypeStore.class);
final ClassTransformer classTransformer = manager.getServices().get(ClassTransformer.class);
for (Type type : environment.getNewBeanTypes()) {
Class<?> clazz = Reflections.getRawType(type);
if (isEjb(clazz)) {
EnhancedAnnotatedType<?> enhancedType = classTransformer.getEnhancedAnnotatedType(clazz, type, manager.getId());
InternalEjbDescriptor<?> descriptor = ejbDescriptors.getUnique(clazz);
environment.addSessionBean(createNewSessionBean(enhancedType, descriptor, manager, store));
}
}
}
private <T> SessionBean<T> createNewSessionBean(EnhancedAnnotatedType<?> type, InternalEjbDescriptor<T> ejbDescriptor, BeanManagerImpl beanManager, SlimAnnotatedTypeStore store) {
store.put(type.slim());
final BeanAttributes<T> attributes = Reflections.cast(SessionBeans.createBeanAttributesForNew(type, ejbDescriptor, beanManager, type.getJavaClass()));
return NewSessionBean.of(attributes, ejbDescriptor, beanManager);
}
@Override
public Class<? extends Annotation> getTimeoutAnnotation() {
return Timeout.class;
}
public void registerCdiInterceptorsForMessageDrivenBeans(BeanDeployerEnvironment environment, BeanManagerImpl manager) {
for (InternalEjbDescriptor<?> descriptor : getEjbDescriptors()) {
if (descriptor.isMessageDriven()) {
EnhancedAnnotatedType<?> type = manager.getServices().getRequired(ClassTransformer.class).getEnhancedAnnotatedType(descriptor.getBeanClass(), manager.getId());
if (!manager.getInterceptorModelRegistry().containsKey(type.slim())) {
InterceptionModelInitializer.of(manager, type, null).init();
}
InterceptionModel model = manager.getInterceptorModelRegistry().get(type.slim());
if (model != null) {
ejbServices.registerInterceptors(descriptor.delegate(), new InterceptorBindingsAdapter(model));
}
}
}
}
@Override
public Collection<InternalEjbDescriptor<?>> getEjbDescriptors() {
return ejbDescriptors.getAll();
}
@Override
public boolean isEjb(Class<?> beanClass) {
return ejbDescriptors.contains(beanClass);
}
@Override
public <T> InternalEjbDescriptor<T> getEjbDescriptor(String beanName) {
return ejbDescriptors.get(beanName);
}
@Override
public boolean isSessionBeanProxy(Object instance) {
return instance instanceof EnterpriseBeanInstance;
}
}