Package org.wso2.carbon.caching.infinispan

Source Code of org.wso2.carbon.caching.infinispan.InfinispanCacheManager$InfinispanJCacheWrapper

/*
*  Copyright (c) 2005-2009, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. licenses this file to you 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 org.wso2.carbon.caching.infinispan;

import net.sf.jsr107cache.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.infinispan.AdvancedCache;
import org.infinispan.config.Configuration;
import org.infinispan.config.GlobalConfiguration;
import org.infinispan.container.entries.InternalCacheEntry;
import org.infinispan.interceptors.CacheMgmtInterceptor;
import org.infinispan.interceptors.base.CommandInterceptor;
import org.infinispan.lifecycle.ComponentStatus;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.stats.Stats;
import org.wso2.carbon.base.CarbonBaseUtils;
import org.wso2.carbon.caching.core.CacheConfiguration;
import org.wso2.carbon.caching.core.CarbonCacheManager;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
* A cache manager based on <a href="http://jboss.org/infinispan">Infinispan</a> from JBoss.
*/
@SuppressWarnings("unused")
public class InfinispanCacheManager extends CacheManager implements CarbonCacheManager {
    private EmbeddedCacheManager cacheManager;
    private static final long DEFAULT_CACHE_LIFESPAN = 60000L;
    private static final String DEFAULT_CLUSTER_NAME = "wso2carbon-cache";
    private static final List<String> ALLOWED_CLASSES =
            Arrays.asList("org.wso2.carbon.utils.multitenancy.CarbonContextHolder");

    private final Map<String, Cache> caches = Collections.synchronizedMap(
            new HashMap<String, Cache>());

    private static final Log log = LogFactory.getLog(InfinispanCacheManager.class);

    /**
     * {@inheritDoc}
     */
    public void initialize(String carbonHome) {
        CarbonBaseUtils.checkSecurity(ALLOWED_CLASSES);
        log.debug("Starting Cache Manager initialization");
        CacheConfiguration cacheConfiguration = CacheConfiguration.getInstance();

        // Infinispan requires the bind.address system property to be set to function as a
        // distributed cache. This has been done in CarbonServerManager#initializeCarbon()
        GlobalConfiguration globalConfiguration;
        if (Boolean.toString(true).equals(
                cacheConfiguration.getProperty("configuration.clustering.enabled"))) {
            globalConfiguration = GlobalConfiguration.getClusteredDefault();
            String clusterName =
                    cacheConfiguration.getProperty("configuration.clustering.clusterName");
            if (clusterName != null) {
                globalConfiguration.setClusterName(clusterName);
            } else {
                globalConfiguration.setClusterName(DEFAULT_CLUSTER_NAME);
            }
        } else {
            globalConfiguration = GlobalConfiguration.getNonClusteredDefault();
        }

        String ec2ConfigFile = cacheConfiguration.getProperty("configuration.ec2.configFile");
        if (ec2ConfigFile != null) {
            Properties props = new Properties();
            props.setProperty("configurationFile", ec2ConfigFile.replace("${carbon.home}",
                    carbonHome));
            globalConfiguration.setTransportProperties(props);
        }

        globalConfiguration.setAllowDuplicateDomains(true);

        Configuration configuration = new Configuration();

        String cacheMode = cacheConfiguration.getProperty("configuration.cacheMode");
        boolean sync = Boolean.toString(true).equals(
                cacheConfiguration.getProperty("configuration.sync"));
        if ("distributed".equals(cacheMode)) {
            configuration.setCacheMode(sync ?
                    Configuration.CacheMode.DIST_SYNC : Configuration.CacheMode.DIST_ASYNC);
            if (log.isDebugEnabled()) {
                log.debug("Infinispan Cache Mode  : " + cacheMode +
                        (sync ? " (synchronous)" : " (asynchronous)"));
            }
            if (Boolean.toString(true).equals(
                    cacheConfiguration.getProperty("configuration.l1.enabled"))) {
                configuration.setL1CacheEnabled(true);
                String l1Lifespan = cacheConfiguration.getProperty("configuration.l1.lifespan");
                if (l1Lifespan != null) {
                    configuration.setL1Lifespan(Long.parseLong(l1Lifespan));
                    if (log.isDebugEnabled()) {
                        log.debug("Infinispan L1 Cache    : enabled");
                        log.debug("Infinispan L1 Lifespan : " + l1Lifespan);
                    }
                } else {
                    configuration.setL1Lifespan(DEFAULT_CACHE_LIFESPAN);
                    if (log.isDebugEnabled()) {
                        log.debug("Infinispan L1 Cache    : enabled");
                        log.debug("Infinispan L1 Lifespan : " + DEFAULT_CACHE_LIFESPAN);
                    }
                }
            } else if (log.isDebugEnabled()) {
                log.debug("Infinispan L1 Cache    : disabled");
            }
        } else if ("replicated".equals(cacheMode)) {
            configuration.setCacheMode(sync ?
                    Configuration.CacheMode.REPL_SYNC : Configuration.CacheMode.REPL_ASYNC);
            if (log.isDebugEnabled()) {
                log.debug("Infinispan Cache Mode : " + cacheMode +
                        (sync ? " (synchronous)" : " (asynchronous)"));
            }
        } else if ("invalidation".equals(cacheMode)) {
            configuration.setCacheMode(sync ?
                    Configuration.CacheMode.INVALIDATION_SYNC :
                    Configuration.CacheMode.INVALIDATION_ASYNC);
            if (log.isDebugEnabled()) {
                log.debug("Infinispan Cache Mode : " + cacheMode +
                        (sync ? " (synchronous)" : " (asynchronous)"));
            }
        } else {
            configuration.setCacheMode(Configuration.CacheMode.LOCAL);
            if (log.isDebugEnabled()) {
                log.debug("Infinispan Cache Mode : local");
            }
        }
        configuration.setExposeJmxStatistics(true);
        cacheManager = new DefaultCacheManager(globalConfiguration, configuration);
        log.debug("Successfully Initialized Infinispan Cache Manager");
    }

