Package org.jasig.portal.utils.cache

Source Code of org.jasig.portal.utils.cache.EhCacheFacade$MapCachingCacheLoader

/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Jasig 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.jasig.portal.utils.cache;

import java.beans.PropertyEditor;
import java.io.Serializable;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

import org.apache.commons.collections.map.ReferenceMap;
import org.apache.commons.lang.Validate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.portal.utils.threading.MapCachingDoubleCheckedCreator;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.util.ObjectUtils;
import org.springmodules.cache.CacheException;
import org.springmodules.cache.CachingModel;
import org.springmodules.cache.FatalCacheException;
import org.springmodules.cache.FlushingModel;
import org.springmodules.cache.provider.AbstractCacheProviderFacade;
import org.springmodules.cache.provider.CacheAccessException;
import org.springmodules.cache.provider.CacheModelValidator;
import org.springmodules.cache.provider.CacheNotFoundException;
import org.springmodules.cache.provider.ReflectionCacheModelEditor;
import org.springmodules.cache.provider.ehcache.EhCacheCachingModel;
import org.springmodules.cache.provider.ehcache.EhCacheFlushingModel;
import org.springmodules.cache.provider.ehcache.EhCacheModelValidator;

/**
* Similar to the spring-modules {@link org.springmodules.cache.provider.ehcache.EhCacheFacade} except this
* will create a cache if it does not already exist.
*
* @author Eric Dalquist
* @version $Revision$
*/
public class EhCacheFacade extends AbstractCacheProviderFacade {
    protected final Log logger = LogFactory.getLog(this.getClass());
   
    private final MapCachingDoubleCheckedCreator<String, Cache> cacheLoader = new MapCachingCacheLoader();
    private final CacheModelValidator cacheModelValidator;
    private CacheManager cacheManager;
    private boolean createMissingCaches = false;

   
    public EhCacheFacade() {
        this.cacheModelValidator = new EhCacheModelValidator();
    }


    /**
     * @return the createMissingCaches
     */
    public boolean isCreateMissingCaches() {
        return createMissingCaches;    }
    /**
     * @param createMissingCaches the createMissingCaches to set
     */
    public void setCreateMissingCaches(boolean createMissingCaches) {
        this.createMissingCaches = createMissingCaches;
    }

    /**
     * @return the cacheManager
     */
    public CacheManager getCacheManager() {
        return cacheManager;
    }
    /**
     * Sets the EHCache cache manager to use.
     *
     * @param newCacheManager
     *          the new cache manager
     */
    @Required
    public void setCacheManager(CacheManager newCacheManager) {
        Validate.notNull(newCacheManager, "cacheManager can not be null");
        this.cacheManager = newCacheManager;
    }


    /**
     * Returns the validator of cache models. It is always an instance of
     * <code>{@link EhCacheModelValidator}</code>.
     *
     * @return the validator of cache models
     */
    public CacheModelValidator modelValidator() {
        return this.cacheModelValidator;
    }

    /**
     * @see org.springmodules.cache.provider.CacheProviderFacade#getCachingModelEditor()
     */
    public PropertyEditor getCachingModelEditor() {
        final ReflectionCacheModelEditor editor = new ReflectionCacheModelEditor();
        editor.setCacheModelClass(EhCacheCachingModel.class);
        return editor;
    }

    /**
     * @see org.springmodules.cache.provider.CacheProviderFacade#getFlushingModelEditor()
     */
    public PropertyEditor getFlushingModelEditor() {
        final ReflectionCacheModelEditor editor = new ReflectionCacheModelEditor();
        editor.setCacheModelClass(EhCacheFlushingModel.class);
        return editor;
    }

    /**
     * Returns a EHCache cache from the cache manager.
     *
     * @param model
     *          the model containing the name of the cache to retrieve
     * @return the cache retrieved from the cache manager
     * @throws CacheNotFoundException
     *           if the cache does not exist
     * @throws CacheAccessException
     *           wrapping any unexpected exception thrown by the cache
     */
    protected Cache getCache(CachingModel model) throws CacheNotFoundException, CacheAccessException {
        final EhCacheCachingModel ehCacheCachingModel = (EhCacheCachingModel) model;
        final String cacheName = ehCacheCachingModel.getCacheName();
        return this.getCache(cacheName);
    }

    /**
     * Returns a EHCache cache from the cache manager.
     *
     * @param name
     *          the name of the cache
     * @return the cache retrieved from the cache manager
     * @throws CacheNotFoundException
     *           if the cache does not exist
     * @throws CacheAccessException
     *           wrapping any unexpected exception thrown by the cache
     */
    protected Cache getCache(String name) throws CacheNotFoundException, CacheAccessException {
        return this.cacheLoader.get(name);
    }

    /**
     * @return <code>true</code>. EHCache can only store Serializable objects
     * @see AbstractCacheProviderFacade#isSerializableCacheElementRequired()
     */
    @Override
    protected boolean isSerializableCacheElementRequired() {
        return false;
    }

    /**
     * Removes all the entries in the caches specified in the given flushing
     * model. The flushing model should be an instance of
     * <code>{@link EhCacheFlushingModel}</code>.
     *
     * @param model
     *          the flushing model.
     *
     * @throws CacheNotFoundException
     *           if the cache specified in the given model cannot be found.
     * @throws CacheAccessException
     *           wrapping any unexpected exception thrown by the cache.
     * @see AbstractCacheProviderFacade#onFlushCache(FlushingModel)
     */
    @Override
    protected void onFlushCache(FlushingModel model) throws CacheException {
        final EhCacheFlushingModel flushingModel = (EhCacheFlushingModel) model;
        final String[] cacheNames = flushingModel.getCacheNames();

        if (!ObjectUtils.isEmpty(cacheNames)) {
            CacheException cacheException = null;

            try {
                for (final String cacheName : cacheNames) {
                    final Cache cache = getCache(cacheName);
                    cache.removeAll();
                }
            }
            catch (CacheException exception) {
                cacheException = exception;
            }
            catch (Exception exception) {
                cacheException = new CacheAccessException(exception);
            }

            if (cacheException != null) {
                throw cacheException;
            }
        }
    }

