FileDocCategorySizeDatePackage
BaseContainer.javaAPI DocGlassfish v2 API169530Thu Jul 26 18:50:48 BST 2007com.sun.ejb.containers

BaseContainer

public abstract class BaseContainer extends Object implements Container, com.sun.ejb.spi.stats.EJBStatsProvider
This class implements part of the com.sun.ejb.Container interface. It implements the container's side of the EJB-to-Container contract defined by the EJB 2.0 spec. It contains code shared by SessionBeans, EntityBeans and MessageDrivenBeans. Its subclasses provide the remaining implementation of the container functionality.

Fields Summary
protected static final Logger
_logger
protected static final Class[]
NO_PARAMS
protected Object[]
logParams
private static final int
EJB_INTF_METHODS_LENGTH
static final int
EJBHome_remove_Handle
static final int
EJBHome_remove_Pkey
static final int
EJBHome_getEJBMetaData
static final int
EJBHome_getHomeHandle
static final int
EJBLocalHome_remove_Pkey
static final int
EJBObject_getEJBHome
static final int
EJBObject_getPrimaryKey
static final int
EJBObject_remove
static final int
EJBObject_getHandle
static final int
EJBObject_isIdentical
static final int
EJBLocalObject_getEJBLocalHome
static final int
EJBLocalObject_getPrimaryKey
static final int
EJBLocalObject_remove
static final int
EJBLocalObject_isIdentical
static final int
EJBHome_create
static final int
EJBLocalHome_create
private static final boolean[]
EJB_INTF_METHODS_INFO
private static final String
USER_TX
private static final byte
HOME_KEY
private static final byte[]
homeInstanceKey
protected ClassLoader
loader
protected Class
ejbClass
protected Method
ejbPassivateMethod
protected Method
ejbActivateMethod
protected Method
ejbRemoveMethod
protected Method
ejbTimeoutMethod
protected Class
webServiceEndpointIntf
protected boolean
isWebServiceEndpoint
private boolean
isTimedObject_
protected boolean
isLocal
Data members for Local views *
protected boolean
hasLocalHomeView
protected boolean
hasLocalBusinessView
protected Class
localHomeIntf
private Class
localIntf
protected EJBLocalHome
ejbLocalHome
protected EJBLocalHomeImpl
ejbLocalHomeImpl
private Constructor
ejbLocalObjectProxyCtor
protected Class
localBusinessHomeIntf
protected Set
localBusinessIntfs
protected GenericEJBLocalHome
ejbLocalBusinessHome
protected EJBLocalHomeImpl
ejbLocalBusinessHomeImpl
private Constructor
ejbLocalBusinessObjectProxyCtor
protected boolean
isRemote
Data members for Remote views *
protected boolean
hasRemoteHomeView
protected boolean
hasRemoteBusinessView
protected Class
homeIntf
protected Class
remoteIntf
protected EJBHomeImpl
ejbHomeImpl
protected EJBHome
ejbHome
protected EJBHome
ejbHomeStub
private Class
ejbObjectProxyClass
private Constructor
ejbObjectProxyCtor
protected RemoteReferenceFactory
remoteHomeRefFactory
private String
remoteHomeJndiName
protected Class
remoteBusinessHomeIntf
protected EJBHomeImpl
ejbRemoteBusinessHomeImpl
protected EJBHome
ejbRemoteBusinessHome
protected EJBHome
ejbRemoteBusinessHomeStub
private String
remoteBusinessHomeJndiName
private String
remoteBusinessJndiName
protected Map
remoteBusinessIntfInfo
protected EJBMetaData
metadata
protected ProtocolManager
protocolMgr
protected J2EETransactionManager
transactionManager
protected NamingManager
namingManager
protected com.sun.enterprise.SecurityManager
securityManager
protected ContainerFactoryImpl
containerFactory
InvocationManager
invocationManager
protected InjectionManager
injectionManager
Switch
theSwitch
protected boolean
isSession
protected boolean
isStatelessSession
protected boolean
isStatefulSession
protected boolean
isMessageDriven
protected boolean
isEntity
protected com.sun.enterprise.deployment.EjbDescriptor
ejbDescriptor
protected String
componentId
protected Map
invocationInfoMap
protected Map
webServiceInvocationInfoMap
private com.sun.ejb.containers.util.MethodMap
proxyInvocationInfoMap
protected Method[]
ejbIntfMethods
protected InvocationInfo[]
ejbIntfMethodInfo
protected Properties
envProps
boolean
isBeanManagedTran
protected boolean
debugMonitorFlag
private static LocalStringManagerImpl
localStrings
private ThreadLocal
threadLocalContext
protected static final int
CONTAINER_INITIALIZING
protected static final int
CONTAINER_STARTED
protected static final int
CONTAINER_STOPPED
protected static final int
CONTAINER_UNDEPLOYED
protected static final int
CONTAINER_ON_HOLD
protected int
containerState
protected int
cmtTimeoutInSeconds
protected int
statCreateCount
protected int
statRemoveCount
protected HashMap
methodMonitorMap
protected boolean
monitorOn
protected com.sun.ejb.base.stats.MonitoringRegistryMediator
registryMediator
protected com.sun.ejb.spi.stats.EJBMethodStatsManager
ejbMethodStatsManager
private String
_debugDescription
protected TimedObjectMonitorableProperties
toMonitorProps
protected com.sun.enterprise.admin.monitor.callflow.Agent
callFlowAgent
protected com.sun.enterprise.admin.monitor.callflow.CallFlowInfo
callFlowInfo
protected com.sun.ejb.containers.interceptors.InterceptorManager
interceptorManager
protected static final Class[]
lifecycleCallbackAnnotationClasses
private Set
monitoredGeneratedClasses
Constructors Summary
protected BaseContainer(com.sun.enterprise.deployment.EjbDescriptor ejbDesc, ClassLoader loader)
This constructor is called from ContainerFactoryImpl when an EJB Jar is deployed.

    
                     
        
         
    
        try {
            this.loader = loader;
            this.ejbDescriptor = ejbDesc;
	    createMonitoringRegistryMediator();

            logParams = new Object[1];
            logParams[0] =  ejbDesc.getName();
            
            theSwitch = Switch.getSwitch();
            protocolMgr = theSwitch.getProtocolManager();
            invocationManager = theSwitch.getInvocationManager();
            injectionManager = theSwitch.getInjectionManager();
            namingManager = theSwitch.getNamingManager();
            transactionManager = theSwitch.getTransactionManager();
            containerFactory = 
                    (ContainerFactoryImpl)theSwitch.getContainerFactory();
            
            // Add this container/descriptor to the table in Switch
            theSwitch.setDescriptorFor(this, ejbDescriptor);

            // get Class objects for creating new EJBs
            ejbClass = loader.loadClass(ejbDescriptor.getEjbImplClassName());
            
            IASEjbExtraDescriptors iased = ejbDesc.getIASEjbExtraDescriptors();
            cmtTimeoutInSeconds = iased.getCmtTimeoutInSeconds();

            if( ejbDescriptor.getType().equals(EjbMessageBeanDescriptor.TYPE) )
            {
                isMessageDriven = true;
                EjbMessageBeanDescriptor mdb =
                (EjbMessageBeanDescriptor) ejbDescriptor;

                if ( mdb.getTransactionType().equals("Bean") ) {
                    isBeanManagedTran = true;
                }
                else {
                    isBeanManagedTran = false;
                }
            }
            else {
                
                if(ejbDescriptor.getType().equals(EjbEntityDescriptor.TYPE)) {
                    isEntity = true;
                } else {
                    isSession = true;
                    EjbSessionDescriptor sd = 
                        (EjbSessionDescriptor)ejbDescriptor;
                    
                    isStatelessSession = sd.isStateless();
                    isStatefulSession  = !isStatelessSession;

                    if( isStatefulSession ) {
                        if( !Serializable.class.isAssignableFrom(ejbClass) ) {
                            ejbClass = EJBUtils.loadGeneratedSerializableClass
                                (loader, ejbClass.getName());
                        }
                    }
                    
                    if ( sd.getTransactionType().equals("Bean") ) {
                        isBeanManagedTran = true;
                    } else {
                        isBeanManagedTran = false;
                    }

                }
                
                if ( ejbDescriptor.isRemoteInterfacesSupported() ) {

                    checkProtocolManager();
                    isRemote = true;
                    hasRemoteHomeView = true;

                    String homeClassName = ejbDescriptor.getHomeClassName();

                    homeIntf = loader.loadClass(homeClassName);
                    remoteIntf = loader.loadClass
                        (ejbDescriptor.getRemoteClassName());

                    String id = 
                        Long.toString(ejbDescriptor.getUniqueId()) + "_RHome";

                    remoteHomeRefFactory = 
                        protocolMgr.getRemoteReferenceFactory(this, true, id);

                }

                if( ejbDescriptor.isRemoteBusinessInterfacesSupported() ) {
                    
                    checkProtocolManager();
                    
                    isRemote = true;
                    hasRemoteBusinessView = true;

                    remoteBusinessHomeIntf = 
                        EJBUtils.loadGeneratedGenericEJBHomeClass(loader);

                    for(String next : 
                            ejbDescriptor.getRemoteBusinessClassNames()) {

                        // The generated remote business interface and the
                        // client wrapper for the business interface are 
                        // produced dynamically.  The following call must be 
                        // made before any EJB 3.0 Remote business interface 
                        // runtime behavior is needed for a particular
                        // classloader.
                        EJBUtils.loadGeneratedRemoteBusinessClasses
                            (loader, next);
                        
                        String nextGen =
                            EJBUtils.getGeneratedRemoteIntfName(next);

                        Class genRemoteIntf = loader.loadClass(nextGen);

                        RemoteBusinessIntfInfo info = 
                            new RemoteBusinessIntfInfo();
                        info.generatedRemoteIntf = genRemoteIntf;
                        info.remoteBusinessIntf  = loader.loadClass(next);

                        // One remote reference factory for each remote 
                        // business interface.  Id must be unique across
                        // all ejb containers.
                        String id = Long.toString(ejbDescriptor.getUniqueId()) 
                             + "_RBusiness" + "_" + genRemoteIntf.getName();

                        info.referenceFactory = protocolMgr.
                            getRemoteReferenceFactory(this, false, id);

                        remoteBusinessIntfInfo.put(genRemoteIntf.getName(),
                                                   info);
                        
                        addToGeneratedMonitoredMethodInfo(nextGen, genRemoteIntf); 
                    }

                }

                if ( ejbDescriptor.isLocalInterfacesSupported() ) {
                    // initialize class objects for LocalHome/LocalIntf etc.
                    isLocal = true;
                    hasLocalHomeView = true;

                    String localHomeClassName = 
                        ejbDescriptor.getLocalHomeClassName();

                    localHomeIntf = 
                        loader.loadClass(localHomeClassName);
                    localIntf = loader.loadClass
                        (ejbDescriptor.getLocalClassName());
                }

                if( ejbDescriptor.isLocalBusinessInterfacesSupported() ) {
                    isLocal = true;
                    hasLocalBusinessView = true;                    

                    localBusinessHomeIntf = GenericEJBLocalHome.class;

                    for(String next : 
                            ejbDescriptor.getLocalBusinessClassNames() ) {
                        Class clz = loader.loadClass(next);
                        localBusinessIntfs.add(clz);
                        addToGeneratedMonitoredMethodInfo(next, clz);
                    }
                }

                if( isStatelessSession ) {
                    EjbBundleDescriptor bundle =
                        ejbDescriptor.getEjbBundleDescriptor();
                    WebServicesDescriptor webServices = bundle.getWebServices();
                    Collection endpoints =
                        webServices.getEndpointsImplementedBy(ejbDescriptor);
                    // JSR 109 doesn't require support for a single ejb
                    // implementing multiple port components.
                    if( endpoints.size() == 1 ) {
                        WebServiceEndpoint endpoint = (WebServiceEndpoint)
                            endpoints.iterator().next();
                        webServiceEndpointIntf = loader.loadClass
                           (ejbDescriptor.getWebServiceEndpointInterfaceName());
                        isWebServiceEndpoint = true;
                    }
                }

                try{
                    // get Method objects for ejbPassivate/Activate/ejbRemove
                    ejbPassivateMethod = 
                        ejbClass.getMethod("ejbPassivate", NO_PARAMS);
                    ejbActivateMethod = 
                        ejbClass.getMethod("ejbActivate", NO_PARAMS);
                    ejbRemoveMethod = 
                        ejbClass.getMethod("ejbRemove", NO_PARAMS);
                } catch(NoSuchMethodException nsme) {
                    // ignore.  Will happen for EJB 3.0 session beans
                }

                
            }
            
            if ( ejbDescriptor.isTimedObject() ) {
                MethodDescriptor ejbTimeoutMethodDesc = 
                    ejbDescriptor.getEjbTimeoutMethod();
                Method method = ejbTimeoutMethodDesc.getMethod(ejbDescriptor);
                
                Class[] params = method.getParameterTypes();
                if( (params.length == 1) &&
                    (params[0] == javax.ejb.Timer.class) &&
                    (method.getReturnType() == Void.TYPE) ) {
                    
                    isTimedObject_ = true;
                    ejbTimeoutMethod = method;

                    final Method ejbTimeoutAccessible = ejbTimeoutMethod;
                    // Since timeout method can have any kind of access
                    // setAccessible to true.
                    if(System.getSecurityManager() == null) {
                        if( !ejbTimeoutAccessible.isAccessible() ) {
                            ejbTimeoutAccessible.setAccessible(true);
                        }
                    } else {
                        java.security.AccessController.doPrivileged(
                                new java.security.PrivilegedExceptionAction() {
                            public java.lang.Object run() throws Exception {
                                if( !ejbTimeoutAccessible.isAccessible() ) {
                                    ejbTimeoutAccessible.setAccessible(true);
                                }
                                return null;
                            }
                        });
                    }
                } else {
                    throw new EJBException
                        ("Invalid @Timeout signature for " + 
                         method + " @Timeout method must return void" +
                         " and take a single javax.ejb.Timer param");
                }
            }
            if( isTimedObject_ ) {
                if( !isStatefulSession ) {
                    EJBTimerService timerService = 
                        containerFactory.getEJBTimerService();
                    if( timerService != null ) {
                        timerService.timedObjectCount();
                    }
                } else {
                    isTimedObject_ = false;
                    throw new EJBException("Ejb " + ejbDescriptor.getName() +
                        " is invalid. Stateful session ejbs can not" +
                        " be Timed Objects");
                }
            }

            preInitialize(ejbDesc, loader);
            
            initializeEjbInterfaceMethods();

            initializeInterceptorManager();

            
            initializeInvocationInfo();

            setupEnvironment();
        } catch (Exception ex) {
            _logger.log(Level.FINE,"ejb.basecontainer_exception",logParams);
            _logger.log(Level.FINE,"", ex);
            throw ex;
        }

	_debugDescription = "ejbName: " + ejbDescriptor.getName()
		+ "; containerId: " + ejbDescriptor.getUniqueId();
	_logger.log(Level.FINE, "Instantiated container for: "
		+ _debugDescription);
    
Methods Summary
protected abstract ComponentContext_getContext(Invocation inv)

private InvocationInfoaddInvocationInfo(java.lang.reflect.Method method, java.lang.String methodIntf, java.lang.Class originalIntf)

        boolean flushEnabled = findFlushEnabledAttr(method, methodIntf);
        int txAttr = findTxAttr(method, methodIntf);
        InvocationInfo info = createInvocationInfo
            (method, txAttr, flushEnabled, methodIntf, originalIntf);
        boolean isHomeIntf = (methodIntf.equals(MethodDescriptor.EJB_HOME)
                || methodIntf.equals(MethodDescriptor.EJB_LOCALHOME));
        if (! isHomeIntf) {
            Method beanMethod = null;
            try {
                beanMethod = getEJBClass().getMethod(
                    method.getName(), method.getParameterTypes());
            } catch (NoSuchMethodException nsmEx) {
                //TODO
            }
            if (beanMethod != null) {
                MethodDescriptor md = new MethodDescriptor(beanMethod, MethodDescriptor.EJB_BEAN);
                info.interceptorChain = interceptorManager.getAroundInvokeChain(md, beanMethod);
            }
        }
        if( methodIntf.equals(MethodDescriptor.EJB_WEB_SERVICE) ) {
            webServiceInvocationInfoMap.put(method, info);
        } else {
            invocationInfoMap.put(method, info);        
        }
                
        return info;
    