    /**
     * {@inheritDoc}
     */
    public String getDefaultCacheName() {
        return DefaultCacheManager.DEFAULT_CACHE_NAME;
    }

    /**
     * {@inheritDoc}
     */
    public Cache getCache(String cacheName) {
        Cache cache = caches.get(cacheName);
        if (cache == null) {
            // We wrap each Infinispan Cache, so that it can be used via the standard JSR107
            // JCache API.
            ClassLoader tccl = Thread.currentThread().getContextClassLoader();
            try {
                Thread.currentThread().setContextClassLoader(InfinispanCacheManager.class.getClassLoader());
                cache = new InfinispanJCacheWrapper(cacheManager.getCache(cacheName));
                registerCache(cacheName, cache);
            } finally {
                Thread.currentThread().setContextClassLoader(tccl);
            }
        }
        return cache;
    }

    /**
     * {@inheritDoc}
     */
    public void registerCache(String cacheName, Cache cache) {
        if (cache == null) {
            Cache removedCache = caches.remove(cacheName);
            // Removing the cache will also result in the stopping of the cache
            if (removedCache != null && removedCache instanceof InfinispanJCacheWrapper) {
                org.infinispan.Cache original =
                        ((InfinispanJCacheWrapper) removedCache).getOriginal();
                if (original.getStatus() == ComponentStatus.RUNNING) {
                    original.stop();
                }
            }
        } else {
            // We register a cache only if there is no cache already registered.
            if (caches.get(cacheName) == null) {
                caches.put(cacheName, cache);
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public CacheFactory getCacheFactory() throws CacheException {
        throw new CacheException("The InfinispanCacheManager does not provide an " +
                "in-built nor look-up a CacheFactory.");
    }
   
    ////////////////////////////////////////////////////////
    // JSR107 JCache wrapper for Infinispan
    ////////////////////////////////////////////////////////

    private static class InfinispanJCacheEntry implements CacheEntry {

        private InternalCacheEntry cacheEntry;

        private InfinispanJCacheEntry(InternalCacheEntry cacheEntry) {
            this.cacheEntry = cacheEntry;
        }

        public int getHits() {
            throw new UnsupportedOperationException("Infinispan does not allow to find the" +
                    " number of hits on a per-entry basis.");
        }

        public long getLastAccessTime() {
            if (cacheEntry == null) {
                return 0;
            }
            return cacheEntry.getLastUsed();
        }

        public long getLastUpdateTime() {
            if (cacheEntry == null) {
                return 0;
            }
            return cacheEntry.getLastUsed();
        }

        public long getCreationTime() {
            if (cacheEntry == null) {
                return 0;
            }
            return cacheEntry.getCreated();
        }

        public long getExpirationTime() {
            if (cacheEntry == null) {
                return 0;
            }
            return cacheEntry.getExpiryTime();
        }

        public long getVersion() {
            // We use the time at which the cache entry was created as the version of the entry.
            return cacheEntry.getCreated();
        }

        public boolean isValid() {
            return cacheEntry.isValid();
        }

        public long getCost() {
            // This implementation does not have a notion of cost. Accordingly, 0 is always
            // returned.
            return 0;
        }

        public Object getKey() {
            return cacheEntry != null ? cacheEntry.getKey() : null;
        }

        public Object getValue() {
            return cacheEntry != null ? cacheEntry.getValue() : null;
        }

        public Object setValue(Object o) {
            return cacheEntry != null ? cacheEntry.setValue(o) : null;
        }
    }

    private static class InfinispanJCacheStatistics implements CacheStatistics {

        private Stats stats;
        private CacheMgmtInterceptor interceptor;

        private InfinispanJCacheStatistics(AdvancedCache cache) {
            this.stats = cache.getStats();
            this.interceptor = null;
            try {
                @SuppressWarnings("unchecked")
                List<CommandInterceptor> chain = (List<CommandInterceptor>) cache.getInterceptorChain();
                for (CommandInterceptor i : chain) {
                    if (i instanceof CacheMgmtInterceptor) {
                        interceptor = (CacheMgmtInterceptor)i;
                        break;
                    }
                }
            } catch (Exception ignored) {
                // We are not bothered if this fails.
            }
        }

        public int getStatisticsAccuracy() {
            throw new UnsupportedOperationException("This version of Infinispan does not provide " +
                    "details on accuracy of statistics.");
        }

        public int getObjectCount() {
            return stats.getCurrentNumberOfEntries();
        }

        public int getCacheHits() {
            return (int) stats.getHits();
        }

        public int getCacheMisses() {
            return (int) stats.getMisses();
        }

        public void clearStatistics() {
            if (interceptor != null) {
                interceptor.resetStatistics();
            }
        }
    }

    private static class InfinispanJCacheWrapper implements Cache {

        private org.infinispan.Cache cache;

        public InfinispanJCacheWrapper(org.infinispan.Cache cache) {
            if (cache.getStatus() == ComponentStatus.TERMINATED ||
                    cache.getStatus() ==  ComponentStatus.INSTANTIATED) {
                cache.start();
            } else if (cache.getStatus() == ComponentStatus.FAILED) {
                throw new RuntimeException("Failed to start the cache: " + cache.getName());
            }
            this.cache = cache;
        }

        public org.infinispan.Cache getOriginal() {
            return cache;
        }

        public boolean containsKey(Object o) {
            return cache.containsKey(o);
        }

        public boolean containsValue(Object o) {
            return cache.containsValue(o);
        }

        public Set entrySet() {
            return cache.entrySet();
        }

        public boolean equals(Object o) {
            return (o instanceof InfinispanJCacheWrapper) &&
                    ((InfinispanJCacheWrapper)o).cache.equals(cache);
        }

        public int hashCode() {
            return (int) (((long) cache.hashCode()) +
                    this.getClass().getCanonicalName().hashCode());
        }

        public boolean isEmpty() {
            return cache.isEmpty();
        }

        public Set keySet() {
            return cache.keySet();
        }

        @SuppressWarnings("unchecked")
        public void putAll(Map map) {
            cache.putAll(map);
        }

        public int size() {
            return cache.size();
        }

        public Collection values() {
            return cache.values();
        }

        public Object get(Object o) {
            return cache.get(o);
        }

        public Map getAll(Collection collection) throws CacheException {
            Map<Object, Object> output = new ConcurrentHashMap<Object, Object>();
            for (Object o : collection) {
                output.put(o, get(o));
            }
            return output;
        }

        public void load(Object o) throws CacheException {
            for (Object listener : cache.getListeners()) {
                if (listener instanceof CacheListener) {
                    ((CacheListener)listener).onLoad(o);
                }
            }
        }

        public void loadAll(Collection collection) throws CacheException {
            for (Object o : collection) {
                load(o);
            }
        }

        public Object peek(Object o) {
            return cache.getAdvancedCache().get(o);
        }

        @SuppressWarnings("unchecked")
        public Object put(Object o, Object o1) {
            return cache.put(o, o1);
        }

        public CacheEntry getCacheEntry(Object o) {
            return new InfinispanJCacheEntry(
                    cache.getAdvancedCache().getDataContainer().get(o));
        }

        public CacheStatistics getCacheStatistics() {
            return new InfinispanJCacheStatistics(cache.getAdvancedCache());
        }

        public Object remove(Object o) {
            return cache.remove(o);
        }

        public void clear() {
            cache.clear();
        }

        public void evict() {
            cache.getAdvancedCache().getEvictionManager().processEviction();
        }

        public void addListener(CacheListener cacheListener) {
            cache.addListener(cacheListener);
        }

        public void removeListener(CacheListener cacheListener) {
            cache.removeListener(cacheListener);
        }
    }
}
TOP

Related Classes of org.wso2.carbon.caching.infinispan.InfinispanCacheManager$InfinispanJCacheWrapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.