Package org.onebusaway.container.spring.ehcache

Source Code of org.onebusaway.container.spring.ehcache.EhCacheFactoryBean

/**
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*         http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onebusaway.container.spring.ehcache;

import java.io.IOException;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.PersistenceConfiguration;
import net.sf.ehcache.config.TerracottaConfiguration;
import net.sf.ehcache.constructs.blocking.BlockingCache;
import net.sf.ehcache.constructs.blocking.CacheEntryFactory;
import net.sf.ehcache.constructs.blocking.SelfPopulatingCache;
import net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory;
import net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

/**
* A Spring {@link FactoryBean} for programmatically creating an EhCache
* {@link Cache} with standard configuration options, but also progrmattic
* Terracotta configuration.
*
* A special note about Terracotta config. While you can create all your
* Terracotta-enabled caches programatically using this FactoryBean, you need to
* have at least one Terracotta-enabled cache created the old fashioned way
* (through an {@code ehcache.xml} resource config) so that the
* {@link CacheManager} will properly enable Terracotta support.
*
* @author bdferris
*
*/
public class EhCacheFactoryBean implements FactoryBean<Ehcache>, BeanNameAware,
    InitializingBean {

  protected final Log logger = LogFactory.getLog(getClass());

  private CacheManager cacheManager;

  private String cacheName;

  private int maxElementsInMemory = 10000;

  private int maxElementsOnDisk = 10000000;

  private MemoryStoreEvictionPolicy memoryStoreEvictionPolicy = MemoryStoreEvictionPolicy.LRU;

  private boolean overflowToDisk = true;

  private boolean eternal = false;

  private int timeToLive = 60 * 5;

  private int timeToIdle = 120;

  private boolean diskPersistent = false;

  private int diskExpiryThreadIntervalSeconds = 60 * 5;

  private boolean blocking = false;

  private boolean terracottaClustered = false;

  private CacheEntryFactory cacheEntryFactory;

  private String beanName;

  private Ehcache cache;

  /**
   * Set a CacheManager from which to retrieve a named Cache instance. By
   * default, <code>CacheManager.getInstance()</code> will be called.
   * <p>
   * Note that in particular for persistent caches, it is advisable to properly
   * handle the shutdown of the CacheManager: Set up a separate
   * EhCacheManagerFactoryBean and pass a reference to this bean property.
   * <p>
   * A separate EhCacheManagerFactoryBean is also necessary for loading EHCache
   * configuration from a non-default config location.
   *
   * @see EhCacheManagerFactoryBean
   * @see net.sf.ehcache.CacheManager#getInstance
   */
  public void setCacheManager(CacheManager cacheManager) {
    this.cacheManager = cacheManager;
  }

  /**
   * Set a name for which to retrieve or create a cache instance. Default is the
   * bean name of this EhCacheFactoryBean.
   */
  public void setCacheName(String cacheName) {
    this.cacheName = cacheName;
  }

  /**
   * Specify the maximum number of cached objects in memory. Default is 10000
   * elements.
   */
  public void setMaxElementsInMemory(int maxElementsInMemory) {
    this.maxElementsInMemory = maxElementsInMemory;
  }

  /**
   * Specify the maximum number of cached objects on disk. Default is 10000000
   * elements.
   */
  public void setMaxElementsOnDisk(int maxElementsOnDisk) {
    this.maxElementsOnDisk = maxElementsOnDisk;
  }

  /**
   * Set the memory style eviction policy for this cache. Supported values are
   * "LRU", "LFU" and "FIFO", according to the constants defined in EHCache's
   * MemoryStoreEvictionPolicy class. Default is "LRU".
   */
  public void setMemoryStoreEvictionPolicy(
      MemoryStoreEvictionPolicy memoryStoreEvictionPolicy) {
    Assert.notNull(memoryStoreEvictionPolicy,
        "memoryStoreEvictionPolicy must not be null");
    this.memoryStoreEvictionPolicy = memoryStoreEvictionPolicy;
  }

  /**
   * Set whether elements can overflow to disk when the in-memory cache has
   * reached the maximum size limit. Default is "true".
   */
  public void setOverflowToDisk(boolean overflowToDisk) {
    this.overflowToDisk = overflowToDisk;
  }

  /**
   * Set whether elements are considered as eternal. If "true", timeouts are
   * ignored and the element is never expired. Default is "false".
   */
  public void setEternal(boolean eternal) {
    this.eternal = eternal;
  }

  /**
   * Set t he time in seconds to live for an element before it expires, i.e. the
   * maximum time between creation time and when an element expires. It is only
   * used if the element is not eternal. Default is 300 seconds.
   */
  public void setTimeToLive(int timeToLive) {
    this.timeToLive = timeToLive;
  }

  /**
   * Set the time in seconds to idle for an element before it expires, that is,
   * the maximum amount of time between accesses before an element expires. This
   * is only used if the element is not eternal. Default is 120 seconds.
   */
  public void setTimeToIdle(int timeToIdle) {
    this.timeToIdle = timeToIdle;
  }

  /**
   * Set whether the disk store persists between restarts of the Virtual
   * Machine. The default is "false".
   */
  public void setDiskPersistent(boolean diskPersistent) {
    this.diskPersistent = diskPersistent;
  }

  /**
   * Set the number of seconds between runs of the disk expiry thread. The
   * default is 300 seconds.
   */
  public void setDiskExpiryThreadIntervalSeconds(
      int diskExpiryThreadIntervalSeconds) {
    this.diskExpiryThreadIntervalSeconds = diskExpiryThreadIntervalSeconds;
  }

  /**
   * Set whether to use a blocking cache that lets read attempts block until the
   * requested element is created.
   * <p>
   * If you intend to build a self-populating blocking cache, consider
   * specifying a {@link #setCacheEntryFactory CacheEntryFactory}.
   *
   * @see net.sf.ehcache.constructs.blocking.BlockingCache
   * @see #setCacheEntryFactory
   */
  public void setBlocking(boolean blocking) {
    this.blocking = blocking;
  }

  public void setTerracottaClustered(boolean terracottaClustered) {
    this.terracottaClustered = terracottaClustered;
  }

  /**
   * Set an EHCache {@link net.sf.ehcache.constructs.blocking.CacheEntryFactory}
   * to use for a self-populating cache. If such a factory is specified, the
   * cache will be decorated with EHCache's
   * {@link net.sf.ehcache.constructs.blocking.SelfPopulatingCache}.
   * <p>
   * The specified factory can be of type
   * {@link net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory}, which
   * will lead to the use of an
   * {@link net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache}.
   * <p>
   * Note: Any such self-populating cache is automatically a blocking cache.
   *
   * @see net.sf.ehcache.constructs.blocking.SelfPopulatingCache
   * @see net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache
   * @see net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory
   */
  public void setCacheEntryFactory(CacheEntryFactory cacheEntryFactory) {
    this.cacheEntryFactory = cacheEntryFactory;
  }

  public void setBeanName(String name) {
    this.beanName = name;
  }

  public void afterPropertiesSet() throws CacheException, IOException {
    // If no CacheManager given, fetch the default.
    if (this.cacheManager == null) {
      if (logger.isDebugEnabled()) {
        logger.debug("Using default EHCache CacheManager for cache region '"
            + this.cacheName + "'");
      }
      this.cacheManager = CacheManager.getInstance();
    }

    // If no cache name given, use bean name as cache name.
    if (this.cacheName == null) {
      this.cacheName = this.beanName;
    }

    // Fetch cache region: If none with the given name exists,
    // create one on the fly.
    Ehcache rawCache = null;
    if (this.cacheManager.cacheExists(this.cacheName)) {
      if (logger.isDebugEnabled()) {
        logger.debug("Using existing EHCache cache region '" + this.cacheName
            + "'");
      }
      rawCache = this.cacheManager.getEhcache(this.cacheName);
    } else {
      if (logger.isDebugEnabled()) {
        logger.debug("Creating new EHCache cache region '" + this.cacheName
            + "'");
      }
      rawCache = createCache();
      this.cacheManager.addCache(rawCache);
    }

    // Decorate cache if necessary.
    Ehcache decoratedCache = decorateCache(rawCache);
    if (decoratedCache != rawCache) {
      this.cacheManager.replaceCacheWithDecoratedCache(rawCache, decoratedCache);
    }
    this.cache = decoratedCache;
  }

  /**
   * Create a raw Cache object based on the configuration of this FactoryBean.
   */
  private Cache createCache() {

    CacheConfiguration config = new CacheConfiguration(this.cacheName,
        this.maxElementsInMemory);
    config.setMemoryStoreEvictionPolicyFromObject(this.memoryStoreEvictionPolicy);

    config.setEternal(this.eternal);
    config.setTimeToLiveSeconds(this.timeToLive);
    config.setTimeToIdleSeconds(this.timeToIdle);
   
    PersistenceConfiguration pc = new PersistenceConfiguration();
    if(this.diskPersistent)  
      pc.strategy(PersistenceConfiguration.Strategy.LOCALRESTARTABLE);
    else if(this.overflowToDisk)
      pc.strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP);
    else
      pc.strategy(PersistenceConfiguration.Strategy.NONE);

    config.setDiskExpiryThreadIntervalSeconds(this.diskExpiryThreadIntervalSeconds);
    config.setMaxElementsOnDisk(this.maxElementsOnDisk);

    if (this.terracottaClustered) {
      TerracottaConfiguration tcConfig = new TerracottaConfiguration();
      tcConfig.setClustered(true);
      config.terracotta(tcConfig);
    }

    return new Cache(config);
  }

  /**
   * Decorate the given Cache, if necessary.
   *
   * @param cache the raw Cache object, based on the configuration of this
   *          FactoryBean
   * @return the (potentially decorated) cache object to be registered with the
   *         CacheManager
   */
  protected Ehcache decorateCache(Ehcache cache) {
    if (this.cacheEntryFactory != null) {
      if (this.cacheEntryFactory instanceof UpdatingCacheEntryFactory) {
        return new UpdatingSelfPopulatingCache(cache,
            (UpdatingCacheEntryFactory) this.cacheEntryFactory);
      } else {
        return new SelfPopulatingCache(cache, this.cacheEntryFactory);
      }
    }
    if (this.blocking) {
      return new BlockingCache(cache);
    }
    return cache;
  }

  public Ehcache getObject() {
    return this.cache;
  }

  public Class<?> getObjectType() {
    return (this.cache != null ? this.cache.getClass() : Ehcache.class);
  }

  public boolean isSingleton() {
    return true;
  }

}
TOP

Related Classes of org.onebusaway.container.spring.ehcache.EhCacheFactoryBean

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.