]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/Activator.java
Fix issue with the ordering of event on the server side.
[gpl/argeo-slc.git] / runtime / org.argeo.slc.osgiboot / src / main / java / org / argeo / slc / osgiboot / Activator.java
1 package org.argeo.slc.osgiboot;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileReader;
6 import java.io.IOException;
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.StringTokenizer;
12
13 import org.argeo.slc.osgiboot.internal.springutil.AntPathMatcher;
14 import org.argeo.slc.osgiboot.internal.springutil.PathMatcher;
15 import org.argeo.slc.osgiboot.internal.springutil.SystemPropertyUtils;
16 import org.osgi.framework.Bundle;
17 import org.osgi.framework.BundleActivator;
18 import org.osgi.framework.BundleContext;
19 import org.osgi.framework.BundleException;
20
21 public class Activator implements BundleActivator {
22 public final static String PROP_SLC_OSGI_START = "slc.osgi.start";
23 public final static String PROP_SLC_OSGI_BUNDLES = "slc.osgi.bundles";
24 public final static String PROP_SLC_OSGI_DEV_BASES = "slc.osgi.devBases";
25 public final static String PROP_SLC_OSGI_DEV_PATTERNS = "slc.osgi.devPatterns";
26 public final static String PROP_SLC_OSGI_LOCATIONS = "slc.osgi.locations";
27 public final static String PROP_SLC_OSGI_BASE_URL = "slc.osgi.baseUrl";
28 public final static String PROP_SLC_MAVEN_DEPENDENCY_FILE = "slc.maven.dependencyFile";
29 public final static String PROP_SLC_OSGIBOOT_DEBUG = "slc.osgiboot.debug";
30
31 private static Boolean debug = Boolean.parseBoolean(System.getProperty(
32 PROP_SLC_OSGIBOOT_DEBUG, "false"));
33
34 public void start(BundleContext bundleContext) throws Exception {
35 try {
36 info("SLC OSGi bootstrap starting...");
37 // installUrls(bundleContext, getDevLocationsUrls());
38
39 installUrls(bundleContext, getBundlesUrls());
40
41 installUrls(bundleContext, getLocationsUrls());
42
43 installUrls(bundleContext, getMavenUrls());
44
45 startBundles(bundleContext);
46
47 info("SLC OSGi bootstrap completed");
48 } catch (Exception e) {
49 e.printStackTrace();
50 throw e;
51 }
52 }
53
54 public void stop(BundleContext context) throws Exception {
55 }
56
57 protected static void installUrls(BundleContext bundleContext,
58 List<String> urls) {
59 Map<String, Bundle> installedBundles = getInstalledBundles(bundleContext);
60 for (String url : urls) {
61 try {
62 if (installedBundles.containsKey(url)) {
63 Bundle bundle = installedBundles.get(url);
64 // bundle.update();
65 if (debug)
66 debug("Bundle " + bundle.getSymbolicName()
67 + " already installed from " + url);
68 } else {
69 Bundle bundle = bundleContext.installBundle(url);
70 if (debug)
71 debug("Installed bundle " + bundle.getSymbolicName()
72 + " from " + url);
73 }
74 } catch (BundleException e) {
75 warn("Could not install bundle from " + url + ": "
76 + e.getMessage());
77 }
78 }
79
80 }
81
82 protected List<String> getLocationsUrls() {
83 List<String> urlsProvided = new ArrayList<String>();
84
85 String baseUrl = getProperty(PROP_SLC_OSGI_BASE_URL, "reference:file:");
86 String bundlesList = getProperty(PROP_SLC_OSGI_LOCATIONS);
87 if (bundlesList == null)
88 return urlsProvided;
89 bundlesList = SystemPropertyUtils.resolvePlaceholders(bundlesList);
90
91 StringTokenizer st = new StringTokenizer(bundlesList,
92 File.pathSeparator);
93 while (st.hasMoreTokens()) {
94 urlsProvided.add(baseUrl + st.nextToken().trim());
95 }
96 return urlsProvided;
97 }
98
99 protected List<String> getDevLocationsUrls() {
100 List<String> urls = new ArrayList<String>();
101
102 String devBase = getProperty(PROP_SLC_OSGI_DEV_BASES);
103 String devPatterns = getProperty(PROP_SLC_OSGI_DEV_PATTERNS);
104 if (devBase == null)
105 return urls;
106 devBase = SystemPropertyUtils.resolvePlaceholders(devBase);
107 devBase = devBase.replace(File.separatorChar, '/');
108 devPatterns = SystemPropertyUtils.resolvePlaceholders(devPatterns);
109
110 List<String> bases = new ArrayList<String>();
111 StringTokenizer st = new StringTokenizer(devBase, ",");
112 while (st.hasMoreTokens()) {
113 String token = st.nextToken().trim();
114 char lastChar = token.charAt(token.length() - 1);
115 if (lastChar != '/')
116 token = token + '/';
117 bases.add(token);
118 }
119
120 List<String> patterns = new ArrayList<String>();
121 st = new StringTokenizer(devPatterns, ";");
122 while (st.hasMoreTokens()) {
123 patterns.add(st.nextToken().trim());
124 }
125
126 List<String> matched = new ArrayList<String>();
127 PathMatcher matcher = new AntPathMatcher();
128 for (String base : bases)
129 for (String pattern : patterns)
130 match(matcher, matched, base, null, pattern);
131
132 for (String fullPath : matched)
133 urls.add("reference:file:" + fullPath);
134
135 return urls;
136 }
137
138 protected List<String> getBundlesUrls() {
139 List<String> urls = new ArrayList<String>();
140
141 List<BundlesSet> bundlesSets = new ArrayList<BundlesSet>();
142 String bundles = getProperty(PROP_SLC_OSGI_BUNDLES);
143 if (bundles == null)
144 return urls;
145 info(PROP_SLC_OSGI_BUNDLES + "=" + bundles);
146
147 StringTokenizer st = new StringTokenizer(bundles, ",");
148 while (st.hasMoreTokens()) {
149 bundlesSets.add(new BundlesSet(st.nextToken()));
150 }
151
152 List<String> included = new ArrayList<String>();
153 PathMatcher matcher = new AntPathMatcher();
154 for (BundlesSet bundlesSet : bundlesSets)
155 for (String pattern : bundlesSet.getIncludes())
156 match(matcher, included, bundlesSet.getDir(), null, pattern);
157
158 List<String> excluded = new ArrayList<String>();
159 for (BundlesSet bundlesSet : bundlesSets)
160 for (String pattern : bundlesSet.getExcludes())
161 match(matcher, excluded, bundlesSet.getDir(), null, pattern);
162
163 for (String fullPath : included) {
164 if (!excluded.contains(fullPath))
165 urls.add("reference:file:" + fullPath);
166 }
167
168 return urls;
169 }
170
171 private class BundlesSet {
172 private String baseUrl = "reference:file";
173 private final String dir;
174 private List<String> includes = new ArrayList<String>();
175 private List<String> excludes = new ArrayList<String>();
176
177 public BundlesSet(String def) {
178 StringTokenizer st = new StringTokenizer(def, ";");
179
180 if (!st.hasMoreTokens())
181 throw new RuntimeException("Base dir not defined.");
182 try {
183 String dirPath = st.nextToken();
184 dir = new File(dirPath.replace('/', File.separatorChar))
185 .getCanonicalPath();
186 if (debug)
187 debug("Base dir: " + dir);
188 } catch (IOException e) {
189 throw new RuntimeException("Cannot convert to absolute path", e);
190 }
191
192 while (st.hasMoreTokens()) {
193 String tk = st.nextToken();
194 StringTokenizer stEq = new StringTokenizer(tk, "=");
195 String type = stEq.nextToken();
196 String pattern = stEq.nextToken();
197 if ("in".equals(type) || "include".equals(type)) {
198 includes.add(pattern);
199 } else if ("ex".equals(type) || "exclude".equals(type)) {
200 excludes.add(pattern);
201 } else if ("baseUrl".equals(type)) {
202 baseUrl = pattern;
203 } else {
204 System.err.println("Unkown bundles pattern type " + type);
205 }
206 }
207 }
208
209 public String getDir() {
210 return dir;
211 }
212
213 public List<String> getIncludes() {
214 return includes;
215 }
216
217 public List<String> getExcludes() {
218 return excludes;
219 }
220
221 public String getBaseUrl() {
222 return baseUrl;
223 }
224
225 }
226
227 protected void match(PathMatcher matcher, List<String> matched,
228 String base, String currentPath, String pattern) {
229 if (currentPath == null) {
230 // Init
231 File baseDir = new File(base.replace('/', File.separatorChar));
232 File[] files = baseDir.listFiles();
233
234 if (files == null) {
235 warn("Base dir " + baseDir + " has no children, exists="
236 + baseDir.exists() + ", isDirectory="
237 + baseDir.isDirectory());
238 return;
239 }
240
241 for (File file : files)
242 match(matcher, matched, base, file.getName(), pattern);
243 } else {
244 String fullPath = base + '/' + currentPath;
245 if (matched.contains(fullPath))
246 return;// don't try deeper if already matched
247
248 boolean ok = matcher.match(pattern, currentPath);
249 if (debug)
250 debug(currentPath + " " + (ok ? "" : " not ")
251 + " matched with " + pattern);
252 if (ok) {
253 matched.add(fullPath);
254 return;
255 } else {
256 String newFullPath = (base + '/' + currentPath).replace('/',
257 File.separatorChar);
258 File[] files = new File(newFullPath).listFiles();
259 if (files != null) {
260 for (File file : files)
261 if (file.isDirectory()) {
262 String newCurrentPath = currentPath + '/'
263 + file.getName();
264 if (matcher.matchStart(pattern, newCurrentPath)) {
265 // recurse only if start matches
266 match(matcher, matched, base, newCurrentPath,
267 pattern);
268 } else {
269 if (debug)
270 debug(newCurrentPath
271 + " does not start match with "
272 + pattern);
273
274 }
275 }
276 } else {
277 warn("Not a directory: " + newFullPath);
278 }
279 }
280 }
281 }
282
283 protected List<String> getMavenUrls() throws Exception {
284 String baseUrl = "reference:file:" + System.getProperty("user.home")
285 + "/.m2/repository/";
286 String config = getProperty(PROP_SLC_MAVEN_DEPENDENCY_FILE);
287 if (config == null)
288 return new ArrayList<String>();
289
290 List<MavenFile> mavenFiles = new ArrayList<MavenFile>();
291 BufferedReader in = new BufferedReader(new FileReader(config));
292 String line = null;
293 while ((line = in.readLine()) != null) {
294 try {
295 line = line.trim();
296 if (line.equals("")
297 || line
298 .startsWith("The following files have been resolved:"))
299 continue;// skip
300
301 mavenFiles.add(convert(line));
302 } catch (Exception e) {
303 warn("Could not load line " + line);
304 }
305 }
306
307 return asUrls(baseUrl, mavenFiles);
308 }
309
310 protected void startBundles(BundleContext bundleContext) throws Exception {
311 String bundlesToStart = getProperty(PROP_SLC_OSGI_START);
312 if (bundlesToStart == null)
313 return;
314
315 StringTokenizer st = new StringTokenizer(bundlesToStart, ",");
316 Map<String, Bundle> bundles = getBundles(bundleContext);
317 while (st.hasMoreTokens()) {
318 String name = st.nextToken().trim();
319 Bundle bundle = bundles.get(name);
320 if (bundle != null)
321 try {
322 bundle.start();
323 } catch (Exception e) {
324 warn("Bundle " + name + " cannot be started: "
325 + e.getMessage());
326 }
327 else
328 warn("Bundle " + name + " not installed.");
329
330 }
331 }
332
333 /** Key is location */
334 protected static Map<String, Bundle> getInstalledBundles(
335 BundleContext bundleContext) {
336 Map<String, Bundle> installedBundles = new HashMap<String, Bundle>();
337
338 for (Bundle bundle : bundleContext.getBundles()) {
339 installedBundles.put(bundle.getLocation(), bundle);
340 }
341 return installedBundles;
342 }
343
344 /** Key is symbolic name */
345 protected static Map<String, Bundle> getBundles(BundleContext bundleContext) {
346 Map<String, Bundle> installedBundles = new HashMap<String, Bundle>();
347 for (Bundle bundle : bundleContext.getBundles())
348 installedBundles.put(bundle.getSymbolicName(), bundle);
349 return installedBundles;
350 }
351
352 protected static List<String> asUrls(String baseUrl,
353 List<MavenFile> mavenFiles) {
354 List<String> urls = new ArrayList<String>();
355 for (MavenFile mf : mavenFiles)
356 urls.add(convertToUrl(baseUrl, mf));
357 return urls;
358 }
359
360 protected static String convertToUrl(String baseUrl, MavenFile mf) {
361 return baseUrl + mf.getGroupId().replace('.', '/') + '/'
362 + mf.getArtifactId() + '/' + mf.getVersion() + '/'
363 + mf.getArtifactId() + '-' + mf.getVersion() + '.'
364 + mf.getType();
365 }
366
367 protected static MavenFile convert(String str) {
368 StringTokenizer st = new StringTokenizer(str, ":");
369 MavenFile component = new MavenFile();
370 component.setGroupId(st.nextToken());
371 component.setArtifactId(st.nextToken());
372 component.setType(st.nextToken());
373 component.setVersion(st.nextToken());
374 component.setScope(st.nextToken());
375 return component;
376 }
377
378 protected static String getProperty(String name, String defaultValue) {
379 final String value;
380 if (defaultValue != null)
381 value = System.getProperty(name, defaultValue);
382 else
383 value = System.getProperty(name);
384
385 if (value == null || value.equals(""))
386 return null;
387 else
388 return value;
389 }
390
391 protected static String getProperty(String name) {
392 return getProperty(name, null);
393 }
394
395 private static void info(Object obj) {
396 System.out.println("# INFO " + obj);
397 }
398
399 private static void debug(Object obj) {
400 if (debug)
401 System.out.println("# DBUG " + obj);
402 }
403
404 private static void warn(Object obj) {
405 System.out.println("# WARN " + obj);
406 // if (System.getProperty("os.name").contains("Windows"))
407 // System.out.println("# WARN " + obj);
408 // else
409 // System.err.println("# WARN " + obj);
410 }
411
412 static class MavenFile {
413 private String groupId;
414 private String artifactId;
415 private String version;
416 private String type;
417 private String classifier;
418 private String scope;
419
420 public String getScope() {
421 return scope;
422 }
423
424 public void setScope(String scope) {
425 this.scope = scope;
426 }
427
428 private String distributionId;
429
430 public String getDistributionId() {
431 return distributionId;
432 }
433
434 public void setDistributionId(String distributionId) {
435 this.distributionId = distributionId;
436 }
437
438 public String getGroupId() {
439 return groupId;
440 }
441
442 public void setGroupId(String groupId) {
443 this.groupId = groupId;
444 }
445
446 public String getArtifactId() {
447 return artifactId;
448 }
449
450 public void setArtifactId(String artifactId) {
451 this.artifactId = artifactId;
452 }
453
454 public String getVersion() {
455 return version;
456 }
457
458 public void setVersion(String version) {
459 this.version = version;
460 }
461
462 public String getType() {
463 return type;
464 }
465
466 public void setType(String type) {
467 this.type = type;
468 }
469
470 public String getClassifier() {
471 return classifier;
472 }
473
474 public void setClassifier(String classifier) {
475 this.classifier = classifier;
476 }
477
478 }
479
480 }