private voidaddToGeneratedMonitoredMethodInfo(java.lang.String qualifiedClassName, java.lang.Class generatedClass)

        monitoredGeneratedClasses.add(generatedClass);
    
abstract voidafterBegin(EJBContextImpl context)

abstract voidafterCompletion(EJBContextImpl context, int status)

public voidassertValidLocalObject(java.lang.Object o)

        boolean valid = false;
        String errorMsg = "";

        if( (o != null) && (o instanceof EJBLocalObject) ) {
            // Given object is always the client view EJBLocalObject.
            // Use utility method to translate it to EJBLocalObjectImpl
            // so we handle both the generated and proxy case.
            EJBLocalObjectImpl ejbLocalObjImpl = 
                EJBLocalObjectImpl.toEJBLocalObjectImpl( (EJBLocalObject) o);
            BaseContainer otherContainer = 
                (BaseContainer) ejbLocalObjImpl._getContainerInternal();
            if( otherContainer.getContainerId() == getContainerId() ) {
                valid = true;
            } else {
                errorMsg = localStrings.getLocalString
                    ("containers.assert_local_obj_bean", "",
                     new Object[] { otherContainer.ejbDescriptor.getName(),
                                    ejbDescriptor.getName() });
            }
        } else {
            errorMsg = (o != null) ? 
               localStrings.getLocalString("containers.assert_local_obj_class",
                   "", new Object[] { o.getClass().getName(), 
                                      ejbDescriptor.getName() }) 
               :
               localStrings.getLocalString("containers.assert_local_obj_null",
                   "", new Object[] { ejbDescriptor.getName() });
        }
        
        if( !valid ) {
            throw new EJBException(errorMsg);
        }
            
    
public voidassertValidRemoteObject(java.lang.Object o)
Asserts validity of RemoteHome objects. This was defined for the J2EE 1.4 implementation and is exposed through Container SPI.

        boolean valid = false;
        String errorMsg = "";
	Exception causeException = null;

        if( (o != null) && (o instanceof EJBObject) ) {
            String className = o.getClass().getName();

            // Given object must be an instance of the remote stub class for
            // this ejb.
            if (hasRemoteHomeView) {
		try {
		    valid = remoteHomeRefFactory.hasSameContainerID(
				(org.omg.CORBA.Object) o);
		} catch (Exception ex) {
		    causeException = ex;
		    errorMsg = localStrings.getLocalString
			("containers.assert_remote_obj_class", "",
			new Object[] { className, ejbDescriptor.getName() });
		    
		}
            } else {
                errorMsg = localStrings.getLocalString
                    ("containers.assert_remote_obj_class", "",
                     new Object[] { className, ejbDescriptor.getName() });
            }
        } else {
            errorMsg = (o != null) ? 
              localStrings.getLocalString("containers.assert_remote_obj_class",
                  "", new Object[] { o.getClass().getName(), 
                                     ejbDescriptor.getName() }) 
              :
              localStrings.getLocalString("containers.assert_remote_obj_null",
                  "", new Object[] { ejbDescriptor.getName() });    
        }

        if( !valid ) {
            if (causeException != null) {
		throw new EJBException(errorMsg, causeException);
	    } else {
		throw new EJBException(errorMsg);
	    }
        }
    
public booleanauthorize(Invocation inv)
Common code to handle EJB security manager authorization call.


        // There are a few paths (e.g. authorizeLocalMethod, 
        // authorizeRemoteMethod, Ejb endpoint pre-handler )
        // for which invocationInfo is not set.  We get better
        // performance with the security manager on subsequent
        // invocations of the same method if invocationInfo is
        // set on the invocation.  However, the authorization
        // does not depend on it being set.  So, try to set
        // invocationInfo but in this case don't treat it as
        // an error if it's not available.  
        if( inv.invocationInfo == null ) {
            
            inv.invocationInfo = getInvocationInfo(inv);
                        
        }

        // Internal methods for 3.0 bean creation so there won't 
        // be corresponding permissions in the security policy file.  
        if( (inv.method.getDeclaringClass() == localBusinessHomeIntf) 
            ||
            (inv.method.getDeclaringClass() == remoteBusinessHomeIntf) ) {
            return true;
        }
       
        boolean authorized = securityManager.authorize(inv);
        
        if( !authorized ) {

            if( inv.context != null ) {
                // This means that an enterprise bean context was created
                // during the authorization call because of a callback from
                // a JACC enterprise bean handler. Since the invocation will 
                // not proceed due to the authorization failure, we need 
                // to release the enterprise bean context.
                releaseContext(inv);
            }
        }

        return authorized;
    
voidauthorizeLocalMethod(int method)
Check if caller is authorized to invoke the method. Only called for EJBLocalObject and EJBLocalHome methods, from EJBLocalHome|ObjectImpl classes.

param
method an integer identifying the method to be checked, must be one of the EJBLocal{Home|Object}_* constants.


        Invocation inv = new Invocation();
        inv.isLocal = true;
        inv.isHome = EJB_INTF_METHODS_INFO[method];
        inv.method = ejbIntfMethods[method];
        inv.invocationInfo = ejbIntfMethodInfo[method];

        if ( !authorize(inv) ) {
            throw new AccessLocalException(
                "Client is not authorized for this invocation.");
        }
    
voidauthorizeRemoteMethod(int method)
Check if caller is authorized to invoke the method. Only called for EJBObject and EJBHome methods, from EJBHome|ObjectImpl classes.

param
method an integer identifying the method to be checked, must be one of the EJB{Home|Object}_* constants.

        Invocation inv = new Invocation();
        inv.isLocal = false;
        inv.isHome = EJB_INTF_METHODS_INFO[method];
        inv.method = ejbIntfMethods[method];
        inv.invocationInfo = ejbIntfMethodInfo[method];

        if ( !authorize(inv) ) {
            AccessException ex = new AccessException(
                "Client is not authorized for this invocation.");
            Throwable t = protocolMgr.mapException(ex);
            if ( t instanceof RuntimeException )
                throw (RuntimeException)t;
            else if ( t instanceof RemoteException )
                throw (RemoteException)t;
            else
                throw ex; // throw the AccessException
        }
    
abstract voidbeforeCompletion(EJBContextImpl context)

booleancallEJBTimeout(RuntimeTimerState timerState, EJBTimerService timerService)

     
        boolean redeliver = false;
     
        if (containerState != CONTAINER_STARTED) {
            throw new EJBException("Attempt to invoke when container is in "
                                   + containerStateToString(containerState));
        }
     
        Invocation inv = new Invocation();
     
        // Let preInvoke do tx attribute lookup.
        inv.transactionAttribute = Container.TX_NOT_INITIALIZED;
     
        // There is never any client tx context so no need to do authorization.
        // If run-as is specified for the bean, it should be used.
        inv.securityPermissions = com.sun.ejb.Container.SEC_UNCHECKED;
     
        inv.method = ejbTimeoutMethod;
        inv.beanMethod = ejbTimeoutMethod;

        // Application must be passed a TimerWrapper.
        Object[] args  = { new TimerWrapper(timerState.getTimerId(),
                                            timerService) };
        
        inv.methodParams = args;
     
        // Delegate to subclass for i.ejbObject / i.isLocal setup.
        doTimerInvocationInit(inv, timerState);
     
        ClassLoader originalClassLoader = null;
     
        try {
            originalClassLoader = Utility.setContextClassLoader(loader);

            preInvoke(inv);

            // AroundInvoke methods don't apply to timeout methods so
            // use invokeTargetBeanMethod() instead of intercept()
            invokeTargetBeanMethod(inv.getBeanMethod(), inv, inv.ejb,
                                   inv.methodParams, null);
     
            if( !isBeanManagedTran && (transactionManager.getStatus() ==
                                       Status.STATUS_MARKED_ROLLBACK) ) {
                redeliver = true;
                _logger.log(Level.FINE, "ejbTimeout called setRollbackOnly");
            }
     
        } catch(InvocationTargetException ite) {
            // A runtime exception thrown from ejbTimeout, independent of
            // its transactional setting(CMT, BMT, etc.), should result in
            // a redelivery attempt.  The instance that threw the runtime
            // exception will be destroyed, as per the EJB spec.
            redeliver = true;
            inv.exception = ite.getCause();
            _logger.log(Level.FINE, "ejbTimeout threw Runtime exception",
                       inv.exception);
        } catch(Throwable c) {
            redeliver = true;
            _logger.log(Level.FINE, "Exception while processing ejbTimeout", c);
            inv.exception = c;
        } finally {

            // Only call postEjbTimeout if there are no errors so far.
            if( !redeliver ) {
                boolean success =                 
                    timerService.postEjbTimeout(timerState.getTimerId());
                redeliver = !success;
            }
            
            postInvoke(inv);

            // If transaction commit fails, set redeliver flag.
            if( (redeliver == false) && (inv.exception != null) ) {
                redeliver = true;
            }

            if( originalClassLoader != null ) {
                Utility.setContextClassLoader(originalClassLoader);
            }

        }
     
        return redeliver;
    
private java.lang.ThrowablecheckExceptionBeanMgTx(EJBContextImpl context, java.lang.Throwable exception, int status)

        Throwable newException = exception;
        // EJB2.0 section 18.3.1, Table 16
        if ( exception != null
        && exception instanceof PreInvokeException ) {
            // A PreInvokeException was thrown, so bean was not invoked
            newException= ((PreInvokeException)exception).exception;
        }
        else if ( status == Status.STATUS_NO_TRANSACTION ) {
            // EJB was invoked, EJB's Tx is complete.
            if ( exception != null )
                newException = checkExceptionNoTx(context, exception);
        }
        else {
            // EJB was invoked, EJB's Tx is incomplete.
            // See EJB2.0 Section 17.6.1
            if ( isSession && !isStatelessSession ) {
                if ( !isSystemUncheckedException(exception) ) {
                    if( isAppExceptionRequiringRollback(exception) ) {
                        transactionManager.rollback();
                    } else {
                        transactionManager.suspend();
                    }
                }
                else {
                    // system/unchecked exception was thrown by EJB
                    try {
                        forceDestroyBean(context);
                    } finally {
                        transactionManager.rollback();
                    }
                    newException = processSystemException(exception);
                }
            }
            else if( isStatelessSession ) { // stateless SessionBean
                try {
                    forceDestroyBean(context);
                } finally {
                    transactionManager.rollback();
                }
                newException = new EJBException(
                    "Stateless SessionBean method returned without" + 
                    " completing transaction");
                _logger.log(Level.FINE,
                    "ejb.incomplete_sessionbean_txn_exception",logParams);
                _logger.log(Level.FINE,"",newException);
            }
            else { // MessageDrivenBean
                try {
                    forceDestroyBean(context);
                } finally {
                    transactionManager.rollback();
                }
                newException = new EJBException(
                    "MessageDrivenBean method returned without" + 
                    " completing transaction");
                _logger.log(Level.FINE,
                    "ejb.incomplete_msgdrivenbean_txn_exception",logParams);
                _logger.log(Level.FINE,"",newException.toString());
                
            }
        }
        return newException;
    
protected java.lang.ThrowablecheckExceptionClientTx(EJBContextImpl context, java.lang.Throwable exception)

        if ( exception instanceof PreInvokeException )
            // A PreInvokeException was thrown, so bean was not invoked
            return ((PreInvokeException)exception).exception;
        
        // If PreInvokeException wasn't thrown, EJB was invoked with client's Tx
        Throwable newException = exception;
        if ( isSystemUncheckedException(exception) ) {
            // Table 15, EJB2.0
            try {
                forceDestroyBean(context);
            } finally {
                transactionManager.setRollbackOnly();
            }
            if ( exception instanceof Exception ) {
                newException = new TransactionRolledbackLocalException(
                	"Exception thrown from bean", (Exception)exception);
            } else {
                newException = new TransactionRolledbackLocalException(
                	"Exception thrown from bean: "+exception.toString());
                newException.initCause(exception);
            }
        } else if( isAppExceptionRequiringRollback(exception ) ) {
            transactionManager.setRollbackOnly();
        }

        return newException;
    
private java.lang.ThrowablecheckExceptionNoTx(EJBContextImpl context, java.lang.Throwable exception)

        if ( exception instanceof PreInvokeException )
            // A PreInvokeException was thrown, so bean was not invoked
            return ((PreInvokeException)exception).exception;
        
        // If PreInvokeException was not thrown, EJB was invoked with no Tx
        Throwable newException = exception;
        if ( isSystemUncheckedException(exception) ) {
            // Table 15, EJB2.0
            newException = processSystemException(exception);
            forceDestroyBean(context);
        }
        return newException;
    
voidcheckExists(EJBLocalRemoteObject ejbObj)
Check if the given EJBObject/LocalObject has been removed.

exception
NoSuchObjectLocalException if the object has been removed.

        throw new EJBException(
            "Internal ERROR: BaseContainer.checkExists called");
    
private voidcheckProtocolManager()

        if (protocolMgr== null) {
            throw new RuntimeException("Protocol manager is null. "
                     + "Possible cause is ORB not started");
        }
    
private voidcheckUnfinishedTx(javax.transaction.Transaction prevTx, Invocation inv)

        try {
            if ( !isMessageDriven && !isStatelessSession && prevTx != null &&
            	prevTx.getStatus() != Status.STATUS_NO_TRANSACTION ) {
                // An unfinished tx exists for the bean.
                // so we cannot invoke the bean with no Tx or a new Tx.
                throw new IllegalStateException(
                    "Bean is associated with a different unfinished transaction");
            }
        } catch (SystemException ex) {
            _logger.log(Level.FINE, "ejb.checkUnfinishedTx_exception", ex);
            throw new EJBException(ex);
        }
    
public voidcheckUserTransactionLookup(ComponentInvocation inv)

        if (! this.isBeanManagedTran) {
            throw new javax.naming.NameNotFoundException("Lookup of java:comp/UserTransaction "
                    + "not allowed for Container managed Transaction beans");
        }
    
private java.lang.ThrowablecompleteNewTx(EJBContextImpl context, java.lang.Throwable exception, int status)

        Throwable newException = exception;
        if ( exception instanceof PreInvokeException )
            newException = ((PreInvokeException)exception).exception;
        
        if ( status == Status.STATUS_NO_TRANSACTION ) {
            // no tx was started, probably an exception was thrown
            // before tm.begin() was called
            return newException;
        }
        
        if ( isSession && !isStatelessSession )
            ((SessionContextImpl)context).setTxCompleting(true);
        
        // A new tx was started, so we must commit/rollback
        if ( newException != null
        && isSystemUncheckedException(newException) ) {
            // EJB2.0 section 18.3.1, Table 15
            // Rollback the Tx we started
            try {
                forceDestroyBean(context);
            } finally {
                transactionManager.rollback();
            }
            newException = processSystemException(newException);
        }
        else {
            try {
                if ( status == Status.STATUS_MARKED_ROLLBACK ) {
                    // EJB2.0 section 18.3.1, Table 15, and 18.3.6:
                    // rollback tx, no exception
                    if (transactionManager.isTimedOut()) {
                        _logger.log(Level.WARNING, "ejb.tx_timeout",
                                    new Object[] { 
                            transactionManager.getTransaction(),
                                ejbDescriptor.getName()});
                    }
                    transactionManager.rollback();
                }
                else {
                    if( (newException != null) &&
                        isAppExceptionRequiringRollback(newException) ) {
                        transactionManager.rollback();
                    } else {
                        // Note: if exception is an application exception
                        // we do a commit as in EJB2.0 Section 18.3.1, 
                        // Table 15. Commit the Tx we started
                        transactionManager.commit();
                    }
                }
            } catch (RollbackException ex) {
                _logger.log(Level.FINE, "ejb.transaction_abort_exception", ex);
                // EJB2.0 section 18.3.6
                newException = new EJBException("Transaction aborted", ex);
            } catch ( Exception ex ) {
                _logger.log(Level.FINE, "ejb.cmt_exception", ex);
                // Commit or rollback failed.
                // EJB2.0 section 18.3.6
                newException = new EJBException("Unable to complete" +
                    " container-managed transaction.", ex);
            }
        }
        return newException;
    
