KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > EntityContainer


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;
23
24 import java.lang.reflect.Method JavaDoc;
25 import java.rmi.RemoteException JavaDoc;
26 import java.util.Collection JavaDoc;
27 import java.util.Enumeration JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.Hashtable JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.Map JavaDoc;
32
33 import javax.ejb.EJBException JavaDoc;
34 import javax.ejb.EJBHome JavaDoc;
35 import javax.ejb.EJBLocalHome JavaDoc;
36 import javax.ejb.EJBLocalObject JavaDoc;
37 import javax.ejb.EJBMetaData JavaDoc;
38 import javax.ejb.EJBObject JavaDoc;
39 import javax.ejb.Handle JavaDoc;
40 import javax.ejb.HomeHandle JavaDoc;
41 import javax.ejb.RemoveException JavaDoc;
42 import javax.ejb.TimedObject JavaDoc;
43 import javax.ejb.Timer JavaDoc;
44 import javax.management.ObjectName JavaDoc;
45 import javax.transaction.Transaction JavaDoc;
46
47 import org.jboss.invocation.Invocation;
48 import org.jboss.invocation.InvocationType;
49 import org.jboss.invocation.MarshalledInvocation;
50 import org.jboss.metadata.ConfigurationMetaData;
51 import org.jboss.metadata.EntityMetaData;
52 import org.jboss.monitor.StatisticsProvider;
53 import org.jboss.util.collection.SerializableEnumeration;
54
55 /**
56  * This is a Container for EntityBeans (both BMP and CMP).
57  *
58  * @see Container
59  * @see EntityEnterpriseContext
60  *
61  * @author <a HREF="mailto:rickard.oberg@telkel.com">Rickard ´┐Żberg</a>
62  * @author <a HREF="mailto:marc.fleury@telkel.com">Marc Fleury</a>
63  * @author <a HREF="mailto:sebastien.alborini@m4x.org">Sebastien Alborini</a>
64  * @author <a HREF="mailto:docodan@mvcsoft.com">Daniel OConnor</a>
65  * @author <a HREF="mailto:bill@burkecentral.com">Bill Burke</a>
66  * @author <a HREF="mailto:andreas.schaefer@madplanet.com">Andreas Schaefer</a>
67  * @author <a HREF="mailto:dain@daingroup.com">Dain Sundstrom</a>
68  * @version $Revision: 46027 $
69  *
70  * @jmx.mbean extends="org.jboss.ejb.ContainerMBean"
71  */

