Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » ejb » plugins » [javadoc | source]
    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;
   25   import java.lang.reflect.InvocationTargetException;
   26   import java.rmi.RemoteException;
   27   import java.util.Collection;
   28   import java.util.HashMap;
   29   
   30   import javax.ejb.EntityBean;
   31   import javax.ejb.RemoveException;
   32   import javax.ejb.EJBException;
   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 createMethods = new HashMap();
   71      HashMap postCreateMethods = new HashMap();
   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
  114      {
  115         if(con.getHomeClass() != null)
  116         {
  117            Method[] methods = con.getHomeClass().getMethods();
  118            createMethodCache(methods);
  119         }
  120   
  121         if(con.getLocalHomeClass() != null)
  122         {
  123            Method[] 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 createBeanClassInstance() throws Exception
  138      {
  139         return store.createBeanClassInstance();
  140      }
  141   
  142      private void createMethodCache(Method[] methods)
  143         throws NoSuchMethodException
  144      {
  145         // Create cache of create methods
  146         Class beanClass = con.getBeanClass();
  147         for(int i = 0; i < methods.length; i++)
  148         {
  149            String name = methods[i].getName();
  150            if(name.startsWith("create"))
  151            {
  152               Class[] types = methods[i].getParameterTypes();
  153               try
  154               {
  155                  String nameSuffix = name.substring(0, 1).toUpperCase() + name.substring(1);
  156                  Method 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 nsme)
  162               {
  163                  throw new NoSuchMethodException("Can't find ejb[Post]Create in " + beanClass.getName());
  164               }
  165            }
  166         }
  167      }
  168   
  169      public void start()
  170         throws Exception
  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 m, Object[] args, EntityEnterpriseContext ctx)
  186         throws Exception
  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 createMethod = (Method) createMethods.get(m);
  196            createMethod.invoke(ctx.getInstance(), args);
  197         }
  198         catch(IllegalAccessException e)
  199         {
  200            // Throw this as a bean exception...(?)
  201            throw new EJBException(e);
  202         }
  203         catch(InvocationTargetException ite)
  204         {
  205            Throwable e = ite.getTargetException();
  206            if(e instanceof EJBException)
  207            {
  208               // Rethrow exception
  209               throw (EJBException) e;
  210            }
  211            else if(e instanceof RuntimeException)
  212            {
  213               // Wrap runtime exceptions
  214               throw new EJBException((Exception) e);
  215            }
  216            else if(e instanceof Exception)
  217            {
  218               // Remote, Create, or custom app. exception
  219               throw (Exception) e;
  220            }
  221            else
  222            {
  223               throw (Error) 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 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 cacheKey = ((EntityCache) con.getInstanceCache()).createCacheKey(id);
  249   
  250         // Give it to the context
  251         ctx.setCacheKey(cacheKey);
  252      }
  253   
  254      public void postCreateEntity(Method m, Object[] args, EntityEnterpriseContext ctx)
  255         throws Exception
  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 postCreateMethod = (Method) postCreateMethods.get(m);
  266            postCreateMethod.invoke(ctx.getInstance(), args);
  267            if(insertAfterEjbPostCreate)
  268            {
  269               store.createEntity(m, args, ctx);
  270            }
  271         }
  272         catch(IllegalAccessException e)
  273         {
  274            // Throw this as a bean exception...(?)
  275            throw new EJBException(e);
  276         }
  277         catch(InvocationTargetException ite)
  278         {
  279            Throwable e = ite.getTargetException();
  280            if(e instanceof EJBException)
  281            {
  282               // Rethrow exception
  283               throw (EJBException) e;
  284            }
  285            else if(e instanceof RuntimeException)
  286            {
  287               // Wrap runtime exceptions
  288               throw new EJBException((Exception) e);
  289            }
  290            else if(e instanceof Exception)
  291            {
  292               // Remote, Create, or custom app. exception
  293               throw (Exception) e;
  294            }
  295            else
  296            {
  297               throw (Error) e;
  298            }
  299         }
  300         finally
  301         {
  302            AllowedOperationsAssociation.popInMethodFlag();
  303         }
  304      }
  305   
  306      public Object findEntity(Method finderMethod,
  307                               Object[] args,
  308                               EntityEnterpriseContext ctx,
  309                               GenericEntityObjectFactory factory)
  310         throws Exception
  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 findEntities(Method finderMethod,
  327                                     Object[] args,
  328                                     EntityEnterpriseContext ctx,
  329                                     GenericEntityObjectFactory factory)
  330         throws Exception
  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
  358      {
  359         // Create a new CacheKey
  360         Object id = ctx.getId();
  361         Object 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 eb = (EntityBean) ctx.getInstance();
  370            eb.ejbActivate();
  371         }
  372         catch(Exception e)
  373         {
  374            if(e instanceof RemoteException)
  375            {
  376               // Rethrow exception
  377               throw (RemoteException) e;
  378            }
  379            else if(e instanceof EJBException)
  380            {
  381               // Rethrow exception
  382               throw (EJBException) e;
  383            }
  384            else
  385            {
  386               // Wrap runtime exceptions
  387               throw new EJBException((Exception) 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
  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
  413      {
  414         return store.isStoreRequired(ctx);
  415      }
  416   
  417      public boolean isModified(EntityEnterpriseContext ctx) throws Exception
  418      {
  419         return store.isModified(ctx);
  420      }
  421   
  422      public void storeEntity(EntityEnterpriseContext ctx)
  423         throws RemoteException
  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
  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 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
  474      {
  475         try
  476         {
  477            AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_PASSIVATE);
  478            EntityBean eb = (EntityBean) ctx.getInstance();
  479            eb.ejbPassivate();
  480         }
  481         catch(Exception 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, RemoveException
  497      {
  498         try
  499         {
  500            AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_REMOVE);
  501            EntityBean eb = (EntityBean) ctx.getInstance();
  502            eb.ejbRemove();
  503         }
  504         catch(Exception e)
  505         {
  506            if(e instanceof RemoveException)
  507            {
  508               // Rethrow exception
  509               throw (RemoveException) 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
  525      {
  526         try
  527         {
  528            AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_LOAD);
  529   
  530            EntityBean eb = (EntityBean) ctx.getInstance();
  531            eb.ejbLoad();
  532         }
  533         catch(Exception 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
  547      {
  548         try
  549         {
  550            EntityBean eb = (EntityBean) ctx.getInstance();
  551            eb.ejbStore();
  552         }
  553         catch(Exception e)
  554         {
  555            throwRemoteException(e);
  556         }
  557      }
  558   
  559      private void throwRemoteException(Exception e)
  560         throws RemoteException
  561      {
  562         if(e instanceof RemoteException)
  563         {
  564            // Rethrow exception
  565            throw (RemoteException) e;
  566         }
  567         else if(e instanceof EJBException)
  568         {
  569            // Rethrow exception
  570            throw (EJBException) e;
  571         }
  572         else
  573         {
  574            // Wrap runtime exceptions
  575            throw new EJBException((Exception) e);
  576         }
  577      }
  578   }

Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » ejb » plugins » [javadoc | source]