KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > ejb > containers > BaseContainer


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23 package com.sun.ejb.containers;
24
25 import java.lang.reflect.*;
26
27 import java.io.*;
28 import java.rmi.RemoteException JavaDoc;
29 import java.rmi.AccessException JavaDoc;
30 import java.security.AccessController JavaDoc;
31 import java.security.PrivilegedExceptionAction JavaDoc;
32 import java.security.PrivilegedActionException JavaDoc;
33 import java.util.*;
34 import java.util.logging.*;
35
36 import javax.ejb.*;
37 import javax.annotation.PostConstruct;
38 import javax.annotation.PreDestroy;
39 import javax.transaction.*;
40 import javax.naming.InitialContext JavaDoc;
41 import javax.naming.NamingException JavaDoc;
42 import javax.naming.Reference JavaDoc;
43 import javax.naming.StringRefAddr JavaDoc;
44 import javax.management.ObjectName JavaDoc;
45 import javax.rmi.PortableRemoteObject JavaDoc;
46 import javax.rmi.CORBA.Util JavaDoc;
47
48 import javax.persistence.EntityManagerFactory;
49 import javax.persistence.EntityManager;
50
51 import com.sun.ejb.*;
52 import com.sun.ejb.containers.interceptors.InterceptorManager;
53 import com.sun.ejb.containers.util.MethodMap;
54 import com.sun.ejb.portable.*;
55 import com.sun.ejb.spi.io.IndirectlySerializable;
56 import com.sun.enterprise.*;
57 import com.sun.enterprise.util.*;
58 import com.sun.enterprise.deployment.*;
59 import com.sun.enterprise.distributedtx.UserTransactionImpl;
60 import com.sun.enterprise.distributedtx.J2EETransaction;
61 import com.sun.enterprise.log.Log;
62 import com.sun.enterprise.appverification.factory.AppVerification;
63 import com.sun.enterprise.deployment.EjbDescriptor;
64 import com.sun.enterprise.deployment.EjbBundleDescriptor;
65 import com.sun.enterprise.deployment.EjbApplicationExceptionInfo;
66 import com.sun.enterprise.security.SecurityContext;
67 import com.sun.enterprise.security.SecurityUtil;
68 import com.sun.logging.*;
69
70 import com.sun.enterprise.admin.monitor.*;
71 import com.sun.enterprise.admin.monitor.callflow.Agent;
72 import com.sun.enterprise.admin.monitor.callflow.CallFlowInfo;
73 import com.sun.enterprise.admin.monitor.callflow.ContainerTypeOrApplicationType;
74 import com.sun.enterprise.admin.monitor.callflow.ComponentType;
75 import com.sun.enterprise.util.io.FileUtils;
76
77 import com.sun.enterprise.deployment.runtime.IASEjbExtraDescriptors;
78
79 import com.sun.ejb.base.stats.MonitoringRegistryMediator;
80 import com.sun.ejb.base.stats.MethodMonitor;
81 import com.sun.ejb.spi.stats.EJBStatsProvider;
82 import com.sun.ejb.spi.stats.EJBMethodStatsManager;
83 import java.lang.annotation.Annotation JavaDoc;
84
85 /**
86  * This class implements part of the com.sun.ejb.Container interface.
87  * It implements the container's side of the EJB-to-Container
88  * contract defined by the EJB 2.0 spec.
89  * It contains code shared by SessionBeans, EntityBeans and MessageDrivenBeans.
90  * Its subclasses provide the remaining implementation of the
91  * container functionality.
92  *
93  */

