com.github.lontime.shaded.org.redisson.jcache.JCacheManager Maven / Gradle / Ivy
The newest version!
/**
* Copyright (c) 2013-2021 Nikita Koksharov
*
* 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 com.github.lontime.shaded.org.redisson.jcache;
import java.lang.management.ManagementFactory;
import java.net.URI;
import java.util.Collections;
import java.util.HashSet;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheManager;
import javax.cache.configuration.CompleteConfiguration;
import javax.cache.configuration.Configuration;
import javax.cache.spi.CachingProvider;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import com.github.lontime.shaded.org.redisson.Redisson;
import com.github.lontime.shaded.org.redisson.jcache.bean.EmptyStatisticsMXBean;
import com.github.lontime.shaded.org.redisson.jcache.bean.JCacheManagementMXBean;
import com.github.lontime.shaded.org.redisson.jcache.bean.JCacheStatisticsMXBean;
import com.github.lontime.shaded.org.redisson.jcache.configuration.JCacheConfiguration;
import com.github.lontime.shaded.org.redisson.jcache.configuration.RedissonConfiguration;
/**
*
* @author Nikita Koksharov
*
*/
public class JCacheManager implements CacheManager {
private static final EmptyStatisticsMXBean EMPTY_INSTANCE = new EmptyStatisticsMXBean();
private static MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
private final ClassLoader classLoader;
private final CachingProvider cacheProvider;
private final Properties properties;
private final URI uri;
private final ConcurrentMap> caches = new ConcurrentHashMap>();
private final ConcurrentMap, JCacheStatisticsMXBean> statBeans = new ConcurrentHashMap, JCacheStatisticsMXBean>();
private final ConcurrentMap, JCacheManagementMXBean> managementBeans = new ConcurrentHashMap, JCacheManagementMXBean>();
private volatile boolean closed;
private final Redisson redisson;
public JCacheManager(Redisson redisson, ClassLoader classLoader, CachingProvider cacheProvider, Properties properties, URI uri) {
super();
this.classLoader = classLoader;
this.cacheProvider = cacheProvider;
this.properties = properties;
this.uri = uri;
this.redisson = redisson;
}
@Override
public CachingProvider getCachingProvider() {
return cacheProvider;
}
@Override
public URI getURI() {
return uri;
}
@Override
public ClassLoader getClassLoader() {
return classLoader;
}
@Override
public Properties getProperties() {
return properties;
}
private void checkNotClosed() {
if (closed) {
throw new IllegalStateException();
}
}
@Override
public > Cache createCache(String cacheName, C configuration)
throws IllegalArgumentException {
checkNotClosed();
Redisson cacheRedisson = redisson;
if (cacheName == null) {
throw new NullPointerException();
}
if (configuration == null) {
throw new NullPointerException();
}
if (cacheRedisson == null && !(configuration instanceof RedissonConfiguration)) {
throw new IllegalStateException("Default configuration hasn't been specified!");
}
boolean hasOwnRedisson = false;
if (configuration instanceof RedissonConfiguration) {
RedissonConfiguration rc = (RedissonConfiguration) configuration;
if (rc.getConfig() != null) {
cacheRedisson = (Redisson) Redisson.create(rc.getConfig());
hasOwnRedisson = true;
} else {
cacheRedisson = (Redisson) rc.getRedisson();
}
}
JCacheConfiguration cfg = new JCacheConfiguration(configuration);
JCache cache = new JCache(this, cacheRedisson, cacheName, cfg, hasOwnRedisson);
JCache, ?> oldCache = caches.putIfAbsent(cacheName, cache);
if (oldCache != null) {
throw new CacheException("Cache " + cacheName + " already exists");
}
if (cfg.isStatisticsEnabled()) {
enableStatistics(cacheName, true);
}
if (cfg.isManagementEnabled()) {
enableManagement(cacheName, true);
}
return cache;
}
@Override
public Cache getCache(String cacheName, Class keyType, Class valueType) {
checkNotClosed();
if (cacheName == null) {
throw new NullPointerException();
}
if (keyType == null) {
throw new NullPointerException();
}
if (valueType == null) {
throw new NullPointerException();
}
JCache, ?> cache = caches.get(cacheName);
if (cache == null) {
return null;
}
if (!keyType.isAssignableFrom(cache.getConfiguration(CompleteConfiguration.class).getKeyType())) {
throw new ClassCastException("Wrong type of key for " + cacheName);
}
if (!valueType.isAssignableFrom(cache.getConfiguration(CompleteConfiguration.class).getValueType())) {
throw new ClassCastException("Wrong type of value for " + cacheName);
}
return (Cache) cache;
}
@Override
public Cache getCache(String cacheName) {
checkNotClosed();
Cache cache = (Cache) getCache(cacheName, Object.class, Object.class);
if (cache != null) {
if (cache.getConfiguration(CompleteConfiguration.class).getKeyType() != Object.class) {
throw new IllegalArgumentException("Wrong type of key for " + cacheName);
}
if (cache.getConfiguration(CompleteConfiguration.class).getValueType() != Object.class) {
throw new IllegalArgumentException("Wrong type of value for " + cacheName);
}
}
return cache;
}
@Override
public Iterable getCacheNames() {
return Collections.unmodifiableSet(new HashSet(caches.keySet()));
}
@Override
public void destroyCache(String cacheName) {
checkNotClosed();
if (cacheName == null) {
throw new NullPointerException();
}
JCache, ?> cache = caches.get(cacheName);
if (cache != null) {
cache.clear();
cache.close();
}
}
public void closeCache(JCache, ?> cache) {
caches.remove(cache.getRawName());
unregisterStatisticsBean(cache);
unregisterManagementBean(cache);
}
@Override
public void enableManagement(String cacheName, boolean enabled) {
checkNotClosed();
if (cacheName == null) {
throw new NullPointerException();
}
JCache, ?> cache = caches.get(cacheName);
if (cache == null) {
throw new NullPointerException();
}
if (enabled) {
JCacheManagementMXBean statBean = managementBeans.get(cache);
if (statBean == null) {
statBean = new JCacheManagementMXBean(cache);
JCacheManagementMXBean oldBean = managementBeans.putIfAbsent(cache, statBean);
if (oldBean != null) {
statBean = oldBean;
}
}
try {
ObjectName objectName = queryNames("Configuration", cache);
if (mBeanServer.queryNames(objectName, null).isEmpty()) {
mBeanServer.registerMBean(statBean, objectName);
}
} catch (MalformedObjectNameException e) {
throw new CacheException(e);
} catch (InstanceAlreadyExistsException e) {
throw new CacheException(e);
} catch (MBeanRegistrationException e) {
throw new CacheException(e);
} catch (NotCompliantMBeanException e) {
throw new CacheException(e);
}
} else {
unregisterManagementBean(cache);
}
cache.getConfiguration(JCacheConfiguration.class).setManagementEnabled(enabled);
}
private ObjectName queryNames(String baseName, JCache, ?> cache) throws MalformedObjectNameException {
String name = getName(baseName, cache);
return new ObjectName(name);
}
private void unregisterManagementBean(JCache, ?> cache) {
JCacheManagementMXBean statBean = managementBeans.remove(cache);
if (statBean != null) {
try {
ObjectName name = queryNames("Configuration", cache);
for (ObjectName objectName : mBeanServer.queryNames(name, null)) {
mBeanServer.unregisterMBean(objectName);
}
} catch (MalformedObjectNameException e) {
throw new CacheException(e);
} catch (MBeanRegistrationException e) {
throw new CacheException(e);
} catch (InstanceNotFoundException e) {
throw new CacheException(e);
}
}
}
public JCacheStatisticsMXBean getStatBean(JCache, ?> cache) {
JCacheStatisticsMXBean bean = statBeans.get(cache);
if (bean != null) {
return bean;
}
return EMPTY_INSTANCE;
}
private String getName(String name, JCache, ?> cache) {
return "javax.cache:type=Cache" + name + ",CacheManager="
+ cache.getCacheManager().getURI().toString().replaceAll(",|:|=|\n", ".")
+ ",Cache=" + cache.getRawName().replaceAll(",|:|=|\n", ".");
}
@Override
public void enableStatistics(String cacheName, boolean enabled) {
checkNotClosed();
if (cacheName == null) {
throw new NullPointerException();
}
JCache, ?> cache = caches.get(cacheName);
if (cache == null) {
throw new NullPointerException();
}
if (enabled) {
JCacheStatisticsMXBean statBean = statBeans.get(cache);
if (statBean == null) {
statBean = new JCacheStatisticsMXBean();
JCacheStatisticsMXBean oldBean = statBeans.putIfAbsent(cache, statBean);
if (oldBean != null) {
statBean = oldBean;
}
}
try {
ObjectName objectName = queryNames("Statistics", cache);
if (!mBeanServer.isRegistered(objectName)) {
mBeanServer.registerMBean(statBean, objectName);
}
} catch (MalformedObjectNameException e) {
throw new CacheException(e);
} catch (InstanceAlreadyExistsException e) {
throw new CacheException(e);
} catch (MBeanRegistrationException e) {
throw new CacheException(e);
} catch (NotCompliantMBeanException e) {
throw new CacheException(e);
}
} else {
unregisterStatisticsBean(cache);
}
cache.getConfiguration(JCacheConfiguration.class).setStatisticsEnabled(enabled);
}
private void unregisterStatisticsBean(JCache, ?> cache) {
JCacheStatisticsMXBean statBean = statBeans.remove(cache);
if (statBean != null) {
try {
ObjectName name = queryNames("Statistics", cache);
for (ObjectName objectName : mBeanServer.queryNames(name, null)) {
mBeanServer.unregisterMBean(objectName);
}
} catch (MalformedObjectNameException e) {
throw new CacheException(e);
} catch (MBeanRegistrationException e) {
throw new CacheException(e);
} catch (InstanceNotFoundException e) {
throw new CacheException(e);
}
}
}
@Override
public void close() {
if (isClosed()) {
return;
}
synchronized (this) {
if (!isClosed()) {
if (cacheProvider != null) {
cacheProvider.close(uri, classLoader);
}
for (Cache, ?> cache : caches.values()) {
try {
cache.close();
} catch (Exception e) {
// skip
}
}
if (redisson != null) {
redisson.shutdown();
}
closed = true;
}
}
}
@Override
public boolean isClosed() {
return closed;
}
@Override
public T unwrap(Class clazz) {
if (clazz.isAssignableFrom(getClass())) {
return clazz.cast(this);
}
throw new IllegalArgumentException();
}
}