X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.init%2Fsrc%2Forg%2Fargeo%2Finit%2Fosgi%2FOsgiRuntimeContext.java;h=2e8c1042ca7d20e21d749fecd7eb418833f9f07b;hb=faeeb8f0ba92b640942d88782ca6f5cfc332597e;hp=b7079f60e87fa7611bbf936bd3603fd78a52e3d7;hpb=6bfcb81dd21d8fdd9094610c00f5f8ad9c6a36a7;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.init/src/org/argeo/init/osgi/OsgiRuntimeContext.java b/org.argeo.init/src/org/argeo/init/osgi/OsgiRuntimeContext.java index b7079f60e..2e8c1042c 100644 --- a/org.argeo.init/src/org/argeo/init/osgi/OsgiRuntimeContext.java +++ b/org.argeo.init/src/org/argeo/init/osgi/OsgiRuntimeContext.java @@ -14,12 +14,12 @@ import java.util.function.Consumer; import java.util.function.Supplier; import org.argeo.api.init.RuntimeContext; -import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.connect.ConnectFrameworkFactory; import org.osgi.framework.launch.Framework; -import org.osgi.framework.launch.FrameworkFactory; /** An OSGi runtime context. */ public class OsgiRuntimeContext implements RuntimeContext, AutoCloseable { @@ -28,8 +28,9 @@ public class OsgiRuntimeContext implements RuntimeContext, AutoCloseable { private final static long STOP_FOR_UPDATE_TIMEOUT = 60 * 1000; private final static long CLOSE_TIMEOUT = 60 * 1000; - private final static String SYMBOLIC_NAME_FELIX_SCR = "org.apache.felix.scr"; + // private final static String SYMBOLIC_NAME_FELIX_SCR = "org.apache.felix.scr"; + private ConnectFrameworkFactory frameworkFactory; private Map config; private Framework framework; // private OsgiBoot osgiBoot; @@ -38,7 +39,8 @@ public class OsgiRuntimeContext implements RuntimeContext, AutoCloseable { * Constructor to use when the runtime context will create the OSGi * {@link Framework}. */ - public OsgiRuntimeContext(Map config) { + public OsgiRuntimeContext(ConnectFrameworkFactory frameworkFactory, Map config) { + this.frameworkFactory = frameworkFactory; this.config = config; } @@ -56,16 +58,18 @@ public class OsgiRuntimeContext implements RuntimeContext, AutoCloseable { throw new IllegalStateException("OSGi framework is already started"); if (framework == null) { - ServiceLoader sl = ServiceLoader.load(FrameworkFactory.class); - Optional opt = sl.findFirst(); - if (opt.isEmpty()) - throw new IllegalStateException("Cannot find OSGi framework"); - framework = opt.get().newFramework(config); +// ServiceLoader sl = ServiceLoader.load(FrameworkFactory.class); +// Optional opt = sl.findFirst(); +// if (opt.isEmpty()) +// throw new IllegalStateException("Cannot find OSGi framework"); +// framework = opt.get().newFramework(config); + framework = frameworkFactory.newFramework(config, null); } try { framework.start(); BundleContext bundleContext = framework.getBundleContext(); + bundleContext.registerService(ConnectFrameworkFactory.class, frameworkFactory, null); start(bundleContext); } catch (BundleException e) { throw new IllegalStateException("Cannot start OSGi framework", e); @@ -95,7 +99,22 @@ public class OsgiRuntimeContext implements RuntimeContext, AutoCloseable { new Hashtable<>(Collections.singletonMap(Constants.SERVICE_PID, "argeo.logging.publisher"))); } OsgiBoot osgiBoot = new OsgiBoot(bundleContext); - osgiBoot.bootstrap(config); + String frameworkUuuid = bundleContext.getProperty(Constants.FRAMEWORK_UUID); + + // separate thread in order to improve logging + Thread osgiBootThread = new Thread("OSGi boot framework " + frameworkUuuid) { + @Override + public void run() { + osgiBoot.bootstrap(); + } + }; + osgiBootThread.start(); + // TODO return a completable stage so that inits can run in parallel +// try { +// osgiBootThread.join(60 * 1000); +// } catch (InterruptedException e) { +// // silent +// } } public void update() { @@ -151,28 +170,19 @@ public class OsgiRuntimeContext implements RuntimeContext, AutoCloseable { public void close() throws Exception { if (framework == null) return; -// Bundle scrBundle = osgiBoot.getBundlesBySymbolicName().get(); -// if (scrBundle != null && scrBundle.getState() > Bundle.RESOLVED) { -// scrBundle.stop(); -// while (!(scrBundle.getState() <= Bundle.RESOLVED)) { -// Thread.sleep(500); + // TODO make shutdown of dynamic service more robust +// for (Bundle scrBundle : framework.getBundleContext().getBundles()) { +// if (scrBundle.getSymbolicName().equals(SYMBOLIC_NAME_FELIX_SCR)) { +// if (scrBundle.getState() > Bundle.RESOLVED) { +// scrBundle.stop(); +// while (!(scrBundle.getState() <= Bundle.RESOLVED)) { +// Thread.sleep(100); +// } +// Thread.sleep(500); +// } // } -// Thread.sleep(1000); // } - // TODO make shutdown of dynamic service more robust - for (Bundle scrBundle : framework.getBundleContext().getBundles()) { - if (scrBundle.getSymbolicName().equals(SYMBOLIC_NAME_FELIX_SCR)) { - if (scrBundle.getState() > Bundle.RESOLVED) { - scrBundle.stop(); - while (!(scrBundle.getState() <= Bundle.RESOLVED)) { - Thread.sleep(100); - } - Thread.sleep(100); - } - } - } - stop(); waitForStop(CLOSE_TIMEOUT); framework = null; @@ -184,4 +194,23 @@ public class OsgiRuntimeContext implements RuntimeContext, AutoCloseable { return framework; } + /** + * Load {@link ConnectFrameworkFactory} from Java service loader. This will not + * work within a pure OSGi runtime, so the reference should be passed to child + * runtimes as an OSGi service. + */ + public static ConnectFrameworkFactory loadFrameworkFactory() { + ServiceLoader sl = ServiceLoader.load(ConnectFrameworkFactory.class); + Optional opt = sl.findFirst(); + if (opt.isEmpty()) + throw new IllegalStateException("Cannot find OSGi framework factory"); + return opt.get(); + } + + public static ConnectFrameworkFactory getFrameworkFactory(BundleContext bundleContext) { + ServiceReference sr = bundleContext.getServiceReference(ConnectFrameworkFactory.class); + if (sr == null) + return null; + return bundleContext.getService(sr); + } }