94
95 public abstract class BaseContainer
96     implements Container, EJBStatsProvider
97 {
98     protected static Logger _logger;
99     static {
100         _logger=LogDomains.getLogger(LogDomains.EJB_LOGGER);
101     }
102     
103     protected static Class JavaDoc[] NO_PARAMS = new Class JavaDoc[] {};
104     
105     protected Object JavaDoc[] logParams = null;
106     
107     // constants for EJB(Local)Home/EJB(Local)Object methods,
108
// used in authorizeRemoteMethod and authorizeLocalMethod
109
private static final int EJB_INTF_METHODS_LENGTH = 16;
110     static final int EJBHome_remove_Handle = 0;
111     static final int EJBHome_remove_Pkey = 1;
112     static final int EJBHome_getEJBMetaData = 2;
113     static final int EJBHome_getHomeHandle = 3;
114     static final int EJBLocalHome_remove_Pkey = 4;
115     static final int EJBObject_getEJBHome = 5;
116     static final int EJBObject_getPrimaryKey = 6;
117     static final int EJBObject_remove = 7;
118     static final int EJBObject_getHandle = 8;
119     static final int EJBObject_isIdentical = 9;
120     static final int EJBLocalObject_getEJBLocalHome = 10;
121     static final int EJBLocalObject_getPrimaryKey = 11;
122     static final int EJBLocalObject_remove = 12;
123     static final int EJBLocalObject_isIdentical = 13;
124     static final int EJBHome_create = 14;
125     static final int EJBLocalHome_create = 15;
126
127     // true if home method, false if component intf method.
128
// Used for setting info on invocation object during authorization.
129
private static final boolean[] EJB_INTF_METHODS_INFO =
130     { true, true, true, true, true,
131       false, false, false, false, false,
132       false, false, false, false,
133       true, true };
134     
135     private static final String JavaDoc USER_TX = "java:comp/UserTransaction";
136
137     private static final byte HOME_KEY = (byte)0xff;
138     private static final byte[] homeInstanceKey = {HOME_KEY};
139
140     protected ClassLoader JavaDoc loader = null;
141     protected Class JavaDoc ejbClass = null;
142     protected Method ejbPassivateMethod = null;
143     protected Method ejbActivateMethod = null;
144     protected Method ejbRemoveMethod = null;
145     protected Method ejbTimeoutMethod = null;
146
147     protected Class JavaDoc webServiceEndpointIntf = null;
148    
149     // true if exposed as a web service endpoint.
150
protected boolean isWebServiceEndpoint = false;
151     
152     private boolean isTimedObject_ = false;
153
154     /*****************************************
155      * Data members for Local views *
156      *****************************************/

157
158     // True if bean has a LocalHome/Local view
159
// OR a Local business view OR both.
160
protected boolean isLocal=false;
161
162     // True if bean exposes a local home view
163
protected boolean hasLocalHomeView=false;
164
165     // True if bean exposes a local business view
166
protected boolean hasLocalBusinessView=false;
167
168     //
169
// Data members for LocalHome/Local view
170
//
171

172     // LocalHome interface written by developer
173
protected Class JavaDoc localHomeIntf = null;
174
175     // Local interface written by developer
176
private Class JavaDoc localIntf = null;
177
178     // Client reference to ejb local home
179
protected EJBLocalHome ejbLocalHome;
180
181     // Implementation of ejb local home. May or may not be the same
182
// object as ejbLocalHome, for example in the case of dynamic proxies.
183
protected EJBLocalHomeImpl ejbLocalHomeImpl;
184
185     // Constructor used to instantiate ejb local object proxy.
186
private Constructor ejbLocalObjectProxyCtor;
187
188     //
189
// Data members for 3.x Local business view
190
//
191

192     // Internal interface describing operation used to create an
193
// instance of a local business object. (GenericEJBLocalHome)
194
protected Class JavaDoc localBusinessHomeIntf = null;
195
196     // Local business interface written by developer
197
protected Set<Class JavaDoc> localBusinessIntfs = new HashSet();
198
199     // Client reference to internal local business home interface.
200
// This is only seen by internal ejb code that instantiates local
201
// business objects during lookups.
202
protected GenericEJBLocalHome ejbLocalBusinessHome;
203
204     // Implementation of internal local business home interface.
205
protected EJBLocalHomeImpl ejbLocalBusinessHomeImpl;
206
207     // Constructor used to instantiate local business object proxy.
208
private Constructor ejbLocalBusinessObjectProxyCtor;
209
210     /*****************************************
211      * Data members for Remote views *
212      *****************************************/

213
214     // True if bean has a RemoteHome/Remote view
215
// OR a Remote business view OR both.
216
protected boolean isRemote=false;
217     
218     // True if bean exposes a RemoteHome view
219
protected boolean hasRemoteHomeView=false;
220
221     // True if bean exposes a Remote Business view.
222
protected boolean hasRemoteBusinessView=false;
223
224     //
225
// Data members for RemoteHome/Remote view
226
//
227

228     // Home interface written by developer.
229
protected Class JavaDoc homeIntf = null;
230     
231     // Remote interface written by developer.
232
protected Class JavaDoc remoteIntf = null;
233
234     // Container implementation of EJB Home. May or may not be the same
235
// object as ejbHome, for example in the case of dynamic proxies.
236
protected EJBHomeImpl ejbHomeImpl;
237
238     // EJB Home reference used by ORB Tie within server to deliver
239
// invocation.
240
protected EJBHome ejbHome;
241
242     // Client reference to EJB Home.
243
protected EJBHome ejbHomeStub;
244
245     // Remote interface proxy class
246
private Class JavaDoc ejbObjectProxyClass;
247
248     // Remote interface proxy constructor.
249
private Constructor ejbObjectProxyCtor;
250
251     // RemoteReference Factory for RemoteHome view
252
protected RemoteReferenceFactory remoteHomeRefFactory = null;
253
254     // Jndi-name under which the Remote Home is registered.
255
private String JavaDoc remoteHomeJndiName;
256
257     //
258
// Data members for 3.x Remote business view
259
//
260

261     // Internal interface describing operation used to create an
262
// instance of a remote business object.
263
protected Class JavaDoc remoteBusinessHomeIntf = null;
264
265     // Container implementation of internal EJB Business Home. May or may
266
// not be same object as ejbRemoteBusinessHome, for example in the
267
// case of dynamic proxies.
268
protected EJBHomeImpl ejbRemoteBusinessHomeImpl;
269
270     // EJB Remote Business Home reference used by ORB Tie within server
271
// to deliver invocation.
272
protected EJBHome ejbRemoteBusinessHome;
273
274     // Client reference to internal Remote EJB Business Home. This is
275
// only seen by internal EJB code that instantiates remote business
276
// objects during lookups.
277
protected EJBHome ejbRemoteBusinessHomeStub;
278
279     // Internal jndi name under which remote business home is registered
280
private String JavaDoc remoteBusinessHomeJndiName;
281
282     // Convenience location for common case of 3.0 session bean with only
283
// 1 remote business interface and no adapted remote home. Allows a
284
// stand-alone client to access 3.0 business interface by using simple
285
// jndi name. Each remote business interface is also always available
286
// at <jndi-name>#<business_interface_name>. This is needed for the
287
// case where the bean has an adapted remote home and/or multiple business
288
// interfaces.
289
private String JavaDoc remoteBusinessJndiName;
290
291     // Holds information such as remote reference factory that are associated
292
// with a particular remote business interface
293
protected Map<String JavaDoc, RemoteBusinessIntfInfo> remoteBusinessIntfInfo
294         = new HashMap<String JavaDoc, RemoteBusinessIntfInfo>();
295
296     //
297
// END -- Data members for Remote views
298
//
299

300     protected EJBMetaData metadata = null;
301
302     
303     // singleton objects in J2EE Server
304
protected ProtocolManager protocolMgr = null;
305     protected J2EETransactionManager transactionManager;
306     protected NamingManager namingManager;
307
308     protected com.sun.enterprise.SecurityManager securityManager;
309     protected ContainerFactoryImpl containerFactory;
310     InvocationManager invocationManager;
311     protected InjectionManager injectionManager;
312     Switch theSwitch;
313     
314     protected boolean isSession;
315     protected boolean isStatelessSession;
316     protected boolean isStatefulSession;
317     protected boolean isMessageDriven;
318     protected boolean isEntity;
319     
320     protected EjbDescriptor ejbDescriptor;
321     protected String JavaDoc componentId; // unique id for java:comp namespace lookup
322

323     
324     protected Map invocationInfoMap = new HashMap();
325     // Need a separate map for web service methods since it's possible for
326
// an EJB Remote interface to be a subtype of the Service Endpoint
327
// Interface. In that case, it's ambiguous to do a lookup based only
328
// on a java.lang.reflect.Method
329
protected Map webServiceInvocationInfoMap = new HashMap();
330
331     // optimized method map for proxies to resolve invocation info
332
private MethodMap proxyInvocationInfoMap;
333
334     protected Method[] ejbIntfMethods;
335
336     protected Properties envProps;
337     boolean isBeanManagedTran=false;
338     
339     
340     protected boolean debugMonitorFlag = false;
341     
342     private static LocalStringManagerImpl localStrings =
343     new LocalStringManagerImpl(BaseContainer.class);
344     
345     private ThreadLocal JavaDoc threadLocalContext = new ThreadLocal JavaDoc();
346
347     protected static final int CONTAINER_INITIALIZING = -1;
348     protected static final int CONTAINER_STARTED = 0;
349     protected static final int CONTAINER_STOPPED = 1;
350     protected static final int CONTAINER_UNDEPLOYED = 3;
351     protected static final int CONTAINER_ON_HOLD = 4;
352     
353     protected int containerState = CONTAINER_INITIALIZING;
354     
355     protected int cmtTimeoutInSeconds = 0;
356
357     protected int statCreateCount = 0;
358     protected int statRemoveCount = 0;
359     protected HashMap methodMonitorMap;
360     protected boolean monitorOn = false;
361     protected MonitoringRegistryMediator registryMediator;
362     protected EJBMethodStatsManager ejbMethodStatsManager;
363         
364     private String JavaDoc _debugDescription;
365
366     protected TimedObjectMonitorableProperties toMonitorProps = null;
367     
368     protected Agent callFlowAgent;
369     
370     protected CallFlowInfo callFlowInfo;
371
372     protected InterceptorManager interceptorManager;
373
374     protected static final Class JavaDoc[] lifecycleCallbackAnnotationClasses = {
375         PostConstruct.class, PrePassivate.class,
376         PostActivate.class, PreDestroy.class
377     };
378     
379     /**
380      * This constructor is called from ContainerFactoryImpl when an
381      * EJB Jar is deployed.
382      */

383     protected BaseContainer(EjbDescriptor ejbDesc, ClassLoader JavaDoc loader)
384         throws Exception JavaDoc
385     {
386         try {
387             this.loader = loader;
388             this.ejbDescriptor = ejbDesc;
389         createMonitoringRegistryMediator();
390
391             logParams = new Object JavaDoc[1];
392             logParams[0] = ejbDesc.getName();
393             
394             theSwitch = Switch.getSwitch();
395             protocolMgr = theSwitch.getProtocolManager();
396             invocationManager = theSwitch.getInvocationManager();
397             injectionManager = theSwitch.getInjectionManager();
398             namingManager = theSwitch.getNamingManager();
399             transactionManager = theSwitch.getTransactionManager();
400             containerFactory =
401                     (ContainerFactoryImpl)theSwitch.getContainerFactory();
402             
403             // Add this container/descriptor to the table in Switch
404
theSwitch.setDescriptorFor(this, ejbDescriptor);
405
406             // get Class objects for creating new EJBs
407
ejbClass = loader.loadClass(ejbDescriptor.getEjbImplClassName());
408             
409             IASEjbExtraDescriptors iased = ejbDesc.getIASEjbExtraDescriptors();
410             cmtTimeoutInSeconds = iased.getCmtTimeoutInSeconds();
411
412             if( ejbDescriptor.getType().equals(EjbMessageBeanDescriptor.TYPE) )
413             {
414                 isMessageDriven = true;
415                 EjbMessageBeanDescriptor mdb =
416                 (EjbMessageBeanDescriptor) ejbDescriptor;
417
418                 if ( mdb.getTransactionType().equals("Bean") ) {
419                     isBeanManagedTran = true;
420                 }
421                 else {
422                     isBeanManagedTran = false;
423                 }
424             }
425             else {
426                 
427                 if(ejbDescriptor.getType().equals(EjbEntityDescriptor.TYPE)) {
428                     isEntity = true;
429                 } else {
430                     isSession = true;
431                     EjbSessionDescriptor sd =
432                         (EjbSessionDescriptor)ejbDescriptor;
433                     
434                     isStatelessSession = sd.isStateless();
435                     isStatefulSession = !isStatelessSession;
436
437                     if( isStatefulSession ) {
438                         if( !Serializable.class.isAssignableFrom(ejbClass) ) {
439                             ejbClass = EJBUtils.loadGeneratedSerializableClass
440                                 (loader, ejbClass.getName());
441                         }
442                     }
443                     
444                     if ( sd.getTransactionType().equals("Bean") ) {
445                         isBeanManagedTran = true;
446                     } else {
447                         isBeanManagedTran = false;
448                     }
449
450                 }
451                 
452                 if ( ejbDescriptor.isRemoteInterfacesSupported() ) {
453
454                     isRemote = true;
455                     hasRemoteHomeView = true;
456
457                     String JavaDoc homeClassName = ejbDescriptor.getHomeClassName();
458
459                     homeIntf = loader.loadClass(homeClassName);
460                     remoteIntf = loader.loadClass
461                         (ejbDescriptor.getRemoteClassName());
462
463                     String JavaDoc id =
464                         Long.toString(ejbDescriptor.getUniqueId()) + "_RHome";
465
466                     remoteHomeRefFactory =
467                         protocolMgr.getRemoteReferenceFactory(this, true, id);
468
469                 }
470
471                 if( ejbDescriptor.isRemoteBusinessInterfacesSupported() ) {
472
473                     isRemote = true;
474                     hasRemoteBusinessView = true;
475
476                     remoteBusinessHomeIntf =
477                         EJBUtils.loadGeneratedGenericEJBHomeClass(loader);
478
479                     for(String JavaDoc next :
480                             ejbDescriptor.getRemoteBusinessClassNames()) {
481
482                         // The generated remote business interface and the
483
// client wrapper for the business interface are
484
// produced dynamically. The following call must be
485
// made before any EJB 3.0 Remote business interface
486
// runtime behavior is needed for a particular
487
// classloader.
488
EJBUtils.loadGeneratedRemoteBusinessClasses
489                             (loader, next);
490                         
491                         String JavaDoc nextGen =
492                             EJBUtils.getGeneratedRemoteIntfName(next);
493
494                         Class JavaDoc genRemoteIntf = loader.loadClass(nextGen);
495
496                         RemoteBusinessIntfInfo info =
497                             new RemoteBusinessIntfInfo();
498                         info.generatedRemoteIntf = genRemoteIntf;
499                         info.remoteBusinessIntf = loader.loadClass(next);
500
501                         // One remote reference factory for each remote
502
// business interface. Id must be unique across
503
// all ejb containers.
504
String JavaDoc id = Long.toString(ejbDescriptor.getUniqueId())
505                              + "_RBusiness" + "_" + genRemoteIntf.getName();
506
507                         info.referenceFactory = protocolMgr.
508                             getRemoteReferenceFactory(this, false, id);
509
510                         remoteBusinessIntfInfo.put(genRemoteIntf.getName(),
511                                                    info);
512                     }
513
514                 }
515
516                 if ( ejbDescriptor.isLocalInterfacesSupported() ) {
517                     // initialize class objects for LocalHome/LocalIntf etc.
518
isLocal = true;
519                     hasLocalHomeView = true;
520
521                     String JavaDoc localHomeClassName =
522                         ejbDescriptor.getLocalHomeClassName();
523
524                     localHomeIntf =
525                         loader.loadClass(localHomeClassName);
526                     localIntf = loader.loadClass
527                         (ejbDescriptor.getLocalClassName());
528                 }
529
530                 if( ejbDescriptor.isLocalBusinessInterfacesSupported() ) {
531                     isLocal = true;
532                     hasLocalBusinessView = true;
533
534                     localBusinessHomeIntf = GenericEJBLocalHome.class;
535
536                     for(String JavaDoc next :
537                             ejbDescriptor.getLocalBusinessClassNames() ) {
538                         localBusinessIntfs.add(loader.loadClass(next));
539                     }
540                 }
541
542                 if( isStatelessSession ) {
543                     EjbBundleDescriptor bundle =
544                         ejbDescriptor.getEjbBundleDescriptor();
545                     WebServicesDescriptor webServices = bundle.getWebServices();
546                     Collection endpoints =
547                         webServices.getEndpointsImplementedBy(ejbDescriptor);
548                     // JSR 109 doesn't require support for a single ejb
549
// implementing multiple port components.
550
if( endpoints.size() == 1 ) {
551                         WebServiceEndpoint endpoint = (WebServiceEndpoint)
552                             endpoints.iterator().next();
553                         webServiceEndpointIntf = loader.loadClass
554                            (ejbDescriptor.getWebServiceEndpointInterfaceName());
555                         isWebServiceEndpoint = true;
556                     }
557                 }
558
559                 try{
560                     // get Method objects for ejbPassivate/Activate/ejbRemove
561
ejbPassivateMethod =
562                         ejbClass.getMethod("ejbPassivate", NO_PARAMS);
563                     ejbActivateMethod =
564                         ejbClass.getMethod("ejbActivate", NO_PARAMS);
565                     ejbRemoveMethod =
566                         ejbClass.getMethod("ejbRemove", NO_PARAMS);
567                 } catch(NoSuchMethodException JavaDoc nsme) {
568                     // ignore. Will happen for EJB 3.0 session beans
569
}
570
571                 
572             }
573             
574             if ( ejbDescriptor.isTimedObject() ) {
575                 MethodDescriptor ejbTimeoutMethodDesc =
576                     ejbDescriptor.getEjbTimeoutMethod();
577                 Method method = ejbTimeoutMethodDesc.getMethod(ejbDescriptor);
578                 
579                 Class JavaDoc[] params = method.getParameterTypes();
580                 if( (params.length == 1) &&
581                     (params[0] == javax.ejb.Timer JavaDoc.class) &&
582                     (method.getReturnType() == Void.TYPE) ) {
583                     
584                     isTimedObject_ = true;
585                     ejbTimeoutMethod = method;
586
587                     final Method ejbTimeoutAccessible = ejbTimeoutMethod;
588                     // Since timeout method can have any kind of access
589
// setAccessible to true.
590
java.security.AccessController.doPrivileged(
591                         new java.security.PrivilegedExceptionAction JavaDoc() {
592                             public java.lang.Object JavaDoc run() throws Exception JavaDoc {
593                                 if( !ejbTimeoutAccessible.isAccessible() ) {
594                                     ejbTimeoutAccessible.setAccessible(true);
595                                 }
596                                 return null;
597                             }
598                         });
599
600                 } else {
601                     throw new EJBException
602                         ("Invalid @Timeout signature for " +
603                          method + " @Timeout method must return void" +
604                          " and take a single javax.ejb.Timer param");
605                 }
606             }
607             if( isTimedObject_ ) {
608                 if( !isStatefulSession ) {
609                     EJBTimerService timerService =
610                         containerFactory.getEJBTimerService();
611                     if( timerService != null ) {
612                         timerService.timedObjectCount();
613                     }
614                 } else {
615                     isTimedObject_ = false;
616                     throw new EJBException("Ejb " + ejbDescriptor.getName() +
617                         " is invalid. Stateful session ejbs can not" +
618                         " be Timed Objects");
619                 }
620             }
621
622             initializeEjbInterfaceMethods();
623
624             initializeInterceptorManager();
625
626             initializeInvocationInfo();
627
628
629             setupEnvironment();
630         } catch (Exception JavaDoc ex) {
631             _logger.log(Level.FINE,"ejb.basecontainer_exception",logParams);
632             _logger.log(Level.FINE,"", ex);
633             throw ex;
634         }
635
636     _debugDescription = "ejbName: " + ejbDescriptor.getName()
637         + "; containerId: " + ejbDescriptor.getUniqueId();
638     _logger.log(Level.FINE, "Instantiated container for: "
639         + _debugDescription);
640     }
641
642     protected final void createCallFlowAgent(ComponentType compType) {
643         this.callFlowAgent = theSwitch.getCallFlowAgent();
644         this.callFlowInfo = new CallFlowInfoImpl(
645                 this, ejbDescriptor, compType);
646     }
647
648     public String JavaDoc toString() {
649     return _debugDescription;
650     }
651
652     public final void setStartedState() {
653         containerState = CONTAINER_STARTED;
654     }
655     
656     public final void setStoppedState() {
657         containerState = CONTAINER_STOPPED;
658     }
659
660     public final void setUndeployedState() {
661         containerState = CONTAINER_UNDEPLOYED;
662     }
663
664     public final boolean isUndeployed() {
665     return (containerState == CONTAINER_UNDEPLOYED);
666     }
667
668     final boolean isTimedObject() {
669         return isTimedObject_;
670     }
671     
672     final boolean isBeanManagedTx() {
673         return isBeanManagedTran;
674     }
675     
676     public final ClassLoader JavaDoc getClassLoader() {
677         return loader;
678     }
679     
680     
681     final long getContainerId() {
682         return ejbDescriptor.getUniqueId();
683     }
684     
685     
686     public final EjbDescriptor getEjbDescriptor() {
687         return ejbDescriptor;
688     }
689     
690     public final EJBMetaData getEJBMetaData() {
691         return metadata;
692     }
693     
694     final UserTransaction getUserTransaction() {
695         // Only session beans with bean-managed transactions
696
// or message-driven beans with bean-managed transactions
697
// can programmatically demarcate transactions.
698
if ( (isSession || isMessageDriven) && isBeanManagedTran ) {
699             try {
700                 UserTransaction utx = (UserTransaction)
701                 namingManager.getInitialContext().lookup(USER_TX);
702                 return utx;
703             } catch ( Exception JavaDoc ex ) {
704                 _logger.log(Level.FINE, "ejb.user_transaction_exception", ex);
705                 throw new EJBException("Unable to lookup UserTransaction", ex);
706             }
707         }
708         else
709             throw new IllegalStateException JavaDoc(
710                 "ERROR: only SessionBeans with bean-managed transactions" +
711                 "can obtain UserTransaction");
712         
713     }
714     
715     
716     /**
717      * EJB spec makes a distinction between access to the UserTransaction
718      * object itself and access to its methods. getUserTransaction covers
719      * the first check and this method covers the second. It is called
720      * by the UserTransaction implementation to verify access.
721      */

722     public boolean userTransactionMethodsAllowed(ComponentInvocation inv) {
723         // Overridden by containers that allowed BMT;
724
return false;
725     }
726     
727     public final EJBHome getEJBHomeStub() {
728         return ejbHomeStub;
729     }
730     
731     public final EJBHome getEJBHome() {
732         return ejbHome;
733     }
734
735     /**
736      * Return an object that implements ejb's local home interface.
737      * If dynamic proxies are being used, this is the proxy itself,
738      * it can't be directly cast to an EJBLocalHomeImpl.
739      */

740     public final EJBLocalHome getEJBLocalHome() {
741         return ejbLocalHome;
742     }
743
744     /**
745      * Return an object that implements ejb's local business home interface.
746      */

747     public final GenericEJBLocalHome getEJBLocalBusinessHome() {
748         return ejbLocalBusinessHome;
749     }
750     
751     public final Class JavaDoc getEJBClass() {
752         return ejbClass;
753     }
754     
755     public final com.sun.enterprise.SecurityManager getSecurityManager() {
756         return securityManager;
757     }
758     
759     public final void setSecurityManager(com.sun.enterprise.SecurityManager sm)
760         throws Exception JavaDoc
761     {
762         securityManager = sm;
763     }
764     
765     final Properties getEnvironmentProperties() {
766         return envProps;
767     }
768     
769     /**
770      * Create an EJBObject reference from the instanceKey
771      * Called from EJBObjectOutputStream.SerializableRemoteRef
772      * during deserialization of a remote-ref
773      * @param the instanceKey of the ejbobject
774      * @param if non-null, this is a remote business view and the param
775      * is the name of the generated remote business interface.
776      * Otherwise, this is for the RemoteHome view
777      */

778     public java.rmi.Remote JavaDoc createRemoteReferenceWithId
779         (byte[] instanceKey, String JavaDoc generatedRemoteBusinessIntf) {
780                                                      
781         final Thread JavaDoc currentThread = Thread.currentThread();
782         final ClassLoader JavaDoc previousClassLoader =
783             currentThread.getContextClassLoader();
784         final ClassLoader JavaDoc myClassLoader = loader;
785     try {
786             java.security.AccessController.doPrivileged(
787             new java.security.PrivilegedAction JavaDoc() {
788                 public java.lang.Object JavaDoc run() {
789                     currentThread.setContextClassLoader(myClassLoader);
790                     return null;
791                 }
792             });
793             java.rmi.Remote JavaDoc remoteRef = null;
794             if( generatedRemoteBusinessIntf == null ) {
795                 remoteRef = remoteHomeRefFactory.createRemoteReference
796                     (instanceKey);
797             } else {
798                 RemoteReferenceFactory remoteBusinessRefFactory =
799                    remoteBusinessIntfInfo.get(generatedRemoteBusinessIntf).
800                     referenceFactory;
801
802                 remoteRef = remoteBusinessRefFactory.createRemoteReference
803                     (instanceKey);
804             }
805             return remoteRef;
806         } finally {
807             java.security.AccessController.doPrivileged(
808             new java.security.PrivilegedAction JavaDoc() {
809                 public java.lang.Object JavaDoc run() {
810                     currentThread.setContextClassLoader(previousClassLoader);
811                     return null;
812                 }
813             });
814         }
815     }
816     
817     /**
818      * Called from the ContainerFactory during initialization.
819      */

820     void initializeHome()
821         throws Exception JavaDoc
822     {
823         
824         if (isRemote) {
825             
826             if( hasRemoteHomeView ) {
827                 this.ejbHomeImpl = instantiateEJBHomeImpl();
828                 this.ejbHome = ejbHomeImpl.getEJBHome();
829
830                 // Since some containers might create multiple EJBObjects for
831
// the same ejb, make sure we use the same Proxy class to
832
// instantiate all the proxy instances.
833
ejbObjectProxyClass =
834                     Proxy.getProxyClass(loader, new Class JavaDoc[] { remoteIntf });
835                 ejbObjectProxyCtor = ejbObjectProxyClass.
836                     getConstructor(new Class JavaDoc[] { InvocationHandler.class });
837
838                 //
839
// Make sure all Home/Remote interfaces conform to RMI-IIOP
840
// rules. Checking for conformance here keeps the exposed
841
// deployment/startup error behavior consistent since when
842
// rmic is used during codegen it makes equivalent checks and
843
// treats any validation problems as fatal errors.
844
//
845
// These same checks will be made when setTarget is called
846
// in POARemoteReferenceFactory.preinvoke, but that happens
847
// only when the actual invocation is made, so it's better to
848
// know at container initialization time if there is a problem.
849
//
850
protocolMgr.validateTargetObjectInterfaces(this.ejbHome);
851
852                 // Unlike the Home, each of the concrete containers are
853
// responsible for creating the EJBObjects, so just create
854
// a dummy EJBObjectImpl for validation purposes.
855
EJBObjectImpl dummyEJBObjectImpl = instantiateEJBObjectImpl();
856                 EJBObject dummyEJBObject = (EJBObject)
857                     dummyEJBObjectImpl.getEJBObject();
858                 protocolMgr.validateTargetObjectInterfaces(dummyEJBObject);
859
860                 // Remotereference factory needs instances of
861
// Home and Remote to get repository Ids since it doesn't have
862
// stubs and ties. This must be done before any Home or Remote
863
// references are created.
864
remoteHomeRefFactory.setRepositoryIds(homeIntf, remoteIntf);
865                              
866                 // get a remote ref for the EJBHome
867
ejbHomeStub = remoteHomeRefFactory.
868                     createHomeReference(homeInstanceKey);
869
870                 remoteHomeJndiName = ejbDescriptor.getJndiName();
871
872                 namingManager.publishObject(remoteHomeJndiName,
873                                             ejbHomeStub, false);
874             }
875
876             
877             if( hasRemoteBusinessView ) {
878                 this.ejbRemoteBusinessHomeImpl =
879                     instantiateEJBRemoteBusinessHomeImpl();
880
881                 this.ejbRemoteBusinessHome =
882                     ejbRemoteBusinessHomeImpl.getEJBHome();
883
884                 remoteBusinessHomeJndiName = EJBUtils.getRemote30HomeJndiName
885                     (ejbDescriptor.getJndiName());
886
887                 if(!hasRemoteHomeView && (remoteBusinessIntfInfo.size() == 1)){
888                     remoteBusinessJndiName = ejbDescriptor.getJndiName();
889                     
890                 }
891
892                 // RMI-IIOP validation
893
protocolMgr.validateTargetObjectInterfaces
894                     (this.ejbRemoteBusinessHome);
895
896                 for(RemoteBusinessIntfInfo next :
897                         remoteBusinessIntfInfo.values()) {
898                         
899                     next.proxyClass = Proxy.getProxyClass
900                         (loader, new Class JavaDoc[] { next.generatedRemoteIntf });
901                         
902                     next.proxyCtor = next.proxyClass.
903                        getConstructor(new Class JavaDoc[] { InvocationHandler.class });
904
905                     // Remotereference factory needs instances of
906
// Home and Remote to get repository Ids since it
907
// doesn't have stubs and ties. This must be done before
908
// any Home or Remote references are created.
909
next.referenceFactory.setRepositoryIds
910                         (remoteBusinessHomeIntf, next.generatedRemoteIntf);
911
912                     // Create home stub from the remote reference factory
913
// associated with one of the remote business interfaces.
914
// It doesn't matter which remote reference factory is
915
// selected, so just do it the first time through the loop.
916
if( ejbRemoteBusinessHomeStub == null ) {
917                         ejbRemoteBusinessHomeStub = next.referenceFactory.
918                             createHomeReference(homeInstanceKey);
919                     }
920
921                 }
922
923                 EJBObjectImpl dummyEJBObjectImpl =
924                     instantiateRemoteBusinessObjectImpl();
925
926                 for(RemoteBusinessIntfInfo next :
927                         remoteBusinessIntfInfo.values()) {
928
929                     java.rmi.Remote JavaDoc dummyEJBObject = dummyEJBObjectImpl.
930                         getEJBObject(next.generatedRemoteIntf.getName());
931                         
932                     protocolMgr.validateTargetObjectInterfaces(dummyEJBObject);
933
934                     next.jndiName = EJBUtils.getRemoteEjbJndiName
935                         (true, next.remoteBusinessIntf.getName(),
936                          ejbDescriptor.getJndiName());
937
938                     // Register an object factory that will retrieve
939
// the generic remote business home and create the
940
// appropriate client business wrapper object for the
941
// given business interface.
942
Reference JavaDoc remoteBusRef = new Reference JavaDoc
943                         (next.remoteBusinessIntf.getName(),
944                          new StringRefAddr JavaDoc("url", remoteBusinessHomeJndiName),
945                          "com.sun.ejb.containers.RemoteBusinessObjectFactory",
946                          null);
947
948                     namingManager.publishObject(next.jndiName, remoteBusRef,
949                                                 false);
950
951                     if( remoteBusinessJndiName != null ) {
952                         namingManager.publishObject(remoteBusinessJndiName,
953                                                     remoteBusRef, false);
954             _logger.log(Level.INFO, "**RemoteBusinessJndiName: "
955                 + remoteBusinessJndiName + "; remoteBusIntf: "
956                 + next.remoteBusinessIntf.getName());
957                     }
958
959                 }
960
961                 namingManager.publishObject(remoteBusinessHomeJndiName,
962                                             ejbRemoteBusinessHomeStub, false);
963
964             }
965             
966         }
967         
968         if (isLocal) {
969
970             if( hasLocalHomeView ) {
971                 this.ejbLocalHomeImpl = instantiateEJBLocalHomeImpl();
972                 this.ejbLocalHome = ejbLocalHomeImpl.getEJBLocalHome();
973
974                 // Since some containers might create multiple EJBLocalObjects
975
// for the same ejb, make sure we use the same Proxy class to
976
// instantiate all the proxy instances.
977
Class JavaDoc ejbLocalObjectProxyClass =
978                     Proxy.getProxyClass(loader,
979                                     new Class JavaDoc[] { IndirectlySerializable.class,
980                                                   localIntf });
981                 ejbLocalObjectProxyCtor = ejbLocalObjectProxyClass.
982                     getConstructor(new Class JavaDoc[] { InvocationHandler.class });
983             }
984
985             if( hasLocalBusinessView ) {
986                 ejbLocalBusinessHomeImpl =
987                     instantiateEJBLocalBusinessHomeImpl();
988                 ejbLocalBusinessHome = (GenericEJBLocalHome)
989                     ejbLocalBusinessHomeImpl.getEJBLocalHome();
990                 
991                 Class JavaDoc[] proxyInterfaces =
992                     new Class JavaDoc[ localBusinessIntfs.size() + 1 ];
993                 proxyInterfaces[0] = IndirectlySerializable.class;
994                 int index = 1;
995                 for(Class JavaDoc next : localBusinessIntfs) {
996                     proxyInterfaces[index] = next;
997                     index++;
998                 }
999
1000                Class JavaDoc proxyClass = Proxy.getProxyClass(loader,proxyInterfaces);
1001                ejbLocalBusinessObjectProxyCtor = proxyClass.
1002                    getConstructor(new Class JavaDoc[] { InvocationHandler.class });
1003            }
1004        }
1005        
1006        // create EJBMetaData
1007
Class JavaDoc primaryKeyClass = null;
1008        if ( isEntity ) {
1009            EjbEntityDescriptor ed = (EjbEntityDescriptor)ejbDescriptor;
1010            primaryKeyClass = loader.loadClass(ed.getPrimaryKeyClassName());
1011        }
1012        metadata = new EJBMetaDataImpl(ejbHomeStub, homeIntf, remoteIntf,
1013            primaryKeyClass, isSession, isStatelessSession);
1014
1015    }
1016    
1017    /**
1018     * Return the EJBObject/EJBHome Proxy for the given ejbId and instanceKey.
1019     * Called from the ProtocolManager when a remote invocation arrives.
1020     * @exception NoSuchObjectLocalException if the target object does not exist
1021     */

1022    public java.rmi.Remote JavaDoc getTargetObject(byte[] instanceKey,
1023                                          String JavaDoc generatedRemoteBusinessIntf) {
1024               
1025        externalPreInvoke();
1026        boolean remoteHomeView = (generatedRemoteBusinessIntf == null);
1027        if ( instanceKey.length == 1 && instanceKey[0] == HOME_KEY ) {
1028            return remoteHomeView ?
1029                ejbHomeImpl.getEJBHome() :
1030                ejbRemoteBusinessHomeImpl.getEJBHome();
1031        } else {
1032
1033            EJBObjectImpl ejbObjectImpl = null;
1034            java.rmi.Remote JavaDoc targetObject = null;
1035
1036            if( remoteHomeView ) {
1037                ejbObjectImpl = getEJBObjectImpl(instanceKey);
1038                // In rare cases for sfsbs and entity beans, this can be null.
1039
if( ejbObjectImpl != null ) {
1040                    targetObject = ejbObjectImpl.getEJBObject();
1041                }
1042            } else {
1043                ejbObjectImpl = getEJBRemoteBusinessObjectImpl(instanceKey);
1044                // In rare cases for sfsbs and entity beans, this can be null.
1045
if( ejbObjectImpl != null ) {
1046                    targetObject = ejbObjectImpl.
1047                        getEJBObject(generatedRemoteBusinessIntf);
1048                }
1049            }
1050
1051            return targetObject;
1052        }
1053    }
1054
1055    /**
1056     * Release the EJBObject/EJBHome object.
1057     * Called from the ProtocolManager after a remote invocation completes.
1058     */

1059    public void releaseTargetObject(java.rmi.Remote JavaDoc remoteObj) {
1060        externalPostInvoke();
1061    }
1062
1063    public void externalPreInvoke() {
1064        BeanContext bc = new BeanContext();
1065        final Thread JavaDoc currentThread = Thread.currentThread();
1066        bc.previousClassLoader = currentThread.getContextClassLoader();
1067        if ( getClassLoader().equals(bc.previousClassLoader)
1068             == false ) {
1069            java.security.AccessController.doPrivileged(
1070                new java.security.PrivilegedAction JavaDoc() {
1071                public java.lang.Object JavaDoc run() {
1072                    currentThread.setContextClassLoader( getClassLoader());
1073                    return null;
1074                }
1075            });
1076            bc.classLoaderSwitched = true;
1077        }
1078
1079        ArrayListStack beanContextStack =
1080            (ArrayListStack) threadLocalContext.get();
1081                
1082        if ( beanContextStack == null ) {
1083            beanContextStack = new ArrayListStack();
1084            threadLocalContext.set(beanContextStack);
1085        }
1086        beanContextStack.push(bc);
1087    }
1088
1089    public void externalPostInvoke() {
1090        try {
1091            ArrayListStack beanContextStack =
1092                (ArrayListStack) threadLocalContext.get();
1093            
1094            final BeanContext bc = (BeanContext) beanContextStack.pop();
1095            if ( bc.classLoaderSwitched == true ) {
1096                java.security.AccessController.doPrivileged(
1097                   new java.security.PrivilegedAction JavaDoc() {
1098                    public java.lang.Object JavaDoc run() {
1099                        Thread.currentThread().setContextClassLoader(
1100                            bc.previousClassLoader);
1101                        return null;
1102                    }
1103                });
1104            }
1105        } catch ( Exception JavaDoc ex ) {
1106            _logger.log(Level.FINE, "externalPostInvoke ex", ex);
1107        }
1108    }
1109
1110
1111    /**
1112     * Called from EJBObject/EJBHome before invoking on EJB.
1113     * Set the EJB instance in the Invocation.
1114     */

1115    public void preInvoke(Invocation inv) {
1116        try {
1117            if (containerState != CONTAINER_STARTED) {
1118                throw new EJBException("Attempt to invoke when container is in "
1119                                       + containerStateToString(containerState));
1120            }
1121            
1122            if( inv.method == null ) {
1123                throw new EJBException("Attempt to invoke container with null " +
1124                                       " invocation method");
1125            }
1126
1127            if( inv.invocationInfo == null ) {
1128
1129                inv.invocationInfo = getInvocationInfo(inv);
1130
1131                if( inv.invocationInfo == null ) {
1132                    throw new EJBException("Invocation Info lookup failed for " +
1133                                           "method " + inv.method);
1134                }
1135            }
1136
1137            inv.transactionAttribute = inv.invocationInfo.txAttr;
1138            inv.container = this;
1139
1140            if (inv.method != ejbTimeoutMethod) {
1141               
1142                if ( !authorize(inv) ) {
1143                    throw new AccessLocalException(
1144                        "Client not authorized for this invocation.");
1145                }
1146            }
1147
1148            ComponentContext ctx = getContext(inv);
1149            inv.context = ctx;
1150            
1151            inv.instance = inv.ejb = ctx.getEJB();
1152
1153            
1154            // Sets thread-specific state for Transaction, Naming, Security, etc
1155
invocationManager.preInvoke(inv);
1156            
1157            // Do Tx machinery
1158
preInvokeTx(inv);
1159            
1160            enlistExtendedEntityManagers(ctx);
1161            if (ejbMethodStatsManager.isMethodMonitorOn()) {
1162                ejbMethodStatsManager.preInvoke(inv.method);
1163            }
1164            
1165            
1166        }
1167        catch ( Exception JavaDoc ex ) {
1168            _logger.log(Level.FINE, "ejb.preinvoke_exception", logParams);
1169            _logger.log(Level.FINE, "", ex);
1170            
1171            EJBException ejbEx;
1172            if ( ex instanceof EJBException ) {
1173                ejbEx = (EJBException)ex;
1174            } else {
1175                ejbEx = new EJBException(ex);
1176            }
1177            
1178            throw new PreInvokeException(ejbEx);
1179        }
1180    }
1181    
1182    protected void enlistExtendedEntityManagers(ComponentContext ctx) {
1183        if (isStatefulSession && (ctx.getTransaction() != null)) {
1184            J2EETransaction j2eeTx = (J2EETransaction) ctx.getTransaction();
1185            SessionContextImpl sessionCtx = (SessionContextImpl) ctx;
1186            Map<EntityManagerFactory, EntityManager> entityManagerMap =
1187                sessionCtx.getExtendedEntityManagerMap();
1188                    
1189            for (Map.Entry<EntityManagerFactory, EntityManager> entry :
1190                     entityManagerMap.entrySet()) {
1191                EntityManagerFactory emf = entry.getKey();
1192                EntityManager extendedEm = entry.getValue();
1193
1194                EntityManager extendedEmAssociatedWithTx =
1195                    j2eeTx.getExtendedEntityManager(emf);
1196
1197                // If there's not already an EntityManager registered for
1198
// this extended EntityManagerFactory within the current tx
1199
if (extendedEmAssociatedWithTx == null) {
1200                    j2eeTx.addExtendedEntityManagerMapping(emf,
1201                                                           extendedEm);
1202                    sessionCtx.setEmfRegisteredWithTx(emf, true);
1203
1204                    // Tell persistence provider to associate the extended
1205
// entity manager with the transaction.
1206
// @@@ Comment this out when joinTransaction supported on
1207
// EntityManager API.
1208
extendedEm.joinTransaction();
1209                }
1210            }
1211        }
1212    }
1213    
1214    /**
1215     * Called from EJBObject/EJBHome after invoking on bean.
1216     */

1217    public void postInvoke(Invocation inv) {
1218        if (ejbMethodStatsManager.isMethodMonitorOn()){
1219        ejbMethodStatsManager.postInvoke(inv.method, inv.exception);
1220        }
1221            
1222        if ( inv.ejb != null ) {
1223
1224            // counterpart of invocationManager.preInvoke
1225
invocationManager.postInvoke(inv);
1226
1227            if( isStatefulSession &&
1228                (((EJBContextImpl)inv.context).getTransaction() != null) ) {
1229
1230                SessionContextImpl sessionCtx = (SessionContextImpl)
1231                    inv.context;
1232                J2EETransaction j2eeTx =
1233                    (J2EETransaction) sessionCtx.getTransaction();
1234
1235                Map<EntityManagerFactory, EntityManager> entityManagerMap =
1236                    sessionCtx.getExtendedEntityManagerMap();
1237                for(EntityManagerFactory emf : entityManagerMap.keySet()) {
1238                    
1239                    if( sessionCtx.isEmfRegisteredWithTx(emf) ) {
1240                        j2eeTx.removeExtendedEntityManagerMapping(emf);
1241                        sessionCtx.setEmfRegisteredWithTx(emf, false);
1242                    }
1243                }
1244            }
1245            
1246            try {
1247                postInvokeTx(inv);
1248            }
1249            catch ( Exception JavaDoc ex ) {
1250                _logger.log(Level.FINE,"ejb.postinvoketx_exception",ex);
1251                if ( ex instanceof EJBException)
1252                    inv.exception = (EJBException)ex;
1253                else
1254                    inv.exception = new EJBException(ex);
1255            }
1256
1257            
1258            releaseContext(inv);
1259        }
1260        
1261        if ( inv.exception != null ) {
1262            
1263            // Unwrap the PreInvokeException if necessary
1264
if ( inv.exception instanceof PreInvokeException ) {
1265                inv.exception = ((PreInvokeException)inv.exception).exception;
1266            }
1267
1268            // Log system exceptions by default and application exceptions only
1269
// when log level is FINE or higher.
1270
Level exLogLevel = isSystemUncheckedException(inv.exception) ?
1271                Level.INFO : Level.FINE;
1272
1273            _logger.log(exLogLevel,"ejb.some_unmapped_exception", logParams);
1274            _logger.log(exLogLevel, "", inv.exception);
1275            
1276            if ( !inv.isLocal ) {
1277
1278                // For remote business case, exception mapping is performed
1279
// in client wrapper.
1280
inv.exception = protocolMgr.mapException(inv.exception);
1281                    
1282                // The most useful portion of the system exception is logged
1283
// above. Only log mapped form when log level is FINE or
1284
// higher.
1285
_logger.log(Level.FINE, "", inv.exception);
1286
1287            } else {
1288
1289                if( inv.isBusinessInterface ) {
1290                    inv.exception =
1291                        mapBusinessInterfaceException(inv.exception);
1292                }
1293
1294            }
1295
1296        }
1297        
1298        if ( AppVerification.doInstrument()) {
1299            // need to pass the method, exception info,
1300
// and EJB descriptor to get app info
1301
AppVerification.getInstrumentLogger().doInstrumentForEjb(
1302            ejbDescriptor, inv.method, inv.exception);
1303            
1304        }
1305        
1306    }
1307    
1308    
1309    
1310    /**
1311     * Check if caller is authorized to invoke the method.
1312     * Only called for EJBLocalObject and EJBLocalHome methods,
1313     * from EJBLocalHome|ObjectImpl classes.
1314     * @param method an integer identifying the method to be checked,
1315     * must be one of the EJBLocal{Home|Object}_* constants.
1316     */

1317    void authorizeLocalMethod(int method) {
1318
1319        Invocation inv = new Invocation();
1320        inv.isLocal = true;
1321        inv.isHome = EJB_INTF_METHODS_INFO[method];
1322        inv.method = ejbIntfMethods[method];
1323
1324        if ( !authorize(inv) ) {
1325            throw new AccessLocalException(
1326                "Client is not authorized for this invocation.");
1327        }
1328    }
1329    
1330    /**
1331     * Check if caller is authorized to invoke the method.
1332     * Only called for EJBObject and EJBHome methods,
1333     * from EJBHome|ObjectImpl classes.
1334     * @param method an integer identifying the method to be checked,
1335     * must be one of the EJB{Home|Object}_* constants.
1336     */

1337    void authorizeRemoteMethod(int method)
1338        throws RemoteException JavaDoc
1339    {
1340        Invocation inv = new Invocation();
1341        inv.isLocal = false;
1342        inv.isHome = EJB_INTF_METHODS_INFO[method];
1343        inv.method = ejbIntfMethods[method];
1344        if ( !authorize(inv) ) {
1345            AccessException JavaDoc ex = new AccessException JavaDoc(
1346                "Client is not authorized for this invocation.");
1347            Throwable JavaDoc t = protocolMgr.mapException(ex);
1348            if ( t instanceof RuntimeException JavaDoc )
1349                throw (RuntimeException JavaDoc)t;
1350            else if ( t instanceof RemoteException JavaDoc )
1351                throw (RemoteException JavaDoc)t;
1352            else
1353                throw ex; // throw the AccessException
1354
}
1355    }
1356
1357    /**
1358     * Encapsulate logic used to map invocation method to invocation info.
1359     * At present, we have two different maps, one for webservice invocation
1360     * info and one for everything else. That might change in the future.
1361     */

1362    private InvocationInfo getInvocationInfo(Invocation inv) {
1363        return inv.isWebService ?
1364            (InvocationInfo) webServiceInvocationInfoMap.get(inv.method) :
1365            (InvocationInfo) invocationInfoMap.get(inv.method);
1366    }
1367
1368    private Throwable JavaDoc mapBusinessInterfaceException(Throwable JavaDoc t) {
1369
1370        Throwable JavaDoc mappedException = null;
1371
1372        if( t instanceof TransactionRolledbackLocalException ) {
1373            mappedException = new EJBTransactionRolledbackException();
1374            mappedException.initCause(t);
1375        } else if( t instanceof TransactionRequiredLocalException ) {
1376            mappedException = new EJBTransactionRequiredException();
1377            mappedException.initCause(t);
1378        } else if( t instanceof NoSuchObjectLocalException ) {
1379            mappedException = new NoSuchEJBException();
1380            mappedException.initCause(t);
1381        }
1382        
1383        return (mappedException != null) ? mappedException : t;
1384
1385    }
1386
1387    /**
1388     * Common code to handle EJB security manager authorization call.
1389     */

1390    public boolean authorize(Invocation inv) {
1391
1392        // There are a few paths (e.g. authorizeLocalMethod,
1393
// authorizeRemoteMethod, Ejb endpoint pre-handler )
1394
// for which invocationInfo is not set. We get better
1395
// performance with the security manager on subsequent
1396
// invocations of the same method if invocationInfo is
1397
// set on the invocation. However, the authorization
1398
// does not depend on it being set. So, try to set
1399
// invocationInfo but in this case don't treat it as
1400
// an error if it's not available.
1401
if( inv.invocationInfo == null ) {
1402            
1403            inv.invocationInfo = getInvocationInfo(inv);
1404                        
1405        }
1406
1407        // Internal methods for 3.0 bean creation so there won't
1408
// be corresponding permissions in the security policy file.
1409
if( (inv.method.getDeclaringClass() == localBusinessHomeIntf)
1410            ||
1411            (inv.method.getDeclaringClass() == remoteBusinessHomeIntf) ) {
1412            return true;
1413        }
1414       
1415        boolean authorized = securityManager.authorize(inv);
1416        
1417        if( !authorized ) {
1418
1419            if( inv.context != null ) {
1420                // This means that an enterprise bean context was created
1421
// during the authorization call because of a callback from
1422
// a JACC enterprise bean handler. Since the invocation will
1423
// not proceed due to the authorization failure, we need
1424
// to release the enterprise bean context.
1425
releaseContext(inv);
1426            }
1427        }
1428
1429        return authorized;
1430    }
1431
1432    /**
1433     * Create an array of all methods in the standard EJB interfaces:
1434     * javax.ejb.EJB(Local){Home|Object} .
1435     */

1436    private void initializeEjbInterfaceMethods()
1437        throws Exception JavaDoc
1438    {
1439        ejbIntfMethods = new Method[EJB_INTF_METHODS_LENGTH];
1440        
1441        if ( isRemote ) {
1442            ejbIntfMethods[ EJBHome_remove_Handle ] =
1443                EJBHome.class.getMethod("remove",
1444                                    new Class JavaDoc[]{javax.ejb.Handle JavaDoc.class});
1445            ejbIntfMethods[ EJBHome_remove_Pkey ] =
1446                EJBHome.class.getMethod("remove",
1447                                        new Class JavaDoc[]{java.lang.Object JavaDoc.class});
1448            ejbIntfMethods[ EJBHome_getEJBMetaData ] =
1449                EJBHome.class.getMethod("getEJBMetaData", NO_PARAMS);
1450            ejbIntfMethods[ EJBHome_getHomeHandle ] =
1451                EJBHome.class.getMethod("getHomeHandle", NO_PARAMS);
1452            
1453            ejbIntfMethods[ EJBObject_getEJBHome ] =
1454                EJBObject.class.getMethod("getEJBHome", NO_PARAMS);
1455            ejbIntfMethods[ EJBObject_getPrimaryKey ] =
1456                EJBObject.class.getMethod("getPrimaryKey", NO_PARAMS);
1457            ejbIntfMethods[ EJBObject_remove ] =
1458                EJBObject.class.getMethod("remove", NO_PARAMS);
1459            ejbIntfMethods[ EJBObject_getHandle ] =
1460                EJBObject.class.getMethod("getHandle", NO_PARAMS);
1461            ejbIntfMethods[ EJBObject_isIdentical ] =
1462                EJBObject.class.getMethod("isIdentical",
1463            new Class JavaDoc[]{javax.ejb.EJBObject JavaDoc.class});
1464            
1465            if ( isStatelessSession ) {
1466                if( hasRemoteHomeView ) {
1467                    ejbIntfMethods[ EJBHome_create ] =
1468                        homeIntf.getMethod("create", NO_PARAMS);
1469                }
1470            }
1471        }
1472        
1473        if ( isLocal ) {
1474            ejbIntfMethods[ EJBLocalHome_remove_Pkey ] =
1475                EJBLocalHome.class.getMethod("remove",
1476                    new Class JavaDoc[]{java.lang.Object JavaDoc.class});
1477            
1478            ejbIntfMethods[ EJBLocalObject_getEJBLocalHome ] =
1479                EJBLocalObject.class.getMethod("getEJBLocalHome", NO_PARAMS);
1480            ejbIntfMethods[ EJBLocalObject_getPrimaryKey ] =
1481                EJBLocalObject.class.getMethod("getPrimaryKey", NO_PARAMS);
1482            ejbIntfMethods[ EJBLocalObject_remove ] =
1483                EJBLocalObject.class.getMethod("remove", NO_PARAMS);
1484            ejbIntfMethods[ EJBLocalObject_isIdentical ] =
1485                EJBLocalObject.class.getMethod("isIdentical",
1486            new Class JavaDoc[]{javax.ejb.EJBLocalObject JavaDoc.class});
1487            
1488            if ( isStatelessSession ) {
1489                if( hasLocalHomeView ) {
1490                    Method m = localHomeIntf.getMethod("create", NO_PARAMS);
1491                    ejbIntfMethods[ EJBLocalHome_create ] = m;
1492                }
1493            }
1494        }
1495        
1496    }
1497    
1498    private void destroyTimers() {
1499        EJBTimerService ejbTimerService = containerFactory.getEJBTimerService();
1500        if( isTimedObject() && (ejbTimerService != null) ) {
1501            ejbTimerService.destroyTimers(getContainerId());
1502        }
1503    }
1504    
1505    // internal API, implemented in subclasses
1506
abstract EJBObjectImpl createEJBObjectImpl()
1507        throws CreateException, RemoteException JavaDoc;
1508
1509    // Only applies to concrete session containers
1510
EJBObjectImpl createRemoteBusinessObjectImpl() throws CreateException,
1511        RemoteException JavaDoc
1512    {
1513        throw new EJBException(
1514            "Internal ERROR: BaseContainer.createRemoteBusinessObject called");
1515    }
1516    
1517    // internal API, implemented in subclasses
1518
EJBLocalObjectImpl createEJBLocalObjectImpl()
1519        throws CreateException
1520    {
1521        throw new EJBException(
1522            "Internal ERROR: BaseContainer.createEJBLocalObject called");
1523    }
1524
1525    // Only implemented in Stateless and Stateful session containers
1526
EJBLocalObjectImpl createEJBLocalBusinessObjectImpl()
1527        throws CreateException
1528    {
1529        throw new EJBException(
1530            "Internal ERROR: BaseContainer.createEJBLocalObject called");
1531    }
1532    
1533    /**
1534     * Called when a remote invocation arrives for an EJB.
1535     * Implemented in subclasses.
1536     */

1537    abstract EJBObjectImpl getEJBObjectImpl(byte[] streamKey);
1538    
1539    EJBObjectImpl getEJBRemoteBusinessObjectImpl(byte[] streamKey) {
1540    throw new EJBException
1541          ("Internal ERROR: BaseContainer.getRemoteBusinessObjectImpl called");
1542    }
1543
1544    EJBLocalObjectImpl getEJBLocalObjectImpl(Object JavaDoc key) {
1545    throw new EJBException
1546            ("Internal ERROR: BaseContainer.getEJBLocalObjectImpl called");
1547    }
1548
1549    EJBLocalObjectImpl getEJBLocalBusinessObjectImpl(Object JavaDoc key) {
1550    throw new EJBException
1551            ("Internal ERROR: BaseContainer.getEJBLocalObjectImpl called");
1552    }
1553
1554    /**
1555     * Check if the given EJBObject/LocalObject has been removed.
1556     * @exception NoSuchObjectLocalException if the object has been removed.
1557     */

1558    void checkExists(EJBLocalRemoteObject ejbObj) {
1559        throw new EJBException(
1560            "Internal ERROR: BaseContainer.checkExists called");
1561    }
1562
1563    protected final ComponentContext getContext(Invocation inv)
1564        throws EJBException {
1565
1566        return (inv.context == null) ? _getContext(inv) : inv.context;
1567
1568    }
1569    
1570    // internal API, implemented in subclasses
1571
protected abstract ComponentContext _getContext(Invocation inv)
1572        throws EJBException;
1573    
1574    // internal API, implemented in subclasses
1575
protected abstract void releaseContext(Invocation inv)
1576        throws EJBException;
1577    
1578    abstract boolean passivateEJB(ComponentContext context);
1579    
1580    // internal API, implemented in subclasses
1581
abstract void forceDestroyBean(EJBContextImpl sc)
1582        throws EJBException;
1583    
1584    abstract void removeBean(EJBLocalRemoteObject ejbo, Method removeMethod,
1585            boolean local)
1586        throws RemoveException, EJBException, RemoteException JavaDoc;
1587    
1588    // default implementation
1589
public void removeBeanUnchecked(Object JavaDoc pkey) {
1590        throw new EJBException(
1591            "removeBeanUnchecked only works for EntityContainer");
1592    }
1593
1594    // default implementation
1595
public void removeBeanUnchecked(EJBLocalObject bean) {
1596        throw new EJBException(
1597            "removeBeanUnchecked only works for EntityContainer");
1598    }
1599
1600    public void preSelect() {
1601        throw new EJBException(
1602        "preSelect only works for EntityContainer");
1603    }
1604
1605    // default implementation
1606
public EJBLocalObject getEJBLocalObjectForPrimaryKey(Object JavaDoc pkey, EJBContext ctx)
1607    {
1608    throw new EJBException("getEJBLocalObjectForPrimaryKey(pkey, ctx) only works for EntityContainer");
1609    }
1610    
1611    // default implementation
1612
public EJBLocalObject getEJBLocalObjectForPrimaryKey(Object JavaDoc pkey) {
1613        throw new EJBException(
1614            "getEJBLocalObjectForPrimaryKey only works for EntityContainer");
1615    }
1616    
1617    // default implementation
1618
public EJBObject getEJBObjectForPrimaryKey(Object JavaDoc pkey) {
1619        throw new EJBException(
1620            "getEJBObjectForPrimaryKey only works for EntityContainer");
1621    }
1622    
1623    // internal API, implemented in subclasses
1624
boolean isIdentical(EJBObjectImpl ejbo, EJBObject other)
1625        throws RemoteException JavaDoc
1626    {
1627        throw new EJBException(
1628            "Internal ERROR: BaseContainer.isIdentical called");
1629    }
1630
1631    /**
1632     * Called-back from security implementation through Invocation
1633     * when a jacc policy provider wants an enterprise bean instance.
1634     */

1635    public Object JavaDoc getJaccEjb(Invocation inv) {
1636        Object JavaDoc bean = null;
1637
1638        // Access to an enterprise bean instance is undefined for
1639
// anything but business method invocations through
1640
// Remote , Local, and ServiceEndpoint interfaces.
1641
if( ( (inv.invocationInfo != null) &&
1642              inv.invocationInfo.isBusinessMethod )
1643            ||
1644            inv.isWebService ) {
1645
1646            // In the typical case the context will not have been
1647
// set when the policy provider invokes this callback.
1648
// There are some cases where it is ok for it to have been
1649
// set, e.g. if the policy provider invokes the callback
1650
// twice within the same authorization decision.
1651
if( inv.context == null ) {
1652
1653                try {
1654                    inv.context = getContext(inv);
1655                    bean = inv.context.getEJB();
1656                    // NOTE : inv.ejb is not set here. Post-invoke logic for
1657
// BaseContainer and webservices uses the fact that
1658
// inv.ejb is non-null as an indication that that
1659
// BaseContainer.preInvoke() proceeded past a certain
1660
// point, which affects which cleanup needs to be
1661
// performed. It would be better to have explicit
1662
// state in the invocation that says which cleanup
1663
// steps are necessary(e.g. for invocationMgr.postInvoke
1664
// , postInvokeTx, etc) but I'm keeping the logic the
1665
// same for now. BaseContainer.authorize() will
1666
// explicitly handle the case where a context was
1667
// created as a result of this call and the
1668
// authorization failed, which means the context needs
1669
// be released.
1670

1671                } catch(EJBException e) {
1672                    _logger.log(Level.WARNING, "ejb.context_failure_jacc",
1673                                logParams[0]);
1674                    _logger.log(Level.WARNING, "", e);
1675                }
1676
1677            } else {
1678                bean = inv.context.getEJB();
1679            }
1680        }
1681
1682        return bean;
1683    }
1684
1685    public void assertValidLocalObject(Object JavaDoc o) throws EJBException
1686    {
1687        boolean valid = false;
1688        String JavaDoc errorMsg = "";
1689
1690        if( (o != null) && (o instanceof EJBLocalObject) ) {
1691            // Given object is always the client view EJBLocalObject.
1692
// Use utility method to translate it to EJBLocalObjectImpl
1693
// so we handle both the generated and proxy case.
1694
EJBLocalObjectImpl ejbLocalObjImpl =
1695                EJBLocalObjectImpl.toEJBLocalObjectImpl( (EJBLocalObject) o);
1696            BaseContainer otherContainer =
1697                (BaseContainer) ejbLocalObjImpl._getContainerInternal();
1698            if( otherContainer.getContainerId() == getContainerId() ) {
1699                valid = true;
1700            } else {
1701                errorMsg = localStrings.getLocalString
1702                    ("containers.assert_local_obj_bean", "",
1703                     new Object JavaDoc[] { otherContainer.ejbDescriptor.getName(),
1704                                    ejbDescriptor.getName() });
1705            }
1706        } else {
1707            errorMsg = (o != null) ?
1708               localStrings.getLocalString("containers.assert_local_obj_class",
1709                   "", new Object JavaDoc[] { o.getClass().getName(),
1710                                      ejbDescriptor.getName() })
1711               :
1712               localStrings.getLocalString("containers.assert_local_obj_null",
1713                   "", new Object JavaDoc[] { ejbDescriptor.getName() });
1714        }
1715        
1716        if( !valid ) {
1717            throw new EJBException(errorMsg);
1718        }
1719            
1720    }
1721
1722    /**
1723     * Asserts validity of RemoteHome objects. This was defined for the
1724     * J2EE 1.4 implementation and is exposed through Container SPI.
1725     */

1726    public void assertValidRemoteObject(Object JavaDoc o) throws EJBException
1727    {
1728        boolean valid = false;
1729        String JavaDoc errorMsg = "";
1730    Exception JavaDoc causeException = null;
1731
1732        if( (o != null) && (o instanceof EJBObject) ) {
1733            String JavaDoc className = o.getClass().getName();
1734
1735            // Given object must be an instance of the remote stub class for
1736
// this ejb.
1737
if (hasRemoteHomeView) {
1738        try {
1739            valid = remoteHomeRefFactory.hasSameContainerID(
1740                (org.omg.CORBA.Object JavaDoc) o);
1741        } catch (Exception JavaDoc ex) {
1742            causeException = ex;
1743            errorMsg = localStrings.getLocalString
1744            ("containers.assert_remote_obj_class", "",
1745            new Object JavaDoc[] { className, ejbDescriptor.getName() });
1746            
1747        }
1748            } else {
1749                errorMsg = localStrings.getLocalString
1750                    ("containers.assert_remote_obj_class", "",
1751                     new Object JavaDoc[] { className, ejbDescriptor.getName() });
1752            }
1753        } else {
1754            errorMsg = (o != null) ?
1755              localStrings.getLocalString("containers.assert_remote_obj_class",
1756                  "", new Object JavaDoc[] { o.getClass().getName(),
1757                                     ejbDescriptor.getName() })
1758              :
1759              localStrings.getLocalString("containers.assert_remote_obj_null",
1760                  "", new Object JavaDoc[] { ejbDescriptor.getName() });
1761        }
1762
1763        if( !valid ) {
1764            if (causeException != null) {
1765        throw new EJBException(errorMsg, causeException);
1766        } else {
1767        throw new EJBException(errorMsg);
1768        }
1769        }
1770    }
1771
1772    /**
1773     *
1774     */

1775    protected final int getTxAttr(Method method, String JavaDoc methodIntf)
1776        throws EJBException
1777    {
1778
1779        InvocationInfo invInfo =
1780            methodIntf.equals(MethodDescriptor.EJB_WEB_SERVICE) ?
1781            (InvocationInfo) webServiceInvocationInfoMap.get(method) :
1782            (InvocationInfo) invocationInfoMap.get(method);
1783
1784        if( invInfo != null ) {
1785            return invInfo.txAttr;
1786        } else {
1787            throw new EJBException("Transaction Attribute not found for method"
1788                                   + method);
1789        }
1790    }
1791    
1792    // Get the transaction attribute for a method.
1793
// Note: this method object is of the remote/EJBHome interface
1794
// class, not the EJB class. (except for MDB's message listener
1795
// callback method or TimedObject ejbTimeout method)
1796
protected final int getTxAttr(Invocation inv)
1797        throws EJBException
1798    {
1799        if ( inv.transactionAttribute != TX_NOT_INITIALIZED ) {
1800            return inv.transactionAttribute;
1801        }
1802
1803        int txAttr = getTxAttr(inv.method, inv.getMethodInterface());
1804        inv.transactionAttribute = txAttr;
1805        return inv.transactionAttribute;
1806
1807    }
1808    
1809    
1810    // Check if a method is a business method.
1811
// Note: this method object is of the EJB's remote/home/local interfaces,
1812
// not the EJB class.
1813
final boolean isBusinessMethod(Method method) {
1814        Class JavaDoc methodClass = method.getDeclaringClass();
1815        
1816        // All methods on the Home/LocalHome & super-interfaces
1817
// are not business methods.
1818
// All methods on javax.ejb.EJBObject and EJBLocalObject
1819
// (e.g. remove) are not business methods.
1820
// All remaining methods are business methods
1821

1822        if ( isRemote ) {
1823            if ( (hasRemoteHomeView &&
1824                  ( (methodClass == homeIntf) ||
1825                    methodClass.isAssignableFrom(homeIntf) ))
1826                 ||
1827                 (hasRemoteBusinessView &&
1828                  ( (methodClass == remoteBusinessHomeIntf) ||
1829                    methodClass.isAssignableFrom(remoteBusinessHomeIntf) ))
1830                 ||
1831                 (methodClass == EJBObject.class ) ) {
1832                return false;
1833            }
1834        }
1835        if ( isLocal ) {
1836            if ( (hasLocalHomeView &&
1837                  ( (methodClass == localHomeIntf) ||
1838                    methodClass.isAssignableFrom(localHomeIntf) ))
1839                 ||
1840                 (hasLocalBusinessView &&
1841                  ( (methodClass == localBusinessHomeIntf) ||
1842                    methodClass.isAssignableFrom(localBusinessHomeIntf) ))
1843                 ||
1844                 (methodClass == EJBLocalObject.class)) {
1845                return false;
1846            }
1847        }
1848        // NOTE : Web Service client view contains ONLY
1849
// business methods
1850

1851        return true;
1852    }
1853    
1854    // Check if a method is a finder / home method.
1855
// Note: this method object is of the EJB's remote/home/local interfaces,
1856
// not the EJB class.
1857
final boolean isHomeFinder(Method method) {
1858        Class JavaDoc methodClass = method.getDeclaringClass();
1859        
1860        // MDBs and SessionBeans cant have finder/home methods.
1861
if ( isMessageDriven || isSession ) {
1862            return false;
1863        }
1864        
1865        if ( isRemote ) {
1866            if ( (hasRemoteHomeView &&
1867                  methodClass.isAssignableFrom(homeIntf))
1868                 && (methodClass != EJBHome.class)
1869                 && (!method.getName().startsWith("create")) ) {
1870                return true;
1871            }
1872        }
1873        if ( isLocal ) {
1874            // No need to check LocalBusiness view b/c home/finder methods
1875
// only apply to entity beans.
1876
if ( (hasLocalHomeView &&
1877                  methodClass.isAssignableFrom(localHomeIntf))
1878                 && (methodClass != EJBLocalHome.class)
1879                 && (!method.getName().startsWith("create")) ) {
1880                return true;
1881            }
1882        }
1883        
1884        return false;
1885    }
1886    
1887    
1888    // Check if a method is a create / finder / home method.
1889
// Note: this method object is of the EJB's remote/home/local interfaces,
1890
// not the EJB class.
1891
final boolean isCreateHomeFinder(Method method) {
1892        Class JavaDoc methodClass = method.getDeclaringClass();
1893        
1894        if ( isMessageDriven ) {
1895            return false;
1896        }
1897        
1898        if ( hasRemoteHomeView
1899             && methodClass.isAssignableFrom(homeIntf)
1900             && (methodClass != EJBHome.class) ) {
1901            return true;
1902        }
1903        
1904        if ( hasRemoteBusinessView
1905             && methodClass.isAssignableFrom(remoteBusinessHomeIntf)
1906             && (methodClass != EJBHome.class) ) {
1907            return true;
1908        }
1909
1910        if ( hasLocalHomeView
1911             && methodClass.isAssignableFrom(localHomeIntf)
1912             && (methodClass != EJBLocalHome.class) ) {
1913            return true;
1914        }
1915
1916        if ( hasLocalBusinessView
1917             && methodClass.isAssignableFrom(localBusinessHomeIntf)
1918             && (methodClass != EJBLocalHome.class) ) {
1919            return true;
1920        }
1921        
1922        
1923        return false;
1924    }
1925
1926    private void addInvocationInfo(Method method, String JavaDoc methodIntf,
1927                                   Class JavaDoc originalIntf)
1928        throws EJBException
1929        
1930    {
1931        boolean flushEnabled = findFlushEnabledAttr(method, methodIntf);
1932        int txAttr = findTxAttr(method, methodIntf);
1933        InvocationInfo info = createInvocationInfo
1934            (method, txAttr, flushEnabled, methodIntf, originalIntf);
1935        boolean isHomeIntf = (methodIntf.equals(MethodDescriptor.EJB_HOME)
1936                || methodIntf.equals(MethodDescriptor.EJB_LOCALHOME));
1937        if (! isHomeIntf) {
1938            Method beanMethod = null;
1939            try {
1940                beanMethod = getEJBClass().getMethod(
1941                    method.getName(), method.getParameterTypes());
1942            } catch (NoSuchMethodException JavaDoc nsmEx) {
1943                //TODO
1944
}
1945            if (beanMethod != null) {
1946                MethodDescriptor md = new MethodDescriptor(beanMethod, MethodDescriptor.EJB_BEAN);
1947                info.interceptorChain = interceptorManager.getAroundInvokeChain(md, beanMethod);
1948            }
1949        }
1950        if( methodIntf.equals(MethodDescriptor.EJB_WEB_SERVICE) ) {
1951            webServiceInvocationInfoMap.put(method, info);
1952        } else {
1953            invocationInfoMap.put(method, info);
1954        }
1955    }
1956
1957    /**
1958     * Create invocation info for one method.
1959     *
1960     * @param originalIntf Leaf interface for the given view. Not set for
1961     * methodIntf == bean.
1962     */

1963    private InvocationInfo createInvocationInfo(Method method, int txAttr,
1964                                                boolean flushEnabled,
1965                                                String JavaDoc methodIntf,
1966                                                Class JavaDoc originalIntf)
1967        throws EJBException {
1968
1969        InvocationInfo invInfo = new InvocationInfo(method);
1970
1971        invInfo.ejbName = ejbDescriptor.getName();
1972        invInfo.txAttr = txAttr;
1973        invInfo.securityPermissions = Container.SEC_NOT_INITIALIZED;
1974        invInfo.methodIntf = methodIntf;
1975
1976        invInfo.isBusinessMethod = isBusinessMethod(method);
1977        invInfo.isCreateHomeFinder = isCreateHomeFinder(method);
1978        invInfo.isHomeFinder = isHomeFinder(method);
1979
1980        invInfo.startsWithCreate = method.getName().startsWith("create");
1981        invInfo.startsWithFind = method.getName().startsWith("find");
1982        invInfo.startsWithRemove = method.getName().startsWith("remove");
1983        invInfo.startsWithFindByPrimaryKey =
1984            method.getName().startsWith("findByPrimaryKey");
1985        invInfo.flushEnabled = flushEnabled;
1986
1987        if( methodIntf.equals(MethodDescriptor.EJB_LOCALHOME) ) {
1988            if( method.getDeclaringClass() != EJBLocalHome.class ) {
1989                setHomeTargetMethodInfo(invInfo, true);
1990            }
1991        } else if( methodIntf.equals(MethodDescriptor.EJB_HOME) ) {
1992            if( method.getDeclaringClass() != EJBHome.class ) {
1993                setHomeTargetMethodInfo(invInfo, false);
1994            }
1995        } else if( methodIntf.equals(MethodDescriptor.EJB_LOCAL) ) {
1996            if( method.getDeclaringClass() != EJBLocalObject.class ) {
1997                setEJBObjectTargetMethodInfo(invInfo, true, originalIntf);
1998            }
1999        } else if( methodIntf.equals(MethodDescriptor.EJB_REMOTE) ) {
2000            if( method.getDeclaringClass() != EJBObject.class ) {
2001                setEJBObjectTargetMethodInfo(invInfo, false, originalIntf);
2002            }
2003        }
2004
2005        if( _logger.isLoggable(Level.FINE) ) {
2006            _logger.log(Level.FINE, invInfo.toString());
2007        }
2008
2009        return invInfo;
2010    }
2011
2012    private void setHomeTargetMethodInfo(InvocationInfo invInfo,
2013                                         boolean isLocal)
2014        throws EJBException {
2015                                         
2016        Class JavaDoc homeIntfClazz = isLocal ?
2017            javax.ejb.EJBLocalHome JavaDoc.class : javax.ejb.EJBHome JavaDoc.class;
2018
2019        boolean isEntity = (ejbDescriptor instanceof EjbEntityDescriptor);
2020
2021        Class JavaDoc methodClass = invInfo.method.getDeclaringClass();
2022        Class JavaDoc[] paramTypes = invInfo.method.getParameterTypes();
2023        String JavaDoc methodName = invInfo.method.getName();
2024
2025        try {
2026            Method m = homeIntfClazz.getMethod(methodName, paramTypes);
2027            // Attempt to override Home/LocalHome method. Print warning
2028
// but don't treat it as a fatal error. At runtime,
2029
// the EJBHome/EJBLocalHome method will be called.
2030
String JavaDoc[] params = { m.toString(),invInfo.method.toString() };
2031            _logger.log(Level.WARNING,
2032                        "ejb.illegal_ejb_interface_override", params);
2033            invInfo.ejbIntfOverride = true;
2034            return;
2035        } catch(NoSuchMethodException JavaDoc nsme) {
2036        }
2037
2038        try {
2039            if( invInfo.startsWithCreate ) {
2040                
2041                String JavaDoc extraCreateChars =
2042                    methodName.substring("create".length());
2043                invInfo.targetMethod1 = ejbClass.getMethod
2044                    ("ejbCreate" + extraCreateChars, paramTypes);
2045                
2046                if( isEntity ) {
2047                    invInfo.targetMethod2 = ejbClass.getMethod
2048                        ("ejbPostCreate" + extraCreateChars, paramTypes);
2049                }
2050                
2051            } else if ( invInfo.startsWithFind ) {
2052                
2053                String JavaDoc extraFinderChars = methodName.substring("find".length());
2054                invInfo.targetMethod1 = ejbClass.getMethod
2055                    ("ejbFind" + extraFinderChars, paramTypes);
2056                
2057            } else {
2058
2059                // HOME method
2060

2061                String JavaDoc upperCasedName =
2062                    methodName.substring(0,1).toUpperCase() +
2063                    methodName.substring(1);
2064                invInfo.targetMethod1 = ejbClass.getMethod
2065                    ("ejbHome" + upperCasedName, paramTypes);
2066            }
2067        } catch(NoSuchMethodException JavaDoc nsme) {
2068            
2069            if( (methodClass == localBusinessHomeIntf) ||
2070                (methodClass == remoteBusinessHomeIntf) ) {
2071                // Not an error. This is the case where the EJB 3.0
2072
// client view is being used and there is no corresponding
2073
// create/init method.
2074
} else if (isStatelessSession ) {
2075                // Ignore. Not an error.
2076
// EJB 3.0 Stateless session ejbCreate/PostConstruct
2077
// is decoupled from RemoteHome/LocalHome create().
2078
} else {
2079
2080                Method initMethod = null;
2081                if( isSession ) {
2082                    EjbSessionDescriptor sessionDesc =
2083                        (EjbSessionDescriptor) ejbDescriptor;
2084
2085                    for(EjbInitInfo next : sessionDesc.getInitMethods()) {
2086                        MethodDescriptor beanMethod = next.getBeanMethod();
2087                        Method m = beanMethod.getMethod(sessionDesc);
2088                        if( next.getCreateMethod().getName().equals(methodName)
2089                            &&
2090                            TypeUtil.sameParamTypes(m, invInfo.method) ) {
2091                            initMethod = m;
2092                            break;
2093                        }
2094                    }
2095                }
2096                
2097                if( initMethod != null ) {
2098                    invInfo.targetMethod1 = initMethod;
2099                } else {
2100                    Object JavaDoc[] params = { logParams[0],
2101                                        (isLocal ? "LocalHome" : "Home"),
2102                                        invInfo.method.toString() };
2103                    _logger.log(Level.WARNING,
2104                                "ejb.bean_class_method_not_found", params);
2105                    // Treat this as a warning instead of a fatal error.
2106
// That matches the behavior of the generated code.
2107
// Mark the target methods as null. If this method is
2108
// invoked at runtime it will be result in an exception
2109
// from the invocation handlers.
2110
invInfo.targetMethod1 = null;
2111                    invInfo.targetMethod2 = null;
2112                }
2113            }
2114        }
2115    }
2116
2117    private void setEJBObjectTargetMethodInfo(InvocationInfo invInfo,
2118                                              boolean isLocal,
2119                                              Class JavaDoc originalIntf)
2120        throws EJBException {
2121
2122        Class JavaDoc ejbIntfClazz = isLocal ?
2123            javax.ejb.EJBLocalObject JavaDoc.class : javax.ejb.EJBObject JavaDoc.class;
2124
2125        Class JavaDoc[] paramTypes = invInfo.method.getParameterTypes();
2126        String JavaDoc methodName = invInfo.method.getName();
2127
2128        // Check for 2.x Remote/Local bean attempts to override
2129
// EJBObject/EJBLocalObject operations.
2130
if( ejbIntfClazz.isAssignableFrom(originalIntf) ) {
2131            try {
2132                Method m = ejbIntfClazz.getMethod(methodName, paramTypes);
2133                // Attempt to override EJBObject/EJBLocalObject method. Print
2134
// warning but don't treat it as a fatal error. At runtime, the
2135
// EJBObject/EJBLocalObject method will be called.
2136
String JavaDoc[] params = { m.toString(),invInfo.method.toString() };
2137                _logger.log(Level.WARNING,
2138                            "ejb.illegal_ejb_interface_override", params);
2139                invInfo.ejbIntfOverride = true;
2140                return;
2141            } catch(NoSuchMethodException JavaDoc nsme) {
2142            }
2143        }
2144
2145        try {
2146            invInfo.targetMethod1 = ejbClass.getMethod(methodName, paramTypes);
2147
2148            if( isSession && isStatefulSession ) {
2149                MethodDescriptor methodDesc = new MethodDescriptor
2150                    (invInfo.targetMethod1, MethodDescriptor.EJB_BEAN);
2151
2152                // Assign removal info to inv info. If this method is not
2153
// an @Remove method, result will be null.
2154
invInfo.removalInfo = ((EjbSessionDescriptor)ejbDescriptor).
2155                    getRemovalInfo(methodDesc);
2156            }
2157
2158        } catch(NoSuchMethodException JavaDoc nsme) {
2159            Object JavaDoc[] params = { logParams[0] + ":" + nsme.toString(),
2160                                (isLocal ? "Local" : "Remote"),
2161                                invInfo.method.toString() };
2162            _logger.log(Level.WARNING,
2163                        "ejb.bean_class_method_not_found", params);
2164            // Treat this as a warning instead of a fatal error.
2165
// That matches the behavior of the generated code.
2166
// Mark the target methods as null. If this method is
2167
// invoked at runtime it will be result in an exception from
2168
// the invocation handlers.
2169
invInfo.targetMethod1 = null;
2170        }
2171    }
2172
2173    //Overridden in StatefulContainerOnly
2174
protected String JavaDoc[] getPre30LifecycleMethodNames() {
2175        return new String JavaDoc[] {
2176            "ejbCreate", "ejbRemove", "ejbPassivate", "ejbActivate"
2177        };
2178    };
2179    
2180    private void initializeInterceptorManager() throws Exception JavaDoc {
2181        this.interceptorManager = new InterceptorManager(_logger, this,
2182                lifecycleCallbackAnnotationClasses,
2183                getPre30LifecycleMethodNames());
2184    }
2185    
2186    /*
2187     * Used by message bean container to register message-listener methods
2188     */

2189    protected void registerTxAttrForMethod(Method method, String JavaDoc methodIntf) {
2190        addInvocationInfo(method, methodIntf, null);
2191    }
2192    
2193    
2194    private void initializeInvocationInfo()
2195        throws Exception JavaDoc
2196    {
2197        
2198        if( isMessageDriven ) {
2199            // message listener method initialization performed by
2200
// message bean container
2201
} else {
2202            if ( isRemote ) {
2203
2204                if( hasRemoteHomeView ) {
2205                    // Process Remote intf
2206
Method[] methods = remoteIntf.getMethods();
2207                    for ( int i=0; i<methods.length; i++ ) {
2208                        Method method = methods[i];
2209                        addInvocationInfo(method, MethodDescriptor.EJB_REMOTE,
2210                                          remoteIntf);
2211                    }
2212                    
2213                    // Process EJBHome intf
2214
methods = homeIntf.getMethods();
2215                    for ( int i=0; i<methods.length; i++ ) {
2216                        Method method = methods[i];
2217                        addInvocationInfo(method, MethodDescriptor.EJB_HOME,
2218                                          homeIntf);
2219                    }
2220                }
2221
2222                if( hasRemoteBusinessView ) {
2223
2224                    for(RemoteBusinessIntfInfo next :
2225                            remoteBusinessIntfInfo.values()) {
2226                        // Get methods from generated remote intf but pass
2227
// actual business interface as original interface.
2228
Method[] methods =
2229                            next.generatedRemoteIntf.getMethods();
2230                        for ( int i=0; i<methods.length; i++ ) {
2231                            Method method = methods[i];
2232                            addInvocationInfo(method,
2233                                              MethodDescriptor.EJB_REMOTE,
2234                                              next.remoteBusinessIntf);
2235                        }
2236                    }
2237                    
2238                    // Process internal EJB RemoteBusinessHome intf
2239
Method[] methods = remoteBusinessHomeIntf.getMethods();
2240                    for ( int i=0; i<methods.length; i++ ) {
2241                        Method method = methods[i];
2242                        addInvocationInfo(method, MethodDescriptor.EJB_HOME,
2243                                          remoteBusinessHomeIntf);
2244                    }
2245                }
2246            }
2247
2248            if ( isLocal ) {
2249                if( hasLocalHomeView ) {
2250                    // Process Local interface
2251
Method[] methods = localIntf.getMethods();
2252                    for ( int i=0; i<methods.length; i++ ) {
2253                        Method method = methods[i];
2254                        addInvocationInfo(method, MethodDescriptor.EJB_LOCAL,
2255                                          localIntf);
2256                    }
2257
2258                    // Process LocalHome interface
2259
methods = localHomeIntf.getMethods();
2260                    for ( int i=0; i<methods.length; i++ ) {
2261                        Method method = methods[i];
2262                        addInvocationInfo(method,
2263                                          MethodDescriptor.EJB_LOCALHOME,
2264                                          localHomeIntf);
2265                    }
2266                }
2267
2268                if( hasLocalBusinessView ) {
2269
2270                    // Process Local Business interfaces
2271
for(Class JavaDoc localBusinessIntf : localBusinessIntfs) {
2272                        Method[] methods = localBusinessIntf.getMethods();
2273                        for ( int i=0; i<methods.length; i++ ) {
2274                            Method method = methods[i];
2275                            addInvocationInfo(method,
2276                                              MethodDescriptor.EJB_LOCAL,
2277                                              localBusinessIntf);
2278                        }
2279                    }
2280
2281                    // Process (internal) Local Business Home interface
2282
Method[] methods = localBusinessHomeIntf.getMethods();
2283                    for ( int i=0; i<methods.length; i++ ) {
2284                        Method method = methods[i];
2285                        addInvocationInfo(method,
2286                                          MethodDescriptor.EJB_LOCALHOME,
2287                                          localBusinessHomeIntf);
2288                    }
2289                }
2290            }
2291
2292            if ( isWebServiceEndpoint ) {
2293                // Process Service Endpoint interface
2294
Method[] methods = webServiceEndpointIntf.getMethods();
2295                for ( int i=0; i<methods.length; i++ ) {
2296                    Method method = methods[i];
2297                    addInvocationInfo(method,MethodDescriptor.EJB_WEB_SERVICE,
2298                                      webServiceEndpointIntf);
2299                }
2300            }
2301
2302        }
2303        
2304        if( isTimedObject() ) {
2305            int txAttr = findTxAttr(ejbTimeoutMethod,
2306                                    MethodDescriptor.EJB_BEAN);
2307            if( isBeanManagedTran ||
2308                txAttr == TX_REQUIRED ||
2309                txAttr == TX_REQUIRES_NEW ||
2310                txAttr == TX_NOT_SUPPORTED ) {
2311                addInvocationInfo(ejbTimeoutMethod, MethodDescriptor.EJB_BEAN,
2312                                  null);
2313            } else {
2314                throw new EJBException("Timeout method " + ejbTimeoutMethod +
2315                                       "must have TX attribute of " +
2316                                       "TX_REQUIRES_NEW or TX_REQUIRED or " +
2317                                       "TX_NOT_SUPPORTED for ejb " +
2318                                       ejbDescriptor.getName());
2319            }
2320        }
2321
2322        // Create a map implementation that is optimized
2323
// for method lookups. This is especially important for local
2324
// invocations through dynamic proxies, where the overhead of the
2325
// the (method -> invocationInfo) lookup has been measured to be
2326
// 6X greater than the overhead of the reflective call itself.
2327
proxyInvocationInfoMap = new MethodMap(invocationInfoMap);
2328
2329    }
2330    
2331    // Search for the transaction attribute for a method.
2332
// This is only used during container initialization. After that,
2333
// tx attributes can be looked up with variations of getTxAttr()
2334
private int findTxAttr(Method method, String JavaDoc methodIntf) {
2335        int txAttr = -1;
2336        
2337        if ( isBeanManagedTran )
2338            return TX_BEAN_MANAGED;
2339
2340        MethodDescriptor md = new MethodDescriptor(method, methodIntf);
2341        ContainerTransaction ct = ejbDescriptor.getContainerTransactionFor(md);
2342                                                                    
2343        if ( ct != null ) {
2344            String JavaDoc attr = ct.getTransactionAttribute();
2345            if ( attr.equals(ContainerTransaction.NOT_SUPPORTED) )
2346                txAttr = TX_NOT_SUPPORTED;
2347            else if ( attr.equals(ContainerTransaction.SUPPORTS) )
2348                txAttr = TX_SUPPORTS;
2349            else if ( attr.equals(ContainerTransaction.REQUIRED) )
2350                txAttr = TX_REQUIRED;
2351            else if ( attr.equals(ContainerTransaction.REQUIRES_NEW) )
2352                txAttr = TX_REQUIRES_NEW;
2353            else if ( attr.equals(ContainerTransaction.MANDATORY) )
2354                txAttr = TX_MANDATORY;
2355            else if ( attr.equals(ContainerTransaction.NEVER) )
2356                txAttr = TX_NEVER;
2357        }
2358        
2359        if ( txAttr == -1 ) {
2360            throw new EJBException("Transaction Attribute not found for method "
2361                + method);
2362        }
2363        
2364        // For EJB2.0 CMP EntityBeans, container is only required to support
2365
// REQUIRED/REQUIRES_NEW/MANDATORY, see EJB2.0 section 17.4.1.
2366
if ( isEntity ) {
2367            if (((EjbEntityDescriptor)ejbDescriptor).getPersistenceType().
2368                equals(EjbEntityDescriptor.CONTAINER_PERSISTENCE)) {
2369                EjbCMPEntityDescriptor e= (EjbCMPEntityDescriptor)ejbDescriptor;
2370                if ( !e.getIASEjbExtraDescriptors().isIsReadOnlyBean() &&
2371                     e.isEJB20() ) {
2372                    if ( txAttr != TX_REQUIRED && txAttr != TX_REQUIRES_NEW
2373                    && txAttr != TX_MANDATORY )
2374                        throw new EJBException(
2375                            "Transaction attribute for EJB2.0 CMP EntityBeans" +
2376                            " must be Required/RequiresNew/Mandatory");
2377                }
2378            }
2379        }
2380
2381        return txAttr;
2382    }
2383    
2384    // Check if the user has enabled flush at end of method flag
2385
// This is only used during container initialization and set into
2386
// the invocation info object. This method is over-riden in the
2387
// EntityContainer.
2388
protected boolean findFlushEnabledAttr(Method method, String JavaDoc methodIntf) {
2389            
2390        //Get the flushMethodDescriptor and then find if flush has been
2391
//enabled for this method
2392
MethodDescriptor md = new MethodDescriptor(method, methodIntf);
2393        boolean flushEnabled =
2394            ejbDescriptor.getIASEjbExtraDescriptors().isFlushEnabledFor(md);
2395
2396        return flushEnabled;
2397    }
2398
2399    private EJBHomeImpl instantiateEJBHomeImpl() throws Exception JavaDoc {
2400
2401        EJBHomeInvocationHandler handler =
2402            new EJBHomeInvocationHandler(ejbDescriptor, homeIntf,
2403                                         proxyInvocationInfoMap);
2404
2405        EJBHomeImpl homeImpl = handler;
2406
2407        // Maintain insertion order
2408
Set proxyInterfacesSet = new LinkedHashSet();
2409
2410        if( ejbDescriptor.getIASEjbExtraDescriptors().isIsReadOnlyBean() ) {
2411            proxyInterfacesSet.add(ReadOnlyEJBHome.class);
2412        }
2413
2414        proxyInterfacesSet.add(homeIntf);
2415
2416        Class JavaDoc[] proxyInterfaces = (Class JavaDoc [])
2417            proxyInterfacesSet.toArray(new Class JavaDoc[0]);
2418
2419        EJBHome ejbHomeProxy = (EJBHome)
2420            Proxy.newProxyInstance( loader, proxyInterfaces, handler);
2421        
2422        handler.setProxy(ejbHomeProxy);
2423
2424        homeImpl.setContainer(this);
2425            
2426        return homeImpl;
2427
2428    }
2429
2430    private EJBHomeImpl instantiateEJBRemoteBusinessHomeImpl()
2431        throws Exception JavaDoc {
2432
2433        EJBHomeInvocationHandler handler =
2434            new EJBHomeInvocationHandler(ejbDescriptor,
2435                                         remoteBusinessHomeIntf,
2436                                         proxyInvocationInfoMap);
2437
2438        EJBHomeImpl remoteBusinessHomeImpl = handler;
2439
2440        EJBHome ejbRemoteBusinessHomeProxy = (EJBHome)
2441            Proxy.newProxyInstance(loader,
2442                                   new Class JavaDoc[] { remoteBusinessHomeIntf },
2443                                   handler);
2444        
2445        handler.setProxy(ejbRemoteBusinessHomeProxy);
2446
2447        remoteBusinessHomeImpl.setContainer(this);
2448            
2449        return remoteBusinessHomeImpl;
2450
2451    }
2452
2453    private EJBLocalHomeImpl instantiateEJBLocalHomeImpl()
2454        throws Exception JavaDoc {
2455
2456        // LocalHome impl
2457
EJBLocalHomeInvocationHandler invHandler =
2458            new EJBLocalHomeInvocationHandler(ejbDescriptor,
2459                                              localHomeIntf,
2460                                              proxyInvocationInfoMap);
2461        
2462        EJBLocalHomeImpl homeImpl = invHandler;
2463        
2464        // Maintain insertion order
2465
Set proxyInterfacesSet = new LinkedHashSet();
2466        
2467        proxyInterfacesSet.add(IndirectlySerializable.class);
2468        if( ejbDescriptor.getIASEjbExtraDescriptors().isIsReadOnlyBean()) {
2469            proxyInterfacesSet.add(ReadOnlyEJBLocalHome.class);
2470        }
2471        proxyInterfacesSet.add(localHomeIntf);
2472        
2473        Class JavaDoc[] proxyInterfaces = (Class JavaDoc[])
2474            proxyInterfacesSet.toArray(new Class JavaDoc[0]);
2475        
2476        // Client's EJBLocalHome object
2477
EJBLocalHome proxy = (EJBLocalHome) Proxy.newProxyInstance
2478            (loader, proxyInterfaces, invHandler);
2479            
2480        invHandler.setProxy(proxy);
2481
2482        homeImpl.setContainer(this);
2483
2484        return homeImpl;
2485    }
2486
2487    private EJBLocalHomeImpl instantiateEJBLocalBusinessHomeImpl()
2488        throws Exception JavaDoc {
2489
2490        EJBLocalHomeInvocationHandler invHandler =
2491            new EJBLocalHomeInvocationHandler(ejbDescriptor,
2492                                              localBusinessHomeIntf,
2493                                              proxyInvocationInfoMap);
2494
2495        EJBLocalHomeImpl homeImpl = invHandler;
2496        
2497        EJBLocalHome proxy = (EJBLocalHome) Proxy.newProxyInstance
2498            (loader, new Class JavaDoc[] { IndirectlySerializable.class,
2499                                   localBusinessHomeIntf }, invHandler);
2500            
2501        invHandler.setProxy(proxy);
2502
2503        homeImpl.setContainer(this);
2504
2505        return homeImpl;
2506    }
2507
2508
2509    protected EJBLocalObjectImpl instantiateEJBLocalObjectImpl()
2510        throws Exception JavaDoc {
2511        EJBLocalObjectImpl localObjImpl = null;
2512
2513        EJBLocalObjectInvocationHandler handler =
2514            new EJBLocalObjectInvocationHandler(proxyInvocationInfoMap,
2515                                                localIntf);
2516
2517        localObjImpl = handler;
2518        EJBLocalObject localObjectProxy = (EJBLocalObject)
2519                ejbLocalObjectProxyCtor.newInstance( new Object JavaDoc[] { handler });
2520        handler.setProxy(localObjectProxy);
2521
2522        localObjImpl.setContainer(this);
2523
2524        return localObjImpl;
2525    }
2526
2527    protected EJBLocalObjectImpl instantiateEJBLocalBusinessObjectImpl()
2528        throws Exception JavaDoc {
2529
2530        EJBLocalObjectInvocationHandler handler =
2531            new EJBLocalObjectInvocationHandler(proxyInvocationInfoMap);
2532
2533        EJBLocalObjectImpl localBusinessObjImpl = handler;
2534
2535        Object JavaDoc localObjectProxy = ejbLocalBusinessObjectProxyCtor.newInstance
2536            ( new Object JavaDoc[] { handler });
2537
2538        localBusinessObjImpl.setContainer(this);
2539
2540        for (Class JavaDoc businessIntfClass : localBusinessIntfs) {
2541            EJBLocalObjectInvocationHandlerDelegate delegate =
2542                new EJBLocalObjectInvocationHandlerDelegate(
2543                        businessIntfClass, getContainerId(), handler);
2544            Proxy proxy = (Proxy) Proxy.newProxyInstance(
2545                    loader, new Class JavaDoc[] { IndirectlySerializable.class,
2546                                   businessIntfClass}, delegate);
2547            localBusinessObjImpl.mapClientObject(businessIntfClass.getName(),
2548                    proxy);
2549        }
2550        return localBusinessObjImpl;
2551    }
2552
2553
2554    protected EJBObjectImpl instantiateEJBObjectImpl() throws Exception JavaDoc {
2555        
2556        EJBObjectInvocationHandler handler =
2557            new EJBObjectInvocationHandler(proxyInvocationInfoMap,
2558                                           remoteIntf);
2559
2560        EJBObjectImpl ejbObjImpl = handler;
2561
2562        EJBObject ejbObjectProxy = (EJBObject)
2563            ejbObjectProxyCtor.newInstance( new Object JavaDoc[] { handler });
2564
2565        handler.setEJBObject(ejbObjectProxy);
2566
2567        ejbObjImpl.setContainer(this);
2568
2569        return ejbObjImpl;
2570    }
2571
2572    protected EJBObjectImpl instantiateRemoteBusinessObjectImpl()
2573        throws Exception JavaDoc {
2574        
2575        // There is one EJBObjectImpl instance, which is an instance of
2576
// the handler. That handler instance is shared by the dynamic
2577
// proxy for each remote business interface. We need to create a
2578
// different proxy for each remote business interface because
2579
// otherwise the target object given to the orb will be invalid
2580
// if the same method happens to be declared on multiple remote
2581
// business interfaces.
2582
EJBObjectInvocationHandler handler =
2583            new EJBObjectInvocationHandler(proxyInvocationInfoMap);
2584
2585        EJBObjectImpl ejbBusinessObjImpl = handler;
2586
2587        for(RemoteBusinessIntfInfo next :
2588                remoteBusinessIntfInfo.values()) {
2589
2590            EJBObjectInvocationHandlerDelegate delegate =
2591                new EJBObjectInvocationHandlerDelegate(next.remoteBusinessIntf,
2592                                                       handler);
2593
2594            java.rmi.Remote JavaDoc ejbBusinessObjectProxy = (java.rmi.Remote JavaDoc)
2595                next.proxyCtor.newInstance( new Object JavaDoc[] { delegate });
2596
2597            ejbBusinessObjImpl.setEJBObject(next.generatedRemoteIntf.getName(),
2598                                            ejbBusinessObjectProxy);
2599
2600        }
2601
2602        ejbBusinessObjImpl.setContainer(this);
2603
2604        return ejbBusinessObjImpl;
2605    }
2606
2607    // default implementation
2608
public void postCreate(Invocation inv, Object JavaDoc primaryKey)
2609        throws CreateException
2610    {
2611        throw new EJBException("Internal error");
2612    }
2613    
2614    // default implementation
2615
public Object JavaDoc postFind(Invocation inv, Object JavaDoc primaryKeys,
2616        Object JavaDoc[] findParams)
2617        throws FinderException
2618    {
2619        throw new EJBException("Internal error");
2620    }
2621    
2622    
2623    private void setupEnvironment()
2624        throws javax.naming.NamingException JavaDoc
2625    {
2626        // call the NamingManager to setup the java:comp/env namespace
2627
// for this EJB.
2628
componentId = namingManager.bindObjects(ejbDescriptor);
2629        
2630        // create envProps object to be returned from EJBContext.getEnvironment
2631
Set env = ejbDescriptor.getEnvironmentProperties();
2632        SafeProperties safeProps = new SafeProperties();
2633        safeProps.copy(env);
2634        envProps = safeProps;
2635    }
2636    
2637    /**
2638     * Called from NamingManagerImpl during java:comp/env lookup.
2639     */

2640    public String JavaDoc getComponentId() {
2641        return componentId;
2642    }
2643    
2644    /**
2645     * Called after all the components in the container's application
2646     * have deployed successfully.
2647     */

2648    public void doAfterApplicationDeploy() {
2649        _logger.log(Level.FINE,"Application deployment successful : " +
2650                    this);
2651
2652        setStartedState();
2653    }
2654    
2655    /**
2656     *
2657     */

2658    boolean callEJBTimeout(RuntimeTimerState timerState,
2659                           EJBTimerService timerService) throws Exception JavaDoc {
2660     
2661        boolean redeliver = false;
2662     
2663        if (containerState != CONTAINER_STARTED) {
2664            throw new EJBException("Attempt to invoke when container is in "
2665                                   + containerStateToString(containerState));
2666        }
2667     
2668        Invocation inv = new Invocation();
2669     
2670        // Let preInvoke do tx attribute lookup.
2671
inv.transactionAttribute = Container.TX_NOT_INITIALIZED;
2672     
2673        // There is never any client tx context so no need to do authorization.
2674
// If run-as is specified for the bean, it should be used.
2675
inv.securityPermissions = com.sun.ejb.Container.SEC_UNCHECKED;
2676     
2677        inv.method = ejbTimeoutMethod;
2678        inv.beanMethod = ejbTimeoutMethod;
2679
2680        // Application must be passed a TimerWrapper.
2681
Object JavaDoc[] args = { new TimerWrapper(timerState.getTimerId(),
2682                                            timerService) };
2683        
2684        inv.methodParams = args;
2685     
2686        // Delegate to subclass for i.ejbObject / i.isLocal setup.
2687
doTimerInvocationInit(inv, timerState);
2688     
2689        ClassLoader JavaDoc originalClassLoader = null;
2690     
2691        try {
2692            originalClassLoader = Utility.setContextClassLoader(loader);
2693
2694            preInvoke(inv);
2695
2696            // AroundInvoke methods don't apply to timeout methods so
2697
// use invokeTargetBeanMethod() instead of intercept()
2698
invokeTargetBeanMethod(inv.getBeanMethod(), inv, inv.ejb,
2699                                   inv.methodParams, null);
2700     
2701            if( !isBeanManagedTran && (transactionManager.getStatus() ==
2702                                       Status.STATUS_MARKED_ROLLBACK) ) {
2703                redeliver = true;
2704                _logger.log(Level.FINE, "ejbTimeout called setRollbackOnly");
2705            }
2706     
2707        } catch(InvocationTargetException ite) {
2708            // A runtime exception thrown from ejbTimeout, independent of
2709
// its transactional setting(CMT, BMT, etc.), should result in
2710
// a redelivery attempt. The instance that threw the runtime
2711
// exception will be destroyed, as per the EJB spec.
2712
redeliver = true;
2713            inv.exception = ite.getCause();
2714            _logger.log(Level.FINE, "ejbTimeout threw Runtime exception",
2715                       inv.exception);
2716        } catch(Throwable JavaDoc c) {
2717            redeliver = true;
2718            _logger.log(Level.FINE, "Exception while processing ejbTimeout", c);
2719            inv.exception = c;
2720        } finally {
2721
2722            // Only call postEjbTimeout if there are no errors so far.
2723
if( !redeliver ) {
2724                boolean success =
2725                    timerService.postEjbTimeout(timerState.getTimerId());
2726                redeliver = !success;
2727            }
2728            
2729            postInvoke(inv);
2730
2731            // If transaction commit fails, set redeliver flag.
2732
if( (redeliver == false) && (inv.exception != null) ) {
2733                redeliver = true;
2734            }
2735
2736            if( originalClassLoader != null ) {
2737                Utility.setContextClassLoader(originalClassLoader);
2738            }
2739
2740        }
2741     
2742        return redeliver;
2743    }
2744
2745    final void onEnteringContainer() {
2746        callFlowAgent.startTime(ContainerTypeOrApplicationType.EJB_CONTAINER);
2747    }
2748
2749    final void onLeavingContainer() {
2750        callFlowAgent.endTime();
2751    }
2752
2753    final void onEjbMethodStart() {
2754        callFlowAgent.ejbMethodStart(callFlowInfo);
2755    }
2756    
2757    final void onEjbMethodEnd() {
2758        callFlowAgent.ejbMethodEnd(callFlowInfo);
2759    }
2760    
2761    final Object JavaDoc invokeTargetBeanMethod(Method beanClassMethod, Invocation inv, Object JavaDoc target,
2762            Object JavaDoc[] params, com.sun.enterprise.SecurityManager mgr)
2763            throws Throwable JavaDoc {
2764        try {
2765            onEjbMethodStart();
2766            return SecurityUtil.invoke(beanClassMethod, inv, target, params, this, mgr);
2767        } catch (InvocationTargetException ite) {
2768            inv.exception = ite.getCause();
2769            throw ite;
2770        } catch(Throwable JavaDoc c) {
2771            inv.exception = c;
2772            throw c;
2773        } finally {
2774            onEjbMethodEnd();
2775        }
2776    }
2777    
2778    /**
2779     * This is implemented by concrete containers that support TimedObjects.
2780     */

2781    void doTimerInvocationInit(Invocation inv, RuntimeTimerState timerState )
2782        throws Exception JavaDoc {
2783        throw new EJBException("This container doesn't support TimedObjects");
2784    }
2785    
2786    /**
2787     * Perform common undeploy actions. NOTE that this should be done
2788     * defensively so that we attempt to do as much cleanup as possible, even
2789     * in the face of errors during undeploy. This might be called after
2790     * an unsuccessful deployment, in which case some of the services might
2791     * not have been initialized.
2792     */

2793    public void undeploy() {
2794        
2795        final Thread JavaDoc currentThread = Thread.currentThread();
2796        final ClassLoader JavaDoc previousClassLoader =
2797            currentThread.getContextClassLoader();
2798       
2799        try {
2800            destroyTimers();
2801        } catch(Exception JavaDoc e) {
2802            _logger.log(Level.FINE, "Error destroying timers for " +
2803                        ejbDescriptor.getName(), e);
2804        }
2805
2806        try {
2807            java.security.AccessController.doPrivileged(
2808            new java.security.PrivilegedAction JavaDoc() {
2809                public java.lang.Object JavaDoc run() {
2810                    currentThread.setContextClassLoader(loader);
2811                    return null;
2812                }
2813            });
2814            
2815            
2816            theSwitch.removeDescriptorFor(this);
2817            securityManager.destroy();
2818            
2819            if( !isMessageDriven ) {
2820                // destroy home objref
2821
try {
2822                    if ( isLocal ) {
2823                        // No specific undeploy steps
2824
}
2825                    if ( isRemote ) {
2826                       
2827
2828                        if( hasRemoteHomeView ) {
2829                            try {
2830                                namingManager.unpublishObject
2831                                    (remoteHomeJndiName);
2832                            } catch(NamingException JavaDoc ne) {
2833                                _logger.log(Level.FINE,
2834                                            "ejb.undeploy_exception",
2835                                            logParams);
2836                                _logger.log(Level.FINE, "", ne);
2837                            }
2838
2839                            remoteHomeRefFactory.destroyReference(ejbHomeStub,
2840                                                              ejbHome);
2841
2842                            // Hints to release stub-related meta-data in ORB
2843
remoteHomeRefFactory.cleanupClass(homeIntf);
2844                            remoteHomeRefFactory.cleanupClass(remoteIntf);
2845                            remoteHomeRefFactory.cleanupClass(ejbHome.getClass());
2846                            remoteHomeRefFactory.cleanupClass(ejbObjectProxyClass);
2847                        
2848                            // destroy the factory itself
2849
remoteHomeRefFactory.destroy();
2850                        }
2851
2852                        if( hasRemoteBusinessView ) {
2853                            try {
2854                                namingManager.unpublishObject
2855                                    (remoteBusinessHomeJndiName);
2856                            } catch(NamingException JavaDoc ne) {
2857                                _logger.log(Level.FINE,
2858                                            "ejb.undeploy_exception",
2859                                            logParams);
2860                                _logger.log(Level.FINE, "", ne);
2861                            }
2862
2863                            if( remoteBusinessJndiName != null ) {
2864                                try {
2865                                    // Unbind object factory. Avoid using
2866
// NamingManager.unpublish() b/c that
2867
// method has a side-effect which first
2868
// does a lookup of the given name.
2869
namingManager.getInitialContext().unbind
2870                                        (remoteBusinessJndiName);
2871                                } catch(NamingException JavaDoc ne) {
2872                                    _logger.log(Level.FINE,
2873                                                "ejb.undeploy_exception",
2874                                                logParams);
2875                                    _logger.log(Level.FINE, "", ne);
2876                                }
2877                            }
2878
2879                            // Home related cleanup
2880
RemoteReferenceFactory remoteBusinessRefFactory =
2881                             remoteBusinessIntfInfo.values().iterator().
2882                                next().referenceFactory;
2883                            remoteBusinessRefFactory.destroyReference
2884                                (ejbRemoteBusinessHomeStub,
2885                                 ejbRemoteBusinessHome);
2886
2887                            remoteBusinessRefFactory.cleanupClass
2888                                (remoteBusinessHomeIntf);
2889                            remoteBusinessRefFactory.cleanupClass
2890                                (ejbRemoteBusinessHome.getClass());
2891
2892                            // Cleanup for each remote business interface
2893
for(RemoteBusinessIntfInfo next :
2894                                    remoteBusinessIntfInfo.values()) {
2895
2896                                try {
2897                                    // Unbind object factory. Avoid using
2898
// NamingManager.unpublish() b/c that
2899
// method has a side-effect which first
2900
// does a lookup of the given name.
2901
namingManager.getInitialContext().unbind
2902                                        (next.jndiName);
2903                                } catch(NamingException JavaDoc ne) {
2904                                    _logger.log(Level.FINE,
2905                                                "ejb.undeploy_exception",
2906                                                logParams);
2907                                    _logger.log(Level.FINE, "", ne);
2908                                }
2909
2910                                next.referenceFactory.cleanupClass
2911                                    (next.generatedRemoteIntf);
2912
2913                                next.referenceFactory.cleanupClass
2914                                    (next.proxyClass);
2915                        
2916                                // destroy the factory itself
2917
next.referenceFactory.destroy();
2918                            }
2919                        }
2920      
2921                    }
2922                } catch ( Exception JavaDoc ex ) {
2923                    _logger.log(Level.FINE, "ejb.undeploy_exception",
2924                        logParams);
2925                    _logger.log(Level.FINE, "", ex);
2926                }
2927            }
2928
2929        try {
2930        namingManager.unbindObjects(ejbDescriptor);
2931        } catch (javax.naming.NamingException JavaDoc namEx) {
2932        _logger.log(Level.FINE, "ejb.undeploy_exception",
2933                        logParams);
2934        _logger.log(Level.FINE, "", namEx);
2935        }
2936            
2937        registryMediator.undeploy();
2938        registryMediator = null;
2939        ejbMethodStatsManager = null;
2940            containerFactory.removeContainer(ejbDescriptor.getUniqueId());
2941
2942            
2943        } finally {
2944            java.security.AccessController.doPrivileged(
2945            new java.security.PrivilegedAction JavaDoc() {
2946                public java.lang.Object JavaDoc run() {
2947                    currentThread.setContextClassLoader(previousClassLoader);
2948                    return null;
2949                }
2950            });
2951        }
2952        
2953        _logger.log(Level.FINE,
2954                    "**** [BaseContainer]: Successfully Undeployed " +
2955                    ejbDescriptor.getName() + " ...");
2956        
2957        ejbDescriptor = null;
2958        
2959        if (invocationInfoMap != null) { invocationInfoMap.clear(); }
2960        if (methodMonitorMap != null) { methodMonitorMap.clear(); }
2961        
2962        
2963        loader = null;
2964        ejbClass = null;
2965        ejbPassivateMethod = null;
2966        ejbActivateMethod = null;
2967        ejbRemoveMethod = null;
2968        
2969        remoteIntf = null;
2970        homeIntf = null;
2971        localHomeIntf = null;
2972        localIntf = null;
2973        ejbLocalHome = null;
2974        metadata = null;
2975        ejbHomeImpl = null;
2976        ejbHomeStub = null;
2977        invocationInfoMap = null;
2978        ejbIntfMethods = null;
2979        envProps = null;
2980        methodMonitorMap = null;
2981    }
2982
2983    /**
2984     * Called when server instance is Ready
2985     */

2986    public void onReady() {}
2987    
2988    
2989    
2990    /**
2991     * Called when server instance is shuting down
2992     */

2993    public void onShutdown() {
2994        setStoppedState();
2995    }
2996    
2997    /**
2998     * Called when server instance is terminating. This method is the last
2999     * one called during server shutdown.
3000     */

3001    public void onTermination() {}
3002    
3003    
3004    /***************************************************************************
3005     * The following methods implement transaction management machinery
3006     * in a reusable way for both SessionBeans and EntityBeans
3007     **************************************************************************/

3008    
3009    /**
3010     * This is called from preInvoke before every method invocation
3011     * on the EJB instance, including ejbCreate, ejbFind*, ejbRemove.
3012     * Also called from MessageBeanContainer, WebServiceInvocationHandler, etc,
3013     * so we can't assume that BaseContainer.preInvoke(Invocation) has run.
3014     * Therefore, handle inv.invocationInfo defensively since it might not have
3015     * been initialized.
3016     */

3017    protected final void preInvokeTx(Invocation inv)
3018        throws Exception JavaDoc
3019    {
3020        Method method = inv.method;
3021
3022        if (inv.invocationInfo==null) {
3023
3024            inv.invocationInfo = getInvocationInfo(inv);
3025
3026            if( inv.invocationInfo == null ) {
3027                throw new EJBException("Invocation Info lookup failed for " +
3028                                       "method " + inv.method);
3029            } else {
3030                inv.transactionAttribute = inv.invocationInfo.txAttr;
3031            }
3032        }
3033        
3034        // Get existing Tx status: this tells us if the client
3035
// started a transaction which was propagated on this invocation.
3036
int status = transactionManager.getStatus();
3037        
3038        //For MessageDrivenBeans,ejbCreate/ejbRemove must be called without a Tx.
3039
// For SessionBeans, ejbCreate/ejbRemove must be called without a Tx.
3040
// For EntityBeans, ejbCreate/ejbRemove/ejbFind must be called with a Tx
3041
// so no special work needed.
3042
if ( isSession && !inv.invocationInfo.isBusinessMethod ) {
3043            // EJB2.0 section 7.5.7 says that ejbCreate/ejbRemove etc are called
3044
// without a Tx. So suspend the client's Tx if any.
3045

3046            // Note: ejbRemove cannot be called when EJB is associated with
3047
// a Tx, according to EJB2.0 section 7.6.4. This check is done in
3048
// the container's implementation of removeBean().
3049

3050            if ( status != Status.STATUS_NO_TRANSACTION ) {
3051                // client request is associated with a Tx
3052
try {
3053                    inv.clientTx = transactionManager.suspend();
3054                } catch (SystemException ex) {
3055                    throw new EJBException(ex);
3056                }
3057            }
3058            return;
3059        }
3060        
3061        // isNullTx is true if the client sent a null tx context
3062
// (i.e. a tx context with a null Coordinator objref)
3063
// or if this server's tx interop mode flag is false.
3064
// Follow the tables in EJB2.0 sections 19.6.2.2.1 and 19.6.2.2.2.
3065
boolean isNullTx = false;
3066        //if (!inv.isLocal && !inv.isMessageDriven && !inv.isWebService)
3067
if (!inv.isLocal) {
3068            isNullTx = transactionManager.isNullTransaction();
3069        }
3070        
3071        int txAttr = getTxAttr(inv);
3072        
3073        EJBContextImpl context = (EJBContextImpl)inv.context;
3074        
3075        // Note: in the code below, inv.clientTx is set ONLY if the
3076
// client's Tx is actually suspended.
3077

3078        // get the Tx associated with the EJB from previous invocation,
3079
// if any.
3080
Transaction prevTx = context.getTransaction();
3081        
3082        switch (txAttr) {
3083            case TX_BEAN_MANAGED:
3084                // TX_BEAN_MANAGED rules from EJB2.0 Section 17.6.1, Table 13
3085
// Note: only MDBs and SessionBeans can be TX_BEAN_MANAGED
3086
if ( status != Status.STATUS_NO_TRANSACTION ) {
3087                    // client request associated with a Tx, always suspend
3088
inv.clientTx = transactionManager.suspend();
3089                }
3090                if ( isSession && !isStatelessSession && prevTx != null
3091                && prevTx.getStatus() != Status.STATUS_NO_TRANSACTION ) {
3092                    // Note: if prevTx != null , then it means
3093
// afterCompletion was not called yet for the
3094
// previous transaction on the EJB.
3095

3096                    // The EJB was previously associated with a Tx which was
3097
// begun by the EJB itself in a previous invocation.
3098
// This is only possible for stateful SessionBeans
3099
// not for StatelessSession or Entity.
3100
transactionManager.resume(prevTx);
3101                    
3102                    // This allows the TM to enlist resources
3103
// used by the EJB with the transaction
3104
transactionManager.enlistComponentResources();
3105                }
3106                
3107                break;
3108                
3109            case TX_NOT_SUPPORTED:
3110                if ( status != Status.STATUS_NO_TRANSACTION )
3111                    inv.clientTx = transactionManager.suspend();
3112                checkUnfinishedTx(prevTx, inv);
3113                if ( isEntity )
3114                    preInvokeNoTx(inv);
3115                break;
3116                
3117            case TX_MANDATORY:
3118                if ( isNullTx || status == Status.STATUS_NO_TRANSACTION )
3119                    throw new TransactionRequiredLocalException();
3120                
3121                useClientTx(prevTx, inv);
3122                break;
3123                
3124            case TX_REQUIRED:
3125                if ( isNullTx )
3126                    throw new TransactionRequiredLocalException();
3127                
3128                if ( status == Status.STATUS_NO_TRANSACTION ) {
3129                    inv.clientTx = null;
3130                    startNewTx(prevTx, inv);
3131                }
3132                else { // There is a client Tx
3133
inv.clientTx = transactionManager.getTransaction();
3134                    useClientTx(prevTx, inv);
3135                }
3136                break;
3137                
3138            case TX_REQUIRES_NEW:
3139                if ( status != Status.STATUS_NO_TRANSACTION )
3140                    inv.clientTx = transactionManager.suspend();
3141                startNewTx(prevTx, inv);
3142                break;
3143                
3144            case TX_SUPPORTS:
3145                if ( isNullTx )
3146                    throw new TransactionRequiredLocalException();
3147                
3148                if ( status != Status.STATUS_NO_TRANSACTION )
3149                    useClientTx(prevTx, inv);
3150                else { // we need to invoke the EJB with no Tx.
3151
checkUnfinishedTx(prevTx, inv);
3152                    if ( isEntity )
3153                        preInvokeNoTx(inv);
3154                }
3155                break;
3156                
3157            case TX_NEVER:
3158                if ( isNullTx || status != Status.STATUS_NO_TRANSACTION )
3159                    throw new EJBException(
3160                        "EJB cannot be invoked in global transaction");
3161                
3162                else { // we need to invoke the EJB with no Tx.
3163
checkUnfinishedTx(prevTx, inv);
3164                    if ( isEntity )
3165                        preInvokeNoTx(inv);
3166                }
3167                break;
3168                
3169            default:
3170                throw new EJBException("Bad transaction attribute");
3171        }
3172    }
3173    
3174    
3175    // Called before invoking a bean with no Tx or with a new Tx.
3176
// Check if the bean is associated with an unfinished tx.
3177
private void checkUnfinishedTx(Transaction prevTx, Invocation inv) {
3178        try {
3179            if ( !isMessageDriven && !isStatelessSession && prevTx != null &&
3180                prevTx.getStatus() != Status.STATUS_NO_TRANSACTION ) {
3181                // An unfinished tx exists for the bean.
3182
// so we cannot invoke the bean with no Tx or a new Tx.
3183
throw new IllegalStateException JavaDoc(
3184                    "Bean is associated with a different unfinished transaction");
3185            }
3186        } catch (SystemException ex) {
3187            _logger.log(Level.FINE, "ejb.checkUnfinishedTx_exception", ex);
3188            throw new EJBException(ex);
3189        }
3190    }
3191    
3192    
3193    private void startNewTx(Transaction prevTx, Invocation inv)
3194        throws Exception JavaDoc
3195    {
3196        checkUnfinishedTx(prevTx, inv);
3197        
3198        if (cmtTimeoutInSeconds > 0) {
3199            transactionManager.begin(cmtTimeoutInSeconds);
3200        } else {
3201            transactionManager.begin();
3202        }
3203        
3204        EJBContextImpl context = (EJBContextImpl)inv.context;
3205        Transaction tx = transactionManager.getTransaction();
3206        context.setTransaction(tx);
3207        
3208        // This allows the TM to enlist resources used by the EJB
3209
// with the transaction
3210
transactionManager.enlistComponentResources();
3211        
3212        // register synchronization for methods other than finders/home methods
3213
Method method = inv.method;
3214        if ( !inv.invocationInfo.isHomeFinder ) {
3215            // Register for Synchronization notification
3216
containerFactory.getContainerSync(tx).addBean(context);
3217        }
3218        
3219        // Call afterBegin/ejbLoad. If ejbLoad throws exceptions,
3220
// the completeNewTx machinery called by postInvokeTx
3221
// will rollback the tx. Since we have already registered
3222
// a Synchronization object with the TM, the afterCompletion
3223
// will get called.
3224
afterBegin(context);
3225    }
3226    
3227    // Called from preInvokeTx before invoking the bean with the client's Tx
3228
// Also called from EntityContainer.removeBean for cascaded deletes
3229
protected void useClientTx(Transaction prevTx, Invocation inv) {
3230        Transaction clientTx;
3231        int status=-1;
3232        int prevStatus=-1;
3233        try {
3234            // Note: inv.clientTx will not be set at this point.
3235
clientTx = transactionManager.getTransaction();
3236            status = clientTx.getStatus(); // clientTx cant be null
3237
if ( prevTx != null )
3238                prevStatus = prevTx.getStatus();
3239        } catch (Exception JavaDoc ex) {
3240            try {
3241                transactionManager.setRollbackOnly();
3242            } catch ( Exception JavaDoc e ) {
3243                //FIXME: Use LogStrings.properties
3244
_logger.log(Level.FINEST, "", e);
3245            }
3246            throw new TransactionRolledbackLocalException("", ex);
3247        }
3248        
3249        // If the client's tx is going to rollback, it is fruitless
3250
// to invoke the EJB, so throw an exception back to client.
3251
if ( status == Status.STATUS_MARKED_ROLLBACK
3252        || status == Status.STATUS_ROLLEDBACK
3253        || status == Status.STATUS_ROLLING_BACK )
3254            throw new TransactionRolledbackLocalException(
3255                "Client's transaction aborted");
3256        
3257
3258        if( isStatefulSession ) {
3259
3260            SessionContextImpl sessionCtx = (SessionContextImpl) inv.context;
3261            Map<EntityManagerFactory, EntityManager> entityManagerMap =
3262                sessionCtx.getExtendedEntityManagerMap();
3263
3264            J2EETransaction clientJ2EETx = (J2EETransaction) clientTx;
3265            for(EntityManagerFactory emf : entityManagerMap.keySet()) {
3266
3267                // Make sure there is no Transactional persistence context
3268
// for the same EntityManagerFactory as this SFSB's
3269
// Extended persistence context for the propagated transaction.
3270
if( clientJ2EETx.getTxEntityManager(emf) != null ) {
3271                    throw new EJBException("There is an active transactional persistence context for the same EntityManagerFactory as the current stateful session bean's extended persistence context");
3272                }
3273
3274                // Now see if there's already a *different* extended
3275
// persistence context within this transaction for the
3276
// same EntityManagerFactory.
3277
EntityManager em = clientJ2EETx.getExtendedEntityManager(emf);
3278                if( (em != null) && entityManagerMap.get(emf) != em ) {
3279                    throw new EJBException("Detected two different extended persistence contexts for the same EntityManagerFactory within a transaction");
3280                }
3281
3282            }
3283            
3284        }
3285
3286        if ( prevTx == null
3287        || prevStatus == Status.STATUS_NO_TRANSACTION ) {
3288            // First time the bean is running in this new client Tx
3289
EJBContextImpl context = (EJBContextImpl)inv.context;
3290            context.setTransaction(clientTx);
3291            try {
3292                transactionManager.enlistComponentResources();
3293                
3294                if ( !isStatelessSession && !isMessageDriven) {
3295                    // Create a Synchronization object.
3296

3297                    // Not needed for stateless beans or message-driven beans
3298
// because they cant have Synchronization callbacks,
3299
// and they cant be associated with a tx across
3300
// invocations.
3301
// Register sync for methods other than finders/home methods
3302
Method method = inv.method;
3303                    if ( !inv.invocationInfo.isHomeFinder ) {
3304                        containerFactory.getContainerSync(clientTx).addBean(
3305                        context);
3306                    }
3307                    
3308                    afterBegin(context);
3309                }
3310            } catch (Exception JavaDoc ex) {
3311                try {
3312                    transactionManager.setRollbackOnly();
3313                } catch ( Exception JavaDoc e ) {
3314                    //FIXME: Use LogStrings.properties
3315
_logger.log(Level.FINEST, "", e);
3316                }
3317                throw new TransactionRolledbackLocalException("", ex);
3318            }
3319        }
3320        else { // Bean already has a transaction associated with it.
3321
if ( !prevTx.equals(clientTx) ) {
3322                // There is already a different Tx in progress !!
3323
// Note: this can only happen for stateful SessionBeans.
3324
// EntityBeans will get a different context for every Tx.
3325
if ( isSession ) {
3326                    // Row 2 in Table E
3327
throw new IllegalStateException JavaDoc(
3328                    "EJB is already associated with an incomplete transaction");
3329                }
3330            }
3331            else { // Bean was invoked again with the same transaction
3332
// This allows the TM to enlist resources used by the EJB
3333
// with the transaction
3334
try {
3335                    transactionManager.enlistComponentResources();
3336                } catch (Exception JavaDoc ex) {
3337                    try {
3338                        transactionManager.setRollbackOnly();
3339                    } catch ( Exception JavaDoc e ) {
3340                        //FIXME: Use LogStrings.properties
3341
_logger.log(Level.FINEST, "", e);
3342                    }
3343                    throw new TransactionRolledbackLocalException("", ex);
3344                }
3345            }
3346        }
3347    }
3348    
3349    
3350    /**
3351     * postInvokeTx is called after every invocation on the EJB instance,
3352     * including ejbCreate/ejbFind---/ejbRemove.
3353     * NOTE: postInvokeTx is called even if the EJB was not invoked
3354     * because of an exception thrown from preInvokeTx.
3355     */

3356    public void postInvokeTx(Invocation inv)
3357        throws Exception JavaDoc
3358    {
3359        Method method = inv.method;
3360        InvocationInfo invInfo = inv.invocationInfo;
3361        Throwable JavaDoc exception = inv.exception;
3362        
3363        // For SessionBeans, ejbCreate/ejbRemove was called without a Tx,
3364
// so resume client's Tx if needed.
3365
// For EntityBeans, ejbCreate/ejbRemove/ejbFind must be called with a Tx
3366
// so no special processing needed.
3367
if ( isSession && !invInfo.isBusinessMethod ) {
3368            // check if there was a suspended client Tx
3369
if ( inv.clientTx != null )
3370                transactionManager.resume(inv.clientTx);
3371            
3372            if ( exception != null
3373                 && exception instanceof PreInvokeException ) {
3374                inv.exception = ((PreInvokeException)exception).exception;
3375            }
3376            
3377            return;
3378        }
3379        
3380        EJBContextImpl context = (EJBContextImpl)inv.context;
3381        
3382        int status = transactionManager.getStatus();
3383        int txAttr = inv.invocationInfo.txAttr;
3384        
3385        Throwable JavaDoc newException = exception; // default
3386

3387        // Note: inv.exception may have been thrown by the container
3388
// during preInvoke (i.e. bean may never have been invoked).
3389

3390        // Exception and Tx handling rules. See EJB2.0 Sections 17.6, 18.3.
3391
switch (txAttr) {
3392            case TX_BEAN_MANAGED:
3393                // EJB2.0 section 18.3.1, Table 16
3394
// Note: only SessionBeans can be TX_BEAN_MANAGED
3395
newException = checkExceptionBeanMgTx(context, exception,
3396                status);
3397                if ( inv.clientTx != null ) {
3398                    // there was a client Tx which was suspended
3399
transactionManager.resume(inv.clientTx);
3400                }
3401                break;
3402                
3403            case TX_NOT_SUPPORTED:
3404            case TX_NEVER:
3405                // NotSupported and Never are handled in the same way
3406
// EJB2.0 sections 17.6.2.1, 17.6.2.6.
3407
// EJB executed in no Tx
3408
if ( exception != null )
3409                    newException = checkExceptionNoTx(context, exception);
3410                if ( isEntity )
3411                    postInvokeNoTx(inv);
3412                
3413                if ( inv.clientTx != null ) {
3414                    // there was a client Tx which was suspended
3415
transactionManager.resume(inv.clientTx);
3416                }
3417                
3418                break;
3419                
3420            case TX_MANDATORY:
3421                // EJB2.0 section 18.3.1, Table 15
3422
// EJB executed in client's Tx
3423
if ( exception != null )
3424                    newException = checkExceptionClientTx(context, exception);
3425                break;
3426                
3427            case TX_REQUIRED:
3428                // EJB2.0 section 18.3.1, Table 15
3429
if ( inv.clientTx == null ) {
3430                    // EJB executed in new Tx started in preInvokeTx
3431
newException = completeNewTx(context, exception);
3432                }
3433                else {
3434                    // EJB executed in client's tx
3435
if ( exception != null ) {
3436                        newException = checkExceptionClientTx(context,
3437                        exception);
3438                    }
3439                }
3440                break;
3441                
3442            case TX_REQUIRES_NEW:
3443                // EJB2.0 section 18.3.1, Table 15
3444
// EJB executed in new Tx started in preInvokeTx
3445
newException = completeNewTx(context, exception);
3446                
3447                if ( inv.clientTx != null ) {
3448                    // there was a client Tx which was suspended
3449
transactionManager.resume(inv.clientTx);
3450                }
3451                break;
3452                
3453            case TX_SUPPORTS:
3454                // EJB2.0 section 18.3.1, Table 15
3455
if ( status != Status.STATUS_NO_TRANSACTION ) {
3456                    // EJB executed in client's tx
3457
if ( exception != null ) {
3458                        newException = checkExceptionClientTx(context,
3459                        exception);
3460                    }
3461                }
3462                else {
3463                    // EJB executed in no Tx
3464
if ( exception != null )
3465                        newException = checkExceptionNoTx(context, exception);
3466                    if ( isEntity )
3467                        postInvokeNoTx(inv);
3468                }
3469                break;
3470                
3471            default:
3472        }
3473        
3474        inv.exception = newException;
3475        
3476        // XXX If any of the TM commit/rollback/suspend calls throws an
3477
// exception, should the transaction be rolled back if not already so ?
3478
}
3479    
3480    
3481    private Throwable JavaDoc checkExceptionBeanMgTx(EJBContextImpl context,
3482            Throwable JavaDoc exception, int status)
3483        throws Exception JavaDoc
3484    {
3485        Throwable JavaDoc newException = exception;
3486        // EJB2.0 section 18.3.1, Table 16
3487
if ( exception != null
3488        && exception instanceof PreInvokeException ) {
3489            // A PreInvokeException was thrown, so bean was not invoked
3490
newException= ((PreInvokeException)exception).exception;
3491        }
3492        else if ( status == Status.STATUS_NO_TRANSACTION ) {
3493            // EJB was invoked, EJB's Tx is complete.
3494
if ( exception != null )
3495                newException = checkExceptionNoTx(context, exception);
3496        }
3497        else {
3498            // EJB was invoked, EJB's Tx is incomplete.
3499
// See EJB2.0 Section 17.6.1
3500
if ( isSession && !isStatelessSession ) {
3501                if ( !isSystemUncheckedException(exception) ) {
3502                    if( isAppExceptionRequiringRollback(exception) ) {
3503                        transactionManager.rollback();
3504                    } else {
3505                        transactionManager.suspend();
3506                    }
3507                }
3508                else {
3509                    // system/unchecked exception was thrown by EJB
3510
try {
3511                        forceDestroyBean(context);
3512                    } finally {
3513                        transactionManager.rollback();
3514                    }
3515                    newException = processSystemException(exception);
3516                }
3517            }
3518            else if( isStatelessSession ) { // stateless SessionBean
3519
try {
3520                    forceDestroyBean(context);
3521                } finally {
3522                    transactionManager.rollback();
3523                }
3524                newException = new EJBException(
3525                    "Stateless SessionBean method returned without" +
3526                    " completing transaction");
3527                _logger.log(Level.FINE,
3528                    "ejb.incomplete_sessionbean_txn_exception",logParams);
3529                _logger.log(Level.FINE,"",newException);
3530            }
3531            else { // MessageDrivenBean
3532
try {
3533                    forceDestroyBean(context);
3534                } finally {
3535                    transactionManager.rollback();
3536                }
3537                newException = new EJBException(
3538                    "MessageDrivenBean method returned without" +
3539                    " completing transaction");
3540                _logger.log(Level.FINE,
3541                    "ejb.incomplete_msgdrivenbean_txn_exception",logParams);
3542                _logger.log(Level.FINE,"",newException.toString());
3543                
3544            }
3545        }
3546        return newException;
3547    }
3548    
3549    private Throwable JavaDoc checkExceptionNoTx(EJBContextImpl context,
3550        Throwable JavaDoc exception)
3551        throws Exception JavaDoc
3552    {
3553        if ( exception instanceof PreInvokeException )
3554            // A PreInvokeException was thrown, so bean was not invoked
3555
return ((PreInvokeException)exception).exception;
3556        
3557        // If PreInvokeException was not thrown, EJB was invoked with no Tx
3558
Throwable JavaDoc newException = exception;
3559        if ( isSystemUncheckedException(exception) ) {
3560            // Table 15, EJB2.0
3561
newException = processSystemException(exception);
3562            forceDestroyBean(context);
3563        }
3564        return newException;
3565    }
3566    
3567    // this is the counterpart of useClientTx
3568
// Called from postInvokeTx after invoking the bean with the client's Tx
3569
// Also called from EntityContainer.removeBean for cascaded deletes
3570
protected Throwable JavaDoc checkExceptionClientTx(EJBContextImpl context,
3571        Throwable JavaDoc exception)
3572        throws Exception JavaDoc
3573    {
3574        if ( exception instanceof PreInvokeException )
3575            // A PreInvokeException was thrown, so bean was not invoked
3576
return ((PreInvokeException)exception).exception;
3577        
3578        // If PreInvokeException wasn't thrown, EJB was invoked with client's Tx
3579
Throwable JavaDoc newException = exception;
3580        if ( isSystemUncheckedException(exception) ) {
3581            // Table 15, EJB2.0
3582
try {
3583                forceDestroyBean(context);
3584            } finally {
3585                transactionManager.setRollbackOnly();
3586            }
3587            if ( exception instanceof Exception JavaDoc ) {
3588                newException = new TransactionRolledbackLocalException(
3589                    "Exception thrown from bean", (Exception JavaDoc)exception);
3590            } else {
3591                newException = new TransactionRolledbackLocalException(
3592                    "Exception thrown from bean: "+exception.toString());
3593                newException.initCause(exception);
3594            }
3595        } else if( isAppExceptionRequiringRollback(exception ) ) {
3596            transactionManager.setRollbackOnly();
3597        }
3598
3599        return newException;
3600    }
3601    
3602    // this is the counterpart of startNewTx
3603
private Throwable JavaDoc completeNewTx(EJBContextImpl context, Throwable JavaDoc exception)
3604        throws Exception JavaDoc
3605    {
3606        Throwable JavaDoc newException = exception;
3607        if ( exception instanceof PreInvokeException )
3608            newException = ((PreInvokeException)exception).exception;
3609        
3610        int status = transactionManager.getStatus();
3611        if ( status == Status.STATUS_NO_TRANSACTION ) {
3612            // no tx was started, probably an exception was thrown
3613
// before tm.begin() was called
3614
return newException;
3615        }
3616        
3617        if ( isSession && !isStatelessSession )
3618            ((SessionContextImpl)context).setTxCompleting(true);
3619        
3620        // A new tx was started, so we must commit/rollback
3621
if ( newException != null
3622        && isSystemUncheckedException(newException) ) {
3623            // EJB2.0 section 18.3.1, Table 15
3624
// Rollback the Tx we started
3625
try {
3626                forceDestroyBean(context);
3627            } finally {
3628                transactionManager.rollback();
3629            }
3630            newException = processSystemException(newException);
3631        }
3632        else {
3633            try {
3634                if ( status == Status.STATUS_MARKED_ROLLBACK ) {
3635                    // EJB2.0 section 18.3.1, Table 15, and 18.3.6:
3636
// rollback tx, no exception
3637
if (transactionManager.isTimedOut()) {
3638                        _logger.log(Level.WARNING, "ejb.tx_timeout",
3639                                    new Object JavaDoc[] {
3640                            transactionManager.getTransaction(),
3641                                ejbDescriptor.getName()});
3642                    }
3643                    transactionManager.rollback();
3644                }
3645                else {
3646                    if( (newException != null) &&
3647                        isAppExceptionRequiringRollback(newException) ) {
3648                        transactionManager.rollback();
3649                    } else {
3650                        // Note: if exception is an application exception
3651
// we do a commit as in EJB2.0 Section 18.3.1,
3652
// Table 15. Commit the Tx we started
3653
transactionManager.commit();
3654                    }
3655                }
3656            } catch (RollbackException ex) {
3657                _logger.log(Level.FINE, "ejb.transaction_abort_exception", ex);
3658                // EJB2.0 section 18.3.6
3659
newException = new EJBException("Transaction aborted", ex);
3660            } catch ( Exception JavaDoc ex ) {
3661                _logger.log(Level.FINE, "ejb.cmt_exception", ex);
3662                // Commit or rollback failed.
3663
// EJB2.0 section 18.3.6
3664
newException = new EJBException("Unable to complete" +
3665                    " container-managed transaction.", ex);
3666            }
3667        }
3668        return newException;
3669    }
3670    
3671    
3672    
3673    // Implementation of Container method.
3674
// Called from UserTransactionImpl after the EJB started a Tx,
3675
// for TX_BEAN_MANAGED EJBs only.
3676
public final void doAfterBegin(ComponentInvocation ci) {
3677        Invocation inv = (Invocation)ci;
3678        try {
3679            // Associate the context with tx so that on subsequent
3680
// invocations with the same tx, we can do the appropriate
3681
// tx.resume etc.
3682
EJBContextImpl sc = (EJBContextImpl)inv.context;
3683            Transaction tx = transactionManager.getTransaction();
3684            sc.setTransaction(tx);
3685            
3686            // Register Synchronization with TM so that we can
3687
// dissociate the context from tx in afterCompletion
3688
containerFactory.getContainerSync(tx).addBean(sc);
3689            
3690            enlistExtendedEntityManagers(sc);
3691            // Dont call container.afterBegin() because
3692
// TX_BEAN_MANAGED EntityBeans are not allowed,
3693
// and SessionSync calls on TX_BEAN_MANAGED SessionBeans
3694
// are not allowed.
3695
} catch (SystemException ex) {
3696            throw new EJBException(ex);
3697        } catch (RollbackException ex) {
3698            throw new EJBException(ex);
3699        } catch (IllegalStateException JavaDoc ex) {
3700            throw new EJBException(ex);
3701        }
3702    }
3703    
3704    // internal APIs, called from ContainerSync, implemented in subclasses
3705
abstract void afterBegin(EJBContextImpl context);
3706    abstract void beforeCompletion(EJBContextImpl context);
3707    abstract void afterCompletion(EJBContextImpl context, int status);
3708    
3709    void preInvokeNoTx(Invocation inv) {
3710        throw new EJBException(
3711            "Internal Error: BaseContainer.preInvokeNoTx called");
3712    }
3713    
3714    void postInvokeNoTx(Invocation inv) {
3715        throw new EJBException(
3716            "Internal Error: BaseContainer.postInvokeNoTx called");
3717    }
3718    
3719    private Throwable JavaDoc processSystemException(Throwable JavaDoc sysEx) {
3720        Throwable JavaDoc newException;
3721        if ( sysEx instanceof EJBException)
3722            return sysEx;
3723        
3724        // EJB2.0 section 18.3.4
3725
if ( sysEx instanceof NoSuchEntityException ) { // for EntityBeans only
3726
newException = new NoSuchObjectLocalException
3727                ("NoSuchEntityException thrown by EJB method.");
3728            newException.initCause(sysEx);
3729        } else {
3730            newException = new EJBException();
3731            newException.initCause(sysEx);
3732        }
3733
3734        return newException;
3735    }
3736    
3737    protected boolean isApplicationException(Throwable JavaDoc exception) {
3738        return !isSystemUncheckedException(exception);
3739    }
3740
3741    protected boolean isSystemUncheckedException(Throwable JavaDoc exception) {
3742        if ( exception != null &&
3743             ( exception instanceof RuntimeException JavaDoc
3744               || exception instanceof Error JavaDoc
3745               || exception instanceof RemoteException JavaDoc ) ) {
3746
3747            String JavaDoc exceptionClassName = exception.getClass().getName();
3748            for(EjbApplicationExceptionInfo excepInfo : ejbDescriptor.
3749                    getEjbBundleDescriptor().getApplicationExceptions()) {
3750                if( exceptionClassName.equals
3751                    (excepInfo.getExceptionClassName()) ) {
3752                    return false;
3753                }
3754            }
3755
3756            return true;
3757        } else {
3758            return false;
3759        }
3760    }
3761
3762    /**
3763     * Returns true if this exception is an Application Exception and
3764     * it requires rollback of the transaction in which it was thrown.
3765     */

3766    protected boolean isAppExceptionRequiringRollback
3767        (Throwable JavaDoc exception) {
3768
3769        boolean appExceptionRequiringRollback = false;
3770
3771        if ( exception != null ) {
3772
3773            String JavaDoc exceptionClassName = exception.getClass().getName();
3774            for(EjbApplicationExceptionInfo excepInfo : ejbDescriptor.
3775                    getEjbBundleDescriptor().getApplicationExceptions()) {
3776                if( exceptionClassName.equals
3777                    (excepInfo.getExceptionClassName()) ) {
3778                    appExceptionRequiringRollback = excepInfo.getRollback();
3779                }
3780            }
3781        }
3782
3783        return appExceptionRequiringRollback;
3784    }
3785    
3786    public void setMonitorOn(boolean flag) {
3787        monitorOn = flag;
3788    }
3789    
3790    public boolean getDebugMonitorFlag() {
3791        return debugMonitorFlag;
3792    }
3793    
3794    public void setDebugMonitorFlag(boolean flag) {
3795        debugMonitorFlag = flag;
3796    }
3797    
3798    protected static final String JavaDoc containerStateToString(int state) {
3799        switch (state) {
3800            case CONTAINER_INITIALIZING:
3801                return "Initializing";
3802            case CONTAINER_STARTED:
3803                return "Started";
3804            case CONTAINER_STOPPED:
3805                return "STOPPED";
3806            case CONTAINER_UNDEPLOYED:
3807                return "Undeployed";
3808            case CONTAINER_ON_HOLD:
3809                return "ON_HOLD";
3810        }
3811        return "Unknown Container state: " + state;
3812    }
3813
3814    protected final boolean isRemoteInterfaceSupported() {
3815        return hasRemoteHomeView;
3816    }
3817
3818    protected final boolean isLocalInterfaceSupported() {
3819        return hasLocalHomeView;
3820    }
3821    
3822
3823    /**
3824     * Called from various places within the container that are responsible
3825     * for dispatching invocations to business methods. This method has
3826     * the exception semantics of Method.invoke(). Any exception that
3827     * originated from the business method or application code within an
3828     * interceptor will be propagated as the cause within an
3829     * InvocationTargetException.
3830     *
3831     */

3832    Object JavaDoc intercept(Invocation inv)
3833        throws Throwable JavaDoc
3834    {
3835        Object JavaDoc result = null;
3836        if (interceptorManager.hasInterceptors()) {
3837            try {
3838                onEjbMethodStart();
3839                result = interceptorManager.intercept(inv);
3840            } catch(Throwable JavaDoc t) {
3841                inv.exception = t;
3842                throw new InvocationTargetException(t);
3843            } finally {
3844                onEjbMethodEnd();
3845            }
3846        } else { // invoke() has the same exc. semantics as Method.invoke
3847
result = this.invokeTargetBeanMethod(inv.getBeanMethod(), inv, inv.ejb,
3848                    inv.methodParams, null);
3849        }
3850        
3851        return result;
3852    }
3853    
3854    /**
3855     * Called from Interceptor Chain to invoke the actual bean method.
3856     * This method must throw any exception from the bean method *as is*,
3857     * without being wrapped in an InvocationTargetException. The exception
3858     * thrown from this method will be propagated through the application's
3859     * interceptor code, so it must not be changed in order for any exception
3860     * handling logic in that code to function properly.
3861     */

3862    public Object JavaDoc invokeBeanMethod(Invocation inv)
3863        throws Throwable JavaDoc
3864    {
3865        try {
3866            return SecurityUtil.invoke(inv.getBeanMethod(), inv, inv.ejb,
3867                                       inv.getParameters(), this, null);
3868        } catch(InvocationTargetException ite) {
3869            throw ite.getCause();
3870        }
3871    }
3872    
3873
3874    public long getCreateCount() {
3875    return statCreateCount;
3876    }
3877
3878    public long getRemoveCount() {
3879    return statRemoveCount;
3880    }
3881
3882    protected void createMonitoringRegistryMediator() {
3883    String JavaDoc appName = null;
3884    String JavaDoc modName = null;
3885    String JavaDoc ejbName = null;
3886    try {
3887        appName = (ejbDescriptor.getApplication().isVirtual())
3888        ? null: ejbDescriptor.getApplication().getRegistrationName();
3889        if (appName == null) {
3890        modName = ejbDescriptor.getApplication().getRegistrationName();
3891        } else {
3892        String JavaDoc archiveuri = ejbDescriptor.getEjbBundleDescriptor().
3893            getModuleDescriptor().getArchiveUri();
3894        modName =
3895            com.sun.enterprise.util.io.FileUtils.makeFriendlyFilename(archiveuri);
3896        }
3897        ejbName = ejbDescriptor.getName();
3898        this.registryMediator =
3899        new MonitoringRegistryMediator(ejbName, modName, appName);
3900    
3901        this.ejbMethodStatsManager = registryMediator.getEJBMethodStatsManager();
3902        _logger.log(Level.FINE, "Created MonitoringRegistryMediator: appName: "
3903                + appName + "; modName: " + modName + "; ejbName: " + ejbName);
3904    } catch (Exception JavaDoc ex) {
3905        _logger.log(Level.SEVERE, "[**BaseContainer**] Could not create MonitorRegistryMediator. appName: " + appName + "; modName: " + modName + "; ejbName: " + ejbName, ex);
3906        
3907    }
3908    }
3909
3910    protected void populateMethodMonitorMap() {
3911    Vector methodVec = ejbDescriptor.getMethods();
3912    int sz = methodVec.size();
3913    Method[] methods = new Method[sz];
3914    for (int i=0; i<sz; i++) {
3915        methods[i] = (Method) methodVec.get(i);
3916    }
3917
3918    populateMethodMonitorMap(methods);
3919    }
3920
3921    protected void populateMethodMonitorMap(Method[] methods) {
3922    /*
3923    methodMonitorMap = new HashMap();
3924    MethodMonitor[] methodMonitors = new MethodMonitor[methods.length];
3925    for (int i=0; i<methods.length; i++ ) {
3926        methodMonitors[i] = new MethodMonitor(methods[i]);
3927        methodMonitorMap.put(methods[i], methodMonitors[i]);
3928    }
3929    
3930    registryMediator.registerProvider(methodMonitors);
3931    */

3932    registryMediator.registerEJBMethods(methods);
3933    _logger.log(Level.FINE, "[Basecontainer] Registered Method Monitors");
3934    }
3935
3936    void logMonitoredComponentsData() {
3937    registryMediator.logMonitoredComponentsData(
3938        _logger.isLoggable(Level.FINE));
3939    }
3940
3941    protected void doFlush( Invocation inv ) {
3942    }
3943
3944    protected void registerMonitorableComponents() {
3945        registerTimerMonitorableComponent();
3946    }
3947
3948    protected void registerTimerMonitorableComponent() {
3949        if( isTimedObject() ) {
3950            toMonitorProps = new TimedObjectMonitorableProperties();
3951        registryMediator.registerProvider( toMonitorProps );
3952    }
3953        _logger.log(Level.FINE, "[BaseContainer] registered timer monitorable");
3954    }
3955
3956    protected void incrementCreatedTimedObject() {
3957        toMonitorProps.incrementTimersCreated();
3958    }
3959
3960    protected void incrementRemovedTimedObject() {
3961        toMonitorProps.incrementTimersRemoved();
3962    }
3963
3964    protected void incrementDeliveredTimedObject() {
3965        toMonitorProps.incrementTimersDelivered();
3966    }
3967
3968} //BaseContainer{}
3969