72 public class EntityContainer
73    extends Container
74    implements EJBProxyFactoryContainer, InstancePoolContainer,
75       EntityContainerMBean
76 {
77    /**
78     * These are the mappings between the home interface methods and the
79     * container methods.
80     */

81    protected Map JavaDoc homeMapping = new HashMap JavaDoc();
82
83    /**
84     * These are the mappings between the remote/local interface methods and the
85     * bean methods.
86     */

87    protected Map JavaDoc beanMapping = new HashMap JavaDoc();
88
89    /** This is the persistence manager for this container */
90    protected EntityPersistenceManager persistenceManager;
91
92    /** This is the instance cache for this container */
93    protected InstanceCache instanceCache;
94
95    /** This is the instancepool that is to be used */
96    protected InstancePool instancePool;
97
98    /**
99     * This is the first interceptor in the chain. The last interceptor must
100     * be provided by the container itself.
101     */

102    protected Interceptor interceptor;
103
104    /**
105     * <code>readOnly</code> determines if state can be written to resource manager.
106     */

107    protected boolean readOnly = false;
108
109    /**
110     * This provides a way to find the entities that are part of a given
111     * transaction EntitySynchronizationInterceptor and InstanceSynchronization
112     * manage this instance.
113     */

114    protected static GlobalTxEntityMap globalTxEntityMap = new GlobalTxEntityMap();
115    
116    public static GlobalTxEntityMap getGlobalTxEntityMap()
117    {
118       return globalTxEntityMap;
119    }
120
121    /**
122     * Stores all of the entities associated with the specified transaction.
123     * As per the spec 9.6.4, entities must be synchronized with the datastore
124     * when an ejbFind<METHOD> is called.
125     * Also, all entities within entire transaction should be synchronized before
126     * a remove, otherwise there may be problems with 'cascade delete'.
127     *
128     * @param tx the transaction that associated entites will be stored
129     */

130    public static void synchronizeEntitiesWithinTransaction(Transaction JavaDoc tx)
131    {
132       // If there is no transaction, there is nothing to synchronize.
133
if(tx != null)
134       {
135          getGlobalTxEntityMap().synchronizeEntities(tx);
136       }
137    }
138
139    // Public --------------------------------------------------------
140

141    public boolean isReadOnly()
142    {
143       return readOnly;
144    }
145
146    public LocalProxyFactory getLocalProxyFactory()
147    {
148       return localProxyFactory;
149    }
150
151    public void setInstancePool(InstancePool ip)
152    {
153       if (ip == null)
154          throw new IllegalArgumentException JavaDoc("Null pool");
155
156       this.instancePool = ip;
157       ip.setContainer(this);
158    }
159
160    public InstancePool getInstancePool()
161    {
162       return instancePool;
163    }
164
165    public void setInstanceCache(InstanceCache ic)
166    {
167       if (ic == null)
168          throw new IllegalArgumentException JavaDoc("Null cache");
169
170       this.instanceCache = ic;
171       ic.setContainer(this);
172    }
173
174    public InstanceCache getInstanceCache()
175    {
176       return instanceCache;
177    }
178
179    public EntityPersistenceManager getPersistenceManager()
180    {
181       return persistenceManager;
182    }
183
184    public void setPersistenceManager(EntityPersistenceManager pm)
185    {
186       if (pm == null)
187          throw new IllegalArgumentException JavaDoc("Null persistence manager");
188
189       persistenceManager = pm;
190       pm.setContainer(this);
191    }
192
193    public void addInterceptor(Interceptor in)
194    {
195       if (interceptor == null)
196       {
197          interceptor = in;
198       }
199       else
200       {
201          Interceptor current = interceptor;
202          while (current.getNext() != null)
203          {
204             current = current.getNext();
205          }
206
207          current.setNext(in);
208       }
209    }
210
211    public Interceptor getInterceptor()
212    {
213       return interceptor;
214    }
215
216    public Class JavaDoc getHomeClass()
217    {
218       return homeInterface;
219    }
220
221    public Class JavaDoc getRemoteClass()
222    {
223       return remoteInterface;
224    }
225
226    /**
227     * Returns a new instance of the bean class or a subclass of the bean class.
228     * If this is 1.x cmp, simply return a new instance of the bean class.
229     * If this is 2.x cmp, return a subclass that provides an implementation
230     * of the abstract accessors.
231     *
232     * @see java.lang.Class#newInstance
233     *
234     * @return The new instance.
235     */

236    public Object JavaDoc createBeanClassInstance() throws Exception JavaDoc {
237       return persistenceManager.createBeanClassInstance();
238    }
239
240    // Container implementation --------------------------------------
241

242    protected void createService() throws Exception JavaDoc
243    {
244       // Associate thread with classloader
245
ClassLoader JavaDoc oldCl = SecurityActions.getContextClassLoader();
246       SecurityActions.setContextClassLoader(getClassLoader());
247
248       try
249       {
250          // Acquire classes from CL
251
if (metaData.getHome() != null)
252             homeInterface = classLoader.loadClass(metaData.getHome());
253          if (metaData.getRemote() != null)
254             remoteInterface = classLoader.loadClass(metaData.getRemote());
255
256          // Call default init
257
super.createService();
258
259          // Make some additional validity checks with regards to the container configuration
260
checkCoherency ();
261
262          // Map the bean methods
263
setupBeanMapping();
264
265          // Map the home methods
266
setupHomeMapping();
267
268          // Map the interfaces to Long
269
setupMarshalledInvocationMapping();
270
271          // Try to register the instance pool as an MBean
272
try
273          {
274             ObjectName JavaDoc containerName = super.getJmxName();
275             Hashtable JavaDoc props = containerName.getKeyPropertyList();
276             props.put("plugin", "pool");
277             ObjectName JavaDoc poolName = new ObjectName JavaDoc(containerName.getDomain(), props);
278             server.registerMBean(instancePool, poolName);
279          }
280          catch(Throwable JavaDoc t)
281          {
282             log.debug("Failed to register cache as mbean", t);
283          }
284          // Initialize pool
285
instancePool.create();
286
287          for (Iterator JavaDoc it = proxyFactories.keySet().iterator(); it.hasNext(); )
288          {
289             String JavaDoc invokerBinding = (String JavaDoc)it.next();
290             EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding);
291             ci.create();
292          }
293
294          // Try to register the instance cache as an MBean
295
try
296          {
297             ObjectName JavaDoc containerName = super.getJmxName();
298             Hashtable JavaDoc props = containerName.getKeyPropertyList();
299             props.put("plugin", "cache");
300             ObjectName JavaDoc cacheName = new ObjectName JavaDoc(containerName.getDomain(), props);
301             server.registerMBean(instanceCache, cacheName);
302          }
303          catch(Throwable JavaDoc t)
304          {
305             log.debug("Failed to register cache as mbean", t);
306          }
307          // Init instance cache
308
instanceCache.create();
309
310          // Init persistence
311
persistenceManager.create();
312
313          // Initialize the interceptor by calling the chain
314
Interceptor in = interceptor;
315          while (in != null)
316          {
317             in.setContainer(this);
318             in.create();
319             in = in.getNext();
320          }
321          readOnly = ((EntityMetaData)metaData).isReadOnly();
322       }
323       finally
324       {
325          // Reset classloader
326
SecurityActions.setContextClassLoader(oldCl);
327       }
328    }
329
330    protected void startService() throws Exception JavaDoc
331    {
332       // Associate thread with classloader
333
ClassLoader JavaDoc oldCl = SecurityActions.getContextClassLoader();
334       SecurityActions.setContextClassLoader(getClassLoader());
335
336       try
337       {
338          // Call default start
339
super.startService();
340
341          // Start container invokers
342
for (Iterator JavaDoc it = proxyFactories.keySet().iterator(); it.hasNext(); )
343          {
344             String JavaDoc invokerBinding = (String JavaDoc)it.next();
345             EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding);
346             ci.start();
347          }
348
349          // Start instance cache
350
instanceCache.start();
351
352          // Start the instance pool
353
instancePool.start();
354
355          Interceptor i = interceptor;
356          while(i != null)
357          {
358             i.start();
359             i = i.getNext();
360          }
361
362          // Restore persisted ejb timers
363
restoreTimers();
364       }
365       finally
366       {
367          // Reset classloader
368
SecurityActions.setContextClassLoader(oldCl);
369       }
370    }
371
372    protected void stopService() throws Exception JavaDoc
373    {
374       // Associate thread with classloader
375
ClassLoader JavaDoc oldCl = SecurityActions.getContextClassLoader();
376       SecurityActions.setContextClassLoader(getClassLoader());
377
378       try
379       {
380          //Stop items in reverse order from start
381
//This assures that CachedConnectionInterceptor will get removed
382
//from in between this and the pm before the pm is stopped.
383
// Stop all interceptors in the chain
384
Interceptor in = interceptor;
385          while (in != null)
386          {
387             in.stop();
388             in = in.getNext();
389          }
390
391          // Stop the instance pool
392
instancePool.stop();
393
394
395          // Stop persistence
396
persistenceManager.stop();
397
398          // Stop instance cache
399
instanceCache.stop();
400
401          // Stop container invoker
402
for (Iterator JavaDoc it = proxyFactories.keySet().iterator(); it.hasNext(); )
403          {
404             String JavaDoc invokerBinding = (String JavaDoc)it.next();
405             EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding);
406             ci.stop();
407          }
408
409          // Call default stop
410
super.stopService();
411       }
412       finally
413       {
414          // Reset classloader
415
SecurityActions.setContextClassLoader(oldCl);
416       }
417    }
418
419    protected void destroyService() throws Exception JavaDoc
420    {
421       // Associate thread with classloader
422
ClassLoader JavaDoc oldCl = SecurityActions.getContextClassLoader();
423       SecurityActions.setContextClassLoader(getClassLoader());
424
425       try
426       {
427          // Destroy container invoker
428
for (Iterator JavaDoc it = proxyFactories.keySet().iterator(); it.hasNext(); )
429          {
430             String JavaDoc invokerBinding = (String JavaDoc)it.next();
431             EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding);
432             ci.destroy();
433          }
434
435          // Destroy instance cache
436
instanceCache.destroy();
437          instanceCache.setContainer(null);
438          try
439          {
440             ObjectName JavaDoc containerName = super.getJmxName();
441             Hashtable JavaDoc props = containerName.getKeyPropertyList();
442             props.put("plugin", "cache");
443             ObjectName JavaDoc cacheName = new ObjectName JavaDoc(containerName.getDomain(), props);
444             server.unregisterMBean(cacheName);
445          }
446          catch(Throwable JavaDoc ignore)
447          {
448          }
449
450          // Destroy persistence
451
persistenceManager.destroy();
452          persistenceManager.setContainer(null);
453
454          // Destroy the pool
455
instancePool.destroy();
456          instancePool.setContainer(null);
457          try
458          {
459             ObjectName JavaDoc containerName = super.getJmxName();
460             Hashtable JavaDoc props = containerName.getKeyPropertyList();
461             props.put("plugin", "pool");
462             ObjectName JavaDoc poolName = new ObjectName JavaDoc(containerName.getDomain(), props);
463             server.unregisterMBean(poolName);
464          }
465          catch(Throwable JavaDoc ignore)
466          {
467          }
468
469          // Destroy all the interceptors in the chain
470
Interceptor in = interceptor;
471          while (in != null)
472          {
473             in.destroy();
474             in.setContainer(null);
475             in = in.getNext();
476          }
477
478          MarshalledInvocation.removeHashes(homeInterface);
479          MarshalledInvocation.removeHashes(remoteInterface);
480
481          // Call default destroy
482
super.destroyService();
483       }
484       finally
485       {
486          // Reset classloader
487
SecurityActions.setContextClassLoader(oldCl);
488       }
489    }
490
491    public Object JavaDoc internalInvokeHome(Invocation mi) throws Exception JavaDoc
492    {
493       Method JavaDoc method = mi.getMethod();
494       if (method != null && method.getName().equals("remove"))
495       {
496          // Map to EJBHome.remove(Object) to EJBObject.remove()
497
InvocationType type = mi.getType();
498          if (type == InvocationType.HOME)
499             mi.setType(InvocationType.REMOTE);
500          else if (type == InvocationType.LOCALHOME)
501             mi.setType(InvocationType.LOCAL);
502          mi.setMethod(EJBOBJECT_REMOVE);
503
504          // Handle or primary key?
505
Object JavaDoc arg = mi.getArguments()[0];
506          if (arg instanceof Handle JavaDoc)
507          {
508             if (arg == null)
509                throw new RemoteException JavaDoc("Null handle");
510             Handle JavaDoc handle = (Handle JavaDoc) arg;
511             EJBObject JavaDoc ejbObject = handle.getEJBObject();
512             mi.setId(ejbObject.getPrimaryKey());
513          }
514          else
515             mi.setId(arg);
516
517          mi.setArguments(new Object JavaDoc[0]);
518          return getInterceptor().invoke(mi);
519       }
520       return getInterceptor().invokeHome(mi);
521    }
522
523    public Object JavaDoc internalInvoke(Invocation mi) throws Exception JavaDoc
524    {
525       // Invoke through interceptors
526
return getInterceptor().invoke(mi);
527    }
528
529    // EJBObject implementation --------------------------------------
530

