/*******************************************************************************
* Copyright 2009, 2010 Innovation Gate GmbH
*
* 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 de.innovationgate.utils.cache;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.Configuration;
/**
* Cache core implementation based on EHCache (http://ehcache.sourceforge.net)
*
*/
public class EHCacheCore implements de.innovationgate.utils.cache.CacheCore {
private static CacheManager _cacheManager;
class Entry implements Serializable {
public Entry(Object value, String group) {
super();
this.value = value;
this.group = group;
}
private String group;
private Object value;
public String getGroup() {
return group;
}
public Object getValue() {
return value;
}
}
public static synchronized CacheManager getCacheManager() {
if (_cacheManager == null) {
Configuration config = new Configuration();
CacheConfiguration defaultConfig = new CacheConfiguration();
defaultConfig.setMaxElementsInMemory(10000);
defaultConfig.setEternal(false);
defaultConfig.setOverflowToDisk(false);
defaultConfig.setTimeToIdleSeconds(120);
defaultConfig.setTimeToLiveSeconds(120);
defaultConfig.setDiskPersistent(false);
defaultConfig.setDiskExpiryThreadIntervalSeconds(120);
config.addDefaultCache(defaultConfig);
_cacheManager = new CacheManager(config);
}
return _cacheManager;
}
private Cache _ehcache;
private String _name;
private int _capacity;
private Map _lastCacheFlush = new HashMap();
private int _timeToLive;
public void destroy() throws de.innovationgate.utils.cache.CacheException {
if (_ehcache == null) {
return;
}
try {
CacheManager cacheManager = getCacheManager();
cacheManager.removeCache(_name);
}
catch (CacheException e) {
throw new de.innovationgate.utils.cache.CacheException("Exception closing ehcache", e);
}
}
public void flushAll() throws de.innovationgate.utils.cache.CacheException {
if (_ehcache == null) {
return;
}
try {
_ehcache.removeAll();
}
catch (Exception e) {
throw new de.innovationgate.utils.cache.CacheException("Exception flushing all entries", e);
}
}
public void flushEntry(String key) throws de.innovationgate.utils.cache.CacheException {
try {
_ehcache.remove(key);
}
catch (Exception e) {
throw new de.innovationgate.utils.cache.CacheException("Exception flushing entry", e);
}
}
public void flushGroup(String group) {
_lastCacheFlush.put(group, new Date());
}
public long getMaxSize() {
return _capacity;
}
public long getSize() throws de.innovationgate.utils.cache.CacheException {
try {
return _ehcache.getSize();
}
catch (Exception e) {
throw new de.innovationgate.utils.cache.CacheException("Exception retrieving size" ,e);
}
}
public int getUtilisation() {
long hitsCount = _ehcache.getStatistics().getCacheHits();
long totalCount = hitsCount + _ehcache.getStatistics().getCacheMisses();
if (totalCount == 0) {
return 0;
}
return (int) Math.round(hitsCount / (totalCount / (double) 100));
}
public void init(String name, int capacity, Map params) throws de.innovationgate.utils.cache.CacheException {
_name = name;
_capacity = capacity;
_timeToLive = 0;
// Use params
if (params.containsKey(de.innovationgate.utils.cache.Cache.PARAM_TIME_TO_LIVE_SECONDS)) {
try {
_timeToLive = ((Integer) params.get(de.innovationgate.utils.cache.Cache.PARAM_TIME_TO_LIVE_SECONDS)).intValue();
}
catch (ClassCastException e) {
throw new CacheException("Invalid data type for timeToLive, must be Integer but is: " + params.get(de.innovationgate.utils.cache.Cache.PARAM_TIME_TO_LIVE_SECONDS).getClass().getName());
}
}
try {
_ehcache = new Cache(name, capacity, false, (_timeToLive > 0), _timeToLive, 0);
getCacheManager().addCache(_ehcache);
}
catch (Exception e) {
throw new de.innovationgate.utils.cache.CacheException("Exception initializing cache", e);
}
}
private boolean isActive(Element element) {
if (element == null) {
return false;
}
Entry entry = (Entry) element.getValue();
if (entry.getGroup() == null) {
return true;
}
Date cacheFlush = (Date) _lastCacheFlush.get(entry.getGroup());
if (cacheFlush != null && cacheFlush.getTime() > element.getCreationTime()) {
return false;
}
return true;
}
public Object readEntry(String key) {
if (_ehcache == null) {
return null;
}
try {
Element element = _ehcache.get(key);
if (isActive(element)) {
Entry entry = (Entry) element.getValue();
return entry.getValue();
}
else {
return null;
}
}
catch (Exception e) {
throw new CacheException("Error reading item cache for key '" + key + "'", e);
}
}
public void writeEntry(String key, Object obj, String group, int secondsToLive) {
if (_ehcache == null) {
return;
}
Entry entry = new Entry(obj, group);
try {
Element element = new Element(key, entry);
if (secondsToLive != 0) {
element.setTimeToLive(secondsToLive);
}
_ehcache.put(element);
}
catch (RuntimeException e) {
throw new CacheException("Exception writing cache entry for key '" + key + "', group '" + group + "'",e);
}
}
public Set getEntryKeys() {
return new HashSet(_ehcache.getKeys());
}
}