All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.jcache.AbstractJCacheManager Maven / Gradle / Ivy

package org.infinispan.jcache;

import static org.infinispan.jcache.RIMBeanServerRegistrationUtility.ObjectNameType.CONFIGURATION;
import static org.infinispan.jcache.RIMBeanServerRegistrationUtility.ObjectNameType.STATISTICS;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

import javax.cache.Cache;
import javax.cache.CacheManager;
import javax.cache.configuration.Configuration;
import javax.cache.spi.CachingProvider;

import org.infinispan.commons.api.BasicCache;
import org.infinispan.commons.logging.LogFactory;
import org.infinispan.jcache.logging.Log;

/**
 * Infinispan's implementation of {@link javax.cache.CacheManager}.
 *
 * @author Vladimir Blagojevic
 * @author Galder Zamarreño
 */
public abstract class AbstractJCacheManager implements CacheManager {
   private static final Log log = LogFactory.getLog(AbstractJCacheManager.class, Log.class);

   private final URI uri;
   private final CachingProvider provider;
   private final Properties properties;

   private final HashMap> caches = new HashMap>();

   private final StackTraceElement[] allocationStackTrace;

   /**
    * Boolean flag tracking down whether the underlying Infinispan cache
    * manager used by JCacheManager is unmanaged or managed. Unmanaged means
    * that this JCacheManager instance controls the lifecycle of the
    * Infinispan Cache Manager. When managed, it means that the cache manager
    * is injected and hence JCacheManager is not the owner of the lifecycle
    * of this cache manager.
    */
   private final boolean managedCacheManager;

   /**
    * A flag indicating whether the cache manager is closed or not.
    * Cache manager's status does not fit well here because even if an
    * trying to stop a cache manager whose status is {@link ComponentStatus#INSTANTIATED}
    * does not change it to {@link ComponentStatus#TERMINATED}
    */
   private volatile boolean isClosed;

   public AbstractJCacheManager(URI uri, ClassLoader classLoader, CachingProvider provider, Properties properties, boolean managedCacheManager) {
      // Track allocation time
      this.allocationStackTrace = Thread.currentThread().getStackTrace();

      this.uri = uri;
      this.provider = provider;
      this.properties = properties;
      this.managedCacheManager = managedCacheManager;
      isClosed = false;
   }

   @Override
   public CachingProvider getCachingProvider() {
      return provider;
   }

   @Override
   public URI getURI() {
      return uri;
   }

   @Override
   public Properties getProperties() {
      return properties;
   }

   @Override
   public > Cache createCache(
         String cacheName, C configuration) {
      checkNotClosed().checkNull(cacheName, "cacheName").checkNull(configuration, "configuration");

      synchronized (caches) {
         AbstractJCache cache = caches.get(cacheName);

         if (cache == null) {
            cache = create(cacheName, configuration);
            caches.put(cache.getName(), cache);
         } else {
            throw log.cacheAlreadyRegistered(cacheName,
                  cache.getConfiguration(Configuration.class), configuration);
         }

         return unchecked(cache);
      }
   }

   @Override
   public  Cache getCache(String cacheName, Class keyType, Class valueType) {
      checkNotClosed().checkNull(keyType, "keyType").checkNull(valueType, "valueType");

      synchronized (caches) {
         Cache cache = unchecked(caches.get(cacheName));
         if (cache != null) {
            Configuration configuration = cache.getConfiguration(Configuration.class);

            Class cfgKeyType = configuration.getKeyType();
            if (verifyType(keyType, cfgKeyType)) {
               Class cfgValueType = configuration.getValueType();
               if (verifyType(valueType, cfgValueType))
                  return cache;

               throw log.incompatibleType(valueType, cfgValueType);
            }

            throw log.incompatibleType(keyType, cfgKeyType);
         }

         return null;
      }
   }