531    public void remove(Invocation mi)
532       throws RemoteException JavaDoc, RemoveException JavaDoc
533    {
534       // synchronize entities with the datastore before the bean is removed
535
// this will write queued updates so datastore will be consistent before removal
536
Transaction JavaDoc tx = mi.getTransaction();
537       if (!getBeanMetaData().getContainerConfiguration().getSyncOnCommitOnly())
538          synchronizeEntitiesWithinTransaction(tx);
539
540       // Get the persistence manager to do the dirty work
541
EntityEnterpriseContext ctx = (EntityEnterpriseContext)mi.getEnterpriseContext();
542       getPersistenceManager().removeEntity(ctx);
543
544       Object JavaDoc pk = ctx.getId();
545       removeTimerService(pk);
546
547       // We signify "removed" with a null id
548
// There is no need to synchronize on the context since all the threads reaching here have
549
// gone through the InstanceInterceptor so the instance is locked and we only have one thread
550
// the case of reentrant threads is unclear (would you want to delete an instance in reentrancy)
551
ctx.setId(null);
552       removeCount++;
553    }
554
555    /**
556     * @throws Error Not yet implemented.
557     */

558    public Handle JavaDoc getHandle(Invocation mi)
559       throws RemoteException JavaDoc
560    {
561       // TODO
562
throw new Error JavaDoc("Not yet implemented");
563    }
564
565    public Object JavaDoc getPrimaryKey(Invocation mi)
566       throws RemoteException JavaDoc
567    {
568       return mi.getId();
569    }
570
571    /**
572     * @throws IllegalStateException If container invoker is null.
573     */

