package org.infinispan.jcache.embedded; import java.io.FileNotFoundException; import java.io.InputStream; import java.net.URI; import java.util.Properties; import java.util.Set; import javax.cache.configuration.Configuration; import javax.cache.spi.CachingProvider; import org.infinispan.AdvancedCache; import org.infinispan.commons.api.BasicCache; import org.infinispan.commons.util.FileLookup; import org.infinispan.commons.util.FileLookupFactory; import org.infinispan.commons.util.ReflectionUtil; import org.infinispan.configuration.global.GlobalConfigurationBuilder; import org.infinispan.configuration.parsing.ConfigurationBuilderHolder; import org.infinispan.configuration.parsing.ParserRegistry; import org.infinispan.jcache.AbstractJCache; import org.infinispan.jcache.AbstractJCacheManager; import org.infinispan.jcache.embedded.logging.Log; import org.infinispan.manager.DefaultCacheManager; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.util.logging.LogFactory; /** * Infinispan's implementation of {@link javax.cache.CacheManager}. * * @author Vladimir Blagojevic * @author Galder ZamarreƱo * @since 5.3 */ public class JCacheManager extends AbstractJCacheManager { private static final Log log = LogFactory.getLog(JCacheManager.class, Log.class); private final EmbeddedCacheManager cm; /** * Create a new InfinispanCacheManager given a cache name and a {@link ClassLoader}. Cache name * might refer to a file on classpath containing Infinispan configuration file. * * @param uri identifies the cache manager * @param classLoader used to load classes stored in this cache manager */ public JCacheManager(URI uri, ClassLoader classLoader, CachingProvider provider, Properties properties) { super(uri, classLoader, provider, properties, false); if (classLoader == null) { throw new IllegalArgumentException("Classloader cannot be null"); } if (uri == null) { throw new IllegalArgumentException("Invalid CacheManager URI " + uri); } ConfigurationBuilderHolder cbh = getConfigurationBuilderHolder(classLoader); GlobalConfigurationBuilder globalBuilder = cbh.getGlobalConfigurationBuilder(); // The cache manager name has to contain all uri, class loader and // provider information in order to guarantee JMX naming uniqueness. // This is tested by the TCK to make sure caching provider loaded // with different classloaders, even if the default classloader for // the cache manager is the same, are really different cache managers. String cacheManagerName = "uri=" + uri + "/classloader=" + classLoader.toString() + "/provider=" + provider.toString(); // Set cache manager class loader and apply name to cache manager MBean globalBuilder.classLoader(classLoader) .globalJmxStatistics().cacheManagerName(cacheManagerName); cm = new DefaultCacheManager(cbh, true); registerPredefinedCaches(); } public JCacheManager(URI uri, EmbeddedCacheManager cacheManager, CachingProvider provider) { super(uri, null, provider, null, true); this.cm = cacheManager; registerPredefinedCaches(); } private void registerPredefinedCaches() { // TODO get predefined caches and register them // TODO galderz find a better way to do this as spec allows predefined caches to be // loaded (config file), instantiated and registered with CacheManager Set<String> cacheNames = cm.getCacheNames(); for (String cacheName : cacheNames) { // With pre-defined caches, obey only pre-defined configuration registerPredefinedCache(cacheName, new JCache<Object, Object>( cm.getCache(cacheName).getAdvancedCache(), this, ConfigurationAdapter.create())); } } private ConfigurationBuilderHolder getConfigurationBuilderHolder( ClassLoader classLoader) { try { FileLookup fileLookup = FileLookupFactory.newInstance(); InputStream configurationStream = getURI().isAbsolute() ? fileLookup.lookupFileStrict(getURI(), classLoader) : fileLookup.lookupFileStrict(getURI().toString(), classLoader); return new ParserRegistry(classLoader).parse(configurationStream); } catch (FileNotFoundException e) { // No such file, lets use default CBH return new ConfigurationBuilderHolder(classLoader); } } @Override public <T> T unwrap(Class<T> clazz) { return ReflectionUtil.unwrapAny(clazz, this, cm); } @Override public ClassLoader getClassLoader() { return cm.getCacheManagerConfiguration().classLoader(); } @Override protected void delegateLogIsClosed() { throw log.cacheManagerClosed(cm.getStatus()); } @Override protected void delegateStop() { cm.stop(); } @Override protected Iterable<String> delegateCacheNames() { return cm.getCacheNames(); } @Override protected boolean delegateIsClosed() { return cm.getStatus().isTerminated(); } @Override protected <K, V> void delegateRemoveCache(AbstractJCache<K, V> jcache) { String cacheName = jcache.getName(); cm.removeCache(cacheName); cm.undefineConfiguration(cacheName); } @Override protected <K, V, C extends Configuration<K, V>> AbstractJCache<K, V> create(String cacheName, C configuration) { ConfigurationAdapter<K, V> adapter = ConfigurationAdapter.create(configuration); cm.defineConfiguration(cacheName, adapter.build()); AdvancedCache<K, V> ispnCache = cm.<K, V>getCache(cacheName).getAdvancedCache(); // In case the cache was stopped if (!ispnCache.getStatus().allowInvocations()) ispnCache.start(); return new JCache<K, V>(ispnCache, this, adapter); } @Override protected <K, V, I extends BasicCache<K, V>> AbstractJCache<K, V> create(I ispnCache) { return new JCache<K, V>((AdvancedCache<K, V>) ispnCache, this, ConfigurationAdapter.<K, V>create()); } }