it.uniroma2.art.coda.osgi.bundle.OSGiAwareAbstractComponentProvider Maven / Gradle / Ivy
package it.uniroma2.art.coda.osgi.bundle;
import it.uniroma2.art.coda.provisioning.ComponentProvider;
import it.uniroma2.art.coda.provisioning.ComponentProvisioningException;
import it.uniroma2.art.owlart.filter.StatementWithAnyOfGivenComponents_Predicate;
import it.uniroma2.art.owlart.model.ARTNode;
import it.uniroma2.art.owlart.model.ARTStatement;
import it.uniroma2.art.owlart.model.ARTURIResource;
import it.uniroma2.art.owlart.model.NodeFilters;
import it.uniroma2.art.owlart.models.LinkedDataResolver;
import it.uniroma2.art.owlart.models.OWLArtModelFactory;
import it.uniroma2.art.owlart.navigation.ARTNodeIterator;
import it.uniroma2.art.owlart.sesame2impl.factory.ARTModelFactorySesame2Impl;
import it.uniroma2.art.owlart.sesame2impl.models.conf.Sesame2ModelConfiguration;
import it.uniroma2.art.owlart.utilities.RDFIterators;
import it.uniroma2.art.owlart.vocabulary.VocabUtilities;
import java.io.File;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.felix.bundlerepository.RepositoryAdmin;
import org.apache.felix.bundlerepository.Requirement;
import org.apache.felix.bundlerepository.Resolver;
import org.apache.felix.bundlerepository.Resource;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Collections2;
public abstract class OSGiAwareAbstractComponentProvider implements ComponentProvider {
private static final Logger logger = LoggerFactory.getLogger(ComponentProvider.class);
private BundleContext hostBundleContext;
private Map serviceReferencesMap;
private Map serviceObjectsMap;
//private File tempDir;
private ServiceTracker convertersTracker;
public OSGiAwareAbstractComponentProvider(BundleContext hostBundleContext) throws Exception {
this.hostBundleContext = hostBundleContext;
//this.tempDir = tempDir;
this.serviceReferencesMap = new HashMap();
this.serviceObjectsMap = new HashMap();
this.convertersTracker = new ServiceTracker(hostBundleContext,
hostBundleContext.createFilter("(it.uniroma2.art.coda.contract=*)"), null);
this.convertersTracker.open();
}
@Override
public void close() {
this.convertersTracker.close();
// for (ServiceReference sr : serviceReferencesMap.values()) {
// this.hostBundleContext.ungetService(sr);
// }
}
@Override
public Object lookup(String contract) throws ComponentProvisioningException {
// Uses an already provisioned converter, if any
Object service = serviceObjectsMap.get(contract);
if (service != null) {
return service;
}
// Looks-up the service registry for a suitable converter, if any
service = lookupServiceRegistry(contract);
if (service != null) {
return service;
}
// Attempts to locate a suitable bundle in the known OBR repositories
RepositoryAdmin repoAdmin = getRepositoryAdmin();
Requirement req = repoAdmin.getHelper().requirement("service",
String.format("(it.uniroma2.art.coda.contract=%s)", contract));
Resource[] candidateResources = repoAdmin.discoverResources(new Requirement[] { req });
// If no candidate is found, attempts to discover a new OBR repository
if (candidateResources.length == 0) {
try {
discover(contract);
} catch (Exception e) {
throw new ComponentProvisioningException(e);
}
candidateResources = repoAdmin.discoverResources(new Requirement[] { req });
if (candidateResources.length == 0) {
throw new ComponentProvisioningException(
"No converter has been found that matches the contract: " + contract);
}
}
// Always choose the first candidate
int chosen = 0;
Resource chosenResource = candidateResources[0];
Resolver resolver = repoAdmin.resolver();
resolver.add(chosenResource);
boolean success = resolver.resolve();
if (!success) {
throw new ComponentProvisioningException("Cannot resolve the bundle: " + chosenResource
+ " providing a converter for contract: " + contract);
}
resolver.deploy(Resolver.START);
logger.info("deploying: " + chosenResource);
for (int i = 0; i < 5; i++) {
service = lookupServiceRegistry(contract);
if (service != null) {
return service;
}
try {
Thread.sleep((i + 1) * 500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
throw new ComponentProvisioningException("Cannot get the service");
}
private Object lookupServiceRegistry(String contract) {
for (ServiceReference sr : atLeastEmpty(ServiceReference.class,
convertersTracker.getServiceReferences())) {
if (contract.equals(sr.getProperty("it.uniroma2.art.coda.contract"))) {
return convertersTracker.getService(sr);
}
}
return null;
}
private static T[] atLeastEmpty(Class clazz, T[] array) {
if (array == null) {
return (T[]) Array.newInstance(clazz, 0);
}
return array;
}
private void discover(String contract) throws Exception {
logger.info("discover({})", contract);
ARTModelFactorySesame2Impl factImpl = new ARTModelFactorySesame2Impl();
OWLArtModelFactory fact = OWLArtModelFactory.createModelFactory(factImpl);
LinkedDataResolver ldResolver = fact.loadLinkedDataResolver();
ARTURIResource contractResource = VocabUtilities.nodeFactory.createURIResource(contract);
Collection contractDescription;
try {
contractDescription = ldResolver.lookup(contractResource);
} catch (Exception e) {
logger.debug("Linked data resolver throwed an exception", e);
return;
}
ARTNodeIterator authoritativeRepoIt = RDFIterators.listObjects(RDFIterators.createARTStatementIterator(Collections2.filter(contractDescription, StatementWithAnyOfGivenComponents_Predicate.getFilter(
contractResource, VocabUtilities.nodeFactory
.createURIResource("http://art.uniroma2.it/coda/ns/authoritativeOBR"),
NodeFilters.ANY)).iterator()));
RepositoryAdmin repoAdmin = getRepositoryAdmin();
while (authoritativeRepoIt.streamOpen()) {
ARTNode authRepo = authoritativeRepoIt.getNext();
if (authRepo.isURIResource()) {
repoAdmin.addRepository(authRepo.asURIResource().getURI());
logger.info("adding repository: " + authRepo.asURIResource().getURI());
}
}
authoritativeRepoIt.close();
}
protected abstract RepositoryAdmin getRepositoryAdmin() throws ComponentProvisioningException;
}