574    public EJBHome JavaDoc getEJBHome(Invocation mi)
575       throws RemoteException JavaDoc
576    {
577       EJBProxyFactory ci = getProxyFactory();
578       if (ci == null)
579       {
580          String JavaDoc msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
581          throw new IllegalStateException JavaDoc(msg);
582       }
583       return (EJBHome JavaDoc) ci.getEJBHome();
584    }
585
586    public boolean isIdentical(Invocation mi)
587       throws RemoteException JavaDoc
588    {
589       EJBProxyFactory ci = getProxyFactory();
590       if (ci == null)
591       {
592          String JavaDoc msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
593          throw new IllegalStateException JavaDoc(msg);
594       }
595
596       return ci.isIdentical(this, mi);
597    }
598
599    /**
600     * MF FIXME these are implemented on the client
601     */

602    public EJBLocalHome JavaDoc getEJBLocalHome(Invocation mi)
603    {
604       return localProxyFactory.getEJBLocalHome();
605    }
606
607    /**
608     * @throws Error Not yet implemented.
609     */

610    public void removeLocalHome(Invocation mi)
611       throws RemoteException JavaDoc, RemoveException JavaDoc
612    {
613       throw new Error JavaDoc("Not Yet Implemented");
614    }
615
616    /**
617     * Local home interface implementation
618     */

619    public EJBLocalObject JavaDoc createLocalHome(Invocation mi)
620       throws Exception JavaDoc
621    {
622       // The persistence manager takes care of the wiring and creating the EJBLocalObject
623
final EntityEnterpriseContext ctx = (EntityEnterpriseContext)mi.getEnterpriseContext();
624       getPersistenceManager().createEntity(mi.getMethod(), mi.getArguments(), ctx);
625
626       // The context implicitely carries the EJBObject
627
createCount++;
628       return localProxyFactory.getEntityEJBLocalObject(ctx.getId(), true);
629    }
630
631    /**
632     * Delegates to the persistence manager postCreateEntityMethod.
633     */

