add mongo property store in file storage bundle

This commit is contained in:
Fredrik Teschke
2015-01-27 16:51:31 +01:00
parent 138ca735e5
commit 336a96a18f
8 changed files with 237 additions and 60 deletions
@@ -9,11 +9,14 @@ Export-Package: com.sap.sse.filestorage,
com.sap.sse.filestorage.impl,
com.sap.sse.filestorage.testsupport
Import-Package: com.sap.sse.osgi,
org.osgi.framework;version="1.8.0"
org.osgi.framework;version="1.8.0",
org.osgi.util.tracker;version="1.5.1"
Bundle-Activator: com.sap.sse.filestorage.impl.Activator
Require-Bundle: org.apache.servicemix.bundles.aws-java-sdk;bundle-version="1.9.8",
com.fasterxml.jackson.core.jackson-databind,
com.fasterxml.jackson.core.jackson-core,
com.fasterxml.jackson.core.jackson-annotations,
org.apache.commons.logging;bundle-version="1.1.3",
com.sap.sse.common
com.sap.sse.common,
com.sap.sse.mongodb;bundle-version="1.0.0",
com.mongodb.driver;bundle-version="2.6.2"
@@ -0,0 +1,17 @@
package com.sap.sse.filestorage;
import java.util.Map;
/**
* Store that can save property values of {@link FileStorageService}s.
*
* TODO mongo store, register it, change startup level of filestorage bundle, replication
*
* @author Fredrik Teschke
*
*/
public interface FileStorageServicePropertyStore {
Map<String, String> readAllProperties(String serviceName);
void writeProperty(String serviceName, String propertyName, String propertyValue);
}
@@ -5,31 +5,44 @@ import java.util.Hashtable;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import com.sap.sse.common.TypeBasedServiceFinder;
import com.sap.sse.filestorage.FileStorageManagementService;
import com.sap.sse.filestorage.FileStorageService;
import com.sap.sse.filestorage.FileStorageServicePropertyStore;
import com.sap.sse.mongodb.MongoDBConfiguration;
public class Activator implements BundleActivator {
private ServiceTracker<FileStorageService, FileStorageService> tracker;
@Override
public void start(BundleContext context) throws Exception {
MongoDBConfiguration dbConfig = MongoDBConfiguration.getDefaultConfiguration();
dbConfig.getService().registerExclusively(MongoFileStorageServicePropertyStoreImpl.class,
MongoFileStorageServicePropertyStoreImpl.COLLECTION_NAME);
FileStorageServicePropertyStore propertyStore = new MongoFileStorageServicePropertyStoreImpl(
dbConfig.getService());
Dictionary<String, String> dict = new Hashtable<>();
dict.put(TypeBasedServiceFinder.TYPE, AmazonS3FileStorageServiceImpl.NAME);
context.registerService(FileStorageService.class, new AmazonS3FileStorageServiceImpl(), dict);
TransientFileStorageManagementServiceImpl mgmtService = new TransientFileStorageManagementServiceImpl();
context.registerService(FileStorageManagementService.class, mgmtService,
null);
mgmtService.setContext(context);
FileStorageManagementServiceImpl mgmtService = new FileStorageManagementServiceImpl(context, propertyStore);
context.registerService(FileStorageManagementService.class, mgmtService, null);
//TODO load service properties from DB on startup
// track all FileStorageServices, so that their properties can be set from the database when added to the OSGi
// registry
tracker = new ServiceTracker<>(context, FileStorageService.class, mgmtService);
tracker.open();
}
@Override
public void stop(BundleContext context) throws Exception {
if (tracker != null) {
tracker.close();
}
}
}
@@ -0,0 +1,98 @@
package com.sap.sse.filestorage.impl;
import java.util.Map.Entry;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
import com.sap.sse.common.TypeBasedServiceFinder;
import com.sap.sse.filestorage.FileStorageManagementService;
import com.sap.sse.filestorage.FileStorageService;
import com.sap.sse.filestorage.FileStorageServicePropertyStore;
import com.sap.sse.osgi.CachedOsgiTypeBasedServiceFinderFactory;
/**
* Implements {@link ServiceTrackerCustomizer} so that all {@link FileStorageServices} announced in the
* registry can receive their stored properties.
*
* @author Fredrik Teschke
*
*/
public class FileStorageManagementServiceImpl implements FileStorageManagementService,
ServiceTrackerCustomizer<FileStorageService, FileStorageService> {
private FileStorageService active;
private final TypeBasedServiceFinder<FileStorageService> serviceFinder;
private final FileStorageServicePropertyStore propertyStore;
private final BundleContext context;
public FileStorageManagementServiceImpl(BundleContext context, FileStorageServicePropertyStore propertyStore) {
this.context = context;
serviceFinder = new CachedOsgiTypeBasedServiceFinderFactory(context)
.createServiceFinder(FileStorageService.class);
this.propertyStore = propertyStore;
context.addServiceListener(new ServiceListener() {
@Override
public void serviceChanged(ServiceEvent event) {
// TODO Auto-generated method stub
}
});
}
@Override
public FileStorageService getActiveFileStorageService() {
if (active == null) {
throw new NoCorrespondingServiceRegisteredException();
}
return active;
}
@Override
public void setActiveFileStorageService(FileStorageService service) {
active = service;
}
@Override
public FileStorageService[] getAvailableFileStorageServices() {
return serviceFinder.findAllServices().toArray(new FileStorageService[0]);
}
@Override
public FileStorageService getFileStorageService(String name) {
return serviceFinder.findService(name);
}
@Override
public void setFileStorageServiceProperty(String serviceName, String propertyName, String propertyValue)
throws NoCorrespondingServiceRegisteredException, IllegalArgumentException {
//TODO replicate
propertyStore.writeProperty(serviceName, propertyName, propertyValue);
serviceFinder.findService(serviceName).setProperty(propertyName, propertyValue);
}
@Override
public FileStorageService addingService(ServiceReference<FileStorageService> reference) {
FileStorageService service = context.getService(reference);
for (Entry<String, String> property : propertyStore.readAllProperties(service.getName()).entrySet()) {
service.setProperty(property.getKey(), property.getValue());
}
return service;
}
@Override
public void modifiedService(ServiceReference<FileStorageService> reference, FileStorageService service) {
//ignore
}
@Override
public void removedService(ServiceReference<FileStorageService> reference, FileStorageService service) {
//ignore
}
}
@@ -0,0 +1,51 @@
package com.sap.sse.filestorage.impl;
import java.util.HashMap;
import java.util.Map;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.sap.sse.filestorage.FileStorageServicePropertyStore;
import com.sap.sse.mongodb.MongoDBService;
public class MongoFileStorageServicePropertyStoreImpl implements FileStorageServicePropertyStore {
public static final String COLLECTION_NAME = "FileStorageServiceProperties";
private final DBCollection collection;
private static enum FieldNames {
SERVICE_NAME, PROPERTY_NAME, PROPERTY_VALUE;
}
public MongoFileStorageServicePropertyStoreImpl(MongoDBService dbService) {
collection = dbService.getDB().getCollection(COLLECTION_NAME);
DBObject index = new BasicDBObjectBuilder().add(FieldNames.SERVICE_NAME.name(), true)
.add(FieldNames.PROPERTY_NAME.name(), true).get();
collection.ensureIndex(index);
}
@Override
public Map<String, String> readAllProperties(String serviceName) {
DBObject query = new BasicDBObject(FieldNames.SERVICE_NAME.name(), serviceName);
DBCursor cursor = collection.find(query);
Map<String, String> properties = new HashMap<>();
for (DBObject property : cursor) {
String name = (String) property.get(FieldNames.PROPERTY_NAME.name());
String value = (String) property.get(FieldNames.PROPERTY_VALUE.name());
properties.put(name, value);
}
return properties;
}
@Override
public void writeProperty(String serviceName, String propertyName, String propertyValue) {
DBObject obj = new BasicDBObjectBuilder().add(FieldNames.SERVICE_NAME.name(), serviceName)
.add(FieldNames.PROPERTY_NAME.name(), propertyName)
.add(FieldNames.PROPERTY_VALUE.name(), propertyValue).get();
collection.insert(obj);
}
}
@@ -1,50 +0,0 @@
package com.sap.sse.filestorage.impl;
import org.osgi.framework.BundleContext;
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
import com.sap.sse.common.TypeBasedServiceFinder;
import com.sap.sse.filestorage.FileStorageManagementService;
import com.sap.sse.filestorage.FileStorageService;
import com.sap.sse.osgi.CachedOsgiTypeBasedServiceFinderFactory;
public class TransientFileStorageManagementServiceImpl implements FileStorageManagementService {
private FileStorageService active;
private TypeBasedServiceFinder<FileStorageService> serviceFinder;
public void setContext(BundleContext context) {
serviceFinder = new CachedOsgiTypeBasedServiceFinderFactory(context)
.createServiceFinder(FileStorageService.class);
}
@Override
public FileStorageService getActiveFileStorageService() {
if (active == null) {
throw new NoCorrespondingServiceRegisteredException();
}
return active;
}
@Override
public void setActiveFileStorageService(FileStorageService service) {
active = service;
}
@Override
public FileStorageService[] getAvailableFileStorageServices() {
return serviceFinder.findAllServices().toArray(new FileStorageService[0]);
}
@Override
public FileStorageService getFileStorageService(String name) {
return serviceFinder.findService(name);
}
@Override
public void setFileStorageServiceProperty(String serviceName, String propertyName, String propertyValue)
throws NoCorrespondingServiceRegisteredException, IllegalArgumentException {
//TODO mgmt service that persists properties on master
serviceFinder.findService(serviceName).setProperty(propertyName, propertyValue);
}
}