use osgi-ds for ApplicationPersistenceServices
Change-Id: Ia81c60745b14f04bd53254e8c6814cecd65a1614
diff --git a/distribution/template/cfgs-template/application-manager.config b/distribution/template/cfgs-template/application-manager.config
index b8ae52a..32b2856 100644
--- a/distribution/template/cfgs-template/application-manager.config
+++ b/distribution/template/cfgs-template/application-manager.config
@@ -1,8 +1,6 @@
#the directory that should be read to look for applications
directory=application
-#if the application should be persisted on the disk
-applicationPersist=true
#in miliseconds
-updateFileCheck=2000
+readingDelay=2000
#The extension to be considered as an application
-applicationFileExtension=json
+fileExtention=json
diff --git a/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/api/persistence/ApplicationPersistenceService.java b/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/api/persistence/ApplicationPersistenceService.java
index c76a892..d489160 100644
--- a/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/api/persistence/ApplicationPersistenceService.java
+++ b/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/api/persistence/ApplicationPersistenceService.java
@@ -17,7 +17,7 @@
import java.util.Collection;
-public interface ApplicationPersistenceService extends Runnable {
+public interface ApplicationPersistenceService{
void persist(Application application) throws ApplicationPersistenceException;
void delete(String applicationName) throws ApplicationPersistenceException;
diff --git a/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/application/persistence/SNAPersistApplicationFileSystem.java b/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/application/persistence/FileSystemApplicationPersistenceService.java
similarity index 60%
rename from platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/application/persistence/SNAPersistApplicationFileSystem.java
rename to platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/application/persistence/FileSystemApplicationPersistenceService.java
index 2af659d..c34eae7 100644
--- a/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/application/persistence/SNAPersistApplicationFileSystem.java
+++ b/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/application/persistence/FileSystemApplicationPersistenceService.java
@@ -10,15 +10,6 @@
*/
package org.eclipse.sensinact.gateway.app.manager.application.persistence;
-import org.eclipse.sensinact.gateway.app.api.persistence.ApplicationPersistenceService;
-import org.eclipse.sensinact.gateway.app.api.persistence.dao.Application;
-import org.eclipse.sensinact.gateway.app.api.persistence.exception.ApplicationPersistenceException;
-import org.eclipse.sensinact.gateway.app.api.persistence.listener.ApplicationAvailabilityListener;
-import org.eclipse.sensinact.gateway.app.manager.application.persistence.exception.ApplicationParseException;
-import org.json.JSONObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
@@ -32,26 +23,118 @@
import java.util.Map;
import java.util.Set;
-public class SNAPersistApplicationFileSystem implements ApplicationPersistenceService {
- private final Logger LOG = LoggerFactory.getLogger(SNAPersistApplicationFileSystem.class);
- private final File directoryMonitor;
+import org.eclipse.sensinact.gateway.app.api.persistence.ApplicationPersistenceService;
+import org.eclipse.sensinact.gateway.app.api.persistence.dao.Application;
+import org.eclipse.sensinact.gateway.app.api.persistence.exception.ApplicationPersistenceException;
+import org.eclipse.sensinact.gateway.app.api.persistence.listener.ApplicationAvailabilityListener;
+import org.eclipse.sensinact.gateway.app.manager.application.persistence.exception.ApplicationParseException;
+import org.json.JSONObject;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.ServiceScope;
+import org.osgi.service.component.propertytypes.ServiceRanking;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = ApplicationPersistenceService.class,scope = ServiceScope.SINGLETON)
+@ServiceRanking(100)
+@Designate(ocd = FileSystemApplicationPersistenceService.Config.class)
+public class FileSystemApplicationPersistenceService implements ApplicationPersistenceService {
+ private final Logger LOG = LoggerFactory.getLogger(FileSystemApplicationPersistenceService.class);
+ @ObjectClassDefinition
+ @interface Config {
+ String directory() default "application";
+ long readingDelay() default 0;
+ String fileExtention() default "json";
+ }
+
+ private File directory;
+ private long readingDelay;
+ private String fileExtention;
private final List<String> files = new ArrayList<>();
private final Map<String, Application> filesPath = new HashMap<>();
private final Set<ApplicationAvailabilityListener> listener = new HashSet<ApplicationAvailabilityListener>();
- private final Long readingDelay;
- private final String fileExtention;
private Boolean active = Boolean.TRUE;
+ private Thread persistenceThread;
private static final Object lock = new Object();
- public SNAPersistApplicationFileSystem(File directoryMonitor, Long readingDelay, String fileExtention) {
- this.directoryMonitor = directoryMonitor;
- this.readingDelay = readingDelay;
- this.fileExtention = fileExtention;
- }
+ @Activate
+ public void activate(Config config) {
+ this.directory = new File(config.directory());
+ this.readingDelay = config.readingDelay();
+ this.fileExtention = config.fileExtention();
+
+ persistenceThread = new Thread(() ->{
+
+ notifyServiceAvailable();
+ while (active) {
+ try {
+ //Thread.sleep(readingDelay);
+ synchronized (lock) {
+ List<String> filesToBeProcessed = new ArrayList<>();
+ for (File applicationFile : directory.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.endsWith("." + fileExtention);
+ }
+ })) {
+ filesToBeProcessed.add(applicationFile.getAbsolutePath());
+ }
+ List<String> filesRemoved = new ArrayList<>(files);
+ filesRemoved.removeAll(filesToBeProcessed);
+ //Remove old application files
+ for (String fileRemoved : filesRemoved) {
+ notifyRemoval(fileRemoved);
+ }
+ //Process (new files or already installed) files
+ for (String toprocess : filesToBeProcessed) {
+ try {
+ Boolean fileManaged = filesPath.containsKey(toprocess);
+ if (!fileManaged) { //new file
+ LOG.info("Application file {} will be loaded.", toprocess);
+ notifyInclusion(toprocess);
+ } else {
+ Application applicationManaged = filesPath.get(toprocess);
+ Application applicationInFs = FileToApplicationParser.parse(toprocess);
+ //taken into account modified files
+ if (!applicationManaged.getDiggest().equals(applicationInFs.getDiggest())) {
+ LOG.info("Application file {} was already loaded but its content changed, dispatching update.", toprocess);
+ notifyModification(toprocess);
+ LOG.info("Application file {}, update procedure finished.", toprocess);
+ } else {
+ //Dont do anything, file already taken into account
+ }
+ }
+ } catch (Exception e) {
+ LOG.warn("Failed to process application description file {}", toprocess, e);
+ }
+ }
+ }
+ Thread.sleep(readingDelay);
+ } catch (Exception e) {
+ LOG.error("Application persistency system failed", e);
+ }
+ }
+ notifyServiceUnavailable();
+ LOG.error("Application persistency system is exiting");
+ });
+ persistenceThread.setDaemon(true);
+ persistenceThread.setPriority(Thread.MIN_PRIORITY);
+ persistenceThread.start();
+ }
+ @Deactivate
+ public void deactivate() {
+ if (persistenceThread != null) {
+ persistenceThread.interrupt();
+ }
+ }
@Override
public void persist(Application application) throws ApplicationPersistenceException {
- final String filename = directoryMonitor + File.separator + application.getName() + "." + fileExtention;
+ final String filename = directory + File.separator + application.getName() + "." + fileExtention;
synchronized (lock) {
File file = new File(filename);
try {
@@ -69,7 +152,7 @@
@Override
public void delete(String applicationName) throws ApplicationPersistenceException {
- final String filename = directoryMonitor + File.separator + applicationName + "." + fileExtention;
+ final String filename = directory + File.separator + applicationName + "." + fileExtention;
synchronized (lock) {
File file = new File(filename);
try {
@@ -104,59 +187,7 @@
}
}
- public void run() {
- notifyServiceAvailable();
- while (active) {
- try {
- //Thread.sleep(readingDelay);
- synchronized (lock) {
- List<String> filesToBeProcessed = new ArrayList<>();
- for (File applicationFile : directoryMonitor.listFiles(new FilenameFilter() {
- @Override
- public boolean accept(File dir, String name) {
- return name.endsWith("." + fileExtention);
- }
- })) {
- filesToBeProcessed.add(applicationFile.getAbsolutePath());
- }
- List<String> filesRemoved = new ArrayList<>(files);
- filesRemoved.removeAll(filesToBeProcessed);
- //Remove old application files
- for (String fileRemoved : filesRemoved) {
- notifyRemoval(fileRemoved);
- }
- //Process (new files or already installed) files
- for (String toprocess : filesToBeProcessed) {
- try {
- Boolean fileManaged = filesPath.containsKey(toprocess);
- if (!fileManaged) { //new file
- LOG.info("Application file {} will be loaded.", toprocess);
- notifyInclusion(toprocess);
- } else {
- Application applicationManaged = filesPath.get(toprocess);
- Application applicationInFs = FileToApplicationParser.parse(toprocess);
- //taken into account modified files
- if (!applicationManaged.getDiggest().equals(applicationInFs.getDiggest())) {
- LOG.info("Application file {} was already loaded but its content changed, dispatching update.", toprocess);
- notifyModification(toprocess);
- LOG.info("Application file {}, update procedure finished.", toprocess);
- } else {
- //Dont do anything, file already taken into account
- }
- }
- } catch (Exception e) {
- LOG.warn("Failed to process application description file {}", toprocess, e);
- }
- }
- }
- Thread.sleep(readingDelay);
- } catch (Exception e) {
- LOG.error("Application persistency system failed", e);
- }
- }
- notifyServiceUnavailable();
- LOG.error("Application persistency system is exiting");
- }
+
private void notifyInclusion(String filepath) {
try {
diff --git a/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/application/persistence/SNAPersistApplicationInMemory.java b/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/application/persistence/InMemoryApplicationPersistenceService.java
similarity index 74%
rename from platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/application/persistence/SNAPersistApplicationInMemory.java
rename to platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/application/persistence/InMemoryApplicationPersistenceService.java
index e64c8a0..0850fbe 100644
--- a/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/application/persistence/SNAPersistApplicationInMemory.java
+++ b/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/application/persistence/InMemoryApplicationPersistenceService.java
@@ -15,6 +15,11 @@
import org.eclipse.sensinact.gateway.app.api.persistence.exception.ApplicationPersistenceException;
import org.eclipse.sensinact.gateway.app.api.persistence.listener.ApplicationAvailabilityListener;
import org.json.JSONObject;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ConfigurationPolicy;
+import org.osgi.service.component.annotations.ServiceScope;
+import org.osgi.service.component.propertytypes.ServiceRanking;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -24,13 +29,21 @@
import java.util.List;
import java.util.Set;
-public class SNAPersistApplicationInMemory implements ApplicationPersistenceService {
- private static Logger LOG = LoggerFactory.getLogger(SNAPersistApplicationInMemory.class);
- private List<Application> applicationList = new ArrayList<Application>();
- private final Set<ApplicationAvailabilityListener> listener = new HashSet<ApplicationAvailabilityListener>();
+@Component(service = ApplicationPersistenceService.class,scope = ServiceScope.SINGLETON,configurationPolicy = ConfigurationPolicy.REQUIRE)
+@ServiceRanking(500)
+public class InMemoryApplicationPersistenceService implements ApplicationPersistenceService {
+ private static Logger LOG = LoggerFactory.getLogger(InMemoryApplicationPersistenceService.class);
+ private List<Application> applications = new ArrayList<Application>();
+ private final Set<ApplicationAvailabilityListener> listeners = new HashSet<ApplicationAvailabilityListener>();
- private Application findApplication(String name) {
- for (Application application : applicationList) {
+
+ @Activate
+ public void activate() {
+ notifyServiceAvailable();
+ }
+
+ private Application findApplication(String name) {
+ for (Application application : applications) {
if (application.getName().equals(name)) return application;
}
return null;
@@ -41,11 +54,11 @@
//Not implemented
Application applicationStored = findApplication(application.getName());
if (applicationStored == null) {
- applicationList.add(application);
+ applications.add(application);
notifyInclusion(application);
} else if (!application.getDiggest().equals(applicationStored.getDiggest())) {
- applicationList.remove(applicationStored);
- applicationList.add(application);
+ applications.remove(applicationStored);
+ applications.add(application);
notifyModification(application);
}
}
@@ -53,7 +66,7 @@
@Override
public void delete(String applicationName) throws ApplicationPersistenceException {
notifyRemoval(findApplication(applicationName));
- applicationList.remove(findApplication(applicationName));
+ applications.remove(findApplication(applicationName));
}
@Override
@@ -63,20 +76,20 @@
@Override
public Collection<Application> list() {
- return applicationList;
+ return applications;
}
@Override
public void registerServiceAvailabilityListener(ApplicationAvailabilityListener listenerClient) {
- synchronized (this.listener) {
- this.listener.add(listenerClient);
+ synchronized (this.listeners) {
+ this.listeners.add(listenerClient);
}
}
@Override
public void unregisterServiceAvailabilityListener(ApplicationAvailabilityListener listenerClient) {
- synchronized (this.listener) {
- this.listener.remove(listenerClient);
+ synchronized (this.listeners) {
+ this.listeners.remove(listenerClient);
}
}
@@ -85,7 +98,7 @@
return;
try {
LOG.info("Notifying application '{}' inclusion ", application.getName());
- for (ApplicationAvailabilityListener list : new HashSet<ApplicationAvailabilityListener>(listener)) {
+ for (ApplicationAvailabilityListener list : new HashSet<ApplicationAvailabilityListener>(listeners)) {
try {
synchronized (list) {
list.applicationFound(application.getName(), application.getContent().toString());
@@ -104,7 +117,7 @@
return;
try {
LOG.info("Notifying application '{}' modification ", application.getName());
- for (ApplicationAvailabilityListener list : new HashSet<ApplicationAvailabilityListener>(listener)) {
+ for (ApplicationAvailabilityListener list : new HashSet<ApplicationAvailabilityListener>(listeners)) {
try {
synchronized (list) {
list.applicationChanged(application.getName(), application.getContent().toString());
@@ -123,7 +136,7 @@
return;
try {
LOG.info("Notifying application '{}' removal ", application.getName());
- for (ApplicationAvailabilityListener list : new HashSet<ApplicationAvailabilityListener>(listener)) {
+ for (ApplicationAvailabilityListener list : new HashSet<ApplicationAvailabilityListener>(listeners)) {
try {
synchronized (list) {
list.applicationRemoved(application.getName());
@@ -139,7 +152,7 @@
private void notifyServiceUnavailable() {
LOG.debug("Memory Persistence service is going offline");
- for (ApplicationAvailabilityListener list : new HashSet<ApplicationAvailabilityListener>(listener)) {
+ for (ApplicationAvailabilityListener list : new HashSet<ApplicationAvailabilityListener>(listeners)) {
try {
list.serviceOffline();
} catch (Exception e) {
@@ -150,17 +163,12 @@
private void notifyServiceAvailable() {
LOG.debug("Memory Persistence service is going online");
- for (ApplicationAvailabilityListener list : new HashSet<ApplicationAvailabilityListener>(listener)) {
+ for (ApplicationAvailabilityListener listener : new HashSet<ApplicationAvailabilityListener>(listeners)) {
try {
- list.serviceOnline();
+ listener.serviceOnline();
} catch (Exception e) {
LOG.error("Memory Persistence service is going online", e);
}
}
}
-
- @Override
- public void run() {
- notifyServiceAvailable();
- }
}
diff --git a/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/osgi/ApplicationManagerConfigurator.java b/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/osgi/ApplicationManagerConfigurator.java
index 7f5da1e..590533c 100644
--- a/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/osgi/ApplicationManagerConfigurator.java
+++ b/platform/sensinact-application/application-manager/src/main/java/org/eclipse/sensinact/gateway/app/manager/osgi/ApplicationManagerConfigurator.java
@@ -10,19 +10,13 @@
*/
package org.eclipse.sensinact.gateway.app.manager.osgi;
-import java.io.File;
-import java.util.Map;
-
import org.eclipse.sensinact.gateway.app.api.persistence.ApplicationPersistenceService;
-import org.eclipse.sensinact.gateway.app.manager.application.persistence.SNAPersistApplicationFileSystem;
-import org.eclipse.sensinact.gateway.app.manager.application.persistence.SNAPersistApplicationInMemory;
import org.eclipse.sensinact.gateway.app.manager.internal.AppManagerFactory;
-import org.eclipse.sensinact.gateway.common.annotation.Property;
-import org.eclipse.sensinact.gateway.common.interpolator.Interpolator;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,61 +26,26 @@
@Component(immediate=true)
public class ApplicationManagerConfigurator {
- private static Logger LOG = LoggerFactory.getLogger(ApplicationManagerConfigurator.class);
-
+ private static Logger LOG = LoggerFactory.getLogger(ApplicationManagerConfigurator.class);
private AppManagerFactory appManagerFactory;
- private Thread persistenceThread;
-
- @Property(defaultValue = "application")
- private String directory;
-
- @Property(validationRegex = Property.INTEGER, mandatory=false, defaultValue="0")
- private Long updateFileCheck;
-
- @Property(mandatory = false, defaultValue="false")
- private Boolean applicationPersist;
-
- @Property(defaultValue = "json", validationRegex = Property.ALPHANUMERIC)
- private String applicationFileExtension;
private AppServiceMediator mediator;
- protected void injectPropertyFields() throws Exception {
- LOG.debug("Starting introspection in bundle %s", mediator.getContext().getBundle().getSymbolicName());
- Interpolator interpolator = new Interpolator(this.mediator);
- interpolator.getInstance(this);
- for(Map.Entry<String,String> entry:interpolator.getPropertiesInjected().entrySet()){
- if(!this.mediator.getProperties().containsKey(entry.getKey()))
- mediator.setProperty(entry.getKey(),entry.getValue());
- }
- }
+ @Reference
+ private ApplicationPersistenceService applicationPersistenceService;
@Activate
public void activate(ComponentContext componentContext) throws Exception {
this.mediator = new AppServiceMediator(componentContext.getBundleContext());
- injectPropertyFields();
-
- ApplicationPersistenceService directoryMonitor = null;
- if (applicationPersist) {
- LOG.info("Filesystem Persistence mechanism is ON");
- directoryMonitor = new SNAPersistApplicationFileSystem(new File(directory), updateFileCheck, applicationFileExtension);
- ;
- } else {
- LOG.info("Filesystem Persistence mechanism is OFF");
- directoryMonitor = new SNAPersistApplicationInMemory();
- }
- this.appManagerFactory = new AppManagerFactory(mediator, directoryMonitor);
- directoryMonitor.registerServiceAvailabilityListener(appManagerFactory);
- persistenceThread = new Thread(directoryMonitor);
- persistenceThread.setDaemon(true);
- persistenceThread.setPriority(Thread.MIN_PRIORITY);
- persistenceThread.start();
+
+ this.appManagerFactory = new AppManagerFactory(mediator, applicationPersistenceService);
+ applicationPersistenceService.registerServiceAvailabilityListener(appManagerFactory);
}
@Deactivate
public void deactivate() throws Exception {
- if (persistenceThread != null) persistenceThread.interrupt();
+
this.appManagerFactory.deleteAppManager();
}
}