protected static final java.lang.StringcontainerStateToString(int state)

        switch (state) {
            case CONTAINER_INITIALIZING:
                return "Initializing";
            case CONTAINER_STARTED:
                return "Started";
            case CONTAINER_STOPPED:
                return "STOPPED";
            case CONTAINER_UNDEPLOYED:
                return "Undeployed";
            case CONTAINER_ON_HOLD:
                return "ON_HOLD";
        }
        return "Unknown Container state: " + state;
    
protected final voidcreateCallFlowAgent(com.sun.enterprise.admin.monitor.callflow.ComponentType compType)

        this.callFlowAgent = theSwitch.getCallFlowAgent();
        this.callFlowInfo = new CallFlowInfoImpl(
                this, ejbDescriptor, compType);
    
EJBLocalObjectImplcreateEJBLocalBusinessObjectImpl()

        throw new EJBException(
            "Internal ERROR: BaseContainer.createEJBLocalObject called");
    
EJBLocalObjectImplcreateEJBLocalObjectImpl()

        throw new EJBException(
            "Internal ERROR: BaseContainer.createEJBLocalObject called");
    
abstract EJBObjectImplcreateEJBObjectImpl()

private InvocationInfocreateInvocationInfo(java.lang.reflect.Method method, int txAttr, boolean flushEnabled, java.lang.String methodIntf, java.lang.Class originalIntf)
Create invocation info for one method.

param
originalIntf Leaf interface for the given view. Not set for methodIntf == bean.


        InvocationInfo invInfo = new InvocationInfo(method);

        invInfo.ejbName = ejbDescriptor.getName();
        invInfo.txAttr = txAttr;
        invInfo.securityPermissions = Container.SEC_NOT_INITIALIZED;
        invInfo.methodIntf = methodIntf;

        invInfo.isBusinessMethod = isBusinessMethod(method);
        invInfo.isCreateHomeFinder = isCreateHomeFinder(method);
        invInfo.isHomeFinder = isHomeFinder(method);

        invInfo.startsWithCreate = method.getName().startsWith("create");
        invInfo.startsWithFind = method.getName().startsWith("find");
        invInfo.startsWithRemove = method.getName().startsWith("remove");
        invInfo.startsWithFindByPrimaryKey = 
            method.getName().startsWith("findByPrimaryKey");
        invInfo.flushEnabled = flushEnabled;

        if( methodIntf.equals(MethodDescriptor.EJB_LOCALHOME) ) {
            if( method.getDeclaringClass() != EJBLocalHome.class ) {
                setHomeTargetMethodInfo(invInfo, true);
            }
        } else if( methodIntf.equals(MethodDescriptor.EJB_HOME) ) {
            if( method.getDeclaringClass() != EJBHome.class ) {
                setHomeTargetMethodInfo(invInfo, false);
            }
        } else if( methodIntf.equals(MethodDescriptor.EJB_LOCAL) ) { 
            if( method.getDeclaringClass() != EJBLocalObject.class ) {
                setEJBObjectTargetMethodInfo(invInfo, true, originalIntf);
            }
        } else if( methodIntf.equals(MethodDescriptor.EJB_REMOTE) ) {
            if( method.getDeclaringClass() != EJBObject.class ) {
                setEJBObjectTargetMethodInfo(invInfo, false, originalIntf);
            }
        }       

        if( _logger.isLoggable(Level.FINE) ) {
            _logger.log(Level.FINE, invInfo.toString());
        }

        return invInfo;
    
protected voidcreateMonitoringRegistryMediator()

	String appName = null;
	String modName = null;
	String ejbName = null;
	try {
	    appName = (ejbDescriptor.getApplication().isVirtual())
		? null: ejbDescriptor.getApplication().getRegistrationName();
	    if (appName == null) {
		modName = ejbDescriptor.getApplication().getRegistrationName();
	    } else {
		String archiveuri = ejbDescriptor.getEjbBundleDescriptor().
		    getModuleDescriptor().getArchiveUri();
		modName = 
		    com.sun.enterprise.util.io.FileUtils.makeFriendlyFilename(archiveuri);
	    }
	    ejbName = ejbDescriptor.getName();
	    this.registryMediator =
		new MonitoringRegistryMediator( getEJBMonitoredObjectType(), ejbName, modName, appName);
    
	    this.ejbMethodStatsManager = registryMediator.getEJBMethodStatsManager();
	    _logger.log(Level.FINE, "Created MonitoringRegistryMediator: appName: "
                + appName + "; modName: " + modName + "; ejbName: " + ejbName);
	} catch (Exception ex) {
	    _logger.log(Level.SEVERE, "[**BaseContainer**] Could not create MonitorRegistryMediator. appName: " + appName + "; modName: " + modName + "; ejbName: " + ejbName, ex);
	    
	}
    
EJBObjectImplcreateRemoteBusinessObjectImpl()

        throw new EJBException(
            "Internal ERROR: BaseContainer.createRemoteBusinessObject called");
    
public java.rmi.RemotecreateRemoteReferenceWithId(byte[] instanceKey, java.lang.String generatedRemoteBusinessIntf)
Create an EJBObject reference from the instanceKey Called from EJBObjectOutputStream.SerializableRemoteRef during deserialization of a remote-ref

param
the instanceKey of the ejbobject
param
if non-null, this is a remote business view and the param is the name of the generated remote business interface. Otherwise, this is for the RemoteHome view

                                                     
        final Thread currentThread = Thread.currentThread();
        final ClassLoader previousClassLoader =
            currentThread.getContextClassLoader();
        final ClassLoader myClassLoader = loader;
	try {
            if(System.getSecurityManager() == null) {
                currentThread.setContextClassLoader(myClassLoader);
            } else {
                java.security.AccessController.doPrivileged(
                        new java.security.PrivilegedAction() {
                    public java.lang.Object run() {
                        currentThread.setContextClassLoader(myClassLoader);
                        return null;
                    }
                });
            }
            java.rmi.Remote remoteRef = null;
            if( generatedRemoteBusinessIntf == null ) {
                remoteRef = remoteHomeRefFactory.createRemoteReference
                    (instanceKey);
            } else {
                RemoteReferenceFactory remoteBusinessRefFactory =
                   remoteBusinessIntfInfo.get(generatedRemoteBusinessIntf).
                    referenceFactory;

                remoteRef = remoteBusinessRefFactory.createRemoteReference
                    (instanceKey);
            }
            return remoteRef;
        } finally {
            if(System.getSecurityManager() == null) {
                currentThread.setContextClassLoader(previousClassLoader);
            } else {
                java.security.AccessController.doPrivileged(
                        new java.security.PrivilegedAction() {
                    public java.lang.Object run() {
                        currentThread.setContextClassLoader(previousClassLoader);
                        return null;
                    }
                });
            }
        }
    
private voiddestroyTimers()

        EJBTimerService ejbTimerService = containerFactory.getEJBTimerService();
        if( isTimedObject() && (ejbTimerService != null) ) {
            ejbTimerService.destroyTimers(getContainerId());
        }
    
public voiddoAfterApplicationDeploy()
Called after all the components in the container's application have deployed successfully.

        _logger.log(Level.FINE,"Application deployment successful : " + 
                    this);

        setStartedState();
    
public final voiddoAfterBegin(ComponentInvocation ci)

        Invocation inv = (Invocation)ci;
        try {
            // Associate the context with tx so that on subsequent
            // invocations with the same tx, we can do the appropriate
            // tx.resume etc.
            EJBContextImpl sc = (EJBContextImpl)inv.context;
            Transaction tx = transactionManager.getTransaction();
            sc.setTransaction(tx);
            
            // Register Synchronization with TM so that we can
            // dissociate the context from tx in afterCompletion
            containerFactory.getContainerSync(tx).addBean(sc);
            
            enlistExtendedEntityManagers(sc);
            // Dont call container.afterBegin() because
            // TX_BEAN_MANAGED EntityBeans are not allowed,
            // and SessionSync calls on TX_BEAN_MANAGED SessionBeans
            // are not allowed.
        } catch (SystemException ex) {
            throw new EJBException(ex);
        } catch (RollbackException ex) {
            throw new EJBException(ex);
        } catch (IllegalStateException ex) {
            throw new EJBException(ex);
        }
    
protected voiddoFlush(Invocation inv)

    
voiddoTimerInvocationInit(Invocation inv, RuntimeTimerState timerState)
This is implemented by concrete containers that support TimedObjects.

        throw new EJBException("This container doesn't support TimedObjects");
    
protected voidenlistExtendedEntityManagers(ComponentContext ctx)

        if (isStatefulSession && (ctx.getTransaction() != null)) {
            J2EETransaction j2eeTx = (J2EETransaction) ctx.getTransaction();
            SessionContextImpl sessionCtx = (SessionContextImpl) ctx;
            Map<EntityManagerFactory, EntityManager> entityManagerMap = 
                sessionCtx.getExtendedEntityManagerMap();
                    
            for (Map.Entry<EntityManagerFactory, EntityManager> entry : 
                     entityManagerMap.entrySet()) {
                EntityManagerFactory emf = entry.getKey();
                EntityManager extendedEm = entry.getValue();

                EntityManager extendedEmAssociatedWithTx = 
                    j2eeTx.getExtendedEntityManager(emf);

                // If there's not already an EntityManager registered for
                // this extended EntityManagerFactory within the current tx
                if (extendedEmAssociatedWithTx == null) {
                    j2eeTx.addExtendedEntityManagerMapping(emf,
                                                           extendedEm);
                    sessionCtx.setEmfRegisteredWithTx(emf, true);

                    // Tell persistence provider to associate the extended
                    // entity manager with the transaction.
                    // @@@ Comment this out when joinTransaction supported on
                    // EntityManager API.
                    extendedEm.joinTransaction();
                }
            }
        }
    
public voidexternalPostInvoke()

        try {
            ArrayListStack beanContextStack = 
                (ArrayListStack) threadLocalContext.get();                
            
            final BeanContext bc = (BeanContext) beanContextStack.pop();
            if ( bc.classLoaderSwitched == true ) {
	        if (System.getSecurityManager() == null) {
		    Thread.currentThread().setContextClassLoader(bc.previousClassLoader);
		} else {
		    java.security.AccessController.doPrivileged(
				  new java.security.PrivilegedAction() {
		                      public java.lang.Object run() {
					  Thread.currentThread().setContextClassLoader(
								    bc.previousClassLoader);
					  return null;
				      }
		    });
		}
            }
        } catch ( Exception ex ) {
            _logger.log(Level.FINE, "externalPostInvoke ex", ex);
        }
    
public voidexternalPreInvoke()

        BeanContext bc = new BeanContext();
        final Thread currentThread = Thread.currentThread();
        bc.previousClassLoader = currentThread.getContextClassLoader();
        if ( getClassLoader().equals(bc.previousClassLoader) == false ) {

	    if (System.getSecurityManager() == null) {
	        currentThread.setContextClassLoader( getClassLoader());
	    } else {
	        java.security.AccessController.doPrivileged(
			      new java.security.PrivilegedAction() {
		                  public java.lang.Object run() {
				      currentThread.setContextClassLoader( getClassLoader());
				      return null;
				  }
		});
	    }
            bc.classLoaderSwitched = true;
        }

        ArrayListStack beanContextStack = 
            (ArrayListStack) threadLocalContext.get();
                
        if ( beanContextStack == null ) {
            beanContextStack = new ArrayListStack();
            threadLocalContext.set(beanContextStack);
        } 
        beanContextStack.push(bc);
    
protected booleanfindFlushEnabledAttr(java.lang.reflect.Method method, java.lang.String methodIntf)

            
        //Get the flushMethodDescriptor and then find if flush has been
        //enabled for this method
        MethodDescriptor md = new MethodDescriptor(method, methodIntf);
        boolean flushEnabled = 
            ejbDescriptor.getIASEjbExtraDescriptors().isFlushEnabledFor(md);

        return flushEnabled;
    
private intfindTxAttr(java.lang.reflect.Method method, java.lang.String methodIntf)

        int txAttr = -1;
        
        if ( isBeanManagedTran )
            return TX_BEAN_MANAGED;

        MethodDescriptor md = new MethodDescriptor(method, methodIntf);
        ContainerTransaction ct = ejbDescriptor.getContainerTransactionFor(md);
                                                                    
        if ( ct != null ) {
            String attr = ct.getTransactionAttribute();
            if ( attr.equals(ContainerTransaction.NOT_SUPPORTED) )
                txAttr = TX_NOT_SUPPORTED;
            else if ( attr.equals(ContainerTransaction.SUPPORTS) )
                txAttr = TX_SUPPORTS;
            else if ( attr.equals(ContainerTransaction.REQUIRED) )
                txAttr = TX_REQUIRED;
            else if ( attr.equals(ContainerTransaction.REQUIRES_NEW) )
                txAttr = TX_REQUIRES_NEW;
            else if ( attr.equals(ContainerTransaction.MANDATORY) )
                txAttr = TX_MANDATORY;
            else if ( attr.equals(ContainerTransaction.NEVER) )
                txAttr = TX_NEVER;
        }
        
        if ( txAttr == -1 ) {
            throw new EJBException("Transaction Attribute not found for method "
                + method);
        }
        
        // For EJB2.0 CMP EntityBeans, container is only required to support
        // REQUIRED/REQUIRES_NEW/MANDATORY, see EJB2.0 section 17.4.1.
        if ( isEntity ) {
            if (((EjbEntityDescriptor)ejbDescriptor).getPersistenceType().
                equals(EjbEntityDescriptor.CONTAINER_PERSISTENCE)) {
                EjbCMPEntityDescriptor e= (EjbCMPEntityDescriptor)ejbDescriptor;
                if ( !e.getIASEjbExtraDescriptors().isIsReadOnlyBean() && 
                     e.isEJB20() ) {
                    if ( txAttr != TX_REQUIRED && txAttr != TX_REQUIRES_NEW
                    && txAttr != TX_MANDATORY )
                        throw new EJBException( 
                            "Transaction attribute for EJB2.0 CMP EntityBeans" + 
                            " must be Required/RequiresNew/Mandatory");
                }
            }
        }

        return txAttr;
    
abstract voidforceDestroyBean(EJBContextImpl sc)

public final java.lang.ClassLoadergetClassLoader()

        return loader;
    
public java.lang.StringgetComponentId()
Called from NamingManagerImpl during java:comp/env lookup.

        return componentId;
    
final longgetContainerId()

        return ejbDescriptor.getUniqueId();
    
protected final ComponentContextgetContext(Invocation inv)


        return (inv.context == null) ? _getContext(inv) : inv.context;

    
public longgetCreateCount()

	return statCreateCount;
    
public booleangetDebugMonitorFlag()

        return debugMonitorFlag;
    
public final java.lang.ClassgetEJBClass()

        return ejbClass;
    
public final EJBHomegetEJBHome()

        return ejbHome;
    
public final EJBHomegetEJBHomeStub()

        return ejbHomeStub;
    
public final GenericEJBLocalHomegetEJBLocalBusinessHome()
Return an object that implements ejb's local business home interface.

        return ejbLocalBusinessHome;
    
