]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.init/src/org/argeo/init/osgi/OsgiBuilder.java
Remove unused configurations in build.properties
[lgpl/argeo-commons.git] / org.argeo.init / src / org / argeo / init / osgi / OsgiBuilder.java
1 package org.argeo.init.osgi;
2
3 import java.lang.reflect.Method;
4 import java.net.URI;
5 import java.util.ArrayList;
6 import java.util.Collections;
7 import java.util.HashMap;
8 import java.util.HashSet;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Properties;
12 import java.util.Set;
13 import java.util.TreeMap;
14
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;
25
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";
31
32 private Map<Integer, StartLevel> startLevels = new TreeMap<>();
33 private List<String> distributionBundles = new ArrayList<>();
34
35 private Map<String, String> configuration = new HashMap<String, String>();
36 private Framework framework;
37 private String baseUrl = null;
38
39 public OsgiBuilder() {
40 // configuration.put("osgi.clean", "true");
41 configuration.put(OsgiBoot.CONFIGURATION_AREA_PROP, System.getProperty(OsgiBoot.CONFIGURATION_AREA_PROP));
42 configuration.put(OsgiBoot.INSTANCE_AREA_PROP, System.getProperty(OsgiBoot.INSTANCE_AREA_PROP));
43 configuration.put(PROP_OSGI_CLEAN, System.getProperty(PROP_OSGI_CLEAN));
44 }
45
46 public Framework launch() {
47 // start OSGi
48 framework = OsgiBootUtils.launch(configuration);
49
50 BundleContext bc = framework.getBundleContext();
51 String osgiData = bc.getProperty(OsgiBoot.INSTANCE_AREA_PROP);
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);
56
57 OsgiBoot osgiBoot = new OsgiBoot(framework.getBundleContext());
58 if (distributionBundles.isEmpty()) {
59 osgiBoot.getProvisioningManager().install(null);
60 } else {
61 // install bundles
62 for (String distributionBundle : distributionBundles) {
63 List<String> bundleUrls = osgiBoot.getDistributionUrls(distributionBundle, baseUrl);
64 osgiBoot.installUrls(bundleUrls);
65 }
66 }
67 // start bundles
68 osgiBoot.startBundles(startLevelsToProperties());
69
70 // if (OsgiBootUtils.isDebug())
71 // for (Bundle bundle : bc.getBundles()) {
72 // OsgiBootUtils.debug(bundle.getLocation());
73 // }
74 return framework;
75 }
76
77 public OsgiBuilder conf(String key, String value) {
78 checkNotLaunched();
79 configuration.put(key, value);
80 return this;
81 }
82
83 public OsgiBuilder install(String uri) {
84 // TODO dynamic install
85 checkNotLaunched();
86 if (!distributionBundles.contains(uri))
87 distributionBundles.add(uri);
88 return this;
89 }
90
91 public OsgiBuilder start(int startLevel, String bundle) {
92 // TODO dynamic start
93 checkNotLaunched();
94 StartLevel sl;
95 if (!startLevels.containsKey(startLevel))
96 startLevels.put(startLevel, new StartLevel());
97 sl = startLevels.get(startLevel);
98 sl.add(bundle);
99 return this;
100 }
101
102 public OsgiBuilder waitForServlet(String base) {
103 service("(&(objectClass=javax.servlet.Servlet)(osgi.http.whiteboard.servlet.pattern=" + base + "))");
104 return this;
105 }
106
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) {
111
112 @Override
113 public Object addingBundle(Bundle bundle, BundleEvent event) {
114 if (lst.contains(bundle.getSymbolicName())) {
115 return bundle.getSymbolicName();
116 } else {
117 return null;
118 }
119 }
120 };
121 bt.open();
122 while (bt.getTrackingCount() != lst.size()) {
123 try {
124 Thread.sleep(500l);
125 } catch (InterruptedException e) {
126 break;
127 }
128 }
129 bt.close();
130 return this;
131
132 }
133
134 public OsgiBuilder main(String clssUri, String[] args) {
135
136 // waitForBundle(bundleSymbolicName);
137 try {
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())) {
146 bundle = b;
147 break;
148 }
149 }
150 if (bundle == null)
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);
158 }
159 return this;
160 }
161
162 public Object service(String service) {
163 return service(service, 0);
164 }
165
166 public Object service(String service, long timeout) {
167 ServiceTracker<Object, Object> st;
168 if (service.contains("(")) {
169 try {
170 st = new ServiceTracker<>(getBc(), FrameworkUtil.createFilter(service), null);
171 } catch (InvalidSyntaxException e) {
172 throw new IllegalArgumentException("Badly formatted filter", e);
173 }
174 } else {
175 st = new ServiceTracker<>(getBc(), service, null);
176 }
177 st.open();
178 try {
179 return st.waitForService(timeout);
180 } catch (InterruptedException e) {
181 OsgiBootUtils.error("Interrupted", e);
182 return null;
183 } finally {
184 st.close();
185 }
186
187 }
188
189 public void shutdown() {
190 checkLaunched();
191 try {
192 framework.stop();
193 } catch (BundleException e) {
194 e.printStackTrace();
195 System.exit(1);
196 }
197 try {
198 framework.waitForStop(10 * 60 * 1000);
199 } catch (InterruptedException e) {
200 e.printStackTrace();
201 System.exit(1);
202 }
203 System.exit(0);
204 }
205
206 public void setHttpPort(Integer port) {
207 checkNotLaunched();
208 configuration.put(PROP_HTTP_PORT, Integer.toString(port));
209 }
210
211 public void setHttpsPort(Integer port) {
212 checkNotLaunched();
213 configuration.put(PROP_HTTPS_PORT, Integer.toString(port));
214 }
215
216 public void setClean(boolean clean) {
217 checkNotLaunched();
218 configuration.put(PROP_OSGI_CLEAN, Boolean.toString(clean));
219 }
220
221 public Integer getHttpPort() {
222 if (!isLaunched()) {
223 if (configuration.containsKey(PROP_HTTP_PORT))
224 return Integer.parseInt(configuration.get(PROP_HTTP_PORT));
225 else
226 return -1;
227 } else {
228 // TODO wait for service?
229 ServiceReference<?> sr = getBc().getServiceReference("org.osgi.service.http.HttpService");
230 if (sr == null)
231 return -1;
232 Object port = sr.getProperty("http.port");
233 if (port == null)
234 return -1;
235 return Integer.parseInt(port.toString());
236 }
237 }
238
239 public Integer getHttpsPort() {
240 if (!isLaunched()) {
241 if (configuration.containsKey(PROP_HTTPS_PORT))
242 return Integer.parseInt(configuration.get(PROP_HTTPS_PORT));
243 else
244 return -1;
245 } else {
246 // TODO wait for service?
247 ServiceReference<?> sr = getBc().getServiceReference("org.osgi.service.http.HttpService");
248 if (sr == null)
249 return -1;
250 Object port = sr.getProperty("https.port");
251 if (port == null)
252 return -1;
253 return Integer.parseInt(port.toString());
254 }
255 }
256
257 public Object spring(String bundle) {
258 return service("(&(Bundle-SymbolicName=" + bundle + ")"
259 + "(objectClass=org.springframework.context.ApplicationContext))");
260 }
261
262 //
263 // BEAN
264 //
265
266 public BundleContext getBc() {
267 checkLaunched();
268 return framework.getBundleContext();
269 }
270
271 public void setBaseUrl(String baseUrl) {
272 this.baseUrl = baseUrl;
273 }
274
275 //
276 // UTILITIES
277 //
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);
285 value.append(',');
286 }
287 // TODO remove trailing comma
288 properties.put(property, value.toString());
289 }
290 return properties;
291 }
292
293 private void checkLaunched() {
294 if (!isLaunched())
295 throw new IllegalStateException("OSGi runtime is not launched");
296 }
297
298 private void checkNotLaunched() {
299 if (isLaunched())
300 throw new IllegalStateException("OSGi runtime already launched");
301 }
302
303 private boolean isLaunched() {
304 return framework != null;
305 }
306
307 private static class StartLevel {
308 private Set<String> bundles = new HashSet<>();
309
310 public void add(String bundle) {
311 String[] b = bundle.split(",");
312 Collections.addAll(bundles, b);
313 }
314
315 public Set<String> getBundles() {
316 return bundles;
317 }
318 }
319 }