/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
import javax.transaction.*;
/**
* This class implements part of the com.sun.ejb.Container interface.
* It implements the container's side of the EJB-to-Container
* contract definweed 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.
*
*/
public abstract class BaseContainer
{
public enum ContainerType {
};
// used in authorizeRemoteMethod and authorizeLocalMethod
// true if home method, false if component intf method.
// Used for setting info on invocation object during authorization.
private static final boolean[] EJB_INTF_METHODS_INFO =
{ true, true, true, true, true,
false, false, false, false, false,
false, false, false, false,
true, true };
// true if exposed as a web service endpoint.
protected boolean isWebServiceEndpoint = false;
private boolean isTimedObject_ = false;
/*****************************************
* Data members for Local views *
*****************************************/
// OR a Local business view OR both.
protected boolean isLocal=false;
// True if bean exposes a local home view
protected boolean hasLocalHomeView=false;
// True if bean exposes a local business view
protected boolean hasLocalBusinessView=false;
protected boolean hasOptionalLocalBusinessView = false;
//
//
// LocalHome interface written by developer
// Local interface written by developer
// Client reference to ejb local home
// Implementation of ejb local home. May or may not be the same
// object as ejbLocalHome, for example in the case of dynamic proxies.
// Constructor used to instantiate ejb local object proxy.
//
// Data members for 3.x Local business view
//
// Internal interface describing operation used to create an
// instance of a local business object. (GenericEJBLocalHome)
// Local business interface written by developer
// Client reference to internal local business home interface.
// This is only seen by internal ejb code that instantiates local
// business objects during lookups.
// Implementation of internal local business home interface.
// Implementation of internal local business home interface.
// Constructor used to instantiate local business object proxy.
// Constructor used to instantiate local business object proxy.
/*****************************************
* Data members for Remote views *
*****************************************/
// True if bean has a RemoteHome/Remote view
// OR a Remote business view OR both.
protected boolean isRemote=false;
// True if bean exposes a RemoteHome view
protected boolean hasRemoteHomeView=false;
// True if bean exposes a Remote Business view.
protected boolean hasRemoteBusinessView=false;
//
// Data members for RemoteHome/Remote view
//
// Home interface written by developer.
// Remote interface written by developer.
// Container implementation of EJB Home. May or may not be the same
// object as ejbHome, for example in the case of dynamic proxies.
// EJB Home reference used by ORB Tie within server to deliver
// invocation.
// Client reference to EJB Home.
// Remote interface proxy class
// Remote interface proxy constructor.
// RemoteReference Factory for RemoteHome view
//
// Data members for 3.x Remote business view
//
// Internal interface describing operation used to create an
// instance of a remote business object.
// Container implementation of internal EJB Business Home. May or may
// not be same object as ejbRemoteBusinessHome, for example in the
// case of dynamic proxies.
// EJB Remote Business Home reference used by ORB Tie within server
// to deliver invocation.
// Client reference to internal Remote EJB Business Home. This is
// only seen by internal EJB code that instantiates remote business
// objects during lookups.
// Holds information such as remote reference factory that are associated
// with a particular remote business interface
//
// END -- Data members for Remote views
//
protected boolean isSession;
protected boolean isStatelessSession;
protected boolean isStatefulSession;
protected boolean isMessageDriven;
protected boolean isEntity;
protected boolean isSingleton;
// Need a separate map for web service methods since it's possible for
// an EJB Remote interface to be a subtype of the Service Endpoint
// Interface. In that case, it's ambiguous to do a lookup based only
// on a java.lang.reflect.Method
// optimized method map for proxies to resolve invocation info
boolean isBeanManagedTran=false;
protected boolean debugMonitorFlag = false;
new LocalStringManagerImpl(BaseContainer.class);
protected boolean monitorOn = false;
//protected TimedObjectMonitorableProperties toMonitorProps = null;
//protected Agent callFlowAgent;
PostConstruct.class, PrePassivate.class,
PostActivate.class, PreDestroy.class
};
// Used to track whether we've done the base container cleanup (JNDI entries, etc.)
// Only. Not applicable to concrete containers.
private boolean baseContainerCleanupDone = false;
// True if there is at least one asynchronous method exposed from the bean.
private boolean hasAsynchronousInvocations = false;
// Information about a web service ejb endpoint. Used as a conduit
// between webservice runtime and ejb container. Contains a Remote
// servant used by jaxrpc to call web service business method.
//The Webservices Ejb Endpoint Registry contract
// used to register and unregister ejb webservices endpoints
/**
* This constructor is called from ContainerFactoryImpl when an
* EJB Jar is deployed.
*/
throws Exception
{
this.containerType = type;
try {
this.ejbDescriptor = ejbDesc;
//this.callFlowAgent = ejbContainerUtilImpl.getCallFlowAgent();
// get Class objects for creating new EJBs
{
assertFullProfile("is a Message-Driven Bean");
isMessageDriven = true;
isBeanManagedTran = true;
}
else {
isBeanManagedTran = false;
}
// Instantiate the ORB and Remote naming manager
// to allow client lookups of JMS queues/topics/connectionfactories
// Once that's available, this call can be removed.
}
else {
assertFullProfile("is an Entity Bean");
isEntity = true;
} else {
isSession = true;
if( !sd.isSessionTypeSet() ) {
"ejb.session_type_not_set",
"Invalid ejb Descriptor. Session type not set for {0}: {1}",
}
if (sd.isSingleton()) {
isSingleton = true;
} else {
if( isStatefulSession ) {
/**
* If bean class isn't explicitly marked Serializable, generate
* a subclass that is. We do this with a generator that uses
* ASM directly instead of the CORBA codegen library since none
* of the corba .jars are part of the Web Profile.
*/
}
}
}
isBeanManagedTran = true;
} else {
isBeanManagedTran = false;
}
if( hasAsynchronousInvocations ) {
assertFullProfile("defines asynchronous session bean methods");
}
}
if ( ejbDescriptor.isRemoteInterfacesSupported() ||
assertFullProfile("exposes a Remote client view");
}
if ( ejbDescriptor.isRemoteInterfacesSupported() ) {
isRemote = true;
hasRemoteHomeView = true;
}
isRemote = true;
hasRemoteBusinessView = true;
// 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.
new RemoteBusinessIntfInfo();
// One remote reference factory for each remote
// business interface. Id must be unique across
// all ejb containers.
getRemoteReferenceFactory(this, false, id);
info);
}
}
if ( ejbDescriptor.isLocalInterfacesSupported() ) {
isLocal = true;
hasLocalHomeView = true;
}
isLocal = true;
hasLocalBusinessView = true;
localBusinessHomeIntf = GenericEJBLocalHome.class;
}
}
if( ejbDescriptor.isLocalBean() ) {
isLocal = true;
hasOptionalLocalBusinessView = true;
((EjbOptionalIntfGenerator) optIntfClassLoader).generateOptionalLocalInterface(ejbClass, optIntfClassName);
}
if( isStatelessSession || isSingleton ) {
// JSR 109 doesn't require support for a single ejb
// implementing multiple port ex.
assertFullProfile("is a Web Service Endpoint");
isWebServiceEndpoint = true;
}
}
try{
// get Method objects for ejbPassivate/Activate/ejbRemove
} catch(NoSuchMethodException nsme) {
// ignore. Will happen for EJB 3.0 session beans
}
}
if ( ejbDescriptor.isTimedObject() ) {
assertFullProfile("uses the EJB Timer Service");
// Can be a @Timeout or @Schedule or TimedObject
if (ejbTimeoutMethodDesc != null) {
}
// This should've been caught in EjbBundleValidator
"ejb.no_timeout_method",
"Class {0} does not define timeout method {1}",
}
}
}
}
}
if( isTimedObject_ ) {
if( !isStatefulSession ) {
// EJBTimerService should be accessed only if needed
// not to cause it to be loaded if it's not used.
if( timerService != null ) {
}
} else {
isTimedObject_ = false;
"ejb.stateful_cannot_be_timed_object",
"EJB {0} is invalid. Stateful session ejbs cannot be Timed Objects",
ejbDescriptor.getName()));
}
}
if( needSystemInterceptorProxy() ) {
}
// NOTE : InterceptorManager initialization delayed until transition to START state.
throw ex;
}
}
return protocolMgr;
}
return containerType;
}
throws RemoteException, RemoveException {
"ejb.ejbhome_remove_on_nonentity",
"EJBHome.remove() called on non entity container"));
}
}
private void initializeProtocolManager() {
try {
} catch(Throwable t) {
throw new RuntimeException("IIOP Protocol Manager initialization failed. " +
"Possible cause is that ORB is not available in this " +
"embedded container, or server instance is running and required ports are in use" :
"container")
, t );
}
}
//Overridden in sub classes
}
if (! this.isBeanManagedTran) {
"Lookup of java:comp/UserTransaction not allowed for Container managed Transaction beans"));
}
}
this.callFlowInfo = new CallFlowInfoImpl(
this, ejbDescriptor, compType);
}
return _debugDescription;
}
public final void setStartedState() {
if( containerState == CONTAINER_STARTED ) {
return;
}
// NOTE : we used to initialize interceptor manager in the ctor but we need to delay
// the initialization to account for the possiblity of a 299-enabled app. In
// that case, the 299-defined ejb interceptors are not added until the
// deployment load() phase. That's ok, as long as everything is initialized
// before any bean instances are created or any ejb invocations take place.
// Therefore, moving the initialization to the point that we transition into the
// ejb container START state.
try {
}
}
} catch(Exception e) {
throw new RuntimeException(e);
}
}
if (info.isEjbTimeout) {
} else {
}
}
}
public final void setStoppedState() {
}
public final boolean isStopped() {
return containerState == CONTAINER_STOPPED;
}
public final void setUndeployedState() {
}
public final boolean isUndeployed() {
return (containerState == CONTAINER_UNDEPLOYED);
}
public final boolean isTimedObject() {
return isTimedObject_;
}
final boolean isBeanManagedTx() {
return isBeanManagedTran;
}
return loader;
}
return loader;
}
final long getContainerId() {
return ejbDescriptor.getUniqueId();
}
final long getApplicationId() {
}
return ejbDescriptor;
}
/**
* Method defined on JavaEEContainer
*/
return getEjbDescriptor();
}
return metadata;
}
// Only session beans with bean-managed transactions
// or message-driven beans with bean-managed transactions
// can programmatically demarcate transactions.
try {
return utx;
}
}
else {
"ejb.ut_only_for_bmt",
"Only session beans with bean-managed transactions can obtain UserTransaction"));
}
}
public boolean isHAEnabled() {
return false;
}
/**
* 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;
}
return ejbHomeStub;
}
return ejbHome;
}
/**
* 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;
}
/**
* Return an object that implements ejb's local business home interface.
*/
return isLocalBeanClass(clientViewClassName)
}
return hasOptionalLocalBusinessView &&
}
return ejbClass;
}
return securityManager;
}
throws Exception
{
}
return envProps;
}
/**
* Create an EJBObject reference from the instanceKey
* Called from EJBObjectOutputStream.SerializableRemoteRef
* during deserialization of a remote-ref
* @param instanceKey instanceKey of the ejbobject
* @param generatedRemoteBusinessIntf 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 ClassLoader previousClassLoader =
try {
} else {
return null;
}
});
}
if( generatedRemoteBusinessIntf == null ) {
(instanceKey);
} else {
(instanceKey);
}
return remoteRef;
} finally {
} else {
return null;
}
});
}
}
}
if( ejbContainerUtilImpl.isEJBLite() ) {
"ejb.assert_full_profile",
"Invalid application. EJB {0} {1}. This feature is not part of the EJB 3.1 Lite API",
}
}
/**
* Called from the ContainerFactory during initialization.
*/
void initializeHome()
throws Exception
{
if( isWebServiceEndpoint ) {
// An ejb can only be exposed through 1 web service endpoint
if (!serviceEndpointIntfClass.isInterface()) {
if (serviceEndpointIntfClass==null) {
"ejb.error_generating_sei",
"Error in generating service endpoint interface class for EJB class {0}", this.ejbClass));
}
}
invocationHandler.setContainer(this);
// starting in 2.0, there is no more generated Ties
}
// Create a facade for container services to be used by web services runtime.
new EjbEndpointFacadeImpl(this, ejbContainerUtilImpl);
WSEjbEndpointRegistry.class);
if (wsejbEndpointRegistry != null ) {
} else {
"ejb.no_webservices_module",
"EJB-based Webservice endpoint is detected but there is no webservices module installed to handle it"));
}
}
// Root of portable global JNDI name for this bean
if (isRemote) {
boolean disableNonPortableJndiName = false;
} else {
}
if (!disableNonPortableJndiName) {
// This is either the default glassfish-specific (non-portable)
// global JNDI name or the one specified via mappedName(), sun-ejb-jar.xml,
// etc.
// If the explicitly specified name is the same as the portable name,
// don't register any of the glassfish-specific names to prevent
// clashes.
if ((glassfishSpecificJndiName != null)
}
}
if( hasRemoteHomeView ) {
this.ejbHomeImpl = instantiateEJBHomeImpl();
// 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.
//
// 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.
//
// Unlike the Home, each of the concrete containers are
// responsible for creating the EJBObjects, so just create
// a dummy EJBObjectImpl for validation purposes.
// 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.
// get a remote ref for the EJBHome
// Add 2.x Home for later portable JNDI name processing.
// If there's a glassfish-specific JNDI name, any 2.x Home object is always
// regsitered under that name. This preserves backward compatibility since
// this was the original use of the jndi name.
if( glassfishSpecificJndiName != null ) {
}
}
if( hasRemoteBusinessView ) {
this.ejbRemoteBusinessHomeImpl =
this.ejbRemoteBusinessHome =
// RMI-IIOP validation
for(RemoteBusinessIntfInfo next :
// 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.
// 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 ) {
}
}
// Internal jndi name under which remote business home is registered for
// glassfish-specific remote business JNDI names
if( glassfishSpecificJndiName != null ) {
}
// Convenience location for common case of 3.0 session bean with only
// 1 remote business interface and no adapted remote home. Allows a
// stand-alone client to access 3.0 business interface by using simple
// jndi name. Each remote business interface is also always available
// at <jndi-name>#<business_interface_name>. This is needed for the
// interfaces.
}
// We need a separate name for the internal generated home object to
// support the portable global JNDI names for business interfaces.
// There won't necessarily be a glassfish-specific name specified so
// it's cleaner to just always use a separate ones.
if( glassfishSpecificJndiName != null ) {
"com.sun.ejb.containers.RemoteBusinessObjectFactory", null);
// Glassfish-specific JNDI name for fully-qualified 3.0 Remote business interface.
}
if( simpleRemoteBusinessJndiName != null ) {
"com.sun.ejb.containers.RemoteBusinessObjectFactory", null);
// Glassfish-specific JNDI name for simple 3.0 Remote business interface lookup.
// Applicable when the bean exposes only a single Remote 3.x client view.
}
"com.sun.ejb.containers.RemoteBusinessObjectFactory", null);
// Always register portable JNDI name for each remote business view
}
if( remoteBusinessHomeJndiName != null ) {
// Glassfish-specific JNDI name for internal generated
// home object used by container
jndiInfo.setInternal(true);
}
// Always registeer internal name for home in support of portable global
// remote business JNDI names.
jndiInfo.setInternal(true);
// If there isn't any jndi name from the descriptor, set one so the
// lookup logic that depends on ejbDescriptor.getJndiName() will work.
if( glassfishSpecificJndiName == null ) {
}
}
}
if (isLocal) {
if( hasLocalHomeView ) {
this.ejbLocalHomeImpl = instantiateEJBLocalHomeImpl();
// 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.
new Class[] { IndirectlySerializable.class,
localIntf });
// Portable JNDI name for EJB 2.x LocalHome. We don't provide a
// glassfish-specific way of accessing Local EJBs.
}
if( hasLocalBusinessView ) {
Class[] proxyInterfaces =
int index = 1;
index++;
}
// Portable JNDI name for EJB 3.x Local business interface.
// We don't provide a glassfish-specific way of accessing Local EJBs.
}
}
Class[] proxyInterfaces =
new Class[ 2 ];
// Portable JNDI name for no-interface view.
// We don't provide a glassfish-specific way of accessing the
// no-interface view of a session bean.
}
}
}
}
try {
} else {
} else {
}
}
} catch(Exception e) {
"ejb.error_binding_jndi_name",
"Error while binding JNDI name {0} for EJB {1}",
}
}
if( !publishedPortableGlobalJndiNames.isEmpty() ) {
}
if( !publishedNonPortableGlobalJndiNames.isEmpty() ) {
}
if( !publishedInternalGlobalJndiNames.isEmpty() ) {
}
// create EJBMetaData
if ( isEntity ) {
}
}
}
}
return javaGlobalPrefix.toString();
}
boolean hasCtorWithArgs = false;
hasCtorWithArgs = true;
break;
}
}
// If constructor injection is being used, let CDI create the instance.
// Either way, instance will be part of JCDI injection context.
} else {
}
}
return contextImpl;
}
// Overridden for any container that supports injection
throw new IllegalStateException();
}
return ejbClass.newInstance();
}
// 299 impl will instantiate and inject the instance, but PostConstruct
// is still our responsibility
ejbBundle, false).getInstance();
}
} else {
ejbDescriptor, false);
}
}
}
}
}
/**
* Called from the ProtocolManager when a remote invocation arrives.
* @exception NoSuchObjectLocalException if the target object does not exist
*/
return remoteHomeView ?
} else {
if( remoteHomeView ) {
// In rare cases for sfsbs and entity beans, this can be null.
if( ejbObjectImpl != null ) {
}
} else {
// In rare cases for sfsbs and entity beans, this can be null.
if( ejbObjectImpl != null ) {
}
}
return targetObject;
}
}
/**
* Called from the ProtocolManager after a remote invocation completes.
*/
}
public void externalPreInvoke() {
} else {
return null;
}
});
}
bc.classLoaderSwitched = true;
}
if ( beanContextStack == null ) {
beanContextStack = new ArrayListStack();
}
}
public void externalPostInvoke() {
try {
if ( bc.classLoaderSwitched == true ) {
} else {
return null;
}});
}
}
}
}
// preInvocation authorization does not apply if this is a timer callback
// OR if it's a remove operation initiated via the 299 SPI
return !skipPreInvokeAuth;
}
/**
* Set the EJB instance in the EjbInvocation.
*
* It must be ensured that the following general pattern
* is followed by various parts of the EJBContainer code:
*
* try {
* container.preInvoke(inv);
* returnValue = container.intercept(inv);
* } catch (Exception1 e1) {
* ...
* } catch (Exception2 e2) {
* ...
* } finally {
* container.postInvoke();
* }
*
*/
}
try {
if (containerState != CONTAINER_STARTED) {
"ejb.container_not_started",
"Attempt to invoke when container is in {0}",
}
"ejb.null_invocation_method",
"Attempt to invoke container with null invocation method"));
}
"ejb.null_invocation_info",
}
}
if (inv.mustInvokeAsynchronously()) {
return;
}
if ( doPreInvokeAuthorization(inv) ) {
"ejb.client_not_authorized",
"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.
// _logger.log(Level.INFO, "Use fastPath() ==> " + info.method);
if (!inv.useFastPath) {
// Sets thread-specific state for Transaction, Naming, Security,
// etc
// Do Tx machinery
// null out invocation preInovkeTxStatus since the cache value
// is obsolete
}
if (ejbMethodStatsManager.isMethodMonitorOn()) {
}
}
if ( ex instanceof EJBException ) {
} else {
}
throw new PreInvokeException(ejbEx);
}
}
entityManagerMap.entrySet()) {
// If there's not already an EntityManager registered for
// this extended EntityManagerFactory within the current tx
if (extendedEmAssociatedWithTx == null) {
// Tell persistence provider to associate the extended
// entity manager with the transaction.
// @@@ Comment this out when joinTransaction supported on
// EntityManager API.
}
}
}
}
/**
* Containers that allow extended EntityManager will override this method.
*/
"ejb.extended_persistence_context_not_supported",
"EntityManager with PersistenceContextType.EXTENDED is not supported for this bean type"));
}
// postInvokeTx is handled by WebServiceInvocationHandler.
// Invoke postInvoke with instructions to skip tx processing portion.
postInvoke(inv, false);
}
/**
*/
postInvoke(inv, true);
}
if (containerState != CONTAINER_STARTED) {
"ejb.container_not_started",
"Attempt to invoke when container is in {0}",
}
if (inv.mustInvokeAsynchronously()) {
return;
}
if (ejbMethodStatsManager.isMethodMonitorOn()) {
}
// counterpart of invocationManager.preInvoke
if (! inv.useFastPath) {
.getTransaction();
}
}
}
} else {
}
try {
if( doTxProcessing ) {
}
if (ex instanceof EJBException)
else
}
}
// Unwrap the PreInvokeException if necessary
}
// Log system exceptions by default and application exceptions only
// when log level is FINE or higher.
} else {
}
if( protocolMgr != null ) {
// For remote business case, exception mapping is performed
// in client wrapper.
// TODO need extra logic to handle implementation-specific ejb exceptions
// (ParallelAccessEXCeption etc. that used to be handled by iiop glue code
}
// The most useful portion of the system exception is logged
// above. Only log mapped form when log level is FINE or
// higher.
} else {
if( inv.isBusinessInterface ) {
}
}
}
/*TODO
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);
}
*/
}
}
/**
* 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.
*/
"ejb.client_not_authorized",
"Client not authorized for this invocation"));
}
}
/**
* 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.
*/
throws RemoteException
{
// TODO see note above about additional special exception handling needed
if ( t instanceof RuntimeException )
throw (RuntimeException)t;
else if ( t instanceof RemoteException )
throw (RemoteException)t;
else
"ejb.client_not_authorized",
"Client not authorized for this invocation")); // throw the AccessException
}
}
/**
* Call back from the timer migration process to add
* automatic timers to the map of scheduleIds
*/
}
}
}
}
/**
* Check timeout method and set it accessable
*/
isTimedObject_ = true;
// Since timeout method can have any kind of access
// setAccessible to true.
if( !ejbTimeoutAccessible.isAccessible() ) {
}
} else {
if( !ejbTimeoutAccessible.isAccessible() ) {
}
return null;
}
});
}
} else {
"ejb.invalid_timeout_method",
"Invalid @Timeout or @Schedule signature for: {0} @Timeout or @Schedule method must return void and be a no-arg method or take a single javax.ejb.Timer param",
method));
}
}
/**
* 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 ?
}
// If it's an asnyc invocation and we're mapping an exception it
// means this is the thread of execution. The exception won't directly
// flow over the wire as a remote exception from the orb's perspective.
// If it's asychronous we know it's a remote business interface, not the
// 2.x client view.
if( mappedException == originalException) {
if( originalException instanceof EJBException ) {
}
}
} else {
}
} else {
// Synchronous invocation. First let the protocol manager perform
// its mapping.
// If no mapping happened
if( mappedException == originalException) {
if( inv.isBusinessInterface ) {
// Wrap it up in a special exception so the
// client can unwrap it and ensure that the client receives EJBException.
if(originalException instanceof EJBException) {
}
} else {
if( originalException instanceof EJBException ) {
}
}
}
}
" for " + inv);
}
return mappedException;
}
if( t instanceof TransactionRolledbackLocalException ) {
} else if( t instanceof TransactionRequiredLocalException ) {
} else if( t instanceof NoSuchObjectLocalException ) {
mappedException = new NoSuchEJBException();
} else if( t instanceof AccessLocalException ) {
mappedException = new EJBAccessException();
}
}
/**
* 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.
}
// Internal methods for 3.0 bean creation so there won't
// be corresponding permissions in the security policy file.
||
return true;
}
if( !authorized ) {
// 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.
}
}
return authorized;
}
/**
* Create an array of all methods in the standard EJB interfaces:
* javax.ejb.EJB(Local){Home|Object} .
*/
private void initializeEjbInterfaceMethods()
throws Exception
{
if ( isRemote ) {
if ( isStatelessSession ) {
if( hasRemoteHomeView ) {
}
}
}
if ( isLocal ) {
if ( isStatelessSession ) {
if( hasLocalHomeView ) {
ejbIntfMethods[ EJBLocalHome_create ] = m;
}
}
}
}
private void destroyTimers() {
if( isTimedObject() ) {
// EJBTimerService should be accessed only if needed
// not to cause it to be loaded if it's not used.
if( ejbTimerService != null ) {
}
}
}
private void stopTimers() {
if( isTimedObject() ) {
if( ejbTimerService != null ) {
}
}
}
// internal API, implemented in subclasses
throws CreateException, RemoteException;
// Only applies to concrete session containers
{
throw new EJBException(
"Internal ERROR: BaseContainer.createRemoteBusinessObject called");
}
// internal API, implemented in subclasses
throws CreateException
{
throw new EJBException(
"Internal ERROR: BaseContainer.createEJBLocalObject called");
}
// Only implemented in Stateless , Stateful, and Singleton session containers
throws CreateException
{
throw new EJBException(
"Internal ERROR: BaseContainer.createEJBLocalBusinessObject called");
}
throws CreateException
{
}
/**
* Called when a remote invocation arrives for an EJB.
* Implemented in subclasses.
*/
"ejb.basecontainer_internal_error",
"Internal ERROR: BaseContainer.{0} called",
"getRemoteBusinessObjectImpl"));
}
"ejb.basecontainer_internal_error",
"Internal ERROR: BaseContainer.{0} called",
"getEJBLocalObjectImpl"));
}
"ejb.basecontainer_internal_error",
"Internal ERROR: BaseContainer.{0} called",
"getEJBLocalBusinessObjectImpl"));
}
"ejb.basecontainer_internal_error",
"Internal ERROR: BaseContainer.{0} called",
"getOptionalEJBLocalBusinessObjectImpl"));
}
/**
* Check if the given EJBObject/LocalObject has been removed.
* @exception NoSuchObjectLocalException if the object has been removed.
*/
"ejb.basecontainer_internal_error",
"Internal ERROR: BaseContainer.{0} called",
"checkExists"));
}
throws EJBException {
}
// internal API, implemented in subclasses
throws EJBException;
// internal API, implemented in subclasses
throws EJBException;
// internal API, implemented in subclasses
throws EJBException;
boolean local)
// default implementation
"ejb.entity_container_only", "{0} only works for EntityContainer",
"removeBeanUnchecked"));
}
// default implementation
"ejb.entity_container_only", "{0} only works for EntityContainer",
"removeBeanUnchecked"));
}
public void preSelect() {
"ejb.entity_container_only", "{0} only works for EntityContainer",
"preSelect"));
}
// default implementation
{
"ejb.entity_container_only", "{0} only works for EntityContainer",
"getEJBLocalObjectForPrimaryKey(pkey, ctx)"));
}
// default implementation
"ejb.entity_container_only", "{0} only works for EntityContainer",
"getEJBLocalObjectForPrimaryKey"));
}
// default implementation
"ejb.entity_container_only", "{0} only works for EntityContainer",
"getEJBObjectForPrimaryKey"));
}
// internal API, implemented in subclasses
throws RemoteException
{
"ejb.basecontainer_internal_error",
"Internal ERROR: BaseContainer.{0} called",
"isIdentical"));
}
/**
* Called-back from security implementation through EjbInvocation
* when a jacc policy provider wants an enterprise bean instance.
*/
// Access to an enterprise bean instance is undefined for
// anything but business method invocations through
// Remote , Local, and ServiceEndpoint interfaces.
||
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.
try {
// 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) {
logParams[0]);
}
} else {
}
}
return bean;
}
{
boolean valid = false;
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.
valid = true;
} else {
" are from different containers" ;
}
} else {
"' is not a valid local interface instance for bean " +
:
}
if( !valid ) {
throw new EJBException(errorMsg);
}
}
/**
* Asserts validity of RemoteHome objects. This was defined for the
* J2EE 1.4 implementation and is exposed through Container SPI.
*/
{
boolean valid = false;
// Given object must be an instance of the remote stub class for
// this ejb.
if (hasRemoteHomeView) {
try {
causeException = ex;
"' is not a valid remote interface instance for bean "
+ ejbDescriptor.getName();
}
} else {
"' is not a valid remote interface instance for bean "
+ ejbDescriptor.getName();
}
} else {
"' is not a valid remote interface instance for bean " +
:
}
if( !valid ) {
if (causeException != null) {
} else {
throw new EJBException(errorMsg);
}
}
}
/**
*
*/
throws EJBException
{
} else {
throw new EJBException("Transaction Attribute not found for method"
+ method);
}
}
// Get the transaction attribute for a method.
// class, not the EJB class. (except for MDB's message listener
// callback method or TimedObject ejbTimeout method)
throws EJBException
{
return inv.transactionAttribute;
}
return inv.transactionAttribute;
}
// Check if a method is a business method.
// not the EJB class.
// 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 == remoteBusinessHomeIntf) ||
||
(methodClass == EJBObject.class ) ) {
return false;
}
}
if ( isLocal ) {
if ( (hasLocalHomeView &&
( (methodClass == localHomeIntf) ||
||
( (methodClass == localBusinessHomeIntf) ||
||
(methodClass == EJBLocalObject.class)) {
return false;
}
}
// NOTE : Web Service client view contains ONLY
// business methods
return true;
}
// Check if a method is a finder / home method.
// not the EJB class.
if ( isMessageDriven || isSession ) {
return false;
}
if ( isRemote ) {
if ( (hasRemoteHomeView &&
&& (methodClass != EJBHome.class)
return true;
}
}
if ( isLocal ) {
// only apply to entity beans.
if ( (hasLocalHomeView &&
&& (methodClass != EJBLocalHome.class)
return true;
}
}
return false;
}
// Check if a method is a create / finder / home method.
// not the EJB class.
if ( isMessageDriven ) {
return false;
}
if ( hasRemoteHomeView
&& (methodClass != EJBHome.class) ) {
return true;
}
&& (methodClass != EJBHome.class) ) {
return true;
}
if ( hasLocalHomeView
&& (methodClass != EJBLocalHome.class) ) {
return true;
}
if ( hasLocalBusinessView
&& (methodClass != EJBLocalHome.class) ) {
return true;
}
return false;
}
throws EJBException {
}
throws EJBException {
}
boolean optionalLocalBusView)
throws EJBException
{
if (! isHomeIntf) {
if (!isEjbTimeout) {
try {
} catch (NoSuchMethodException nsmEx) {
//TODO
}
} else {
// For a timeout it is the method
beanMethod = method;
}
if( beanMethod != null ) {
// Can't set AroundInvoke/AroundTimeout chains here, but set up some
// state on info object so it can be done right after InterceptorManager
// is initialized.
}
// Asynchronous method initialization
if( isAsync ) {
// Check return type
if( optionalLocalBusView ) {
if ( !beanMethodReturnTypeVoid && !beanMethodReturnTypeFuture ){
throw new RuntimeException("Invalid no-interface view asynchronous method '"
". Async method exposed through no-interface view must " +
" have return type void or java.lang.concurrent.Future<V>");
}
} else {
// Use actual interface method instead of method from generated interface
try {
} catch (NoSuchMethodException nsmEx) {
throw new RuntimeException("No matching async intf method for method '" +
}
if( beanMethod == null ) {
throw new RuntimeException("No matching bean class method for async method '" +
}
boolean valid = false;
if( bothVoid ) {
valid = true;
} else if( bothFuture ) {
valid = true;
}
if( !valid ) {
throw new RuntimeException("Invalid asynchronous bean class / interface " +
+ intfMethod + "'");
}
}
info.setIsAsynchronous(true);
}
}
}
} else {
}
return info;
}
boolean eligibleForAsync = false;
}
return eligibleForAsync;
}
/**
* Create invocation info for one method.
*
* @param originalIntf Leaf interface for the given view. Not set for
* methodIntf == bean.
*/
boolean flushEnabled,
throws EJBException {
setHomeTargetMethodInfo(invInfo, true);
}
setHomeTargetMethodInfo(invInfo, false);
}
}
}
}
}
return invInfo;
}
if( isSingleton ) {
lockInfo = new MethodLockInfo();
break;
}
}
lockInfo = new MethodLockInfo();
break;
}
}
}
}
// Set AccessTimeout info
if( isSingleton || isStatefulSession ) {
lockInfo = new MethodLockInfo();
}
break;
}
}
}
}
}
private boolean implMethodMatchesInvInfoMethod
boolean match = false;
// Declaring class must match in addition to signature
} else {
}
return match;
}
return invInfo;
}
boolean isLocal)
throws EJBException {
try {
// but don't treat it as a fatal error. At runtime,
// the EJBHome/EJBLocalHome method will be called.
"ejb.illegal_ejb_interface_override", params);
invInfo.ejbIntfOverride = true;
return;
} catch(NoSuchMethodException nsme) {
}
try {
if( invInfo.startsWithCreate ) {
if( isEntity ) {
}
} else if ( invInfo.startsWithFind ) {
} else {
// HOME method
}
} catch(NoSuchMethodException nsme) {
if( (methodClass == localBusinessHomeIntf) ||
(methodClass == remoteBusinessHomeIntf) ||
(methodClass == GenericEJBHome.class)) ) {
// Not an error. This is the case where the EJB 3.0
// client view is being used and there is no corresponding
} else if (isStatelessSession || isSingleton) {
// Ignore. Not an error.
// EJB 3.0 Stateless session ejbCreate/PostConstruct
// is decoupled from RemoteHome/LocalHome create().
} else {
if( isSession ) {
&&
initMethod = m;
break;
}
}
}
if( initMethod != null ) {
} else {
"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.
}
}
}
}
boolean isLocal,
throws EJBException {
// EJBObject/EJBLocalObject operations.
try {
// 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.
"ejb.illegal_ejb_interface_override", params);
invInfo.ejbIntfOverride = true;
return;
} catch(NoSuchMethodException nsme) {
}
}
try {
if( isSession && isStatefulSession ) {
// Assign removal info to inv info. If this method is not
// an @Remove method, result will be null.
}
} catch(NoSuchMethodException nsme) {
"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.
}
}
//Overridden in StatefulContainerOnly
return new String[] {
"ejbCreate", "ejbRemove", "ejbPassivate", "ejbActivate"
};
};
}
if (needSystemInterceptorProxy()) {
}
}
private boolean needSystemInterceptorProxy() {
// TODO only really needed if JAX-RS needs to dynamically register an
// interceptor during web application init. Can optimize this out
// by checking for the existence of any JAX-RS resources in module.
// Only applies to stateless and singleton session beans.
return isSession && !isStatefulSession;
}
private void addSystemInterceptorProxy() {
}
/*
* Used by message bean container to register message-listener methods
*/
}
private void initializeInvocationInfo()
throws Exception
{
if( isMessageDriven ) {
// message listener method initialization performed by
// message bean container
} else {
if ( isRemote ) {
if( hasRemoteHomeView ) {
// Process Remote intf
}
// Process EJBHome intf
homeIntf);
}
}
if( hasRemoteBusinessView ) {
for(RemoteBusinessIntfInfo next :
// Get methods from generated remote intf but pass
// actual business interface as original interface.
}
}
// Process internal EJB RemoteBusinessHome intf
}
}
}
if ( isLocal ) {
if( hasLocalHomeView ) {
// Process Local interface
}
// Process LocalHome interface
}
}
if( hasLocalBusinessView ) {
// Process Local Business interfaces
}
}
// Process (internal) Local Business Home interface
}
}
if (hasOptionalLocalBusinessView) {
// Process generated Optional Local Business interface
false, true);
}
// Process generated Optional Local Business interface
}
}
if( !hasLocalHomeView ) {
// Add dummy local business interface remove method so that internal
// container remove operations will work. (needed for internal 299 contract)
}
}
if ( isWebServiceEndpoint ) {
// Process Service Endpoint interface
}
}
}
if( isTimedObject() ) {
if (ejbTimeoutMethod != null) {
}
}
}
// 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.
// Store InvocationInfo by standard ejb interface method type
// to avoid an invocation info map lookup during authorizeLocalMethod
// and authorizeRemoteMethod.
Method m = ejbIntfMethods[i];
}
}
// Search for the transaction attribute for a method.
// This is only used during container initialization. After that,
// tx attributes can be looked up with variations of getTxAttr()
int txAttr = -1;
if ( isBeanManagedTran )
return TX_BEAN_MANAGED;
}
if ( txAttr == -1 ) {
throw new EJBException("Transaction Attribute not found for method "
+ md.prettyPrint());
}
// 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 ( !e.getIASEjbExtraDescriptors().isIsReadOnlyBean() &&
e.isEJB20() ) {
&& txAttr != TX_MANDATORY )
throw new EJBException(
"Transaction attribute for EJB2.0 CMP EntityBeans" +
" must be Required/RequiresNew/Mandatory");
}
}
}
return txAttr;
}
/**
* Verify transaction attribute on the timeout or schedule method and process
* this method if it's correct.
*/
if( isBeanManagedTran ||
txAttr == TX_REQUIRED ||
txAttr == TX_REQUIRES_NEW ||
txAttr == TX_NOT_SUPPORTED ) {
} else {
throw new EJBException("Timeout method " + m +
"must have TX attribute of " +
"TX_REQUIRES_NEW or TX_REQUIRED or " +
"TX_NOT_SUPPORTED for ejb " +
ejbDescriptor.getName());
}
}
// Check if the user has enabled flush at end of method flag
// This is only used during container initialization and set into
// the invocation info object. This method is over-riden in the
// EntityContainer.
//Get the flushMethodDescriptor and then find if flush has been
//enabled for this method
boolean flushEnabled =
return flushEnabled;
}
// Maintain insertion order
}
homeImpl.setContainer(this);
return homeImpl;
}
throws Exception {
new Class[] { remoteBusinessHomeIntf },
handler);
return remoteBusinessHomeImpl;
}
return invFactory.create();
}
}
throws Exception {
// LocalHome impl
// Maintain insertion order
}
// Client's EJBLocalHome object
homeImpl.setContainer(this);
return homeImpl;
}
throws Exception {
homeImpl.setContainer(this);
return homeImpl;
}
throws Exception {
homeImpl.setContainer(this);
return homeImpl;
}
throws Exception {
localObjImpl.setContainer(this);
return localObjImpl;
}
throws Exception {
new EJBLocalObjectInvocationHandler(proxyInvocationInfoMap, false);
localBusinessObjImpl.setContainer(this);
proxy);
}
return localBusinessObjImpl;
}
throws Exception {
localBusinessObjImpl.setContainer(this);
return localBusinessObjImpl;
}
ejbObjImpl.setContainer(this);
return ejbObjImpl;
}
throws Exception {
// 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.
for(RemoteBusinessIntfInfo next :
handler);
}
ejbBusinessObjImpl.setContainer(this);
return ejbBusinessObjImpl;
}
// default implementation
throws CreateException
{
throw new EJBException("Internal error");
}
// default implementation
Object[] findParams)
throws FinderException
{
throw new EJBException("Internal error");
}
private void setupEnvironment()
{
// for this EJB.
// create envProps object to be returned from EJBContext.getEnvironment
}
/**
*/
return componentId;
}
/**
* Called after all the components in the container's application
* have deployed successfully.
*/
this);
// By now all existing timers should have been restored.
if( isTimedObject_ ) {
// EJBTimerService should be accessed only if needed
// not to cause it to be loaded if it's not used.
if (timerService != null) {
deploy0 = false;
"keepstate is true and will not create new auto timers during deployment.");
}
} else {
throw new RuntimeException("EJB Timer Service is not available");
}
}
}
/**
*
*/
boolean redeliver = false;
if (containerState != CONTAINER_STARTED) {
throw new EJBException("Attempt to invoke when container is in "
}
inv.isTimerCallback = true;
// Let preInvoke do tx attribute lookup.
// 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.
try {
// Delegate to subclass for i.ejbObject / i.isLocal setup.
// AroundTimeout interceptors will be checked for timeout methods
redeliver = true;
}
} 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;
} catch(Throwable c) {
redeliver = true;
} finally {
// Only call postEjbTimeout if there are no errors so far.
if( !redeliver ) {
boolean success =
}
// If transaction commit fails, set redeliver flag.
redeliver = true;
}
if( originalClassLoader != null ) {
}
}
return redeliver;
}
return (m != null) ? m : ejbTimeoutMethod;
}
// Create a TimerWrapper for AroundTimeout and as a method argument.
} else {
}
}
final void onEnteringContainer() {
//callFlowAgent.startTime(ContainerTypeOrApplicationType.EJB_CONTAINER);
}
final void onLeavingContainer() {
//callFlowAgent.endTime();
}
}
}
}
}
method);
//callFlowAgent.ejbMethodStart(callFlowInfo);
}
th,
method);
//callFlowAgent.ejbMethodEnd(callFlowInfo);
}
throws Throwable {
try {
if (inv.useFastPath) {
} else {
params);
}
} catch (InvocationTargetException ite) {
throw ite;
} catch(Throwable c) {
throw c;
} finally {
}
}
/**
* This is implemented by concrete containers that support TimedObjects.
*/
throws Exception {
throw new EJBException("This container doesn't support TimedObjects");
}
/**
* Undeploy event.
* calls for the same container instance.
*
*/
public final void undeploy() {
try {
if ( !isUndeployed() ) {
try {
stopTimers();
//destroyTimers();
} catch(Exception e) {
ejbDescriptor.getName(), e);
}
// Shutdown with undeploy
doConcreteContainerShutdown(true);
// BaseContainer cleanup
}
} catch(Throwable t) {
// Make sure we don't propagate an exception since that could
// prevent the cleanup of some other component.
}
}
/**
* Container shutdown event. This happens for every kind of
* shutdown other than undeploy. It could mean the server
* is shutting down or that the app has been disabled while
* the server is still running. The two cases are handled
* the same. We must be able to gracefully handle redundant
* shutdown calls for the same container instance.
*/
public final void onShutdown() {
try {
if ( !isStopped() ) {
try {
stopTimers();
} catch(Exception e) {
ejbDescriptor.getName(), e);
}
// Cleanup without undeploy
doConcreteContainerShutdown(false);
// BaseContainer cleanup
}
} catch(Throwable t) {
// Make sure we don't propagate an exception since that could
// prevent the cleanup of some other component.
}
}
// Concrete container shutdown actions
/**
* Perform common container shutdown 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. This might be called after
* an unsuccessful deployment, in which case some of the services might
* not have been initialized.
*/
private void doContainerCleanup() {
if( baseContainerCleanupDone ) {
return;
}
try {
if (wsejbEndpointRegistry != null) {
}
}
// NOTE : Pipe cleanup that used to done here is now encapsulated within
// endpoint registry unregisterEndpoint operation
} catch(Exception e) {
ejbDescriptor.getName(), e);
}
if( hasAsynchronousInvocations ) {
}
final ClassLoader previousClassLoader =
// Unpublish all portable and non-portable JNDI names
try {
} catch(Exception e) {
}
}
try {
} else {
return null;
}
});
}
if ( isRemote ) {
try {
if( hasRemoteHomeView ) {
ejbHome);
// Hints to release stub-related meta-data in ORB
// destroy the factory itself
}
if( hasRemoteBusinessView ) {
// Home related cleanup
// Cleanup for each remote business interface
// destroy the factory itself
}
}
}
}
try {
}
} finally {
} else {
return null;
}
});
}
}
baseContainerCleanupDone = true;
}
private void unregisterProbeListeners() {
try {
if (timerProbeListener != null) {
}
if (poolProbeListener != null) {
}
if (cacheProbeListener != null) {
if (cacheProbeNotifier != null) {
}
}
}
}
}
/**
* Called when server instance is Ready
*/
public void onReady() {}
/**
* Called when server instance is terminating. This method is the last
* one called during server shutdown.
*/
public void onTermination() {}
/***************************************************************************
* The following methods implement transaction management machinery
* in a reusable way for both SessionBeans and EntityBeans
**************************************************************************/
/**
* 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(EjbInvocation) has run.
* Therefore, handle inv.invocationInfo defensively since it might not have
* been initialized.
*/
throws Exception
{
throw new EJBException("EjbInvocation Info lookup failed for " +
} else {
}
}
// Get existing Tx status: this tells us if the client
// started a transaction which was propagated on this invocation.
// so no special work needed.
if ( (isStatefulSession || isStatelessSession) &&
// 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().
// client request is associated with a Tx
try {
} 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;
}
// 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.
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
// client request associated with a Tx, always suspend
}
// 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.
// This allows the TM to enlist resources
// used by the EJB with the transaction
}
break;
case TX_NOT_SUPPORTED:
if ( isEntity )
break;
case TX_MANDATORY:
throw new TransactionRequiredLocalException();
break;
case TX_REQUIRED:
if ( isNullTx )
throw new TransactionRequiredLocalException();
}
else { // There is a client Tx
}
break;
case TX_REQUIRES_NEW:
break;
case TX_SUPPORTS:
if ( isNullTx )
throw new TransactionRequiredLocalException();
else { // we need to invoke the EJB with no Tx.
if ( isEntity )
}
break;
case TX_NEVER:
throw new EJBException(
"EJB cannot be invoked in global transaction");
else { // we need to invoke the EJB with no Tx.
if ( isEntity )
}
break;
default:
throw new EJBException("Bad transaction attribute");
}
}
// Called before invoking a bean with no Tx or with a new Tx.
// Check if the bean is associated with an unfinished tx.
try {
// 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) {
throw new EJBException(ex);
}
}
throws Exception
{
if (cmtTimeoutInSeconds > 0) {
} else {
}
if (! isSingleton) {
}
// This allows the TM to enlist resources used by the EJB
// with the transaction
// Register for Synchronization notification
}
// 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.
}
// Called from preInvokeTx before invoking the bean with the client's Tx
// Also called from EntityContainer.removeBean for cascaded deletes
int status=-1;
int prevStatus=-1;
try {
// Note: inv.clientTx will not be set at this point.
try {
} catch ( Exception e ) {
//FIXME: Use LogStrings.properties
}
}
// If the client's tx is going to rollback, it is fruitless
// to invoke the EJB, so throw an exception back to client.
throw new TransactionRolledbackLocalException(
"Client's transaction aborted");
if( isStatefulSession ) {
// Make sure there is no Transactional persistence context
// for the same EntityManagerFactory as this SFSB's
// Extended persistence context for the propagated transaction.
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.
throw new EJBException("Detected two different extended persistence contexts for the same EntityManagerFactory within a transaction");
}
}
}
// First time the bean is running in this new client Tx
//Must change this for singleton
if (! isSingleton) {
}
try {
// Create a Synchronization object.
// Not needed for stateless beans or message-driven beans
// or singletons because they cant have Synchronization callbacks,
// and they cant be associated with a tx across
// invocations.
context);
}
}
try {
} catch ( Exception e ) {
//FIXME: Use LogStrings.properties
}
}
}
else { // Bean already has a transaction associated with it.
// 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 {
try {
} catch ( Exception e ) {
//FIXME: Use LogStrings.properties
}
}
}
}
}
/**
* postInvokeTx is called after every invocation on the EJB instance,
* NOTE: postInvokeTx is called even if the EJB was not invoked
* because of an exception thrown from preInvokeTx.
*/
throws Exception
{
// so resume client's Tx if needed.
// so no special processing needed.
// check if there was a suspended client Tx
&& exception instanceof PreInvokeException ) {
}
return;
}
// 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
status);
// there was a client Tx which was suspended
}
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 ( isEntity )
// there was a client Tx which was suspended
}
break;
case TX_MANDATORY:
// EJB2.0 section 18.3.1, Table 15
// EJB executed in client's Tx
break;
case TX_REQUIRED:
// EJB2.0 section 18.3.1, Table 15
// EJB executed in new Tx started in preInvokeTx
}
else {
// EJB executed in client's tx
}
}
break;
case TX_REQUIRES_NEW:
// EJB2.0 section 18.3.1, Table 15
// EJB executed in new Tx started in preInvokeTx
// there was a client Tx which was suspended
}
break;
case TX_SUPPORTS:
// EJB2.0 section 18.3.1, Table 15
// EJB executed in client's tx
}
}
else {
// EJB executed in no Tx
if ( isEntity )
}
break;
default:
}
// exception, should the transaction be rolled back if not already so ?
}
throws Exception
{
// EJB2.0 section 18.3.1, Table 16
&& exception instanceof PreInvokeException ) {
// A PreInvokeException was thrown, so bean was not invoked
}
// EJB was invoked, EJB's Tx is complete.
}
else {
// EJB was invoked, EJB's Tx is incomplete.
// See EJB2.0 Section 17.6.1
if ( isStatefulSession ) {
if ( !isSystemUncheckedException(exception) ) {
if( isAppExceptionRequiringRollback(exception) ) {
} else {
}
}
else {
try {
} finally {
}
}
}
else if( isStatelessSession ) { // stateless SessionBean
try {
} finally {
}
newException = new EJBException(
"Stateless SessionBean method returned without" +
" completing transaction");
"ejb.incomplete_sessionbean_txn_exception",logParams);
}
else if( isSingleton ) {
try {
} finally {
}
newException = new EJBException(
"Singleton SessionBean method returned without" +
" completing transaction");
"ejb.incomplete_sessionbean_txn_exception",logParams);
}
else { // MessageDrivenBean
try {
} finally {
}
newException = new EJBException(
"MessageDrivenBean method returned without" +
" completing transaction");
"ejb.incomplete_msgdrivenbean_txn_exception",logParams);
}
}
return newException;
}
throws Exception
{
if ( exception instanceof PreInvokeException )
// A PreInvokeException was thrown, so bean was not invoked
// If PreInvokeException was not thrown, EJB was invoked with no Tx
if ( isSystemUncheckedException(exception) ) {
// Table 15, EJB2.0
}
return newException;
}
// this is the counterpart of useClientTx
// Called from postInvokeTx after invoking the bean with the client's Tx
// Also called from EntityContainer.removeBean for cascaded deletes
throws Exception
{
if ( exception instanceof PreInvokeException )
// A PreInvokeException was thrown, so bean was not invoked
// If PreInvokeException wasn't thrown, EJB was invoked with client's Tx
if ( isSystemUncheckedException(exception) ) {
// Table 15, EJB2.0
try {
} finally {
}
} else {
}
} else if( isAppExceptionRequiringRollback(exception ) ) {
}
return newException;
}
// this is the counterpart of startNewTx
throws Exception
{
if ( exception instanceof PreInvokeException )
// no tx was started, probably an exception was thrown
// before tm.begin() was called
return newException;
}
}
if ( newException != null
// EJB2.0 section 18.3.1, Table 15
// Rollback the Tx we started
try {
} finally {
}
}
else {
try {
// EJB2.0 section 18.3.1, Table 15, and 18.3.6:
// rollback tx, no exception
if (transactionManager.isTimedOut()) {
new Object[] {
ejbDescriptor.getName()});
}
}
else {
if( (newException != null) &&
} 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
}
}
} catch (RollbackException ex) {
// EJB2.0 section 18.3.6
// Commit or rollback failed.
// EJB2.0 section 18.3.6
" container-managed transaction.", ex);
}
}
return newException;
}
// Implementation of Container method.
// Called from UserTransactionImpl after the EJB started a Tx,
// for TX_BEAN_MANAGED EJBs only.
try {
// Associate the context with tx so that on subsequent
// invocations with the same tx, we can do the appropriate
// tx.resume etc.
if (! isSingleton) {
}
// Register Synchronization with TM so that we can
// dissociate the context from tx in afterCompletion
// 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);
}
}
// internal APIs, called from ContainerSync, implemented in subclasses
throw new EJBException(
"Internal Error: BaseContainer.preInvokeNoTx called");
}
throw new EJBException(
"Internal Error: BaseContainer.postInvokeNoTx called");
}
if ( sysEx instanceof EJBException)
return sysEx;
// EJB2.0 section 18.3.4
("NoSuchEntityException thrown by EJB method.");
} else {
newException = new EJBException();
}
return newException;
}
return !isSystemUncheckedException(exception);
}
( exception instanceof RuntimeException
|| exception instanceof RemoteException ) ) {
// Exact exception is specified as an ApplicationException
return false;
} else {
// Superclass exception is not inherited
}
}
}
return true;
} else {
return false;
}
}
/**
* Returns true if this exception is an Application Exception and
* it requires rollback of the transaction in which it was thrown.
*/
protected boolean isAppExceptionRequiringRollback
boolean appExceptionRequiringRollback = false;
// Exact exception is specified as an ApplicationException
// or superclass exception is inherited
}
break;
}
}
}
return appExceptionRequiringRollback;
}
}
public boolean getDebugMonitorFlag() {
return debugMonitorFlag;
}
}
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 boolean isRemoteInterfaceSupported() {
return hasRemoteHomeView;
}
protected final boolean isLocalInterfaceSupported() {
return hasLocalHomeView;
}
/**
* 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.
*
*/
throws Throwable
{
if (inv.mustInvokeAsynchronously()) {
} else {
}
return result;
}
throws Throwable
{
if (interceptorManager.hasInterceptors()) {
try {
} catch(Throwable t) {
throw new InvocationTargetException(t);
} finally {
}
} else { // invoke() has the same exc. semantics as Method.invoke
}
return result;
}
/**
* 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.
*/
throws Throwable
{
try {
inv.getParameters());
} catch(InvocationTargetException ite) {
}
}
{
/*TODO
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;
}
protected void createMonitoringRegistryMediator() {
try {
} else {
modName =
}
this.registryMediator =
ejbProbeListener.addMethods(getContainerId(), appName, modName, ejbName, getMonitoringMethodsArray());
_logger.log(Level.SEVERE, "[**BaseContainer**] Could not create MonitorRegistryMediator. appName: " + appName + "; modName: " + modName + "; ejbName: " + ejbName, ex);
}
// Always create to avoid NPE
try {
}
}
}
}
protected void populateMethodMonitorMap() {
}
}
if (hasGeneratedClasses) {
methodList.add(m);
}
}
} else {
for (int i = 0; i < sz; i++) {
}
}
return methods;
}
populateMethodMonitorMap(methods, false);
}
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);
*/
}
void logMonitoredComponentsData() {
}
}
protected void registerMonitorableComponents() {
}
protected void registerTimerMonitorableComponent() {
if( isTimedObject() ) {
//toMonitorProps = new TimedObjectMonitorableProperties();
//registryMediator.registerProvider( toMonitorProps );
String invokerId = EjbMonitoringUtils.getInvokerId(containerInfo.appName, containerInfo.modName, containerInfo.ejbName);
try {
}
}
}
}
}
protected void incrementCreatedTimedObject() {
//toMonitorProps.incrementTimersCreated();
}
protected void incrementRemovedTimedObject() {
//toMonitorProps.incrementTimersRemoved();
}
protected void incrementDeliveredTimedObject() {
//toMonitorProps.incrementTimersDelivered();
}
private static class JndiInfo {
}
return jndiInfo;
}
return jndiInfo;
}
return jndiInfo;
}
// If it's a portable name, use rebind since the name is guaranteed
// to be unique. Otherwise, use bind() so we detect any clashes.
// NOTE : Will need to revisit this if we allow a developer-specified
// portable JNDI name.
if( cosNaming ) {
} else {
}
publishedSuccessfully = true;
}
if( publishedSuccessfully ) {
if( cosNaming ) {
} else {
}
} else {
"never published successfully in the first place");
}
}
}
}
boolean local;
boolean cosNaming;
boolean portable;
boolean internal;
boolean publishedSuccessfully;
}
} //BaseContainer{}
final class CallFlowInfoImpl
implements CallFlowInfo
{
this.ejbDescriptor = descriptor;
this.componentType = compType;
}
return appName;
}
return modName;
}
return ejbName;
}
return componentType;
}
}
try {
tx =
//TODO: Log exception
}
}
}
}
}
final class RemoteBusinessIntfInfo {
}
/**
* PreInvokeException is used to wrap exceptions thrown
* from BaseContainer.preInvoke, so it indicates that the bean's
* method will not be called.
*/
}
} //PreInvokeException{}
"Environment properties cannot be modified";
throw new RuntimeException(errstr);
}
throw new RuntimeException(errstr);
}
throw new RuntimeException(errstr);
}
throw new RuntimeException(errstr);
}
public void clear() {
throw new RuntimeException(errstr);
}
defaults = new Properties();
while ( i.hasNext() ) {
}
}
}
{
}
{
}
} //SafeProperties{}
/** TODO: remove
final class TimedObjectMonitorableProperties
implements com.sun.ejb.spi.stats.EJBTimedObjectStatsProvider
{
long timersCreated = 0;
long timersRemoved = 0;
long timersDelivered = 0;
boolean toMonitor = false;
public TimedObjectMonitorableProperties() {
timersCreated = 0;
timersRemoved = 0;
timersDelivered = 0;
toMonitor = false;
}
public void incrementTimersCreated() {
if( toMonitor ) {
synchronized( this ) {
timersCreated++;
}
}
}
public long getTimersCreated() {
return timersCreated;
}
public void incrementTimersRemoved() {
if( toMonitor ) {
synchronized( this ) {
timersRemoved++;
}
}
}
public long getTimersRemoved() {
return timersRemoved;
}
public void incrementTimersDelivered() {
if( toMonitor ) {
synchronized( this ) {
timersDelivered++;
}
}
}
public long getTimersDelivered() {
return timersDelivered;
}
public void appendStats(StringBuffer sbuf) {
sbuf.append("[Timers: ")
.append("Created=").append(timersCreated).append("; ")
.append("Removed=").append(timersRemoved).append("; ")
.append("Delivered=").append(timersDelivered).append("; ");
sbuf.append("]");
}
public void monitoringLevelChanged( boolean monitoringOn ) {
timersCreated = 0;
timersRemoved = 0;
timersDelivered = 0;
toMonitor = monitoringOn;
}
} //TimedObjectMonitorableProperties{}
**/
final class ContainerInfo {
}
}