KickJava   Java API By Example, From Geeks To Geeks.

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


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: StatelessInstanceManager.java 1096 2004-03-26 21:41:16Z 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.EnterpriseBean JavaDoc;
56 import javax.ejb.SessionBean JavaDoc;
57
58 import org.apache.log4j.Category;
59 import org.openejb.OpenEJBException;
60 import org.openejb.SystemException;
61 import org.openejb.core.DeploymentInfo;
62 import org.openejb.core.EnvProps;
63 import org.openejb.core.Operations;
64 import org.openejb.core.ThreadContext;
65 import org.openejb.util.LinkedListStack;
66 import org.openejb.util.SafeProperties;
67 import org.openejb.util.SafeToolkit;
68 import org.openejb.util.Stack;
69
70 /**
71  * This instance manager has a pool limit for each bean class
72  * the pooling policy applies to how many beans maybe pooled in the method ready; it
73  * will always return a bean instance for every thread (no waiting for available instances).
74  * Instances returning to the pool are removed if pool is already full.
75  *
76  * Automatic pool reduction will require the the ejbRemove method be invoked.
77  * setSessionContext must be done within the instance manager
78  */

79
80 public class StatelessInstanceManager {
81
82     protected java.util.HashMap JavaDoc poolMap = new HashMap JavaDoc();
83     protected int poolLimit = 0;
84     protected int beanCount = 0;
85     protected boolean strictPooling = false;
86     
87     protected PoolQueue poolQueue= null;
88
89     protected final SafeToolkit toolkit = SafeToolkit.getToolkit("StatefulInstanceManager");
90     protected final static Category logger = Category.getInstance("OpenEJB");
91
92     /******************************************************************
93                         CONSTRUCTOR METHODS
94     *******************************************************************/

95     public StatelessInstanceManager( ){
96     }
97
98     public void init(Properties JavaDoc props)
99     throws OpenEJBException{
100
101         
102         SafeProperties safeProps = toolkit.getSafeProperties(props);
103
104         poolLimit = safeProps.getPropertyAsInt(EnvProps.IM_POOL_SIZE, 10);
105         strictPooling = safeProps.getPropertyAsBoolean(EnvProps.IM_STRICT_POOLING,new Boolean JavaDoc(false)).booleanValue();
106         if(strictPooling){
107             int waitTime = safeProps.getPropertyAsInt(EnvProps.IM_TIME_OUT, 0);
108             poolQueue = new PoolQueue(waitTime);
109         }
110     }
111     public EnterpriseBean JavaDoc getInstance(ThreadContext callContext)
112     throws OpenEJBException{
113             SessionBean JavaDoc bean = null;
114             Object JavaDoc deploymentId = callContext.getDeploymentInfo().getDeploymentID();
115             Stack pool = (Stack)poolMap.get(deploymentId);
116             if(pool==null){
117                 pool = new LinkedListStack(poolLimit);
118                 poolMap.put(deploymentId,pool);
119             }else
120                 bean = (SessionBean JavaDoc)pool.pop();
121             
122             // apply strict pooling policy if used. Wait for available instance
123
while(strictPooling && bean == null && pool.size() >= poolLimit){
124                poolQueue.waitForAvailableInstance();
125                bean = (SessionBean JavaDoc)pool.pop();
126             }
127             
128              // If it's a new bean we must call setSessionContext and ejbCreate
129
if(bean==null){
130                 try{
131                 Class JavaDoc beanClass = callContext.getDeploymentInfo().getBeanClass();
132                 bean = (SessionBean JavaDoc)toolkit.newInstance(beanClass);
133                 }catch(OpenEJBException oee){
134                     throw (SystemException)oee;
135                 }
136                     
137                 byte originalOperation = callContext.getCurrentOperation();
138                 try{
139                     // invoke the setSessionContext method
140
callContext.setCurrentOperation(Operations.OP_SET_CONTEXT);
141                     DeploymentInfo deploymentInfo = callContext.getDeploymentInfo();
142                     bean.setSessionContext((javax.ejb.SessionContext JavaDoc)deploymentInfo.getEJBContext());
143                     // invoke the ejbCreate method
144
callContext.setCurrentOperation(Operations.OP_CREATE);
145                     Method JavaDoc createMethod = deploymentInfo.getCreateMethod();
146                     createMethod.invoke(bean, null);
147                 }catch(Throwable JavaDoc e){
148                     if(e instanceof java.lang.reflect.InvocationTargetException JavaDoc) {
149                         e = ((java.lang.reflect.InvocationTargetException JavaDoc)e).getTargetException();
150                     }
151                     String JavaDoc t = "The bean instance "+bean+" threw a system exception:"+e;
152                     logger.error(t, e);
153                     throw new org.openejb.ApplicationException(new RemoteException JavaDoc("Can not obtain a free instance."));
154                 } finally {
155                     callContext.setCurrentOperation( originalOperation );
156                 }
157             }
158             return bean;
159     }
160     public void poolInstance(ThreadContext callContext, EnterpriseBean JavaDoc bean)
161     throws OpenEJBException{
162         if(bean == null)
163             throw new SystemException("Invalid arguments");
164         Object JavaDoc deploymentId = callContext.getDeploymentInfo().getDeploymentID();
165         Stack pool = (Stack)poolMap.get(deploymentId);
166         if(strictPooling){
167             pool.push(bean);
168             poolQueue.notifyWaitingThreads();
169         }else{
170             if(pool.size() > poolLimit)
171                 freeInstance(callContext,bean);
172             else
173                 pool.push(bean);
174         }
175         
176     }
177
178     public void freeInstance(ThreadContext callContext, EnterpriseBean JavaDoc bean){
179         try{
180             callContext.setCurrentOperation(Operations.OP_REMOVE);
181             ((SessionBean JavaDoc)bean).ejbRemove();
182         }catch(Throwable JavaDoc re){
183             // not in client scope, do nothing
184
logger.error("The bean instance "+bean+" threw a system exception:"+re, re);
185         }
186         
187         // allow the bean instance to be GCed.
188
}
189
190     /**
191      * This methods cleans up benas that threw a system exception. EJB 2.0, page 376. note C:
192      * " Discard instance means that the Container must not invoke any business methods
193      * or container callbacks on the instance."
194      */

195     public void discardInstance(ThreadContext callContext, EnterpriseBean JavaDoc bean){
196         // do absolutely nothing here
197
}
198     
199     static class PoolQueue{
200         private final long waitPeriod;
201         public PoolQueue(long time){waitPeriod = time;}
202         public synchronized void waitForAvailableInstance( )
203         throws org.openejb.InvalidateReferenceException{
204             try{
205                 wait(waitPeriod);
206             }catch(InterruptedException JavaDoc ie){
207                 throw new org.openejb.InvalidateReferenceException(new RemoteException JavaDoc("No instance avaiable to service request"));
208             }
209         }
210         public synchronized void notifyWaitingThreads(){
211             notify();
212         }
213     }
214     
215 }
216
Popular Tags