Refactor Argeo init
[lgpl/argeo-commons.git] / org.argeo.init / src / org / argeo / init / osgi / OsgiRuntimeContext.java
index 7f44f6b2746dccc914312180b493d56e7328ce3c..c35046b20aec4f0576f272a6e1b4bd11a013418f 100644 (file)
@@ -1,5 +1,7 @@
 package org.argeo.init.osgi;
 
+import java.io.Serializable;
+import java.lang.System.LoggerFinder;
 import java.util.Collections;
 import java.util.Hashtable;
 import java.util.Map;
@@ -8,32 +10,35 @@ 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.init.RuntimeContext;
-import org.argeo.init.logging.ThinLoggerFinder;
+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.ServiceRegistration;
 import org.osgi.framework.launch.Framework;
 import org.osgi.framework.launch.FrameworkFactory;
 
 /** An OSGi runtime context. */
-public class OsgiRuntimeContext implements RuntimeContext {
+public class OsgiRuntimeContext implements RuntimeContext, AutoCloseable {
        private Map<String, String> config;
        private Framework framework;
        private OsgiBoot osgiBoot;
 
-       @SuppressWarnings("rawtypes")
-       private ServiceRegistration<Consumer> loggingConfigurationSr;
-       @SuppressWarnings("rawtypes")
-       private ServiceRegistration<Flow.Publisher> logEntryPublisherSr;
-
+       /**
+        * Constructor to use when the runtime context will create the OSGi
+        * {@link Framework}.
+        */
        public OsgiRuntimeContext(Map<String, String> config) {
                this.config = config;
        }
 
-       public OsgiRuntimeContext(BundleContext bundleContext) {
+       /**
+        * Constructor to use when the OSGi {@link Framework} has been created by other
+        * means.
+        */
+       OsgiRuntimeContext(BundleContext bundleContext) {
                start(bundleContext);
        }
 
@@ -54,16 +59,29 @@ public class OsgiRuntimeContext implements RuntimeContext {
        }
 
        public void start(BundleContext bundleContext) {
-               // logging
-               loggingConfigurationSr = bundleContext.registerService(Consumer.class,
-                               ThinLoggerFinder.getConfigurationConsumer(),
-                               new Hashtable<>(Collections.singletonMap(Constants.SERVICE_PID, "argeo.logging.configuration")));
-               logEntryPublisherSr = bundleContext.registerService(Flow.Publisher.class,
-                               ThinLoggerFinder.getLogEntryPublisher(),
-                               new Hashtable<>(Collections.singletonMap(Constants.SERVICE_PID, "argeo.logging.publisher")));
-
+               // preferences
+//             SystemRootPreferences systemRootPreferences = ThinPreferencesFactory.getInstance().getSystemRootPreferences();
+//             bundleContext.registerService(AbstractPreferences.class, systemRootPreferences, new Hashtable<>());
+
+               // Make sure LoggerFinder has been searched for, since it is lazily loaded
+               LoggerFinder loggerFinder = LoggerFinder.getLoggerFinder();
+
+               if (loggerFinder instanceof Consumer<?> && loggerFinder instanceof Supplier<?>) {
+                       @SuppressWarnings("unchecked")
+                       Consumer<Map<String, Object>> consumer = (Consumer<Map<String, Object>>) loggerFinder;
+                       // ThinLoggerFinder.getConfigurationConsumer()
+                       // ThinLoggerFinder.getLogEntryPublisher()
+
+                       @SuppressWarnings("unchecked")
+                       Supplier<Flow.Publisher<Map<String, Serializable>>> supplier = (Supplier<Flow.Publisher<Map<String, Serializable>>>) loggerFinder;
+                       // logging
+                       bundleContext.registerService(Consumer.class, consumer,
+                                       new Hashtable<>(Collections.singletonMap(Constants.SERVICE_PID, "argeo.logging.configuration")));
+                       bundleContext.registerService(Flow.Publisher.class, supplier.get(),
+                                       new Hashtable<>(Collections.singletonMap(Constants.SERVICE_PID, "argeo.logging.publisher")));
+               }
                osgiBoot = new OsgiBoot(bundleContext);
-               osgiBoot.bootstrap();
+               osgiBoot.bootstrap(config);
 
        }
 
@@ -73,25 +91,47 @@ public class OsgiRuntimeContext implements RuntimeContext {
        }
 
        public void stop(BundleContext bundleContext) {
-               if (loggingConfigurationSr != null)
-                       loggingConfigurationSr.unregister();
-               if (logEntryPublisherSr != null)
-                       logEntryPublisherSr.unregister();
-
+//             if (loggingConfigurationSr != null)
+//                     try {
+//                             loggingConfigurationSr.unregister();
+//                     } catch (Exception e) {
+//                             // silent
+//                     }
+//             if (logEntryPublisherSr != null)
+//                     try {
+//                             logEntryPublisherSr.unregister();
+//                     } catch (Exception e) {
+//                             // silent
+//                     }
        }
 
        @Override
        public void waitForStop(long timeout) throws InterruptedException {
                if (framework == null)
                        throw new IllegalStateException("Framework is not initialised");
-               stop(framework.getBundleContext());
+
                framework.waitForStop(timeout);
        }
 
-       @Override
        public void close() throws Exception {
+               // TODO make shutdown of dynamic service more robust
+               Bundle scrBundle = osgiBoot.getBundlesBySymbolicName().get("org.apache.felix.scr");
+               if (scrBundle != null) {
+                       scrBundle.stop();
+                       while (!(scrBundle.getState() <= Bundle.RESOLVED)) {
+                               Thread.sleep(500);
+                       }
+                       Thread.sleep(1000);
+               }
+
+               stop(framework.getBundleContext());
                if (framework != null)
                        framework.stop();
+
+       }
+
+       public Framework getFramework() {
+               return framework;
        }
 
 }