    /**
     * Retrieves an object stored under the given key from the cache specified in
     * the given caching model. The caching model should be an instance of
     * <code>{@link EhCacheCachingModel}</code>.
     *
     * @param key
     *          the key of the cache entry
     * @param model
     *          the caching model
     * @return the object retrieved from the cache. Can be <code>null</code>.
     *
     * @throws CacheNotFoundException
     *           if the cache specified in the given model cannot be found.
     * @throws CacheAccessException
     *           wrapping any unexpected exception thrown by the cache.
     * @see AbstractCacheProviderFacade#onGetFromCache(Serializable, CachingModel)
     */
    @Override
    protected Object onGetFromCache(Serializable key, CachingModel model) throws CacheException {
        final Cache cache = this.getCache(model);
        Object cachedObject = null;

        try {
            final Element cacheElement = cache.get(key);
            if (cacheElement != null) {
                cachedObject = cacheElement.getObjectValue();
            }
        }
        catch (Exception exception) {
            throw new CacheAccessException(exception);
        }

        return cachedObject;
    }

    /**
     * Stores the given object under the given key in the cache specified in the
     * given caching model. The caching model should be an instance of
     * <code>{@link EhCacheCachingModel}</code>.
     *
     * @param key
     *          the key of the cache entry
     * @param model
     *          the caching model
     * @param obj
     *          the object to store in the cache
     *
     * @throws ObjectCannotBeCachedException
     *           if the object to store is not an implementation of
     *           <code>java.io.Serializable</code>.
     * @throws CacheNotFoundException
     *           if the cache specified in the given model cannot be found.
     * @throws CacheAccessException
     *           wrapping any unexpected exception thrown by the cache.
     *
     * @see AbstractCacheProviderFacade#onPutInCache(Serializable, CachingModel,
     *      Object)
     */
    @Override
    protected void onPutInCache(Serializable key, CachingModel model, Object obj) throws CacheException {
        final Cache cache = this.getCache(model);
        final Element newCacheElement = new Element(key, obj);

        try {
            cache.put(newCacheElement);
        }
        catch (Exception exception) {
            throw new CacheAccessException(exception);
        }
    }

    /**
     * Removes the object stored under the given key from the cache specified in
     * the given caching model. The caching model should be an instance of
     * <code>{@link EhCacheCachingModel}</code>.
     *
     * @param key
     *          the key of the cache entry
     * @param model
     *          the caching model
     *
     * @throws CacheNotFoundException
     *           if the cache specified in the given model cannot be found.
     * @throws CacheAccessException
     *           wrapping any unexpected exception thrown by the cache.
     * @see AbstractCacheProviderFacade#onRemoveFromCache(Serializable,
     *      CachingModel)
     */
    @Override
    protected void onRemoveFromCache(Serializable key, CachingModel model) throws CacheException {
        final Cache cache = this.getCache(model);

        try {
            cache.remove(key);
        }
        catch (Exception exception) {
            throw new CacheAccessException(exception);
        }
    }

    /**
     * @see AbstractCacheProviderFacade#validateCacheManager()
     *
     * @throws FatalCacheException
     *           if the cache manager is <code>null</code>.
     */
    @Override
    protected void validateCacheManager() throws FatalCacheException {
        this.assertCacheManagerIsNotNull(this.cacheManager);
    }

   
    /**
     * Loads {@link Cache} instances once then tracks them via a WEAK reference avoiding re-loading the
     * Cache objects for each request
     */
    private final class MapCachingCacheLoader extends MapCachingDoubleCheckedCreator<String, Cache> {
        @SuppressWarnings("unchecked")
        private MapCachingCacheLoader() {
            super(new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK));
        }

        /* (non-Javadoc)
         * @see org.jasig.portal.utils.threading.MapCachingDoubleCheckedCreator#createInternal(java.lang.Object, java.lang.Object[])
         */
        @Override
        protected Cache createInternal(String name, Object... args) {
            final Cache cache;
           
            final CacheManager cacheManager = EhCacheFacade.this.cacheManager;
            final Log logger = EhCacheFacade.this.logger;

            try {
                if (cacheManager.cacheExists(name)) {
                    cache = cacheManager.getCache(name);
                   
                    if (logger.isDebugEnabled()) {
                        logger.debug("Using existing EhCache for '" + name + "'");
                    }
                }
                else if (EhCacheFacade.this.createMissingCaches) {
                    cacheManager.addCache(name);
                    cache = cacheManager.getCache(name);
                   
                    if (logger.isWarnEnabled()) {
                        logger.warn("Created new default EhCache for '" + name + "'");
                    }
                }
                else {
                    cache = null;
                   
                    if (logger.isDebugEnabled()) {
                        logger.debug("No EhCache exists for '" + name + "' and createMissingCaches is false");
                    }
                }
            }
            catch (Exception exception) {
                throw new CacheAccessException(exception);
            }

            if (cache == null) {
                throw new CacheNotFoundException(name);
            }

            return cache;
        }

        /* (non-Javadoc)
         * @see org.jasig.portal.utils.threading.MapCachingDoubleCheckedCreator#getKey(java.lang.Object[])
         */
        @Override
        protected String getKey(Object... args) {
            return (String)args[0];
        }
    }
}
TOP

Related Classes of org.jasig.portal.utils.cache.EhCacheFacade$MapCachingCacheLoader

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.