added OfflineObserver for test purpose

This commit is contained in:
Lucio Lelii 2022-02-07 09:43:30 +01:00
parent 1855c9e872
commit ddfafd0201
9 changed files with 364 additions and 61 deletions

View File

@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v2.1.0-SNAPSHOT] - [2022-02-04]
added OfflineObserver for test purpose
## [v2.0.3] - [2020-11-03]
removed WARNING log on Vfs.Dir at startup (https://support.d4science.org/issues/18551)

View File

@ -10,7 +10,7 @@
<groupId>org.gcube.core</groupId>
<artifactId>common-smartgears-app</artifactId>
<version>2.0.3</version>
<version>2.1.0-SNAPSHOT</version>
<name>Smartgears Application</name>

View File

@ -1,43 +1,60 @@
package org.gcube.smartgears;
import java.lang.reflect.Method;
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;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.smartgears.annotations.ManagedBy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ApplicationManagerProvider {
public abstract class ApplicationManagerProvider {
private static Logger logger = LoggerFactory.getLogger(ApplicationManagerProvider.class);
static Map<String, Map<String, Future<ApplicationManager>>> appManagerMap = new HashMap<String, Map<String, Future<ApplicationManager>>>();
private static Map<String, Class<?>> proxyClassMap = Collections.synchronizedMap(new HashMap<String, Class<?>>());
private Map<String, Class<?>> proxyClassMap = Collections.synchronizedMap(new HashMap<String, Class<?>>());
private static Map<String, Object> classProxyObjetMap = Collections.synchronizedMap(new HashMap<String, Object>());
private Map<String, Object> classProxyObjetMap = Collections.synchronizedMap(new HashMap<String, Object>());
public static synchronized ApplicationManager get(){
final Class<? extends ApplicationManager> applicationManagerClass = retrieveManagerClass();
return get(applicationManagerClass);
}
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 applicationManagerClass.cast(obj);
return obj;
} else {
obj = _class.newInstance();
classProxyObjetMap.put(_class.getCanonicalName(), obj);
@ -47,24 +64,18 @@ public class ApplicationManagerProvider {
} catch (Exception e) {
throw new RuntimeException("error creating proxy ", e);
}
MethodHandler handler = new MethodHandler() {
@Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
if (ScopeProvider.instance.get()==null) throw new RuntimeException("error invoking application manager method, scope is not set in this thread");
logger.debug("applicationManagerClass is {}",applicationManagerClass.getCanonicalName());
Future<ApplicationManager> appManagerFuture = appManagerMap.get(applicationManagerClass.getCanonicalName()).get(ScopeProvider.instance.get());
logger.debug("appmanager future is null? {}", appManagerFuture==null);
logger.debug("thisMethod is null? {}", thisMethod==null);
return thisMethod.invoke(appManagerFuture.get(), args);
}
};
((ProxyObject)obj).setHandler(handler);
return applicationManagerClass.cast(obj);
((ProxyObject)obj).setHandler(getMethdoHandler(applicationManagerClass));
return obj;
}
private static Class<?> getProxyClass(Class<? extends ApplicationManager> applicationManagerClass){
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());
@ -78,7 +89,7 @@ public class ApplicationManagerProvider {
}
private static Class<? extends ApplicationManager> retrieveManagerClass(){
protected Class<? extends ApplicationManager> retrieveManagerClass(){
String classname = Thread.currentThread().getStackTrace()[3].getClassName();
logger.trace("managed servlet caller is {}",classname);
ManagedBy annotation;
@ -95,4 +106,9 @@ public class ApplicationManagerProvider {
return annotation.value();
}
protected abstract Future<ApplicationManager> retrieveFuture(Class<? extends ApplicationManager> applicationManagerClass);
protected abstract MethodHandler getMethdoHandler(Class<? extends ApplicationManager> applicationManagerClass);
protected abstract AppManagerObserver getObserver();
}

View File

@ -9,7 +9,9 @@ import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.gcube.smartgears.Constants;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.application.manager.AppManagerObserver;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
@ -23,13 +25,12 @@ import org.slf4j.LoggerFactory;
public class ContextListener implements ServletContextListener {
private static Logger log = LoggerFactory.getLogger(ContextListener.class);
RegisterApplicationManagerObserver observer;
AppManagerObserver observer;
@Override
public void contextInitialized(ServletContextEvent sce) {
ApplicationContext context = (ApplicationContext) sce.getServletContext().getAttribute(Constants.context_attribute);
if (context==null) {
@ -39,13 +40,15 @@ public class ContextListener implements ServletContextListener {
log.info("configuring context provider for {}",context.name());
ContextProvider.set(context);
retrieveAndRegisterManagers(context);
}
private void retrieveAndRegisterManagers(ApplicationContext context) {
ApplicationManagerProvider.init(context);
Collection<URL> urls = ClasspathHelper.forClassLoader();
urls.removeIf(url -> url.toString().endsWith(".so") || url.toString().endsWith(".zip") );
@ -62,7 +65,11 @@ public class ContextListener implements ServletContextListener {
managers.add(manageBy.value());
}
if (managers.size()>0){
observer = new RegisterApplicationManagerObserver(managers, context.configuration().startTokens());
observer = ApplicationManagerProvider.instance.getObserver();
observer.setStartingTokens(context.configuration().startTokens());
observer.setApplicationManagerClasses(managers);
observer.register();
context.events().subscribe(observer);
}
}

View File

@ -0,0 +1,25 @@
package org.gcube.smartgears.application.manager;
import java.util.Collection;
import java.util.Set;
import org.gcube.smartgears.ApplicationManager;
import org.gcube.smartgears.context.application.ApplicationContext;
public interface AppManagerObserver {
void onRegistration(String parameter);
void onRemove(String securityToken);
void onStop(ApplicationContext appContext);
void unregister();
void setStartingTokens(Collection<String> startingTokens);
void setApplicationManagerClasses(Set<Class<? extends ApplicationManager>> managersClasses);
public void register();
}

View File

@ -0,0 +1,121 @@
package org.gcube.smartgears.application.manager;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.gcube.common.events.Observes;
import org.gcube.common.events.Observes.Kind;
import org.gcube.smartgears.ApplicationManager;
import org.gcube.smartgears.Constants;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OfflineObserver implements AppManagerObserver {
private static Logger log = LoggerFactory.getLogger(OfflineObserver.class);
private static ExecutorService service = Executors.newCachedThreadPool();
private Set<Class<? extends ApplicationManager>> managerClasses ;
private OfflineProvider provider;
public OfflineObserver(OfflineProvider provider) {
this.provider = provider;
}
public void register() {
this.onRegistration(null);
}
@Override
@Observes(value=Constants.token_registered, kind=Kind.safe)
public synchronized void onRegistration(String parameter){
log.info("offline registration");
for (Class<? extends ApplicationManager> appManager: managerClasses){
Future<ApplicationManager> appManagerFuture = service.submit(new OfflineInitAppManager(appManager));
provider.getAppmanagerMap().put(appManager.getCanonicalName(), appManagerFuture);
}
}
@Override
@Observes(value=Constants.token_removed, kind=Kind.critical)
public synchronized void onRemove(final String securityToken){
}
@Override
public synchronized void onStop(ApplicationContext appContext){
provider.getAppmanagerMap().values().forEach( v -> {
try {
v.get().onShutdown();
} catch (InterruptedException | ExecutionException e) {
log.warn("error shutting down appmanager ");
}
});
unregister();
}
@Override
public void unregister(){
service.shutdownNow();
}
public class OfflineInitAppManager implements Callable<ApplicationManager>{
private Class<? extends ApplicationManager> managerClass;
public OfflineInitAppManager(Class<? extends ApplicationManager> managerClass){
this.managerClass = managerClass;
}
@Override
public ApplicationManager call() throws Exception {
ApplicationManager manager = managerClass.newInstance();
try {
log.info("calling on onInit of {}",manager.getClass().getCanonicalName());
manager.onInit();
} catch (Exception e) {
log.warn("error on onInit of {}",manager.getClass().getCanonicalName(), e);
}
return manager;
}
}
public class OfflineShutDownAppManager implements Runnable{
private Future<ApplicationManager> appManager;
public OfflineShutDownAppManager(Future<ApplicationManager> appManager){
this.appManager = appManager;
}
@Override
public void run() {
try {
log.info("calling on ShutDown of {} ",appManager.getClass().getCanonicalName());
appManager.get().onShutdown();
} catch (Exception e) {
log.warn("error on onShutdown of {} ",appManager.getClass().getCanonicalName(), e);
}
}
}
@Override
public void setStartingTokens(Collection<String> startingTokens) {
}
@Override
public void setApplicationManagerClasses(Set<Class<? extends ApplicationManager>> managerClasses) {
this.managerClasses = managerClasses;
}
}

View File

@ -0,0 +1,56 @@
package org.gcube.smartgears.application.manager;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Future;
import org.gcube.smartgears.ApplicationManager;
import org.gcube.smartgears.ApplicationManagerProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javassist.util.proxy.MethodHandler;
public class OfflineProvider extends ApplicationManagerProvider {
private static Logger logger = LoggerFactory.getLogger(OfflineProvider.class);
private Map<String, Future<ApplicationManager>> appManagerMap = new HashMap<String, Future<ApplicationManager>>();
private OfflineObserver observer = new OfflineObserver(this);
@Override
protected Future<ApplicationManager> retrieveFuture(Class<? extends ApplicationManager> applicationManagerClass) {
return appManagerMap.get(applicationManagerClass.getCanonicalName());
}
@Override
protected MethodHandler getMethdoHandler(Class<? extends ApplicationManager> applicationManagerClass) {
MethodHandler handler = new MethodHandler() {
@Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
logger.debug("applicationManagerClass is {}",applicationManagerClass.getCanonicalName());
Future<ApplicationManager> appManagerFuture = retrieveFuture(applicationManagerClass);
logger.debug("appmanager future is null? {}", appManagerFuture==null);
logger.debug("thisMethod is null? {}", thisMethod==null);
return thisMethod.invoke(appManagerFuture.get(), args);
}
};
return handler;
}
public Map<String, Future<ApplicationManager>> getAppmanagerMap(){
return appManagerMap;
}
@Override
protected AppManagerObserver getObserver() {
return observer;
}
}

View File

@ -1,4 +1,4 @@
package org.gcube.smartgears;
package org.gcube.smartgears.application.manager;
import static org.gcube.common.authorization.client.Constants.authorizationService;
@ -18,50 +18,55 @@ import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.events.Observes;
import org.gcube.common.events.Observes.Kind;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.smartgears.ApplicationManager;
import org.gcube.smartgears.Constants;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RegisterApplicationManagerObserver {
public class OnlineObserver implements AppManagerObserver{
private static Logger log = LoggerFactory.getLogger(RegisterApplicationManagerObserver.class);
private static Logger log = LoggerFactory.getLogger(OnlineObserver.class);
private static ExecutorService service = Executors.newCachedThreadPool();
private Set<Class<? extends ApplicationManager>> managersClass ;
private Map<String, List<Future<ApplicationManager>>> instanciatedManagerPerScope = new HashMap<String, List<Future<ApplicationManager>>>();
public RegisterApplicationManagerObserver(
Set<Class<? extends ApplicationManager>> managersClass, Collection<String> startingTokens) {
super();
this.managersClass = managersClass;
for (String startingToken : startingTokens )
this.onRegistation(startingToken);
private OnlineProvider provider;
private Collection<String> startingTokens;
private Set<Class<? extends ApplicationManager>> managersClasses;
public OnlineObserver(OnlineProvider provider) {
this.provider = provider;
}
public void register() {
for (String startingToken : startingTokens )
this.onRegistration(startingToken);
}
@Observes(value=Constants.token_registered, kind=Kind.safe)
public synchronized void onRegistation(final String securityToken){
public synchronized void onRegistration(final String securityToken){
log.info("token registered called with token {}", securityToken);
List<Future<ApplicationManager>> futureList = new ArrayList<Future<ApplicationManager>>();
try {
final String context = authorizationService().get(securityToken).getContext();
for (Class<? extends ApplicationManager> appManager: managersClass){
for (Class<? extends ApplicationManager> appManager: managersClasses){
Future<ApplicationManager> appManagerFuture = service.submit(new InitAppManager(securityToken, context, appManager));
log.info("intializing app in context {} with token {} ",context, securityToken);
futureList.add(appManagerFuture);
if (ApplicationManagerProvider.appManagerMap.containsKey(appManager.getCanonicalName()))
ApplicationManagerProvider.appManagerMap.get(appManager.getCanonicalName()).put(context, appManagerFuture);
if (provider.getAppmanagerMap().containsKey(appManager.getCanonicalName()))
provider.getAppmanagerMap().get(appManager.getCanonicalName()).put(context, appManagerFuture);
else {
Map<String, Future<ApplicationManager>> tokenFutureMap = new HashMap<String, Future<ApplicationManager>>();
tokenFutureMap.put(context, appManagerFuture);
ApplicationManagerProvider.appManagerMap.put(appManager.getCanonicalName(), tokenFutureMap);
provider.getAppmanagerMap().put(appManager.getCanonicalName(), tokenFutureMap);
}
}
if (!futureList.isEmpty())
@ -83,7 +88,7 @@ public class RegisterApplicationManagerObserver {
for (Future<ApplicationManager> appManager: instanciatedManagerPerScope.get(context)){
service.execute(new ShutDownAppManager(securityToken, context, appManager));
ApplicationManagerProvider.appManagerMap.get(appManager).remove(context);
provider.getAppmanagerMap().get(appManager).remove(context);
}
instanciatedManagerPerScope.remove(context);
@ -192,4 +197,17 @@ public class RegisterApplicationManagerObserver {
}
}
}
@Override
public void setStartingTokens(Collection<String> startingTokens) {
this.startingTokens = startingTokens;
}
@Override
public void setApplicationManagerClasses(Set<Class<? extends ApplicationManager>> managersClasses) {
this.managersClasses = managersClasses;
}
}

View File

@ -0,0 +1,56 @@
package org.gcube.smartgears.application.manager;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Future;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.smartgears.ApplicationManager;
import org.gcube.smartgears.ApplicationManagerProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javassist.util.proxy.MethodHandler;
public class OnlineProvider extends ApplicationManagerProvider {
private static Logger logger = LoggerFactory.getLogger(OnlineProvider.class);
private Map<String, Map<String, Future<ApplicationManager>>> appManagerMap = new HashMap<String, Map<String, Future<ApplicationManager>>>();
private OnlineObserver observer = new OnlineObserver(this);
@Override
protected Future<ApplicationManager> retrieveFuture(Class<? extends ApplicationManager> applicationManagerClass) {
return appManagerMap.get(applicationManagerClass.getCanonicalName()).get(ScopeProvider.instance.get());
}
@Override
protected MethodHandler getMethdoHandler(Class<? extends ApplicationManager> applicationManagerClass) {
MethodHandler handler = new MethodHandler() {
@Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
if (ScopeProvider.instance.get()==null) throw new RuntimeException("error invoking application manager method, scope is not set in this thread");
logger.debug("applicationManagerClass is {}",applicationManagerClass.getCanonicalName());
Future<ApplicationManager> appManagerFuture = retrieveFuture(applicationManagerClass);
logger.debug("appmanager future is null? {}", appManagerFuture==null);
logger.debug("thisMethod is null? {}", thisMethod==null);
return thisMethod.invoke(appManagerFuture.get(), args);
}
};
return handler;
}
public Map<String, Map<String, Future<ApplicationManager>>> getAppmanagerMap(){
return appManagerMap;
}
@Override
protected AppManagerObserver getObserver() {
return observer;
}
}