   @Override
   public  Cache getCache(String cacheName) {
      checkNotClosed();
      synchronized (caches) {
         Cache cache = unchecked(caches.get(cacheName));
         if (cache != null) {
            Configuration configuration = cache.getConfiguration(Configuration.class);
            Class keyType = configuration.getKeyType();
            Class valueType = configuration.getValueType();
            if (Object.class.equals(keyType) && Object.class.equals(valueType))
               return cache;

            throw log.unsafeTypedCacheRequest(cacheName, keyType, valueType);
         }

         return null;
      }
   }

   @Override
   public Iterable getCacheNames() {
      return isClosed ? Collections.emptyList() : delegateCacheNames();
   }

   @Override
   public void destroyCache(String cacheName) {
      checkNotClosed().checkNull(cacheName, "cacheName");

      AbstractJCache destroyedCache;
      synchronized (caches) {
         destroyedCache = caches.remove(cacheName);
      }

      if (destroyedCache != null) {
         /* Don't destroy caches not created through jcache. */
         delegateRemoveCache(destroyedCache);
      }
      unregisterCacheMBeans(destroyedCache);
   }

   @Override
   public void enableManagement(String cacheName, boolean enabled) {
      checkNotClosed();
      caches.get(cacheName).setManagementEnabled(enabled);
   }

   @Override
   public void enableStatistics(String cacheName, boolean enabled) {
      checkNotClosed();
      caches.get(cacheName).setStatisticsEnabled(enabled);
   }

   @Override
   public void close() {
      if (!isClosed()) {
         ArrayList> cacheList;
         synchronized (caches) {
            cacheList = new ArrayList>(caches.values());
            caches.clear();
         }
         for (AbstractJCache cache : cacheList) {
            try {
               cache.close();
               unregisterCacheMBeans(cache);
            } catch (Exception e) {
               // log?
            }
         }
         delegateStop();
         isClosed = true;
      }
   }

   @Override
   public boolean isClosed() {
      return delegateIsClosed() || isClosed;
   }

   /**
    * Avoid weak references to this cache manager
    * being garbage collected without being shutdown.
    */
   @Override
   protected void finalize() throws Throwable {
      try {
         if(!managedCacheManager && !isClosed) {
            // Create the leak description
            Throwable t = log.cacheManagerNotClosed();
            t.setStackTrace(allocationStackTrace);
            log.leakedCacheManager(t);
            // Close
            delegateStop();
         }
      } finally {
         super.finalize();
      }
   }

   public  > Cache getOrCreateCache(String cacheName, I ispnCache) {
      synchronized (caches) {
         AbstractJCache cache = caches.get(cacheName);
         if (cache == null) {
            cache = create(ispnCache);
            caches.put(cacheName, cache);
         }
         return unchecked(cache);
      }
   }

   protected  void registerPredefinedCache(String cacheName, AbstractJCache cache) {
      caches.put(cacheName, cache);
   }

   protected abstract void delegateLogIsClosed();
   protected abstract Iterable delegateCacheNames();
   protected abstract void delegateStop();
   protected abstract boolean delegateIsClosed();
   protected abstract  void delegateRemoveCache(AbstractJCache cacheName);

   protected abstract > AbstractJCache create(String cacheName, C configuration);
   protected abstract  > AbstractJCache create(I ispnCache);

   protected Set getManagedCacheNames() {
      HashSet result = new HashSet();
      synchronized (caches) {
         result.addAll(caches.keySet());
      }
      return Collections.unmodifiableSet(result);
   }

   private void unregisterCacheMBeans(AbstractJCache cache) {
      if (cache != null) {
         RIMBeanServerRegistrationUtility.unregisterCacheObject(cache, STATISTICS);
         RIMBeanServerRegistrationUtility.unregisterCacheObject(cache, CONFIGURATION);
      }
   }

   private AbstractJCacheManager checkNotClosed() {
      if (isClosed())
         delegateLogIsClosed();

      return this;
   }

   private AbstractJCacheManager checkNull(Object obj, String name) {
      if (obj == null)
         throw log.parameterMustNotBeNull(name);

      return this;
   }

   @SuppressWarnings("unchecked")
   private  Cache unchecked(Cache cache) {
      return (Cache) cache;
   }

   private  boolean verifyType(Class type, Class cfgType) {
      return cfgType != null && cfgType.equals(type);
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy