KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > CMPPersistenceManager


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.ejb.plugins;
23
24 import java.lang.reflect.Method JavaDoc;
25 import java.lang.reflect.InvocationTargetException JavaDoc;
26 import java.rmi.RemoteException JavaDoc;
27 import java.util.Collection JavaDoc;
28 import java.util.HashMap JavaDoc;
29
30 import javax.ejb.EntityBean JavaDoc;
31 import javax.ejb.RemoveException JavaDoc;
32 import javax.ejb.EJBException JavaDoc;
33
34 import org.jboss.ejb.Container;
35 import org.jboss.ejb.EntityContainer;
36 import org.jboss.ejb.EntityPersistenceManager;
37 import org.jboss.ejb.EntityEnterpriseContext;
38 import org.jboss.ejb.EntityCache;
39 import org.jboss.ejb.EntityPersistenceStore;
40 import org.jboss.ejb.AllowedOperationsAssociation;
41 import org.jboss.ejb.GenericEntityObjectFactory;
42 import org.jboss.metadata.ConfigurationMetaData;
43
44 /**
45  * The CMP Persistence Manager implements the semantics of the CMP
46  * EJB 1.1 call back specification.
47  * <p/>
48  * This Manager works with a "EntityPersistenceStore" that takes care of the
49  * physical storing of instances (JAWS, JDBC O/R, FILE, Object).
50  *
51  * @author <a HREF="mailto:marc.fleury@telkel.com">Marc Fleury</a>
52  * @author <a HREF="mailto:danch@nvisia.com">Dan Christopherson</a>
53  * @author <a HREF="mailto:bill@burkecentral.com">Bill Burke</a>
54  * @author <a HREF="mailto:andreas.schaefer@madplanet.com">Andreas Schaefer</a>
55  * @author <a HREF="mailto:dain@daingroup.com">Dain Sundstrom</a>
56  * @author <a HREF="mailto:alex@jboss.org">Alex Loubyansky</a>
57  * @version $Revision: 37459 $
58  */

