User: mnf999  
  Date: 01/08/01 11:26:57

  Modified:    src/main/org/jboss/ejb/plugins
                        EntityInstanceInterceptor.java
  Log:
  With the new Bill lock we can in fact factored the full locking mechanisms to a 
whole new interceptor with pluggable policies.  This results in a GREATLY simplified 
design for this interceptor, just a few straightforward lines
  
  Revision  Changes    Path
  1.40      +258 -422  
jboss/src/main/org/jboss/ejb/plugins/EntityInstanceInterceptor.java
  
  Index: EntityInstanceInterceptor.java
  ===================================================================
  RCS file: 
/cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/EntityInstanceInterceptor.java,v
  retrieving revision 1.39
  retrieving revision 1.40
  diff -u -r1.39 -r1.40
  --- EntityInstanceInterceptor.java    2001/07/17 04:37:32     1.39
  +++ EntityInstanceInterceptor.java    2001/08/01 18:26:57     1.40
  @@ -1,9 +1,9 @@
   /*
  - * JBoss, the OpenSource EJB server
  - *
  - * Distributable under LGPL license.
  - * See terms of license at gnu.org.
  - */
  +* JBoss, the OpenSource EJB server
  +*
  +* Distributable under LGPL license.
  +* See terms of license at gnu.org.
  +*/
   package org.jboss.ejb.plugins;
   
   import java.lang.reflect.Method;
  @@ -26,6 +26,8 @@
   import javax.transaction.SystemException;
   
   import org.jboss.ejb.Container;
  +import org.jboss.ejb.BeanLock;
  +import org.jboss.ejb.BeanLockManager;
   import org.jboss.ejb.EntityContainer;
   import org.jboss.ejb.EntityPersistenceManager;
   import org.jboss.ejb.EntityEnterpriseContext;
  @@ -36,438 +38,272 @@
   import org.jboss.ejb.CacheKey;
   import org.jboss.logging.log4j.JBossCategory;
   import org.jboss.metadata.EntityMetaData;
  -import org.jboss.util.Sync;
   import org.jboss.tm.TxManager;
   
   /**
  - * The instance interceptors role is to acquire a context representing
  - * the target object from the cache.
  - *
  - * <p>This particular container interceptor implements pessimistic locking
  - *    on the transaction that is associated with the retrieved instance.  If
  - *    there is a transaction associated with the target component and it is
  - *    different from the transaction associated with the MethodInvocation
  - *    coming in then the policy is to wait for transactional commit. 
  - *   
  - * <p>We also implement serialization of calls in here (this is a spec
  - *    requirement). This is a fine grained notify, notifyAll mechanism. We
  - *    notify on ctx serialization locks and notifyAll on global transactional
  - *    locks.
  - *   
  - * <p><b>WARNING: critical code</b>, get approval from senior developers
  - *    before changing.
  - *    
  - * @author <a href="mailto:[EMAIL PROTECTED]";>Marc Fleury</a>
  - * @author <a href="mailto:[EMAIL PROTECTED]";>Scott Stark</a>
  - * @author <a href="mailto:[EMAIL PROTECTED]";>Bill Burke</a>
  - * @version $Revision: 1.39 $
  - *
  - * <p><b>Revisions:</b><br>
  - * <p><b>2001/06/28: marcf</b>
  - * <ol>
  - *   <li>Moved to new synchronization
  - *   <li>Pools are gone simple design
  - *   <li>two levels of syncrhonization with Tx and ctx
  - *   <li>remove busy wait from previous mechanisms
  - * </ol>
  - * <p><b>2001/07/11: starksm</b>
  - * <ol>
  - *   <li>Fix a thread starvation problem due to incomplete condition notification
  - *   <li>Add support for trace level diagnositics
  - * </ol>
  - * <p><b>2001/07/12: starksm</b>
  - * <ol>
  - *   <li>Handle a race condition when there is no ctx transaction
  - * </ol>
  - * </ol>
  - * <p><b>2001/07/16: billb</b>
  - * <ol>
  - *   <li>Added wait(timeout) code, commented out so that we can easily turn it on
  - *   when this new code is done with it's trial period.
  - *   <li>Fixed bug when ejbLoad threw an exception and threads waiting 
  - *   on TxLock did not get awakened.
  - *   
  - * </ol>
  - */
  +* The instance interceptors role is to acquire a context representing
  +* the target object from the cache.
  +*
  +* <p>This particular container interceptor implements pessimistic locking
  +*    on the transaction that is associated with the retrieved instance.  If
  +*    there is a transaction associated with the target component and it is
  +*    different from the transaction associated with the MethodInvocation
  +*    coming in then the policy is to wait for transactional commit. 
  +*   
  +* <p>We also implement serialization of calls in here (this is a spec
  +*    requirement). This is a fine grained notify, notifyAll mechanism. We
  +*    notify on ctx serialization locks and notifyAll on global transactional
  +*    locks.
  +*   
  +* <p><b>WARNING: critical code</b>, get approval from senior developers
  +*    before changing.
  +*    
  +* @author <a href="mailto:[EMAIL PROTECTED]";>Marc Fleury</a>
  +* @author <a href="mailto:[EMAIL PROTECTED]";>Scott Stark</a>
  +* @author <a href="mailto:[EMAIL PROTECTED]";>Bill Burke</a>
  +* @version $Revision: 1.40 $
  +*
  +* <p><b>Revisions:</b><br>
  +* <p><b>2001/06/28: marcf</b>
  +* <ol>
  +*   <li>Moved to new synchronization
  +*   <li>Pools are gone simple design
  +*   <li>two levels of syncrhonization with Tx and ctx
  +*   <li>remove busy wait from previous mechanisms
  +* </ol>
  +* <p><b>2001/07/11: starksm</b>
  +* <ol>
  +*   <li>Fix a thread starvation problem due to incomplete condition notification
  +*   <li>Add support for trace level diagnositics
  +* </ol>
  +* <p><b>2001/07/12: starksm</b>
  +* <ol>
  +*   <li>Handle a race condition when there is no ctx transaction
  +* </ol>
  +* </ol>
  +* <p><b>2001/07/16: billb</b>
  +* <ol>
  +*   <li>Added wait(timeout) code, commented out so that we can easily turn it on
  +*   when this new code is done with it's trial period.
  +*   <li>Fixed bug when ejbLoad threw an exception and threads waiting 
  +*   on TxLock did not get awakened.
  +* </ol>
  +* <p><b>2001/07/26: billb</b>
  +* <ol>
  +*   <li>Locking is now separate from EntityEnterpriseContext objects and is now
  +*   encapsulated in BeanLock and BeanLockManager.  Did this because the lifetime
  +*   of an EntityLock is sometimes longer than the lifetime of the ctx.
  +* </ol>
  +* <p><b>2001/08/1: marcf</b>
  +* <ol>
  +*   <li> Taking the lock out pointed to something new, the fact that the locking 
