KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas_ejb > container > JStatefulFactory


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: JStatefulFactory.java,v 1.22 2005/07/13 06:29:45 durieuxp Exp $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.jonas_ejb.container;
27
28 import java.io.BufferedInputStream JavaDoc;
29 import java.io.BufferedOutputStream JavaDoc;
30 import java.io.File JavaDoc;
31 import java.io.FileInputStream JavaDoc;
32 import java.io.FileNotFoundException JavaDoc;
33 import java.io.FileOutputStream JavaDoc;
34 import java.io.IOException JavaDoc;
35 import java.rmi.RemoteException JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.Iterator JavaDoc;
38
39 import javax.ejb.EJBException JavaDoc;
40 import javax.ejb.SessionBean JavaDoc;
41 import javax.ejb.TimerService JavaDoc;
42
43 import org.objectweb.jonas_ejb.deployment.api.SessionDesc;
44 import org.objectweb.jonas_ejb.deployment.api.SessionStatefulDesc;
45 import org.objectweb.jonas_ejb.lib.EJBInvocation;
46
47 import org.objectweb.util.monolog.api.BasicLevel;
48
49 /**
50  * This class is a factory for a Session Stateful Bean.
51  * @author Philippe Durieux
52  */

53 public class JStatefulFactory extends JSessionFactory {
54
55     /**
56      * List of JStatefulSwitch objects (pool of session instances)
57      * Key is the sessionId
58      */

59     protected HashMap JavaDoc statefulList = new HashMap JavaDoc();
60
61     /**
62      * Current Cache Size
63      */

64     protected int cacheSize = 0;
65
66     /**
67      * Context id (increment counter)
68      */

69     private int sessionCount = 0;
70
71     /**
72      * constructor
73      * @param dd Bean Deployment Descriptor
74      * @param cont Container where the bean is defined
75      */

76     public JStatefulFactory(SessionStatefulDesc dd, JContainer cont) {
77         super((SessionDesc) dd, cont);
78         TraceEjb.interp.log(BasicLevel.DEBUG, "");
79         isSynchro = javax.ejb.SessionSynchronization JavaDoc.class.isAssignableFrom(beanclass);
80         isStateful = true;
81     }
82
83     // ---------------------------------------------------------------
84
// BeanFactory implementation
85
// ---------------------------------------------------------------
86

87     /**
88      * @return the Instance pool size for this Ejb
89      */

90     public int getPoolSize() {
91         return sessionList.size();
92     }
93
94     /**
95      * Reduce number of instances in memory
96      */

97     public void reduceCache() {
98     }
99
100     /**
101      * No pool of instances for stateful session beans
102      */

103     public void initInstancePool() {
104     }
105
106     // ---------------------------------------------------------------
107
// preInvoke / postInvoke
108
// ---------------------------------------------------------------
109

110     /**
111      * preInvoke for Session beans stateful
112      * @param txa Transaction Attribute (Supports, Required, ...)
113      * @return A RequestCtx object
114      * @throws EJBException
115      */

116     public RequestCtx preInvoke(int txa) {
117         if (TraceEjb.isDebugIc()) {
118             TraceEjb.interp.log(BasicLevel.DEBUG, "");
119         }
120         RequestCtx rctx = super.preInvoke(txa);
121         return rctx;
122     }
123
124     /**
125      * Check if the access to the bean is authorized
126      * @param ejbInv object containing security signature of the method, args of
127      * method, etc
128      */

129      public void checkSecurity(EJBInvocation ejbInv) {
130          if (TraceEjb.isDebugIc()) {
131              TraceEjb.interp.log(BasicLevel.DEBUG, "");
132          }
133          super.checkSecurity(ejbInv);
134      }
135
136      /**
137      * postinvoke
138      * @param rctx The RequestCtx that was returned at preInvoke()
139      * @throws EJBException
140      */

141     public void postInvoke(RequestCtx rctx) {
142         if (TraceEjb.isDebugIc()) {
143             TraceEjb.interp.log(BasicLevel.DEBUG, "");
144         }
145         super.postInvoke(rctx);
146     }
147
148     // ---------------------------------------------------------------
149
// other public methods
150
// ---------------------------------------------------------------
151

152     /**
153      * Obtains the TimerService associated for this Bean
154      * @return a JTimerService instance.
155      */

156     public TimerService JavaDoc getTimerService() {
157         throw new EJBException JavaDoc("No TimerService for Stateful Session beans");
158     }
159
160     /**
161      * Creates a new Session Stateful called back from createEJB
162      * @return The Session Switch object
163      */

164     public JSessionSwitch createNewSession() throws RemoteException JavaDoc {
165         JStatefulSwitch bs = new JStatefulSwitch(this);
166         return bs;
167     }
168
169     public synchronized int getNewSessionId(JStatefulSwitch jss) {
170         // Get a unique identifier
171
int sid = sessionCount++;
172         if (TraceEjb.isDebugSsfpool()) {
173             TraceEjb.ssfpool.log(BasicLevel.DEBUG, "#" + sid);
174         }
175         // Check if we must passivate some beans first
176
while (maxCacheSize > 0 && cacheSize >= maxCacheSize) {
177             // LRU algo
178
long maxtime = Long.MAX_VALUE;
179             JStatefulSwitch victim = null;
180             for (Iterator JavaDoc i = statefulList.values().iterator(); i.hasNext(); ) {
181                 JStatefulSwitch ss = (JStatefulSwitch) i.next();
182                 long time = ss.getLastAccessTime();
183                 if (time < maxtime) {
184                     if (ss.canPassivate()) {
185                         victim = ss;
186                     }
187                 }
188             }
189             if (victim != null) {
190                 TraceEjb.ssfpool.log(BasicLevel.DEBUG, "try to passivate a bean");
191                 if (victim.passivate()) {
192                     cacheSize--;
193                 }
194             } else {
195                 TraceEjb.ssfpool.log(BasicLevel.DEBUG, "Could not find enough beans to passivate");
196                 break;
197             }
198         }
199         // Put in in the statefulList
200
statefulList.put(new Integer JavaDoc(sid), jss);
201         cacheSize++;
202         return sid;
203     }
204
205     private FileOutputStream JavaDoc getFileOutputStream(int sid) throws IOException JavaDoc {
206         File JavaDoc file = new File JavaDoc(passivationDir, String.valueOf(sid) + ".ssf");
207         file.createNewFile();
208         return new FileOutputStream JavaDoc(file);
209     }
210
211     private FileInputStream JavaDoc getFileInputStream(int sid) throws IOException JavaDoc {
212         File JavaDoc file = new File JavaDoc(passivationDir, String.valueOf(sid) + ".ssf");
213         return new FileInputStream JavaDoc(file);
214     }
215
216     public boolean passivateStateful(JStatefulSwitch jss) {
217         int sid = jss.getSessionId();
218         if (TraceEjb.isDebugSsfpool()) {
219             TraceEjb.ssfpool.log(BasicLevel.DEBUG, "#" + sid);
220         }
221         JStatefulContext ctx = jss.getStatefulContext();
222         try {
223             SessionBean JavaDoc instance = ctx.getInstance();
224             instance.ejbPassivate();
225             JStatefulOutputStream out =
226                 new JStatefulOutputStream(new BufferedOutputStream JavaDoc(getFileOutputStream(sid)));
227             out.writeObject(instance);
228             out.close();
229         } catch (Exception JavaDoc e) {
230             TraceEjb.ssfpool.log(BasicLevel.WARN, "Cannot passivate instance:" + e);
231             return false;
232         }
233         return true;
234     }
235
236     public JStatefulContext activateStateful(JStatefulSwitch jss) {
237         int sid = jss.getSessionId();
238         if (TraceEjb.isDebugSsfpool()) {
239             TraceEjb.ssfpool.log(BasicLevel.DEBUG, "#" + sid);
240         }
241         // In this version, only instance is garbaged at passivation (not Context)
242
JStatefulContext bctx = (JStatefulContext) jss.getStatefulContext();
243         try {
244             JStatefulInputStream in =
245                 new JStatefulInputStream(new BufferedInputStream JavaDoc(getFileInputStream(sid)), jss);
246             Object JavaDoc obj = in.readObject();
247             TraceEjb.ssfpool.log(BasicLevel.DEBUG, "Deserialized object:" + obj);
248             SessionBean JavaDoc sb = (SessionBean JavaDoc) obj;
249             in.close();
250             bctx.setInstance(sb);
251             sb.ejbActivate();
252             // TODO remove passivated file
253
} catch (Exception JavaDoc e) {
254             TraceEjb.ssfpool.log(BasicLevel.WARN, "Cannot activate instance:" + e);
255             return null;
256         }
257         return bctx;
258     }
259
260     public synchronized void removeStateful(int sid) {
261         if (TraceEjb.isDebugSsfpool()) {
262             TraceEjb.ssfpool.log(BasicLevel.DEBUG, "#" + sid);
263         }
264         // Remove from statefulList
265
JStatefulSwitch jss = (JStatefulSwitch) statefulList.remove(new Integer JavaDoc(sid));
266         if (! jss.isPassivated()) {
267             cacheSize--;
268         }
269         if (TraceEjb.isDebugSsfpool()) {
270             TraceEjb.ssfpool.log(BasicLevel.DEBUG, "statefulList size = " + statefulList.size());
271             TraceEjb.ssfpool.log(BasicLevel.DEBUG, "cache size = " + cacheSize);
272         }
273     }
274
275     /**
276      * get a new session context must call newInstance (EJB specs) => no pool
277      * should be used.
278      * @return a new Session Context
279      */

280     public JSessionContext getJContext(JSessionSwitch ss) {
281         if (TraceEjb.isDebugIc()) {
282             TraceEjb.interp.log(BasicLevel.DEBUG, "");
283         }
284         JStatefulContext bctx = null;
285         try {
286             bctx = createNewInstance(ss);
287         } catch (Exception JavaDoc e) {
288             throw new EJBException JavaDoc("Cannot create a new instance", e);
289         }
290         return bctx;
291     }
292
293     // ---------------------------------------------------------------
294
// private methods
295
// ---------------------------------------------------------------
296

297     /**
298      * Create a new instance of the bean and its StatefulContext
299      */

300     private JStatefulContext createNewInstance(JSessionSwitch ss) throws Exception JavaDoc {
301         if (TraceEjb.isDebugIc()) {
302             TraceEjb.interp.log(BasicLevel.DEBUG, "");
303         }
304         // create the bean instance
305
SessionBean JavaDoc bean = null;
306         try {
307             bean = (SessionBean JavaDoc) beanclass.newInstance();
308         } catch (InstantiationException JavaDoc e) {
309             TraceEjb.logger.log(BasicLevel.ERROR, ejbname + " cannot instantiate session bean");
310             throw e;
311         } catch (IllegalAccessException JavaDoc e) {
312             TraceEjb.logger.log(BasicLevel.ERROR, ejbname + " cannot instantiate session bean");
313             throw e;
314         }
315         // create a new StatefulContext and bind it to the instance
316
JStatefulContext bctx = new JStatefulContext(this, bean, isSynchro);
317         bean.setSessionContext(bctx);
318         bctx.setState(1);
319         return bctx;
320     }
321
322 }
323
Popular Tags