Copyright 2011-2016 Terracotta, Inc. Copyright 2011-2016 Oracle America Incorporated 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.
/** * Copyright 2011-2016 Terracotta, Inc. * Copyright 2011-2016 Oracle America Incorporated * * 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 javax.cache; import javax.cache.spi.CachingProvider; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.ServiceLoader; import java.util.WeakHashMap;
The Caching class provides a convenient means for an application to acquire an appropriate CachingProvider implementation.

While defined as part of the specification, its use is not required. Applications and/or containers may instead choose to directly instantiate a CachingProvider implementation based on implementation specific instructions.

When using the Caching class, CachingProvider implementations are automatically discovered when they follow the conventions outlined by the Java Development Kit ServiceLoader class.

Although automatically discovered, applications that choose to use this class should not make assumptions regarding the order in which implementations are returned by the getCachingProviders() or getCachingProviders(ClassLoader) methods.

For a CachingProvider to be automatically discoverable by the Caching class, the fully qualified class name of the CachingProvider implementation must be declared in the following file:

  META-INF/services/javax.cache.spi.CachingProvider
This file must be resolvable via the class path.

For example, in the reference implementation the contents of this file are: org.jsr107.ri.RICachingProvider

Alternatively when the fully qualified class name of a CachingProvider implementation is specified using the system property javax.cache.spi.cachingprovider, that implementation will be used as the default CachingProvider.

All CachingProviders that are automatically detected or explicitly declared and loaded by the Caching class are maintained in an internal registry. Consequently when a previously loaded CachingProvider is requested, it will be simply returned from the internal registry, without reloading and/or instantiating the said implementation again.

As required by some applications and containers, multiple co-existing CachingProviders implementations, from the same or different implementors are permitted at runtime.

To iterate through those that are currently registered a developer may use the following methods:

  1. getCachingProviders()
  2. getCachingProviders(ClassLoader)
To request a specific CachingProvider implementation, a developer should use either the getCachingProvider(String) or getCachingProvider(String, ClassLoader) method.

Where multiple CachingProviders are present, the CachingProvider returned by getters getCachingProvider() and getCachingProvider(ClassLoader) is undefined and as a result a CacheException will be thrown when attempted.

Author:Brian Oliver, Greg Luck, Yannis Cosmadopoulos
See Also:
Since:1.0
/** * The {@link Caching} class provides a convenient means for an application to * acquire an appropriate {@link CachingProvider} implementation. * <p> * While defined as part of the specification, its use is not required. * Applications and/or containers may instead choose to directly instantiate a * {@link CachingProvider} implementation based on implementation specific * instructions. * <p> * When using the {@link Caching} class, {@link CachingProvider} implementations * are automatically discovered when they follow the conventions outlined by the * Java Development Kit {@link ServiceLoader} class. * <p> * Although automatically discovered, applications that choose to use this class * should not make assumptions regarding the order in which implementations are * returned by the {@link #getCachingProviders()} or * {@link #getCachingProviders(ClassLoader)} methods. * <p> * For a {@link CachingProvider} to be automatically discoverable by the * {@link Caching} class, the fully qualified class name of the * {@link CachingProvider} implementation must be declared in the following * file: * <pre> * META-INF/services/javax.cache.spi.CachingProvider * </pre> * This file must be resolvable via the class path. * <p> * For example, in the reference implementation the contents of this file are: * <code>org.jsr107.ri.RICachingProvider</code> * <p> * Alternatively when the fully qualified class name of a * {@link CachingProvider} implementation is specified using the system property * <code>javax.cache.spi.cachingprovider</code>, that implementation will be used * as the default {@link CachingProvider}. * <p> * All {@link CachingProvider}s that are automatically detected or explicitly * declared and loaded by the {@link Caching} class are maintained in an * internal registry. Consequently when a previously loaded * {@link CachingProvider} is requested, it will be simply returned from the * internal registry, without reloading and/or instantiating the said * implementation again. * <p> * As required by some applications and containers, multiple co-existing * {@link CachingProvider}s implementations, from the same or different * implementors are permitted at runtime. * <p> * To iterate through those that are currently registered a developer may use * the following methods: * <ol> * <li>{@link #getCachingProviders()}</li> * <li>{@link #getCachingProviders(ClassLoader)}</li> * </ol> * To request a specific {@link CachingProvider} implementation, a developer * should use either the {@link #getCachingProvider(String)} or * {@link #getCachingProvider(String, ClassLoader)} method. * <p> * Where multiple {@link CachingProvider}s are present, the * {@link CachingProvider} returned by getters {@link #getCachingProvider()} and * {@link #getCachingProvider(ClassLoader)} is undefined and as a result a * {@link CacheException} will be thrown when attempted. * * @author Brian Oliver * @author Greg Luck * @author Yannis Cosmadopoulos * @since 1.0 * @see ServiceLoader * @see CachingProvider */
public final class Caching {
The javax.cache.spi.cachingprovider constant.
/** * The <code>javax.cache.spi.cachingprovider</code> constant. */
public static final String JAVAX_CACHE_CACHING_PROVIDER = "javax.cache" + ".spi.CachingProvider"; /** * The {@link CachingProviderRegistry} that tracks the {@link CachingProvider}s. */ private static final CachingProviderRegistry CACHING_PROVIDERS = new CachingProviderRegistry();
No public constructor as all methods are static.
/** * No public constructor as all methods are static. */
private Caching() { }
Obtains the ClassLoader to use for API methods that don't explicitly require a ClassLoader but internally require one.

By default this is the Thread.getContextClassLoader().

Returns:the default ClassLoader
/** * Obtains the {@link ClassLoader} to use for API methods that don't * explicitly require a {@link ClassLoader} but internally require one. * <p> * By default this is the {@link Thread#getContextClassLoader()}. * * @return the default {@link ClassLoader} */
public static ClassLoader getDefaultClassLoader() { return CACHING_PROVIDERS.getDefaultClassLoader(); }
Set the ClassLoader to use for API methods that don't explicitly require a ClassLoader, but internally use one.
Params:
/** * Set the {@link ClassLoader} to use for API methods that don't explicitly * require a {@link ClassLoader}, but internally use one. * * @param classLoader the {@link ClassLoader} or <code>null</code> if the * calling {@link Thread#getContextClassLoader()} should * be used */
public static void setDefaultClassLoader(ClassLoader classLoader) { CACHING_PROVIDERS.setDefaultClassLoader(classLoader); }
Obtains the default CachingProvider available via the getDefaultClassLoader().
Throws:
Returns:the CachingProvider
/** * Obtains the default {@link CachingProvider} available via the * {@link #getDefaultClassLoader()}. * * @return the {@link CachingProvider} * @throws CacheException should zero, or more than one * {@link CachingProvider} be available on the * classpath, or it could not be loaded * @throws SecurityException when the operation could not be performed * due to the current security settings */
public static CachingProvider getCachingProvider() { return CACHING_PROVIDERS.getCachingProvider(); }
Obtains the single CachingProvider visible to the specified ClassLoader.
Params:
Throws:
See Also:
Returns:the CachingProvider
/** * Obtains the single {@link CachingProvider} visible to the specified * {@link ClassLoader}. * * @param classLoader the {@link ClassLoader} to use for loading the * {@link CachingProvider} * @return the {@link CachingProvider} * @throws CacheException should zero, or more than one * {@link CachingProvider} be available on the * classpath, or it could not be loaded * @throws SecurityException when the operation could not be performed * due to the current security settings * @see #getCachingProviders(ClassLoader) */
public static CachingProvider getCachingProvider(ClassLoader classLoader) { return CACHING_PROVIDERS.getCachingProvider(classLoader); }
Obtains the CachingProviders that are available via the getDefaultClassLoader().

If a javax.cache.spi.cachingprovider system property is defined, only that CachingProvider specified by that property is returned. Otherwise all CachingProviders that are available via a ServiceLoader for CachingProviders using the default ClassLoader (including those previously requested via getCachingProvider(String)) are returned.

Returns:an Iterable of CachingProviders loaded by the specified ClassLoader
/** * Obtains the {@link CachingProvider}s that are available via the * {@link #getDefaultClassLoader()}. * <p> * If a <code>javax.cache.spi.cachingprovider</code> system property is defined, * only that {@link CachingProvider} specified by that property is returned. * Otherwise all {@link CachingProvider}s that are available via a * {@link ServiceLoader} for {@link CachingProvider}s using the default * {@link ClassLoader} (including those previously requested via * {@link #getCachingProvider(String)}) are returned. * * @return an {@link Iterable} of {@link CachingProvider}s loaded by the * specified {@link ClassLoader} */
public static Iterable<CachingProvider> getCachingProviders() { return CACHING_PROVIDERS.getCachingProviders(); }
Obtains the CachingProviders that are available via the specified ClassLoader.

If a javax.cache.spi.cachingprovider system property is defined, only that CachingProvider specified by that property is returned. Otherwise all CachingProviders that are available via a ServiceLoader for CachingProviders using the specified ClassLoader (including those previously requested via getCachingProvider(String, ClassLoader)) are returned.

Params:
Returns:an Iterable of CachingProviders loaded by the specified ClassLoader
/** * Obtains the {@link CachingProvider}s that are available via the specified * {@link ClassLoader}. * <p> * If a <code>javax.cache.spi.cachingprovider</code> system property is defined, * only that {@link CachingProvider} specified by that property is returned. * Otherwise all {@link CachingProvider}s that are available via a * {@link ServiceLoader} for {@link CachingProvider}s using the specified * {@link ClassLoader} (including those previously requested via * {@link #getCachingProvider(String, ClassLoader)}) are returned. * * @param classLoader the {@link ClassLoader} of the returned * {@link CachingProvider}s * @return an {@link Iterable} of {@link CachingProvider}s loaded by the * specified {@link ClassLoader} */
public static Iterable<CachingProvider> getCachingProviders( ClassLoader classLoader) { return CACHING_PROVIDERS.getCachingProviders(classLoader); }
Obtain the CachingProvider that is implemented by the specified fully qualified class name using the getDefaultClassLoader(). Should this CachingProvider already be loaded it is simply returned, otherwise an attempt will be made to load and instantiate the specified class (using a no-args constructor).
Params:
  • fullyQualifiedClassName – the fully qualified class name of the CachingProvider
Throws:
Returns:the CachingProvider
/** * Obtain the {@link CachingProvider} that is implemented by the specified * fully qualified class name using the {@link #getDefaultClassLoader()}. * Should this {@link CachingProvider} already be loaded it is simply returned, * otherwise an attempt will be made to load and instantiate the specified * class (using a no-args constructor). * * @param fullyQualifiedClassName the fully qualified class name of the * {@link CachingProvider} * @return the {@link CachingProvider} * @throws CacheException if the {@link CachingProvider} cannot be created * @throws SecurityException when the operation could not be performed * due to the current security settings */
public static CachingProvider getCachingProvider(String fullyQualifiedClassName) { return CACHING_PROVIDERS.getCachingProvider(fullyQualifiedClassName); }
Obtain the CachingProvider that is implemented by the specified fully qualified class name using the provided ClassLoader. Should this CachingProvider already be loaded it is returned, otherwise an attempt will be made to load and instantiate the specified class (using a no-args constructor).
Params:
Throws:
Returns:the CachingProvider
/** * Obtain the {@link CachingProvider} that is implemented by the specified * fully qualified class name using the provided {@link ClassLoader}. * Should this {@link CachingProvider} already be loaded it is returned, * otherwise an attempt will be made to load and instantiate the specified * class (using a no-args constructor). * * @param fullyQualifiedClassName the fully qualified class name of the * {@link CachingProvider} * @param classLoader the {@link ClassLoader} to load the * {@link CachingProvider} * @return the {@link CachingProvider} * @throws CacheException if the {@link CachingProvider} cannot be created * @throws SecurityException when the operation could not be performed * due to the current security settings */
public static CachingProvider getCachingProvider(String fullyQualifiedClassName, ClassLoader classLoader) { return CACHING_PROVIDERS.getCachingProvider(fullyQualifiedClassName, classLoader); }
A convenience that method that looks up a managed Cache given its name. using the default CachingProvider and CacheManager . For the full range of Cache look up methods see CacheManager.

This method must be used for Caches that were configured with runtime key and value types. Use CacheManager.getCache(String) for Caches where these were not specified.

Implementations must ensure that the key and value types are the same as those configured for the Cache prior to returning from this method.

Implementations may further perform type checking on mutative cache operations and throw a ClassCastException if these checks fail.

Implementations that support declarative mechanisms for pre-configuring Caches may return a pre-configured Cache instead of null.

Params:
  • cacheName – the name of the managed Cache to acquire
  • keyType – the expected Class of the key
  • valueType – the expected Class of the value
Type parameters:
  • <K> – the type of key
  • <V> – the type of value
Throws:
See Also:
Returns:the Cache or null if it does exist or can't be pre-configured
/** * A convenience that method that looks up a managed {@link Cache} given its * name. using the default <code>CachingProvider</code> and <code>CacheManager * </code>. For the full range of <code>Cache</code> look up methods see * {@link CacheManager}. * <p> * This method must be used for {@link Cache}s that were configured with * runtime key and value types. Use {@link CacheManager#getCache(String)} for * {@link Cache}s where these were not specified. * <p> * Implementations must ensure that the key and value types are the same as * those configured for the {@link Cache} prior to returning from this method. * <p> * Implementations may further perform type checking on mutative cache operations * and throw a {@link ClassCastException} if these checks fail. * <p> * Implementations that support declarative mechanisms for pre-configuring * {@link Cache}s may return a pre-configured {@link Cache} instead of * <code>null</code>. * @param <K> the type of key * @param <V> the type of value * @param cacheName the name of the managed {@link Cache} to acquire * @param keyType the expected {@link Class} of the key * @param valueType the expected {@link Class} of the value * @return the Cache or null if it does exist or can't be pre-configured * @throws IllegalStateException if the CacheManager is * {@link CacheManager#isClosed()} * @throws IllegalArgumentException if the specified key and/or value types are * incompatible with the configured cache. * @throws SecurityException when the operation could not be performed * due to the current security settings * @see CacheManager#getCache(String, Class, Class) * @see CacheManager#getCache(String) */
public static <K, V> Cache<K, V> getCache(String cacheName, Class<K> keyType, Class<V> valueType) { return getCachingProvider().getCacheManager().getCache(cacheName, keyType, valueType); }
Maintains a registry of loaded CachingProviders scoped by ClassLoader.
/** * Maintains a registry of loaded {@link CachingProvider}s scoped by * {@link ClassLoader}. */
private static class CachingProviderRegistry {
The CachingProviders by Class Name organized by the ClassLoader was used to load them.
/** * The {@link CachingProvider}s by Class Name organized by the * {@link ClassLoader} was used to load them. */
private WeakHashMap<ClassLoader, LinkedHashMap<String, CachingProvider>> cachingProviders;
The default ClassLoader. When null the Thread.getContextClassLoader() will be used.
/** * The default {@link ClassLoader}. When <code>null</code> the * {@link Thread#getContextClassLoader()} will be used. */
private volatile ClassLoader classLoader;
Constructs a CachingProviderManager.
/** * Constructs a CachingProviderManager. */
public CachingProviderRegistry() { this.cachingProviders = new WeakHashMap<ClassLoader, LinkedHashMap<String, CachingProvider>>(); this.classLoader = null; }
Obtains the ClassLoader to use for API methods that don't explicitly require a ClassLoader but internally require one.

By default this is the Thread.getContextClassLoader().

Returns:the default ClassLoader
/** * Obtains the {@link ClassLoader} to use for API methods that don't * explicitly require a {@link ClassLoader} but internally require one. * <p> * By default this is the {@link Thread#getContextClassLoader()}. * </p> * @return the default {@link ClassLoader} */
public ClassLoader getDefaultClassLoader() { ClassLoader loader = classLoader; return loader == null ? Thread.currentThread().getContextClassLoader() : loader; }
Set the ClassLoader to use for API methods that don't explicitly require a ClassLoader, but internally use one.
Params:
/** * Set the {@link ClassLoader} to use for API methods that don't explicitly * require a {@link ClassLoader}, but internally use one. * * @param classLoader the {@link ClassLoader} or <code>null</code> if the * calling {@link Thread#getContextClassLoader()} should * be used */
public void setDefaultClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; }
Obtains the only CachingProvider defined by the getDefaultClassLoader().

Should zero or more than one CachingProviders be available, a CacheException is thrown.

Throws:
See Also:
Returns:the CachingProvider
/** * Obtains the only {@link CachingProvider} defined by the * {@link #getDefaultClassLoader()}. * <p> * Should zero or more than one {@link CachingProvider}s be available, a * CacheException is thrown. * </p> * @return the {@link CachingProvider} * @throws CacheException should zero or more than one * {@link CachingProvider} be available * or a {@link CachingProvider} could not be loaded * @see #getCachingProvider(ClassLoader) * @see #getCachingProviders(ClassLoader) */
public CachingProvider getCachingProvider() { return getCachingProvider(getDefaultClassLoader()); }
Obtains the only CachingProvider defined by the specified ClassLoader.

Should zero or more than one CachingProviders be available, a CacheException is thrown.

Params:
Throws:
See Also:
Returns:the CachingProvider
/** * Obtains the only {@link CachingProvider} defined by the specified * {@link ClassLoader}. * <p> * Should zero or more than one {@link CachingProvider}s be available, a * CacheException is thrown. * </p> * @param classLoader the {@link ClassLoader} to use for loading the * {@link CachingProvider} * @return the {@link CachingProvider} * @throws CacheException should zero or more than one * {@link CachingProvider} be available * or a {@link CachingProvider} could not be loaded * @see #getCachingProviders(ClassLoader) */
public CachingProvider getCachingProvider(ClassLoader classLoader) { Iterator<CachingProvider> iterator = getCachingProviders(classLoader).iterator(); if (iterator.hasNext()) { CachingProvider provider = iterator.next(); if (iterator.hasNext()) { throw new CacheException("Multiple CachingProviders have been configured when only a single CachingProvider is expected"); } else { return provider; } } else { throw new CacheException("No CachingProviders have been configured"); } }
Obtain the CachingProviders that are available via the getDefaultClassLoader().

If a javax.cache.spi.cachingprovider system property is defined, only that CachingProvider specified by that property is returned. Otherwise all CachingProviders that are available via a ServiceLoader for CachingProviders using the default ClassLoader (and those explicitly requested via getCachingProvider(String)) are returned.

Returns:an Iterable of CachingProviders loaded by the default ClassLoader
/** * Obtain the {@link CachingProvider}s that are available via the * {@link #getDefaultClassLoader()}. * <p> * If a <code>javax.cache.spi.cachingprovider</code> system property is defined, * only that {@link CachingProvider} specified by that property is returned. * Otherwise all {@link CachingProvider}s that are available via a * {@link ServiceLoader} for {@link CachingProvider}s using the default * {@link ClassLoader} (and those explicitly requested via * {@link #getCachingProvider(String)}) are returned. * </p> * @return an {@link Iterable} of {@link CachingProvider}s loaded by the * default {@link ClassLoader} */
public Iterable<CachingProvider> getCachingProviders() { return getCachingProviders(getDefaultClassLoader()); }
Obtain the CachingProviders that are available via the specified ClassLoader.

If a javax.cache.spi.cachingprovider system property is defined, only that CachingProvider specified by that property is returned. Otherwise all CachingProviders that are available via a ServiceLoader for CachingProviders using the specified ClassLoader (and those explicitly requested via getCachingProvider(String, ClassLoader)) are returned.

Params:
Returns:an Iterable of CachingProviders loaded by the specified ClassLoader
/** * Obtain the {@link CachingProvider}s that are available via the specified * {@link ClassLoader}. * <p> * If a <code>javax.cache.spi.cachingprovider</code> system property is defined, * only that {@link CachingProvider} specified by that property is returned. * Otherwise all {@link CachingProvider}s that are available via a * {@link ServiceLoader} for {@link CachingProvider}s using the specified * {@link ClassLoader} (and those explicitly requested via * {@link #getCachingProvider(String, ClassLoader)}) are returned. * </p> * @param classLoader the {@link ClassLoader} of the returned * {@link CachingProvider}s * @return an {@link Iterable} of {@link CachingProvider}s loaded by the * specified {@link ClassLoader} */
public synchronized Iterable<CachingProvider> getCachingProviders(ClassLoader classLoader) { final ClassLoader serviceClassLoader = classLoader == null ? getDefaultClassLoader() : classLoader; LinkedHashMap<String, CachingProvider> providers = cachingProviders.get(serviceClassLoader); if (providers == null) { String className = System.getProperty(JAVAX_CACHE_CACHING_PROVIDER); if (className != null) { providers = new LinkedHashMap<String, CachingProvider>(); providers.put(className, loadCachingProvider(className, serviceClassLoader)); } else { providers = AccessController.doPrivileged(new PrivilegedAction<LinkedHashMap<String, CachingProvider>>() { @Override public LinkedHashMap<String, CachingProvider> run() { LinkedHashMap<String, CachingProvider> result = new LinkedHashMap<String, CachingProvider>(); ServiceLoader<CachingProvider> serviceLoader = ServiceLoader.load(CachingProvider.class, serviceClassLoader); for (CachingProvider provider : serviceLoader) { result.put(provider.getClass().getName(), provider); } return result; } }); } cachingProviders.put(serviceClassLoader, providers); } return providers.values(); }
Obtain the CachingProvider that is implemented by the specified fully qualified class name using the getDefaultClassLoader(). Should this CachingProvider already be loaded it is simply returned, otherwise an attempt will be made to load and instantiate the specified class name (using a no-args constructor).
Params:
  • fullyQualifiedClassName – the fully qualified class name of the CachingProvider
Throws:
Returns:the CachingProvider
/** * Obtain the {@link CachingProvider} that is implemented by the specified * fully qualified class name using the {@link #getDefaultClassLoader()}. * Should this {@link CachingProvider} already be loaded it is simply * returned, otherwise an attempt will be made to load and instantiate the * specified class name (using a no-args constructor). * * @param fullyQualifiedClassName the fully qualified class name of the * {@link CachingProvider} * @return the {@link CachingProvider} * @throws CacheException when the {@link CachingProvider} can't be created */
public CachingProvider getCachingProvider(String fullyQualifiedClassName) { return getCachingProvider(fullyQualifiedClassName, getDefaultClassLoader()); }
Load and instantiate the CachingProvider with the specified fully qualified class name using the provided ClassLoader
Params:
Throws:
Returns:a new CachingProvider instance
/** * Load and instantiate the {@link CachingProvider} with the specified * fully qualified class name using the provided {@link ClassLoader} * * @param fullyQualifiedClassName the name of the {@link CachingProvider} * class * @param classLoader the {@link ClassLoader} to use * @return a new {@link CachingProvider} instance * @throws CacheException if the specified {@link CachingProvider} could not be * loaded * or the specified class is not a {@link * CachingProvider} */
protected CachingProvider loadCachingProvider(String fullyQualifiedClassName, ClassLoader classLoader) throws CacheException { synchronized (classLoader) { try { Class<?> clazz = classLoader.loadClass(fullyQualifiedClassName); if (CachingProvider.class.isAssignableFrom(clazz)) { return ((Class<CachingProvider>) clazz).newInstance(); } else { throw new CacheException("The specified class [" + fullyQualifiedClassName + "] is not a CachingProvider"); } } catch (Exception e) { throw new CacheException("Failed to load the CachingProvider [" + fullyQualifiedClassName + "]", e); } } }
Obtain the CachingProvider that is implemented by the specified fully qualified class name using the provided ClassLoader. Should this CachingProvider already be loaded it is returned, otherwise an attempt will be made to load and instantiate the specified class (using a no-args constructor).
Params:
Throws:
Returns:the CachingProvider
/** * Obtain the {@link CachingProvider} that is implemented by the specified * fully qualified class name using the provided {@link ClassLoader}. * Should this {@link CachingProvider} already be loaded it is returned, * otherwise an attempt will be made to load and instantiate the specified * class (using a no-args constructor). * * @param fullyQualifiedClassName the fully qualified class name of the * {@link CachingProvider} * @param classLoader the {@link ClassLoader} to load the * {@link CachingProvider} * @return the {@link CachingProvider} * @throws CacheException when the {@link CachingProvider} can't be created */
public synchronized CachingProvider getCachingProvider(String fullyQualifiedClassName, ClassLoader classLoader) { ClassLoader serviceClassLoader = classLoader == null ? getDefaultClassLoader() : classLoader; LinkedHashMap<String, CachingProvider> providers = cachingProviders.get(serviceClassLoader); if (providers == null) { // first load the CachingProviders for the {@link ClassLoader} // this may automatically load the CachingProvider we desire getCachingProviders(serviceClassLoader); providers = cachingProviders.get(serviceClassLoader); } CachingProvider provider = providers.get(fullyQualifiedClassName); if (provider == null) { provider = loadCachingProvider(fullyQualifiedClassName, serviceClassLoader); providers.put(fullyQualifiedClassName, provider); } return provider; } } }