1 package org
.argeo
.osgi
.boot
;
3 import java
.lang
.reflect
.Method
;
5 import java
.util
.ArrayList
;
6 import java
.util
.Collections
;
7 import java
.util
.HashMap
;
8 import java
.util
.HashSet
;
11 import java
.util
.Properties
;
13 import java
.util
.TreeMap
;
15 import org
.eclipse
.osgi
.launch
.EquinoxFactory
;
16 import org
.osgi
.framework
.Bundle
;
17 import org
.osgi
.framework
.BundleContext
;
18 import org
.osgi
.framework
.BundleEvent
;
19 import org
.osgi
.framework
.BundleException
;
20 import org
.osgi
.framework
.FrameworkUtil
;
21 import org
.osgi
.framework
.InvalidSyntaxException
;
22 import org
.osgi
.framework
.ServiceReference
;
23 import org
.osgi
.framework
.launch
.Framework
;
24 import org
.osgi
.framework
.launch
.FrameworkFactory
;
25 import org
.osgi
.util
.tracker
.BundleTracker
;
26 import org
.osgi
.util
.tracker
.ServiceTracker
;
28 /** OSGi builder, focusing on ease of use for scripting. */
29 public class OsgiBuilder
{
30 private final static String PROP_HTTP_PORT
= "org.osgi.service.http.port";
31 private final static String PROP_HTTPS_PORT
= "org.osgi.service.https.port";
32 private final static String PROP_OSGI_CLEAN
= "osgi.clean";
34 private Map
<Integer
, StartLevel
> startLevels
= new TreeMap
<>();
35 private List
<String
> distributionBundles
= new ArrayList
<>();
37 private Map
<String
, String
> configuration
= new HashMap
<String
, String
>();
38 private Framework framework
;
39 private String baseUrl
= null;
41 public OsgiBuilder() {
42 // configuration.put("osgi.clean", "true");
43 configuration
.put(OsgiBoot
.CONFIGURATION_AREA_PROP
, System
.getProperty(OsgiBoot
.CONFIGURATION_AREA_PROP
));
44 configuration
.put(OsgiBoot
.INSTANCE_AREA_PROP
, System
.getProperty(OsgiBoot
.INSTANCE_AREA_PROP
));
45 configuration
.put(PROP_OSGI_CLEAN
, System
.getProperty(PROP_OSGI_CLEAN
));
48 public Framework
launch() {
50 FrameworkFactory frameworkFactory
= new EquinoxFactory();
51 framework
= frameworkFactory
.newFramework(configuration
);
54 } catch (BundleException e
) {
55 throw new OsgiBootException("Cannot start OSGi framework", e
);
58 BundleContext bc
= framework
.getBundleContext();
59 String osgiData
= bc
.getProperty(OsgiBoot
.INSTANCE_AREA_PROP
);
60 // String osgiConf = bc.getProperty(OsgiBoot.CONFIGURATION_AREA_PROP);
61 String osgiConf
= framework
.getDataFile("").getAbsolutePath();
62 if (OsgiBootUtils
.isDebug())
63 OsgiBootUtils
.debug("OSGi starting - data: " + osgiData
+ " conf: " + osgiConf
);
65 OsgiBoot osgiBoot
= new OsgiBoot(framework
.getBundleContext());
66 if (distributionBundles
.isEmpty()) {
67 osgiBoot
.getProvisioningManager().install(null);
70 for (String distributionBundle
: distributionBundles
) {
71 List
<String
> bundleUrls
= osgiBoot
.getDistributionUrls(distributionBundle
, baseUrl
);
72 osgiBoot
.installUrls(bundleUrls
);
76 osgiBoot
.startBundles(startLevelsToProperties());
78 // if (OsgiBootUtils.isDebug())
79 // for (Bundle bundle : bc.getBundles()) {
80 // OsgiBootUtils.debug(bundle.getLocation());
85 public OsgiBuilder
conf(String key
, String value
) {
87 configuration
.put(key
, value
);
91 public OsgiBuilder
install(String uri
) {
92 // TODO dynamic install
94 if (!distributionBundles
.contains(uri
))
95 distributionBundles
.add(uri
);
99 public OsgiBuilder
start(int startLevel
, String bundle
) {
100 // TODO dynamic start
103 if (!startLevels
.containsKey(startLevel
))
104 startLevels
.put(startLevel
, new StartLevel());
105 sl
= startLevels
.get(startLevel
);
110 public OsgiBuilder
waitForServlet(String base
) {
111 service("(&(objectClass=javax.servlet.Servlet)(osgi.http.whiteboard.servlet.pattern=" + base
+ "))");
115 public OsgiBuilder
waitForBundle(String bundles
) {
116 List
<String
> lst
= new ArrayList
<>();
117 Collections
.addAll(lst
, bundles
.split(","));
118 BundleTracker
<Object
> bt
= new BundleTracker
<Object
>(getBc(), Bundle
.ACTIVE
, null) {
121 public Object
addingBundle(Bundle bundle
, BundleEvent event
) {
122 if (lst
.contains(bundle
.getSymbolicName())) {
123 return bundle
.getSymbolicName();
130 while (bt
.getTrackingCount() != lst
.size()) {
133 } catch (InterruptedException e
) {
142 public OsgiBuilder
main(String clssUri
, String
[] args
) {
144 // waitForBundle(bundleSymbolicName);
146 URI uri
= new URI(clssUri
);
147 if (!"bundleclass".equals(uri
.getScheme()))
148 throw new IllegalArgumentException("Unsupported scheme for " + clssUri
);
149 String bundleSymbolicName
= uri
.getHost();
150 String clss
= uri
.getPath().substring(1);
151 Bundle bundle
= null;
152 for (Bundle b
: getBc().getBundles()) {
153 if (bundleSymbolicName
.equals(b
.getSymbolicName())) {
159 throw new OsgiBootException("Bundle " + bundleSymbolicName
+ " not found");
160 Class
<?
> c
= bundle
.loadClass(clss
);
161 Object
[] mainArgs
= { args
};
162 Method mainMethod
= c
.getMethod("main", String
[].class);
163 mainMethod
.invoke(null, mainArgs
);
164 } catch (Throwable e
) {
165 throw new OsgiBootException("Cannot execute " + clssUri
, e
);
170 public Object
service(String service
) {
171 return service(service
, 0);
174 public Object
service(String service
, long timeout
) {
175 ServiceTracker
<Object
, Object
> st
;
176 if (service
.contains("(")) {
178 st
= new ServiceTracker
<>(getBc(), FrameworkUtil
.createFilter(service
), null);
179 } catch (InvalidSyntaxException e
) {
180 throw new IllegalArgumentException("Badly formatted filter", e
);
183 st
= new ServiceTracker
<>(getBc(), service
, null);
187 return st
.waitForService(timeout
);
188 } catch (InterruptedException e
) {
189 OsgiBootUtils
.error("Interrupted", e
);
197 public void shutdown() {
201 } catch (BundleException e
) {
206 framework
.waitForStop(10 * 60 * 1000);
207 } catch (InterruptedException e
) {
214 public void setHttpPort(Integer port
) {
216 configuration
.put(PROP_HTTP_PORT
, Integer
.toString(port
));
219 public void setHttpsPort(Integer port
) {
221 configuration
.put(PROP_HTTPS_PORT
, Integer
.toString(port
));
224 public void setClean(boolean clean
) {
226 configuration
.put(PROP_OSGI_CLEAN
, Boolean
.toString(clean
));
229 public Integer
getHttpPort() {
231 if (configuration
.containsKey(PROP_HTTP_PORT
))
232 return Integer
.parseInt(configuration
.get(PROP_HTTP_PORT
));
236 // TODO wait for service?
237 ServiceReference
<?
> sr
= getBc().getServiceReference("org.osgi.service.http.HttpService");
240 Object port
= sr
.getProperty("http.port");
243 return Integer
.parseInt(port
.toString());
247 public Integer
getHttpsPort() {
249 if (configuration
.containsKey(PROP_HTTPS_PORT
))
250 return Integer
.parseInt(configuration
.get(PROP_HTTPS_PORT
));
254 // TODO wait for service?
255 ServiceReference
<?
> sr
= getBc().getServiceReference("org.osgi.service.http.HttpService");
258 Object port
= sr
.getProperty("https.port");
261 return Integer
.parseInt(port
.toString());
265 public Object
spring(String bundle
) {
266 return service("(&(Bundle-SymbolicName=" + bundle
+ ")"
267 + "(objectClass=org.springframework.context.ApplicationContext))");
274 public BundleContext
getBc() {
276 return framework
.getBundleContext();
279 public void setBaseUrl(String baseUrl
) {
280 this.baseUrl
= baseUrl
;
286 private Properties
startLevelsToProperties() {
287 Properties properties
= new Properties();
288 for (Integer startLevel
: startLevels
.keySet()) {
289 String property
= OsgiBoot
.PROP_ARGEO_OSGI_START
+ "." + startLevel
;
290 StringBuilder value
= new StringBuilder();
291 for (String bundle
: startLevels
.get(startLevel
).getBundles()) {
292 value
.append(bundle
);
295 // TODO remove trailing comma
296 properties
.put(property
, value
.toString());
301 private void checkLaunched() {
303 throw new OsgiBootException("OSGi runtime is not launched");
306 private void checkNotLaunched() {
308 throw new OsgiBootException("OSGi runtime already launched");
311 private boolean isLaunched() {
312 return framework
!= null;
315 private static class StartLevel
{
316 private Set
<String
> bundles
= new HashSet
<>();
318 public void add(String bundle
) {
319 String
[] b
= bundle
.split(",");
320 Collections
.addAll(bundles
, b
);
323 public Set
<String
> getBundles() {