KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openejb > core > stateless > StatelessContainer


1 /**
2  * Redistribution and use of this software and associated documentation
3  * ("Software"), with or without modification, are permitted provided
4  * that the following conditions are met:
5  *
6  * 1. Redistributions of source code must retain copyright
7  * statements and notices. Redistributions must also contain a
8  * copy of this document.
9  *
10  * 2. Redistributions in binary form must reproduce the
11  * above copyright notice, this list of conditions and the
12  * following disclaimer in the documentation and/or other
13  * materials provided with the distribution.
14  *
15  * 3. The name "Exolab" must not be used to endorse or promote
16  * products derived from this Software without prior written
17  * permission of Exoffice Technologies. For written permission,
18  * please contact info@exolab.org.
19  *
20  * 4. Products derived from this Software may not be called "Exolab"
21  * nor may "Exolab" appear in their names without prior written
22  * permission of Exoffice Technologies. Exolab is a registered
23  * trademark of Exoffice Technologies.
24  *
25  * 5. Due credit should be given to the Exolab Project
26  * (http://www.exolab.org/).
27  *
28  * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32  * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39  * OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * Copyright 1999 (C) Exoffice Technologies Inc. All Rights Reserved.
42  *
43  * $Id: StatelessContainer.java 1976 2005-07-06 02:04:04Z dblevins $
44  */

45
46
47 package org.openejb.core.stateless;
48
49
50 import java.lang.reflect.Method JavaDoc;
51 import java.rmi.RemoteException JavaDoc;
52 import java.util.HashMap JavaDoc;
53 import java.util.Properties JavaDoc;
54
55 import javax.ejb.EJBHome JavaDoc;
56 import javax.ejb.EJBLocalHome JavaDoc;
57 import javax.ejb.EJBLocalObject JavaDoc;
58 import javax.ejb.EJBObject JavaDoc;
59 import javax.ejb.EnterpriseBean JavaDoc;
60 import javax.ejb.SessionBean JavaDoc;
61
62 import org.openejb.Container;
63 import org.openejb.DeploymentInfo;
64 import org.openejb.OpenEJB;
65 import org.openejb.OpenEJBException;
66 import org.openejb.ProxyInfo;
67 import org.openejb.core.EnvProps;
68 import org.openejb.core.Operations;
69 import org.openejb.core.ThreadContext;
70 import org.openejb.core.transaction.TransactionContainer;
71 import org.openejb.core.transaction.TransactionContext;
72 import org.openejb.core.transaction.TransactionPolicy;
73 import org.openejb.util.SafeProperties;
74 import org.openejb.util.SafeToolkit;
75
76 /**
77  * Stateless SessionBean container
78  *
79  * @author <a HREF="mailto:Richard@Monson-Haefel.com">Richard Monson-Haefel</a>
80  * @author <a HREF="mailto:david.blevins@visi.com">David Blevins</a>
81  * @version $Revision: 1976 $ $Date: 2005-07-05 19:04:04 -0700 (Tue, 05 Jul 2005) $
82  */