EJBLocalObjectImplgetEJBLocalBusinessObjectImpl(java.lang.Object key)

	throw new EJBException
            ("Internal ERROR: BaseContainer.getEJBLocalObjectImpl called");
    
public final EJBLocalHomegetEJBLocalHome()
Return an object that implements ejb's local home interface. If dynamic proxies are being used, this is the proxy itself, it can't be directly cast to an EJBLocalHomeImpl.

        return ejbLocalHome;
    
public EJBLocalObjectgetEJBLocalObjectForPrimaryKey(java.lang.Object pkey, EJBContext ctx)

	throw new EJBException("getEJBLocalObjectForPrimaryKey(pkey, ctx) only works for EntityContainer");
    
public EJBLocalObjectgetEJBLocalObjectForPrimaryKey(java.lang.Object pkey)

        throw new EJBException(
            "getEJBLocalObjectForPrimaryKey only works for EntityContainer");
    
EJBLocalObjectImplgetEJBLocalObjectImpl(java.lang.Object key)

	throw new EJBException
            ("Internal ERROR: BaseContainer.getEJBLocalObjectImpl called");
    
public final EJBMetaDatagetEJBMetaData()

        return metadata;
    
private com.sun.enterprise.admin.monitor.registry.MonitoredObjectTypegetEJBMonitoredObjectType()

        MonitoredObjectType type    = MonitoredObjectType.NONE;
        
        final Class<? extends BaseContainer>  thisClass = this.getClass();
        
        if ( StatelessSessionContainer.class.isAssignableFrom( thisClass ) )
        {
            type    = MonitoredObjectType.STATELESS_BEAN;
        }
        else if ( StatefulSessionContainer.class.isAssignableFrom( thisClass ) )
        {
            type    = MonitoredObjectType.STATEFUL_BEAN;
        }
        else if ( EntityContainer.class.isAssignableFrom( thisClass )  )
        {
            type    = MonitoredObjectType.ENTITY_BEAN;
        }
        else if ( MessageBeanContainer.class.isAssignableFrom( thisClass ) )
        {
            type    = MonitoredObjectType.MESSAGE_DRIVEN_BEAN;
        }
        else
        {
            throw new RuntimeException( "getEJBMonitoredObjectType: unknown: " + this.getClass().getName() );
        }
        return type;
    
public EJBObjectgetEJBObjectForPrimaryKey(java.lang.Object pkey)

        throw new EJBException(
            "getEJBObjectForPrimaryKey only works for EntityContainer");
    
abstract EJBObjectImplgetEJBObjectImpl(byte[] streamKey)
Called when a remote invocation arrives for an EJB. Implemented in subclasses.

EJBObjectImplgetEJBRemoteBusinessObjectImpl(byte[] streamKey)

	throw new EJBException
          ("Internal ERROR: BaseContainer.getRemoteBusinessObjectImpl called");
    
public final com.sun.enterprise.deployment.EjbDescriptorgetEjbDescriptor()

        return ejbDescriptor;
    
final java.util.PropertiesgetEnvironmentProperties()

        return envProps;
    
private InvocationInfogetInvocationInfo(Invocation inv)
Encapsulate logic used to map invocation method to invocation info. At present, we have two different maps, one for webservice invocation info and one for everything else. That might change in the future.

        return inv.isWebService ?
            (InvocationInfo) webServiceInvocationInfoMap.get(inv.method) :
            (InvocationInfo) invocationInfoMap.get(inv.method);        
    
public java.lang.ObjectgetJaccEjb(Invocation inv)
Called-back from security implementation through Invocation when a jacc policy provider wants an enterprise bean instance.

        Object bean = null;

        // Access to an enterprise bean instance is undefined for
        // anything but business method invocations through
        // Remote , Local, and ServiceEndpoint interfaces.
        if( ( (inv.invocationInfo != null) && 
              inv.invocationInfo.isBusinessMethod )
            || 
            inv.isWebService ) {

            // In the typical case the context will not have been
            // set when the policy provider invokes this callback.
            // There are some cases where it is ok for it to have been
            // set, e.g. if the policy provider invokes the callback
            // twice within the same authorization decision.
            if( inv.context == null ) {

                try {
                    inv.context = getContext(inv);
                    bean = inv.context.getEJB();
                    // NOTE : inv.ejb is not set here.  Post-invoke logic for
                    // BaseContainer and webservices uses the fact that 
                    // inv.ejb is non-null as an indication that that
                    // BaseContainer.preInvoke() proceeded past a certain 
                    // point, which affects which cleanup needs to be 
                    // performed.  It would be better to have explicit 
                    // state in the invocation that says which cleanup 
                    // steps are necessary(e.g. for invocationMgr.postInvoke
                    // , postInvokeTx, etc) but I'm keeping the logic the 
                    // same for now.   BaseContainer.authorize() will 
                    // explicitly handle the case where a context was 
                    // created as a result of this call and the 
                    // authorization failed, which means the context needs
                    // be released.

                } catch(EJBException e) {
                    _logger.log(Level.WARNING, "ejb.context_failure_jacc", 
                                logParams[0]);
                    _logger.log(Level.WARNING, "", e);
                }

            } else {
                bean = inv.context.getEJB();
            }
        }

        return bean;
    
protected java.lang.String[]getPre30LifecycleMethodNames()

        return new String[] {
            "ejbCreate", "ejbRemove", "ejbPassivate", "ejbActivate"
        };
    
public longgetRemoveCount()

	return statRemoveCount;
    
public final com.sun.enterprise.SecurityManagergetSecurityManager()

        return securityManager;
    
public java.rmi.RemotegetTargetObject(byte[] instanceKey, java.lang.String generatedRemoteBusinessIntf)
Return the EJBObject/EJBHome Proxy for the given ejbId and instanceKey. Called from the ProtocolManager when a remote invocation arrives.

exception
NoSuchObjectLocalException if the target object does not exist

               
        externalPreInvoke();
        boolean remoteHomeView = (generatedRemoteBusinessIntf == null);
        if ( instanceKey.length == 1 && instanceKey[0] == HOME_KEY ) {
            return remoteHomeView ? 
                ejbHomeImpl.getEJBHome() :
                ejbRemoteBusinessHomeImpl.getEJBHome();
        } else {

            EJBObjectImpl ejbObjectImpl  = null;
            java.rmi.Remote targetObject = null;

            if( remoteHomeView ) {
                ejbObjectImpl = getEJBObjectImpl(instanceKey);
                // In rare cases for sfsbs and entity beans, this can be null.
                if( ejbObjectImpl != null ) {
                    targetObject = ejbObjectImpl.getEJBObject();
                }
            } else {
                ejbObjectImpl = getEJBRemoteBusinessObjectImpl(instanceKey);
                // In rare cases for sfsbs and entity beans, this can be null.
                if( ejbObjectImpl != null ) {
                    targetObject = ejbObjectImpl.
                        getEJBObject(generatedRemoteBusinessIntf);
                }
            }

            return targetObject;
        }
    
protected final intgetTxAttr(java.lang.reflect.Method method, java.lang.String methodIntf)


        InvocationInfo invInfo = 
            methodIntf.equals(MethodDescriptor.EJB_WEB_SERVICE) ?
            (InvocationInfo) webServiceInvocationInfoMap.get(method) :
            (InvocationInfo) invocationInfoMap.get(method);

        if( invInfo != null ) {
            return invInfo.txAttr;
        } else {
            throw new EJBException("Transaction Attribute not found for method"
                                   + method);
        }
    
protected final intgetTxAttr(Invocation inv)

        if ( inv.transactionAttribute != TX_NOT_INITIALIZED ) {
            return inv.transactionAttribute;
        }

        int txAttr = getTxAttr(inv.method, inv.getMethodInterface());
        inv.transactionAttribute = txAttr;
        return inv.transactionAttribute;

    
final javax.transaction.UserTransactiongetUserTransaction()

        // Only session beans with bean-managed transactions
        // or message-driven beans with bean-managed transactions
        // can programmatically demarcate transactions.
        if ( (isSession || isMessageDriven) && isBeanManagedTran ) {
            try {
                UserTransaction utx = (UserTransaction)
                namingManager.getInitialContext().lookup(USER_TX);
                return utx;
            } catch ( Exception ex ) {
                _logger.log(Level.FINE, "ejb.user_transaction_exception", ex);
                throw new EJBException("Unable to lookup UserTransaction", ex);
            }
        }
        else
            throw new IllegalStateException(
                "ERROR: only SessionBeans with bean-managed transactions" + 
                "can obtain UserTransaction");
        
    
protected voidincrementCreatedTimedObject()

        toMonitorProps.incrementTimersCreated();
    
protected voidincrementDeliveredTimedObject()

        toMonitorProps.incrementTimersDelivered();
    
protected voidincrementRemovedTimedObject()

        toMonitorProps.incrementTimersRemoved();
    
private voidinitializeEjbInterfaceMethods()
Create an array of all methods in the standard EJB interfaces: javax.ejb.EJB(Local){Home|Object} .

        ejbIntfMethods = new Method[EJB_INTF_METHODS_LENGTH];
        
        if ( isRemote ) {
            ejbIntfMethods[ EJBHome_remove_Handle ] =
                EJBHome.class.getMethod("remove",
                                    new Class[]{javax.ejb.Handle.class});
            ejbIntfMethods[ EJBHome_remove_Pkey ] =
                EJBHome.class.getMethod("remove",
                                        new Class[]{java.lang.Object.class});
            ejbIntfMethods[ EJBHome_getEJBMetaData ] =
                EJBHome.class.getMethod("getEJBMetaData", NO_PARAMS);
            ejbIntfMethods[ EJBHome_getHomeHandle ] =
                EJBHome.class.getMethod("getHomeHandle", NO_PARAMS);
            
            ejbIntfMethods[ EJBObject_getEJBHome ] =
                EJBObject.class.getMethod("getEJBHome", NO_PARAMS);
            ejbIntfMethods[ EJBObject_getPrimaryKey ] =
                EJBObject.class.getMethod("getPrimaryKey", NO_PARAMS);
            ejbIntfMethods[ EJBObject_remove ] =
                EJBObject.class.getMethod("remove", NO_PARAMS);
            ejbIntfMethods[ EJBObject_getHandle ] =
                EJBObject.class.getMethod("getHandle", NO_PARAMS);
            ejbIntfMethods[ EJBObject_isIdentical ] =
                EJBObject.class.getMethod("isIdentical",
            new Class[]{javax.ejb.EJBObject.class});
            
            if ( isStatelessSession ) {
                if( hasRemoteHomeView ) {
                    ejbIntfMethods[ EJBHome_create ] =
                        homeIntf.getMethod("create", NO_PARAMS);
                }
            }
        }
        
        if ( isLocal ) {
            ejbIntfMethods[ EJBLocalHome_remove_Pkey ] =
                EJBLocalHome.class.getMethod("remove",
                    new Class[]{java.lang.Object.class});
            
            ejbIntfMethods[ EJBLocalObject_getEJBLocalHome ] =
                EJBLocalObject.class.getMethod("getEJBLocalHome", NO_PARAMS);
            ejbIntfMethods[ EJBLocalObject_getPrimaryKey ] =
                EJBLocalObject.class.getMethod("getPrimaryKey", NO_PARAMS);
            ejbIntfMethods[ EJBLocalObject_remove ] =
                EJBLocalObject.class.getMethod("remove", NO_PARAMS);
            ejbIntfMethods[ EJBLocalObject_isIdentical ] =
                EJBLocalObject.class.getMethod("isIdentical",
            new Class[]{javax.ejb.EJBLocalObject.class});
            
            if ( isStatelessSession ) {
                if( hasLocalHomeView ) {
                    Method m = localHomeIntf.getMethod("create", NO_PARAMS);
                    ejbIntfMethods[ EJBLocalHome_create ] = m;
                }
            }
        }
        
    
voidinitializeHome()
Called from the ContainerFactory during initialization.

        
        if (isRemote) {
            
            if( hasRemoteHomeView ) {
                this.ejbHomeImpl = instantiateEJBHomeImpl();
                this.ejbHome = ejbHomeImpl.getEJBHome();           

                // Since some containers might create multiple EJBObjects for
                // the same ejb, make sure we use the same Proxy class to 
                // instantiate all the proxy instances.              
                ejbObjectProxyClass = 
                    Proxy.getProxyClass(loader, new Class[] { remoteIntf });
                ejbObjectProxyCtor = ejbObjectProxyClass.
                    getConstructor(new Class[] { InvocationHandler.class });

                //
                // Make sure all Home/Remote interfaces conform to RMI-IIOP
                // rules.  Checking for conformance here keeps the exposed 
                // deployment/startup error behavior consistent since when 
                // rmic is used during codegen it makes equivalent checks and
                // treats any validation problems as fatal errors. 
                //
                // These same checks will be made when setTarget is called
                // in POARemoteReferenceFactory.preinvoke, but that happens
                // only when the actual invocation is made, so it's better to
                // know at container initialization time if there is a problem.
                //
                checkProtocolManager();
                protocolMgr.validateTargetObjectInterfaces(this.ejbHome);

                // Unlike the Home, each of the concrete containers are
                // responsible for creating the EJBObjects, so just create
                // a dummy EJBObjectImpl for validation purposes.
                EJBObjectImpl dummyEJBObjectImpl = instantiateEJBObjectImpl();
                EJBObject dummyEJBObject = (EJBObject)
                    dummyEJBObjectImpl.getEJBObject();
                protocolMgr.validateTargetObjectInterfaces(dummyEJBObject);

                // Remotereference factory needs instances of
                // Home and Remote to get repository Ids since it doesn't have
                // stubs and ties.  This must be done before any Home or Remote
                // references are created.
                remoteHomeRefFactory.setRepositoryIds(homeIntf, remoteIntf);
                             
                // get a remote ref for the EJBHome
                ejbHomeStub = remoteHomeRefFactory.
                    createHomeReference(homeInstanceKey);

                remoteHomeJndiName = ejbDescriptor.getJndiName();

                namingManager.publishObject(remoteHomeJndiName,
                                            ejbHomeStub, false);            
            }

            
            if( hasRemoteBusinessView ) {
                this.ejbRemoteBusinessHomeImpl = 
                    instantiateEJBRemoteBusinessHomeImpl();

                this.ejbRemoteBusinessHome = 
                    ejbRemoteBusinessHomeImpl.getEJBHome();           

                remoteBusinessHomeJndiName = EJBUtils.getRemote30HomeJndiName
                    (ejbDescriptor.getJndiName());

                if(!hasRemoteHomeView && (remoteBusinessIntfInfo.size() == 1)){                    
                    remoteBusinessJndiName = ejbDescriptor.getJndiName();
                    
                }

                checkProtocolManager();
                // RMI-IIOP validation
                protocolMgr.validateTargetObjectInterfaces
                    (this.ejbRemoteBusinessHome);

                for(RemoteBusinessIntfInfo next : 
                        remoteBusinessIntfInfo.values()) {
                        
                    next.proxyClass = Proxy.getProxyClass
                        (loader, new Class[] { next.generatedRemoteIntf });
                        
                    next.proxyCtor = next.proxyClass.
                       getConstructor(new Class[] { InvocationHandler.class });

                    // Remotereference factory needs instances of
                    // Home and Remote to get repository Ids since it 
                    // doesn't have stubs and ties.  This must be done before 
                    // any Home or Remote references are created.
                    next.referenceFactory.setRepositoryIds
                        (remoteBusinessHomeIntf, next.generatedRemoteIntf);

                    // Create home stub from the remote reference factory
                    // associated with one of the remote business interfaces.
                    // It doesn't matter which remote reference factory is
                    // selected, so just do it the first time through the loop.
                    if( ejbRemoteBusinessHomeStub == null ) {
                        ejbRemoteBusinessHomeStub = next.referenceFactory.
                            createHomeReference(homeInstanceKey);
                    }

                }

                EJBObjectImpl dummyEJBObjectImpl = 
                    instantiateRemoteBusinessObjectImpl();

                for(RemoteBusinessIntfInfo next : 
                        remoteBusinessIntfInfo.values()) { 

                    java.rmi.Remote dummyEJBObject = dummyEJBObjectImpl.
                        getEJBObject(next.generatedRemoteIntf.getName());
                        
                    protocolMgr.validateTargetObjectInterfaces(dummyEJBObject);

                    next.jndiName = EJBUtils.getRemoteEjbJndiName
                        (true, next.remoteBusinessIntf.getName(), 
                         ejbDescriptor.getJndiName());

                    // Register an object factory that will retrieve 
                    // the generic remote business home and create the
                    // appropriate client business wrapper object for the
                    // given business interface.  
                    Reference remoteBusRef = new Reference
                        (next.remoteBusinessIntf.getName(),
                         new StringRefAddr("url", remoteBusinessHomeJndiName),
                         "com.sun.ejb.containers.RemoteBusinessObjectFactory",
                         null);

                    namingManager.publishObject(next.jndiName, remoteBusRef,
                                                false);

                    if( remoteBusinessJndiName != null ) {
                        namingManager.publishObject(remoteBusinessJndiName,
                                                    remoteBusRef, false);
			_logger.log(Level.INFO, "**RemoteBusinessJndiName: "
				+ remoteBusinessJndiName + "; remoteBusIntf: "
				+ next.remoteBusinessIntf.getName());
                    }

                }

                namingManager.publishObject(remoteBusinessHomeJndiName,
                                            ejbRemoteBusinessHomeStub, false);

            }
            
        }
        
        if (isLocal) {

            if( hasLocalHomeView ) {
                this.ejbLocalHomeImpl = instantiateEJBLocalHomeImpl();
                this.ejbLocalHome = ejbLocalHomeImpl.getEJBLocalHome();

                // Since some containers might create multiple EJBLocalObjects
                // for the same ejb, make sure we use the same Proxy class to 
                // instantiate all the proxy instances.  
                Class ejbLocalObjectProxyClass = 
                    Proxy.getProxyClass(loader, 
                                    new Class[] { IndirectlySerializable.class,
                                                  localIntf });
                ejbLocalObjectProxyCtor = ejbLocalObjectProxyClass.
                    getConstructor(new Class[] { InvocationHandler.class });
            }

            if( hasLocalBusinessView ) {
                ejbLocalBusinessHomeImpl =
                    instantiateEJBLocalBusinessHomeImpl();
                ejbLocalBusinessHome = (GenericEJBLocalHome)
                    ejbLocalBusinessHomeImpl.getEJBLocalHome();
                
                Class[] proxyInterfaces = 
                    new Class[ localBusinessIntfs.size() + 1 ];
                proxyInterfaces[0] = IndirectlySerializable.class;
                int index = 1;
                for(Class next : localBusinessIntfs) {
                    proxyInterfaces[index] = next;
                    index++;
                }

                Class proxyClass = Proxy.getProxyClass(loader,proxyInterfaces);
                ejbLocalBusinessObjectProxyCtor = proxyClass.
                    getConstructor(new Class[] { InvocationHandler.class });
            }
        }
        
        // create EJBMetaData
        Class primaryKeyClass = null;
        if ( isEntity ) {
            EjbEntityDescriptor ed = (EjbEntityDescriptor)ejbDescriptor;
            primaryKeyClass = loader.loadClass(ed.getPrimaryKeyClassName());
        }
        metadata = new EJBMetaDataImpl(ejbHomeStub, homeIntf, remoteIntf,
            primaryKeyClass, isSession, isStatelessSession);

    
