Interceptor.java :  » JBoss » JBossCache » org » jboss » cache » interceptors » Java Open Source

Java Open Source » JBoss » JBossCache 
JBossCache » org » jboss » cache » interceptors » Interceptor.java
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.cache.interceptors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.CacheException;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.Fqn;
import org.jboss.cache.InvocationContext;
import org.jboss.cache.NodeSPI;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.factories.annotations.Start;

import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import java.util.Collections;
import java.util.Map;

/**
 * Class representing an interceptor.
 *
 * @author Bela Ban
 * @version $Id: Interceptor.java 5306 2008-02-06 01:19:52Z manik.surtani@jboss.com $
 */
public abstract class Interceptor implements InterceptorMBean
{
   protected Interceptor next = null, last = null;
   protected CacheSPI<?, ?> cache;
   protected Log log = null;
   protected Configuration configuration;
   private boolean statsEnabled = false;
   protected boolean trace;

   public Interceptor()
   {
      initLogger();
   }

   protected void initLogger()
   {
      log = LogFactory.getLog(getClass());
      trace = log.isTraceEnabled();
   }

   public void setNext(Interceptor i)
   {
      next = i;
   }

   public Interceptor getNext()
   {
      return next;
   }

   public void setCache(CacheSPI cache)
   {
   }

   @Start
   private void start()
   {
      setStatisticsEnabled(configuration.getExposeManagementStatistics());
      // for backward compatibility, this must only be done when the cache starts.
      setCache(cache);
   }

   @Inject
   private void injectDependencies(CacheSPI cache, Configuration configuration)
   {
      this.configuration = configuration;
      this.cache = cache;
   }

   /**
    * Using this method call for forwarding a call in the chain is not redable and error prone in the case of interceptors
    * extending other interceptors. This metod rather refers to interceptor doing its business operations rather than
    * delegating to the nextInterceptor interceptor in chain. For delegation please use {@link #nextInterceptor(org.jboss.cache.InvocationContext)}
    */
   public Object invoke(InvocationContext ctx) throws Throwable
   {
      return next.invoke(ctx);
   }

   /**
    * Forwards the call to the nextInterceptor interceptor in the chain.
    */
   public Object nextInterceptor(InvocationContext ctx) throws Throwable
   {
      return next.invoke(ctx);
   }

   public boolean getStatisticsEnabled()
   {
      return statsEnabled;
   }

   public void setStatisticsEnabled(boolean enabled)
   {
      statsEnabled = enabled;
   }

   public Interceptor getLast()
   {
      return last;
   }

   public void setLast(Interceptor last)
   {
      this.last = last;
   }

   /**
    * This implementation returns an empty Map.  If individual Interceptors wish to expose statistics, they can override this
    * method.
    */
   public Map<String, Object> dumpStatistics()
   {
      return Collections.emptyMap();
   }

   /**
    * This implementation is a no-op.  If individual Interceptors wish to expose statistics, they can override this
    * method.
    */
   public void resetStatistics()
   {
   }

   /**
    * Returns true if transaction is ACTIVE, false otherwise
    */
   protected boolean isActive(Transaction tx)
   {
      if (tx == null) return false;
      int status = -1;
      try
      {
         status = tx.getStatus();
         return status == Status.STATUS_ACTIVE;
      }
      catch (SystemException e)
      {
         log.error("failed getting transaction status", e);
         return false;
      }
   }

   /**
    * Returns true if transaction is PREPARING, false otherwise
    */
   protected boolean isPreparing(Transaction tx)
   {
      if (tx == null) return false;
      int status = -1;
      try
      {
         status = tx.getStatus();
         return status == Status.STATUS_PREPARING;
      }
      catch (SystemException e)
      {
         log.error("failed getting transaction status", e);
         return false;
      }
   }

   /**
    * Return s true of tx's status is ACTIVE or PREPARING
    *
    * @param tx
    * @return true if the tx is active or preparing
    */
   protected boolean isValid(Transaction tx)
   {
      return isActive(tx) || isPreparing(tx);
   }

   /**
    * Tests whether the caller is in a valid transaction.  If not, will throw a CacheException.
    */
   protected void assertTransactionValid(InvocationContext ctx)
   {
      Transaction tx = ctx.getTransaction();
      if (!isValid(tx)) try
      {
         throw new CacheException("Invalid transaction " + tx + ", status = " + (tx == null ? null : tx.getStatus()));
      }
      catch (SystemException e)
      {
         throw new CacheException("Exception trying to analyse status of transaction " + tx, e);
      }
   }

   public String toString()
   {
      return getClass().getName()
            + "{next: "
            + (getNext() == null ? null : getNext().getClass())
            + "; last: "
            + (getLast() == null ? null : getLast().getClass())
            + "}";
   }

   /**
    * First checks the invocation context for previously obtained reference to a node, if this doesn't exist, performs
    * a cache.peek() and holds on to the node reference.
    *
    * @param ctx                 invocation context
    * @param f                   fqn to find
    * @param forceRefresh        forces calling cache.peek() even if we hold a reference to the relevant node.
    * @param includeDeletedNodes includes nodes marked for deletion if this is true
    * @param includeInvalidNodes includes nodes marked as invalid if this is true
    * @return a node, or null if one cannot be found.
    * @since 2.1.0
    */
   public NodeSPI peekNode(InvocationContext ctx, Fqn f, boolean forceRefresh, boolean includeDeletedNodes, boolean includeInvalidNodes)
   {
      return cache.peek(f, includeDeletedNodes, includeInvalidNodes);

      // Disabling this for now, until we can prove that it is in fact beneficial.
      // preliminary profiling tests show that it is not.

//      NodeSPI n;
//      if (forceRefresh || (n = ctx.getPeekedNode(f)) == null)
//      {
//         n = cache.peek(f, true, true);
//         // put this in the invocation cache
//         ctx.savePeekedNode(n, f);
//      }
//
//      if (n != null)
//      {
//         if (!includeDeletedNodes && n.isDeleted()) return null;
//         if (!includeInvalidNodes && !n.isValid()) return null;
//      }
//      return n;
   }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.