634    public void postCreateLocalHome(Invocation mi) throws Exception JavaDoc
635    {
636       // The persistence manager takes care of the post create step
637
getPersistenceManager().postCreateEntity(mi.getMethod(),mi.getArguments(),
638          (EntityEnterpriseContext) mi.getEnterpriseContext());
639    }
640
641    public Object JavaDoc findLocal(Invocation mi)
642       throws Exception JavaDoc
643    {
644       Method JavaDoc method = mi.getMethod();
645       Object JavaDoc[] args = mi.getArguments();
646       EntityEnterpriseContext instance = (EntityEnterpriseContext)mi.getEnterpriseContext();
647
648       boolean syncOnCommitOnly = metaData.getContainerConfiguration().getSyncOnCommitOnly();
649       Transaction JavaDoc tx = mi.getTransaction();
650
651       Class JavaDoc returnType = method.getReturnType();
652       if (Collection JavaDoc.class.isAssignableFrom(returnType) || returnType == Enumeration JavaDoc.class)
653       {
654          // as per the spec 9.6.4, entities must be synchronized with the datastore when an ejbFind<METHOD> is called.
655
if (!syncOnCommitOnly)
656          {
657             synchronizeEntitiesWithinTransaction(tx);
658          }
659
660          // Iterator finder
661
Collection JavaDoc c = getPersistenceManager().findEntities(method, args, instance, localProxyFactory);
662
663          // BMP entity finder methods are allowed to return java.util.Enumeration.
664
if (returnType == Enumeration JavaDoc.class)
665          {
666             return java.util.Collections.enumeration(c);
667          }
668          else
669          {
670             return c;
671          }
672       }
673       else
674       {
675          return findSingleObject(tx, method, args, instance, localProxyFactory);
676       }
677    }
678
679    // Home interface implementation ---------------------------------
680

681    /**
682     * This methods finds the target instances by delegating to the persistence
683     * manager It then manufactures EJBObject for all the involved instances
684     * found.
685     */

686    public Object JavaDoc find(Invocation mi) throws Exception JavaDoc
687    {
688       EJBProxyFactory ci = getProxyFactory();
689       if (ci == null)
690       {
691          String JavaDoc msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
692          throw new IllegalStateException JavaDoc(msg);
693       }
694
695       Method JavaDoc method = mi.getMethod();
696       Object JavaDoc[] args = mi.getArguments();
697       EntityEnterpriseContext instance = (EntityEnterpriseContext)mi.getEnterpriseContext();
698
699       boolean syncOnCommitOnly = metaData.getContainerConfiguration().getSyncOnCommitOnly();
700       Transaction JavaDoc tx = mi.getTransaction();
701
702       Class JavaDoc returnType = method.getReturnType();
703       if (Collection JavaDoc.class.isAssignableFrom(returnType) || returnType == Enumeration JavaDoc.class)
704       {
705          // as per the spec 9.6.4, entities must be synchronized with the datastore when an ejbFind<METHOD> is called.
706
if (!syncOnCommitOnly)
707          {
708             synchronizeEntitiesWithinTransaction(tx);
709          }
710
711          // Iterator finder
712
Collection JavaDoc c = getPersistenceManager().findEntities(method, args, instance, ci);
713
714          // BMP entity finder methods are allowed to return java.util.Enumeration.
715
// We need a serializable Enumeration, so we can't use Collections.enumeration()
716
if (returnType == Enumeration JavaDoc.class)
717          {
718             return new SerializableEnumeration(c);
719          }
720          else
721          {
722             return c;
723          }
724       }
725       else
726       {
727          return findSingleObject(tx, method, args, instance, ci);
728       }
729    }
730
731    /**
732     * Invokes ejbStore method on the instance
733     * @param ctx the instance to invoke ejbStore on
734     * @throws Exception
735     */

736    public void invokeEjbStore(EntityEnterpriseContext ctx) throws Exception JavaDoc
737    {
738       if (ctx.getId() != null)
739       {
740          final EntityPersistenceManager pm = getPersistenceManager();
741          pm.invokeEjbStore(ctx);
742       }
743    }
744
745    /**
746     * For CMP actually stores the instance
747     */

748    public void storeEntity(EntityEnterpriseContext ctx) throws Exception JavaDoc
749    {
750       if (ctx.getId() != null)
751       {
752          final EntityPersistenceManager pm = getPersistenceManager();
753          if(pm.isStoreRequired(ctx))
754          {
755             pm.storeEntity(ctx);
756          }
757       }
758    }
759
760    /**
761     * Delegates to the persistence manager postCreateEntityMethod.
762     */

763    public void postCreateHome(Invocation mi) throws Exception JavaDoc
764    {
765       // The persistence manager takes care of the post create step
766
getPersistenceManager().postCreateEntity(mi.getMethod(),mi.getArguments(),
767          (EntityEnterpriseContext) mi.getEnterpriseContext());
768    }
769
770    /**
771     * This method takes care of the wiring of the "EJBObject" trio
772     * (target, context, proxy). It delegates to the persistence manager.
773     */

