KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb3 > stateful > StatefulBeanContext


1 /*
2  * JBoss, Home of Professional Open Source
3  * Copyright 2005, JBoss Inc., and individual contributors as indicated
4  * by the @authors tag. See the copyright.txt in the distribution for a
5  * full listing of individual contributors.
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this software; if not, write to the Free
19  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21  */

22 package org.jboss.ejb3.stateful;
23
24 import org.jboss.aop.metadata.SimpleMetaData;
25 import org.jboss.ejb3.BaseContext;
26 import org.jboss.ejb3.Container;
27 import org.jboss.ejb3.Ejb3Registry;
28 import org.jboss.ejb3.ThreadLocalStack;
29 import org.jboss.ejb3.interceptor.InterceptorInfo;
30 import org.jboss.ejb3.tx.TxUtil;
31 import org.jboss.serial.io.MarshalledObject;
32 import org.jboss.tm.TxUtils;
33
34 import javax.persistence.EntityManager;
35 import javax.transaction.Synchronization JavaDoc;
36 import javax.transaction.Transaction JavaDoc;
37 import java.io.Externalizable JavaDoc;
38 import java.io.IOException JavaDoc;
39 import java.io.ObjectInput JavaDoc;
40 import java.io.ObjectOutput JavaDoc;
41 import java.util.ArrayList JavaDoc;
42 import java.util.HashMap JavaDoc;
43 import java.util.List JavaDoc;
44 import java.util.Map JavaDoc;
45 import java.util.concurrent.locks.ReentrantLock JavaDoc;
46
47 /**
48  * Comment
49  *
50  * @author <a HREF="mailto:bill@jboss.org">Bill Burke</a>
51  * @version $Revision: 58480 $
52  */

