1 package org
.argeo
.init
.osgi
;
3 import java
.io
.Serializable
;
4 import java
.lang
.System
.Logger
;
5 import java
.lang
.System
.Logger
.Level
;
6 import java
.lang
.System
.LoggerFinder
;
7 import java
.util
.Collections
;
8 import java
.util
.Hashtable
;
10 import java
.util
.Optional
;
11 import java
.util
.ServiceLoader
;
12 import java
.util
.concurrent
.Flow
;
13 import java
.util
.function
.Consumer
;
14 import java
.util
.function
.Supplier
;
16 import org
.argeo
.api
.init
.RuntimeContext
;
17 import org
.osgi
.framework
.BundleContext
;
18 import org
.osgi
.framework
.BundleException
;
19 import org
.osgi
.framework
.Constants
;
20 import org
.osgi
.framework
.launch
.Framework
;
21 import org
.osgi
.framework
.launch
.FrameworkFactory
;
23 /** An OSGi runtime context. */
24 public class OsgiRuntimeContext
implements RuntimeContext
, AutoCloseable
{
25 private final static Logger logger
= System
.getLogger(OsgiRuntimeContext
.class.getName());
27 private final static long STOP_FOR_UPDATE_TIMEOUT
= 60 * 1000;
28 private final static long CLOSE_TIMEOUT
= 60 * 1000;
30 // private final static String SYMBOLIC_NAME_FELIX_SCR = "org.apache.felix.scr";
32 private Map
<String
, String
> config
;
33 private Framework framework
;
34 // private OsgiBoot osgiBoot;
37 * Constructor to use when the runtime context will create the OSGi
40 public OsgiRuntimeContext(Map
<String
, String
> config
) {
45 * Constructor to use when the OSGi {@link Framework} has been created by other
48 OsgiRuntimeContext(BundleContext bundleContext
) {
54 if (framework
!= null && framework
.getState() >= Framework
.STARTING
)
55 throw new IllegalStateException("OSGi framework is already started");
57 if (framework
== null) {
58 ServiceLoader
<FrameworkFactory
> sl
= ServiceLoader
.load(FrameworkFactory
.class);
59 Optional
<FrameworkFactory
> opt
= sl
.findFirst();
61 throw new IllegalStateException("Cannot find OSGi framework");
62 framework
= opt
.get().newFramework(config
);
67 BundleContext bundleContext
= framework
.getBundleContext();
69 } catch (BundleException e
) {
70 throw new IllegalStateException("Cannot start OSGi framework", e
);
74 protected void start(BundleContext bundleContext
) {
76 // SystemRootPreferences systemRootPreferences = ThinPreferencesFactory.getInstance().getSystemRootPreferences();
77 // bundleContext.registerService(AbstractPreferences.class, systemRootPreferences, new Hashtable<>());
79 // Make sure LoggerFinder has been searched for, since it is lazily loaded
80 LoggerFinder loggerFinder
= LoggerFinder
.getLoggerFinder();
82 if (loggerFinder
instanceof Consumer
<?
> && loggerFinder
instanceof Supplier
<?
>) {
83 @SuppressWarnings("unchecked")
84 Consumer
<Map
<String
, Object
>> consumer
= (Consumer
<Map
<String
, Object
>>) loggerFinder
;
85 // ThinLoggerFinder.getConfigurationConsumer()
86 // ThinLoggerFinder.getLogEntryPublisher()
88 @SuppressWarnings("unchecked")
89 Supplier
<Flow
.Publisher
<Map
<String
, Serializable
>>> supplier
= (Supplier
<Flow
.Publisher
<Map
<String
, Serializable
>>>) loggerFinder
;
91 bundleContext
.registerService(Consumer
.class, consumer
,
92 new Hashtable
<>(Collections
.singletonMap(Constants
.SERVICE_PID
, "argeo.logging.configuration")));
93 bundleContext
.registerService(Flow
.Publisher
.class, supplier
.get(),
94 new Hashtable
<>(Collections
.singletonMap(Constants
.SERVICE_PID
, "argeo.logging.publisher")));
96 OsgiBoot osgiBoot
= new OsgiBoot(bundleContext
);
97 String frameworkUuuid
= bundleContext
.getProperty(Constants
.FRAMEWORK_UUID
);
99 // separate thread in order to improve logging
100 Thread osgiBootThread
= new Thread("OSGi boot framework " + frameworkUuuid
) {
103 osgiBoot
.bootstrap();
106 osgiBootThread
.start();
107 // TODO return a completable stage so that inits can run in parallel
109 // osgiBootThread.join(60 * 1000);
110 // } catch (InterruptedException e) {
115 public void update() {
118 waitForStop(STOP_FOR_UPDATE_TIMEOUT
);
119 } catch (InterruptedException e
) {
120 logger
.log(Level
.TRACE
, "Wait for stop interrupted", e
);
124 // TODO Optimise with OSGi mechanisms (e.g. framework.update())
125 // if (osgiBoot != null) {
126 // Objects.requireNonNull(osgiBoot);
127 // osgiBoot.update();
131 protected void stop() {
132 if (framework
== null)
134 stop(framework
.getBundleContext());
137 } catch (BundleException e
) {
138 throw new IllegalStateException("Cannot stop OSGi framework", e
);
142 protected void stop(BundleContext bundleContext
) {
143 // if (loggingConfigurationSr != null)
145 // loggingConfigurationSr.unregister();
146 // } catch (Exception e) {
149 // if (logEntryPublisherSr != null)
151 // logEntryPublisherSr.unregister();
152 // } catch (Exception e) {
158 public void waitForStop(long timeout
) throws InterruptedException
{
159 if (framework
== null)
162 framework
.waitForStop(timeout
);
165 public void close() throws Exception
{
166 if (framework
== null)
168 // TODO make shutdown of dynamic service more robust
169 // for (Bundle scrBundle : framework.getBundleContext().getBundles()) {
170 // if (scrBundle.getSymbolicName().equals(SYMBOLIC_NAME_FELIX_SCR)) {
171 // if (scrBundle.getState() > Bundle.RESOLVED) {
173 // while (!(scrBundle.getState() <= Bundle.RESOLVED)) {
174 // Thread.sleep(100);
176 // Thread.sleep(500);
182 waitForStop(CLOSE_TIMEOUT
);
188 public Framework
getFramework() {