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

org.sakaiproject.memory.impl.SakaiCacheManagerFactoryBean Maven / Gradle / Ivy

There is a newer version: 23.3
Show newest version
/******************************************************************************
 * $URL: https://source.sakaiproject.org/svn/master/trunk/header.java $
 * $Id: header.java 307632 2014-03-31 15:29:37Z [email protected] $
 ******************************************************************************
 *
 * Copyright (c) 2003-2014 The Apereo Foundation
 *
 * Licensed under the Educational Community 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://opensource.org/licenses/ecl2
 *
 * 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.sakaiproject.memory.impl;

import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.config.*;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.component.api.ServerConfigurationService;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;

/**
 * NOTE: This file was modeled after org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java from URL
 * http://grepcode.com/file_/repo1.maven.org/maven2/org.springframework/spring-context-support/3.2.3.RELEASE/org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java/?v=source
 *
 * @author rlong Bob Long [email protected]
 * @author azeckoski Aaron Zeckoski [email protected]
 *
 * ORIGINAL JAVADOC BELOW:
 * {@link FactoryBean} that exposes an EhCache {@link net.sf.ehcache.CacheManager}
 * instance (independent or shared), configured from a specified config location.
 *
 * 

If no config location is specified, a CacheManager will be configured from * "ehcache.xml" in the root of the class path (that is, default EhCache initialization * - as defined in the EhCache docs - will apply). * *

Setting up a separate EhCacheManagerFactoryBean is also advisable when using * EhCacheFactoryBean, as it provides a (by default) independent CacheManager instance * and cares for proper shutdown of the CacheManager. EhCacheManagerFactoryBean is * also necessary for loading EhCache configuration from a non-default config location. * *

Note: As of Spring 3.0, Spring's EhCache support requires EhCache 1.3 or higher. * As of Spring 3.2, we recommend using EhCache 2.1 or higher. * * @author Dmitriy Kopylenko * @author Juergen Hoeller */ public class SakaiCacheManagerFactoryBean implements FactoryBean, InitializingBean, DisposableBean { // Check whether EhCache 2.1+ CacheManager.create(Configuration) method is available... private static final Method createWithConfiguration = ClassUtils.getMethodIfAvailable(CacheManager.class, "create", Configuration.class); /** cache defaults **/ private final static String DEFAULT_CACHE_SERVER_URL = "localhost:9510"; private final static int DEFAULT_CACHE_TIMEOUT = 600; // 10 mins private final static int DEFAULT_CACHE_MAX_OBJECTS = 10000; protected final Log logger = LogFactory.getLog(getClass()); protected ServerConfigurationService serverConfigurationService; private Resource configLocation; private boolean shared = false; private String cacheManagerName = "Sakai"; private CacheManager cacheManager; private Boolean cacheEnabled; public SakaiCacheManagerFactoryBean() { } public SakaiCacheManagerFactoryBean(ServerConfigurationService serverConfigurationService) { this.serverConfigurationService = serverConfigurationService; this.cacheManagerName = "SakaiTest"; try { this.afterPropertiesSet(); } catch (Exception e) { throw new RuntimeException(e); } } /** * Set the location of the EhCache config file. A typical value is "/WEB-INF/ehcache.xml". *

Default is "ehcache.xml" in the root of the class path, or if not found, * "ehcache-failsafe.xml" in the EhCache jar (default EhCache initialization). * @see net.sf.ehcache.CacheManager#create(java.io.InputStream) * @see net.sf.ehcache.CacheManager#CacheManager(java.io.InputStream) */ public void setConfigLocation(Resource configLocation) { this.configLocation = configLocation; } /** * Set whether the EhCache CacheManager should be shared (as a singleton at the VM level) * or independent (typically local within the application). Default is "false", creating * an independent instance. * @see net.sf.ehcache.CacheManager#create() * @see net.sf.ehcache.CacheManager#CacheManager() */ public void setShared(boolean shared) { this.shared = shared; } /** * Set the name of the EhCache CacheManager (if a specific name is desired). * @see net.sf.ehcache.CacheManager#setName(String) */ public void setCacheManagerName(String cacheManagerName) { this.cacheManagerName = cacheManagerName; } /** * Creates a CacheConfiguration based on the cache name. * Any Cache properties below that are not set will use the default values * Valid properties include: maxSize, timeToIdle, timeToLive, eternal * Defaults: maxSize=10000, timeToIdle=600, timeToLive=600, eternal=false * Configure cluster caches using: memory.cluster.{cacheName}.{property)={value} * * @param clusterCacheName the full name of the cache (e.g. org.sakaiproject.event.impl.ClusterEventTracking.eventsCache) * @return Terracotta cluster cache configuration */ private CacheConfiguration createClusterCacheConfiguration(String clusterCacheName) { String clusterConfigName = "memory.cluster."+clusterCacheName; CacheConfiguration clusterCache = new CacheConfiguration( clusterCacheName, serverConfigurationService.getInt(clusterConfigName + ".maxEntries", DEFAULT_CACHE_MAX_OBJECTS)); boolean isEternal = serverConfigurationService.getBoolean(clusterConfigName + ".eternal", false); if (isEternal) { clusterCache.eternal(true).timeToIdleSeconds(0).timeToLiveSeconds(0); } else { clusterCache.eternal(false) .timeToIdleSeconds(serverConfigurationService.getInt(clusterConfigName + ".timeToIdle", DEFAULT_CACHE_TIMEOUT)) .timeToLiveSeconds(serverConfigurationService.getInt(clusterConfigName + ".timeToLive", DEFAULT_CACHE_TIMEOUT)); } clusterCache.terracotta(new TerracottaConfiguration() .nonstop(new NonstopConfiguration() .timeoutBehavior(new TimeoutBehaviorConfiguration() .type(TimeoutBehaviorConfiguration.LOCAL_READS_TYPE_NAME)) .enabled(true))); // Make sure we don't go to local disk clusterCache.overflowToOffHeap(false); // Required to control the L2 cache size in terracotta itself, default should be adequate clusterCache.maxElementsOnDisk(10000); return clusterCache; } /** * This is the init method * If using Terracotta, enable caching via sakai.properties and ensure the Terracotta server is reachable * Use '-Dcom.tc.tc.config.total.timeout=10000' to specify how long we should try to connect to the TC server */ public void afterPropertiesSet() throws IOException { logger.info("Initializing EhCache CacheManager"); InputStream is = (this.configLocation != null ? this.configLocation.getInputStream() : null); if (this.cacheEnabled == null) { this.cacheEnabled = serverConfigurationService.getBoolean("memory.cluster.enabled", false); } try { Configuration configuration = (is != null) ? ConfigurationFactory.parseConfiguration(is) : ConfigurationFactory.parseConfiguration(); configuration.setName(this.cacheManagerName); // force the sizeof calculations to not generate lots of warnings OR degrade server performance configuration.getSizeOfPolicyConfiguration().maxDepthExceededBehavior(SizeOfPolicyConfiguration.MaxDepthExceededBehavior.ABORT); configuration.getSizeOfPolicyConfiguration().maxDepth(100); // Setup the Terracotta cluster config TerracottaClientConfiguration terracottaConfig = new TerracottaClientConfiguration(); // use Terracotta server if running and available if (this.cacheEnabled) { logger.info("Attempting to load cluster caching using Terracotta at: "+ serverConfigurationService.getString("memory.cluster.server.urls", DEFAULT_CACHE_SERVER_URL)+"."); // set the URL to the server String[] serverUrls = serverConfigurationService.getStrings("memory.cluster.server.urls"); // create comma-separated string of URLs String serverUrlsString = StringUtils.join(serverUrls, ","); terracottaConfig.setUrl(serverUrlsString); terracottaConfig.setRejoin(true); configuration.addTerracottaConfig(terracottaConfig); // retrieve the names of all caches that will be managed by Terracotta and create cache configurations for them String[] caches = serverConfigurationService.getStrings("memory.cluster.names"); if (ArrayUtils.isNotEmpty(caches)) { for (String cacheName : caches) { CacheConfiguration cacheConfiguration = this.createClusterCacheConfiguration(cacheName); if (cacheConfiguration != null) { configuration.addCache(cacheConfiguration); } } } // create new cache manager with the above configuration if (this.shared) { this.cacheManager = (CacheManager) ReflectionUtils.invokeMethod(createWithConfiguration, null, configuration); } else { this.cacheManager = new CacheManager(configuration); } } else { // This block contains the original code from org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java // A bit convoluted for EhCache 1.x/2.0 compatibility. // To be much simpler once we require EhCache 2.1+ logger.info("Attempting to load default cluster caching."); configuration.addTerracottaConfig(terracottaConfig); if (this.cacheManagerName != null) { if (this.shared && createWithConfiguration == null) { // No CacheManager.create(Configuration) method available before EhCache 2.1; // can only set CacheManager name after creation. this.cacheManager = (is != null ? CacheManager.create(is) : CacheManager.create()); this.cacheManager.setName(this.cacheManagerName); } else { configuration.setName(this.cacheManagerName); if (this.shared) { this.cacheManager = (CacheManager) ReflectionUtils.invokeMethod(createWithConfiguration, null, configuration); } else { this.cacheManager = new CacheManager(configuration); } } } else if (this.shared) { // For strict backwards compatibility: use simplest possible constructors... this.cacheManager = (is != null ? CacheManager.create(is) : CacheManager.create()); } else { this.cacheManager = (is != null ? new CacheManager(is) : new CacheManager()); } } } catch (CacheException ce) { // this is thrown if we can't connect to the Terracotta server on initialization if (this.cacheEnabled && this.cacheManager == null) { logger.error("You have cluster caching enabled in sakai.properties, but do not have a Terracotta server running at "+ serverConfigurationService.getString("memory.cluster.server.urls", DEFAULT_CACHE_SERVER_URL)+ ". Please ensure the server is running and available.", ce); // use the default cache instead this.cacheEnabled = false; afterPropertiesSet(); } else { logger.error("An error occurred while creating the cache manager: ", ce); } } finally { if (is != null) { is.close(); } } } public CacheManager getObject() { return this.cacheManager; } public Class getObjectType() { return (this.cacheManager != null ? this.cacheManager.getClass() : CacheManager.class); } public boolean isSingleton() { return true; } public void destroy() { logger.info("Shutting down EhCache CacheManager"); this.cacheManager.shutdown(); } public void setServerConfigurationService(ServerConfigurationService serverConfigurationService) { this.serverConfigurationService = serverConfigurationService; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy