com.caucho.ejb.session.AbstractSessionManager Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2018 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.ejb.session;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.SessionContext;
import javax.ejb.TimerService;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.Specializes;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.enterprise.inject.spi.SessionBeanType;
import com.caucho.config.ConfigException;
import com.caucho.config.gen.BeanGenerator;
import com.caucho.config.inject.BeanBuilder;
import com.caucho.config.inject.InjectManager;
import com.caucho.config.inject.ManagedBeanImpl;
import com.caucho.config.inject.OwnerCreationalContext;
import com.caucho.config.j2ee.BeanName;
import com.caucho.config.j2ee.BeanNameLiteral;
import com.caucho.config.reflect.AnnotatedMethodImpl;
import com.caucho.config.reflect.AnnotatedTypeUtil;
import com.caucho.config.reflect.BaseType;
import com.caucho.ejb.cfg.EjbLazyGenerator;
import com.caucho.ejb.inject.ProcessSessionBeanImpl;
import com.caucho.ejb.inject.SessionRegistrationBean;
import com.caucho.ejb.manager.EjbManager;
import com.caucho.ejb.server.AbstractEjbBeanManager;
import com.caucho.java.gen.JavaClassGenerator;
import com.caucho.loader.DynamicClassLoader;
import com.caucho.naming.Jndi;
import com.caucho.util.L10N;
/**
* Server container for a session bean.
*/
abstract public class AbstractSessionManager extends AbstractEjbBeanManager {
private static final L10N L = new L10N(AbstractSessionManager.class);
private final static Logger log
= Logger.getLogger(AbstractSessionManager.class.getName());
private EjbLazyGenerator _lazyGenerator;
private Class> _proxyImplClass;
private HashMap, AbstractSessionContext> _contextMap
= new HashMap, AbstractSessionContext>();
private InjectManager _injectManager;
private Bean _bean;
private String[] _declaredRoles;
public AbstractSessionManager(EjbManager manager,
String ejbName,
String moduleName,
AnnotatedType rawAnnType,
AnnotatedType annotatedType,
EjbLazyGenerator lazyGenerator)
{
super(manager, ejbName, moduleName, rawAnnType, annotatedType);
_lazyGenerator = lazyGenerator;
DeclareRoles declareRoles
= annotatedType.getJavaClass().getAnnotation(DeclareRoles.class);
RolesAllowed rolesAllowed
= annotatedType.getJavaClass().getAnnotation(RolesAllowed.class);
if (declareRoles != null && rolesAllowed != null) {
_declaredRoles = new String[declareRoles.value().length +
rolesAllowed.value().length];
System.arraycopy(declareRoles.value(), 0,
_declaredRoles, 0,
declareRoles.value().length);
System.arraycopy(rolesAllowed.value(), 0,
_declaredRoles, declareRoles.value().length,
rolesAllowed.value().length);
}
else if (declareRoles != null) {
_declaredRoles = declareRoles.value();
}
else if (rolesAllowed != null) {
_declaredRoles = rolesAllowed.value();
}
}
@Override
protected String getType()
{
return "session:";
}
@Override
public Bean getDeployBean()
{
return _bean;
}
public Class> getProxyImplClass()
{
return _proxyImplClass;
}
@Override
public InjectManager getInjectManager()
{
return _injectManager;
}
protected EjbLazyGenerator getLazyGenerator()
{
return _lazyGenerator;
}
@Override
public ArrayList> getLocalApi()
{
return _lazyGenerator.getLocalApi();
}
@Override
public ArrayList> getRemoteApi()
{
return _lazyGenerator.getRemoteApi();
}
@Override
public AnnotatedType getLocalBean()
{
return _lazyGenerator.getLocalBean();
}
@SuppressWarnings("unchecked")
protected AbstractSessionContext getSessionContext(Class api)
{
return (AbstractSessionContext) _contextMap.get(api);
}
/**
* Initialize the server during the config phase.
*/
@Override
public void init() throws Exception
{
Thread thread = Thread.currentThread();
ClassLoader oldLoader = thread.getContextClassLoader();
try {
thread.setContextClassLoader(getClassLoader());
super.init();
_injectManager = InjectManager.create();
registerInjection();
for (AnnotatedType super X> localApi : _lazyGenerator.getLocalApi()) {
createContext(localApi.getJavaClass());
}
AnnotatedType localBean = _lazyGenerator.getLocalBean();
if (localBean != null)
createContext(localBean.getJavaClass());
for (AnnotatedType super X> remoteApi : _lazyGenerator.getRemoteApi()) {
createContext(remoteApi.getJavaClass());
}
bindContext();
} finally {
thread.setContextClassLoader(oldLoader);
}
registerCdiBeans();
log.fine(this + " initialized");
}
@Override
public void bind()
{
Thread thread = Thread.currentThread();
ClassLoader loader = thread.getContextClassLoader();
try {
thread.setContextClassLoader(getClassLoader());
boolean isAutoCompile = true;
if (_proxyImplClass == null) {
BeanGenerator beanGen = createBeanGenerator();
String fullClassName = beanGen.getFullClassName();
JavaClassGenerator javaGen = getLazyGenerator().getJavaClassGenerator();
if (javaGen.preload(fullClassName) != null) {
}
else if (isAutoCompile) {
beanGen.introspect();
javaGen.generate(beanGen);
}
javaGen.compilePendingJava();
_proxyImplClass = generateProxyClass(fullClassName, javaGen);
}
for (AbstractSessionContext cxt : _contextMap.values()) {
cxt.bind();
}
} catch (Exception e) {
throw ConfigException.create(e);
} finally {
thread.setContextClassLoader(loader);
}
}
/**
* Creates the bean generator for the session bean.
*/
protected BeanGenerator createBeanGenerator()
{
throw new UnsupportedOperationException();
}
private void createContext(Class api)
{
if (_contextMap.get(api) != null)
throw new IllegalStateException(String.valueOf(api));
AbstractSessionContext context = createSessionContext(api);
InjectManager injectManager = context.getInjectManager();
BeanBuilder factory
= injectManager.createBeanFactory(SessionContext.class);
context.setDeclaredRoles(_declaredRoles);
// XXX: separate additions?
if (injectManager.getBeans(SessionContext.class).size() == 0)
injectManager.addBeanDiscover(factory.singleton(context));
_contextMap.put(context.getApi(), context);
try {
String beanName = getAnnotatedType().getJavaClass().getName();
Jndi.bindDeep("java:comp/EJBContext", context);
Jndi.bindDeep("java:comp/" + beanName + "/ejbContext", context);
Jndi.bindDeep("java:comp/" + beanName + "/sessionContext", context);
} catch (Exception e) {
log.log(Level.FINER, e.toString(), e);
}
try {
TimerService timer = context.getTimerService();
BeanBuilder timerBuilder
= injectManager.createBeanFactory(TimerService.class);
if (injectManager.getBeans(TimerService.class).size() == 0)
injectManager.addBeanDiscover(timerBuilder.singleton(timer));
} catch (Exception e) {
log.log(Level.ALL, e.toString(), e);
}
/*
if (_sessionContext == null) {
}
*/
}
private Class> generateProxyClass(String skeletonName,
JavaClassGenerator javaGen)
throws ClassNotFoundException
{
Class> proxyImplClass;
Class> ejbClass = getAnnotatedType().getJavaClass();
if (! isPublic(ejbClass)
&& (ejbClass.getClassLoader() instanceof DynamicClassLoader)) {
// ejb/1103
proxyImplClass = javaGen.loadClassParentLoader(skeletonName, ejbClass);
}
else {
proxyImplClass = javaGen.loadClass(skeletonName);
}
try {
Method method = proxyImplClass.getMethod("__caucho_getException");
RuntimeException exn = (RuntimeException) method.invoke(null);
if (exn != null)
throw exn;
} catch (RuntimeException exn) {
throw exn;
} catch (Exception exn) {
throw new RuntimeException(exn);
}
// contextImplClass.getDeclaredConstructors();
return proxyImplClass;
}
private boolean isPublic(Class> cl)
{
if (! Modifier.isPublic(cl.getModifiers()))
return false;
Class> superClass = cl.getSuperclass();
if (superClass != null && ! Modifier.isPublic(superClass.getModifiers()))
return false;
// ejb/5092 - CDI TCK
for (Class> ifClass : cl.getInterfaces()) {
if (! Modifier.isPublic(ifClass.getModifiers()))
return false;
}
return true;
}
@Override
public T getLocalProxy(Class api)
{
OwnerCreationalContext owner = new OwnerCreationalContext(null);
return (T) getSessionContext(api).createProxy(owner);
}
protected AbstractSessionContext
createSessionContext(Class api)
{
throw new UnsupportedOperationException(getClass().getName());
}
protected SessionProxyFactory
createProxyFactory(AbstractSessionContext context)
{
try {
if (_proxyImplClass == null)
bind();
Class> []param = new Class[] { getClass(), getContextClass() };
Constructor> ctor = _proxyImplClass.getConstructor(param);
return (SessionProxyFactory) ctor.newInstance(this, context);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException)
throw (RuntimeException) cause;
else
throw new IllegalStateException(cause);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
protected Class> getContextClass()
{
throw new UnsupportedOperationException(getClass().getName());
}
private void registerCdiBeans()
{
ArrayList> localApiList = getLocalApi();
ArrayList> remoteApiList = getRemoteApi();
AnnotatedType rawAnnType = getRawAnnotatedType();
AnnotatedType annType = getAnnotatedType();
AnnotatedType extAnnType = createExternalAnnotatedType(annType, localApiList);
InjectManager moduleBeanManager = InjectManager.create();
ManagedBeanImpl mBean
= new ManagedBeanImpl(getInjectManager(), getAnnotatedType(), true);
mBean.introspect();
InjectionTarget target = mBean.getInjectionTarget();
target = moduleBeanManager.processInjectionTarget(target, getRawAnnotatedType());
mBean.setInjectionTarget(target);
Class> baseApi = annType.getJavaClass();
Set apiList = new LinkedHashSet();
AnnotatedType baseType = getLocalBean();
if (baseType != null) {
BaseType sourceApi = moduleBeanManager.createSourceBaseType(baseType.getBaseType());
apiList.addAll(sourceApi.getTypeClosure(moduleBeanManager));
}
if (localApiList != null) {
for (AnnotatedType super X> api : localApiList) {
baseApi = api.getJavaClass();
BaseType sourceApi = moduleBeanManager.createSourceBaseType(api.getJavaClass());
apiList.addAll(sourceApi.getTypeClosure(moduleBeanManager));
}
}
apiList.add(Object.class);
// ioc/024p
/*
if (remoteApiList != null) {
for (AnnotatedType super X> api : remoteApiList) {
if (baseApi == null)
baseApi = api.getJavaClass();
BaseType sourceApi = moduleBeanManager.createSourceBaseType(api.getJavaClass());
apiList.addAll(sourceApi.getTypeClosure(moduleBeanManager));
}
}
*/
if (baseApi == null)
throw new NullPointerException();
_bean = (Bean) createBean(mBean, baseApi, apiList, extAnnType);
// CDI TCK requires the rawAnnType, not the processed one
ProcessSessionBeanImpl process
= new ProcessSessionBeanImpl(moduleBeanManager,
_bean,
rawAnnType,
getEJBName(),
getSessionBeanType());
moduleBeanManager.addBean(_bean, process);
if (! moduleBeanManager.isSpecialized(annType.getJavaClass())) {
moduleBeanManager.addProduces(_bean, extAnnType);
}
for (AnnotatedType> localApi : getLocalApi()) {
registerLocalSession(moduleBeanManager, localApi.getJavaClass());
}
for (AnnotatedType> remoteApi : getRemoteApi()) {
registerLocalSession(moduleBeanManager, remoteApi.getJavaClass());
}
if (getLocalBean() != null) {
registerLocalSession(moduleBeanManager, getLocalBean().getJavaClass());
}
}
private AnnotatedType
createExternalAnnotatedType(AnnotatedType baseType,
ArrayList> apiList)
{
ExtAnnotatedType extAnnType = new ExtAnnotatedType(baseType);
for (AnnotatedField super X> field : baseType.getFields()) {
if (field.isStatic())
extAnnType.addField(field);
}
for (AnnotatedMethod super X> method : baseType.getMethods()) {
AnnotatedMethod super X> extMethod = mergeMethod(method, apiList);
if (extMethod != null) {
extAnnType.addMethod(extMethod);
}
else if (method.isAnnotationPresent(Produces.class)
&& ! baseType.isAnnotationPresent(Specializes.class)) {
// TCK: conflict
// ioc/07fa, ioc/07a4
throw new ConfigException(L.l("{0}.{1} is an invalid @Produces EJB method because the method is not in a @Local interface.",
method.getDeclaringType().getJavaClass().getName(),
method.getJavaMember().getName()));
}
else if (isDisposes(method)) {
throw new ConfigException(L.l("{0}.{1} is an invalid @Disposes EJB method because the method is not in a @Local interface.",
method.getDeclaringType().getJavaClass().getName(),
method.getJavaMember().getName()));
}
}
return extAnnType;
}
private boolean isDisposes(AnnotatedMethod super X> method)
{
for (AnnotatedParameter super X> param : method.getParameters()) {
if (param.isAnnotationPresent(Disposes.class))
return true;
}
return false;
}
private AnnotatedMethod super X>
mergeMethod(AnnotatedMethod super X> method,
ArrayList> apiList)
{
// ioc/07g3
if (apiList.size() == 0) {
return method;
}
for (AnnotatedType super X> api : apiList) {
AnnotatedMethod super X> apiMethod
= AnnotatedTypeUtil.findMethod(api, method);
if (apiMethod != null) {
AnnotatedMethodImpl super X> extMethod
= new AnnotatedMethodImpl(apiMethod.getDeclaringType(),
method,
apiMethod.getJavaMember(),
toArray(apiMethod.getAnnotations()),
null);
return extMethod;
}
}
return null;
}
private Annotation []toArray(Set annSet)
{
Annotation []ann = new Annotation[annSet.size()];
annSet.toArray(ann);
return ann;
}
private void registerLocalSession(InjectManager beanManager,
Class localApi)
{
AbstractSessionContext context = getSessionContext(localApi);
BeanName beanName = new BeanNameLiteral(getEJBName());
SessionRegistrationBean regBean
= new SessionRegistrationBean(beanManager, context, _bean, beanName);
beanManager.addBeanImpl(regBean, regBean.getAnnotated());
}
protected Bean getBean()
{
return _bean;
}
abstract protected Bean
createBean(ManagedBeanImpl mBean,
Class api,
Set apiList,
AnnotatedType extAnnType);
protected SessionBeanType getSessionBeanType()
{
return SessionBeanType.STATELESS;
}
@Override
public void destroy()
{
for (AbstractSessionContext context : _contextMap.values()) {
try {
context.destroy();
} catch (Exception e) {
log.log(Level.WARNING, e.toString(), e);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy