package org.infinispan.jcache.remote;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Objects;
import java.util.Properties;
import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.configuration.Configuration;
import javax.cache.spi.CachingProvider;
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
import org.infinispan.commons.api.BasicCache;
import org.infinispan.commons.logging.LogFactory;
import org.infinispan.commons.util.FileLookupFactory;
import org.infinispan.commons.util.ReflectionUtil;
import org.infinispan.jcache.AbstractJCache;
import org.infinispan.jcache.AbstractJCacheManager;
import org.infinispan.jcache.logging.Log;
public class JCacheManager extends AbstractJCacheManager {
private static final Log log = LogFactory.getLog(JCacheManager.class, Log.class);
private RemoteCacheManager cm;
private RemoteCacheManager cmForceReturnValue;
private RemoteCacheAccess cacheAccess;
public JCacheManager(URI uri, ClassLoader classLoader, CachingProvider provider, Properties properties) {
super(uri, classLoader, provider, properties, false);
ConfigurationBuilder builder = getConfigurationBuilder(properties);
org.infinispan.client.hotrod.configuration.Configuration configuration = builder.build();
cm = new RemoteCacheManager(configuration, true);
builder.forceReturnValues(true);
cmForceReturnValue = new RemoteCacheManager(builder.build(), true);
cacheAccess = RemoteCacheAccess.createCacheAccess(cm, properties);
}
private ConfigurationBuilder getConfigurationBuilder(Properties userProperties) {
ConfigurationBuilder builder = new ConfigurationBuilder();
InputStream is;
if (userProperties != null && !userProperties.isEmpty()) {
this.properties = userProperties;
builder.withProperties(userProperties);
} else if ((is = findPropertiesFile()) != null) {
Properties fileProperties = new Properties();
try {
fileProperties.load(is);
this.properties = fileProperties;
builder.withProperties(fileProperties);
} catch (IOException e) {
throw new CacheException("Unable to load properties from `hotrod-client.properties`", e);
}
} else {
builder.addServer().host("127.0.0.1").port(11222);
}
return builder;
}
private InputStream findPropertiesFile() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
return FileLookupFactory.newInstance()
.lookupFile(RemoteCacheManager.HOTROD_CLIENT_PROPERTIES, cl);
}
@Override
public ClassLoader getClassLoader() {
return cm.getConfiguration().classLoader();
}
@Override
protected <K, V, C extends Configuration<K, V>> AbstractJCache<K, V> create(String cacheName, C configuration) {
ConfigurationAdapter<K, V> adapter = ConfigurationAdapter.create(configuration);
cacheAccess.addCacheIfAbsent(cacheName);
return createJCache(cacheName, adapter);
}
private <K, V> AbstractJCache<K, V> createJCache(String cacheName, ConfigurationAdapter<K, V> adapter) {
RemoteCache<K, V> ispnCache = getRemoteCache(cm, cacheName);
RemoteCache<K, V> ispnCacheForceReturnValue = getRemoteCache(cmForceReturnValue, cacheName);
return new JCache<K, V>(ispnCache, ispnCacheForceReturnValue, this, adapter);
}
private <K, V> RemoteCache<K, V> getRemoteCache(RemoteCacheManager cm, String cacheName) {
RemoteCache<K, V> ispnCache = cm.getCache(cacheName);
if (ispnCache == null) {
throw log.cacheNotFound(cacheName);
}
return ispnCache;
}
@Override
public <K, V> Cache<K, V> getCache(String cacheName) {
Cache<K, V> cache = super.getCache(cacheName);
return Objects.isNull(cache)
? createRegisterJCache(cacheName)
: cache;
}
public <K, V> Cache<K, V> createRegisterJCache(String cacheName) {
RemoteCache<K, V> ispnCache = cm.getCache(cacheName);
RemoteCache<K, V> ispnCacheForceReturnValue = cmForceReturnValue.getCache(cacheName);
if (ispnCache != null && cmForceReturnValue != null) {
ConfigurationAdapter<K, V> adapter = ConfigurationAdapter.create();
JCache<K, V> jcache = new JCache<>(ispnCache, ispnCacheForceReturnValue, this, adapter);
registerPredefinedCache(cacheName, jcache);
return jcache;
}
return null;
}
@Override
public <K, V> Cache<K, V> getCache(String cacheName, Class<K> keyType, Class<V> valueType) {
Cache<K, V> cache = super.getCache(cacheName, keyType, valueType);
return Objects.isNull(cache)
? createRegisterJCache(cacheName)
: cache;
}
@Override
protected <K, V, I extends BasicCache<K, V>> AbstractJCache<K, V> create(I ispnCache) {
return null;
//FIXME implement me
}
@Override
public <T> T unwrap(Class<T> clazz) {
return ReflectionUtil.unwrap(this, clazz);
}
@Override
protected Iterable<String> delegateCacheNames() {
return getManagedCacheNames();
}
@Override
protected void delegateStop() {
cm.stop();
cmForceReturnValue.stop();
}
@Override
protected boolean delegateIsClosed() {
return false;
//FIXME implement me
}
@Override
protected <K, V> void delegateRemoveCache(AbstractJCache<K, V> jcache) {
cacheAccess.removeCache(jcache.getName());
jcache.close();
}
@Override
protected void delegateLogIsClosed() {
throw log.cacheClosed();
}
}