]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.osgi.boot/src/org/argeo/osgi/boot/OsgiBuilder.java
81315cf4ede73dc542fa389330f3cb3ac7b21c06
[lgpl/argeo-commons.git] / org.argeo.osgi.boot / src / org / argeo / osgi / boot / OsgiBuilder.java
1 package org.argeo.osgi.boot;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.HashMap;
6 import java.util.HashSet;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Properties;
10 import java.util.Set;
11 import java.util.TreeMap;
12
13 import org.eclipse.osgi.launch.EquinoxFactory;
14 import org.osgi.framework.Bundle;
15 import org.osgi.framework.BundleContext;
16 import org.osgi.framework.BundleEvent;
17 import org.osgi.framework.BundleException;
18 import org.osgi.framework.FrameworkUtil;
19 import org.osgi.framework.InvalidSyntaxException;
20 import org.osgi.framework.ServiceReference;
21 import org.osgi.framework.launch.Framework;
22 import org.osgi.framework.launch.FrameworkFactory;
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 Map<Integer, StartLevel> startLevels = new TreeMap<>();
29 private List<String> distributionBundles = new ArrayList<>();
30
31 private Map<String, String> configuration = new HashMap<String, String>();
32 private Framework framework;
33 private String baseUrl = null;
34
35 public OsgiBuilder() {
36 // configuration.put("osgi.clean", "true");
37 configuration.put(OsgiBoot.CONFIGURATION_AREA_PROP, System.getProperty(OsgiBoot.CONFIGURATION_AREA_PROP));
38 configuration.put(OsgiBoot.INSTANCE_AREA_PROP, System.getProperty(OsgiBoot.INSTANCE_AREA_PROP));
39 }
40
41 public Framework launch() {
42 // start OSGi
43 FrameworkFactory frameworkFactory = new EquinoxFactory();
44 framework = frameworkFactory.newFramework(configuration);
45 try {
46 framework.start();
47 } catch (BundleException e) {
48 throw new OsgiBootException("Cannot start OSGi framework", e);
49 }
50
51 BundleContext bc = framework.getBundleContext();
52 String osgiData = bc.getProperty(OsgiBoot.INSTANCE_AREA_PROP);
53 // String osgiConf = bc.getProperty(OsgiBoot.CONFIGURATION_AREA_PROP);
54 String osgiConf = framework.getDataFile("").getAbsolutePath();
55 if (OsgiBootUtils.isDebug())
56 OsgiBootUtils.debug("OSGi starting - data: " + osgiData + " conf: " + osgiConf);
57
58 OsgiBoot osgiBoot = new OsgiBoot(framework.getBundleContext());
59 // install bundles
60 for (String distributionBundle : distributionBundles) {
61 List<String> bundleUrls = osgiBoot.getDistributionUrls(distributionBundle, baseUrl);
62 osgiBoot.installUrls(bundleUrls);
63 }
64
65 // start bundles
66 osgiBoot.startBundles(startLevelsToProperties());
67
68 // if (OsgiBootUtils.isDebug())
69 // for (Bundle bundle : bc.getBundles()) {
70 // OsgiBootUtils.debug(bundle.getLocation());
71 // }
72 return framework;
73 }
74
75 public OsgiBuilder conf(String key, String value) {
76 checkNotLaunched();
77 configuration.put(key, value);
78 return this;
79 }
80
81 public OsgiBuilder install(String uri) {
82 // TODO dynamic install
83 checkNotLaunched();
84 if (!distributionBundles.contains(uri))
85 distributionBundles.add(uri);
86 return this;
87 }
88
89 public OsgiBuilder start(int startLevel, String bundle) {
90 // TODO dynamic start
91 checkNotLaunched();
92 StartLevel sl;
93 if (!startLevels.containsKey(startLevel))
94 startLevels.put(startLevel, new StartLevel());
95 sl = startLevels.get(startLevel);
96 sl.add(bundle);
97 return this;
98 }
99
100 public OsgiBuilder waitForBundle(String bundles) {
101 List<String> lst = new ArrayList<>();
102 Collections.addAll(lst, bundles.split(","));
103 BundleTracker<Object> bt = new BundleTracker<Object>(getBc(), Bundle.ACTIVE, null) {
104
105 @Override
106 public Object addingBundle(Bundle bundle, BundleEvent event) {
107 if (lst.contains(bundle.getSymbolicName())) {
108 return bundle.getSymbolicName();
109 } else {
110 return null;
111 }
112 }
113 };
114 bt.open();
115 while (bt.getTrackingCount() != lst.size()) {
116 try {
117 Thread.sleep(500l);
118 } catch (InterruptedException e) {
119 break;
120 }
121 }
122 bt.close();
123 return this;
124
125 }
126
127 public Object service(String service) {
128 return service(service, 0);
129 }
130
131 public Object service(String service, long timeout) {
132 ServiceTracker<Object, Object> st;
133 if (service.contains("(")) {
134 try {
135 st = new ServiceTracker<>(getBc(), FrameworkUtil.createFilter(service), null);
136 } catch (InvalidSyntaxException e) {
137 throw new IllegalArgumentException("Badly formatted filter", e);
138 }
139 } else {
140 st = new ServiceTracker<>(getBc(), service, null);
141 }
142 st.open();
143 try {
144 return st.waitForService(timeout);
145 } catch (InterruptedException e) {
146 OsgiBootUtils.error("Interrupted", e);
147 return null;
148 } finally {
149 st.close();
150 }
151
152 }
153
154 public void shutdown() {
155 checkLaunched();
156 try {
157 framework.stop();
158 } catch (BundleException e) {
159 e.printStackTrace();
160 System.exit(1);
161 }
162 try {
163 framework.waitForStop(10 * 60 * 1000);
164 } catch (InterruptedException e) {
165 e.printStackTrace();
166 System.exit(1);
167 }
168 System.exit(0);
169 }
170
171 public Integer getHttpPort() {
172 ServiceReference<?> sr = getBc().getServiceReference("org.osgi.service.http.HttpService");
173 if (sr == null)
174 return -1;
175 Object port = sr.getProperty("http.port");
176 if (port == null)
177 return -1;
178 return Integer.parseInt(port.toString());
179 }
180
181 public Integer getHttpsPort() {
182 ServiceReference<?> sr = getBc().getServiceReference("org.osgi.service.http.HttpService");
183 if (sr == null)
184 return -1;
185 Object port = sr.getProperty("https.port");
186 if (port == null)
187 return -1;
188 return Integer.parseInt(port.toString());
189 }
190
191 public Object spring(String bundle) {
192 return service("(&(Bundle-SymbolicName=" + bundle + ")"
193 + "(objectClass=org.springframework.context.ApplicationContext))");
194 }
195
196 //
197 // BEAN
198 //
199
200 public BundleContext getBc() {
201 checkLaunched();
202 return framework.getBundleContext();
203 }
204
205 public void setBaseUrl(String baseUrl) {
206 this.baseUrl = baseUrl;
207 }
208
209 //
210 // UTILITIES
211 //
212 private Properties startLevelsToProperties() {
213 Properties properties = new Properties();
214 for (Integer startLevel : startLevels.keySet()) {
215 String property = OsgiBoot.PROP_ARGEO_OSGI_START + "." + startLevel;
216 StringBuilder value = new StringBuilder();
217 for (String bundle : startLevels.get(startLevel).getBundles()) {
218 value.append(bundle);
219 value.append(',');
220 }
221 // TODO remove trailing comma
222 properties.put(property, value.toString());
223 }
224 return properties;
225 }
226
227 private void checkLaunched() {
228 if (!isLaunched())
229 throw new OsgiBootException("OSGi runtime is not launched");
230 }
231
232 private void checkNotLaunched() {
233 if (isLaunched())
234 throw new OsgiBootException("OSGi runtime already launched");
235 }
236
237 private boolean isLaunched() {
238 return framework != null;
239 }
240
241 private static class StartLevel {
242 private Set<String> bundles = new HashSet<>();
243
244 public void add(String bundle) {
245 String[] b = bundle.split(",");
246 Collections.addAll(bundles, b);
247 }
248
249 public Set<String> getBundles() {
250 return bundles;
251 }
252 }
253 }