}
final boolean dynamicBean = DynamicProxyImplFactory.isKnownDynamicallyImplemented(clazz);
final MetaAnnotatedClass<?> metaClass = new MetaAnnotatedClass(clazz);
final AnnotationFinder finder;
final AnnotationFinder annotationFinder;
if (ejbModule.getFinder() instanceof AnnotationFinder) {
final AnnotationFinder af = (AnnotationFinder) ejbModule.getFinder();
final List<Class<?>> ancestors = Classes.ancestors(clazz);
final String[] names = new String[ancestors.size()];
int i = 0;
for (final Class<?> ancestor : ancestors) {
names[i++] = ancestor.getName();
}
annotationFinder = af.select(names);
finder = af.select(clazz.getName());
} else {
if (!dynamicBean) {
annotationFinder = createFinder(clazz);
finder = new AnnotationFinder(new ClassesArchive(clazz));
} else {
final Class<?>[] classes;
final Proxy proxy = metaClass.getAnnotation(Proxy.class);
if (proxy == null) {
classes = new Class<?>[]{clazz};
} else {
classes = new Class<?>[]{clazz, proxy.value()};
}
annotationFinder = createFinder(classes);
finder = new AnnotationFinder(new ClassesArchive(classes));
}
}
/*
* @PostConstruct
* @PreDestroy
* @AroundInvoke
* @Timeout
* @PostActivate
* @PrePassivate
* @Init
* @Remove
* @AroundTimeout
* @AfterBegin
* @BeforeCompletion
* @AfterCompletion
*/
processCallbacks(bean, annotationFinder);
/*
* @TransactionManagement
*/
if (bean.getTransactionType() == null) {
final TransactionManagement tx = getInheritableAnnotation(clazz, TransactionManagement.class);
TransactionManagementType transactionType = TransactionManagementType.CONTAINER;
if (tx != null) {
transactionType = tx.value();
}
switch (transactionType) {
case BEAN:
bean.setTransactionType(TransactionType.BEAN);
break;
case CONTAINER:
bean.setTransactionType(TransactionType.CONTAINER);
break;
}
}
final AssemblyDescriptor assemblyDescriptor = ejbModule.getEjbJar().getAssemblyDescriptor();
/*
* @ApplicationException
*/
processApplicationExceptions(clazz, assemblyDescriptor);
/*
* TransactionAttribute
*/
if (bean.getTransactionType() == TransactionType.CONTAINER) {
processAttributes(new TransactionAttributeHandler(assemblyDescriptor, ejbName), clazz, annotationFinder);
} else {
checkAttributes(new TransactionAttributeHandler(assemblyDescriptor, ejbName), ejbName, ejbModule, finder, "invalidTransactionAttribute");
}
/*
* @RolesAllowed
* @PermitAll
* @DenyAll
* @RunAs
* @DeclareRoles
*/
processSecurityAnnotations(clazz, ejbName, ejbModule, annotationFinder, bean);
/*
* @Schedule
* @Schedules
*/
processSchedules(bean, annotationFinder);
/*
* Add any interceptors they may have referenced in xml but did not declare
*/
for (final InterceptorBinding binding : assemblyDescriptor.getInterceptorBinding()) {
final EjbJar ejbJar = ejbModule.getEjbJar();
final List<String> list = new ArrayList<String>(binding.getInterceptorClass());
if (binding.getInterceptorOrder() != null) {
list.clear();
list.addAll(binding.getInterceptorOrder().getInterceptorClass());
}
for (final String interceptor : list) {
if (ejbJar.getInterceptor(interceptor) == null) {
logger.debug("Adding '<ejb-jar><interceptors><interceptor>' entry for undeclared interceptor " + interceptor);
ejbJar.addInterceptor(new Interceptor(interceptor));
}
}
}
/*
* @Interceptors
*/
final List<Annotated<Class<?>>> annotatedClasses = sortClasses(annotationFinder.findMetaAnnotatedClasses(Interceptors.class));
for (final Annotated<Class<?>> interceptorsAnnotatedClass : annotatedClasses) {
final Interceptors interceptors = interceptorsAnnotatedClass.getAnnotation(Interceptors.class);
final EjbJar ejbJar = ejbModule.getEjbJar();
for (final Class interceptor : interceptors.value()) {
if (ejbJar.getInterceptor(interceptor.getName()) == null) {
ejbJar.addInterceptor(new Interceptor(interceptor.getName()));
}
}
final InterceptorBinding binding = new InterceptorBinding(bean);
assemblyDescriptor.getInterceptorBinding().add(0, binding);
for (final Class interceptor : interceptors.value()) {
binding.getInterceptorClass().add(interceptor.getName());
}
}
final List<Annotated<Method>> annotatedMethods = sortMethods(annotationFinder.findMetaAnnotatedMethods(Interceptors.class));
for (final Annotated<Method> method : annotatedMethods) {
final Interceptors interceptors = method.getAnnotation(Interceptors.class);
if (interceptors != null) {
final EjbJar ejbJar = ejbModule.getEjbJar();
for (final Class interceptor : interceptors.value()) {
if (ejbJar.getInterceptor(interceptor.getName()) == null) {
ejbJar.addInterceptor(new Interceptor(interceptor.getName()));
}
}
final InterceptorBinding binding = new InterceptorBinding(bean);
assemblyDescriptor.getInterceptorBinding().add(0, binding);
for (final Class interceptor : interceptors.value()) {
binding.getInterceptorClass().add(interceptor.getName());
}
binding.setMethod(new NamedMethod(method.get()));
}
}
/*
* @ExcludeDefaultInterceptors
*/
final ExcludeDefaultInterceptors excludeDefaultInterceptors = clazz.getAnnotation(ExcludeDefaultInterceptors.class);
if (excludeDefaultInterceptors != null) {
final InterceptorBinding binding = assemblyDescriptor.addInterceptorBinding(new InterceptorBinding(bean));
binding.setExcludeDefaultInterceptors(true);
}
for (final Annotated<Method> method : annotationFinder.findMetaAnnotatedMethods(ExcludeDefaultInterceptors.class)) {
final InterceptorBinding binding = assemblyDescriptor.addInterceptorBinding(new InterceptorBinding(bean));
binding.setExcludeDefaultInterceptors(true);
binding.setMethod(new NamedMethod(method.get()));
}
for (final Annotated<Method> method : sortMethods(annotationFinder.findMetaAnnotatedMethods(ExcludeClassInterceptors.class))) {
final InterceptorBinding binding = assemblyDescriptor.addInterceptorBinding(new InterceptorBinding(bean));
binding.setExcludeClassInterceptors(true);
binding.setMethod(new NamedMethod(method.get()));
}
/**
* All beans except MDBs have remoting capabilities (busines or legacy interfaces)
*/
if (bean instanceof RemoteBean) {
final RemoteBean remoteBean = (RemoteBean) bean;
/*
* @RemoteHome
*/
if (remoteBean.getHome() == null) {
final RemoteHome remoteHome = getInheritableAnnotation(clazz, RemoteHome.class);
if (remoteHome != null) {
final Class<?> homeClass = remoteHome.value();
try {
Method create = null;
for (final Method method : homeClass.getMethods()) {
if (method.getName().startsWith("create")) {
create = method;
break;
}
}
if (create == null) {
throw new NoSuchMethodException("create");
}
final Class<?> remoteClass = create.getReturnType();
remoteBean.setHome(homeClass.getName());
remoteBean.setRemote(remoteClass.getName());
} catch (final NoSuchMethodException e) {
logger.error("Class annotated as a RemoteHome has no 'create()' method. Unable to determine remote interface type. Bean class: " + clazz.getName() + ", Home class: " + homeClass.getName());
}
}
}
/*
* @LocalHome
*/
if (remoteBean.getLocalHome() == null) {
final LocalHome localHome = getInheritableAnnotation(clazz, LocalHome.class);
if (localHome != null) {
final Class<?> homeClass = localHome.value();
try {
Method create = null;
for (final Method method : homeClass.getMethods()) {
if (method.getName().startsWith("create")) {
create = method;
break;
}
}
if (create == null) {
throw new NoSuchMethodException("create");
}
final Class<?> remoteClass = create.getReturnType();
remoteBean.setLocalHome(homeClass.getName());
remoteBean.setLocal(remoteClass.getName());
} catch (final NoSuchMethodException e) {
logger.error("Class annotated as a LocalHome has no 'create()' method. Unable to determine remote interface type. Bean class: " + clazz.getName() + ", Home class: " + homeClass.getName());
}
}
}
/*
* Annotations specific to @Stateless, @Stateful and @Singleton beans
*/
if (remoteBean instanceof SessionBean) {
final SessionBean sessionBean = (SessionBean) remoteBean;
// add parents
sessionBean.getParents().add(clazz.getName());
if (!clazz.isInterface()) {
for (Class<?> current = clazz.getSuperclass(); !current.equals(Object.class); current = current.getSuperclass()) {
sessionBean.getParents().add(current.getName());
}
}
/*
* @Remote
* @Local
* @WebService
* @WebServiceProvider
*/
processSessionInterfaces(sessionBean, clazz, ejbModule);
/*
* @Asynchronous
*/
processAsynchronous(bean, annotationFinder);
/*
* Allow for all session bean types
* @DependsOn
*/
if (sessionBean.getDependsOn() == null) {
final DependsOn dependsOn = getInheritableAnnotation(clazz, DependsOn.class);
if (dependsOn != null) {
sessionBean.setDependsOn(dependsOn.value());
} else {
sessionBean.setDependsOn(Collections.EMPTY_LIST);
}
}
/**
* Annotations for singletons and stateless
*/
if (sessionBean.getSessionType() != SessionType.STATEFUL) {
// REST can be fun
if (annotationFinder.isAnnotationPresent(Path.class)) {
sessionBean.setRestService(true);
}
}
/*
* Annotations specific to @Singleton beans
*/
if (sessionBean.getSessionType() == SessionType.SINGLETON) {
/*
* @ConcurrencyManagement
*/
if (sessionBean.getConcurrencyManagementType() == null) {
final ConcurrencyManagement tx = getInheritableAnnotation(clazz, ConcurrencyManagement.class);
javax.ejb.ConcurrencyManagementType concurrencyType = javax.ejb.ConcurrencyManagementType.CONTAINER;
if (tx != null) {
concurrencyType = tx.value();
}
switch (concurrencyType) {
case BEAN:
sessionBean.setConcurrencyManagementType(ConcurrencyManagementType.BEAN);
break;
case CONTAINER:
sessionBean.setConcurrencyManagementType(ConcurrencyManagementType.CONTAINER);
break;
}
}
/*
* @Lock
*/
final LockHandler lockHandler = new LockHandler(assemblyDescriptor, sessionBean);
if (sessionBean.getConcurrencyManagementType() == ConcurrencyManagementType.CONTAINER) {
processAttributes(lockHandler, clazz, annotationFinder);
} else {
checkAttributes(lockHandler, ejbName, ejbModule, annotationFinder, "invalidConcurrencyAttribute");
}
/*
* @AccessTimeout
*/
final AccessTimeoutHandler accessTimeoutHandler =
new AccessTimeoutHandler(assemblyDescriptor, sessionBean, lockHandler.getContainerConcurrency());
processAttributes(accessTimeoutHandler, clazz, annotationFinder);
/*
* @Startup
*/
if (!sessionBean.hasInitOnStartup()) {
final Startup startup = getInheritableAnnotation(clazz, Startup.class);
sessionBean.setInitOnStartup(startup != null);
}
} else if (sessionBean.getSessionType() == SessionType.STATEFUL) {
/*
* Annotations specific to @Stateful beans
*/
/*
* @StatefulTimeout
*/
if (sessionBean.getStatefulTimeout() == null) {
final StatefulTimeout annotation = getInheritableAnnotation(clazz, StatefulTimeout.class);
if (annotation != null) {
final Timeout timeout = new Timeout();
timeout.setTimeout(annotation.value());
timeout.setUnit(annotation.unit());
sessionBean.setStatefulTimeout(timeout);
}
}
/*
* @AccessTimeout
*/
final AccessTimeoutHandler accessTimeoutHandler = new AccessTimeoutHandler(assemblyDescriptor, sessionBean);
processAttributes(accessTimeoutHandler, clazz, annotationFinder);
}
}
}
if (bean instanceof MessageDrivenBean) {
/*
* @ActivationConfigProperty
*/
final MessageDrivenBean mdb = (MessageDrivenBean) bean;
final MessageDriven messageDriven = clazz.getAnnotation(MessageDriven.class);
if (messageDriven != null) {
ActivationConfig activationConfig = mdb.getActivationConfig();
if (activationConfig == null) {
activationConfig = new ActivationConfig();
}
if (!messageDriven.mappedName().isEmpty()) {
if (mdb.getActivationConfig() == null) {
mdb.setActivationConfig(activationConfig);
}
if (!activationConfig.toProperties().containsKey("destinationType")) {
activationConfig.addProperty("destinationType", Queue.class.getName());
}
activationConfig.addProperty("destination", messageDriven.mappedName());
}
final ActivationConfigProperty[] configProperties = messageDriven.activationConfig();
if (configProperties != null) {
if (mdb.getActivationConfig() == null) {
mdb.setActivationConfig(activationConfig);
}
final Properties properties = activationConfig.toProperties();
for (final ActivationConfigProperty property : configProperties) {
if (!properties.containsKey(property.propertyName())) {
activationConfig.addProperty(property.propertyName(), property.propertyValue());
}
}
}
if (mdb.getMessagingType() == null) {
final Class<?> interfce = messageDriven.messageListenerInterface();
if (interfce != null && !interfce.equals(Object.class)) {
if (!interfce.isInterface()) {
// TODO: Move this check to o.a.o.c.rules.CheckClasses and do it for all MDBs, annotated or not
throw new OpenEJBException("MessageListenerInterface property of @MessageDriven is not an interface");
}
mdb.setMessagingType(interfce.getName());
}
}
}
/*
* Determine the MessageListener interface
*/
if (mdb.getMessagingType() == null) {
final List<Class<?>> interfaces = new ArrayList<Class<?>>();
for (final Class<?> intf : clazz.getInterfaces()) {
final String name = intf.getName();
if (!name.equals("java.io.Serializable") &&
!name.equals("java.io.Externalizable") &&
!name.startsWith("javax.ejb.") &&
!intf.isSynthetic()) {
interfaces.add(intf);
}
}
if (interfaces.size() != 1) {
String msg = "When annotating a bean class as @MessageDriven without declaring messageListenerInterface, the bean must implement exactly one interface, no more and no less. beanClass=" + clazz.getName() + " interfaces=";
for (final Class<?> intf : interfaces) {
msg += intf.getName() + ", ";
}
// TODO: Make this a validation failure, not an exception
throw new IllegalStateException(msg);
}
mdb.setMessagingType(interfaces.get(0).getName());
}
}
buildAnnotatedRefs(bean, annotationFinder, classLoader);
processWebServiceHandlers(ejbModule, bean);
processWebServiceClientHandlers(bean, classLoader);
try {
if (BeanContext.Comp.class.getName().equals(bean.getEjbClass())) {
buildAnnotatedRefs(bean, ejbModule.getFinder(), classLoader);
}
} catch (final OpenEJBException e) {
logger.error("Processing of @Resource, @EJB, and other references failed for CDI managed beans", e);
}
}
for (final Interceptor interceptor : ejbModule.getEjbJar().getInterceptors()) {
final Class<?> clazz;
try {
clazz = classLoader.loadClass(realClassName(interceptor.getInterceptorClass()));
} catch (final ClassNotFoundException e) {
throw new OpenEJBException("Unable to load interceptor class: " + interceptor.getInterceptorClass(), e);
}
final AnnotationFinder annotationFinder = createFinder(clazz);
/*
* @PostConstruct
* @PreDestroy
* @AroundInvoke