package org.ff4j.cache; /* * #%L ff4j-cache-ehcache %% Copyright (C) 2013 Ff4J %% 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. #L% */ import java.util.HashSet; import java.util.Set; import org.ff4j.core.Feature; import org.ff4j.property.Property; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; import net.sf.ehcache.config.Configuration; import static org.ff4j.ehcache.FF4JEhCacheConstants.*; /** * Cache-aside implementation with EHCACHE. * * Application code uses the cache directly. This means that application code which accesses the system-of-record (SOR) should * consult the cache first, and if the cache contains the data, then return the data directly from the cache, bypassing the SOR. * * * Warn : DO NOT USE THIS CACHE WHEN WORKING WITH EXTERNAL FEATURESTORE (as Database) and cluster application : EACH NODE GOT * ITS MEMORY AND AN MODIFICATION IN STORE WON'T REFRESH THIS CACHE. Please use REDIS/MEMCACHED implementations. */ public class FeatureCacheProviderEhCache implements FF4JCacheManager { /** Logger for the class. */ private static final Logger LOG = LoggerFactory.getLogger(FF4jCacheProxy.class); /** Setup Cache configuration to work with Terracotta for instance. */ private Configuration cacheConfiguration; /** The cache manager. */ private CacheManager cacheManager; /** Eh Cache - cache-aside mode utlization. */ private Cache cacheFeatures = null; /** Eh Cache - cache-aside mode utlization. */ private Cache cacheProperties = null; /** * Default constructor to allow IoC. */ public FeatureCacheProviderEhCache() { } /** * Default constructor to allow IoC. */ public FeatureCacheProviderEhCache(Configuration config) { this.cacheConfiguration = config; } /** {@inheritDoc} */ @Override public String getCacheProviderName() { return "EHCACHE"; } /** {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public Set<String> listCachedFeatureNames() { return new HashSet<String>(getCacheFeatures().getKeys()); } /** * Ininitialize cache */ private void initializeCache() { if (null == getCacheConfiguration()) { this.cacheManager = CacheManager.create(); } else { this.cacheManager = CacheManager.create(getCacheConfiguration()); } if (!cacheManager.cacheExists(CACHENAME_FEATURES)) { cacheManager.addCache(CACHENAME_FEATURES); } if (!cacheManager.cacheExists(CACHENAME_PROPERTIES)) { cacheManager.addCache(CACHENAME_PROPERTIES); } cacheFeatures = cacheManager.getCache(CACHENAME_FEATURES); cacheProperties = cacheManager.getCache(CACHENAME_PROPERTIES); LOG.debug("CacheManager initialized as '{}'", cacheFeatures.getName()); } /** {@inheritDoc} */ @Override public void clearFeatures() { getCacheFeatures().flush(); } /** {@inheritDoc} */ @Override public void clearProperties() { getCacheProperties().flush(); } /** {@inheritDoc} */ @Override public void evictFeature(String featureId) { getCacheFeatures().remove(featureId); } /** {@inheritDoc} */ @Override public void evictProperty(String propertyName) { getCacheProperties().remove(propertyName); } /** {@inheritDoc} */ @Override public void putFeature(Feature feat) { getCacheFeatures().put(new Element(feat.getUid(), feat)); } /** {@inheritDoc} */ @Override public void putProperty(Property<?> property) { getCacheProperties().put(new Element(property.getName(), property)); } /** {@inheritDoc} */ @Override public Feature getFeature(String featureId) { Element e = getCacheFeatures().get(featureId); if (e != null) { return (Feature) e.getObjectValue(); } return null; } /** {@inheritDoc} */ @Override public Property<?> getProperty(String featureId) { Element e = getCacheProperties().get(featureId); if (e != null) { return (Property<?>) e.getObjectValue(); } return null; } /** {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public Set<String> listCachedPropertyNames() { return new HashSet<String>(getCacheProperties().getKeys()); } /** {@inheritDoc} */ @Override public Object getFeatureNativeCache() { return getCacheFeatures(); } /** {@inheritDoc} */ @Override public Object getPropertyNativeCache() { return getCacheProperties(); } /** * Getter accessor for attribute 'cacheFeatures'. * * @return * current value of 'cacheFeatures' */ public Cache getCacheFeatures() { if (cacheFeatures == null) initializeCache(); return cacheFeatures; } /** * Setter accessor for attribute 'cacheFeatures'. * @param cacheFeatures * new value for 'cacheFeatures ' */ public void setCacheFeatures(Cache cacheFeatures) { this.cacheFeatures = cacheFeatures; } /** * Getter accessor for attribute 'cacheProperties'. * * @return * current value of 'cacheProperties' */ public Cache getCacheProperties() { if (cacheProperties == null) initializeCache(); return cacheProperties; } /** * Setter accessor for attribute 'cacheProperties'. * @param cacheProperties * new value for 'cacheProperties ' */ public void setCacheProperties(Cache cacheProperties) { this.cacheProperties = cacheProperties; } /** * Getter accessor for attribute 'cacheConfiguration'. * * @return * current value of 'cacheConfiguration' */ public Configuration getCacheConfiguration() { return cacheConfiguration; } /** * Setter accessor for attribute 'cacheConfiguration'. * @param cacheConfiguration * new value for 'cacheConfiguration ' */ public void setCacheConfiguration(Configuration cacheConfiguration) { this.cacheConfiguration = cacheConfiguration; } /** * Getter accessor for attribute 'cacheManager'. * * @return * current value of 'cacheManager' */ public CacheManager getCacheManager() { return cacheManager; } /** * Setter accessor for attribute 'cacheManager'. * @param cacheManager * new value for 'cacheManager ' */ public void setCacheManager(CacheManager cacheManager) { this.cacheManager = cacheManager; } }