com.caucho.ejb.cfg.EjbBean Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of resin Show documentation
Show all versions of resin Show documentation
Resin Java Application Server
/*
* 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.cfg;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import javax.annotation.PostConstruct;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.Local;
import javax.ejb.LocalBean;
import javax.ejb.Remote;
import javax.ejb.StatefulTimeout;
import javax.ejb.Timeout;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.interceptor.AroundInvoke;
import com.caucho.config.ConfigException;
import com.caucho.config.Configurable;
import com.caucho.config.DependencyBean;
import com.caucho.config.LineConfigException;
import com.caucho.config.gen.BeanGenerator;
import com.caucho.config.inject.AnnotatedOverrideMap;
import com.caucho.config.inject.InjectManager;
import com.caucho.config.program.ConfigProgram;
import com.caucho.config.program.ContainerProgram;
import com.caucho.config.reflect.AnnotatedMethodImpl;
import com.caucho.config.reflect.AnnotatedTypeImpl;
import com.caucho.config.reflect.AnnotatedTypeUtil;
import com.caucho.config.reflect.BaseType;
import com.caucho.config.reflect.ReflectionAnnotatedFactory;
import com.caucho.config.types.DataSourceRef;
import com.caucho.config.types.DescriptionGroupConfig;
import com.caucho.config.types.EjbLocalRef;
import com.caucho.config.types.EjbRef;
import com.caucho.config.types.EnvEntry;
import com.caucho.config.types.MessageDestinationRef;
import com.caucho.config.types.Period;
import com.caucho.config.types.ResourceEnvRef;
import com.caucho.config.types.ResourceGroupConfig;
import com.caucho.config.types.ResourceRef;
import com.caucho.ejb.manager.EjbManager;
import com.caucho.ejb.server.AbstractEjbBeanManager;
import com.caucho.java.gen.JavaClassGenerator;
import com.caucho.loader.EnvironmentBean;
import com.caucho.make.ClassDependency;
import com.caucho.util.L10N;
import com.caucho.vfs.Depend;
import com.caucho.vfs.Path;
import com.caucho.vfs.PersistentDependency;
import com.caucho.vfs.Vfs;
/**
* Configuration for an ejb bean.
*/
public class EjbBean extends DescriptionGroupConfig
implements EnvironmentBean, DependencyBean
{
private static final L10N L = new L10N(EjbBean.class);
private final EjbConfig _ejbConfig;
private final String _ejbModuleName;
private EjbJar _jar;
private ClassLoader _loader;
protected ClassLoader _jClassLoader;
private String _ejbName;
private AnnotatedType _rawAnnType;
private AnnotatedTypeImpl _ejbClass;
// The published name as used by IIOP, Hessian, and
// jndi-remote-prefix/jndi-local-prefix
private String _mappedName;
private String _location = "";
private String _filename;
private int _line;
private boolean _isInit; // used for error messsage line #
private InjectionTarget _injectionTarget;
protected ArrayList> _remoteList
= new ArrayList>();
protected ArrayList> _localList
= new ArrayList>();
private boolean _isLocalBean;
private AnnotatedType _localBean;
// protected BeanGenerator _bean;
private boolean _isAllowPOJO = true;
protected boolean _isContainerTransaction = true;
private ConcurrencyManagementType _concurrencyManagementType;
private StatefulTimeout _statefulTimeout;
ArrayList _dependList
= new ArrayList();
ArrayList _configDependList
= new ArrayList();
ArrayList _beanDependList = new ArrayList();
private ArrayList> _methodList
= new ArrayList>();
private ArrayList> _beanMethodList
= new ArrayList>();
private ContainerProgram _initProgram;
private ArrayList _postConstructList
= new ArrayList();
private ContainerProgram _serverProgram;
private ArrayList _resourceList
= new ArrayList();
private ArrayList _defaultInterceptors
= new ArrayList();
private ArrayList _classInterceptors
= new ArrayList();
private ArrayList _aroundInvoke
= new ArrayList();
private ArrayList _asyncConfig
= new ArrayList();
private String _timeoutMethodName;
private long _transactionTimeout;
/**
* Creates a new entity bean configuration.
*/
public EjbBean(EjbConfig ejbConfig, String ejbModuleName)
{
_ejbConfig = ejbConfig;
_ejbModuleName = ejbModuleName;
_loader = ejbConfig.getEjbContainer().getClassLoader();
}
/**
* Creates a new entity bean configuration.
*/
public EjbBean(EjbConfig ejbConfig,
AnnotatedType rawAnnType,
AnnotatedType annType,
String ejbModuleName)
{
_ejbConfig = ejbConfig;
_rawAnnType = rawAnnType;
_ejbClass = AnnotatedTypeImpl.create(annType);
_ejbModuleName = ejbModuleName;
setEJBClass(_ejbClass.getJavaClass());
_loader = ejbConfig.getEjbContainer().getClassLoader();
}
public EjbConfig getConfig()
{
return _ejbConfig;
}
public EjbManager getEjbContainer()
{
return _ejbConfig.getEjbContainer();
}
public InjectManager getCdiManager()
{
return getEjbContainer().getInjectManager();
}
public String getModuleName()
{
return _ejbModuleName;
}
public EjbJar getJar()
{
return _jar;
}
public void setJar(EjbJar jar)
{
_jar = jar;
}
public void setAroundInvoke(AroundInvokeConfig aroundInvoke)
{
_aroundInvoke.add(aroundInvoke);
}
public void addAsyncMethod(AsyncConfig async)
{
_asyncConfig.add(async);
}
public void setInjectionTarget(InjectionTarget injectTarget)
{
_injectionTarget = injectTarget;
}
public InjectionTarget getInjectionTarget()
{
return _injectionTarget;
}
/**
* Returns the remove-method for the given method.
*/
/*
public RemoveMethod getRemoveMethod(Method method)
{
for (RemoveMethod removeMethod : _removeMethods) {
if (removeMethod.isMatch(method))
return removeMethod;
}
return null;
}
*/
/**
* Returns the remove-method list.
*/
/*
public ArrayList getRemoveMethods()
{
return _removeMethods;
}
*/
/**
* Returns the timeout method name.
*/
public String getTimeoutMethodName()
{
return _timeoutMethodName;
}
/**
* Adds a new remove-method
*/
@Configurable
public void addRemoveMethod(RemoveMethod removeMethod)
{
// _removeMethods.add(removeMethod);
_beanMethodList.add(removeMethod);
}
/**
* Adds a new concurrent-method
*/
@Configurable
public void addConcurrentMethod(ConcurrentMethod concurrentMethod)
{
// _removeMethods.add(removeMethod);
_beanMethodList.add(concurrentMethod);
}
public void addAfterBeginMethod(AfterBeginMethod method)
{
_beanMethodList.add(method);
}
public void addBeforeCompletionMethod(BeforeCompletionMethod method)
{
_beanMethodList.add(method);
}
/**
* Adds a new interceptor.
*/
public void addInterceptor(Interceptor interceptor, boolean isDefault)
{
if (isDefault)
_defaultInterceptors.add(interceptor);
else
_classInterceptors.add(interceptor);
}
public String getEJBModuleName()
{
return _ejbModuleName;
}
/**
* Returns the class loader.
*/
@Override
public ClassLoader getClassLoader()
{
return _loader;
}
protected Class> loadClass(String className)
{
try {
return Class.forName(className, false, _loader);
} catch (ClassNotFoundException e) {
throw ConfigException.create(e);
}
}
/**
* Sets the location
*/
public void setConfigLocation(String filename, int line)
{
if (_filename == null) {
_filename = filename;
_line = line;
}
if (_location == null)
_location = filename + ":" + line + ": ";
}
/**
* Sets the location
*/
public void setLocation(String location)
{
_location = location;
}
/**
* Gets the location
*/
public String getLocation()
{
return _location;
}
/**
* Gets the file name
*/
public String getFilename()
{
return _filename;
}
/**
* Gets the line
*/
public int getLine()
{
return _line;
}
/**
* Sets true if POJO are allowed.
*/
public void setAllowPOJO(boolean allowPOJO)
{
_isAllowPOJO = allowPOJO;
}
/**
* Return true if POJO are allowed.
*/
public boolean isAllowPOJO()
{
return _isAllowPOJO;
}
/**
* Sets the ejbName
*/
public void setEJBName(String ejbName)
{
_ejbName = ejbName;
}
/**
* Gets the ejbName
*/
public String getEJBName()
{
return _ejbName;
}
/**
* The mapped-name is the remote published name
* used by IIOP, Hessian, and jndi-remote-prefix, jndi-local-prefix.
* The default is the EJBName.
*/
public void setMappedName(String mappedName)
{
_mappedName = mappedName;
}
/**
* The mapped-name is the published name
* used by IIOP, Hessian, and jndi-remote-prefix, jndi-local-prefix.
*/
public String getMappedName()
{
return _mappedName == null ? getEJBName() : _mappedName;
}
/**
* Returns the kind of bean.
*/
public String getEJBKind()
{
return "unknown";
}
/**
* Sets the ejb implementation class.
*/
public void setEJBClass(Class ejbClass)
throws ConfigException
{
if (_ejbClass != null)
return;
AnnotatedTypeImpl annType;
AnnotatedType refType = ReflectionAnnotatedFactory.introspectType(ejbClass);
annType = new AnnotatedTypeImpl(refType);
setEJBClassWrapper(annType);
}
/**
* Sets the ejb implementation class.
*/
public void setEJBClassWrapper(AnnotatedType ejbClass)
throws ConfigException
{
if (_ejbClass != null && ! _ejbClass.getJavaClass().getName().equals(ejbClass.getJavaClass().getName()))
throw error(L.l("ejb-class '{0}' cannot be redefined. Old value is '{1}'.",
_ejbClass.getJavaClass().getName(),
ejbClass.getJavaClass().getName()));
_ejbClass = AnnotatedTypeImpl.create(ejbClass);
int modifiers = _ejbClass.getJavaClass().getModifiers();
/*
if (! _ejbClass.isPublic())
throw error(L.l("'{0}' must be public. Bean implementations must be public.", ejbClass.getName()));
*/
if (Modifier.isPrivate(modifiers))
throw error(L.l("'{0}' must be public. Bean implementations must be public.", ejbClass.getJavaClass().getName()));
if (Modifier.isFinal(modifiers))
throw error(L.l("'{0}' must not be final. Bean implementations must not be final.", ejbClass.getJavaClass().getName()));
if (_ejbClass.getJavaClass().isInterface())
throw error(L.l("'{0}' must not be an interface. Bean implementations must be classes.", ejbClass.getJavaClass().getName()));
AnnotatedMethod super X> method = getMethod("finalize", new Class[0]);
if (method != null
&& ! method.getJavaMember().getDeclaringClass().equals(Object.class)) {
throw error(L.l("'{0}' may not implement finalize(). Bean implementations may not implement finalize().",
method.getJavaMember().getDeclaringClass().getName()));
}
}
/**
* Gets the ejb implementation class.
*/
public Class getEJBClass()
{
try {
if (_ejbClass == null)
return null;
return (Class) Class.forName(_ejbClass.getJavaClass().getName(), false, getClassLoader());
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw ConfigException.create(e);
}
}
public AnnotatedType getRawAnnotatedType()
{
return _rawAnnType;
}
public AnnotatedTypeImpl getAnnotatedType()
{
return _ejbClass;
}
/**
* Gets the ejb implementation class.
*/
public String getEJBFullClassName()
{
return _ejbClass.getJavaClass().getName();
}
/**
* Gets the ejb implementation class.
*/
public String getEJBClassName()
{
String s = _ejbClass.getJavaClass().getName();
int p = s.lastIndexOf('.');
if (p > 0)
return s.substring(p + 1);
else
return s;
}
/**
* Gets the implementation class name.
*/
public String getFullImplName()
{
return getEJBFullClassName();
}
public void addRemote(Class remote)
throws ConfigException
{
BaseType type = getCdiManager().createTargetBaseType(remote);
addRemoteType(type);
}
/**
* Sets the ejb remote interface
*/
public void addRemoteType(BaseType remote)
throws ConfigException
{
AnnotatedTypeImpl annType;
AnnotatedType> refType = ReflectionAnnotatedFactory.introspectType(remote);
annType = new AnnotatedTypeImpl(refType);
addRemoteWrapper(annType);
}
/**
* Sets the remote interface class.
*/
public void addRemoteWrapper(AnnotatedType super X> remote)
throws ConfigException
{
Class> remoteClass = remote.getJavaClass();
int modifiers = remoteClass.getModifiers();
if (! Modifier.isPublic(modifiers))
throw error(L.l("'{0}' must be public. interfaces must be public.", remoteClass.getName()));
if (! remoteClass.isInterface())
throw error(L.l("'{0}' must be an interface. interfaces must be interfaces.", remoteClass.getName()));
if (! _remoteList.contains(remote)) {
_remoteList.add(remote);
}
}
/**
* Gets the remote interface class.
*/
public ArrayList> getRemoteList()
{
return _remoteList;
}
/**
* Sets the ejb local interface
*/
public void addLocal(Class> local)
throws ConfigException
{
BaseType type = getCdiManager().createTargetBaseType(local);
addLocalType(type);
}
protected void addLocalType(BaseType local)
{
AnnotatedTypeImpl annType;
AnnotatedType> refType = ReflectionAnnotatedFactory.introspectType(local);
annType = new AnnotatedTypeImpl(refType);
addLocalWrapper(annType);
}
/**
* Sets the local interface class.
*/
public void addLocalWrapper(AnnotatedType super X> local)
throws ConfigException
{
Class> localClass = local.getJavaClass();
/*
int modifiers = localClass.getModifiers();
if (! Modifier.isPublic(modifiers))
throw error(L.l("'{0}' must be public. interfaces must be public.", localClass.getName()));
*/
if (! localClass.isInterface())
throw error(L.l("'{0}' must be an interface. interfaces must be interfaces.", localClass.getName()));
for (int i = _localList.size() - 1; i >= 0; i--) {
AnnotatedType super X> oldLocal = _localList.get(i);
Class> oldClass = oldLocal.getJavaClass();
// ioc/1235 vs ejb/4040
if (localClass.equals(oldClass))
return;
/*
if (localClass.isAssignableFrom(oldClass))
return;
if (oldClass.isAssignableFrom(localClass)) {
_localList.set(i, local);
return;
}
else if (localClass.isAssignableFrom(oldClass))
return;
*/
}
_localList.add(local);
}
/**
* Gets the local interface class.
*/
public ArrayList> getLocalList()
{
return _localList;
}
public AnnotatedType getLocalBean()
{
return _localBean;
}
/**
* Returns true if the transaction type is container.
*/
public boolean isContainerTransaction()
{
return _isContainerTransaction;
}
/**
* Returns true if the transaction type is container.
*/
public void setContainerTransaction(boolean isContainerTransaction)
{
_isContainerTransaction = isContainerTransaction;
}
public void setConcurrencyManagementType(String type)
{
if ("Container".equals(type))
_concurrencyManagementType = ConcurrencyManagementType.CONTAINER;
else if ("Bean".equals(type))
_concurrencyManagementType = ConcurrencyManagementType.BEAN;
else
throw new ConfigException(L.l("'{0}' is an unknown concurrency-management-type",
type));
}
public void setStatefulTimeout(EjbTimeout timeout)
{
_statefulTimeout = new StatefulTimeoutLiteral(timeout.getTimeoutValue());
}
/**
* Adds a method.
*/
public EjbMethodPattern createMethod(MethodSignature sig)
{
for (int i = 0; i < _methodList.size(); i++) {
EjbMethodPattern method = _methodList.get(i);
if (method.getSignature().equals(sig))
return method;
}
EjbMethodPattern method = new EjbMethodPattern(this, sig);
_methodList.add(method);
return method;
}
/**
* Adds a method.
*/
public void addMethod(EjbMethodPattern method)
{
_methodList.add(method);
}
public boolean isMatch(AnnotatedMethod> method)
{
if (_methodList.size() == 0)
return true;
for (EjbMethodPattern> ejbMethod : _methodList) {
if (ejbMethod.isMatch(method))
return true;
}
return false;
}
/**
* Gets the best method.
*/
public EjbMethodPattern getMethodPattern(AnnotatedMethod> method,
String intf)
{
EjbMethodPattern bestMethod = null;
int bestCost = -1;
for (int i = 0; i < _methodList.size(); i++) {
EjbMethodPattern ejbMethod = _methodList.get(i);
MethodSignature sig = ejbMethod.getSignature();
if (sig.isMatch(method, intf) && bestCost < sig.getCost()) {
bestMethod = ejbMethod;
bestCost = sig.getCost();
}
}
return bestMethod;
}
/**
* returns the method list.
*/
public ArrayList> getMethodList()
{
return _methodList;
}
/**
* Sets the transaction timeout.
*/
public void setTransactionTimeout(Period timeout)
{
_transactionTimeout = timeout.getPeriod();
}
public void addBusinessLocal(Class> localApi)
{
addLocal(localApi);
}
public void addBusinessRemote(Class> remoteApi)
{
addRemote(remoteApi);
}
public void setLocalBean(boolean isLocal)
{
_isLocalBean = true;
if (_localBean == null)
_localBean = getAnnotatedType();
}
/**
* Gets the transaction timeout.
*/
public long getTransactionTimeout()
{
return _transactionTimeout;
}
public MessageDestinationRef createMessageDestinationRef()
{
return new MessageDestinationRef(Vfs.lookup());
}
/**
* Sets the security identity
*/
public void setSecurityIdentity(EjbSecurityIdentity securityIdentity)
{
}
/**
* Adds a list of dependencies.
*/
public void addDependencyList(ArrayList dependList)
{
for (int i = 0; dependList != null && i < dependList.size(); i++) {
addDependency(dependList.get(i));
}
}
/**
* Add a dependency.
*/
public void addDepend(Path path)
{
addDependency(new Depend(path));
}
/**
* Add a dependency.
*/
public void addDependency(PersistentDependency depend)
{
if (! _dependList.contains(depend))
_dependList.add(depend);
}
/**
* Add a dependency.
*/
public void addDependency(Class> cl)
{
addDependency(new ClassDependency(cl));
}
/**
* Gets the depend list.
*/
public ArrayList getDependList()
{
return _dependList;
}
/**
* Add a bean dependency.
*/
public void addBeanDependency(String ejbName)
{
if (! _beanDependList.contains(ejbName))
_beanDependList.add(ejbName);
}
/**
* Gets the bean depend list.
*/
public ArrayList getBeanDependList()
{
return _beanDependList;
}
/**
* Adds an init program.
*/
public void addInitProgram(ConfigProgram init)
{
if (_initProgram == null)
_initProgram = new ContainerProgram();
_initProgram.addProgram(init);
}
/**
* Adds an undefined value, e.g. env-entry
*/
public void addBuilderProgram(ConfigProgram init)
{
if (_serverProgram == null)
_serverProgram = new ContainerProgram();
_serverProgram.addProgram(init);
}
//
// references and resources
//
public DataSourceRef createDataSource()
{
DataSourceRef def = new DataSourceRef();
def.setProgram(true);
ClassLoader loader = Thread.currentThread().getContextClassLoader();
def.setJndiClassLoader(loader);
_resourceList.add(def);
return def;
}
public EnvEntry createEnvEntry()
{
EnvEntry env = new EnvEntry();
env.setProgram(true);
// ejb/7038, ejb/8203, ejb/8220, tck
ClassLoader loader = Thread.currentThread().getContextClassLoader();
env.setJndiClassLoader(loader);
_resourceList.add(env);
return env;
}
public EjbRef createEjbRef()
{
EjbRef ref = new EjbRef();
ref.setProgram(true);
ClassLoader loader = Thread.currentThread().getContextClassLoader();
ref.setJndiClassLoader(loader);
_resourceList.add(ref);
return ref;
}
public EjbLocalRef createEjbLocalRef()
{
EjbLocalRef ref = new EjbLocalRef();
ref.setProgram(true);
ClassLoader loader = Thread.currentThread().getContextClassLoader();
ref.setJndiClassLoader(loader);
_resourceList.add(ref);
return ref;
}
public ResourceRef createResourceRef()
{
ResourceRef ref= new ResourceRef();
ref.setProgram(true);
ClassLoader loader = Thread.currentThread().getContextClassLoader();
ref.setJndiClassLoader(loader);
_resourceList.add(ref);
return ref;
}
public ResourceEnvRef createResourceEnvRef()
{
ResourceEnvRef ref = new ResourceEnvRef();
ref.setProgram(true);
_resourceList.add(ref);
return ref;
}
public ArrayList getResourceList()
{
return _resourceList;
}
public void setInit(ContainerProgram init)
{
if (_initProgram == null)
_initProgram = new ContainerProgram();
_initProgram.addProgram(init);
}
public void addPostConstruct(PostConstructType postConstruct)
{
_beanMethodList.add(postConstruct);
// _postConstructList.add(postConstruct.getProgram(getEJBClass()));
}
/**
* Gets the init program.
*/
public ContainerProgram getInitProgram()
{
/*
if (_postConstructList != null) {
if (_initProgram == null)
_initProgram = new ContainerProgram();
for (ConfigProgram program : _postConstructList)
_initProgram.addProgram(program);
_postConstructList = null;
}
*/
return _initProgram;
}
/**
* Gets the server program.
*/
public ContainerProgram getServerProgram()
{
return _serverProgram;
}
/**
* Configure initialization.
*/
@PostConstruct
public void init()
throws ConfigException
{
try {
if (_isInit)
return;
_isInit = true;
if (getAnnotatedType() == null)
throw error(L.l("ejb-class is not defined for '{0}'",
getEJBName()));
for (EjbMethodPattern methodPattern : _methodList) {
for (AnnotatedType> localList : _localList) {
for (AnnotatedMethod> apiMethod : localList.getMethods()) {
methodPattern.configure(apiMethod);
}
}
for (AnnotatedType> remoteList : _remoteList) {
for (AnnotatedMethod> apiMethod : remoteList.getMethods()) {
methodPattern.configure(apiMethod);
}
}
}
// XXX: add local api
introspect();
initIntrospect();
addInterceptors();
} catch (ConfigException e) {
throw ConfigException.createLine(_location, e);
}
}
protected void introspect()
{
// _bean.introspect();
}
/**
* Creates the BeanGenerator generator instance
*/
protected BeanGenerator createBeanGenerator()
{
throw new UnsupportedOperationException(getClass().getName());
}
/**
* Configure initialization.
*/
public void initIntrospect()
throws ConfigException
{
// configureBeanMethods(getAnnotatedType());
boolean isExcludeDefault = false;
for (InterceptorBinding interceptor :
_ejbConfig.getInterceptorBinding(getEJBName(), isExcludeDefault)) {
introspectInterceptor(interceptor);
}
configureAroundInvoke(getAnnotatedType());
configureAsync(getAnnotatedType());
configureMethods(getAnnotatedType());
if (_concurrencyManagementType != null)
getAnnotatedType().addAnnotation(new ConcurrencyManagementLiteral(_concurrencyManagementType));
if (_statefulTimeout != null)
getAnnotatedType().addAnnotation(_statefulTimeout);
if (_isLocalBean)
_localBean = getAnnotatedType();
}
private void introspectInterceptor(InterceptorBinding binding)
{
ArrayList interceptorClasses = new ArrayList();
if (binding.getMethodList().isEmpty()) {
for (Class> iClass : binding.getInterceptors()) {
interceptorClasses.add(iClass.getName());
}
if (interceptorClasses.isEmpty()) {
InterceptorOrder interceptorOrder = binding.getInterceptorOrder();
if (interceptorOrder != null) {
for (Class> cl : interceptorOrder.getInterceptorClasses()) {
interceptorClasses.add(cl.getName());
}
}
}
AnnotatedTypeImpl> typeImpl = (AnnotatedTypeImpl>) getAnnotatedType();
if (binding.isExcludeDefaultInterceptors())
typeImpl.addAnnotation(new ExcludeDefaultInterceptorsLiteral());
if (binding.isExcludeClassInterceptors())
typeImpl.addAnnotation(new ExcludeClassInterceptorsLiteral());
}
else {
for (AnnotatedMethod> method : getAnnotatedType().getMethods()) {
if (binding.isMatch(method)) {
if (method instanceof AnnotatedMethodImpl>) {
AnnotatedMethodImpl> methodImpl = (AnnotatedMethodImpl>) method;
if (binding.getAnnotation() != null)
methodImpl.addAnnotation(binding.mergeAnnotation(methodImpl));
if (binding.isExcludeClassInterceptors())
methodImpl.addAnnotationIfAbsent(new ExcludeClassInterceptorsLiteral());
}
}
}
}
for (String className : interceptorClasses) {
/*
Interceptor interceptor = getInterceptor(className);
// ejb/0fb5 vs ejb/0fb6
if (interceptor != null) {
_interceptors.remove(interceptor);
addInterceptor(interceptor, binding.isDefault());
}
else {
*/
Interceptor interceptor = _ejbConfig.getInterceptor(className);
if (interceptor == null) {
interceptor = new Interceptor();
interceptor.setInterceptorClass(className);
_ejbConfig.addInterceptor(interceptor);
}
interceptor.init();
addInterceptor(interceptor, binding.isDefault());
}
}
private void addInterceptors()
{
if (_defaultInterceptors.size() > 0) {
addDefaultInterceptors(createInterceptors(_defaultInterceptors));
}
if (_classInterceptors.size() > 0) {
addClassInterceptors(createInterceptors(_classInterceptors));
}
}
private Class> []createInterceptors(ArrayList interceptorList)
{
Class> []interceptors = new Class>[interceptorList.size()];
for (int i = 0; i < interceptorList.size(); i++) {
String className = interceptorList.get(i).getInterceptorClass();
Class> cl = null;
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
cl = Class.forName(className, false, loader);
interceptors[i] = cl;
} catch (ClassNotFoundException e) {
throw ConfigException.create(e);
}
}
return interceptors;
}
private void addClassInterceptors(Class> []cl)
{
_ejbClass.addAnnotation(new InterceptorsLiteral(cl));
}
private void addDefaultInterceptors(Class> []cl)
{
_ejbClass.addAnnotation(new InterceptorsDefaultLiteral(cl));
}
/**
* Deploys the bean.
*/
public AbstractEjbBeanManager deployServer(EjbManager ejbContainer,
EjbLazyGenerator lazyGenerator)
throws ClassNotFoundException, ConfigException
{
throw new UnsupportedOperationException();
}
/**
* Validates the local interface.
*/
protected void validateLocal(AnnotatedType objectType)
throws ConfigException
{
validateRemote(objectType);
}
/**
* Validates the remote interface.
*/
protected void validateRemote(AnnotatedType objectType)
throws ConfigException
{
Class objectClass = objectType.getJavaClass();
String objectName = objectClass.getName();
if (! objectClass.isInterface())
throw error(L.l("'{0}' must be an interface", objectName));
for (AnnotatedMethod super T> method : objectType.getMethods()) {
Method javaMethod = method.getJavaMember();
String name = javaMethod.getName();
Class> []param = javaMethod.getParameterTypes();
if (name.startsWith("ejb")) {
throw error(L.l("'{0}' forbidden in {1}. Local or remote interfaces may not define ejbXXX methods.",
getFullMethodName(method),
objectName));
}
// ejb/11d6
//Type returnType = javaMethod.getGenericReturnType();
AnnotatedMethod super X> implMethod =
validateRemoteImplMethod(javaMethod.getName(), param,
method, objectType);
/*
InjectManager manager = InjectManager.create();
BaseType target = manager.createTargetBaseType(returnType);
BaseType source = manager.createSourceBaseType(returnType);
if (! target.isAssignableFrom(source)) {
throw error(L.l("{0}: '{1}' must return {2} to match {3}.{4}. Business methods must return a type assignable to interface return type.",
javaMethod.getDeclaringClass().getName(),
getFullMethodName(method),
implMethod.getJavaMember().getReturnType().getName(),
implMethod.getJavaMember().getDeclaringClass().getSimpleName(),
getFullMethodName(implMethod)));
}*/
validateExceptions(method, implMethod.getJavaMember().getExceptionTypes());
}
}
/**
* Check that a method exists, is public, not abstract.
*
* @param methodName the name of the method to check for
* @param args the expected method parameters
*
* @return the matching method
*/
private AnnotatedMethod super X>
validateRemoteImplMethod(String methodName,
Class> []param,
AnnotatedMethod super T> sourceMethod,
AnnotatedType sourceClass)
throws ConfigException
{
AnnotatedMethod super X> method = null;
AnnotatedType beanClass = getAnnotatedType();
// method = AnnotatedTypeUtil.findMethod(beanClass, methodName, param);
method = AnnotatedTypeUtil.findMethod(beanClass, sourceMethod);
if (method == null && sourceMethod != null) {
throw error(L.l("{0}: '{1}' needed on the implementation class to match {2}.{3}",
beanClass.getJavaClass().getName(),
getFullMethodName(methodName, param),
sourceMethod.getJavaMember().getDeclaringClass().getSimpleName(),
getFullMethodName(sourceMethod)));
}
else if (method == null) {
throw error(L.l("{0}: '{1}' expected",
beanClass.getJavaClass().getName(),
getFullMethodName(methodName, param)));
}
Method javaMethod = method.getJavaMember();
int modifiers = javaMethod.getModifiers();
if (! Modifier.isPublic(modifiers)) {
throw error(L.l("{0}: '{1}' must be public",
beanClass.getJavaClass().getName(),
getFullMethodName(methodName, param)));
}
if (method.isStatic()) {
throw error(L.l("{0}: '{1}' must not be static",
beanClass.getJavaClass().getName(),
getFullMethodName(methodName, param)));
}
if (Modifier.isFinal(modifiers)) {
throw error(L.l("{0}: '{1}' must not be final.",
beanClass.getJavaClass().getName(),
getFullMethodName(methodName, param),
beanClass.getJavaClass().getName()));
}
return method;
}
public String getSkeletonName()
{
// XXX: needs to match generator
StringBuilder sb = new StringBuilder();
sb.append(getEJBClass().getName());
sb.append("__");
sb.append(getBeanType()).append("Proxy");
return JavaClassGenerator.cleanClassName(sb.toString());
}
/**
* @return Type of bean (Stateful, Stateless, etc.)
*/
protected String getBeanType()
{
return "Bean";
}
/**
* Finds the method in the class.
*
* @param cl owning class
* @param method source method
*
* @return the matching method or null if non matches.
*/
protected AnnotatedMethod super X>
getMethod(String methodName, Class> []paramTypes)
{
return AnnotatedTypeUtil.findMethod(getAnnotatedType(), methodName, paramTypes);
}
/**
* Finds the method in the class.
*
* @param cl owning class
* @param method source method
*
* @return the matching method or null if non matches.
*/
public static AnnotatedMethod super X>
getMethod(AnnotatedType cl, AnnotatedMethod extends T> sourceMethod)
{
Method method = sourceMethod.getJavaMember();
return AnnotatedTypeUtil.findMethod(cl,
method.getName(),
method.getParameterTypes());
}
/**
* Finds the method in the class.
*
* @param cl owning class
* @param name method name to match
* @param params method parameters to match
*
* @return the matching method or null if non matches.
*/
public static AnnotatedMethod super X>
getMethod(AnnotatedType cl, String name, Class> []param)
{
return AnnotatedTypeUtil.findMethod(cl, name, param);
}
public boolean isCMP()
{
return false;
}
public boolean isCMP1()
{
return false;
}
/**
* Finds the method in the class.
*
* @param cl owning class
* @param name method name to match
* @param params method parameters to match
*
* @return the matching method or null if non matches.
*/
public static AnnotatedMethod super Y>
findMethod(MethodSignature sig, AnnotatedType cl, String intf)
{
if (cl == null)
return null;
for (AnnotatedMethod super Y> method : cl.getMethods()) {
if (sig.isMatch(method, intf))
return method;
}
return null;
}
/**
* Returns a printable version of a class.
*/
public static String getClassName(Class> cl)
{
if (cl == null)
return "null";
else if (cl.isArray())
return getClassName(cl.getComponentType()) + "[]";
else if (cl.getName().startsWith("java")) {
int p = cl.getName().lastIndexOf('.');
return cl.getName().substring(p + 1);
}
else
return cl.getName();
}
/**
* Returns a printable version of a class.
*/
public static String getShortClassName(Class> cl)
{
if (cl.isArray())
return getShortClassName(cl.getComponentType()) + "[]";
else
return cl.getSimpleName();
}
/**
* Tests is a method is declared in a class.
*/
public boolean classHasMethod(AnnotatedType> cl,
AnnotatedMethod> method)
{
return AnnotatedTypeUtil.findMethod(cl, method) != null;
}
public void validateException(AnnotatedMethod> method, Class> e)
throws ConfigException
{
validateExceptions(method, new Class[] { e });
}
/**
* Check that the method throws the expected exceptions.
*
* @param method the method to test
* @param exn the expected exceptions
*/
public void validateExceptions(AnnotatedMethod> method, Class> []exn)
throws ConfigException
{
Method javaMethod = method.getJavaMember();
Class> []methodExceptions = javaMethod.getExceptionTypes();
loop:
for (int i = 0; i < exn.length; i++) {
if (RuntimeException.class.isAssignableFrom(exn[i]))
continue;
for (int j = 0; j < methodExceptions.length; j++) {
if (methodExceptions[j].isAssignableFrom(exn[i]))
continue loop;
}
throw new ConfigException(L.l("{2}: '{0}' must throw {1}.",
getFullMethodName(method),
exn[i].getName(),
javaMethod.getDeclaringClass().getName()));
}
}
public void validateExceptions(AnnotatedMethod> caller,
AnnotatedMethod super X> callee)
throws ConfigException
{
Method callerMethod = caller.getJavaMember();
Method calleeMethod = callee.getJavaMember();
Class> []exn = calleeMethod.getExceptionTypes();
Class> missing = findMissingException(caller, exn);
if (missing != null) {
throw error(L.l("{0}: '{1}' must throw {2}.",
callerMethod.getDeclaringClass().getName(),
getFullMethodName(caller),
getShortClassName(missing),
callerMethod.getDeclaringClass().getName()) +
L.l(" {0} must throw all {1}.{2} exceptions.",
callerMethod.getName(),
calleeMethod.getDeclaringClass().getSimpleName(),
calleeMethod.getName()));
}
}
/**
* Finds any exception in the exception array that the method isn't
* throwing.
*
* @param method the method which should throw a superset of exceptions.
* @param exn an array of exceptions the method should throw.
*
* @return the first missing exception
*/
Class> findMissingException(AnnotatedMethod> method, Class> []exn)
{
for (int i = 0; i < exn.length; i++) {
if (! AnnotatedTypeUtil.hasException(method, exn[i])
&& ! RuntimeException.class.isAssignableFrom(exn[i]))
return exn[i];
}
return null;
}
protected AnnotatedMethod super T>
findFirstCreateMethod(AnnotatedType cl)
{
for (AnnotatedMethod super T> method : cl.getMethods()) {
if (method.getJavaMember().getName().startsWith("create"))
return method;
}
return null;
}
protected void introspectBean(AnnotatedType type, String defaultName)
throws ConfigException
{
try {
setEJBClassWrapper(type);
String name = getEJBName();
if (name == null || name.equals(""))
name = defaultName;
if (name == null || name.equals("")) {
name = type.getJavaClass().getSimpleName();
}
setEJBName(name);
Local local = type.getAnnotation(Local.class);
if (local != null) {
for (Class> localClass : local.value()) {
addLocal(localClass);
}
}
if (type.isAnnotationPresent(LocalBean.class)) {
_localBean = type;
}
if (_localList.size() == 0)
_localBean = type;
Remote remote = type.getAnnotation(Remote.class);
if (remote != null) {
for (Class> localClass : local.value()) {
addRemote(localClass);
}
/*
// ejb/0f08: single interface
if (values.length == 0) {
// XXX: getGenericInterfaces
Class []ifs = type.getJavaClass().getInterfaces();
if (ifs.length == 1)
setRemoteWrapper(new ApiClass(ifs[0]));
}
*/
}
TransactionAttribute xa = type.getAnnotation(TransactionAttribute.class);
if (xa != null) {
MethodSignature sig = new MethodSignature();
sig.setMethodName("*");
EjbMethodPattern pattern = createMethod(sig);
setPatternTransaction(pattern, xa);
}
configureMethods(getAnnotatedType());
configureAroundInvoke(getAnnotatedType());
configureAsync(getAnnotatedType());
/*
for (int i = 0; i < _initList.size(); i++)
addInitProgram(_initList.get(i).getBuilderProgram());
*/
} catch (ConfigException e) {
throw e;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw ConfigException.createLine(_location, e);
}
}
private void configureAroundInvoke(AnnotatedType type)
{
AnnotatedTypeImpl typeImpl = (AnnotatedTypeImpl) type;
for (AroundInvokeConfig aroundInvoke : _aroundInvoke) {
configureAroundInvoke(typeImpl, type.getJavaClass(), aroundInvoke);
}
}
private void configureAroundInvoke(AnnotatedTypeImpl type,
Class> cl,
AroundInvokeConfig aroundInvoke)
{
if (cl == null)
return;
for (Method method : cl.getDeclaredMethods()) {
if (aroundInvoke.isMatch(method)) {
AnnotatedMethod> annMethod = AnnotatedTypeUtil.findMethod(type, method);
if (annMethod == null) {
annMethod = type.createMethod(method);
}
AnnotatedMethodImpl> methodImpl = (AnnotatedMethodImpl>) annMethod;
methodImpl.addAnnotation(new AroundInvokeLiteral());
AnnotatedOverrideMap.putMethod(method, methodImpl);
return;
}
}
configureAroundInvoke(type, cl.getSuperclass(), aroundInvoke);
}
private void configureAsync(AnnotatedType type)
{
AnnotatedTypeImpl typeImpl = (AnnotatedTypeImpl) type;
for (AsyncConfig async : _asyncConfig) {
configureAsync(typeImpl, type.getJavaClass(), async);
}
}
private void configureAsync(AnnotatedTypeImpl type,
Class> cl,
AsyncConfig async)
{
if (cl == null)
return;
for (Method method : cl.getDeclaredMethods()) {
if (async.isMatch(method)) {
AnnotatedMethod> annMethod = AnnotatedTypeUtil.findMethod(type, method);
if (annMethod == null) {
annMethod = type.createMethod(method);
}
AnnotatedMethodImpl> methodImpl = (AnnotatedMethodImpl>) annMethod;
methodImpl.addAnnotation(new AsynchronousLiteral());
AnnotatedOverrideMap.putMethod(method, methodImpl);
return;
}
}
configureAsync(type, cl.getSuperclass(), async);
}
private void configureMethods(AnnotatedTypeImpl type)
{
if (_beanMethodList.size() == 0) {
return;
}
for (AnnotatedMethod> method : type.getMethodsForUpdate()) {
for (EjbMethodPattern> cfgMethod : _beanMethodList) {
if (cfgMethod.isMatch(method)) {
cfgMethod.configure(method);
}
}
}
}
private void setPatternTransaction(EjbMethodPattern pattern,
TransactionAttribute xa)
throws ConfigException
{
TransactionAttributeType xaType = xa.value();
pattern.setTransaction(xaType);
}
private MethodSignature getSignature(AnnotatedMethod> annMethod)
throws ConfigException
{
MethodSignature sig = new MethodSignature();
Method method = annMethod.getJavaMember();
sig.setMethodName(method.getName());
Class> []paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
sig.addParam(paramTypes[i].getName());
}
return sig;
}
/**
* Returns a full method name with arguments.
*/
public static String getFullMethodName(AnnotatedMethod> method)
{
Method javaMethod = method.getJavaMember();
return getFullMethodName(javaMethod.getName(),
javaMethod.getParameterTypes());
}
/**
* Returns a full method name with arguments.
*/
public static String getFullMethodName(String methodName, Class> []params)
{
String name = methodName + "(";
for (int i = 0; i < params.length; i++) {
if (i != 0)
name += ", ";
name += params[i].getSimpleName();
}
return name + ")";
}
/**
* Returns an error.
*/
public ConfigException error(String msg)
{
if (_isInit && _filename != null)
return new LineConfigException(_filename, _line, msg);
else if (_isInit && ! "".equals(_location))
return new LineConfigException(_location + msg);
else
return new ConfigException(msg);
}
/**
* Returns an error.
*/
public RuntimeException error(Exception e)
{
if (_filename != null)
return LineConfigException.create(_filename, _line, e);
else if (_location != null)
return ConfigException.createLine(_location, e);
else
return ConfigException.create(e);
}
@Override
public String toString()
{
return getClass().getSimpleName() + "[" + _ejbName + "]";
}
}