]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - org.argeo.init/src/org/argeo/init/osgi/OsgiRuntimeContext.java
Improve runtime manager
[lgpl/argeo-commons.git] / org.argeo.init / src / org / argeo / init / osgi / OsgiRuntimeContext.java
index 268fb221b3e54796d46cea0775ba2e35bdf62258..3d4b9768c34c33d75e0519a3f2b376b4ed5fe4ee 100644 (file)
@@ -4,22 +4,26 @@ import java.io.Serializable;
 import java.lang.System.Logger;
 import java.lang.System.Logger.Level;
 import java.lang.System.LoggerFinder;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.ServiceLoader;
 import java.util.concurrent.Flow;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 
+import org.argeo.api.init.InitConstants;
 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,18 +32,42 @@ 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 ConnectFrameworkFactory frameworkFactory;
        private Map<String, String> config;
        private Framework framework;
-//     private OsgiBoot osgiBoot;
+
+       // Nested runtimes
+//     private final BundleContext foreignBundleContext;
+       // private final List<String> foreignCategories;
+
+       private final ForeignModuleConnector moduleConnector;
 
        /**
         * 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, config, null, null);
+       }
+
+       /**
+        * Constructor to use when the runtime context will create the OSGi
+        * {@link Framework} and will potentially have a parent runtime.
+        */
+       OsgiRuntimeContext(ConnectFrameworkFactory frameworkFactory, Map<String, String> config,
+                       BundleContext foreignBundleContext, List<String> foreignCategories) {
+               this.frameworkFactory = frameworkFactory;
                this.config = config;
+               if (foreignCategories != null) {
+//             String parentCategories = config.get(InitConstants.PROP_ARGEO_OSGI_PARENT_CATEGORIES);
+//             if (parentCategories != null) {
+//                     Objects.requireNonNull(foreignBundleContext, "Foreign bundle context");
+//                     List<String> foreignCategories = Arrays.asList(parentCategories.trim().split(","));
+//                     foreignCategories.removeIf((s) -> "".equals(s));
+                       this.moduleConnector = new ForeignModuleConnector(foreignBundleContext, foreignCategories);
+               } else {
+                       this.moduleConnector = null;
+               }
        }
 
        /**
@@ -47,6 +75,9 @@ public class OsgiRuntimeContext implements RuntimeContext, AutoCloseable {
         * means.
         */
        OsgiRuntimeContext(BundleContext bundleContext) {
+               this.frameworkFactory = null;
+               // TODO try nesting within Eclipse PDE
+               this.moduleConnector = null;
                start(bundleContext);
        }
 
@@ -56,16 +87,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, moduleConnector);
                }
 
                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);
@@ -97,11 +130,13 @@ public class OsgiRuntimeContext implements RuntimeContext, AutoCloseable {
                OsgiBoot osgiBoot = new OsgiBoot(bundleContext);
                String frameworkUuuid = bundleContext.getProperty(Constants.FRAMEWORK_UUID);
 
+//             osgiBoot.bootstrap();
+
                // separate thread in order to improve logging
                Thread osgiBootThread = new Thread("OSGi boot framework " + frameworkUuuid) {
                        @Override
                        public void run() {
-                               osgiBoot.bootstrap(config);
+                               osgiBoot.bootstrap();
                        }
                };
                osgiBootThread.start();
@@ -190,4 +225,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);
+       }
 }