3970final class CallFlowInfoImpl
3971    implements CallFlowInfo
3972{
3973    
3974    private final BaseContainer container;
3975    
3976    private final EjbDescriptor ejbDescriptor;
3977    
3978    private final String JavaDoc appName;
3979    
3980    private final String JavaDoc modName;
3981    
3982    private final String JavaDoc ejbName;
3983    
3984    private final ComponentType componentType;
3985    
3986    private final InvocationManager invocationManager;
3987    
3988    private final J2EETransactionManager transactionManager;
3989    
3990    CallFlowInfoImpl(BaseContainer container, EjbDescriptor descriptor,
3991            ComponentType compType) {
3992        this.container = container;
3993        this.ejbDescriptor = descriptor;
3994        
3995        this.appName = (ejbDescriptor.getApplication().isVirtual()) ? null
3996                : ejbDescriptor.getApplication().getRegistrationName();
3997        String JavaDoc archiveuri = ejbDescriptor.getEjbBundleDescriptor()
3998                .getModuleDescriptor().getArchiveUri();
3999        this.modName = com.sun.enterprise.util.io.FileUtils
4000                .makeFriendlyFilename(archiveuri);
4001        this.ejbName = ejbDescriptor.getName();
4002        
4003        this.componentType = compType;
4004        
4005        this.invocationManager = Switch.getSwitch().getInvocationManager();
4006        
4007        this.transactionManager = Switch.getSwitch().getTransactionManager();
4008    }
4009    
4010    public String JavaDoc getApplicationName() {
4011        return appName;
4012    }
4013    
4014    public String JavaDoc getModuleName() {
4015        return modName;
4016    }
4017    
4018    public String JavaDoc getComponentName() {
4019        return ejbName;
4020    }
4021    
4022    public ComponentType getComponentType() {
4023        return componentType;
4024    }
4025    
4026    public java.lang.reflect.Method JavaDoc getMethod() {
4027        Invocation inv = (Invocation)
4028            invocationManager.getCurrentInvocation();
4029        
4030        return inv.method;
4031    }
4032    
4033    public String JavaDoc getTransactionId() {
4034        com.sun.enterprise.distributedtx.J2EETransaction tx = null;
4035        try {
4036            tx = ((com.sun.enterprise.distributedtx.J2EETransaction)
4037                (transactionManager.getTransaction()));
4038        } catch (Exception JavaDoc ex) {
4039            //TODO: Log exception
4040
}
4041        
4042        return (tx == null) ? null : tx.getTransactionId();
4043    }
4044    
4045    public String JavaDoc getCallerPrincipal() {
4046        java.security.Principal JavaDoc principal =
4047                container.getSecurityManager().getCallerPrincipal();
4048        
4049        return (principal != null) ? principal.getName() : null;
4050    }
4051    
4052    public Throwable JavaDoc getException() {
4053        return ((Invocation) invocationManager.getCurrentInvocation()).exception;
4054    }
4055}
4056final class RemoteBusinessIntfInfo {
4057
4058    Class JavaDoc generatedRemoteIntf;
4059    Class JavaDoc remoteBusinessIntf;
4060    String JavaDoc jndiName;
4061    RemoteReferenceFactory referenceFactory;
4062    Class JavaDoc proxyClass;
4063    Constructor proxyCtor;
4064
4065}
4066
4067/**
4068 * PreInvokeException is used to wrap exceptions thrown
4069 * from BaseContainer.preInvoke, so it indicates that the bean's
4070 * method will not be called.
4071 */

