Package org.jboss.cache.invocation

Source Code of org.jboss.cache.invocation.AbstractInvocationDelegate

package org.jboss.cache.invocation;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.CacheException;
import org.jboss.cache.CacheImpl;
import org.jboss.cache.CacheStatus;
import org.jboss.cache.InvocationContext;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.interceptors.Interceptor;
import org.jboss.cache.marshall.MethodCall;

/**
* The JBoss Cache hand-wired interceptor stack.  A "minimal" AOP framework which uses delegation through an
* interceptor chain rather than any bytecode manipulation.
* <p/>
* This class provides some generic behaviour such as the construction of an {@link org.jboss.cache.InvocationContext}
* which is passed up the interceptor chain.
* <p/>
*
* @author Manik Surtani (<a href="mailto:manik@jboss.org">manik@jboss.org</a>)
* @see org.jboss.cache.interceptors.Interceptor
* @see org.jboss.cache.InvocationContext
* @since 2.1.0
*/
public abstract class AbstractInvocationDelegate
{
   protected Interceptor interceptorChain;
   protected CacheImpl cache;
   protected Log log = LogFactory.getLog(AbstractInvocationDelegate.class);
   protected Configuration configuration;
   protected boolean originLocal = true;

   protected InvocationContextContainer invocationContextContainer;

   /**
    * Used by the interceptor chain factory to inject dependencies.
    *
    * @param interceptorChain interceptor chain to pass calls up
    * @param cache            cache instance
    * @param configuration    configuration for the cache
    */
   @Inject
   private void initialise(Interceptor interceptorChain, CacheImpl cache, Configuration configuration, InvocationContextContainer invocationContextContainer)
   {
      this.interceptorChain = interceptorChain;
      this.cache = cache;
      this.configuration = configuration;
      this.invocationContextContainer = invocationContextContainer;
   }

   /**
    * Passes a method call up the interceptor chain.
    *
    * @param call methodcall to pass
    * @return an Object, the generic return type for the interceptors.
    * @throws Throwable in the event of problems
    */
   protected Object invoke(MethodCall call) throws CacheException
   {
      assertIsConstructed();
      InvocationContext ctx = invocationContextContainer.get();
      return invoke(call, ctx.getOptionOverrides().isSkipCacheStatusCheck(), ctx);
   }

   /**
    * Passes a method call up the interceptor chain, optionally allowing you to skip cache status checks.
    *
    * @param call methodcall to pass
    * @return an Object, the generic return type for the interceptors.
    * @throws Throwable in the event of problems
    */
   protected Object invoke(MethodCall call, boolean skipCacheStatusCheck) throws CacheException
   {
      assertIsConstructed();
      return invoke(call, skipCacheStatusCheck, invocationContextContainer.get());
   }

   protected void assertIsConstructed()
   {
      if (invocationContextContainer == null) throw new IllegalStateException("The cache has been destroyed!");
   }

   private Object invoke(MethodCall call, boolean skipCacheStatusCheck, InvocationContext ctx) throws CacheException
   {
      if (!cache.getCacheStatus().allowInvocations() && !skipCacheStatusCheck)
      {
         // only throw an exception if this is a locally originating call - JBCACHE-1179
         if (originLocal)
         {
            throw new IllegalStateException("Cache not in STARTED state!");
         }
         else
         {
            if (cache.getCacheStatus() == CacheStatus.STARTING)
            {
               try
               {
                  blockUntilCacheStarts();
               }
               catch (InterruptedException e)
               {
                  Thread.currentThread().interrupt();
               }
            }
            else
            {
               log.warn("Received a remote call but the cache is not in STARTED state - ignoring call.");
               return null;
            }
         }
      }

      MethodCall oldCall = null;
      try
      {
         // check if we had a method call lurking around
         oldCall = ctx.getMethodCall();
         ctx.setMethodCall(call);
         // only set this if originLocal is EXPLICITLY passed in as FALSE.  Otherwise leave it as a default.
         if (!originLocal) ctx.setOriginLocal(false);
         return interceptorChain.invoke(ctx);
      }
      catch (CacheException e)
      {
         throw e;
      }
      catch (RuntimeException e)
      {
         throw e;
      }
      catch (Throwable t)
      {
         throw new CacheException(t);
      }
      finally
      {
         if (!originLocal) ctx.setOriginLocal(true);
         // reset old method call
         if (ctx == null) ctx = invocationContextContainer.get();
         ctx.setMethodCall(oldCall);
      }
   }

   /**
    * Blocks until the current cache instance is in it's {@link org.jboss.cache.CacheStatus#STARTED started} phase.  Blocks
    * for up to {@link org.jboss.cache.config.Configuration#getStateRetrievalTimeout()} milliseconds, throwing an IllegalStateException
    * if the cache doesn't reach this state even after this maximum wait time.
    *
    * @throws InterruptedException  if interrupted while waiting
    * @throws IllegalStateException if even after waiting the cache has not started.
    */
   private void blockUntilCacheStarts() throws InterruptedException, IllegalStateException
   {
      int pollFrequencyMS = 100;
      long startupWaitTime = configuration.getStateRetrievalTimeout();
      long giveUpTime = System.currentTimeMillis() + startupWaitTime;

      while (System.currentTimeMillis() < giveUpTime)
      {
         if (cache.getCacheStatus().allowInvocations()) break;
         Thread.sleep(pollFrequencyMS);
      }

      // check if we have started.
      if (!cache.getCacheStatus().allowInvocations())
         throw new IllegalStateException("Cache not in STARTED state, even after waiting " + configuration.getStateRetrievalTimeout() + " millis.");
   }
}
TOP

Related Classes of org.jboss.cache.invocation.AbstractInvocationDelegate

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.