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());
67 for (String distributionBundle
: distributionBundles
) {
68 List
<String
> bundleUrls
= osgiBoot
.getDistributionUrls(distributionBundle
, baseUrl
);
69 osgiBoot
.installUrls(bundleUrls
);
73 osgiBoot
.startBundles(startLevelsToProperties());
75 // if (OsgiBootUtils.isDebug())
76 // for (Bundle bundle : bc.getBundles()) {
77 // OsgiBootUtils.debug(bundle.getLocation());
82 public OsgiBuilder
conf(String key
, String value
) {
84 configuration
.put(key
, value
);
88 public OsgiBuilder
install(String uri
) {
89 // TODO dynamic install
91 if (!distributionBundles
.contains(uri
))
92 distributionBundles
.add(uri
);
96 public OsgiBuilder
start(int startLevel
, String bundle
) {
100 if (!startLevels
.containsKey(startLevel
))
101 startLevels
.put(startLevel
, new StartLevel());
102 sl
= startLevels
.get(startLevel
);
107 public OsgiBuilder
waitForServlet(String base
) {
108 service("(&(objectClass=javax.servlet.Servlet)(osgi.http.whiteboard.servlet.pattern=" + base
+ "))");
112 public OsgiBuilder
waitForBundle(String bundles
) {
113 List
<String
> lst
= new ArrayList
<>();
114 Collections
.addAll(lst
, bundles
.split(","));
115 BundleTracker
<Object
> bt
= new BundleTracker
<Object
>(getBc(), Bundle
.ACTIVE
, null) {
118 public Object
addingBundle(Bundle bundle
, BundleEvent event
) {
119 if (lst
.contains(bundle
.getSymbolicName())) {
120 return bundle
.getSymbolicName();
127 while (bt
.getTrackingCount() != lst
.size()) {
130 } catch (InterruptedException e
) {
139 public OsgiBuilder
main(String clssUri
, String
[] args
) {
141 // waitForBundle(bundleSymbolicName);
143 URI uri
= new URI(clssUri
);
144 if (!"bundleclass".equals(uri
.getScheme()))
145 throw new IllegalArgumentException("Unsupported scheme for " + clssUri
);
146 String bundleSymbolicName
= uri
.getHost();
147 String clss
= uri
.getPath().substring(1);
148 Bundle bundle
= null;
149 for (Bundle b
: getBc().getBundles()) {
150 if (bundleSymbolicName
.equals(b
.getSymbolicName())) {
156 throw new OsgiBootException("Bundle " + bundleSymbolicName
+ " not found");
157 Class
<?
> c
= bundle
.loadClass(clss
);
158 Object
[] mainArgs
= { args
};
159 Method mainMethod
= c
.getMethod("main", String
[].class);
160 mainMethod
.invoke(null, mainArgs
);
161 } catch (Throwable e
) {
162 throw new OsgiBootException("Cannot execute " + clssUri
, e
);
167 public Object
service(String service
) {
168 return service(service
, 0);
171 public Object
service(String service
, long timeout
) {
172 ServiceTracker
<Object
, Object
> st
;
173 if (service
.contains("(")) {
175 st
= new ServiceTracker
<>(getBc(), FrameworkUtil
.createFilter(service
), null);
176 } catch (InvalidSyntaxException e
) {
177 throw new IllegalArgumentException("Badly formatted filter", e
);
180 st
= new ServiceTracker
<>(getBc(), service
, null);
184 return st
.waitForService(timeout
);
185 } catch (InterruptedException e
) {
186 OsgiBootUtils
.error("Interrupted", e
);
194 public void shutdown() {
198 } catch (BundleException e
) {
203 framework
.waitForStop(10 * 60 * 1000);
204 } catch (InterruptedException e
) {
211 public void setHttpPort(Integer port
) {
213 configuration
.put(PROP_HTTP_PORT
, Integer
.toString(port
));
216 public void setHttpsPort(Integer port
) {
218 configuration
.put(PROP_HTTPS_PORT
, Integer
.toString(port
));
221 public void setClean(boolean clean
) {
223 configuration
.put(PROP_OSGI_CLEAN
, Boolean
.toString(clean
));
226 public Integer
getHttpPort() {
228 if (configuration
.containsKey(PROP_HTTP_PORT
))
229 return Integer
.parseInt(configuration
.get(PROP_HTTP_PORT
));
233 // TODO wait for service?
234 ServiceReference
<?
> sr
= getBc().getServiceReference("org.osgi.service.http.HttpService");
237 Object port
= sr
.getProperty("http.port");
240 return Integer
.parseInt(port
.toString());
244 public Integer
getHttpsPort() {
246 if (configuration
.containsKey(PROP_HTTPS_PORT
))
247 return Integer
.parseInt(configuration
.get(PROP_HTTPS_PORT
));
251 // TODO wait for service?
252 ServiceReference
<?
> sr
= getBc().getServiceReference("org.osgi.service.http.HttpService");
255 Object port
= sr
.getProperty("https.port");
258 return Integer
.parseInt(port
.toString());
262 public Object
spring(String bundle
) {
263 return service("(&(Bundle-SymbolicName=" + bundle
+ ")"
264 + "(objectClass=org.springframework.context.ApplicationContext))");
271 public BundleContext
getBc() {
273 return framework
.getBundleContext();
276 public void setBaseUrl(String baseUrl
) {
277 this.baseUrl
= baseUrl
;
283 private Properties
startLevelsToProperties() {
284 Properties properties
= new Properties();
285 for (Integer startLevel
: startLevels
.keySet()) {
286 String property
= OsgiBoot
.PROP_ARGEO_OSGI_START
+ "." + startLevel
;
287 StringBuilder value
= new StringBuilder();
288 for (String bundle
: startLevels
.get(startLevel
).getBundles()) {
289 value
.append(bundle
);
292 // TODO remove trailing comma
293 properties
.put(property
, value
.toString());
298 private void checkLaunched() {
300 throw new OsgiBootException("OSGi runtime is not launched");
303 private void checkNotLaunched() {
305 throw new OsgiBootException("OSGi runtime already launched");
308 private boolean isLaunched() {
309 return framework
!= null;
312 private static class StartLevel
{
313 private Set
<String
> bundles
= new HashSet
<>();
315 public void add(String bundle
) {
316 String
[] b
= bundle
.split(",");
317 Collections
.addAll(bundles
, b
);
320 public Set
<String
> getBundles() {