59 public class CMPPersistenceManager
60    implements EntityPersistenceManager
61 {
62    // Constants -----------------------------------------------------
63

64    // Attributes ----------------------------------------------------
65
EntityContainer con;
66    // Physical persistence implementation
67
EntityPersistenceStore store;
68
69
70    HashMap JavaDoc createMethods = new HashMap JavaDoc();
71    HashMap JavaDoc postCreateMethods = new HashMap JavaDoc();
72    private boolean insertAfterEjbPostCreate;
73    private boolean ejbStoreForClean;
74
75    // Static --------------------------------------------------------
76

77    // Constructors --------------------------------------------------
78

79    // Public --------------------------------------------------------
80
public void setContainer(Container c)
81    {
82       con = (EntityContainer) c;
83
84       if(store != null)
85       {
86          store.setContainer(c);
87       }
88
89       if(con != null)
90       {
91          ConfigurationMetaData configuration = con.getBeanMetaData().getContainerConfiguration();
92          ejbStoreForClean = configuration.isEjbStoreForClean();
93       }
94    }
95
96    /**
97     * Gets the entity persistence store.
98     */

99    public EntityPersistenceStore getPersistenceStore()
100    {
101       return store;
102    }
103
104    public void setPersistenceStore(EntityPersistenceStore store)
105    {
106       this.store = store;
107
108       //Give it the container
109
if(con != null) store.setContainer(con);
110    }
111
112    public void create()
113       throws Exception JavaDoc
114    {
115       if(con.getHomeClass() != null)
116       {
117          Method JavaDoc[] methods = con.getHomeClass().getMethods();
118          createMethodCache(methods);
119       }
120
121       if(con.getLocalHomeClass() != null)
122       {
123          Method JavaDoc[] methods = con.getLocalHomeClass().getMethods();
124          createMethodCache(methods);
125       }
126
127       insertAfterEjbPostCreate = con.getBeanMetaData().getContainerConfiguration().isInsertAfterEjbPostCreate();
128
129       store.create();
130    }
131
132    /**
133     * Returns a new instance of the bean class or a subclass of the bean class.
134     *
135     * @return the new instance
136     */

137    public Object JavaDoc createBeanClassInstance() throws Exception JavaDoc
138    {
139       return store.createBeanClassInstance();
140    }
141
142    private void createMethodCache(Method JavaDoc[] methods)
143       throws NoSuchMethodException JavaDoc
144    {
145       // Create cache of create methods
146
Class JavaDoc beanClass = con.getBeanClass();
147       for(int i = 0; i < methods.length; i++)
148       {
149          String JavaDoc name = methods[i].getName();
150          if(name.startsWith("create"))
151          {
152             Class JavaDoc[] types = methods[i].getParameterTypes();
153             try
154             {
155                String JavaDoc nameSuffix = name.substring(0, 1).toUpperCase() + name.substring(1);
156                Method JavaDoc beanMethod = beanClass.getMethod("ejb" + nameSuffix, types);
157                createMethods.put(methods[i], beanMethod);
158                beanMethod = beanClass.getMethod("ejbPost" + nameSuffix, types);
159                postCreateMethods.put(methods[i], beanMethod);
160             }
161             catch(NoSuchMethodException JavaDoc nsme)
162             {
163                throw new NoSuchMethodException JavaDoc("Can't find ejb[Post]Create in " + beanClass.getName());
164             }
165          }
166       }
167    }
168
169    public void start()
170       throws Exception JavaDoc
171    {
172       store.start();
173    }
174
175    public void stop()
176    {
177       store.stop();
178    }
179
180    public void destroy()
181    {
182       store.destroy();
183    }
184
185    public void createEntity(Method JavaDoc m, Object JavaDoc[] args, EntityEnterpriseContext ctx)
186       throws Exception JavaDoc
187    {
188       // Deligate initialization of bean to persistence store
189
store.initEntity(ctx);
190
191       // Call ejbCreate on the target bean
192
try
193       {
194          AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_CREATE);
195          Method JavaDoc createMethod = (Method JavaDoc) createMethods.get(m);
196          createMethod.invoke(ctx.getInstance(), args);
197       }
198       catch(IllegalAccessException JavaDoc e)
199       {
200          // Throw this as a bean exception...(?)
201
throw new EJBException JavaDoc(e);
202       }
203       catch(InvocationTargetException JavaDoc ite)
204       {
205          Throwable JavaDoc e = ite.getTargetException();
206          if(e instanceof EJBException JavaDoc)
207          {
208             // Rethrow exception
209
throw (EJBException JavaDoc) e;
210          }
211          else if(e instanceof RuntimeException JavaDoc)
212          {
213             // Wrap runtime exceptions
214
throw new EJBException JavaDoc((Exception JavaDoc) e);
215          }
216          else if(e instanceof Exception JavaDoc)
217          {
218             // Remote, Create, or custom app. exception
219
throw (Exception JavaDoc) e;
220          }
221          else
222          {
223             throw (Error JavaDoc) e;
224          }
225       }
226       finally
227       {
228          AllowedOperationsAssociation.popInMethodFlag();
229       }
230
231       // if insertAfterEjbPostCreate == true, this will INSERT entity
232
// otherwise, primary key is extracted from the context and returned
233
Object JavaDoc id;
234       try
235       {
236          AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_CREATE);
237          id = store.createEntity(m, args, ctx);
238       }
239       finally
240       {
241          AllowedOperationsAssociation.popInMethodFlag();
242       }
243
244       // Set the key on the target context
245
ctx.setId(id);
246
247       // Create a new CacheKey
248
Object JavaDoc cacheKey = ((EntityCache) con.getInstanceCache()).createCacheKey(id);
249
250       // Give it to the context
251
ctx.setCacheKey(cacheKey);
252    }
253
254    public void postCreateEntity(Method JavaDoc m, Object JavaDoc[] args, EntityEnterpriseContext ctx)
255       throws Exception JavaDoc
256    {
257       // this call should go first as it sets up relationships
258
// for fk fields mapped to pk fields
259
store.postCreateEntity(m, args, ctx);
260
261       try
262       {
263          AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_POST_CREATE);
264
265          Method JavaDoc postCreateMethod = (Method JavaDoc) postCreateMethods.get(m);
266          postCreateMethod.invoke(ctx.getInstance(), args);
267          if(insertAfterEjbPostCreate)
268          {
269             store.createEntity(m, args, ctx);
270          }
271       }
272       catch(IllegalAccessException JavaDoc e)
273       {
274          // Throw this as a bean exception...(?)
275
throw new EJBException JavaDoc(e);
276       }
277       catch(InvocationTargetException JavaDoc ite)
278       {
279          Throwable JavaDoc e = ite.getTargetException();
280          if(e instanceof EJBException JavaDoc)
281          {
282             // Rethrow exception
283
throw (EJBException JavaDoc) e;
284          }
285          else if(e instanceof RuntimeException JavaDoc)
286          {
287             // Wrap runtime exceptions
288
throw new EJBException JavaDoc((Exception JavaDoc) e);
289          }
290          else if(e instanceof Exception JavaDoc)
291          {
292             // Remote, Create, or custom app. exception
293
throw (Exception JavaDoc) e;
294          }
295          else
296          {
297             throw (Error JavaDoc) e;
298          }
299       }
300       finally
301       {
302          AllowedOperationsAssociation.popInMethodFlag();
303       }
304    }
305
306    public Object JavaDoc findEntity(Method JavaDoc finderMethod,
307                             Object JavaDoc[] args,
308                             EntityEnterpriseContext ctx,
309                             GenericEntityObjectFactory factory)
310       throws Exception JavaDoc
311    {
312       try
313       {
314          AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_FIND);
315          return store.findEntity(finderMethod, args, ctx, factory);
316       }
317       finally
318       {
319          AllowedOperationsAssociation.popInMethodFlag();
320       }
321    }
322
323    /**
324     * find multiple entities
325     */

