/* * JBoss, the OpenSource J2EE webOS * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jboss.ejb; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.ejb.EJBException; import javax.management.MalformedObjectNameException; import javax.management.MBeanException; import javax.management.ObjectName; import javax.naming.*; import javax.transaction.TransactionManager; import org.jboss.deployment.DeploymentException; import org.jboss.deployment.DeploymentInfo; import org.jboss.ejb.BeanLockManager; import org.jboss.ejb.plugins.local.BaseLocalProxyFactory; import org.jboss.invocation.Invocation; import org.jboss.invocation.InvocationType; import org.jboss.invocation.MarshalledInvocation; import org.jboss.invocation.InvocationStatistics; import org.jboss.logging.Logger; import org.jboss.metadata.ApplicationMetaData; import org.jboss.metadata.BeanMetaData; import org.jboss.metadata.EjbLocalRefMetaData; import org.jboss.metadata.EjbRefMetaData; import org.jboss.metadata.EnvEntryMetaData; import org.jboss.metadata.ResourceEnvRefMetaData; import org.jboss.metadata.ResourceRefMetaData; import org.jboss.naming.ENCThreadLocalKey; import org.jboss.naming.Util; import org.jboss.security.AuthenticationManager; import org.jboss.security.RealmMapping; import org.jboss.system.ServiceMBeanSupport; import org.jboss.util.NestedError; import org.jboss.mx.util.ObjectNameFactory; import org.jboss.mx.util.ObjectNameConverter; /** * This is the base class for all EJB-containers in JBoss. A Container * functions as the central hub of all metadata and plugins. Through this * the container plugins can get hold of the other plugins and any metadata * they need. * *
The EJBDeployer creates instances of subclasses of this class * and calls the appropriate initialization methods. * *
A Container does not perform any significant work, but instead delegates
* to the plugins to provide for all kinds of algorithmic functionality.
*
* @see EJBDeployer
*
* @author Rickard Öberg
* @author Marc Fleury
* @author Scott Stark.
* @author Bill Burke
* @author David Jencks
* @version $Revision: 1.96.2.16 $
*
* @jmx:mbean extends="org.jboss.system.ServiceMBean"
*/
public abstract class Container
extends ServiceMBeanSupport
implements ContainerMBean
{
public final static String BASE_EJB_CONTAINER_NAME =
"jboss.j2ee:service=EJB";
public final static ObjectName EJB_CONTAINER_QUERY_NAME =
ObjectNameFactory.create(BASE_EJB_CONTAINER_NAME + ",*");
/** This is the application that this container is a part of */
protected EjbModule ejbModule;
/**
* This is the local classloader of this container. Used for loading
* resources that must come from the local jar file for the container.
* NOT for loading classes!
*/
protected ClassLoader localClassLoader;
/**
* This is the classloader of this container. All classes and resources that
* the bean uses will be loaded from here. By doing this we make the bean
* re-deployable
*/
protected ClassLoader classLoader;
/** The class loader for remote dynamic classloading */
protected ClassLoader webClassLoader;
/**
* Externally supplied configuration data
*/
private DeploymentInfo di;
/**
* This is the new metadata. it includes information from both ejb-jar and
* jboss.xml the metadata for the application can be accessed trough
* metaData.getApplicationMetaData()
*/
protected BeanMetaData metaData;
/** This is the EnterpriseBean class */
protected Class beanClass;
/** This is the Home interface class */
protected Class homeInterface;
/** This is the Remote interface class */
protected Class remoteInterface;
/** The local home interface class */
protected Class localHomeInterface;
/** The local inteface class */
protected Class localInterface;
/** This is the TransactionManager */
protected TransactionManager tm;
/** This is the SecurityManager */
protected AuthenticationManager sm;
/** This is the realm mapping */
protected RealmMapping rm;
/** The custom security proxy used by the SecurityInterceptor */
protected Object securityProxy;
/** This is the bean lock manager that is to be used */
protected BeanLockManager lockManager;
/** ??? */
protected LocalProxyFactory localProxyFactory =
new BaseLocalProxyFactory();
/** This is a cache for method permissions */
private HashMap methodPermissionsCache = new HashMap();
/** Maps for MarshalledInvocation mapping */
protected Map marshalledInvocationMapping = new HashMap();
/** This Container's codebase, a sequence of URLs separated by spaces */
//protected String codebase = "";
/** ObjectName of Container */
private ObjectName jmxName;
protected HashMap proxyFactories = new HashMap();
/**
* The Proxy factory is set in the Invocation. This TL is used
* for methods that do not have access to the Invocation.
*/
protected ThreadLocal proxyFactoryTL = new ThreadLocal();
/** The number of create invocations that have been made */
protected long createCount;
/** The number of create invocations that have been made */
protected long removeCount;
/** Time statistics for the invoke(Invocation) methods */
protected InvocationStatistics invokeStats = new InvocationStatistics();
/**
* boolean started indicates if this container is currently
* started. if not, calls to non lifecycle methods will raise exceptions.
*/
private boolean started = false;
// Public --------------------------------------------------------
public Class getLocalClass()
{
return localInterface;
}
public Class getLocalHomeClass()
{
return localHomeInterface;
}
/**
* Sets a transaction manager for this container.
*
* @see javax.transaction.TransactionManager
*
* @param tm
*/
public void setTransactionManager(final TransactionManager tm)
{
this.tm = tm;
}
/**
* Returns this container's transaction manager.
*
* @return A concrete instance of javax.transaction.TransactionManager
*/
public TransactionManager getTransactionManager()
{
return tm;
}
public void setSecurityManager(AuthenticationManager sm)
{
this.sm = sm;
}
public AuthenticationManager getSecurityManager()
{
return sm;
}
public BeanLockManager getLockManager()
{
return lockManager;
}
public void setLockManager(final BeanLockManager lockManager)
{
this.lockManager = lockManager;
lockManager.setContainer(this);
}
public void addProxyFactory(String invokerBinding, EJBProxyFactory factory)
{
proxyFactories.put(invokerBinding, factory);
}
public void setRealmMapping(final RealmMapping rm)
{
this.rm = rm;
}
public RealmMapping getRealmMapping()
{
return rm;
}
public void setSecurityProxy(Object proxy)
{
this.securityProxy = proxy;
}
public Object getSecurityProxy()
{
return securityProxy;
}
public EJBProxyFactory getProxyFactory()
{
return (EJBProxyFactory)proxyFactoryTL.get();
}
public void setProxyFactory(Object factory)
{
proxyFactoryTL.set(factory);
}
public EJBProxyFactory lookupProxyFactory(String binding)
{
return (EJBProxyFactory)proxyFactories.get(binding);
}
/**
* Gets the DeploymentInfo for this Container
*
* @return The DeploymentInfo for this Container
*/
public final DeploymentInfo getDeploymentInfo()
{
return di;
}
/**
* Sets the DeploymentInfo of this Container
*
* @param di The new DeploymentInfo to be used
*/
public final void setDeploymentInfo( DeploymentInfo di )
{
this.di = di;
}
/**
* Sets the application deployment unit for this container. All the bean
* containers within the same application unit share the same instance.
*
* @param app application for this container
*/
public void setEjbModule(EjbModule app)
{
if (app == null)
throw new IllegalArgumentException("Null EjbModule");
ejbModule = app;
}
/**
* Gets the application deployment unit for this container. All the bean
* containers within the same application unit share the same instance.
* @jmx:managed-attribute
*/
public EjbModule getEjbModule()
{
return ejbModule;
}
/**
* Gets the number of create invocations that have been made
* @jmx:managed-attribute
*/
public long getCreateCount()
{
return createCount;
}
/**
* Gets the number of remove invocations that have been made
* @jmx:managed-attribute
*/
public long getRemoveCount()
{
return removeCount;
}
/** Gets the invocation statistics collection
* @jmx:managed-attribute
*/
public InvocationStatistics getInvokeStats()
{
return invokeStats;
}
/**
* Sets the local class loader for this container.
* Used for loading resources from the local jar file for this container.
* NOT for loading classes!
*
* @param cl
*/
public void setLocalClassLoader(ClassLoader cl)
{
this.localClassLoader = cl;
}
/**
* Returns the local classloader for this container.
*
* @return The local classloader for this container.
*/
public ClassLoader getLocalClassLoader()
{
return localClassLoader;
}
/**
* Sets the class loader for this container. All the classes and resources
* used by the bean in this container will use this classloader.
*
* @param cl
*/
public void setClassLoader(ClassLoader cl)
{
this.classLoader = cl;
}
/**
* Returns the classloader for this container.
*
* @return
*/
public ClassLoader getClassLoader()
{
return classLoader;
}
/** Get the class loader for dynamic class loading via http.
*/
public ClassLoader getWebClassLoader()
{
return webClassLoader;
}
/** Set the class loader for dynamic class loading via http.
*/
public void setWebClassLoader(final ClassLoader webClassLoader)
{
this.webClassLoader = webClassLoader;
}
/**
* Sets the meta data for this container. The meta data consists of the
* properties found in the XML descriptors.
*
* @param metaData
*/
public void setBeanMetaData(final BeanMetaData metaData)
{
this.metaData = metaData;
}
/**
* Returns the metadata of this container.
*
* @jmx:managed-attribute
* @return metaData;
*/
public BeanMetaData getBeanMetaData()
{
return metaData;
}
/**
* Returns the permissions for a method. (a set of roles)
*
* @return assemblyDescriptor;
*/
public Set getMethodPermissions(Method m, InvocationType iface)
{
Set permissions;
if (methodPermissionsCache.containsKey(m))
{
permissions = (Set) methodPermissionsCache.get( m );
}
else
{
String name = m.getName();
Class[] sig = m.getParameterTypes();
permissions = getBeanMetaData().getMethodPermissions(name, sig, iface);
methodPermissionsCache.put(m, permissions);
}
return permissions;
}
/**
* Returns the bean class instance of this container.
*
* @return instance of the Enterprise bean class.
*/
public Class getBeanClass()
{
return beanClass;
}
/**
* Returns a new instance of the bean class or a subclass of the bean class.
* This factory style method is speciffically used by a container to supply
* an implementation of the abstract accessors in EJB2.0, but could be
* usefull in other situations. This method should ALWAYS be used instead
* of getBeanClass().newInstance();
*
* @return the new instance
*
* @see java.lang.Class#newInstance
*/
public Object createBeanClassInstance() throws Exception {
return getBeanClass().newInstance();
}
/**
* Sets the codebase of this container.
*
* @param codebase a possibly empty, but non null String with
* a sequence of URLs separated by spaces
* /
public void setCodebase(final String codebase)
{
if (codebase != null)
this.codebase = codebase;
}
*/
/**
* Gets the codebase of this container.
*
* @return this container's codebase String, a sequence of URLs
* separated by spaces
* /
public String getCodebase()
{
return codebase;
}
*/
/** Build a JMX name using the pattern jboss.j2ee:service=EJB,jndiName=[jndiName]
where the [jndiName] is either the bean remote home JNDI binding, or
the local home JNDI binding if the bean has no remote interfaces.
*/
public ObjectName getJmxName()
{
if (jmxName == null)
{
BeanMetaData beanMetaData = getBeanMetaData();
if (beanMetaData == null)
{
throw new IllegalStateException("Container metaData is null");
}
String jndiName = beanMetaData.getContainerObjectNameJndiName();
if (jndiName == null)
{
throw new IllegalStateException("Container jndiName is null");
}
// The name must be escaped since the jndiName may be arbitrary
String name = BASE_EJB_CONTAINER_NAME + ",jndiName=" + jndiName;
try
{
jmxName = ObjectNameConverter.convert(name);
}
catch(MalformedObjectNameException e)
{
throw new RuntimeException("Failed to create ObjectName, msg="+e.getMessage());
}
}
return jmxName;
}
/**
* The EJBDeployer calls this method. The EJBDeployer has set
* all the plugins and interceptors that this bean requires and now proceeds
* to initialize the chain. The method looks for the standard classes in
* the URL, sets up the naming environment of the bean. The concrete
* container classes should override this method to introduce
* implementation specific initialization behaviour.
*
* @throws Exception if loading the bean class failed
* (ClassNotFoundException) or setting up "java:"
* naming environment failed (DeploymentException)
*/
protected void createService() throws Exception
{
// Acquire classes from CL
beanClass = classLoader.loadClass(metaData.getEjbClass());
if (metaData.getLocalHome() != null)
localHomeInterface = classLoader.loadClass(metaData.getLocalHome());
if (metaData.getLocal() != null)
localInterface = classLoader.loadClass(metaData.getLocal());
localProxyFactory.setContainer( this );
localProxyFactory.create();
if (localHomeInterface != null)
ejbModule.addLocalHome(this, localProxyFactory.getEJBLocalHome() );
}
/**
* A default implementation of starting the container service.
* The container registers it's dynamic MBean interface in the JMX base.
*
* The concrete container classes should override this method to introduce
* implementation specific start behaviour.
*
* @todo implement the service lifecycle methods in an xmbean interceptor so
* non lifecycle managed ops are blocked when mbean is not started.
*
* @throws Exception An exception that occured during start
*/
protected void startService() throws Exception
{
// Setup "java:comp/env" namespace
setupEnvironment();
started = true;
localProxyFactory.start();
}
/**
* A default implementation of stopping the container service (no-op). The
* concrete container classes should override this method to introduce
* implementation specific stop behaviour.
*/
protected void stopService() throws Exception
{
started = false;
localProxyFactory.stop();
teardownEnvironment();
}
/**
* A default implementation of destroying the container service (no-op).
* The concrete container classes should override this method to introduce
* implementation specific destroy behaviour.
*/
protected void destroyService() throws Exception
{
localProxyFactory.destroy();
ejbModule.removeLocalHome( this );
this.classLoader = null;
this.webClassLoader = null;
this.localClassLoader = null;
this.ejbModule = null;
// this.lockManager = null; Setting this to null causes AbstractCache
// to fail on undeployment
di = null;
metaData = null;
beanClass = null;
homeInterface = null;
remoteInterface = null;
localHomeInterface = null;
localInterface = null;
tm = null;
sm = null;
rm = null;
securityProxy = null;
methodPermissionsCache.clear();
proxyFactories.clear();
invokeStats.resetStats();
marshalledInvocationMapping.clear();
proxyFactories.clear();
proxyFactoryTL = null;
}
/**
* This method is called when a method call comes
* in on the Home object. The Container forwards this call to the
* interceptor chain for further processing.
*
* @param mi the object holding all info about this invocation
* @return the result of the home invocation
*
* @throws Exception
*/
public abstract Object internalInvokeHome(Invocation mi)
throws Exception;
/**
* This method is called when a method call comes
* in on an EJBObject. The Container forwards this call to the interceptor
* chain for further processing.
*
* @param id the id of the object being invoked. May be null
* if stateless
* @param method the method being invoked
* @param args the parameters
* @return the result of the invocation
*
* @throws Exception
*/
public abstract Object internalInvoke(Invocation mi)
throws Exception;
abstract Interceptor createContainerInterceptor();
public abstract void addInterceptor(Interceptor in);
/**
* @jmx:managed-operation
*
* @param mi
* @return
* @throws Exception
*/
public Object invoke(Invocation mi)
throws Exception
{
Thread currentThread = Thread.currentThread();
ClassLoader callerClassLoader = currentThread.getContextClassLoader();
long start = System.currentTimeMillis();
Method m = null;
Object type = null;
try
{
currentThread.setContextClassLoader(this.classLoader);
// Check against home, remote, localHome, local, getHome,
// getRemote, getLocalHome, getLocal
type = mi.getType();
// stat gathering: concurrent calls
this.invokeStats.callIn();
if(type == InvocationType.REMOTE ||
type == InvocationType.LOCAL)
{
if (mi instanceof MarshalledInvocation)
{
((MarshalledInvocation) mi).setMethodMap(
marshalledInvocationMapping);
if (log.isTraceEnabled())
{
log.trace("METHOD REMOTE INVOKE "+
mi.getObjectName()+"||"+
mi.getMethod().getName()+"||");
}
}
m = mi.getMethod();
return internalInvoke(mi);
}
else if(type == InvocationType.HOME ||
type == InvocationType.LOCALHOME)
{
if (mi instanceof MarshalledInvocation)
{
((MarshalledInvocation) mi).setMethodMap(
marshalledInvocationMapping);
if (log.isTraceEnabled())
{
log.trace("METHOD HOME INVOKE " +
mi.getObjectName() + "||"+
mi.getMethod().getName() + "||"+
mi.getArguments().toString());
}
}
m = mi.getMethod();
return internalInvokeHome(mi);
}
else
{
throw new MBeanException(new IllegalArgumentException(
"Unknown invocation type: " + type));
}
}
finally
{
if( m != null )
{
long end = System.currentTimeMillis();
long elapsed = end - start;
this.invokeStats.updateStats(m, elapsed);
}
// stat gathering: concurrent calls
this.invokeStats.callOut();
currentThread.setContextClassLoader(callerClassLoader);
}
}
// Private -------------------------------------------------------
/**
* This method sets up the naming environment of the bean.
* We create the java:comp/env namespace with properties, EJB-References,
* and DataSource ressources.
*/
private void setupEnvironment() throws Exception
{
boolean debug = log.isDebugEnabled();
BeanMetaData beanMetaData = getBeanMetaData();
if (debug)
{
log.debug("Begin java:comp/env for EJB: "+beanMetaData.getEjbName());
log.debug("TCL: "+Thread.currentThread().getContextClassLoader());
}
// Since the BCL is already associated with this thread we can start
// using the java: namespace directly
Context ctx = (Context) new InitialContext().lookup("java:comp");
Context envCtx = ctx.createSubcontext("env");
// Bind environment properties
{
Iterator enum = beanMetaData.getEnvironmentEntries();
while(enum.hasNext())
{
EnvEntryMetaData entry = (EnvEntryMetaData)enum.next();
if (debug) {
log.debug("Binding env-entry: "+entry.getName()+" of type: "+
entry.getType()+" to value:"+entry.getValue());
}
EnvEntryMetaData.bindEnvEntry(envCtx, entry);
}
}
// Bind EJB references
{
Iterator enum = beanMetaData.getEjbReferences();
while(enum.hasNext())
{
EjbRefMetaData ref = (EjbRefMetaData)enum.next();
if (debug)
log.debug("Binding an EJBReference "+ref.getName());
if (ref.getLink() != null)
{
// Internal link
String linkName = ref.getLink();
String jndiName = EjbUtil.findEjbLink(server, di, linkName);
if (debug)
{
log.debug("Binding "+ref.getName()+
" to ejb-link: "+linkName+" -> "+jndiName);
}
if( jndiName == null )
{
String msg = "Failed to resolve ejb-link: "+linkName
+" make by ejb-name: "+ref.getName();
throw new DeploymentException(msg);
}
Util.bind(envCtx,
ref.getName(),
new LinkRef(jndiName));
}
else
{
// Get the invoker specific ejb-ref mappings
Iterator it = beanMetaData.getInvokerBindings();
Reference reference = null;
while (it.hasNext())
{
String invokerBinding = (String)it.next();
// Check for an invoker level jndi-name
String name = ref.getInvokerBinding(invokerBinding);
// Check for an global jndi-name
if (name == null)
name = ref.getJndiName();
if (name == null)
{
throw new DeploymentException
("ejb-ref "+ref.getName()+
", expected either ejb-link in ejb-jar.xml or " +
"jndi-name in jboss.xml");
}
StringRefAddr addr = new StringRefAddr(invokerBinding, name);
log.debug("adding " + invokerBinding + ":" + name +
" to Reference");
if (reference == null)
{
reference = new Reference("javax.naming.LinkRef",
ENCThreadLocalKey.class.getName(),
null);
}
reference.add(addr);
}
// If there were invoker bindings create bind the reference
if (reference != null)
{
if (ref.getJndiName() != null)
{
// Add default for the bean level ejb-ref/jndi-name
StringRefAddr addr =
new StringRefAddr("default", ref.getJndiName());
reference.add(addr);
}
if ( reference.size() == 1 && reference.get("default") == null )
{
/* There is only one invoker binding and its not default so
create a default binding to allow the link to have a value
when accessed without an invoker active.
*/
StringRefAddr addr = (StringRefAddr) reference.get(0);
String target = (String) addr.getContent();
StringRefAddr addr1 = new StringRefAddr("default", target);
reference.add(addr1);
}
Util.bind(envCtx, ref.getName(), reference);
}
else
{
// Bind the bean level ejb-ref/jndi-name
if (ref.getJndiName() == null)
{
throw new DeploymentException("ejb-ref " + ref.getName()+
", expected either ejb-link in ejb-jar.xml " +
"or jndi-name in jboss.xml");
}
Util.bind(envCtx,
ref.getName(),
new LinkRef(ref.getJndiName()));
}
}
}
}
// Bind Local EJB references
{
Iterator enum = beanMetaData.getEjbLocalReferences();
// unique key name
String localJndiName = beanMetaData.getLocalJndiName();
while(enum.hasNext())
{
EjbLocalRefMetaData ref = (EjbLocalRefMetaData)enum.next();
String refName = ref.getName();
log.debug("Binding an EJBLocalReference "+ref.getName());
if (ref.getLink() != null)
{
// Internal link
log.debug("Binding "+refName+" to bean source: "+ref.getLink());
String jndiName = EjbUtil.findLocalEjbLink(server, di,
ref.getLink());
Util.bind(envCtx,
ref.getName(),
new LinkRef(jndiName));
}
else
{
// Bind the bean level ejb-local-ref/local-jndi-name
if (ref.getJndiName() == null)
{
throw new DeploymentException("ejb-local-ref " + ref.getName()+
", expected either ejb-link in ejb-jar.xml " +
"or local-jndi-name in jboss.xml");
}
Util.bind(envCtx,
ref.getName(),
new LinkRef(ref.getJndiName()));
}
}
}
// Bind resource references
{
Iterator enum = beanMetaData.getResourceReferences();
// let's play guess the cast game ;) New metadata should fix this.
ApplicationMetaData application =
beanMetaData.getApplicationMetaData();
while(enum.hasNext())
{
ResourceRefMetaData ref = (ResourceRefMetaData)enum.next();
String resourceName = ref.getResourceName();
String finalName = application.getResourceByName(resourceName);
// If there was no resource-manager specified then an immeadiate
// jndi-name or res-url name should have been given
if (finalName == null)
finalName = ref.getJndiName();
if (finalName == null)
{
// the application assembler did not provide a resource manager
// if the type is javax.sql.Datasoure use the default one
if (ref.getType().equals("javax.sql.DataSource"))
{
// Go through JNDI and look for DataSource - use the first one
Context dsCtx = new InitialContext();
try
{
// Check if it is available in JNDI
dsCtx.lookup("java:/DefaultDS");
finalName = "java:/DefaultDS";
}
catch (Exception e)
{
if (debug)
log.debug("failed to lookup DefaultDS; ignoring", e);
}
finally
{
dsCtx.close();
}
}
// Default failed? Warn user and move on
// POTENTIALLY DANGEROUS: should this be a critical error?
if (finalName == null)
{
log.warn("No resource manager found for " +
ref.getResourceName());
continue;
}
}
if (ref.getType().equals("java.net.URL"))
{
// URL bindings
if (debug)
log.debug("Binding URL: " + ref.getRefName() +
" to JDNI ENC as: " + finalName);
Util.bind(envCtx, ref.getRefName(), new URL(finalName));
}
else
{
// Resource Manager bindings, should validate the type...
if (debug) {
log.debug("Binding resource manager: "+ref.getRefName()+
" to JDNI ENC as: " +finalName);
}
Util.bind(envCtx, ref.getRefName(), new LinkRef(finalName));
}
}
}
// Bind resource env references
{
Iterator enum = beanMetaData.getResourceEnvReferences();
while( enum.hasNext() )
{
ResourceEnvRefMetaData resRef =
(ResourceEnvRefMetaData) enum.next();
String encName = resRef.getRefName();
String jndiName = resRef.getJndiName();
// Should validate the type...
if (debug)
log.debug("Binding env resource: " + encName +
" to JDNI ENC as: " +jndiName);
Util.bind(envCtx, encName, new LinkRef(jndiName));
}
}
// Create a java:comp/env/security/security-domain link to the container
// or application security-domain if one exists so that access to the
// security manager can be made without knowing the global jndi name.
String securityDomain =
metaData.getContainerConfiguration().getSecurityDomain();
if( securityDomain == null )
securityDomain = metaData.getApplicationMetaData().getSecurityDomain();
if( securityDomain != null )
{
if (debug) {
log.debug("Binding securityDomain: "+securityDomain+
" to JDNI ENC as: security/security-domain");
}
Util.bind(
envCtx,
"security/security-domain",
new LinkRef(securityDomain));
Util.bind(
envCtx,
"security/subject",
new LinkRef(securityDomain+"/subject"));
}
if (debug)
log.debug("End java:comp/env for EJB: "+beanMetaData.getEjbName());
}
/**
*The teardownEnvironment method unbinds everything from
* the comp/env context. It would be better do destroy the env context
* but destroyContext is not currently implemented..
*
* @exception Exception if an error occurs
*/
private void teardownEnvironment() throws Exception
{
Context ctx = (Context)new InitialContext().lookup("java:comp");
ctx.unbind("env");
log.debug("Removed bindings from java:comp/env for EJB: "+getBeanMetaData().getEjbName());
}
/**
* The base class for container interceptors.
*
*
* All container interceptors perform the same basic functionality * and only differ slightly. */ protected abstract class AbstractContainerInterceptor implements Interceptor { protected final Logger log = Logger.getLogger(this.getClass()); public void setContainer(Container con) {} public void setNext(Interceptor interceptor) {} public Interceptor getNext() { return null; } public void create() {} public void start() {} public void stop() {} public void destroy() {} protected void rethrow(Exception e) throws Exception { if (e instanceof IllegalAccessException) { // Throw this as a bean exception...(?) throw new EJBException(e); } else if(e instanceof InvocationTargetException) { Throwable t = ((InvocationTargetException)e).getTargetException(); if (t instanceof EJBException) { throw (EJBException)t; } else if (t instanceof Exception) { throw (Exception)t; } else if (t instanceof Error) { throw (Error)t; } else { throw new NestedError("Unexpected Throwable", t); } } throw e; } // Monitorable implementation ------------------------------------ public void sample(Object s) { // Just here to because Monitorable request it but will be removed soon } public Map retrieveStatistic() { return null; } public void resetStatistic() { } } } /* vim:ts=3:sw=3:et */