/**
* Copyright (C) 2014 Cohesive Integrations, LLC (info@cohesiveintegrations.com)
*
* 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 net.di2e.ecdr.libs.cache.impl;
import java.net.URI;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import javax.cache.Cache;
import javax.cache.CacheManager;
import javax.cache.Caching;
import javax.cache.configuration.MutableConfiguration;
import javax.cache.expiry.AccessedExpiryPolicy;
import javax.cache.expiry.Duration;
import javax.cache.spi.CachingProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.hazelcast.cache.HazelcastCachingProvider;
import com.hazelcast.config.Config;
import com.hazelcast.config.JoinConfig;
import com.hazelcast.config.NetworkConfig;
import com.hazelcast.core.Hazelcast;
import ddf.catalog.data.Metacard;
public class MetacardJCacheManager implements net.di2e.ecdr.api.cache.CacheManager<Metacard> {
private static final long DEFAULT_CACHE_MINUTES = 60;
private static final String CACHE_ID_PREFIX = "jcache-metacard-";
private static final Logger LOGGER = LoggerFactory.getLogger( MetacardJCacheManager.class );
private CachingProvider cachingProvider = null;
private CacheManager cacheManager = null;
public MetacardJCacheManager() {
LOGGER.debug( "Creating a new JCacheManager for caching Metacards" );
Caching.setDefaultClassLoader( JCache.class.getClassLoader() );
cachingProvider = Caching.getCachingProvider();
cacheManager = cachingProvider.getCacheManager( URI.create( "ecdr-jcache-cache-manager" ), getClass().getClassLoader(), getConfigProperties() );
}
private Properties getConfigProperties() {
Config config = new Config();
config.setClassLoader( getClass().getClassLoader() );
config.setInstanceName( "ecdr-jcache-config-instance" );
NetworkConfig networkConfig = config.getNetworkConfig();
JoinConfig join = networkConfig.getJoin();
join.getMulticastConfig().setEnabled( false );
join.getTcpIpConfig().setEnabled( false );
join.getAwsConfig().setEnabled( false );
// This actually creates the config so it will be available to the CacheManager
Hazelcast.newHazelcastInstance( config );
Properties props = new Properties();
props.setProperty( HazelcastCachingProvider.HAZELCAST_INSTANCE_NAME, config.getInstanceName() );
return props;
}
@Override
public net.di2e.ecdr.api.cache.Cache<Metacard> createCacheInstance( String cacheId, Map<String, Object> cacheProperties ) {
if ( cacheId == null ) {
throw new IllegalArgumentException( "CacheId cannot be null when calling the MetacardJCacheManager.createCache method" );
} else if ( cacheManager.getCache( CACHE_ID_PREFIX + cacheId ) != null ) {
throw new IllegalArgumentException( "CacheId with the name [" + cacheId + "] already exists, each cache instance must have a unique name" );
}
// configure the cache
MutableConfiguration<String, Metacard> config = new MutableConfiguration<String, Metacard>();
config.setStoreByValue( true ).setTypes( String.class, Metacard.class ).setExpiryPolicyFactory( AccessedExpiryPolicy.factoryOf( getDuration( cacheProperties ) ) )
.setStatisticsEnabled( true );
// create the cache
Cache<String, Metacard> cache = cacheManager.createCache( CACHE_ID_PREFIX + cacheId, config );
JCache<Metacard> jcache = new JCache<Metacard>( cache );
return jcache;
}
@Override
public void destroy() {
LOGGER.debug( "Destroying all active caches and destroying the Cache Manager" );
for ( String cacheId : cacheManager.getCacheNames() ) {
cacheManager.destroyCache( CACHE_ID_PREFIX + cacheId );
}
cacheManager.close();
cachingProvider.close();
Hazelcast.shutdownAll();
}
@Override
public void removeCacheInstance( String cacheId ) {
LOGGER.debug( "Removing the cache instance [{}]", cacheId );
cacheManager.destroyCache( CACHE_ID_PREFIX + cacheId );
}
protected Duration getDuration( Map<String, Object> cacheProperties ) {
Duration duration = null;
if ( cacheProperties != null ) {
Object minutes = cacheProperties.get( net.di2e.ecdr.api.cache.CacheManager.CACHE_EXPIRE_AFTER_MINUTES );
if ( minutes != null ) {
if ( minutes instanceof Long ) {
LOGGER.debug( "Setting cache duration of newly created cache to [{}] minutes", minutes );
duration = new Duration( TimeUnit.MINUTES, (Long) minutes );
} else {
LOGGER.warn( "Cache property [{}] was not the expected type of Long, instead it was [{}]", net.di2e.ecdr.api.cache.CacheManager.CACHE_EXPIRE_AFTER_MINUTES, minutes.getClass()
.getName() );
}
}
}
if ( duration == null ) {
LOGGER.debug( "Duration was not passed into cache creation, so defaulting to cache of 60 minutes" );
duration = new Duration( TimeUnit.MINUTES, DEFAULT_CACHE_MINUTES );
}
return duration;
}
}