]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - org.argeo.init/src/org/argeo/init/osgi/OsgiRuntimeContext.java
Improve init launch
[lgpl/argeo-commons.git] / org.argeo.init / src / org / argeo / init / osgi / OsgiRuntimeContext.java
index b7079f60e87fa7611bbf936bd3603fd78a52e3d7..2e8c1042ca7d20e21d749fecd7eb418833f9f07b 100644 (file)
@@ -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<String, String> 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<String, String> config) {
+       public OsgiRuntimeContext(ConnectFrameworkFactory frameworkFactory, Map<String, String> 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<FrameworkFactory> sl = ServiceLoader.load(FrameworkFactory.class);
-                       Optional<FrameworkFactory> opt = sl.findFirst();
-                       if (opt.isEmpty())
-                               throw new IllegalStateException("Cannot find OSGi framework");
-                       framework = opt.get().newFramework(config);
+//                     ServiceLoader<FrameworkFactory> sl = ServiceLoader.load(FrameworkFactory.class);
+//                     Optional<FrameworkFactory> 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<ConnectFrameworkFactory> sl = ServiceLoader.load(ConnectFrameworkFactory.class);
+               Optional<ConnectFrameworkFactory> opt = sl.findFirst();
+               if (opt.isEmpty())
+                       throw new IllegalStateException("Cannot find OSGi framework factory");
+               return opt.get();
+       }
+
+       public static ConnectFrameworkFactory getFrameworkFactory(BundleContext bundleContext) {
+               ServiceReference<ConnectFrameworkFactory> sr = bundleContext.getServiceReference(ConnectFrameworkFactory.class);
+               if (sr == null)
+                       return null;
+               return bundleContext.getService(sr);
+       }
 }