1 package org
.argeo
.init
.osgi
;
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
.osgi
.framework
.Bundle
;
16 import org
.osgi
.framework
.BundleContext
;
17 import org
.osgi
.framework
.BundleEvent
;
18 import org
.osgi
.framework
.BundleException
;
19 import org
.osgi
.framework
.FrameworkUtil
;
20 import org
.osgi
.framework
.InvalidSyntaxException
;
21 import org
.osgi
.framework
.ServiceReference
;
22 import org
.osgi
.framework
.launch
.Framework
;
23 import org
.osgi
.util
.tracker
.BundleTracker
;
24 import org
.osgi
.util
.tracker
.ServiceTracker
;
26 /** OSGi builder, focusing on ease of use for scripting. */
27 public class OsgiBuilder
{
28 private final static String PROP_HTTP_PORT
= "org.osgi.service.http.port";
29 private final static String PROP_HTTPS_PORT
= "org.osgi.service.https.port";
30 private final static String PROP_OSGI_CLEAN
= "osgi.clean";
32 private Map
<Integer
, StartLevel
> startLevels
= new TreeMap
<>();
33 private List
<String
> distributionBundles
= new ArrayList
<>();
35 private Map
<String
, String
> configuration
= new HashMap
<String
, String
>();
36 private Framework framework
;
37 private String baseUrl
= null;
39 public OsgiBuilder() {
40 // configuration.put("osgi.clean", "true");
41 configuration
.put(OsgiBoot
.PROP_OSGI_CONFIGURATION_AREA
, System
.getProperty(OsgiBoot
.PROP_OSGI_CONFIGURATION_AREA
));
42 configuration
.put(OsgiBoot
.PROP_OSGI_INSTANCE_AREA
, System
.getProperty(OsgiBoot
.PROP_OSGI_INSTANCE_AREA
));
43 configuration
.put(PROP_OSGI_CLEAN
, System
.getProperty(PROP_OSGI_CLEAN
));
46 public Framework
launch() {
48 framework
= OsgiBootUtils
.launch(configuration
);
50 BundleContext bc
= framework
.getBundleContext();
51 String osgiData
= bc
.getProperty(OsgiBoot
.PROP_OSGI_INSTANCE_AREA
);
52 // String osgiConf = bc.getProperty(OsgiBoot.CONFIGURATION_AREA_PROP);
53 String osgiConf
= framework
.getDataFile("").getAbsolutePath();
54 if (OsgiBootUtils
.isDebug())
55 OsgiBootUtils
.debug("OSGi starting - data: " + osgiData
+ " conf: " + osgiConf
);
57 OsgiBoot osgiBoot
= new OsgiBoot(framework
.getBundleContext());
58 if (distributionBundles
.isEmpty()) {
59 osgiBoot
.getProvisioningManager().install(null);
62 for (String distributionBundle
: distributionBundles
) {
63 List
<String
> bundleUrls
= osgiBoot
.getDistributionUrls(distributionBundle
, baseUrl
);
64 osgiBoot
.installUrls(bundleUrls
);
68 osgiBoot
.startBundles(startLevelsToProperties());
70 // if (OsgiBootUtils.isDebug())
71 // for (Bundle bundle : bc.getBundles()) {
72 // OsgiBootUtils.debug(bundle.getLocation());
77 public OsgiBuilder
conf(String key
, String value
) {
79 configuration
.put(key
, value
);
83 public OsgiBuilder
install(String uri
) {
84 // TODO dynamic install
86 if (!distributionBundles
.contains(uri
))
87 distributionBundles
.add(uri
);
91 public OsgiBuilder
start(int startLevel
, String bundle
) {
95 if (!startLevels
.containsKey(startLevel
))
96 startLevels
.put(startLevel
, new StartLevel());
97 sl
= startLevels
.get(startLevel
);
102 public OsgiBuilder
waitForServlet(String base
) {
103 service("(&(objectClass=javax.servlet.Servlet)(osgi.http.whiteboard.servlet.pattern=" + base
+ "))");
107 public OsgiBuilder
waitForBundle(String bundles
) {
108 List
<String
> lst
= new ArrayList
<>();
109 Collections
.addAll(lst
, bundles
.split(","));
110 BundleTracker
<Object
> bt
= new BundleTracker
<Object
>(getBc(), Bundle
.ACTIVE
, null) {
113 public Object
addingBundle(Bundle bundle
, BundleEvent event
) {
114 if (lst
.contains(bundle
.getSymbolicName())) {
115 return bundle
.getSymbolicName();
122 while (bt
.getTrackingCount() != lst
.size()) {
125 } catch (InterruptedException e
) {
134 public OsgiBuilder
main(String clssUri
, String
[] args
) {
136 // waitForBundle(bundleSymbolicName);
138 URI uri
= new URI(clssUri
);
139 if (!"bundleclass".equals(uri
.getScheme()))
140 throw new IllegalArgumentException("Unsupported scheme for " + clssUri
);
141 String bundleSymbolicName
= uri
.getHost();
142 String clss
= uri
.getPath().substring(1);
143 Bundle bundle
= null;
144 for (Bundle b
: getBc().getBundles()) {
145 if (bundleSymbolicName
.equals(b
.getSymbolicName())) {
151 throw new IllegalStateException("Bundle " + bundleSymbolicName
+ " not found");
152 Class
<?
> c
= bundle
.loadClass(clss
);
153 Object
[] mainArgs
= { args
};
154 Method mainMethod
= c
.getMethod("main", String
[].class);
155 mainMethod
.invoke(null, mainArgs
);
156 } catch (Throwable e
) {
157 throw new RuntimeException("Cannot execute " + clssUri
, e
);
162 public Object
service(String service
) {
163 return service(service
, 0);
166 public Object
service(String service
, long timeout
) {
167 ServiceTracker
<Object
, Object
> st
;
168 if (service
.contains("(")) {
170 st
= new ServiceTracker
<>(getBc(), FrameworkUtil
.createFilter(service
), null);
171 } catch (InvalidSyntaxException e
) {
172 throw new IllegalArgumentException("Badly formatted filter", e
);
175 st
= new ServiceTracker
<>(getBc(), service
, null);
179 return st
.waitForService(timeout
);
180 } catch (InterruptedException e
) {
181 OsgiBootUtils
.error("Interrupted", e
);
189 public void shutdown() {
193 } catch (BundleException e
) {
198 framework
.waitForStop(10 * 60 * 1000);
199 } catch (InterruptedException e
) {
206 public void setHttpPort(Integer port
) {
208 configuration
.put(PROP_HTTP_PORT
, Integer
.toString(port
));
211 public void setHttpsPort(Integer port
) {
213 configuration
.put(PROP_HTTPS_PORT
, Integer
.toString(port
));
216 public void setClean(boolean clean
) {
218 configuration
.put(PROP_OSGI_CLEAN
, Boolean
.toString(clean
));
221 public Integer
getHttpPort() {
223 if (configuration
.containsKey(PROP_HTTP_PORT
))
224 return Integer
.parseInt(configuration
.get(PROP_HTTP_PORT
));
228 // TODO wait for service?
229 ServiceReference
<?
> sr
= getBc().getServiceReference("org.osgi.service.http.HttpService");
232 Object port
= sr
.getProperty("http.port");
235 return Integer
.parseInt(port
.toString());
239 public Integer
getHttpsPort() {
241 if (configuration
.containsKey(PROP_HTTPS_PORT
))
242 return Integer
.parseInt(configuration
.get(PROP_HTTPS_PORT
));
246 // TODO wait for service?
247 ServiceReference
<?
> sr
= getBc().getServiceReference("org.osgi.service.http.HttpService");
250 Object port
= sr
.getProperty("https.port");
253 return Integer
.parseInt(port
.toString());
257 public Object
spring(String bundle
) {
258 return service("(&(Bundle-SymbolicName=" + bundle
+ ")"
259 + "(objectClass=org.springframework.context.ApplicationContext))");
266 public BundleContext
getBc() {
268 return framework
.getBundleContext();
271 public void setBaseUrl(String baseUrl
) {
272 this.baseUrl
= baseUrl
;
278 private Properties
startLevelsToProperties() {
279 Properties properties
= new Properties();
280 for (Integer startLevel
: startLevels
.keySet()) {
281 String property
= OsgiBoot
.PROP_ARGEO_OSGI_START
+ "." + startLevel
;
282 StringBuilder value
= new StringBuilder();
283 for (String bundle
: startLevels
.get(startLevel
).getBundles()) {
284 value
.append(bundle
);
287 // TODO remove trailing comma
288 properties
.put(property
, value
.toString());
293 private void checkLaunched() {
295 throw new IllegalStateException("OSGi runtime is not launched");
298 private void checkNotLaunched() {
300 throw new IllegalStateException("OSGi runtime already launched");
303 private boolean isLaunched() {
304 return framework
!= null;
307 private static class StartLevel
{
308 private Set
<String
> bundles
= new HashSet
<>();
310 public void add(String bundle
) {
311 String
[] b
= bundle
.split(",");
312 Collections
.addAll(bundles
, b
);
315 public Set
<String
> getBundles() {