blob: d6e5daa9d7ee4e3fde70fcf69273fd70af7e165c [file] [log] [blame]
/*
*
* Apache Geronimo JCache Spec 1.0
*
* Copyright (C) 2003 - 2014 The Apache Software Foundation
*
* 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.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ServiceLoader;
import java.util.WeakHashMap;
public final class Caching {
public static final String JAVAX_CACHE_CACHING_PROVIDER = "javax.cache.spi.CachingProvider";
private static final CachingProviderRegistry CACHING_PROVIDERS = new CachingProviderRegistry();
private Caching() {
// no-op
}
public static ClassLoader getDefaultClassLoader() {
return CACHING_PROVIDERS.getDefaultClassLoader();
}
public static void setDefaultClassLoader(ClassLoader classLoader) {
CACHING_PROVIDERS.setDefaultClassLoader(classLoader);
}
public static CachingProvider getCachingProvider() {
return CACHING_PROVIDERS.getCachingProvider();
}
public static CachingProvider getCachingProvider(ClassLoader classLoader) {
return CACHING_PROVIDERS.getCachingProvider(classLoader);
}
public static Iterable<CachingProvider> getCachingProviders() {
return CACHING_PROVIDERS.getCachingProviders();
}
public static Iterable<CachingProvider> getCachingProviders(ClassLoader classLoader) {
return CACHING_PROVIDERS.getCachingProviders(classLoader);
}
public static CachingProvider getCachingProvider(String fullyQualifiedClassName) {
return CACHING_PROVIDERS.getCachingProvider(fullyQualifiedClassName);
}
public static CachingProvider getCachingProvider(String fullyQualifiedClassName, ClassLoader classLoader) {
return CACHING_PROVIDERS.getCachingProvider(fullyQualifiedClassName, classLoader);
}
public static <K, V> Cache<K, V> getCache(String cacheName, Class<K> keyType, Class<V> valueType) {
return getCachingProvider().getCacheManager().getCache(cacheName, keyType, valueType);
}
// logic taken from RI API
private static class CachingProviderRegistry {
private WeakHashMap<ClassLoader, LinkedHashMap<String, CachingProvider>> cachingProviders;
private volatile ClassLoader classLoader;
public CachingProviderRegistry() {
this.cachingProviders = new WeakHashMap<ClassLoader, LinkedHashMap<String, CachingProvider>>();
this.classLoader = null;
}
public ClassLoader getDefaultClassLoader() {
ClassLoader loader = classLoader;
return loader == null ? Thread.currentThread().getContextClassLoader() : loader;
}
public void setDefaultClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
public CachingProvider getCachingProvider() {
return getCachingProvider(getDefaultClassLoader());
}
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;
}
}
throw new CacheException("No CachingProviders have been configured");
}
public Iterable<CachingProvider> getCachingProviders() {
return getCachingProviders(getDefaultClassLoader());
}
public synchronized Iterable<CachingProvider> getCachingProviders(ClassLoader classLoader) {
final ClassLoader serviceClassLoader = classLoader == null ? getDefaultClassLoader() : classLoader;
LinkedHashMap<String, CachingProvider> providers = cachingProviders.get(serviceClassLoader);
if (providers == null) {
if (System.getProperties().containsKey(JAVAX_CACHE_CACHING_PROVIDER)) {
final String className = System.getProperty(JAVAX_CACHE_CACHING_PROVIDER);
providers = new LinkedHashMap<String, CachingProvider>();
providers.put(className, loadCachingProvider(className, serviceClassLoader));
} else {
providers = AccessController.doPrivileged(new PrivilegedAction<LinkedHashMap<String, CachingProvider>>() {
public LinkedHashMap<String, CachingProvider> run() {
final LinkedHashMap<String, CachingProvider> result = new LinkedHashMap<String, CachingProvider>();
try {
final Class<?> clazz = Class.forName("org.apache.geronimo.osgi.locator.ProviderLocator");
final Method getServices = clazz.getDeclaredMethod("getServices", String.class, Class.class, ClassLoader.class);
for (final CachingProvider provider : (List<CachingProvider>) getServices.invoke(null, CachingProvider.class.getName(), CachingProvider.class, serviceClassLoader)) {
result.put(provider.getClass().getName(), provider);
}
} catch (final Throwable e) {
// locator not available, try normal mode
}
final ServiceLoader<CachingProvider> serviceLoader = ServiceLoader.load(CachingProvider.class, serviceClassLoader);
for (final CachingProvider provider : serviceLoader) {
result.put(provider.getClass().getName(), provider);
}
return result;
}
});
}
cachingProviders.put(serviceClassLoader, providers);
}
return providers.values();
}
public CachingProvider getCachingProvider(String fullyQualifiedClassName) {
return getCachingProvider(fullyQualifiedClassName, getDefaultClassLoader());
}
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);
}
}
}
public synchronized CachingProvider getCachingProvider(String fullyQualifiedClassName, ClassLoader classLoader) {
ClassLoader serviceClassLoader = classLoader == null ? getDefaultClassLoader() : classLoader;
LinkedHashMap<String, CachingProvider> providers = cachingProviders.get(serviceClassLoader);
if (providers == null) {
getCachingProviders(serviceClassLoader);
providers = cachingProviders.get(serviceClassLoader);
}
CachingProvider provider = providers.get(fullyQualifiedClassName);
if (provider == null) {
provider = loadCachingProvider(fullyQualifiedClassName, serviceClassLoader);
providers.put(fullyQualifiedClassName, provider);
}
return provider;
}
}
}