326    public Collection JavaDoc findEntities(Method JavaDoc finderMethod,
327                                   Object JavaDoc[] args,
328                                   EntityEnterpriseContext ctx,
329                                   GenericEntityObjectFactory factory)
330       throws Exception JavaDoc
331    {
332       try
333       {
334          // return the finderResults so that the invoker layer can extend this back
335
// giving the client an OO 'cursor'
336
AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_FIND);
337          return store.findEntities(finderMethod, args, ctx, factory);
338       }
339       finally
340       {
341          AllowedOperationsAssociation.popInMethodFlag();
342       }
343    }
344
345    /*
346     * activateEntity(EnterpriseContext ctx)
347     *
348     * The method calls the target beans for spec compliant callbacks.
349     * Since these are pure EJB calls it is not obvious that the store should
350     * expose the interfaces. In case of jaws however we found that store specific
351     * contexts could be set in the activateEntity calls and hence a propagation of
352     * the call made sense. The persistence store is called for "extension" purposes.
353     *
354     * @see activateEntity on EntityPersistenceStore.java
355     */

356    public void activateEntity(EntityEnterpriseContext ctx)
357       throws RemoteException JavaDoc
358    {
359       // Create a new CacheKey
360
Object JavaDoc id = ctx.getId();
361       Object JavaDoc cacheKey = ((EntityCache) con.getInstanceCache()).createCacheKey(id);
362
363       // Give it to the context
364
ctx.setCacheKey(cacheKey);
365
366       try
367       {
368          AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_ACTIVATE);
369          EntityBean JavaDoc eb = (EntityBean JavaDoc) ctx.getInstance();
370          eb.ejbActivate();
371       }
372       catch(Exception JavaDoc e)
373       {
374          if(e instanceof RemoteException JavaDoc)
375          {
376             // Rethrow exception
377
throw (RemoteException JavaDoc) e;
378          }
379          else if(e instanceof EJBException JavaDoc)
380          {
381             // Rethrow exception
382
throw (EJBException JavaDoc) e;
383          }
384          else
385          {
386             // Wrap runtime exceptions
387
throw new EJBException JavaDoc((Exception JavaDoc) e);
388          }
389       }
390       finally
391       {
392          AllowedOperationsAssociation.popInMethodFlag();
393       }
394
395       // The implementation of the call can be left absolutely empty, the
396
// propagation of the call is just a notification for stores that would
397
// need to know that an instance is being activated
398
store.activateEntity(ctx);
399    }
400
401    public void loadEntity(EntityEnterpriseContext ctx)
402       throws RemoteException JavaDoc
403    {
404       //long lStart = System.currentTimeMillis();
405
// Have the store load the fields of the instance
406
store.loadEntity(ctx);
407       //mLoad.add( System.currentTimeMillis() - lStart );
408

409       invokeLoad(ctx);
410    }
411
412    public boolean isStoreRequired(EntityEnterpriseContext ctx) throws Exception JavaDoc
413    {
414       return store.isStoreRequired(ctx);
415    }
416
417    public boolean isModified(EntityEnterpriseContext ctx) throws Exception JavaDoc
418    {
419       return store.isModified(ctx);
420    }
421
422    public void storeEntity(EntityEnterpriseContext ctx)
423       throws RemoteException JavaDoc
424    {
425       AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_STORE);
426       try
427       {
428          store.storeEntity(ctx);
429       }
430       finally
431       {
432          AllowedOperationsAssociation.popInMethodFlag();
433       }
434    }
435
436    public void invokeEjbStore(EntityEnterpriseContext ctx) throws RemoteException JavaDoc
437    {
438       AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_STORE);
439
440       try
441       {
442          // if call-ejb-store-for-clean=true then invoke ejbStore first (the last chance to modify the instance)
443
if(ejbStoreForClean)
444          {
445             ejbStore(ctx);
446          }
447          else
448          {
449             // else check whether the instance is dirty and invoke ejbStore only if it is really dirty
450
boolean modified = false;
451             try
452             {
453                modified = isStoreRequired(ctx);
454             }
455             catch(Exception JavaDoc e)
456             {
457                throwRemoteException(e);
458             }
459
460             if(modified)
461             {
462                ejbStore(ctx);
463             }
464          }
465       }
466       finally
467       {
468          AllowedOperationsAssociation.popInMethodFlag();
469       }
470    }
471
472    public void passivateEntity(EntityEnterpriseContext ctx)
473       throws RemoteException JavaDoc
474    {
475       try
476       {
477          AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_PASSIVATE);
478          EntityBean JavaDoc eb = (EntityBean JavaDoc) ctx.getInstance();
479          eb.ejbPassivate();
480       }
481       catch(Exception JavaDoc e)
482       {
483          throwRemoteException(e);
484       }
485       finally
486       {
487          AllowedOperationsAssociation.popInMethodFlag();
488       }
489
490       store.passivateEntity(ctx);
491       ctx.setEJBObject(null);
492       ctx.setEJBLocalObject(null);
493    }
494
495    public void removeEntity(EntityEnterpriseContext ctx)
496       throws RemoteException JavaDoc, RemoveException JavaDoc
497    {
498       try
499       {
500          AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_REMOVE);
501          EntityBean JavaDoc eb = (EntityBean JavaDoc) ctx.getInstance();
502          eb.ejbRemove();
503       }
504       catch(Exception JavaDoc e)
505       {
506          if(e instanceof RemoveException JavaDoc)
507          {
508             // Rethrow exception
509
throw (RemoveException JavaDoc) e;
510          }
511          else
512          {
513             throwRemoteException(e);
514          }
515       }
516       finally
517       {
518          AllowedOperationsAssociation.popInMethodFlag();
519       }
520
521       store.removeEntity(ctx);
522    }
523
524    protected void invokeLoad(EntityEnterpriseContext ctx) throws RemoteException JavaDoc
525    {
526       try
527       {
528          AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_LOAD);
529
530          EntityBean JavaDoc eb = (EntityBean JavaDoc) ctx.getInstance();
531          eb.ejbLoad();
532       }
533       catch(Exception JavaDoc e)
534       {
535          throwRemoteException(e);
536       }
537       finally
538       {
539          AllowedOperationsAssociation.popInMethodFlag();
540       }
541    }
542
543    // Private
544

545    private void ejbStore(EntityEnterpriseContext ctx)
546       throws RemoteException JavaDoc
547    {
548       try
549       {
550          EntityBean JavaDoc eb = (EntityBean JavaDoc) ctx.getInstance();
551          eb.ejbStore();
552       }
553       catch(Exception JavaDoc e)
554       {
555          throwRemoteException(e);
556       }
557    }
558
559    private void throwRemoteException(Exception JavaDoc e)
560       throws RemoteException JavaDoc
561    {
562       if(e instanceof RemoteException JavaDoc)
563       {
564          // Rethrow exception
565
throw (RemoteException JavaDoc) e;
566       }
567       else if(e instanceof EJBException JavaDoc)
568       {
569          // Rethrow exception
570
throw (EJBException JavaDoc) e;
571       }
572       else
573       {
574          // Wrap runtime exceptions
575
throw new EJBException JavaDoc((Exception JavaDoc) e);
576       }
577    }
578 }
579
Popular Tags