private voidinitializeInterceptorManager()

        this.interceptorManager = new InterceptorManager(_logger, this,
                lifecycleCallbackAnnotationClasses,
                getPre30LifecycleMethodNames());
    
private voidinitializeInvocationInfo()

        
        if( isMessageDriven ) {
            // message listener method initialization performed by 
            // message bean container 
        } else {
            if ( isRemote ) {

                if( hasRemoteHomeView ) {
                    // Process Remote intf
                    Method[] methods = remoteIntf.getMethods();
                    for ( int i=0; i<methods.length; i++ ) {
                        Method method = methods[i];                    
                        addInvocationInfo(method, MethodDescriptor.EJB_REMOTE,
                                          remoteIntf);
                    }
                    
                    // Process EJBHome intf
                    methods = homeIntf.getMethods();
                    for ( int i=0; i<methods.length; i++ ) {
                        Method method = methods[i];                   
                        addInvocationInfo(method, MethodDescriptor.EJB_HOME,
                                          homeIntf);
                    }
                }

                if( hasRemoteBusinessView ) {

                    for(RemoteBusinessIntfInfo next : 
                            remoteBusinessIntfInfo.values()) {
                        // Get methods from generated remote intf but pass
                        // actual business interface as original interface.
                        Method[] methods = 
                            next.generatedRemoteIntf.getMethods();
                        for ( int i=0; i<methods.length; i++ ) {
                            Method method = methods[i];                    
                            addInvocationInfo(method, 
                                              MethodDescriptor.EJB_REMOTE,
                                              next.remoteBusinessIntf);
                        }
                    }
                    
                    // Process internal EJB RemoteBusinessHome intf
                    Method[] methods = remoteBusinessHomeIntf.getMethods();
                    for ( int i=0; i<methods.length; i++ ) {
                        Method method = methods[i];                   
                        addInvocationInfo(method, MethodDescriptor.EJB_HOME,
                                          remoteBusinessHomeIntf);
                    } 
                }
            }

            if ( isLocal ) {
                if( hasLocalHomeView ) {
                    // Process Local interface
                    Method[] methods = localIntf.getMethods();
                    for ( int i=0; i<methods.length; i++ ) {
                        Method method = methods[i];                    
                        InvocationInfo info = addInvocationInfo(method, MethodDescriptor.EJB_LOCAL,
                                          localIntf);
                        postProcessInvocationInfo(info);
                    }

                    // Process LocalHome interface
                    methods = localHomeIntf.getMethods();
                    for ( int i=0; i<methods.length; i++ ) {
                        Method method = methods[i];                    
                        addInvocationInfo(method, 
                                          MethodDescriptor.EJB_LOCALHOME,
                                          localHomeIntf);
                    }
                }

                if( hasLocalBusinessView ) {

                    // Process Local Business interfaces
                    for(Class localBusinessIntf : localBusinessIntfs) {
                        Method[] methods = localBusinessIntf.getMethods();
                        for ( int i=0; i<methods.length; i++ ) {
                            Method method = methods[i];                    
                            addInvocationInfo(method, 
                                              MethodDescriptor.EJB_LOCAL,
                                              localBusinessIntf);
                        }
                    }

                    // Process (internal) Local Business Home interface
                    Method[] methods = localBusinessHomeIntf.getMethods();
                    for ( int i=0; i<methods.length; i++ ) {
                        Method method = methods[i];                    
                        addInvocationInfo(method, 
                                          MethodDescriptor.EJB_LOCALHOME,
                                          localBusinessHomeIntf);
                    }
                }
            }

            if ( isWebServiceEndpoint ) {
                // Process Service Endpoint interface
                Method[] methods = webServiceEndpointIntf.getMethods();
                for ( int i=0; i<methods.length; i++ ) {
                    Method method = methods[i];                   
                    addInvocationInfo(method,MethodDescriptor.EJB_WEB_SERVICE,
                                      webServiceEndpointIntf);
                }
            }

        }
        
        if( isTimedObject() ) {
            int txAttr = findTxAttr(ejbTimeoutMethod, 
                                    MethodDescriptor.EJB_BEAN);
            if( isBeanManagedTran ||
                txAttr == TX_REQUIRED ||
                txAttr == TX_REQUIRES_NEW ||
                txAttr == TX_NOT_SUPPORTED ) {
                addInvocationInfo(ejbTimeoutMethod, MethodDescriptor.EJB_BEAN,
                                  null);
            } else {
                throw new EJBException("Timeout method " + ejbTimeoutMethod +
                                       "must have TX attribute of " +
                                       "TX_REQUIRES_NEW or TX_REQUIRED or " +
                                       "TX_NOT_SUPPORTED for ejb " +
                                       ejbDescriptor.getName());
            }
        }

        // Create a map implementation that is optimized
        // for method lookups.  This is especially important for local
        // invocations through dynamic proxies, where the overhead of the
        // the (method -> invocationInfo) lookup has been measured to be 
        // 6X greater than the overhead of the reflective call itself.
        proxyInvocationInfoMap = new MethodMap(invocationInfoMap);

        
        // Store InvocationInfo by standard ejb interface method type
        // to avoid an invocation info map lookup during authorizeLocalMethod
        // and authorizeRemoteMethod.
        ejbIntfMethodInfo = new InvocationInfo[EJB_INTF_METHODS_LENGTH];
        for(int i = 0; i < ejbIntfMethods.length; i++) {
            Method m = ejbIntfMethods[i];
            ejbIntfMethodInfo[i] = (InvocationInfo) invocationInfoMap.get(m);
        }
    
private EJBHomeImplinstantiateEJBHomeImpl()


        EJBHomeInvocationHandler handler =
            new EJBHomeInvocationHandler(ejbDescriptor, homeIntf,
                                         proxyInvocationInfoMap);

        EJBHomeImpl homeImpl = handler;

        // Maintain insertion order
        Set proxyInterfacesSet = new LinkedHashSet();

        if( ejbDescriptor.getIASEjbExtraDescriptors().isIsReadOnlyBean() ) {
            proxyInterfacesSet.add(ReadOnlyEJBHome.class);
        }

        proxyInterfacesSet.add(homeIntf); 

        Class[] proxyInterfaces = (Class [])
            proxyInterfacesSet.toArray(new Class[0]);

        EJBHome ejbHomeProxy = (EJBHome) 
            Proxy.newProxyInstance( loader, proxyInterfaces, handler);
        
        handler.setProxy(ejbHomeProxy);

        homeImpl.setContainer(this);
            
        return homeImpl;

    
private EJBLocalHomeImplinstantiateEJBLocalBusinessHomeImpl()


        EJBLocalHomeInvocationHandler invHandler = 
            new EJBLocalHomeInvocationHandler(ejbDescriptor, 
                                              localBusinessHomeIntf,
                                              proxyInvocationInfoMap);

        EJBLocalHomeImpl homeImpl = invHandler;
        
        EJBLocalHome proxy = (EJBLocalHome) Proxy.newProxyInstance
            (loader, new Class[] { IndirectlySerializable.class,
                                   localBusinessHomeIntf }, invHandler);
            
        invHandler.setProxy(proxy);

        homeImpl.setContainer(this);

        return homeImpl;
    
protected EJBLocalObjectImplinstantiateEJBLocalBusinessObjectImpl()


        EJBLocalObjectInvocationHandler handler = 
            new EJBLocalObjectInvocationHandler(proxyInvocationInfoMap);

        EJBLocalObjectImpl localBusinessObjImpl = handler;

        Object localObjectProxy = ejbLocalBusinessObjectProxyCtor.newInstance
            ( new Object[] { handler });

        localBusinessObjImpl.setContainer(this);

        for (Class businessIntfClass : localBusinessIntfs) {
            EJBLocalObjectInvocationHandlerDelegate delegate =
                new EJBLocalObjectInvocationHandlerDelegate(
                        businessIntfClass, getContainerId(), handler);
            Proxy proxy = (Proxy) Proxy.newProxyInstance(
                    loader, new Class[] { IndirectlySerializable.class,
                                   businessIntfClass}, delegate);
            localBusinessObjImpl.mapClientObject(businessIntfClass.getName(),
                    proxy);
        }
        return localBusinessObjImpl;
    
private EJBLocalHomeImplinstantiateEJBLocalHomeImpl()


        // LocalHome impl
        EJBLocalHomeInvocationHandler invHandler = 
            new EJBLocalHomeInvocationHandler(ejbDescriptor, 
                                              localHomeIntf,
                                              proxyInvocationInfoMap);
        
        EJBLocalHomeImpl homeImpl = invHandler;
        
        // Maintain insertion order
        Set proxyInterfacesSet = new LinkedHashSet();
        
        proxyInterfacesSet.add(IndirectlySerializable.class);
        if( ejbDescriptor.getIASEjbExtraDescriptors().isIsReadOnlyBean()) {
            proxyInterfacesSet.add(ReadOnlyEJBLocalHome.class);
        }
        proxyInterfacesSet.add(localHomeIntf);
        
        Class[] proxyInterfaces = (Class[])
            proxyInterfacesSet.toArray(new Class[0]);
        
        // Client's EJBLocalHome object
        EJBLocalHome proxy = (EJBLocalHome) Proxy.newProxyInstance
            (loader, proxyInterfaces, invHandler);
            
        invHandler.setProxy(proxy);

        homeImpl.setContainer(this);

        return homeImpl;
    
protected EJBLocalObjectImplinstantiateEJBLocalObjectImpl()

        EJBLocalObjectImpl localObjImpl = null;

        EJBLocalObjectInvocationHandler handler = 
            new EJBLocalObjectInvocationHandler(proxyInvocationInfoMap,
                                                localIntf);

        localObjImpl = handler;
        EJBLocalObject localObjectProxy = (EJBLocalObject) 
                ejbLocalObjectProxyCtor.newInstance( new Object[] { handler });
        handler.setProxy(localObjectProxy);

        localObjImpl.setContainer(this);

        return localObjImpl;
    
protected EJBObjectImplinstantiateEJBObjectImpl()

        
        EJBObjectInvocationHandler handler =
            new EJBObjectInvocationHandler(proxyInvocationInfoMap,
                                           remoteIntf);        

        EJBObjectImpl ejbObjImpl = handler;

        EJBObject ejbObjectProxy = (EJBObject)
            ejbObjectProxyCtor.newInstance( new Object[] { handler });

        handler.setEJBObject(ejbObjectProxy);

        ejbObjImpl.setContainer(this);

        return ejbObjImpl;
    
private EJBHomeImplinstantiateEJBRemoteBusinessHomeImpl()


        EJBHomeInvocationHandler handler =
            new EJBHomeInvocationHandler(ejbDescriptor,
                                         remoteBusinessHomeIntf,
                                         proxyInvocationInfoMap);

        EJBHomeImpl remoteBusinessHomeImpl = handler;

        EJBHome ejbRemoteBusinessHomeProxy = (EJBHome) 
            Proxy.newProxyInstance(loader, 
                                   new Class[] { remoteBusinessHomeIntf },
                                   handler);
        
        handler.setProxy(ejbRemoteBusinessHomeProxy);

        remoteBusinessHomeImpl.setContainer(this);
            
        return remoteBusinessHomeImpl;

    
protected EJBObjectImplinstantiateRemoteBusinessObjectImpl()

        
        // There is one EJBObjectImpl instance, which is an instance of
        // the handler.   That handler instance is shared by the dynamic
        // proxy for each remote business interface.  We need to create a
        // different proxy for each remote business interface because 
        // otherwise the target object given to the orb will be invalid
        // if the same method happens to be declared on multiple remote
        // business interfaces.
        EJBObjectInvocationHandler handler =
            new EJBObjectInvocationHandler(proxyInvocationInfoMap);        

        EJBObjectImpl ejbBusinessObjImpl = handler;

        for(RemoteBusinessIntfInfo next : 
                remoteBusinessIntfInfo.values()) {

            EJBObjectInvocationHandlerDelegate delegate = 
                new EJBObjectInvocationHandlerDelegate(next.remoteBusinessIntf,
                                                       handler);

            java.rmi.Remote ejbBusinessObjectProxy = (java.rmi.Remote)
                next.proxyCtor.newInstance( new Object[] { delegate });

            ejbBusinessObjImpl.setEJBObject(next.generatedRemoteIntf.getName(),
                                            ejbBusinessObjectProxy);

        }

        ejbBusinessObjImpl.setContainer(this);

        return ejbBusinessObjImpl;
    