774    public EJBObject JavaDoc createHome(Invocation mi)
775       throws Exception JavaDoc
776    {
777       // The persistence manager takes care of the wiring and creating the EJBObject
778
getPersistenceManager().createEntity(mi.getMethod(),mi.getArguments(),
779          (EntityEnterpriseContext) mi.getEnterpriseContext());
780
781       // The context implicitely carries the EJBObject
782
createCount++;
783       return ((EntityEnterpriseContext)mi.getEnterpriseContext()).getEJBObject();
784    }
785
786    /**
787     * A method for the getEJBObject from the handle
788     */

789    public EJBObject JavaDoc getEJBObject(Invocation mi)
790       throws RemoteException JavaDoc
791    {
792       EJBProxyFactory ci = getProxyFactory();
793       if (ci == null)
794       {
795          String JavaDoc msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
796          throw new IllegalStateException JavaDoc(msg);
797       }
798       // All we need is an EJBObject for this Id;
799
return (EJBObject JavaDoc)ci.getEntityEJBObject(((EntityCache) instanceCache).createCacheKey(mi.getId()));
800    }
801
802    // EJBHome implementation ----------------------------------------
803

804    /**
805     * @throws Error Not yet implemented.
806     */

807    public void removeHome(Invocation mi)
808       throws RemoteException JavaDoc, RemoveException JavaDoc
809    {
810       throw new Error JavaDoc("Not yet implemented");
811    }
812
813    public EJBMetaData JavaDoc getEJBMetaDataHome(Invocation mi)
814       throws RemoteException JavaDoc
815    {
816       EJBProxyFactory ci = getProxyFactory();
817       if (ci == null)
818       {
819          String JavaDoc msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
820          throw new IllegalStateException JavaDoc(msg);
821       }
822       return ci.getEJBMetaData();
823    }
824
825    /**
826     * @throws Error Not yet implemented.
827     */

828    public HomeHandle JavaDoc getHomeHandleHome(Invocation mi)
829       throws RemoteException JavaDoc
830    {
831       // TODO
832
throw new Error JavaDoc("Not yet implemented");
833    }
834
835    /**
836     * @jmx.managed-attribute
837     * @return the current cache size
838     */

839    public long getCacheSize()
840    {
841       return instanceCache.getCacheSize();
842    }
843
844    /** Flush the cache
845     * @jmx.managed-operation
846     */

847    public void flushCache()
848    {
849       instanceCache.flush();
850    }
851
852    // StatisticsProvider implementation ------------------------------------
853

854    public Map JavaDoc retrieveStatistic()
855    {
856       // Loop through all Interceptors and add statistics
857
Map JavaDoc lStatistics = new HashMap JavaDoc();
858       StatisticsProvider lProvider = (StatisticsProvider) getPersistenceManager();
859       lStatistics.putAll( lProvider.retrieveStatistic() );
860       lProvider = (StatisticsProvider) getInstancePool();
861       lStatistics.putAll( lProvider.retrieveStatistic() );
862       return lStatistics;
863    }
864
865    public void resetStatistic()
866    {
867    }
868
869    // Private -------------------------------------------------------
870

