/* * * 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; } } }