53 public class StatefulBeanContext extends BaseContext implements Externalizable JavaDoc
54 {
55    protected Object JavaDoc id;
56
57    protected boolean txSynchronized = false;
58
59    protected boolean inInvocation = false;
60
61    protected MarshalledObject beanMO;
62
63    protected ReentrantLock JavaDoc lock = new ReentrantLock JavaDoc();
64
65    protected boolean discarded;
66
67    // this two are needed for propagated extended persistence contexts when one
68
// SFSB injects another.
69
public static ThreadLocalStack<StatefulBeanContext> propagatedContainedIn = new ThreadLocalStack<StatefulBeanContext>();
70
71    public static ThreadLocalStack<StatefulBeanContext> currentBean = new ThreadLocalStack<StatefulBeanContext>();
72
73    protected StatefulBeanContext containedIn;
74
75    protected List JavaDoc<StatefulBeanContext> contains;
76
77    protected HashMap JavaDoc<String JavaDoc, EntityManager> persistenceContexts;
78
79    protected boolean removed;
80
81    protected String JavaDoc containerName;
82
83    public StatefulBeanContext()
84
85    {
86
87    }
88
89    public List JavaDoc<StatefulBeanContext> getContains()
90    {
91       if (bean == null)
92          extractBeanAndInterceptors();
93       return contains;
94    }
95
96    public EntityManager getExtendedPersistenceContext(String JavaDoc id)
97    {
98       EntityManager found = null;
99       Map JavaDoc<String JavaDoc, EntityManager> extendedPCS = getExtendedPersistenceContexts();
100       if (extendedPCS != null)
101       {
102          found = extendedPCS.get(id);
103       }
104       if (found != null)
105          return found;
106       if (containedIn != null)
107       {
108          found = containedIn.getExtendedPersistenceContext(id);
109       }
110       return found;
111    }
112
113    public void addExtendedPersistenceContext(String JavaDoc id, EntityManager pc)
114    {
115       Map JavaDoc<String JavaDoc, EntityManager> extendedPCS = getExtendedPersistenceContexts();
116       if (extendedPCS == null)
117       {
118          extendedPCS = persistenceContexts = new HashMap JavaDoc<String JavaDoc, EntityManager>();
119       }
120       extendedPCS.put(id, pc);
121    }
122
123    public Map JavaDoc<String JavaDoc, EntityManager> getExtendedPersistenceContexts()
124    {
125       if (persistenceContexts == null)
126       {
127          if (bean == null)
128             getInstance(); // unmarshall
129
}
130       return persistenceContexts;
131    }
132
133    public StatefulBeanContext getContainedIn()
134    {
135       return containedIn;
136    }
137
138    public void addContains(StatefulBeanContext ctx)
139    {
140       if (contains == null)
141          contains = new ArrayList JavaDoc<StatefulBeanContext>();
142       contains.add(ctx);
143       ctx.containedIn = this;
144    }
145
146    public StatefulBeanContext pushContainedIn()
147    {
148       StatefulBeanContext thisPtr = this;
149       if (propagatedContainedIn.getList() != null)
150       {
151          // if this is a nested stateful bean, within another nested stateful
152
// bean
153
// we need to create a nested bean context. The nested one will be put
154
// in the
155
// parents list and owned by it. It is a special class because we do
156
// not want
157
// to put its state in a marshalled object as we want to maintain
158
// object references
159
// We also do not want to put the nested context within its containers
160
// cache
161
// instead, we return a proxy to it that will be stored in its
162
// containers cache
163
containedIn = propagatedContainedIn.get();
164          NestedStatefulBeanContext nested = new NestedStatefulBeanContext();
165          nested.id = id;
166          nested.container = getContainer();
167          nested.containerName = containerName;
168          nested.bean = bean;
169          containedIn.addContains(nested);
170          thisPtr = new ProxiedStatefulBeanContext(nested);
171       }
172       propagatedContainedIn.push(thisPtr);
173       return thisPtr;
174    }
175
176    public void prePassivate()
177    {
178       getContainer().invokePrePassivate(this);
179    }
180
181    public void postActivate()
182    {
183       getContainer().invokePostActivate(this); // handled in getInstance()
184
}
185
186    public void popContainedIn()
187    {
188       propagatedContainedIn.pop();
189    }
190
191    public boolean isDiscarded()
192    {
193       return discarded;
194    }
195
196    public void setDiscarded(boolean discarded)
197    {
198       this.discarded = discarded;
199    }
200
201    public ReentrantLock JavaDoc getLock()
202    {
203       return lock;
204    }
205
206    public boolean isInInvocation()
207    {
208       return inInvocation;
209    }
210
211    public void setInInvocation(boolean inInvocation)
212    {
213       this.inInvocation = inInvocation;
214    }
215
216    public Object JavaDoc getId()
217    {
218       return id;
219    }
220
221    public void setId(Object JavaDoc id)
222    {
223       this.id = id;
224    }
225
226    public boolean isTxSynchronized()
227    {
228       return txSynchronized;
229    }
230
231    public void setTxSynchronized(boolean txSynchronized)
232    {
233       this.txSynchronized = txSynchronized;
234    }
235
236    public boolean isRemoved()
237    {
238       return removed;
239    }
240
241    public void remove()
242    {
243       if (removed)
244          return;
245       removed = true;
246       RuntimeException JavaDoc exceptionThrown = null;
247       if (contains != null)
248       {
249          for (StatefulBeanContext contained : contains)
250          {
251             try
252             {
253                ((StatefulContainer) contained.getContainer()).getCache().remove(
254                        contained.getId());
255             }
256             catch (RuntimeException JavaDoc e)
257             {
258                // we still need to remove every contained SFSB
259
// save the thrown exception and rethrow it after we have cleaned up.
260
exceptionThrown = e;
261             }
262          }
263       }
264       try
265       {
266          Transaction JavaDoc tx = TxUtil.getTransactionManager().getTransaction();
267          if (tx != null && TxUtils.isActive(tx))
268          {
269             tx.registerSynchronization(new Synchronization JavaDoc()
270             {
271                public void beforeCompletion()
272                {
273                }
274
275                public void afterCompletion(int status)
276                {
277                   closeExtendedPCs();
278                }
279             });
280          }
281          else
282          {
283             closeExtendedPCs();
284          }
285       }
286       catch (Exception JavaDoc e)
287       {
288          throw new RuntimeException JavaDoc("Exception thrown while removing SFSB", e);
289       }
290       if (exceptionThrown != null) throw new RuntimeException JavaDoc("exception thrown while removing SFSB", exceptionThrown);
291    }
292
293    private void closeExtendedPCs()
294    {
295       Map JavaDoc<String JavaDoc, EntityManager> extendedPCS = getExtendedPersistenceContexts();
296       if (extendedPCS != null)
297       {
298          RuntimeException JavaDoc exceptionThrown = null;
299          for (EntityManager pc : extendedPCS.values())
300          {
301             try
302             {
303                pc.close();
304             }
305             catch (RuntimeException JavaDoc e)
306             {
307                exceptionThrown = e;
308             }
309          }
310          if (exceptionThrown != null) throw new RuntimeException JavaDoc("Error cleaning up PersistenceContexts in SFSB removal", exceptionThrown);
311       }
312    }
313
314    public void setContainer(Container container)
315    {
316       super.setContainer(container);
317       containerName = container.getObjectName().getCanonicalName();
318    }
319
320    public Container getContainer()
321    {
322       if (container == null)
323       {
324          container = Ejb3Registry.getContainer(containerName);
325       }
326       return container;
327    }
328
329    @Override JavaDoc
330    public Object JavaDoc getInstance()
331    {
332       if (bean == null)
333       {
334          extractBeanAndInterceptors();
335          // getContainer().invokePostActivate(this);
336
}
337       return bean;
338    }
339
340    @Override JavaDoc
341    public SimpleMetaData getMetaData()
342    {
343       return super.getMetaData();
344    }
345
346    // these are public for fast concurrent access/update
347
public volatile boolean markedForPassivation = false;
348
349    public volatile boolean inUse = false;
350
351    public volatile long lastUsed = System.currentTimeMillis();
352
353    @Override JavaDoc
354    public Object JavaDoc[] getInterceptorInstances(InterceptorInfo[] interceptorInfos)
355    {
356       if (bean == null)
357       {
358          extractBeanAndInterceptors();
359       }
360       return super.getInterceptorInstances(interceptorInfos);
361    }
362
363    protected void extractBeanAndInterceptors()
364    {
365       try
366       {
367          Object JavaDoc[] beanAndInterceptors = (Object JavaDoc[]) beanMO.get();
368          bean = beanAndInterceptors[0];
369          persistenceContexts = (HashMap JavaDoc<String JavaDoc, EntityManager>) beanAndInterceptors[1];
370          ArrayList JavaDoc list = (ArrayList JavaDoc) beanAndInterceptors[2];
371          interceptorInstances = new HashMap JavaDoc<Class JavaDoc, Object JavaDoc>();
372          if (list != null)
373          {
374             for (Object JavaDoc o : list)
375             {
376                interceptorInstances.put(o.getClass(), o);
377             }
378          }
379          contains = (List JavaDoc<StatefulBeanContext>) beanAndInterceptors[3];
380 /* We should let pm to handle this.
381          if (contains != null)
382          {
383             for (StatefulBeanContext ctx : contains)
384             {
385                ctx.getContainer().invokePostActivate(ctx);
386             }
387          }
388 */

389       }
390       catch (IOException JavaDoc e)
391       {
392          throw new RuntimeException JavaDoc(e);
393       }
394       catch (ClassNotFoundException JavaDoc e)
395       {
396          throw new RuntimeException JavaDoc(e);
397       }
398    }
399
400    public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc
401    {
402       out.writeUTF(containerName);
403       out.writeObject(id);
404       out.writeObject(metadata);
405       if (bean == null)
406       {
407          out.writeObject(beanMO);
408       }
409       else
410       {
411          Object JavaDoc[] beanAndInterceptors = new Object JavaDoc[4];
412          beanAndInterceptors[0] = bean;
413          beanAndInterceptors[1] = persistenceContexts;
414          if (interceptorInstances != null && interceptorInstances.size() > 0)
415          {
416             ArrayList JavaDoc list = new ArrayList JavaDoc();
417             list.addAll(interceptorInstances.values());
418             beanAndInterceptors[2] = list;
419          }
420          beanAndInterceptors[3] = contains;
421 /* Since replication also uses this. We c'ant call this directly. Let pm handle this.
422          if (contains != null)
423          {
424             for (StatefulBeanContext ctx : contains)
425             {
426                ctx.prePassivate();
427             }
428          }
429 */

430          beanMO = new MarshalledObject(beanAndInterceptors);
431          out.writeObject(beanMO);
432       }
433    }
434
435    public void readExternal(ObjectInput JavaDoc in) throws IOException JavaDoc,
436            ClassNotFoundException JavaDoc
437    {
438       containerName = in.readUTF();
439       id = in.readObject();
440       metadata = (SimpleMetaData) in.readObject();
441       beanMO = (MarshalledObject) in.readObject();
442    }
443
444    public Object JavaDoc getInvokedMethodKey()
445    {
446       return this.getId();
447    }
448 }
449
Popular Tags