package org.foo.dosgi.hooks;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.foo.dosgi.helper.LogUtil;
import org.foo.dosgi.helper.PropertyUtil;
import org.foo.dosgi.registry.Registry;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
public class ExportedServiceTracker extends ServiceTracker {
private static final LogUtil log = LogUtil.getLog(ExportedServiceTracker.class.getName());
private final BundleContext ctx;
private final Registry registry;
private final String[] intents;
private final String[] configs;
public ExportedServiceTracker(BundleContext ctx, Registry registry,
String[] intents, String[] configs) {
super(ctx, createFilter(ctx), null);
this.ctx = ctx;
this.registry = registry;
this.intents = intents == null ? new String[0] : intents;
this.configs = configs == null ? new String[0] : configs;
}
private static Filter createFilter(BundleContext ctx) {
try {
return ctx.createFilter("(service.exported.interfaces=*)");
} catch (InvalidSyntaxException e) {
throw new IllegalStateException(e);
}
}
@Override
public Object addingService(ServiceReference ref) {
Object svc = super.addingService(ref);
log.info("Found " + ref);
if (isValidService(ref)) {
String[] ifaces = findExportedInterfaces(ref);
for (String iface : ifaces) {
log.info("Registering " + iface + "->" + svc);
registry.registerService(ref, iface, svc);
}
}
return svc;
}
@Override
public void removedService(ServiceReference ref, Object svc) {
String[] ifaces = findExportedInterfaces(ref);
if (ifaces != null && isValidService(ref)) {
registry.unregisterService(ref);
ctx.ungetService(ref);
}
}
/**
* Find interfaces exported by this service
*
* @param ref
* @return
* @throws ClassNotFoundException
*/
private String[] findExportedInterfaces(ServiceReference ref) {
Object ifaces = ref.getProperty("service.exported.interfaces");
if (ifaces == null) {
return null;
} else {
String[] strs = PropertyUtil.toStringArray(ifaces);
if (strs.length == 1 && "*".equals(strs[0])) {
ifaces = ref.getProperty(Constants.OBJECTCLASS);
strs = PropertyUtil.toStringArray(ifaces);
}
return strs;
}
}
/**
* Checks if reference contains any unsupported intents or references
*
* @param ref
* @return
*/
private boolean isValidService(ServiceReference ref) {
List<String> list = readIntents(ref);
list.removeAll(Arrays.asList(intents));
if (list.isEmpty()) {
list = readConfigs(ref);
list.removeAll(Arrays.asList(configs));
return list.isEmpty();
} else {
return false;
}
}
private List<String> readIntents(ServiceReference ref) {
Object val = ref.getProperty("service.exported.intents");
ArrayList<String> intents = new ArrayList<String>();
if (val != null) {
intents.addAll(Arrays.asList(PropertyUtil.toStringArray(val)));
}
val = ref.getProperty("service.exported.intents.extra");
if (val != null) {
intents.addAll(Arrays.asList(PropertyUtil.toStringArray(val)));
}
return intents;
}
private List<String> readConfigs(ServiceReference ref) {
ArrayList<String> configs = new ArrayList<String>();
Object val = ref.getProperty("service.exported.configs");
if (val != null) {
configs.addAll(Arrays.asList(PropertyUtil.toStringArray(val)));
}
return configs;
}
}