java.lang.Objectintercept(Invocation inv)
Called from various places within the container that are responsible for dispatching invocations to business methods. This method has the exception semantics of Method.invoke(). Any exception that originated from the business method or application code within an interceptor will be propagated as the cause within an InvocationTargetException.

        Object result = null;
        if (interceptorManager.hasInterceptors()) {
            try {
                onEjbMethodStart();
                result = interceptorManager.intercept(inv);
            } catch(Throwable t) {
                inv.exception = t;
                throw new InvocationTargetException(t);
            } finally {
                onEjbMethodEnd();
            }
        } else { // invoke() has the same exc. semantics as Method.invoke
            result = this.invokeTargetBeanMethod(inv.getBeanMethod(), inv, inv.ejb,
                    inv.methodParams, null);
        }
        
        return result;
    
public java.lang.ObjectinvokeBeanMethod(Invocation inv)
Called from Interceptor Chain to invoke the actual bean method. This method must throw any exception from the bean method *as is*, without being wrapped in an InvocationTargetException. The exception thrown from this method will be propagated through the application's interceptor code, so it must not be changed in order for any exception handling logic in that code to function properly.

        try {
            return SecurityUtil.invoke(inv.getBeanMethod(), inv, inv.ejb,
                                       inv.getParameters(), this, null);
        } catch(InvocationTargetException ite) {
            throw ite.getCause();
        }
    
java.lang.ObjectinvokeTargetBeanMethod(java.lang.reflect.Method beanClassMethod, Invocation inv, java.lang.Object target, java.lang.Object[] params, com.sun.enterprise.SecurityManager mgr)

        try {
            onEjbMethodStart();
            if (inv.useFastPath) {
                return inv.getBeanMethod().invoke(inv.ejb, inv.methodParams);
            } else {
                return SecurityUtil.invoke(beanClassMethod, inv, target,
                        params, this, mgr);
            }
        } catch (InvocationTargetException ite) {
            inv.exception = ite.getCause();
            throw ite;
        } catch(Throwable c) {
            inv.exception = c;
            throw c;
        } finally {
            onEjbMethodEnd();
        }
    
protected booleanisAppExceptionRequiringRollback(java.lang.Throwable exception)
Returns true if this exception is an Application Exception and it requires rollback of the transaction in which it was thrown.


        boolean appExceptionRequiringRollback = false;

        if ( exception != null ) {

            String exceptionClassName = exception.getClass().getName();
            for(EjbApplicationExceptionInfo excepInfo : ejbDescriptor.
                    getEjbBundleDescriptor().getApplicationExceptions()) {
                if( exceptionClassName.equals
                    (excepInfo.getExceptionClassName()) ) {
                    appExceptionRequiringRollback = excepInfo.getRollback();
                }
            }
        }

        return appExceptionRequiringRollback;
    
protected booleanisApplicationException(java.lang.Throwable exception)

        return !isSystemUncheckedException(exception);
    
final booleanisBeanManagedTx()

        return isBeanManagedTran;
    
final booleanisBusinessMethod(java.lang.reflect.Method method)

        Class methodClass = method.getDeclaringClass();
        
        // All methods on the Home/LocalHome & super-interfaces
        // are not business methods.
        // All methods on javax.ejb.EJBObject and EJBLocalObject
        // (e.g. remove) are not business methods.
        // All remaining methods are business methods
        
        if ( isRemote ) {
            if ( (hasRemoteHomeView && 
                  ( (methodClass == homeIntf) ||
                    methodClass.isAssignableFrom(homeIntf) ))
                 ||
                 (hasRemoteBusinessView && 
                  ( (methodClass == remoteBusinessHomeIntf) ||
                    methodClass.isAssignableFrom(remoteBusinessHomeIntf) ))
                 ||
                 (methodClass == EJBObject.class ) ) {
                return false;
            }
        }
        if ( isLocal ) {
            if ( (hasLocalHomeView && 
                  ( (methodClass == localHomeIntf) ||
                    methodClass.isAssignableFrom(localHomeIntf) )) 
                 ||
                 (hasLocalBusinessView &&
                  ( (methodClass == localBusinessHomeIntf) ||
                    methodClass.isAssignableFrom(localBusinessHomeIntf) ))   
                 || 
                 (methodClass == EJBLocalObject.class)) {
                return false;
            }
        }
        // NOTE : Web Service client view contains ONLY
        // business methods
        
        return true;
    
final booleanisCreateHomeFinder(java.lang.reflect.Method method)

        Class methodClass = method.getDeclaringClass();
        
        if ( isMessageDriven ) {
            return false;
        }
        
        if ( hasRemoteHomeView 
             && methodClass.isAssignableFrom(homeIntf)
             && (methodClass != EJBHome.class) ) {
            return true;
        }
        
        if ( hasRemoteBusinessView
             && methodClass.isAssignableFrom(remoteBusinessHomeIntf)
             && (methodClass != EJBHome.class) ) {
            return true;
        }

        if ( hasLocalHomeView 
             && methodClass.isAssignableFrom(localHomeIntf)
             && (methodClass != EJBLocalHome.class) ) {
            return true;
        }

        if ( hasLocalBusinessView
             && methodClass.isAssignableFrom(localBusinessHomeIntf)
             && (methodClass != EJBLocalHome.class) ) {
            return true;
        }
        
        
        return false;
    
public booleanisHAEnabled()

        return false;
    
final booleanisHomeFinder(java.lang.reflect.Method method)

        Class methodClass = method.getDeclaringClass();
        
        // MDBs and SessionBeans cant have finder/home methods.
        if ( isMessageDriven || isSession ) {
            return false;
        }
        
        if ( isRemote ) {
            if ( (hasRemoteHomeView &&
                  methodClass.isAssignableFrom(homeIntf))
                 && (methodClass != EJBHome.class)
                 && (!method.getName().startsWith("create")) ) {
                return true;
            }
        }
        if ( isLocal ) {
            // No need to check LocalBusiness view b/c home/finder methods
            // only apply to entity beans.
            if ( (hasLocalHomeView &&
                  methodClass.isAssignableFrom(localHomeIntf)) 
                 && (methodClass != EJBLocalHome.class)
                 && (!method.getName().startsWith("create")) ) {
                return true;
            }
        }
        
        return false;
    
booleanisIdentical(EJBObjectImpl ejbo, EJBObject other)

        throw new EJBException(
            "Internal ERROR: BaseContainer.isIdentical called");
    
protected final booleanisLocalInterfaceSupported()

        return hasLocalHomeView;
    
protected final booleanisRemoteInterfaceSupported()

        return hasRemoteHomeView;
    
protected booleanisSystemUncheckedException(java.lang.Throwable exception)

        if ( exception != null &&
             ( exception instanceof RuntimeException
               || exception instanceof Error
               || exception instanceof RemoteException ) ) {

            String exceptionClassName = exception.getClass().getName();
            for(EjbApplicationExceptionInfo excepInfo : ejbDescriptor.
                    getEjbBundleDescriptor().getApplicationExceptions()) {
                if( exceptionClassName.equals
                    (excepInfo.getExceptionClassName()) ) {
                    return false;
                }
            }

            return true;
        } else {
            return false;
        }
    
final booleanisTimedObject()

        return isTimedObject_;
    
public final booleanisUndeployed()

	return (containerState == CONTAINER_UNDEPLOYED);
    
voidlogMonitoredComponentsData()

	registryMediator.logMonitoredComponentsData(
	    _logger.isLoggable(Level.FINE));
    
private java.lang.ThrowablemapBusinessInterfaceException(java.lang.Throwable t)


        Throwable mappedException = null;

        if( t instanceof TransactionRolledbackLocalException ) {
            mappedException = new EJBTransactionRolledbackException();
            mappedException.initCause(t);
        } else if( t instanceof TransactionRequiredLocalException ) {
            mappedException = new EJBTransactionRequiredException();
            mappedException.initCause(t);
        } else if( t instanceof NoSuchObjectLocalException ) {
            mappedException = new NoSuchEJBException();
            mappedException.initCause(t);
        }
        
        return (mappedException != null) ? mappedException : t;

    
final voidonEjbMethodEnd()

        callFlowAgent.ejbMethodEnd(callFlowInfo);
    
final voidonEjbMethodStart()

        callFlowAgent.ejbMethodStart(callFlowInfo);
    
final voidonEnteringContainer()

        callFlowAgent.startTime(ContainerTypeOrApplicationType.EJB_CONTAINER);
    
final voidonLeavingContainer()

        callFlowAgent.endTime();
    
public voidonReady()
Called when server instance is Ready

public voidonShutdown()
Called when server instance is shuting down

        setStoppedState();
    
public voidonTermination()
Called when server instance is terminating. This method is the last one called during server shutdown.

abstract booleanpassivateEJB(ComponentContext context)

protected voidpopulateMethodMonitorMap()

        Method[] methods = null;
        boolean hasGeneratedClasses = (monitoredGeneratedClasses.size() > 0);
        if (hasGeneratedClasses) {
            List<Method> methodList = new ArrayList<Method>();
            for (Class clz : monitoredGeneratedClasses) {
                for (Method m : clz.getDeclaredMethods()) {
                    methodList.add(m);
                }
            }
            methods = methodList.toArray(new Method[0]);
        } else {
            Vector methodVec = ejbDescriptor.getMethods();
            int sz = methodVec.size();
            methods = new Method[sz];
            for (int i = 0; i < sz; i++) {
                methods[i] = (Method) methodVec.get(i);
            }
        }
        
        populateMethodMonitorMap(methods, hasGeneratedClasses);
    
protected voidpopulateMethodMonitorMap(java.lang.reflect.Method[] methods)

        populateMethodMonitorMap(methods, false);
    
protected voidpopulateMethodMonitorMap(java.lang.reflect.Method[] methods, boolean prefixClassName)

	/*
	methodMonitorMap = new HashMap();
	MethodMonitor[] methodMonitors = new MethodMonitor[methods.length];
	for (int i=0; i<methods.length; i++ ) {
	    methodMonitors[i] = new MethodMonitor(methods[i]);
	    methodMonitorMap.put(methods[i], methodMonitors[i]);
	}
	
	registryMediator.registerProvider(methodMonitors);
	*/
	registryMediator.registerEJBMethods(methods, prefixClassName);
	_logger.log(Level.FINE, "[Basecontainer] Registered Method Monitors");
    
public voidpostCreate(Invocation inv, java.lang.Object primaryKey)

        throw new EJBException("Internal error");
    
public java.lang.ObjectpostFind(Invocation inv, java.lang.Object primaryKeys, java.lang.Object[] findParams)

        throw new EJBException("Internal error");
    
public voidpostInvoke(Invocation inv)
Called from EJBObject/EJBHome after invoking on bean.

        postInvoke(inv, true);
    
protected voidpostInvoke(Invocation inv, boolean doTxProcessing)


        if (ejbMethodStatsManager.isMethodMonitorOn()) {
            ejbMethodStatsManager.postInvoke(inv.method, inv.exception);
        }
        
        
        if ( inv.ejb != null ) {
            // counterpart of invocationManager.preInvoke
            if (! inv.useFastPath) {
                invocationManager.postInvoke(inv);

                if (isStatefulSession
                        && (((EJBContextImpl) inv.context).getTransaction() != null)) {

                    SessionContextImpl sessionCtx = (SessionContextImpl) inv.context;
                    J2EETransaction j2eeTx = (J2EETransaction) sessionCtx
                            .getTransaction();

                    Map<EntityManagerFactory, EntityManager> entityManagerMap = sessionCtx
                            .getExtendedEntityManagerMap();
                    for (EntityManagerFactory emf : entityManagerMap.keySet()) {

                        if (sessionCtx.isEmfRegisteredWithTx(emf)) {
                            j2eeTx.removeExtendedEntityManagerMapping(emf);
                            sessionCtx.setEmfRegisteredWithTx(emf, false);
                        }
                    }
                }
            } else {
                doTxProcessing = doTxProcessing && (inv.exception != null);
            }
            
            try {
                if( doTxProcessing ) {
                    postInvokeTx(inv);
                }
            } catch (Exception ex) {
                _logger.log(Level.FINE, "ejb.postinvoketx_exception", ex);
                if (ex instanceof EJBException)
                    inv.exception = (EJBException) ex;
                else
                    inv.exception = new EJBException(ex);
            }
            
            releaseContext(inv);
        }
        
        if ( inv.exception != null ) {
            
            // Unwrap the PreInvokeException if necessary
            if ( inv.exception instanceof PreInvokeException ) {
                inv.exception = ((PreInvokeException)inv.exception).exception;
            }

            // Log system exceptions by default and application exceptions only
            // when log level is FINE or higher.
            Level exLogLevel = isSystemUncheckedException(inv.exception) ?
                Level.INFO : Level.FINE;

            _logger.log(exLogLevel,"ejb.some_unmapped_exception", logParams);
            _logger.log(exLogLevel, "", inv.exception);
            
            if ( !inv.isLocal ) {

                // For remote business case, exception mapping is performed
                // in client wrapper.  
                inv.exception = protocolMgr.mapException(inv.exception);
                    
                // The most useful portion of the system exception is logged 
                // above.  Only log mapped form when log level is FINE or 
                // higher.
                _logger.log(Level.FINE, "", inv.exception);

            } else {

                if( inv.isBusinessInterface ) {
                    inv.exception = 
                        mapBusinessInterfaceException(inv.exception);
                }

            }

        }
        
        if ( AppVerification.doInstrument()) {
            // need to pass the method, exception info,
            // and EJB descriptor to get app info
            AppVerification.getInstrumentLogger().doInstrumentForEjb(
            ejbDescriptor, inv.method, inv.exception);
            
        }
        
    
voidpostInvokeNoTx(Invocation inv)

        throw new EJBException(
            "Internal Error: BaseContainer.postInvokeNoTx called");
    
