diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0f99c22..8f9b6d9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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)
diff --git a/pom.xml b/pom.xml
index e043aaf..9fbb391 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
org.gcube.core
common-smartgears-app
- 2.0.3
+ 2.1.0-SNAPSHOT
Smartgears Application
diff --git a/src/main/java/org/gcube/smartgears/ApplicationManagerProvider.java b/src/main/java/org/gcube/smartgears/ApplicationManagerProvider.java
index a3af77a..6877106 100644
--- a/src/main/java/org/gcube/smartgears/ApplicationManagerProvider.java
+++ b/src/main/java/org/gcube/smartgears/ApplicationManagerProvider.java
@@ -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>> appManagerMap = new HashMap>>();
-
- private static Map> proxyClassMap = Collections.synchronizedMap(new HashMap>());
+ private Map> proxyClassMap = Collections.synchronizedMap(new HashMap>());
- private static Map classProxyObjetMap = Collections.synchronizedMap(new HashMap());
+ private Map classProxyObjetMap = Collections.synchronizedMap(new HashMap());
- 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 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 retrieveFuture(Class extends ApplicationManager> applicationManagerClass);
+ protected abstract MethodHandler getMethdoHandler(Class extends ApplicationManager> applicationManagerClass);
+ protected abstract AppManagerObserver getObserver();
+
}
diff --git a/src/main/java/org/gcube/smartgears/ContextListener.java b/src/main/java/org/gcube/smartgears/ContextListener.java
index ad5430f..343f66c 100644
--- a/src/main/java/org/gcube/smartgears/ContextListener.java
+++ b/src/main/java/org/gcube/smartgears/ContextListener.java
@@ -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 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);
}
}
diff --git a/src/main/java/org/gcube/smartgears/application/manager/AppManagerObserver.java b/src/main/java/org/gcube/smartgears/application/manager/AppManagerObserver.java
new file mode 100644
index 0000000..13c1844
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/application/manager/AppManagerObserver.java
@@ -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 startingTokens);
+
+ void setApplicationManagerClasses(Set> managersClasses);
+
+ public void register();
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/smartgears/application/manager/OfflineObserver.java b/src/main/java/org/gcube/smartgears/application/manager/OfflineObserver.java
new file mode 100644
index 0000000..bd65043
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/application/manager/OfflineObserver.java
@@ -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> 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 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{
+
+ 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 appManager;
+
+ public OfflineShutDownAppManager(Future 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 startingTokens) {
+ }
+
+ @Override
+ public void setApplicationManagerClasses(Set> managerClasses) {
+ this.managerClasses = managerClasses;
+ }
+}
+
diff --git a/src/main/java/org/gcube/smartgears/application/manager/OfflineProvider.java b/src/main/java/org/gcube/smartgears/application/manager/OfflineProvider.java
new file mode 100644
index 0000000..49f915f
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/application/manager/OfflineProvider.java
@@ -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> appManagerMap = new HashMap>();
+
+ private OfflineObserver observer = new OfflineObserver(this);
+
+
+ @Override
+ protected Future 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 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> getAppmanagerMap(){
+ return appManagerMap;
+ }
+
+ @Override
+ protected AppManagerObserver getObserver() {
+ return observer;
+ }
+
+}
+
+
+
diff --git a/src/main/java/org/gcube/smartgears/RegisterApplicationManagerObserver.java b/src/main/java/org/gcube/smartgears/application/manager/OnlineObserver.java
similarity index 83%
rename from src/main/java/org/gcube/smartgears/RegisterApplicationManagerObserver.java
rename to src/main/java/org/gcube/smartgears/application/manager/OnlineObserver.java
index 3c133df..7463379 100644
--- a/src/main/java/org/gcube/smartgears/RegisterApplicationManagerObserver.java
+++ b/src/main/java/org/gcube/smartgears/application/manager/OnlineObserver.java
@@ -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> managersClass ;
-
private Map>> instanciatedManagerPerScope = new HashMap>>();
- public RegisterApplicationManagerObserver(
- Set> managersClass, Collection startingTokens) {
- super();
- this.managersClass = managersClass;
- for (String startingToken : startingTokens )
- this.onRegistation(startingToken);
-
+ private OnlineProvider provider;
+
+ private Collection startingTokens;
+
+ private Set> 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> futureList = new ArrayList>();
try {
final String context = authorizationService().get(securityToken).getContext();
-
- for (Class extends ApplicationManager> appManager: managersClass){
+ for (Class extends ApplicationManager> appManager: managersClasses){
Future 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> tokenFutureMap = new HashMap>();
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 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 startingTokens) {
+ this.startingTokens = startingTokens;
+
+ }
+
+ @Override
+ public void setApplicationManagerClasses(Set> managersClasses) {
+ this.managersClasses = managersClasses;
+ }
+
+
}
diff --git a/src/main/java/org/gcube/smartgears/application/manager/OnlineProvider.java b/src/main/java/org/gcube/smartgears/application/manager/OnlineProvider.java
new file mode 100644
index 0000000..91f034b
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/application/manager/OnlineProvider.java
@@ -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>> appManagerMap = new HashMap>>();
+
+ private OnlineObserver observer = new OnlineObserver(this);
+
+ @Override
+ protected Future 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 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>> getAppmanagerMap(){
+ return appManagerMap;
+ }
+
+ @Override
+ protected AppManagerObserver getObserver() {
+ return observer;
+ }
+
+}