4072final class PreInvokeException extends EJBException {
4073    
4074    Exception JavaDoc exception;
4075    
4076    PreInvokeException(Exception JavaDoc ex) {
4077        this.exception = ex;
4078    }
4079} //PreInvokeException{}
4080

4081final class SafeProperties extends Properties {
4082    private static final String JavaDoc errstr =
4083        "Environment properties cannot be modified";
4084    private static final String JavaDoc ejb10Prefix = "ejb10-properties/";
4085    
4086    public void load(java.io.InputStream JavaDoc inStream) {
4087        throw new RuntimeException JavaDoc(errstr);
4088    }
4089    public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
4090        throw new RuntimeException JavaDoc(errstr);
4091    }
4092    public void putAll(Map t) {
4093        throw new RuntimeException JavaDoc(errstr);
4094    }
4095    public Object JavaDoc remove(Object JavaDoc key) {
4096        throw new RuntimeException JavaDoc(errstr);
4097    }
4098    public void clear() {
4099        throw new RuntimeException JavaDoc(errstr);
4100    }
4101    void copy(Set s) {
4102        Iterator i = s.iterator();
4103        defaults = new Properties();
4104        while ( i.hasNext() ) {
4105            EnvironmentProperty p = (EnvironmentProperty)i.next();
4106            if ( p.getName().startsWith(ejb10Prefix) ) {
4107                String JavaDoc newName = p.getName().substring(ejb10Prefix.length());
4108                defaults.put(newName, p.getValue());
4109            }
4110        }
4111    }
4112    
4113    private void readObject(java.io.ObjectInputStream JavaDoc stream)
4114        throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc
4115    {
4116        defaults = (Properties)stream.readObject();
4117    }
4118    
4119    private void writeObject(java.io.ObjectOutputStream JavaDoc stream)
4120        throws java.io.IOException JavaDoc
4121    {
4122        stream.writeObject(defaults);
4123    }
4124} //SafeProperties{}
4125