public voidpostInvokeTx(Invocation inv)
postInvokeTx is called after every invocation on the EJB instance, including ejbCreate/ejbFind---/ejbRemove. NOTE: postInvokeTx is called even if the EJB was not invoked because of an exception thrown from preInvokeTx.

        Method method = inv.method;
        InvocationInfo invInfo = inv.invocationInfo;
        Throwable exception = inv.exception;
        
        // For SessionBeans, ejbCreate/ejbRemove was called without a Tx,
        // so resume client's Tx if needed.
        // For EntityBeans, ejbCreate/ejbRemove/ejbFind must be called with a Tx
        // so no special processing needed.
        if ( isSession && !invInfo.isBusinessMethod ) {
            // check if there was a suspended client Tx
            if ( inv.clientTx != null )
                transactionManager.resume(inv.clientTx);
            
            if ( exception != null
                 && exception instanceof PreInvokeException ) {
                inv.exception = ((PreInvokeException)exception).exception;
            }
            
            return;
        }
        
        EJBContextImpl context = (EJBContextImpl)inv.context;
        
        int status = transactionManager.getStatus();
        int txAttr = inv.invocationInfo.txAttr;
        
        Throwable newException = exception; // default
        
        // Note: inv.exception may have been thrown by the container
        // during preInvoke (i.e. bean may never have been invoked).
        
        // Exception and Tx handling rules. See EJB2.0 Sections 17.6, 18.3.
        switch (txAttr) {
            case TX_BEAN_MANAGED:
                // EJB2.0 section 18.3.1, Table 16
                // Note: only SessionBeans can be TX_BEAN_MANAGED
                newException = checkExceptionBeanMgTx(context, exception,
                status);
                if ( inv.clientTx != null ) {
                    // there was a client Tx which was suspended
                    transactionManager.resume(inv.clientTx);
                }
                break;
                
            case TX_NOT_SUPPORTED:
            case TX_NEVER:
                // NotSupported and Never are handled in the same way
                // EJB2.0 sections 17.6.2.1, 17.6.2.6.
                // EJB executed in no Tx
                if ( exception != null )
                    newException = checkExceptionNoTx(context, exception);
                if ( isEntity )
                    postInvokeNoTx(inv);
                
                if ( inv.clientTx != null ) {
                    // there was a client Tx which was suspended
                    transactionManager.resume(inv.clientTx);
                }
                
                break;
                
            case TX_MANDATORY:
                // EJB2.0 section 18.3.1, Table 15
                // EJB executed in client's Tx
                if ( exception != null )
                    newException = checkExceptionClientTx(context, exception);
                break;
                
            case TX_REQUIRED:
                // EJB2.0 section 18.3.1, Table 15
                if ( inv.clientTx == null ) {
                    // EJB executed in new Tx started in preInvokeTx
                    newException = completeNewTx(context, exception, status);
                }
                else {
                    // EJB executed in client's tx
                    if ( exception != null ) {
                        newException = checkExceptionClientTx(context,
                        exception);
                    }
                }
                break;
                
            case TX_REQUIRES_NEW:
                // EJB2.0 section 18.3.1, Table 15
                // EJB executed in new Tx started in preInvokeTx
                newException = completeNewTx(context, exception, status);
                
                if ( inv.clientTx != null ) {
                    // there was a client Tx which was suspended
                    transactionManager.resume(inv.clientTx);
                }
                break;
                
            case TX_SUPPORTS:
                // EJB2.0 section 18.3.1, Table 15
                if ( status != Status.STATUS_NO_TRANSACTION ) {
                    // EJB executed in client's tx
                    if ( exception != null ) {
                        newException = checkExceptionClientTx(context,
                        exception);
                    }
                }
                else {
                    // EJB executed in no Tx
                    if ( exception != null )
                        newException = checkExceptionNoTx(context, exception);
                    if ( isEntity )
                        postInvokeNoTx(inv);
                }
                break;
                
            default:
        }
        
        inv.exception = newException;
        
        // XXX If any of the TM commit/rollback/suspend calls throws an
        // exception, should the transaction be rolled back if not already so ?
    
protected InvocationInfopostProcessInvocationInfo(InvocationInfo invInfo)

        return invInfo;
    
protected voidpreInitialize(com.sun.enterprise.deployment.EjbDescriptor ejbDesc, java.lang.ClassLoader loader)

        //Overridden in sub classes
    
public voidpreInvoke(Invocation inv)
Called from EJBObject/EJBHome before invoking on EJB. Set the EJB instance in the Invocation.

        try {
            if (containerState != CONTAINER_STARTED) {
                throw new EJBException("Attempt to invoke when container is in "
                                       + containerStateToString(containerState));
            }
            
            if( inv.method == null ) {
                throw new EJBException("Attempt to invoke container with null " +
                                       " invocation method");
            }

            if( inv.invocationInfo == null ) {

                inv.invocationInfo = getInvocationInfo(inv);

                if( inv.invocationInfo == null ) {
                    throw new EJBException("Invocation Info lookup failed for " +
                                           "method " + inv.method);
                }
            }

            inv.transactionAttribute = inv.invocationInfo.txAttr;
            inv.container = this;

            if (inv.method != ejbTimeoutMethod) {
               
                if (! authorize(inv)) {
                    throw new AccessLocalException(
                        "Client not authorized for this invocation.");
                }
                
            }
            
            // Cache value of txManager.getStatus() in invocation to avoid
            // multiple thread-local accesses of that value during pre-invoke
            // stage.
            inv.setPreInvokeTxStatus(transactionManager.getStatus());

            ComponentContext ctx = getContext(inv);
            inv.context = ctx;
            
            inv.instance = inv.ejb = ctx.getEJB();
            InvocationInfo info = inv.invocationInfo;
            
            inv.useFastPath = (info.isTxRequiredLocalCMPField) && (inv.foundInTxCache);
            //    _logger.log(Level.INFO, "Use fastPath() ==> " + info.method);
            
            if (!inv.useFastPath) {
                // Sets thread-specific state for Transaction, Naming, Security,
                // etc
                invocationManager.preInvoke(inv);

                // Do Tx machinery
                preInvokeTx(inv);

                // null out invocation preInovkeTxStatus since the cache value
                // is obsolete
                inv.setPreInvokeTxStatus(null);

                enlistExtendedEntityManagers(ctx);
            }
            
            if (ejbMethodStatsManager.isMethodMonitorOn()) {
                ejbMethodStatsManager.preInvoke(inv.method);
            }
            
        }
        catch ( Exception ex ) {
            _logger.log(Level.FINE, "ejb.preinvoke_exception", logParams);
            _logger.log(Level.FINE, "", ex);
            
            EJBException ejbEx;
            if ( ex instanceof EJBException ) {
                ejbEx = (EJBException)ex;
            } else {
                ejbEx = new EJBException(ex);
            }
            
            throw new PreInvokeException(ejbEx);
        }
    
voidpreInvokeNoTx(Invocation inv)

        throw new EJBException(
            "Internal Error: BaseContainer.preInvokeNoTx called");
    
protected final voidpreInvokeTx(Invocation inv)
This is called from preInvoke before every method invocation on the EJB instance, including ejbCreate, ejbFind*, ejbRemove. Also called from MessageBeanContainer, WebServiceInvocationHandler, etc, so we can't assume that BaseContainer.preInvoke(Invocation) has run. Therefore, handle inv.invocationInfo defensively since it might not have been initialized.

        Method method = inv.method;       

        if (inv.invocationInfo==null) {

            inv.invocationInfo = getInvocationInfo(inv);

            if( inv.invocationInfo == null ) {
                throw new EJBException("Invocation Info lookup failed for " +
                                       "method " + inv.method);
            } else {
                inv.transactionAttribute = inv.invocationInfo.txAttr;
            }
        }
        
        // Get existing Tx status: this tells us if the client
        // started a transaction which was propagated on this invocation.
        Integer preInvokeTxStatus = inv.getPreInvokeTxStatus();
        int status = (preInvokeTxStatus != null) ?
            preInvokeTxStatus.intValue() : transactionManager.getStatus();
        
        //For MessageDrivenBeans,ejbCreate/ejbRemove must be called without a Tx.
        // For SessionBeans, ejbCreate/ejbRemove must be called without a Tx.
        // For EntityBeans, ejbCreate/ejbRemove/ejbFind must be called with a Tx
        // so no special work needed.
        if ( isSession && !inv.invocationInfo.isBusinessMethod ) {
            // EJB2.0 section 7.5.7 says that ejbCreate/ejbRemove etc are called
            // without a Tx. So suspend the client's Tx if any.
            
            // Note: ejbRemove cannot be called when EJB is associated with
            // a Tx, according to EJB2.0 section 7.6.4. This check is done in
            // the container's implementation of removeBean().
            
            if ( status != Status.STATUS_NO_TRANSACTION ) {
                // client request is associated with a Tx
                try {
                    inv.clientTx = transactionManager.suspend();
                } catch (SystemException ex) {
                    throw new EJBException(ex);
                }
            }
            return;
        }
        
        // isNullTx is true if the client sent a null tx context
        // (i.e. a tx context with a null Coordinator objref)
        // or if this server's tx interop mode flag is false.
        // Follow the tables in EJB2.0 sections 19.6.2.2.1 and 19.6.2.2.2.
        boolean isNullTx = false;
        //if (!inv.isLocal && !inv.isMessageDriven && !inv.isWebService)
        if (!inv.isLocal) {
            isNullTx = transactionManager.isNullTransaction();
        }
        
        int txAttr = getTxAttr(inv);
        
        EJBContextImpl context = (EJBContextImpl)inv.context;
        
        // Note: in the code below, inv.clientTx is set ONLY if the
        // client's Tx is actually suspended.
        
        // get the Tx associated with the EJB from previous invocation,
        // if any.
        Transaction prevTx = context.getTransaction();
        
        switch (txAttr) {
            case TX_BEAN_MANAGED:
                // TX_BEAN_MANAGED rules from EJB2.0 Section 17.6.1, Table 13
                // Note: only MDBs and SessionBeans can be TX_BEAN_MANAGED
                if ( status != Status.STATUS_NO_TRANSACTION ) {
                    // client request associated with a Tx, always suspend
                    inv.clientTx = transactionManager.suspend();
                }
                if ( isSession && !isStatelessSession && prevTx != null
                && prevTx.getStatus() != Status.STATUS_NO_TRANSACTION ) {
                    // Note: if prevTx != null , then it means
                    // afterCompletion was not called yet for the
                    // previous transaction on the EJB.
                    
                    // The EJB was previously associated with a Tx which was
                    // begun by the EJB itself in a previous invocation.
                    // This is only possible for stateful SessionBeans
                    // not for StatelessSession or Entity.
                    transactionManager.resume(prevTx);
                    
                    // This allows the TM to enlist resources
                    // used by the EJB with the transaction
                    transactionManager.enlistComponentResources();
                }
                
                break;
                
            case TX_NOT_SUPPORTED:
                if ( status != Status.STATUS_NO_TRANSACTION )
                    inv.clientTx = transactionManager.suspend();
                checkUnfinishedTx(prevTx, inv);
                if ( isEntity )
                    preInvokeNoTx(inv);
                break;
                
            case TX_MANDATORY:
                if ( isNullTx || status == Status.STATUS_NO_TRANSACTION )
                    throw new TransactionRequiredLocalException();
                
                useClientTx(prevTx, inv);
                break;
                
            case TX_REQUIRED:
                if ( isNullTx )
                    throw new TransactionRequiredLocalException();
                
                if ( status == Status.STATUS_NO_TRANSACTION ) {
                    inv.clientTx = null;
                    startNewTx(prevTx, inv);
                }
                else { // There is a client Tx
                    inv.clientTx = transactionManager.getTransaction();
                    useClientTx(prevTx, inv);
                }
                break;
                
            case TX_REQUIRES_NEW:
                if ( status != Status.STATUS_NO_TRANSACTION )
                    inv.clientTx = transactionManager.suspend();
                startNewTx(prevTx, inv);
                break;
                
            case TX_SUPPORTS:
                if ( isNullTx )
                    throw new TransactionRequiredLocalException();
                
                if ( status != Status.STATUS_NO_TRANSACTION )
                    useClientTx(prevTx, inv);
                else { // we need to invoke the EJB with no Tx.
                    checkUnfinishedTx(prevTx, inv);
                    if ( isEntity )
                        preInvokeNoTx(inv);
                }
                break;
                
            case TX_NEVER:
                if ( isNullTx || status != Status.STATUS_NO_TRANSACTION )
                    throw new EJBException(
                        "EJB cannot be invoked in global transaction");
                
                else { // we need to invoke the EJB with no Tx.
                    checkUnfinishedTx(prevTx, inv);
                    if ( isEntity )
                        preInvokeNoTx(inv);
                }
                break;
                
            default:
                throw new EJBException("Bad transaction attribute");
        }
    
public voidpreSelect()

        throw new EJBException(
	    "preSelect only works for EntityContainer");
    
private java.lang.ThrowableprocessSystemException(java.lang.Throwable sysEx)

        Throwable newException;
        if ( sysEx instanceof EJBException)
            return sysEx;
        
        // EJB2.0 section 18.3.4
        if ( sysEx instanceof NoSuchEntityException ) { // for EntityBeans only
            newException = new NoSuchObjectLocalException
                ("NoSuchEntityException thrown by EJB method.");
            newException.initCause(sysEx);
        } else {
            newException = new EJBException();
            newException.initCause(sysEx);
        }

        return newException;
    
protected voidregisterMonitorableComponents()

        registerTimerMonitorableComponent();
    
protected voidregisterTimerMonitorableComponent()

        if( isTimedObject() ) {
            toMonitorProps = new TimedObjectMonitorableProperties();
	    registryMediator.registerProvider( toMonitorProps );
	}
        _logger.log(Level.FINE, "[BaseContainer] registered timer monitorable");
    
protected voidregisterTxAttrForMethod(java.lang.reflect.Method method, java.lang.String methodIntf)

        addInvocationInfo(method, methodIntf, null);
    
protected abstract voidreleaseContext(Invocation inv)

public voidreleaseTargetObject(java.rmi.Remote remoteObj)
Release the EJBObject/EJBHome object. Called from the ProtocolManager after a remote invocation completes.

        externalPostInvoke();
    
abstract voidremoveBean(EJBLocalRemoteObject ejbo, java.lang.reflect.Method removeMethod, boolean local)

public voidremoveBeanUnchecked(java.lang.Object pkey)

        throw new EJBException(
            "removeBeanUnchecked only works for EntityContainer");
    
public voidremoveBeanUnchecked(EJBLocalObject bean)

        throw new EJBException(
            "removeBeanUnchecked only works for EntityContainer");
    
public voidsetDebugMonitorFlag(boolean flag)

        debugMonitorFlag = flag;
    
private voidsetEJBObjectTargetMethodInfo(InvocationInfo invInfo, boolean isLocal, java.lang.Class originalIntf)


        Class ejbIntfClazz = isLocal ? 
            javax.ejb.EJBLocalObject.class : javax.ejb.EJBObject.class;

        Class[] paramTypes = invInfo.method.getParameterTypes();
        String methodName  = invInfo.method.getName();

        // Check for 2.x Remote/Local bean attempts to override 
        // EJBObject/EJBLocalObject operations.  
        if( ejbIntfClazz.isAssignableFrom(originalIntf) ) {
            try {
                Method m = ejbIntfClazz.getMethod(methodName, paramTypes);
                // Attempt to override EJBObject/EJBLocalObject method.  Print 
                // warning but don't treat it as a fatal error. At runtime, the
                // EJBObject/EJBLocalObject method will be called.
                String[] params = { m.toString(),invInfo.method.toString() };
                _logger.log(Level.WARNING, 
                            "ejb.illegal_ejb_interface_override", params);
                invInfo.ejbIntfOverride = true;
                return;
            } catch(NoSuchMethodException nsme) {
            }
        }

        try {
            invInfo.targetMethod1 = ejbClass.getMethod(methodName, paramTypes);

            if( isSession && isStatefulSession ) {
                MethodDescriptor methodDesc = new MethodDescriptor
                    (invInfo.targetMethod1, MethodDescriptor.EJB_BEAN);

                // Assign removal info to inv info.  If this method is not
                // an @Remove method, result will be null.
                invInfo.removalInfo = ((EjbSessionDescriptor)ejbDescriptor).
                    getRemovalInfo(methodDesc);
            }

        } catch(NoSuchMethodException nsme) {
            Object[] params = { logParams[0] + ":" + nsme.toString(), 
                                (isLocal ? "Local" : "Remote"),
                                invInfo.method.toString() };
            _logger.log(Level.WARNING, 
                        "ejb.bean_class_method_not_found", params);
            // Treat this as a warning instead of a fatal error.
            // That matches the behavior of the generated code.
            // Mark the target methods as null.  If this method is
            // invoked at runtime it will be result in an exception from
            // the invocation handlers.
            invInfo.targetMethod1 = null;            
        }
    
