common-smartgears-app/src/main/java/org/gcube/smartgears/ApplicationManagerProvider....

115 lines
4.3 KiB
Java

package org.gcube.smartgears;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Future;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.application.manager.AppManagerObserver;
import org.gcube.smartgears.application.manager.OfflineProvider;
import org.gcube.smartgears.application.manager.OnlineProvider;
import org.gcube.smartgears.configuration.Mode;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import javassist.util.proxy.ProxyObject;
public abstract class ApplicationManagerProvider {
private static Logger logger = LoggerFactory.getLogger(ApplicationManagerProvider.class);
private Map<String, Class<?>> proxyClassMap = Collections.synchronizedMap(new HashMap<String, Class<?>>());
private Map<String, Object> classProxyObjetMap = Collections.synchronizedMap(new HashMap<String, Object>());
protected static ApplicationManagerProvider instance;
private static boolean initialized = false;
protected static synchronized void init(ApplicationContext appcontext) {
if (!initialized) {
if (appcontext.container().configuration().mode()== Mode.offline)
instance = new OfflineProvider();
else
instance = new OnlineProvider();
}
}
public static synchronized ApplicationManager get(final Class<? extends ApplicationManager> applicationManagerClass){
if (!initialized) throw new RuntimeException("ApplicationManagerProvider not yet initialized");
Object obj = instance.getApplicationManagerObject(applicationManagerClass);
return applicationManagerClass.cast(obj);
}
private Object getApplicationManagerObject(Class<? extends ApplicationManager> applicationManagerClass) {
Object obj;
try {
Class<?> _class = getProxyClass(applicationManagerClass);
if(classProxyObjetMap.containsKey(_class.getCanonicalName())){
obj = classProxyObjetMap.get(_class.getCanonicalName());
logger.trace("getting object {} from cache ",_class.getCanonicalName());
return obj;
} else {
obj = _class.newInstance();
classProxyObjetMap.put(_class.getCanonicalName(), obj);
}
} catch (Exception e) {
throw new RuntimeException("error creating proxy ", e);
}
((ProxyObject)obj).setHandler(getMethdoHandler(applicationManagerClass));
return obj;
}
protected synchronized ApplicationManager get(){
final Class<? extends ApplicationManager> applicationManagerClass = retrieveManagerClass();
return get(applicationManagerClass);
}
private Class<?> getProxyClass(Class<? extends ApplicationManager> applicationManagerClass){
if (proxyClassMap.containsKey(applicationManagerClass.getCanonicalName())){
logger.debug("getting proxy class {} for appManager from cache ",applicationManagerClass.getCanonicalName());
return proxyClassMap.get(applicationManagerClass.getCanonicalName());
}
logger.debug("creating new proxy class for appManager "+applicationManagerClass.getCanonicalName());
ProxyFactory proxyfactory = new ProxyFactory();
proxyfactory.setSuperclass(applicationManagerClass);
Class<?> proxyClass=proxyfactory.createClass();
proxyClassMap.put(applicationManagerClass.getCanonicalName(), proxyClass);
return proxyClass;
}
protected Class<? extends ApplicationManager> retrieveManagerClass(){
String classname = Thread.currentThread().getStackTrace()[3].getClassName();
logger.trace("managed servlet caller is {}",classname);
ManagedBy annotation;
try {
annotation = Class.forName(classname).getAnnotation(ManagedBy.class);
} catch (ClassNotFoundException e) {
throw new RuntimeException("error initializing ApplicationManager",e);
}
if (annotation == null){
logger.error(" {} is not managed by an ApplicationManager", classname);
throw new RuntimeException(classname+" is not managed by an ApplicationManager");
}
return annotation.value();
}
protected abstract Future<ApplicationManager> retrieveFuture(Class<? extends ApplicationManager> applicationManagerClass);
protected abstract MethodHandler getMethdoHandler(Class<? extends ApplicationManager> applicationManagerClass);
protected abstract AppManagerObserver getObserver();
}