871    private void setupHomeMappingImpl(Method JavaDoc[] m,
872                                      String JavaDoc finderName,
873                                      String JavaDoc append)
874       throws Exception JavaDoc
875    {
876       // Adrian Brock: This should go away when we don't support EJB1x
877
boolean isEJB1x = metaData.getApplicationMetaData().isEJB1x();
878
879       for (int i = 0; i < m.length; i++)
880       {
881          String JavaDoc methodName = m[i].getName();
882          try
883          {
884             try // Try home method
885
{
886                String JavaDoc ejbHomeMethodName = "ejbHome" + methodName.substring(0,1).toUpperCase() + methodName.substring(1);
887                homeMapping.put(m[i], beanClass.getMethod(ejbHomeMethodName, m[i].getParameterTypes()));
888
889                continue;
890             }
891             catch (NoSuchMethodException JavaDoc ignore) {} // just go on with other types of methods
892

893
894             // Implemented by container (in both cases)
895
if (methodName.startsWith("find"))
896             {
897                homeMapping.put(m[i], this.getClass().getMethod(finderName, new Class JavaDoc[] { Invocation.class }));
898             }
899             else if (methodName.equals("create") ||
900                   (isEJB1x == false && methodName.startsWith("create")))
901             {
902                homeMapping.put(m[i], this.getClass().getMethod("create"+append, new Class JavaDoc[] { Invocation.class }));
903                beanMapping.put(m[i], this.getClass().getMethod("postCreate"+append, new Class JavaDoc[] { Invocation.class }));
904             }
905             else
906             {
907                homeMapping.put(m[i], this.getClass().getMethod(methodName+append, new Class JavaDoc[] { Invocation.class }));
908             }
909          }
910          catch (NoSuchMethodException JavaDoc e)
911          {
912             throw new NoSuchMethodException JavaDoc("Could not find matching method for "+m[i]);
913          }
914       }
915    }
916
917    protected void setupHomeMapping() throws Exception JavaDoc
918    {
919       try {
920          if (homeInterface != null)
921          {
922             Method JavaDoc[] m = homeInterface.getMethods();
923             setupHomeMappingImpl( m, "find", "Home" );
924          }
925          if (localHomeInterface != null)
926          {
927             Method JavaDoc[] m = localHomeInterface.getMethods();
928             setupHomeMappingImpl( m, "findLocal", "LocalHome" );
929          }
930
931          // Special methods
932

933          // Get the One on Handle (getEJBObject), get the class
934
Class JavaDoc handleClass = Class.forName("javax.ejb.Handle");
935
936          // Get the methods (there is only one)
937
Method JavaDoc[] handleMethods = handleClass.getMethods();
938
939          //Just to make sure let's iterate
940
for (int j=0; j<handleMethods.length ;j++)
941          {
942             //Get only the one called handle.getEJBObject
943
if (handleMethods[j].getName().equals("getEJBObject"))
944             {
945                //Map it in the home stuff
946
homeMapping.put(handleMethods[j],
947                                this.getClass().getMethod("getEJBObject",
948                                                          new Class JavaDoc[] {Invocation.class}));
949             }
950          }
951       }
952       catch (Exception JavaDoc e)
953       {
954          // ditch the half built mappings
955
homeMapping.clear();
956          beanMapping.clear();
957
958          throw e;
959       }
960    }
961
962    private void setupBeanMappingImpl( Method JavaDoc[] m, String JavaDoc intfName )
963       throws Exception JavaDoc
964    {
965       for (int i = 0; i < m.length; i++)
966       {
967          if (!m[i].getDeclaringClass().getName().equals(intfName))
968          {
969             // Implemented by bean
970
beanMapping.put(m[i], beanClass.getMethod(m[i].getName(), m[i].getParameterTypes()));
971          }
972          else
973          {
974             // Implemented by container
975
beanMapping.put(m[i], getClass().getMethod(m[i].getName(),
976                                                        new Class JavaDoc[] { Invocation.class }));
977          }
978       }
979    }
980
981    protected void setupBeanMapping() throws Exception JavaDoc
982    {
983       try {
984          if (remoteInterface != null)
985          {
986             Method JavaDoc[] m = remoteInterface.getMethods();
987             setupBeanMappingImpl( m, "javax.ejb.EJBObject" );
988          }
989          if (localInterface != null)
990          {
991             Method JavaDoc[] m = localInterface.getMethods();
992             setupBeanMappingImpl( m, "javax.ejb.EJBLocalObject" );
993          }
994          if( TimedObject JavaDoc.class.isAssignableFrom( beanClass ) ) {
995              // Map ejbTimeout
996
beanMapping.put(
997                 TimedObject JavaDoc.class.getMethod( "ejbTimeout", new Class JavaDoc[] { Timer JavaDoc.class } ),
998                 beanClass.getMethod( "ejbTimeout", new Class JavaDoc[] { Timer JavaDoc.class } )
999              );
1000         }
1001      }
1002      catch (Exception JavaDoc e)
1003      {
1004         // ditch the half built mappings
1005
homeMapping.clear();
1006         beanMapping.clear();
1007
1008         throw e;
1009      }
1010   }
1011
1012   protected void setupMarshalledInvocationMapping() throws Exception JavaDoc
1013   {
1014      // Create method mappings for container invoker
1015
if (homeInterface != null)
1016      {
1017         Method JavaDoc [] m = homeInterface.getMethods();
1018         for (int i = 0 ; i<m.length ; i++)
1019         {
1020            marshalledInvocationMapping.put( new Long JavaDoc(MarshalledInvocation.calculateHash(m[i])), m[i]);
1021         }
1022      }
1023
1024      if (remoteInterface != null)
1025      {
1026         Method JavaDoc [] m = remoteInterface.getMethods();
1027         for (int j = 0 ; j<m.length ; j++)
1028         {
1029            marshalledInvocationMapping.put( new Long JavaDoc(MarshalledInvocation.calculateHash(m[j])), m[j]);
1030         }
1031      }
1032
1033      // Get the getEJBObjectMethod
1034
Method JavaDoc getEJBObjectMethod = Class.forName("javax.ejb.Handle").getMethod("getEJBObject", new Class JavaDoc[0]);
1035
1036      // Hash it
1037
marshalledInvocationMapping.put(new Long JavaDoc(MarshalledInvocation.calculateHash(getEJBObjectMethod)),getEJBObjectMethod);
1038   }
1039
1040   Interceptor createContainerInterceptor()
1041   {
1042      return new ContainerInterceptor();
1043   }
1044
1045   protected void checkCoherency () throws Exception JavaDoc
1046   {
1047      // Check clustering cohrency wrt metadata
1048
//
1049
if (metaData.isClustered())
1050      {
1051         boolean clusteredProxyFactoryFound = false;
1052         for (Iterator JavaDoc it = proxyFactories.keySet().iterator(); it.hasNext(); )
1053         {
1054            String JavaDoc invokerBinding = (String JavaDoc)it.next();
1055            EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding);
1056            if (ci instanceof org.jboss.proxy.ejb.ClusterProxyFactory)
1057               clusteredProxyFactoryFound = true;
1058         }
1059
1060         if (!clusteredProxyFactoryFound)
1061         {
1062            log.warn("*** EJB '" + this.metaData.getEjbName() + "' deployed as CLUSTERED but not a single clustered-invoker is bound to container ***");
1063         }
1064      }
1065   }
1066
1067   private Object JavaDoc findSingleObject(Transaction JavaDoc tx,
1068                                   Method JavaDoc method,
1069                                   Object JavaDoc[] args,
1070                                   EntityEnterpriseContext instance,
1071                                   GenericEntityObjectFactory factory)
1072      throws Exception JavaDoc
1073   {
1074      if(method.getName().equals("findByPrimaryKey"))
1075      {
1076         if(args[0] == null)
1077            throw new IllegalArgumentException JavaDoc("findByPrimaryKey called with null argument.");
1078
1079         if(metaData.getContainerConfiguration().getCommitOption() != ConfigurationMetaData.B_COMMIT_OPTION)
1080         {
1081            Object JavaDoc key = instance.getCacheKey();
1082            if(key == null)
1083            {
1084               key = ((EntityCache)instanceCache).createCacheKey(args[0]);
1085            }
1086
1087            if(instanceCache.isActive(key))
1088            {
1089               return factory.getEntityEJBObject(key);
1090            }
1091         }
1092      }
1093      else if(!metaData.getContainerConfiguration().getSyncOnCommitOnly())
1094      {
1095         EntityContainer.synchronizeEntitiesWithinTransaction(tx);
1096      }
1097
1098      return getPersistenceManager().findEntity(method, args, instance, factory);
1099   }
1100
1101   // Inner classes -------------------------------------------------
1102