private voidsetHomeTargetMethodInfo(InvocationInfo invInfo, boolean isLocal)

                                         
        Class homeIntfClazz = isLocal ? 
            javax.ejb.EJBLocalHome.class : javax.ejb.EJBHome.class;

        boolean isEntity = (ejbDescriptor instanceof EjbEntityDescriptor);

        Class methodClass  = invInfo.method.getDeclaringClass();
        Class[] paramTypes = invInfo.method.getParameterTypes();
        String methodName  = invInfo.method.getName();

        try {
            Method m = homeIntfClazz.getMethod(methodName, paramTypes);
            // Attempt to override Home/LocalHome method.  Print warning
            // but don't treat it as a fatal error. At runtime, 
            // the EJBHome/EJBLocalHome method will be called.
            String[] params = { m.toString(),invInfo.method.toString() };
            _logger.log(Level.WARNING, 
                        "ejb.illegal_ejb_interface_override", params);
            invInfo.ejbIntfOverride = true;
            return;
        } catch(NoSuchMethodException nsme) {
        }

        try {
            if( invInfo.startsWithCreate ) {
                
                String extraCreateChars = 
                    methodName.substring("create".length());
                invInfo.targetMethod1 = ejbClass.getMethod
                    ("ejbCreate" + extraCreateChars, paramTypes);
                
                if( isEntity ) {
                    invInfo.targetMethod2 = ejbClass.getMethod
                        ("ejbPostCreate" + extraCreateChars, paramTypes);
                }
                
            } else if ( invInfo.startsWithFind ) {
                
                String extraFinderChars = methodName.substring("find".length());
                invInfo.targetMethod1 = ejbClass.getMethod
                    ("ejbFind" + extraFinderChars, paramTypes);
                
            } else {

                // HOME method

                String upperCasedName = 
                    methodName.substring(0,1).toUpperCase() +
                    methodName.substring(1);
                invInfo.targetMethod1 = ejbClass.getMethod
                    ("ejbHome" + upperCasedName, paramTypes);
            }
        } catch(NoSuchMethodException nsme) {
            
            if( (methodClass == localBusinessHomeIntf) ||
                (methodClass == remoteBusinessHomeIntf) ) {
                // Not an error.  This is the case where the EJB 3.0
                // client view is being used and there is no corresponding
                // create/init method.
            } else if (isStatelessSession ) {
                // Ignore.  Not an error.  
                // EJB 3.0 Stateless session ejbCreate/PostConstruct
                // is decoupled from RemoteHome/LocalHome create().
            } else {

                Method initMethod = null;
                if( isSession ) {
                    EjbSessionDescriptor sessionDesc = 
                        (EjbSessionDescriptor) ejbDescriptor;

                    for(EjbInitInfo next : sessionDesc.getInitMethods()) {
                        MethodDescriptor beanMethod = next.getBeanMethod();
                        Method m = beanMethod.getMethod(sessionDesc);
                        if( next.getCreateMethod().getName().equals(methodName)
                            &&
                            TypeUtil.sameParamTypes(m, invInfo.method) ) {
                            initMethod = m;
                            break;
                        }
                    }
                }
                
                if( initMethod != null ) {
                    invInfo.targetMethod1 = initMethod;
                } else {
                    Object[] params = { logParams[0], 
                                        (isLocal ? "LocalHome" : "Home"),
                                        invInfo.method.toString() };
                    _logger.log(Level.WARNING, 
                                "ejb.bean_class_method_not_found", params);
                    // Treat this as a warning instead of a fatal error.
                    // That matches the behavior of the generated code.
                    // Mark the target methods as null.  If this method is
                    // invoked at runtime it will be result in an exception 
                    // from the invocation handlers.
                    invInfo.targetMethod1 = null;
                    invInfo.targetMethod2 = null;
                }
            }
        }
    
public voidsetMonitorOn(boolean flag)

        monitorOn = flag;
    
public final voidsetSecurityManager(com.sun.enterprise.SecurityManager sm)

        securityManager = sm;
    
public final voidsetStartedState()

        containerState = CONTAINER_STARTED;
    
public final voidsetStoppedState()

        containerState = CONTAINER_STOPPED;
    
public final voidsetUndeployedState()

        containerState = CONTAINER_UNDEPLOYED;
    
private voidsetupEnvironment()

        // call the NamingManager to setup the java:comp/env namespace
        // for this EJB.
        componentId = namingManager.bindObjects(ejbDescriptor);
        
        // create envProps object to be returned from EJBContext.getEnvironment
        Set env = ejbDescriptor.getEnvironmentProperties();
        SafeProperties safeProps = new SafeProperties();
        safeProps.copy(env);
        envProps = safeProps;
    
private voidstartNewTx(javax.transaction.Transaction prevTx, Invocation inv)

        checkUnfinishedTx(prevTx, inv);
        
        if (cmtTimeoutInSeconds > 0) {
            transactionManager.begin(cmtTimeoutInSeconds);
        } else {
            transactionManager.begin();
        }
        
        EJBContextImpl context = (EJBContextImpl)inv.context;
        Transaction tx = transactionManager.getTransaction();
        context.setTransaction(tx);
        
        // This allows the TM to enlist resources used by the EJB
        // with the transaction
        transactionManager.enlistComponentResources();
        
        // register synchronization for methods other than finders/home methods
        Method method = inv.method;
        if ( !inv.invocationInfo.isHomeFinder ) {
            // Register for Synchronization notification
            containerFactory.getContainerSync(tx).addBean(context);
        }
        
        // Call afterBegin/ejbLoad. If ejbLoad throws exceptions,
        // the completeNewTx machinery called by postInvokeTx
        // will rollback the tx. Since we have already registered
        // a Synchronization object with the TM, the afterCompletion
        // will get called.
        afterBegin(context);
    
public java.lang.StringtoString()

	return _debugDescription;
    
public voidundeploy()
Perform common undeploy actions. NOTE that this should be done defensively so that we attempt to do as much cleanup as possible, even in the face of errors during undeploy. This might be called after an unsuccessful deployment, in which case some of the services might not have been initialized.

        
        final Thread currentThread = Thread.currentThread();
        final ClassLoader previousClassLoader =
            currentThread.getContextClassLoader();
       
        try {
            destroyTimers();
        } catch(Exception e) {
            _logger.log(Level.FINE, "Error destroying timers for " +
                        ejbDescriptor.getName(), e);
        }

        try {
            if(System.getSecurityManager() == null) {
                currentThread.setContextClassLoader(loader);
            } else {
                java.security.AccessController.doPrivileged(
                        new java.security.PrivilegedAction() {
                    public java.lang.Object run() {
                        currentThread.setContextClassLoader(loader);
                        return null;
                    }
                });
            }
            
            theSwitch.removeDescriptorFor(this);
            securityManager.destroy();
            
            if( !isMessageDriven ) {
                // destroy home objref
                try {
                    if ( isLocal ) {
                        // No specific undeploy steps
                    }
                    if ( isRemote ) {
                       

                        if( hasRemoteHomeView ) {
                            try {
                                namingManager.unpublishObject
                                    (remoteHomeJndiName);
                            } catch(NamingException ne) {
                                _logger.log(Level.FINE, 
                                            "ejb.undeploy_exception", 
                                            logParams);
                                _logger.log(Level.FINE, "", ne);
                            }

                            remoteHomeRefFactory.destroyReference(ejbHomeStub, 
                                                              ejbHome);

                            // Hints to release stub-related meta-data in ORB
                            remoteHomeRefFactory.cleanupClass(homeIntf);
                            remoteHomeRefFactory.cleanupClass(remoteIntf);
                            remoteHomeRefFactory.cleanupClass(ejbHome.getClass());
                            remoteHomeRefFactory.cleanupClass(ejbObjectProxyClass);
                        
                            // destroy the factory itself
                            remoteHomeRefFactory.destroy(); 
                        }

                        if( hasRemoteBusinessView ) {
                            try {
                                namingManager.unpublishObject
                                    (remoteBusinessHomeJndiName);
                            } catch(NamingException ne) {
                                _logger.log(Level.FINE, 
                                            "ejb.undeploy_exception", 
                                            logParams);
                                _logger.log(Level.FINE, "", ne);
                            }

                            if( remoteBusinessJndiName != null ) {
                                try {
                                    // Unbind object factory.  Avoid using
                                    // NamingManager.unpublish() b/c that
                                    // method has a side-effect which first
                                    // does a lookup of the given name.
                                    namingManager.getInitialContext().unbind
                                        (remoteBusinessJndiName);
                                } catch(NamingException ne) {
                                    _logger.log(Level.FINE, 
                                                "ejb.undeploy_exception", 
                                                logParams);
                                    _logger.log(Level.FINE, "", ne);
                                }
                            }

                            // Home related cleanup
                            RemoteReferenceFactory remoteBusinessRefFactory =
                             remoteBusinessIntfInfo.values().iterator().
                                next().referenceFactory;
                            remoteBusinessRefFactory.destroyReference
                                (ejbRemoteBusinessHomeStub, 
                                 ejbRemoteBusinessHome);

                            remoteBusinessRefFactory.cleanupClass
                                (remoteBusinessHomeIntf);
                            remoteBusinessRefFactory.cleanupClass
                                (ejbRemoteBusinessHome.getClass());

                            // Cleanup for each remote business interface
                            for(RemoteBusinessIntfInfo next : 
                                    remoteBusinessIntfInfo.values()) {

                                try {
                                    // Unbind object factory.  Avoid using
                                    // NamingManager.unpublish() b/c that
                                    // method has a side-effect which first
                                    // does a lookup of the given name.
                                    namingManager.getInitialContext().unbind
                                        (next.jndiName);
                                } catch(NamingException ne) {
                                    _logger.log(Level.FINE, 
                                                "ejb.undeploy_exception", 
                                                logParams);
                                    _logger.log(Level.FINE, "", ne);
                                }

                                next.referenceFactory.cleanupClass
                                    (next.generatedRemoteIntf);

                                next.referenceFactory.cleanupClass
                                    (next.proxyClass);
                        
                                // destroy the factory itself
                                next.referenceFactory.destroy(); 
                            }
                        }
      
                    }
                } catch ( Exception ex ) {
                    _logger.log(Level.FINE, "ejb.undeploy_exception", 
                        logParams);
                    _logger.log(Level.FINE, "", ex);
                }
            }

	    try {
		namingManager.unbindObjects(ejbDescriptor);
	    } catch (javax.naming.NamingException namEx) {
		_logger.log(Level.FINE, "ejb.undeploy_exception", 
                        logParams);
		_logger.log(Level.FINE, "", namEx);
	    }
            
	    registryMediator.undeploy();
	    registryMediator = null;
	    ejbMethodStatsManager = null;
            containerFactory.removeContainer(ejbDescriptor.getUniqueId());

            
        } finally {
            if(System.getSecurityManager() == null) {
                currentThread.setContextClassLoader(previousClassLoader);
            } else {
                java.security.AccessController.doPrivileged(
                        new java.security.PrivilegedAction() {
                    public java.lang.Object run() {
                        currentThread.setContextClassLoader(previousClassLoader);
                        return null;
                    }
                });
            }
        }
        
        _logger.log(Level.FINE,
                    "**** [BaseContainer]: Successfully Undeployed " +
                    ejbDescriptor.getName() + " ...");
        
        ejbDescriptor = null;
        
        if (invocationInfoMap != null)  { invocationInfoMap.clear(); }
        if (methodMonitorMap != null)   { methodMonitorMap.clear();  }
        
        
        loader                  = null;
        ejbClass                = null;
        ejbPassivateMethod      = null;
        ejbActivateMethod       = null;
        ejbRemoveMethod         = null;
        
        remoteIntf              = null;
        homeIntf                = null;
        localHomeIntf           = null;
        localIntf               = null;
        ejbLocalHome            = null;
        metadata                = null;
        ejbHomeImpl             = null;
        ejbHomeStub             = null;
        invocationInfoMap       = null;
        ejbIntfMethods          = null;
        envProps                = null;
        methodMonitorMap        = null;
    
protected voiduseClientTx(javax.transaction.Transaction prevTx, Invocation inv)

        Transaction clientTx;
        int status=-1;
        int prevStatus=-1;
        try {
            // Note: inv.clientTx will not be set at this point.
            clientTx = transactionManager.getTransaction();
            status = clientTx.getStatus();  // clientTx cant be null
            if ( prevTx != null )
                prevStatus = prevTx.getStatus();
        } catch (Exception ex) {
            try {
                transactionManager.setRollbackOnly();
            } catch ( Exception e ) { 
				//FIXME: Use LogStrings.properties
				_logger.log(Level.FINEST, "", e); 
			} 
            throw new TransactionRolledbackLocalException("", ex);
        }
        
        // If the client's tx is going to rollback, it is fruitless
        // to invoke the EJB, so throw an exception back to client.
        if ( status == Status.STATUS_MARKED_ROLLBACK
        || status == Status.STATUS_ROLLEDBACK
        || status == Status.STATUS_ROLLING_BACK )
            throw new TransactionRolledbackLocalException(
                "Client's transaction aborted");
        

        if( isStatefulSession ) {

            SessionContextImpl sessionCtx = (SessionContextImpl) inv.context;
            Map<EntityManagerFactory, EntityManager> entityManagerMap =
                sessionCtx.getExtendedEntityManagerMap();

            J2EETransaction clientJ2EETx = (J2EETransaction) clientTx;
            for(EntityManagerFactory emf : entityManagerMap.keySet()) {

                // Make sure there is no Transactional persistence context
                // for the same EntityManagerFactory as this SFSB's 
                // Extended persistence context for the propagated transaction.
                if( clientJ2EETx.getTxEntityManager(emf) != null ) {
                    throw new EJBException("There is an active transactional persistence context for the same EntityManagerFactory as the current stateful session bean's extended persistence context");
                }

                // Now see if there's already a *different* extended 
                // persistence context within this transaction for the 
                // same EntityManagerFactory.
                EntityManager em = clientJ2EETx.getExtendedEntityManager(emf);
                if( (em != null) && entityManagerMap.get(emf) != em ) {
                    throw new EJBException("Detected two different extended persistence contexts for the same EntityManagerFactory within a transaction");
                }

            }
            
        }

        if ( prevTx == null
        || prevStatus == Status.STATUS_NO_TRANSACTION ) {
            // First time the bean is running in this new client Tx
            EJBContextImpl context = (EJBContextImpl)inv.context;
            context.setTransaction(clientTx);
            try {
                transactionManager.enlistComponentResources();
                
                if ( !isStatelessSession && !isMessageDriven) {
                    // Create a Synchronization object.
                    
                    // Not needed for stateless beans or message-driven beans
                    // because they cant have Synchronization callbacks,
                    // and they cant be associated with a tx across
                    // invocations.
                    // Register sync for methods other than finders/home methods
                    Method method = inv.method;
                    if ( !inv.invocationInfo.isHomeFinder ) {
                        containerFactory.getContainerSync(clientTx).addBean(
                        context);
                    }
                    
                    afterBegin(context);
                }
            } catch (Exception ex) {
                try {
                    transactionManager.setRollbackOnly();
                } catch ( Exception e ) { 
					//FIXME: Use LogStrings.properties
					_logger.log(Level.FINEST, "", e); 
				} 
                throw new TransactionRolledbackLocalException("", ex);
            }
        }
        else { // Bean already has a transaction associated with it.
            if ( !prevTx.equals(clientTx) ) {
                // There is already a different Tx in progress !!
                // Note: this can only happen for stateful SessionBeans.
                // EntityBeans will get a different context for every Tx.
                if ( isSession ) {
                    // Row 2 in Table E
                    throw new IllegalStateException(
                    "EJB is already associated with an incomplete transaction");
                }
            }
            else { // Bean was invoked again with the same transaction
                // This allows the TM to enlist resources used by the EJB
                // with the transaction
                try {
                    transactionManager.enlistComponentResources();
                } catch (Exception ex) {
                    try {
                        transactionManager.setRollbackOnly();
                    } catch ( Exception e ) { 
                        //FIXME: Use LogStrings.properties
                        _logger.log(Level.FINEST, "", e); 
					}
                    throw new TransactionRolledbackLocalException("", ex);
                }
            }
        }
    
public booleanuserTransactionMethodsAllowed(ComponentInvocation inv)
EJB spec makes a distinction between access to the UserTransaction object itself and access to its methods. getUserTransaction covers the first check and this method covers the second. It is called by the UserTransaction implementation to verify access.

        // Overridden by containers that allowed BMT;
        return false;
    
public voidwebServicePostInvoke(Invocation inv)

        // postInvokeTx is handled by WebServiceInvocationHandler.
        // Invoke postInvoke with instructions to skip tx processing portion.
        postInvoke(inv, false);