policies
  +*    can be fully automated and factored out of the instance interceptor this 
results in a 
  +*    new interceptor EntityLockInterceptor that by design sits in front of this one 
in the 
  +*    chain of interceptors. 
  +*   <li> This interceptor is greatly simplified and all it does is retrieve the 
instance from cache
  +*   <li> Scheduling is implemented in new interceptor, all notify policies gone, 
simple
  +*   <li> For the record, locking went from cache (early 2.0) -> this interceptor -> 
new interceptor
  +*   <li> new locking is pluggable
  +* </ol>
  +*/
   public class EntityInstanceInterceptor
  -   extends AbstractInterceptor
  +extends AbstractInterceptor
   {
  -   // Constants -----------------------------------------------------
  +     // Constants -----------------------------------------------------
        
  -   // Attributes ----------------------------------------------------
  -
  -   protected EntityContainer container;
  -   protected int timeout;
  +     // Attributes ----------------------------------------------------
        
  -   // Static --------------------------------------------------------
  -
  -   /** Use a JBoss custom log4j category for trace level logging */
  -   static JBossCategory log = (JBossCategory) 
JBossCategory.getInstance(EntityInstanceInterceptor.class);
  -
  -   // Constructors --------------------------------------------------
  +     protected EntityContainer container;
        
  -   // Public --------------------------------------------------------
  -   
  -   public void setContainer(Container container)
  -   {
  -      this.container = (EntityContainer)container;
  -      timeout = 5000;
  -      if (container.getTransactionManager() != null)
  -      {
  -         if (container.getTransactionManager() instanceof TxManager)
  -         {
  -            TxManager mgr = (TxManager)container.getTransactionManager();
  -            timeout = (mgr.getDefaultTransactionTimeout() * 1000) + 50;
  -         }
  -      }
  -      boolean trace = log.isTraceEnabled();
  -      if ( trace )
  -         log.trace("wait timeout = " + timeout);
  -   }
  -     
  -   public Container getContainer()
  -   {
  -      return container;
  -   }
  -     
  -   // Interceptor implementation --------------------------------------
  -   
  -   public Object invokeHome(MethodInvocation mi)
  -      throws Exception
  -   {
  -      // Get context
  -      EnterpriseContext ctx = 
((EntityContainer)getContainer()).getInstancePool().get();
  -             
  -      // Pass it to the method invocation
  -      mi.setEnterpriseContext(ctx);
  -             
  -      // Give it the transaction
  -      ctx.setTransaction(mi.getTransaction());
  -             
  -      // This context is brand new. We can lock without more "fuss" 
  -      // The reason we need to lock it is that it will be put in cache before the 
end
  -      // of the call.  So another thread could access it before we are done.
  -             
  -      ctx.lock();
  -             
  -      try
  -      {
  -         // Invoke through interceptors
  -         return getNext().invokeHome(mi);
  -      } 
  -      finally
  -      {
  -         //Other threads can be coming for this instance if it is in cache
  -         synchronized(ctx) {
  -            // Always unlock, no matter what
  -            ctx.unlock();
  -            // Wake everyone up in case of create with Tx contention
  -            ctx.notifyAll();
  -         }
  -         //Do not send back to pools in any case, let the instance be GC'ed
  -      }
  -   }
  -     
  -   public Object invoke(MethodInvocation mi)
  -      throws Exception
  -   {
  -      // It's all about the context
  -      EntityEnterpriseContext ctx = null;
  -             
  -      // And it must correspond to the key.
  -      CacheKey key = (CacheKey) mi.getId();
  -      Transaction tx = null;
  -      boolean trace = log.isTraceEnabled();
  -      if( trace )
  -         log.trace("Begin invoke, key="+key);
  -      while (ctx == null)
  -      {
  -         // Maybe my transaction already expired?  This must be at the top of the 
loop.
  -         Transaction miTx = mi.getTransaction();
  -         if (miTx != null && miTx.getStatus() == Status.STATUS_MARKED_ROLLBACK)
  -         {
  -            log.error("Saw rolled back tx="+miTx);
  -            throw new RuntimeException("Transaction marked for rollback, possibly a 
timeout");
  -         }
  -
  -         // Ok, get moving...
  -         ctx = (EntityEnterpriseContext) container.getInstanceCache().get(key);
  -         if( trace )
  -            log.trace("Begin while ctx==null, ctx="+ctx);
  +     // Static --------------------------------------------------------
  +     
  +     /** Use a JBoss custom log4j category for trace level logging */
  +     static JBossCategory log = (JBossCategory) 
JBossCategory.getInstance(EntityInstanceInterceptor.class);
  +     
  +     // Constructors --------------------------------------------------
  +     
  +     // Public --------------------------------------------------------
  +     
  +     public void setContainer(Container container)
  +     {
  +             this.container = (EntityContainer)container;
  +     }
  +     
  +     public Container getContainer()
  +     {
  +             return container;
  +     }
  +     
  +     // Interceptor implementation --------------------------------------
  +     
  +     public Object invokeHome(MethodInvocation mi)
  +     throws Exception
  +     {
  +             // Get context
  +             EntityEnterpriseContext ctx = 
(EntityEnterpriseContext)((EntityContainer)getContainer()).getInstancePool().get();
  +             
  +             // Pass it to the method invocation
  +             mi.setEnterpriseContext(ctx);
  +             
  +             // Give it the transaction
  +             ctx.setTransaction(mi.getTransaction());
  +             
  +             try
  +             {
  +                     // Invoke through interceptors
  +                     return getNext().invokeHome(mi);
  +             } 
  +             finally
  +             {         
                        
  -         //Next test is independent of whether the context is locked or not, it is 
purely transactional
  -         // Is the instance involved with another transaction? if so we implement 
pessimistic locking
  -         synchronized(ctx.getTxLock()) 
  -         {
  -            tx = ctx.getTransaction();
  -            if( trace )
  -               log.trace("Checking tx on ctx="+ctx+", tx="+tx);
  -
  -            // Do we have a running transaction with the context?
  -            if (tx != null &&
  -                // And are we trying to enter with another transaction?
  -                !tx.equals(mi.getTransaction()))
  -            {
  -               // That's no good, only one transaction per context
  -               // Let's put the thread to sleep the transaction demarcation will 
wake them up
  -               if( trace )
  -                  log.trace("Transactional contention on context"+ctx.getId());
  -
  -               // Wait for it to finish, note that we use wait() and not 
wait(5000), why? 
  -               // cause we got cojones, if there a problem in this code we want a 
freeze not illusion
  -               // Threads finishing the transaction must notifyAll() on the 
ctx.txLock
  -               //
  -               // billb: wait() is good for debugging purposes, but transaction 
timeouts will
  -               // never rollback this thread.  wait() will wait forever and ever.  
You must uncomment
  -               // the wait(timeout) lines below to turn on transaction timeouts.  
BTW, remove this
  -               // comment when wait() is finally removed.
  -               try
  -               {
  -                  if( trace )
  -                     log.trace("Begin wait on TxLock="+tx);
  -                  // FIXME: Uncomment this next line to enable transaction timeouts
  -                  // ctx.getTxLock().wait(timeout);
  -                  ctx.getTxLock().wait(); // FIXME, delete this line when 2.5 is 
released
  -                  if( trace )
  -                     log.trace("End wait on TxLock="+tx);
  -               }
  -
  -               // We need to try again
  -               finally {ctx = null; continue;}
  -            }
  -
  -            /*
  -              In future versions we can use copies of the instance per transaction
  -            */
  -         }
  -
  -         // The next test is the pure serialization from the EJB specification.
  -         // If we are here we either did not have a tx(tx == null) or this is a
  -         // recursive call and the current ctx.tx == mi.tx
  -         synchronized(ctx) 
  -         {
  -            // synchronized is a time gap, when the thread enters here it can be 
after "sleep"
  -            // we need to make sure that stuff is still kosher
  -
  -            // First make sure another thread who saw a null tx has not already 
assigned a new tx
  -            if( tx == null && ctx.getTransaction() != null )
  -            {
  -               ctx = null;
  -               if( trace )
  -                  log.trace("End synchronized(ctx), ctx="+ctx+", lost ctx.tx 
race");         
  -               continue;
  -            }
  -
  -            if( trace )
  -               log.trace("Begin synchronized(ctx), ctx="+ctx+", mi.tx="+miTx);
  -            // We do not use pools any longer so the only thing that can happen is 
that 
  -            // a ctx has a null id (instance removed) (no more "wrong id" problem)
  -            if (ctx.getId() == null) 
  -            {
  -               // This will happen when the instance is removed from cache 
  -               // We need to go through the same mechs and get the new ctx
  -               ctx = null;
  -               if( trace )
  -                  log.trace("End synchronized(ctx), ctx="+ctx+", null id");         
 
  -               continue;
  -            }
  -            // So the ctx is still valid and the transaction is still game and we 
own the context
  -            // so no one can change ctx.  Make sure that all access to ctx is 
synchronized.
  +                     // Is the context now with an identity? in which case we need 
to insert
  +                     if (ctx.getId() != null)
  +                     {
                                
  -            // The ctx is still kosher go on with the real serialization
  +                             BeanLock lock = 
container.getLockManager().getLock(ctx.getCacheKey());
                                
  -            //Is the context used already (with or without a transaction), is it 
locked?
  -            if (ctx.isLocked()) 
  -            {
  -               // It is locked but re-entrant calls permitted (reentrant home ones 
are ok as well)
  -               if (!isCallAllowed(mi)) 
  -               {
  -                  // This instance is in use and you are not permitted to reenter
  -                  // Go to sleep and wait for the lock to be released
  -                  if( trace )
  -                     log.trace("Thread contention on context"+key);
  -
  -                  // we want to know about freezes so we wait(), let us know if 
this locks  
  -                  // Threads finishing invocation will come here and notify() on 
the ctx
  -                  try
  -                  {
  -                     if( trace )
  -                        log.trace("Begin ctx.wait(), ctx="+ctx);
  -                     // FIXME: Uncomment this next line to enable transaction 
timeouts
  -                     // ctx.wait(timeout);
  -                     ctx.wait(); //FIXME, delete this line when 2.5 is released.
  -                  }
  -                  catch (InterruptedException ignored) {}                           
         
  -                  // We need to try again
  -                  finally
  -                  {
  -                     if( trace )
  -                        log.trace("End ctx.wait(), ctx="+ctx+", 
isLocked="+ctx.isLocked());
  -                     ctx = null;
  -                     continue;
  -                  }
  -               }
  -               else
  -               {
  -                  //We are in a valid reentrant call so take the lock, take it!
  -                  ctx.lock();
  -                  if( trace )
  -                     log.trace("In synchronized(ctx), ctx="+ctx+", reentrant call, 
have lock");              
  -               }
  -            }
  -            // No one is using that context
  -            else 
  -            {
  -               // We are now using the context
  -               ctx.lock();
  -               if( trace )
  -                  log.trace("In synchronized(ctx), ctx="+ctx+", unused ctx, have 
lock");             
  -            }
  -
  -            // The transaction is associated with the ctx while we own the lock 
  -            ctx.setTransaction(miTx);
  -            if( trace )
  -               log.trace("End synchronized(ctx), ctx="+ctx+", set tx="+miTx);
  -
  -         }// end sychronized(ctx)
  -         if( trace )
  -            log.trace("End while ctx==null, ctx="+ctx);              
  -      }
  -
  -      // Set context on the method invocation
  -      mi.setEnterpriseContext(ctx);
  +                             lock.sync(); // lock all access to BeanLock
  +                             
  +                             try {
  +                                     
  +                                     // Set the transaction on the lock it will 
protect the instance
  +                                     lock.setTransaction(ctx.getTransaction());
  +                                     
  +                                     // marcf: possible race on creation and usage
  +                                     // insert instance in cache, 
  +                                     container.getInstanceCache().insert(ctx);
  +                                     
  +                             }
  +                             finally
  +                             {
  +                                     lock.releaseSync();
  +                                     
  +                                     
container.getLockManager().removeLockRef(ctx.getCacheKey());
  +                             }
  +                     }
  +                     //Do not send back to pools in any case, let the instance be 
GC'ed
  +             }
  +     }
  +     
  +     public Object invoke(MethodInvocation mi)
  +     throws Exception
  +     {
                
  -      boolean exceptionThrown = false;
  +             // The key
  +             CacheKey key = (CacheKey) mi.getId();
                
  -      try
  -      {      
  -         // Go on, you won
  -         if( trace )
  -            log.trace("Begin next invoker");
  -         Object returnValue = getNext().invoke(mi);
  -         if( trace )
  -            log.trace("End next invoker");
  -         return returnValue;
  -      }
  -      catch (RemoteException e)
  -      {
  -         exceptionThrown = true;
  -         throw e;
  -      } catch (RuntimeException e)
  -      {
  -         exceptionThrown = true;
  -         throw e;
  -      } catch (Error e)
  -      {
  -         exceptionThrown = true;
  -         throw e;
  -      } 
  -      finally
  -      {
  -         // ctx can be null if cache.get throws an Exception, for
  -         // example when activating a bean.
  -         if (ctx != null)
  -         {
  -                             
  -            synchronized(ctx) 
  -            {
  -               ctx.unlock();
  -               if( trace )
  -                  log.trace("Ending invoke, unlock ctx="+ctx);
  -                             
  -               // If an exception has been thrown, 
  -               if (exceptionThrown &&                                        
  -                   // if tx, the ctx has been registered in an 
InstanceSynchronization. 
  -                   // that will remove the context, so we shouldn't.
  -                   // if no synchronization then we need to do it by hand
  -                   !ctx.isTxSynchronized()) 
  -               {
  -                  // Discard instance
  -                  // EJB 1.1 spec 12.3.1
  -                  container.getInstanceCache().remove(key);
  -                  // Notify all those waiting on TxLock. Since this ctx is not 
TxSynchronized
  -                  // there is nobody else to wake up waiting threads.
  -                  if (ctx.getTransaction() != null 
  -                      && ctx.getTransaction().equals(mi.getTransaction()))
  -                  {
  -                     ctx.setTransaction(null);
  -                     synchronized(ctx.getTxLock())
  -                     {
  -                        ctx.getTxLock().notifyAll();
  -                     }
  -                  }
  -                  if( trace )
  -                     log.trace("Ending invoke, exceptionThrown, ctx="+ctx);
  -               }
  +             // The context
  +             EntityEnterpriseContext ctx = (EntityEnterpriseContext) 
container.getInstanceCache().get(key);
  +             
  +             boolean trace = log.isTraceEnabled();
  +             if( trace ) log.trace("Begin invoke, key="+key);
  +                     
  +             // Associate transaction, in the new design the lock already has the 
transaction from the 
  +             // previous interceptor
  +             ctx.setTransaction(mi.getTransaction());
  +             
  +             // Set context on the method invocation
  +             mi.setEnterpriseContext(ctx);
  +             
  +             boolean exceptionThrown = false;
  +             
  +             try
  +             {       
  +                     return getNext().invoke(mi);
  +             }
  +             catch (RemoteException e)
  +             {
  +                     exceptionThrown = true;
  +                     throw e;
  +             } catch (RuntimeException e)
  +             {
  +                     exceptionThrown = true;
  +                     throw e;
  +             } catch (Error e)
  +             {
  +                     exceptionThrown = true;
  +                     throw e;
  +             } 
  +             finally
  +             {
  +                     // ctx can be null if cache.get throws an Exception, for
  +                     // example when activating a bean.
  +                     if (ctx != null)
  +                     {                               
  +                             // If an exception has been thrown, 
  +                             if (exceptionThrown &&                                 
 
  +                                     // if tx, the ctx has been registered in an 
InstanceSynchronization. 
  +                                     // that will remove the context, so we 
shouldn't.
  +                                     // if no synchronization then we need to do it 
by hand
  +                                     !ctx.hasTxSynchronization()) 
  +                             {
  +                                     // Discard instance
  +                                     // EJB 1.1 spec 12.3.1
  +                                     container.getInstanceCache().remove(key);
                                        
  -               else if (ctx.getId() == null)
  -               {
  -                  // The key from the MethodInvocation still identifies the right 
cachekey
  -                  container.getInstanceCache().remove(key);
  -                  if( trace )
  -                     log.trace("Ending invoke, cache removal, ctx="+ctx);
  -                  // no more pool return
  -               }
  +                                     if( trace ) log.trace("Ending invoke, 
exceptionThrown, ctx="+ctx);
  +                             }
  +                             else if (ctx.getId() == null)
  +                             {
  +                                     // The key from the MethodInvocation still 
identifies the right cachekey
  +                                     container.getInstanceCache().remove(key);
                                        
  -               // We are done using the context so we wake up the next thread 
waiting for the ctx
  -               // marcf: I suspect we could use it only if lock = 0 (code it in the 
context.lock in fact)
  -               // this doesn't hurt here, meaning that even if we don't wait for 0 
to come up 
  -               // we will wake up a thread that will go back to sleep and the next 
coming out of 
  -               // the body of code will wake the next one etc until we reach 0.  
Reentrants are a pain
  -               // a minor though and I really suspect not checking for 0 is quite 
ok in all cases.
  -               if( trace )
  -                  log.trace("Ending invoke, send notifyAll ctx="+ctx);
  -               ctx.notifyAll();
  -            }
  -         }// synchronized ctx
  -         if( trace )
  -            log.trace("End invoke, key="+key+", ctx="+ctx);
  -      } // finally
  -   }
  -
  -   // Private --------------------------------------------------------
  +                                     if( trace )     log.trace("Ending invoke, 
cache removal, ctx="+ctx);
  +                                             // no more pool return
  +                             }
  +                     }
  +                     
  +                     if( trace )     log.trace("End invoke, key="+key+", ctx="+ctx);
  +             
  +             }       // end invoke           
  +     }
  +     
  +     // Private --------------------------------------------------------
        
  -   private static Method getEJBHome;
  -   private static Method getHandle;
  -   private static Method getPrimaryKey;
  -   private static Method isIdentical;
  -   private static Method remove;
  -   
  -   static
  -   {
  -      try
  -      {
  -         Class[] noArg = new Class[0];
  -         getEJBHome = EJBObject.class.getMethod("getEJBHome", noArg);
  -         getHandle = EJBObject.class.getMethod("getHandle", noArg);
  -         getPrimaryKey = EJBObject.class.getMethod("getPrimaryKey", noArg);
  -         isIdentical = EJBObject.class.getMethod("isIdentical", new Class[] 
{EJBObject.class});
  -         remove = EJBObject.class.getMethod("remove", noArg);
  -      }
  -      catch (Exception x) {x.printStackTrace();}
  -   }
  -     
  -   private boolean isCallAllowed(MethodInvocation mi)
  -   {
  -      boolean reentrant = 
((EntityMetaData)container.getBeanMetaData()).isReentrant();
  -             
  -      if (reentrant)
  -      {
  -         return true;
  -      }
  -      else
  -      {
  -         Method m = mi.getMethod();
  -         if (m.equals(getEJBHome) ||
  -             m.equals(getHandle) ||
  -             m.equals(getPrimaryKey) ||
  -             m.equals(isIdentical) ||
  -             m.equals(remove))
  -         {
  -            return true;
  -         }
  -      }
  +     private static Method getEJBHome;
  +     private static Method getHandle;
  +     private static Method getPrimaryKey;
  +     private static Method isIdentical;
  +     private static Method remove;
  +     
  +     static
  +     {
  +             try
  +             {
  +                     Class[] noArg = new Class[0];
  +                     getEJBHome = EJBObject.class.getMethod("getEJBHome", noArg);
  +                     getHandle = EJBObject.class.getMethod("getHandle", noArg);
  +                     getPrimaryKey = EJBObject.class.getMethod("getPrimaryKey", 
noArg);
  +                     isIdentical = EJBObject.class.getMethod("isIdentical", new 
Class[] {EJBObject.class});
  +                     remove = EJBObject.class.getMethod("remove", noArg);
  +             }
  +             catch (Exception x) {x.printStackTrace();}
  +     }
  +     
  +     private boolean isCallAllowed(MethodInvocation mi)
  +     {
  +             boolean reentrant = 
((EntityMetaData)container.getBeanMetaData()).isReentrant();
  +             
  +             if (reentrant)
  +             {
  +                     return true;
  +             }
  +             else
  +             {
  +                     Method m = mi.getMethod();
  +                     if (m.equals(getEJBHome) ||
  +                             m.equals(getHandle) ||
  +                             m.equals(getPrimaryKey) ||
  +                             m.equals(isIdentical) ||
  +                             m.equals(remove))
  +                     {
  +                             return true;
  +                     }
  +             }
                
  -      return false;
  -   }
  +             return false;
  +     }
   }
  +
  +
  +
  
  
  

_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to