83 public class StatelessContainer implements org.openejb.RpcContainer, TransactionContainer{
84
85     /** managed bean instances; passivation and cache */
86     StatelessInstanceManager instanceManager;
87
88     /** contains deployment information for each by deployed to this container */
89     HashMap JavaDoc deploymentRegistry;
90
91     /** the server unique id for this container */
92     Object JavaDoc containerID = null;
93
94
95     /** manages the transactional scope according to the bean's transaction attributes */
96     //StatelessTransactionScopeHandler txScopeHandle;
97

98
99     /**
100      * Construct this container with the specified container id, deployments, container manager and properties.
101      * The properties can include the class name of the preferred InstanceManager, org.openejb.core.entity.EntityInstanceManager
102      * is the default. The properties should also include the properties for the instance manager.
103      *
104      * @param id the unique id to identify this container in the ContainerSystem
105      * @param registry a hashMap of bean delpoyments that this container will be responsible for
106      * @param properties the properties this container needs to initialize and run
107      * @throws OpenEJBException if there is a problem constructing the container
108      * @see org.openejb.Container
109      */

110     public void init(Object JavaDoc id, HashMap JavaDoc registry, Properties JavaDoc properties)
111     throws org.openejb.OpenEJBException{
112         containerID = id;
113         deploymentRegistry = registry;
114
115         if(properties == null)properties = new Properties JavaDoc();
116
117
118         SafeToolkit toolkit = SafeToolkit.getToolkit("StatelessContainer");
119         SafeProperties safeProps = toolkit.getSafeProperties(properties);
120         try{
121         String JavaDoc className = safeProps.getProperty(EnvProps.IM_CLASS_NAME, "org.openejb.core.stateless.StatelessInstanceManager");
122         ClassLoader JavaDoc cl = OpenEJB.getContextClassLoader();
123         instanceManager =(StatelessInstanceManager)Class.forName(className, true, cl).newInstance();
124         }catch(Exception JavaDoc e){
125         throw new org.openejb.SystemException("Initialization of InstanceManager for the \""+containerID+"\" stateful container failed",e);
126         }
127         instanceManager.init(properties);
128
129
130 // txScopeHandle = new StatelessTransactionScopeHandler(this,instanceManager);
131

132         /*
133         * This block of code is necessary to avoid a chicken and egg problem. The DeploymentInfo
134         * objects must have a reference to their container during this assembly process, but the
135         * container is created after the DeploymentInfo necessitating this loop to assign all
136         * deployment info object's their containers.
137         */

138         org.openejb.DeploymentInfo [] deploys = this.deployments();
139         for(int x = 0; x < deploys.length; x++){
140             org.openejb.core.DeploymentInfo di = (org.openejb.core.DeploymentInfo)deploys[x];
141             di.setContainer(this);
142         }
143
144     }
145
146     //===============================
147
// begin Container Implementation
148
//
149

150     /**
151      * Gets the <code>DeploymentInfo</code> objects for all the beans deployed in this container.
152      *
153      * @return an array of DeploymentInfo objects
154      * @see org.openejb.DeploymentInfo
155      */

156     public DeploymentInfo [] deployments(){
157         return (DeploymentInfo [])deploymentRegistry.values().toArray(new DeploymentInfo[deploymentRegistry.size()]);
158     }
159
160     /**
161      * Gets the <code>DeploymentInfo</code> object for the bean with the specified deployment id.
162      *
163      * @param deploymentID the deployment id of the deployed bean.
164      * @return the DeploymentInfo object associated with the bean.
165      * @see org.openejb.DeploymentInfo
166      * @see org.openejb.DeploymentInfo#getDeploymentID()
167      */

168     public DeploymentInfo getDeploymentInfo(Object JavaDoc deploymentID){
169         return (DeploymentInfo)deploymentRegistry.get(deploymentID);
170     }
171     /**
172      * Gets the type of container (STATELESS, STATEFUL, ENTITY, or MESSAGE_DRIVEN
173      *
174      * @return id type bean container
175      */

176     public int getContainerType( ){
177         return Container.STATELESS;
178     }
179
180     /**
181      * Gets the id of this container.
182      *
183      * @return the id of this container.
184      */

185     public Object JavaDoc getContainerID(){
186         return containerID;
187     }
188
189     /**
190      * Adds a bean to this container.
191      * @param deploymentID the deployment id of the bean to deploy.
192      * @param info the DeploymentInfo object associated with the bean.
193      * @throws org.openejb.OpenEJBException
194      * Occurs when the container is not able to deploy the bean for some
195      * reason.
196      */

197     public void deploy(Object JavaDoc deploymentID, DeploymentInfo info) throws OpenEJBException {
198         HashMap JavaDoc registry = (HashMap JavaDoc)deploymentRegistry.clone();
199         registry.put(deploymentID, info);
200         deploymentRegistry = registry;
201     }
202
203     /**
204      * Invokes a method on an instance of the specified bean deployment.
205      *
206      * @param deployID the dployment id of the bean deployment
207      * @param callMethod the method to be called on the bean instance
208      * @param args the arguments to use when invoking the specified method
209      * @param primKey the primary key class of the bean or null if the bean does not need a primary key
210      * @param securityIdentity identity
211      * @return the result of invoking the specified method on the bean instance
212      * @throws org.openejb.OpenEJBException
213      * @see org.openejb.core.stateful.StatefulContainer#invoke StatefulContainer.invoke
214      */

215     public Object JavaDoc invoke(Object JavaDoc deployID, Method JavaDoc callMethod,Object JavaDoc [] args,Object JavaDoc primKey, Object JavaDoc securityIdentity)
216             throws org.openejb.OpenEJBException {
217         try{
218
219         org.openejb.core.DeploymentInfo deployInfo = (org.openejb.core.DeploymentInfo)this.getDeploymentInfo(deployID);
220
221         ThreadContext callContext = ThreadContext.getThreadContext();
222         callContext.set(deployInfo, primKey, securityIdentity);
223
224         // check authorization to invoke
225

226         boolean authorized = OpenEJB.getSecurityService().isCallerAuthorized(securityIdentity, deployInfo.getAuthorizedRoles(callMethod));
227         if(!authorized)
228             throw new org.openejb.ApplicationException(new RemoteException JavaDoc("Unauthorized Access by Principal Denied"));
229
230         // use special methods for remove and create requests
231
Class JavaDoc declaringClass = callMethod.getDeclaringClass();
232         if(EJBHome JavaDoc.class.isAssignableFrom(declaringClass) || EJBLocalHome JavaDoc.class.isAssignableFrom(declaringClass) ){
233             if(callMethod.getName().equals("create")){
234                 return createEJBObject(deployInfo, callMethod);
235             }else
236                 return null;// EJBHome.remove( ) and other EJBHome methods are not process by the container
237
} else if(EJBObject JavaDoc.class == declaringClass || EJBLocalObject JavaDoc.class == declaringClass) {
238             return null;// EJBObject.remove( ) and other EJBObject methods are not process by the container
239
}
240
241
242         SessionBean JavaDoc bean = null;
243
244         // retreive instance from instance manager
245
bean = (SessionBean JavaDoc)instanceManager.getInstance(callContext);
246
247         // allows the container to know the context of the call to check allowed operations
248
callContext.setCurrentOperation(Operations.OP_BUSINESS);
249
250         // converts a remote interface Method object into its corresponding bean class Method.
251
Method JavaDoc runMethod = deployInfo.getMatchingBeanMethod(callMethod);
252
253         Object JavaDoc retValue = invoke(callMethod, runMethod, args, bean, callContext) ;
254         instanceManager.poolInstance(callContext,bean);
255
256         // see comments in org.openejb.core.DeploymentInfo.
257
return deployInfo.convertIfLocalReference(callMethod, retValue);
258
259         }finally{
260             /*
261                 The thread context must be stripped from the thread before returning or throwing an exception
262                 so that an object outside the container does not have access to a
263                 bean's JNDI ENC. In addition, its important for the
264                 org.openejb.core.ivm.java.javaURLContextFactory, which determines the context
265                 of a JNDI lookup based on the presence of a ThreadContext object. If no ThreadContext
266                 object is available, then the request is assumed to be made from outside the container
267                 system and is given the global OpenEJB JNDI name space instead. If there is a thread context,
268                 then the request is assumed to be made from within the container system and so the
269                 javaContextFactory must return the JNDI ENC of the current enterprise bean which it
270                 obtains from the DeploymentInfo object associated with the current thread context.
271             */

272             ThreadContext.setThreadContext(null);
273         }
274     }
275     //
276
// end ContainerManager Implementation
277
//====================================
278

279
280     //============================================
281
// begin methods unique to this implementation
282
//
283

284     public StatelessInstanceManager getInstanceManager( ){
285         return instanceManager;
286     }
287
288     protected Object JavaDoc invoke(Method JavaDoc callMethod, Method JavaDoc runMethod, Object JavaDoc [] args, EnterpriseBean JavaDoc bean, ThreadContext callContext)
289     throws org.openejb.OpenEJBException{
290
291         TransactionPolicy txPolicy = callContext.getDeploymentInfo().getTransactionPolicy( callMethod );
292         TransactionContext txContext = new TransactionContext();
293         txContext.callContext = callContext;
294
295         //OLD:Transaction originalTx = txScopeHandle.beforeInvoke(callMethod, bean, callContext);
296
txPolicy.beforeInvoke( bean, txContext );
297
298         // txScopeHandler.afterInvoke( ) peformed in the finally clause
299

300         Object JavaDoc returnValue = null;
301         try{
302             // using Java reflection, invoke the method on the bean instance.
303
returnValue = runMethod.invoke(bean, args);
304         }catch(java.lang.reflect.InvocationTargetException JavaDoc ite){// handle exceptions thrown by enterprise bean
305
if ( ite.getTargetException() instanceof RuntimeException JavaDoc ) {
306                 /* System Exception ****************************/
307                 //OLD:txScopeHandle.handleSystemException(callMethod,bean,callContext, originalTx,ite.getTargetException());
308
txPolicy.handleSystemException( ite.getTargetException(), bean, txContext );
309             } else {
310                 /* Application Exception ***********************/
311                 instanceManager.poolInstance(callContext,bean);
312                 //OLD:txScopeHandle.handleApplicationException(callMethod,bean,callContext, originalTx,ite.getTargetException());
313
txPolicy.handleApplicationException( ite.getTargetException(), txContext );
314             }
315         }catch(Throwable JavaDoc re){// handle reflection exception
316
/*
317               Any exception thrown by reflection; not by the enterprise bean. Possible
318               Exceptions are:
319                 IllegalAccessException - if the underlying method is inaccessible.
320                 IllegalArgumentException - if the number of actual and formal parameters differ, or if an unwrapping conversion fails.
321                 NullPointerException - if the specified object is null and the method is an instance method.
322                 ExceptionInInitializerError - if the initialization provoked by this method fails.
323             */

324             txPolicy.handleSystemException( re, bean, txContext );
325         }finally{
326             //OLD:txScopeHandle.afterInvoke(callMethod, bean,callContext, originalTx);
327
txPolicy.afterInvoke( bean, txContext );
328         }
329
330         return returnValue;
331     }
332
333     /**
334     * This method creates a ProxyInfo object for a specific deployment. When a stateless
335     * session bean is created, the container does not need to create an bean instance
336     * because instances are shared and pooled and only delegated to service a request when a call is
337     * received from the client. The ProxyInfo object will allow the server to construct an
338     * appropriate remote reference that the client can use to make calls.
339     */

340     protected ProxyInfo createEJBObject(org.openejb.core.DeploymentInfo deploymentInfo, Method JavaDoc callMethod) {
341         Class JavaDoc callingClass = callMethod.getDeclaringClass();
342         boolean isLocalInterface = EJBLocalHome JavaDoc.class.isAssignableFrom(callingClass);
343         return new ProxyInfo(deploymentInfo, null, isLocalInterface, this);
344     }
345
346     //
347
// end methods unique to this implementation
348
//================================================
349

350     public void discardInstance(EnterpriseBean JavaDoc instance, ThreadContext context) {
351         instanceManager.discardInstance( context, instance );
352     }
353
354 }
355
Popular Tags