/* * Copyright (C) 2011 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.services.ispn; import org.exoplatform.commons.utils.SecurityHelper; import org.exoplatform.container.ExoContainer; import org.exoplatform.container.configuration.ConfigurationManager; import org.exoplatform.container.util.TemplateConfigurationHelper; import org.exoplatform.container.xml.InitParams; import org.exoplatform.container.xml.PropertiesParam; import org.exoplatform.container.xml.ValueParam; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.transaction.TransactionService; import org.infinispan.Cache; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.configuration.global.GlobalConfigurationBuilder; import org.infinispan.configuration.parsing.ConfigurationBuilderHolder; import org.infinispan.configuration.parsing.ParserRegistry; import org.infinispan.manager.DefaultCacheManager; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.transaction.lookup.TransactionManagerLookup; import org.picocontainer.Startable; import java.security.PrivilegedExceptionAction; import java.util.Map; import java.util.Map.Entry; import javax.transaction.TransactionManager; /** * This class is used to allow to use infinispan in distribution mode with * the ability to launch infinispan instances in standalone mode, in other * words outside an application server. To make it possible we will need to share * the same cache instance whatever the related {@link ExoContainer} because * to be able to launch ispn instances in standalone mode we need to have a static * configuration file. * * @author <a href="mailto:nfilotto@exoplatform.com">Nicolas Filotto</a> * @version $Id$ * */ public class DistributedCacheManager implements Startable { /** * The logger */ private static final Log LOG = ExoLogger //NOSONAR .getLogger("exo.kernel.component.ext.cache.impl.infinispan.v5.DistributedCacheManager");//NOSONAR /** * The parameter name corresponding to the infinispan configuration */ private static final String CONFIG_FILE_PARAMETER_NAME = "infinispan-configuration"; /** * The parameter name corresponding to the parameters to inject * into the infinispan configuration file */ private static final String PARAMS_PARAMETER_NAME = "parameters"; /** * The infinispan cache manager */ protected final EmbeddedCacheManager manager; /** * Default constructor */ public DistributedCacheManager(String configurationFile, Map<String, String> parameters, ConfigurationManager configManager) { this.manager = init(configurationFile, parameters, configManager, null); } /** * Default constructor */ public DistributedCacheManager(InitParams params, ConfigurationManager configManager) { this(params, configManager, null); } /** * Default constructor */ public DistributedCacheManager(InitParams params, ConfigurationManager configManager, TransactionService ts) { ValueParam vp; final String result; if (params != null && (vp = params.getValueParam(CONFIG_FILE_PARAMETER_NAME)) != null && (result = vp.getValue()) != null && !result.isEmpty()) { PropertiesParam pp = params.getPropertiesParam(PARAMS_PARAMETER_NAME); this.manager = init(result, pp == null ? null : pp.getProperties(), configManager, ts == null ? null : ts.getTransactionManager()); } else { throw new IllegalArgumentException("The parameter '" + CONFIG_FILE_PARAMETER_NAME + "' must be set"); } } /** * Initializes and created the CacheManager * @param configurationFile the path of the configuration file * @param parameters the parameters to inject into the configuration file * @param configManager the configuration manager used to get the configuration file * @param tm the transaction manager * @return the CacheManager initialized */ private EmbeddedCacheManager init(final String configurationFile, final Map<String, String> parameters, final ConfigurationManager configManager, final TransactionManager tm) { try { if (configurationFile == null || configurationFile.isEmpty()) { throw new IllegalArgumentException("The parameter 'configurationFile' must be set"); } if (LOG.isDebugEnabled()) { LOG.debug("The configuration file of the DistributedCacheManager will be loaded from " + configurationFile); } final TemplateConfigurationHelper helper = new TemplateConfigurationHelper(new String[]{"^.*"}, new String[]{}, configManager); if (LOG.isDebugEnabled() && parameters != null && !parameters.isEmpty()) { LOG.debug("The parameters to use while processing the configuration file are " + parameters); } return SecurityHelper.doPrivilegedIOExceptionAction(new PrivilegedExceptionAction<EmbeddedCacheManager>() { public EmbeddedCacheManager run() throws Exception { ParserRegistry parser = new ParserRegistry(Thread.currentThread().getContextClassLoader()); // Load the configuration ConfigurationBuilderHolder holder = parser.parse(helper.fillTemplate(configurationFile, parameters)); GlobalConfigurationBuilder configBuilder = holder.getGlobalConfigurationBuilder(); Utils.loadJGroupsConfig(configManager, configBuilder.build(), configBuilder); // Create the CacheManager from the new configuration EmbeddedCacheManager manager = new DefaultCacheManager(configBuilder.build(), holder.getDefaultConfigurationBuilder().build()); TransactionManagerLookup tml = new TransactionManagerLookup() { public TransactionManager getTransactionManager() throws Exception { return tm; } }; for (Entry<String, ConfigurationBuilder> entry : holder.getNamedConfigurationBuilders().entrySet()) { ConfigurationBuilder b = entry.getValue(); if (tm != null) { b.transaction().transactionManagerLookup(tml); } manager.defineConfiguration(entry.getKey(), b.build()); manager.getCache(entry.getKey()); } return manager; } }); } catch (Exception e)//NOSONAR { throw new IllegalStateException( "Could not initialize the cache manager corresponding to the configuration file " + configurationFile, e); } } /** * Gives the cache corresponding to the given name if it doesn't exist * a {@link NullPointerException} will be thrown */ public <K, V> Cache<K, V> getCache(String cacheName) { Cache<K, V> cache = manager.getCache(cacheName, false); if (cache == null) { throw new IllegalArgumentException("The expected cache named '" + cacheName + "' has not been defined in the configuration of infinispan as named cache."); } return cache; } /** * @see org.picocontainer.Startable#start() */ @Override public void start() { } /** * @see org.picocontainer.Startable#stop() */ @Override public void stop() { manager.stop(); } }