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