package org.argeo.init;
-import static org.argeo.api.init.InitConstants.SYMBOLIC_NAME_INIT;
-
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
import java.util.Map;
-import java.util.TreeMap;
-import java.util.function.Consumer;
import org.argeo.api.init.InitConstants;
-import org.argeo.api.init.RuntimeContext;
import org.argeo.api.init.RuntimeManager;
import org.argeo.init.logging.ThinLoggerFinder;
-import org.argeo.init.osgi.OsgiBoot;
import org.argeo.init.osgi.OsgiRuntimeContext;
import org.argeo.internal.init.InternalState;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkEvent;
-import org.osgi.framework.launch.Framework;
/**
* Dynamically configures and launches multiple runtimes, coordinated by a main
private final static long RUNTIME_SHUTDOWN_TIMEOUT = 60 * 1000;
- private Path baseConfigArea;
- private Path baseWritableArea;
private Map<String, String> configuration = new HashMap<>();
RuntimeManagerMain(Path configArea, Path stateArea) {
RuntimeManager.loadConfig(configArea, configuration);
-
+
// integration with OSGi runtime; this will be read by the init bundle
configuration.put(ServiceMain.PROP_ARGEO_INIT_MAIN, "true");
configuration.put(InitConstants.PROP_OSGI_SHARED_CONFIGURATION_AREA, configArea.toUri().toString());
-
- configuration.put(InitConstants.PROP_OSGI_CONFIGURATION_AREA, stateArea.resolve(RuntimeManager.STATE).toUri().toString());
+
+ configuration.put(InitConstants.PROP_OSGI_CONFIGURATION_AREA,
+ stateArea.resolve(RuntimeManager.STATE).toUri().toString());
// use config area if instance area is not set
if (!configuration.containsKey(InitConstants.PROP_OSGI_INSTANCE_AREA))
- configuration.put(InitConstants.PROP_OSGI_INSTANCE_AREA, stateArea.resolve(RuntimeManager.DATA).toUri().toString());
- this.baseConfigArea = configArea.getParent();
- this.baseWritableArea = stateArea.getParent();
+ configuration.put(InitConstants.PROP_OSGI_INSTANCE_AREA,
+ stateArea.resolve(RuntimeManager.DATA).toUri().toString());
logger.log(Level.TRACE, () -> "Runtime manager configuration: " + configuration);
}
public void run() {
- OsgiRuntimeContext managerRuntimeContext = new OsgiRuntimeContext(configuration);
+ OsgiRuntimeContext managerRuntimeContext = new OsgiRuntimeContext(OsgiRuntimeContext.loadFrameworkFactory(),
+ configuration);
try {
managerRuntimeContext.run();
InternalState.setMainRuntimeContext(managerRuntimeContext);
final static String FILE_SYSTEM_PROPERTIES = "system.properties";
+ @Deprecated
public final static String PROP_ARGEO_INIT_MAIN = "argeo.init.main";
// private static RuntimeContext runtimeContext = null;
config.put(InitConstants.PROP_OSGI_INSTANCE_AREA, dataArea);
// config.put(OsgiBoot.PROP_OSGI_USE_SYSTEM_PROPERTIES, "true");
- OsgiRuntimeContext osgiRuntimeContext = new OsgiRuntimeContext(config);
+ OsgiRuntimeContext osgiRuntimeContext = new OsgiRuntimeContext(
+ OsgiRuntimeContext.loadFrameworkFactory(), config);
osgiRuntimeContext.run();
InternalState.setMainRuntimeContext(osgiRuntimeContext);
for (Runnable run : postStart) {
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
+import java.lang.reflect.InvocationTargetException;
import java.util.Objects;
import org.argeo.api.init.RuntimeManager;
-import org.argeo.init.ServiceMain;
import org.argeo.init.logging.ThinLoggerFinder;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.connect.ConnectFrameworkFactory;
+import org.osgi.framework.launch.Framework;
/**
* An OSGi configurator. See
private Long checkpoint = null;
- private boolean argeoInit = false;
+ // TODO use framework factory SR
+// @Deprecated
+// private boolean argeoInit = false;
/** Not null if we created it ourselves. */
private OsgiRuntimeContext runtimeContext;
+ private ServiceRegistration<ConnectFrameworkFactory> frameworkFactorySr = null;
private static OsgiRuntimeManager runtimeManager;
public void start(final BundleContext bundleContext) throws Exception {
+ ConnectFrameworkFactory frameworkFactory = OsgiRuntimeContext.getFrameworkFactory(bundleContext);
+ if (frameworkFactory == null) {
+// argeoInit = false;
+ frameworkFactory = newFrameworkFactory();
+ frameworkFactorySr = bundleContext.registerService(ConnectFrameworkFactory.class, frameworkFactory, null);
+ }
+
// The OSGi runtime was created by us, and therefore already initialized
- argeoInit = Boolean.parseBoolean(bundleContext.getProperty(ServiceMain.PROP_ARGEO_INIT_MAIN));
- if (!argeoInit) {
+// argeoInit = Boolean.parseBoolean(bundleContext.getProperty(ServiceMain.PROP_ARGEO_INIT_MAIN));
+ if (!isArgeoInit()) {
if (runtimeContext == null) {
runtimeContext = new OsgiRuntimeContext(bundleContext);
logger.log(Level.DEBUG, () -> "Argeo init via OSGi activator");
runtimeContext.update();
checkpoint = System.currentTimeMillis();
}
- }
+ } else {
- if (runtimeManager != null)
- throw new IllegalArgumentException("Runtime manager is already set");
- runtimeManager = new OsgiRuntimeManager(bundleContext);
+ if (runtimeManager != null)
+ throw new IllegalArgumentException("Runtime manager is already set");
+ runtimeManager = new OsgiRuntimeManager(bundleContext);
+ }
}
public void stop(BundleContext context) throws Exception {
- if (!argeoInit) {
+ if (!isArgeoInit()) {
+ frameworkFactorySr.unregister();
Objects.nonNull(runtimeContext);
runtimeContext.stop(context);
runtimeContext = null;
runtimeManager = null;
}
+ /** Whether it wa sinitialised by an Argeo Init main class. */
+ private boolean isArgeoInit() {
+ return frameworkFactorySr == null;
+ }
+
public static RuntimeManager getRuntimeManager() {
return runtimeManager;
}
+ /**
+ * Workaround to explicitly instantiate an Equinox
+ * {@link ConnectFrameworkFactory} when running in a pure OSGi runtime.
+ */
+ private ConnectFrameworkFactory newFrameworkFactory() {
+ final String EQUINOX_FRAMEWORK_FACTORY_CLASS = "org.eclipse.osgi.launch.EquinoxFactory";
+ try {
+ @SuppressWarnings("unchecked")
+ Class<? extends ConnectFrameworkFactory> frameworkFactoryClass = (Class<? extends ConnectFrameworkFactory>) Framework.class
+ .getClassLoader().loadClass(EQUINOX_FRAMEWORK_FACTORY_CLASS);
+ return frameworkFactoryClass.getConstructor().newInstance();
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException | NoSuchMethodException | SecurityException e) {
+ throw new IllegalStateException("Cannot create OSGi framework factory", e);
+ }
+ }
}
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 {
// 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;
* 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;
}
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);
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);
+ }
}
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
-import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.argeo.api.init.RuntimeManager;
import org.argeo.internal.init.InternalState;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.connect.ConnectFrameworkFactory;
import org.osgi.framework.launch.Framework;
private final static long RUNTIME_SHUTDOWN_TIMEOUT = 60 * 1000;
- private final static String EQUINOX_FRAMEWORK_FACTORY_CLASS = "org.eclipse.osgi.launch.EquinoxFactory";
-
private Path baseConfigArea;
private Path baseWritableArea;
private Map<String, String> configuration = new HashMap<>();
private ConnectFrameworkFactory frameworkFactory;
OsgiRuntimeManager(BundleContext bundleContext) {
- try {
- @SuppressWarnings("unchecked")
- Class<? extends ConnectFrameworkFactory> frameworkFactoryClass = (Class<? extends ConnectFrameworkFactory>) Framework.class
- .getClassLoader().loadClass(EQUINOX_FRAMEWORK_FACTORY_CLASS);
- frameworkFactory = frameworkFactoryClass.getConstructor().newInstance();
- } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException
- | InvocationTargetException | NoSuchMethodException | SecurityException e) {
- throw new IllegalStateException("Cannot create OSGi framework factory", e);
- }
-
+ frameworkFactory = OsgiRuntimeContext.getFrameworkFactory(bundleContext);
this.baseConfigArea = Paths
.get(URI.create(bundleContext.getProperty(InitConstants.PROP_OSGI_SHARED_CONFIGURATION_AREA)))
.getParent();
config.put(InitConstants.PROP_OSGI_INSTANCE_AREA, writableArea.resolve(DATA).toUri().toString());
// create framework
- Framework framework = frameworkFactory.newFramework(config, null);
- try {
- framework.start();
- } catch (BundleException e) {
- throw new IllegalStateException("Cannot initialise framework", e);
- }
- OsgiRuntimeContext runtimeContext = new OsgiRuntimeContext(framework.getBundleContext());
+// Framework framework = frameworkFactory.newFramework(config, null);
+// try {
+// framework.start();
+// } catch (BundleException e) {
+// throw new IllegalStateException("Cannot initialise framework", e);
+// }
+ OsgiRuntimeContext runtimeContext = new OsgiRuntimeContext(frameworkFactory, config);
runtimeContexts.put(relPath, runtimeContext);
return runtimeContext;
}
public void startRuntime(String relPath, Consumer<Map<String, String>> configCallback) {
OsgiRuntimeContext runtimeContext = loadRuntime(relPath, configCallback);
- //runtimeContext.run();
+ runtimeContext.run();
Framework framework = runtimeContext.getFramework();
if (framework != null) {// in case the framework has closed very quickly after run
framework.getBundleContext().addFrameworkListener((e) -> {