package com.isencia.passerelle.starter;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
import java.util.StringTokenizer;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ActorBundleInitializer {
private static final Logger LOGGER = LoggerFactory.getLogger(Activator.class);
private boolean alreadyLoaded;
private BundleContext context;
public ActorBundleInitializer(BundleContext context) {
this.context = context;
}
/**
* Attempts to start the passerelle bundles in a thread safe way.
*/
public synchronized void start() {
if (alreadyLoaded) return;
Stack<Bundle> bundles = parseBundles();
// IMPORTANT Doing this is evil! We spent many days attempting to
// find out why OSGI was broken in the UI product. The start exceptions
// is not printed so dependencies can change which result in the wrong
// thing being started at the wrong time. Resulting in these defects:
// http://jira.diamond.ac.uk/browse/DAWNSCI-858
// http://jira.diamond.ac.uk/browse/DAWNSCI-841
// http://jira.diamond.ac.uk/browse/DAWNSCI-840
// However if this plugin is only started in the workflow config, then
// hopefully this is not an issue, although festering evil may escape one day...
// while there are bundles still to be started...
Bundle bundle = null;
while (!bundles.isEmpty()) {
bundle = bundles.pop();
try {
start(bundle, bundles);
} catch (BundleException e) {
e.printStackTrace();
}
}
alreadyLoaded = true;
}
private Stack<Bundle> parseBundles() {
Stack<Bundle> bundles = new Stack<Bundle>();
//context.addBundleListener(this);
for (Bundle bundle : context.getBundles()) {
if (!(bundle.getSymbolicName().equals("com.isencia.passerelle.workbench"))
&& !(bundle.getSymbolicName().contains("eclipse")
&& !bundle.getSymbolicName().contains("persistence"))
&& !bundle.equals(context.getBundle())) {
if (bundle.getSymbolicName().startsWith("com.isencia")) {
bundles.push(bundle);
continue;
}
// Identify actor plugins and load them
final String buds = bundle.getHeaders().get("Eclipse-RegisterBuddy");
if (buds!=null) {
final String[] buddies = buds.split(",");
// Buddy list for actor plugins
// [com.isencia.passerelle.engine, ptolemy.core, com.isencia.passerelle.actor]
if (buddies!=null) {
List<String> budList = Arrays.asList(buddies);
if (budList.contains("ptolemy.core")) {
bundles.push(bundle);
} else if (budList.contains("com.isencia.passerelle.actor")) {
bundles.push(bundle);
}
}
}
// Identify services and ensure these bundles are also loaded
final String serv = bundle.getHeaders().get("Service-Component");
if (serv!=null && !"".equals(serv)) {
bundles.push(bundle);
}
}
}
return bundles;
}
private void start(Bundle bundle, Stack<Bundle> bundles) throws BundleException {
// first start any required bundles
String requiredBundles = (String) bundle.getHeaders().get("Require-Bundle");
if (requiredBundles != null) {
StringTokenizer tokenizer = new StringTokenizer(requiredBundles, ",");
while (tokenizer.hasMoreTokens()) {
String bundleName = tokenizer.nextToken();
// strip version info
int index = bundleName.indexOf(';');
if (index > 0)
bundleName = bundleName.substring(0, index);
// look for the required bundle in the stack of bundles still to be started
for (int i = 0; i < bundles.size(); i++) {
Bundle requiredBundle = bundles.get(i);
if (requiredBundle.getSymbolicName().equals(bundleName)) {
// remove the required bundle from the stack
bundles.remove(i);
start(requiredBundle, bundles);
break;
}
}
}
}
try {
bundle.start();
LOGGER.debug(bundle.getSymbolicName() + " started.");
} catch (org.osgi.framework.BundleException ignored) {
// Otherwise one gets a read error when starting the workflow run configuration.
}
}
public void stop(BundleContext context) {
//if (context!=null) context.removeBundleListener(this);
}
}