1103   /**
1104    * This is the last step before invocation - all interceptors are done
1105    */

1106   class ContainerInterceptor
1107      extends AbstractContainerInterceptor
1108   {
1109      public Object JavaDoc invokeHome(Invocation mi) throws Exception JavaDoc
1110      {
1111         // Invoke and handle exceptions
1112
Method JavaDoc miMethod = mi.getMethod();
1113         Method JavaDoc m = (Method JavaDoc) homeMapping.get(miMethod);
1114         if( m == null )
1115         {
1116            String JavaDoc msg = "Invalid invocation, check your deployment packaging"
1117               +", method="+miMethod;
1118            throw new EJBException JavaDoc(msg);
1119         }
1120
1121         if (m.getDeclaringClass().equals(EntityContainer.class))
1122         {
1123            try
1124            {
1125               return mi.performCall(EntityContainer.this, m, new Object JavaDoc[] { mi });
1126            }
1127            catch (Exception JavaDoc e)
1128            {
1129               rethrow(e);
1130            }
1131         }
1132         else // Home method
1133
{
1134            EnterpriseContext ctx = (EnterpriseContext) mi.getEnterpriseContext();
1135            try
1136            {
1137               AllowedOperationsAssociation.pushInMethodFlag(AllowedOperationsAssociation.IN_EJB_HOME);
1138               return mi.performCall(ctx.getInstance(), m, mi.getArguments());
1139            }
1140            catch (Exception JavaDoc e)
1141            {
1142               rethrow(e);
1143            }
1144            finally{
1145               AllowedOperationsAssociation.popInMethodFlag();
1146            }
1147         }
1148
1149         // We will never get this far, but the compiler does not know that
1150
throw new org.jboss.util.UnreachableStatementException();
1151      }
1152
1153      public Object JavaDoc invoke(Invocation mi) throws Exception JavaDoc
1154      {
1155         // Get method
1156
Method JavaDoc miMethod = mi.getMethod();
1157         Method JavaDoc m = (Method JavaDoc) beanMapping.get(miMethod);
1158         if( m == null )
1159         {
1160            String JavaDoc msg = "Invalid invocation, check your deployment packaging"
1161               +", method="+miMethod;
1162            throw new EJBException JavaDoc(msg);
1163         }
1164
1165         // Select instance to invoke (container or bean)
1166
if (m.getDeclaringClass().equals(EntityContainer.class))
1167         {
1168            // Invoke container
1169
try
1170            {
1171               return mi.performCall(EntityContainer.this, m, new Object JavaDoc[]{ mi });
1172            }
1173            catch (Exception JavaDoc e)
1174            {
1175               rethrow(e);
1176            }
1177         }
1178         else
1179         {
1180            // Invoke bean instance
1181
try
1182            {
1183               EnterpriseContext ctx = (EnterpriseContext) mi.getEnterpriseContext();
1184               Object JavaDoc instance = ctx.getInstance();
1185
1186               return mi.performCall(instance, m, mi.getArguments());
1187            }
1188            catch (Exception JavaDoc e)
1189            {
1190               rethrow(e);
1191            }
1192         }
1193
1194         // We will never get this far, but the compiler does not know that
1195
throw new org.jboss.util.UnreachableStatementException();
1196      }
1197   }
1198}
1199
Popular Tags