4126final class TimedObjectMonitorableProperties
4127    implements com.sun.ejb.spi.stats.EJBTimedObjectStatsProvider
4128    {
4129
4130    long timersCreated = 0;
4131    long timersRemoved = 0;
4132    long timersDelivered = 0;
4133    boolean toMonitor = false;
4134
4135    public TimedObjectMonitorableProperties() {
4136        timersCreated = 0;
4137        timersRemoved = 0;
4138        timersDelivered = 0;
4139        toMonitor = false;
4140    }
4141
4142    public void incrementTimersCreated() {
4143        if( toMonitor ) {
4144            synchronized( this ) {
4145                timersCreated++;
4146            }
4147        }
4148    }
4149
4150    public long getTimersCreated() {
4151        return timersCreated;
4152    }
4153
4154    public void incrementTimersRemoved() {
4155        if( toMonitor ) {
4156            synchronized( this ) {
4157                timersRemoved++;
4158            }
4159        }
4160    }
4161
4162    public long getTimersRemoved() {
4163        return timersRemoved;
4164    }
4165
4166    public void incrementTimersDelivered() {
4167        if( toMonitor ) {
4168            synchronized( this ) {
4169                timersDelivered++;
4170            }
4171        }
4172    }
4173
4174    public long getTimersDelivered() {
4175        return timersDelivered;
4176    }
4177
4178    public void appendStats(StringBuffer JavaDoc sbuf) {
4179    sbuf.append("[Timers: ")
4180        .append("Created=").append(timersCreated).append("; ")
4181        .append("Removed=").append(timersRemoved).append("; ")
4182        .append("Delivered=").append(timersDelivered).append("; ");
4183    sbuf.append("]");
4184    }
4185
4186    public void monitoringLevelChanged( boolean monitoringOn ) {
4187        timersCreated = 0;
4188        timersRemoved = 0;
4189        timersDelivered = 0;
4190        toMonitor = monitoringOn;
4191    }
4192
4193} //TimedObjectMonitorableProperties{}
4194
Popular Tags