com.maxifier.mxcache.impl.RegistryEntry Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mxcache-runtime Show documentation
Show all versions of mxcache-runtime Show documentation
Constains all classes necessary for launching a MxCache-instrumentated application
/*
* Copyright (c) 2008-2014 Maxifier Ltd. All Rights Reserved.
*/
package com.maxifier.mxcache.impl;
import com.maxifier.mxcache.NoSuchInstanceException;
import com.maxifier.mxcache.UseStorage;
import com.maxifier.mxcache.UseStorageFactory;
import com.maxifier.mxcache.caches.Cache;
import com.maxifier.mxcache.context.CacheContext;
import com.maxifier.mxcache.provider.*;
import com.maxifier.mxcache.storage.Storage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import java.util.*;
/**
* @author Alexander Kochurov ([email protected])
*/
class RegistryEntry implements CacheContext.ContextRelatedItem> {
private static final Logger logger = LoggerFactory.getLogger(RegistryEntry.class);
private static final StrategyProperty STORAGE_FACTORY_PROPERTY = new AnnotationProperty("storage.factory", Class.class, UseStorageFactory.class) {
@Override
public Class getFromAnnotation(@Nonnull UseStorageFactory annotation) {
return annotation.value();
}
};
private static final StrategyProperty STORAGE_PROPERTY = new AnnotationProperty("storage", Class.class, UseStorage.class) {
@Override
public Class getFromAnnotation(@Nonnull UseStorage annotation) {
return annotation.value();
}
};
private final CacheDescriptor descriptor;
private final CacheManager nullCacheManager;
private final WeakHashMap relatedContexts;
public RegistryEntry(CacheDescriptor descriptor) {
this.descriptor = descriptor;
if (descriptor.isDisabled()) {
nullCacheManager = new NullCacheManager(descriptor);
relatedContexts = null;
} else {
nullCacheManager = null;
relatedContexts = new WeakHashMap();
}
}
private CachingStrategy getStrategyInstance(CacheContext context, Class extends CachingStrategy> strategy) {
if (strategy == null || strategy == DefaultStrategy.class) {
return DefaultStrategy.getInstance();
}
try {
return context.getInstanceProvider().forClass(strategy);
} catch (NoSuchInstanceException e) {
logger.error("Cannot acquire instance of " + strategy, e);
return DefaultStrategy.getInstance();
}
}
public synchronized Collection> getManagers() {
if (relatedContexts == null) {
return Collections.emptySet();
}
List> managers = new ArrayList>();
for (CacheContext context : relatedContexts.keySet()) {
CacheManager manager = context.getRelated(this);
if (manager != null) {
managers.add(manager);
}
}
return Collections.unmodifiableCollection(managers);
}
private synchronized CacheManager getManager(CacheContext context) {
if (nullCacheManager != null) {
return nullCacheManager;
}
relatedContexts.put(context, null);
CacheManager manager = context.getRelated(this);
if (manager == null) {
try {
manager = createManager(context);
context.setRelated(this, manager);
} catch (Exception e) {
logger.error("Cannot instantiate cache for " + descriptor + ", will use default", e);
return DefaultStrategy.getInstance().getManager(context, descriptor);
}
}
return manager;
}
public Cache createCache(CacheContext context, T instance) {
try {
return getManager(context).createCache(instance);
} catch (RuntimeException e) {
logger.error("Cannot create cache for " + instance + ", DefaultStrategy will be used", e);
return DefaultStrategy.getInstance().getManager(context, descriptor).createCache(instance);
}
}
private void checkTooManyStrategies(Class> storageFactoryClass, Class storageClass, Class extends CachingStrategy> strategyClass) {
int n = 0;
StringBuilder message = new StringBuilder();
if (storageFactoryClass != null) {
message.append("storageFactory = ").append(storageFactoryClass);
n++;
}
if (storageClass != null) {
if (n != 0) {
message.append(", ");
}
message.append("storage = ").append(storageClass);
n++;
}
if (strategyClass != null) {
if (n != 0) {
message.append(", ");
}
message.append("strategy = ").append(strategyClass);
n++;
}
if (n > 1) {
logger.error("Too many strategy assignments: " + message + " at " + descriptor);
}
}
@SuppressWarnings({ "unchecked" })
private CacheManager createManager(CacheContext context) {
Class> storageFactoryClass = descriptor.getProperty(STORAGE_FACTORY_PROPERTY);
Class storageClass = descriptor.getProperty(STORAGE_PROPERTY);
Class extends CachingStrategy> strategyClass = descriptor.getStrategyClass();
checkTooManyStrategies(storageFactoryClass, storageClass, strategyClass);
if (storageFactoryClass != null) {
return new StorageBasedCacheManager(context, descriptor, DefaultStrategy.getInstance().getStorageFactory(context, descriptor, storageFactoryClass));
}
if (storageClass != null) {
return new StorageBasedCacheManager(context, descriptor, new CustomStorageFactory(context, descriptor, storageClass));
}
if (strategyClass == null) {
strategyClass = DefaultStrategy.class;
}
CachingStrategy strategy = getStrategyInstance(context, strategyClass);
CacheManager manager;
try {
manager = strategy.getManager(context, descriptor);
} catch (RuntimeException e) {
logger.error("Strategy failed: " + strategy + ", will try default strategy", e);
return DefaultStrategy.getInstance().getManager(context, descriptor);
}
if (manager == null) {
logger.error("Strategy failed: " + strategy + " returned null manager");
return DefaultStrategy.getInstance().getManager(context, descriptor);
}
return manager;
}
public CacheDescriptor getDescriptor() {
return descriptor;
}
@Override
public String toString() {
return "RegistryEntry{descriptor=" + descriptor + ", managers=" + (nullCacheManager == null ? getManagers() : nullCacheManager) + '}';
}
}