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

org.modeshape.jcr.LocalEnvironment Maven / Gradle / Ivy

There is a newer version: 5.4.1.Final
Show newest version
/*
 * ModeShape (http://www.modeshape.org)
 *
 * Licensed 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.modeshape.jcr;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfiguration;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.manager.CacheContainer;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.transaction.LockingMode;
import org.infinispan.transaction.TransactionMode;
import org.infinispan.transaction.lookup.GenericTransactionManagerLookup;
import org.infinispan.transaction.lookup.TransactionManagerLookup;
import org.modeshape.common.logging.Logger;
import org.modeshape.common.util.CheckArg;
import org.modeshape.common.util.DelegatingClassLoader;
import org.modeshape.common.util.StringURLClassLoader;
import org.modeshape.common.util.StringUtil;

/**
 * An {@link Environment} that can be used within a local (non-clustered) process.
 * 

* To use a custom Environment instance, simply create a {@link RepositoryConfiguration} as usual but then call the * {@link RepositoryConfiguration#with(Environment)} with the Environment instance and then use the resulting * RepositoryConfiguration instance. *

*

* When a ModeShape {@link RepositoryConfiguration repository configuration} defines cache containers with configuration files on * the file system or the classpath, then a {@link LocalEnvironment} instance can be used as-is with no other configuration or * setup. *

*

* If applications wish to programmatically configure the Infinispan caches or cache containers, then those configurations can be * registered with a LocalEnvironment instance. Specifically, the {@link #addCacheContainer(String, CacheContainer)} and * {@link #addCacheContainerIfAbsent(String, CacheContainer)} methods register a programmatically created instance of a * {@link CacheContainer}. Alternatively, the {@link #defineCache(String, String, Configuration)} method can be used to register a * named cache with a programmatically created {@link Configuration Infinispan cache configuration}. *

*/ public class LocalEnvironment implements Environment { public static final Class DEFAULT_TRANSACTION_MANAGER_LOOKUP_CLASS = GenericTransactionManagerLookup.class; /** * The name for the default cache container that is used when {@link #getCacheContainer()} is called or if null is supplied as * the name in {@link #getCacheContainer(String)}. */ public static final String DEFAULT_CONFIGURATION_NAME = "defaultCacheContainer"; private final Class transactionManagerLookupClass; private final ConcurrentMap containers = new ConcurrentHashMap(); private volatile boolean shared = false; private final Logger logger = Logger.getLogger(getClass()); public LocalEnvironment() { this.transactionManagerLookupClass = DEFAULT_TRANSACTION_MANAGER_LOOKUP_CLASS; } public LocalEnvironment( Class transactionManagerLookupClass ) { if (transactionManagerLookupClass == null) transactionManagerLookupClass = DEFAULT_TRANSACTION_MANAGER_LOOKUP_CLASS; this.transactionManagerLookupClass = transactionManagerLookupClass; } /** * Get the default cache container. * * @return the default cache container; never null * @throws IOException * @throws NamingException */ public CacheContainer getCacheContainer() throws IOException, NamingException { return getCacheContainer(null); } @Override public synchronized CacheContainer getCacheContainer( String name ) throws IOException, NamingException { if (name == null) name = DEFAULT_CONFIGURATION_NAME; CacheContainer container = containers.get(name); if (container == null) { container = createContainer(name); containers.put(name, container); } return container; } /** * Shutdown this environment, allowing it to reclaim any resources. *

* This method does nothing if the environment has been marked as {@link #isShared() shared}. *

*/ @Override public synchronized void shutdown() { if (!shared) doShutdown(); } /** * Shutdown all containers and caches. */ protected void doShutdown() { for (CacheContainer container : containers.values()) { shutdown(container); } containers.clear(); } @Override public ClassLoader getClassLoader( ClassLoader fallbackLoader, String... classpathEntries ) { List urls = new ArrayList(); if (classpathEntries != null) { for (String url : classpathEntries) { if (!StringUtil.isBlank(url)) { urls.add(url); } } } Set delegates = new LinkedHashSet<>(); if (!urls.isEmpty()) { StringURLClassLoader urlClassLoader = new StringURLClassLoader(urls); // only if any custom urls were parsed add this loader if (urlClassLoader.getURLs().length > 0) { delegates.add(urlClassLoader); } } ClassLoader currentLoader = getClass().getClassLoader(); ClassLoader tccl = Thread.currentThread().getContextClassLoader(); //add the TCCL to the list if it's not the same as the current loader or the fallback loader if (fallbackLoader != null && !fallbackLoader.equals(tccl) || fallbackLoader == null && !currentLoader.equals(tccl)) { delegates.add(tccl); } if (fallbackLoader != null && !fallbackLoader.equals(currentLoader)) { // if the parent of fallback is the same as the current loader, just use that if (fallbackLoader.getParent().equals(currentLoader)) { currentLoader = fallbackLoader; } else { delegates.add(fallbackLoader); } } return delegates.isEmpty() ? currentLoader : new DelegatingClassLoader(currentLoader, delegates); } protected void shutdown( CacheContainer container ) { container.stop(); } protected Class transactionManagerLookupClass() { return transactionManagerLookupClass; } protected TransactionManagerLookup transactionManagerLookupInstance() { try { return transactionManagerLookupClass().newInstance(); } catch (Throwable t) { throw new RuntimeException(t); } } protected CacheContainer createContainer( String configFile ) throws IOException, NamingException { CacheContainer container = null; // First try finding the cache configuration ... if (configFile != null && !configFile.equals(DEFAULT_CONFIGURATION_NAME)) { configFile = configFile.trim(); try { logger.debug("Starting cache manager using configuration at '{0}'", configFile); container = new DefaultCacheManager(configFile); } catch (FileNotFoundException e) { // Configuration file was not found, so try JNDI using configFileName as JNDI name... container = (CacheContainer)jndiContext().lookup(configFile); } } if (container == null) { // The default Infinispan configuration is in-memory, local and non-clustered. // But we need a transaction manager, so use the generic TM which is a good default ... ConfigurationBuilder config = createDefaultConfigurationBuilder(); GlobalConfigurationBuilder global = createGlobalConfigurationBuilder(); container = createContainer(global, config); } return container; } /** * Create the default configuration. * * @return the default cache configuration. */ protected ConfigurationBuilder createDefaultConfigurationBuilder() { ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); configurationBuilder.transaction().transactionMode(TransactionMode.TRANSACTIONAL); configurationBuilder.transaction().transactionManagerLookup(transactionManagerLookupInstance()); configurationBuilder.transaction().lockingMode(LockingMode.PESSIMISTIC); return configurationBuilder; } /** * Create the global configuration. * * @return the global configuration. */ protected GlobalConfigurationBuilder createGlobalConfigurationBuilder() { GlobalConfigurationBuilder global = new GlobalConfigurationBuilder(); global.globalJmxStatistics().allowDuplicateDomains(true); // TODO author=Horia Chiorean date=7/26/12 description=MODE-1524 - Currently we don't use advanced externalizers // global = global.fluent().serialization().addAdvancedExternalizer(Schematic.externalizers()).build(); return global; } /** * Create a cache container using the supplied configurations. * * @param globalConfigurationBuilder the global configuration builder * @param configurationBuilder the default cache configuration builder * @return the cache container */ protected CacheContainer createContainer( GlobalConfigurationBuilder globalConfigurationBuilder, ConfigurationBuilder configurationBuilder ) { GlobalConfiguration globalConfiguration = globalConfigurationBuilder.build(); Configuration configuration = configurationBuilder.build(); logger.debug("Starting cache manager with global configuration \n{0}\nand default configuration:\n{1}", globalConfiguration, configuration); return new DefaultCacheManager(globalConfiguration, configuration); } /** * Create the default configuration. * * @return the default cache configuration. * @deprecated see {@link #createDefaultConfigurationBuilder()} */ @Deprecated protected Configuration createDefaultConfiguration() { return createDefaultConfigurationBuilder().build(); } /** * Create the global configuration. * * @return the global configuration. * @deprecated see {@link #createGlobalConfigurationBuilder()} */ @Deprecated protected GlobalConfiguration createGlobalConfiguration() { return createGlobalConfigurationBuilder().build(); } /** * Create a cache container using the supplied configurations. * * @param globalConfiguration the global configuration * @param configuration the default cache configuration * @return the cache container * @deprecated use {@link #createContainer(GlobalConfigurationBuilder, ConfigurationBuilder)} instead */ @Deprecated protected CacheContainer createContainer( GlobalConfiguration globalConfiguration, Configuration configuration ) { logger.debug("Starting cache manager with global configuration \n{0}\nand default configuration:\n{1}", globalConfiguration, configuration); return new DefaultCacheManager(globalConfiguration, configuration); } protected Context jndiContext() throws NamingException { return new InitialContext(); } /** * Add the supplied {@link CacheContainer} under the supplied name if and only if there is not already a cache container * registered at that name. * * @param name the cache container name; may be null if the {@link #DEFAULT_CONFIGURATION_NAME default configuration name} * should be used * @param cacheContainer the cache container; may not be null */ public void addCacheContainerIfAbsent( String name, CacheContainer cacheContainer ) { CheckArg.isNotNull(cacheContainer, "cacheContainer"); containers.putIfAbsent(name, cacheContainer); } /** * Add the supplied {@link CacheContainer} under the supplied name if and only if there is not already a cache container * registered at that name. * * @param name the cache container name; may be null if the {@link #DEFAULT_CONFIGURATION_NAME default configuration name} * should be used * @param cacheContainer the cache container; may not be null * @return the cache container that was previously registered in this environment by the supplied name, or null if there was * no such previously-registered cache container */ public CacheContainer addCacheContainer( String name, CacheContainer cacheContainer ) { CheckArg.isNotNull(cacheContainer, "cacheContainer"); return containers.put(name, cacheContainer); } /** * Define within the default cache container an Infinispan cache with the given cache name and configuration. Note that the * cache container is created if required, but if it exists it must implement the {@link EmbeddedCacheManager} interface for * this method to succeed. * * @param cacheName the name of the cache being defined; may not be null * @param configuration the cache configuration; may not be null * @return the clone of the supplied configuration that is used by the cache container; never null */ public Configuration defineCache( String cacheName, Configuration configuration ) { CheckArg.isNotNull(cacheName, "cacheName"); CheckArg.isNotNull(configuration, "configuration"); return defineCache(null, cacheName, configuration); } /** * Define within the named cache container an Infinispan cache with the given cache name and configuration. Note that the * cache container is created if required, but if it exists it must implement the {@link EmbeddedCacheManager} interface for * this method to succeed. * * @param cacheContainerName the name of the cache container; if null, the {@link #DEFAULT_CONFIGURATION_NAME default * container name} is used * @param cacheName the name of the cache being defined; may not be null * @param configuration the cache configuration; may not be null * @return the clone of the supplied configuration that is used by the cache container; never null */ public Configuration defineCache( String cacheContainerName, String cacheName, Configuration configuration ) { CheckArg.isNotNull(cacheName, "cacheName"); CheckArg.isNotNull(configuration, "configuration"); if (cacheContainerName == null) cacheContainerName = DEFAULT_CONFIGURATION_NAME; CacheContainer container = containers.get(cacheContainerName); if (container == null) { Configuration config = createDefaultConfiguration(); GlobalConfiguration global = createGlobalConfiguration(); CacheContainer newContainer = createContainer(global, config); container = containers.putIfAbsent(cacheContainerName, newContainer); if (container == null) container = newContainer; } return ((EmbeddedCacheManager)container).defineConfiguration(cacheName, configuration); } /** * Set whether this environment is shared amongst multiple repositories. Shared environments are not shutdown automatically, * and the application is expected to shutdown all containers and caches. By default, environments are not shared unless this * method is explicitly called with a parameter value of true. * * @param shared true if this environment is shared, or false otherwise * @see #isShared() */ public void setShared( boolean shared ) { this.shared = shared; } /** * Return whether this environment is shared amongst multiple repositories. * * @return true if this environment is shared, or false otherwise * @see #setShared(boolean) */ public boolean isShared() { return shared; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy