]> git.argeo.org Git - lgpl/argeo-commons.git/blob - osgiboot/OsgiBoot.java
Prepare next development cycle
[lgpl/argeo-commons.git] / osgiboot / OsgiBoot.java
1 package org.argeo.slc.osgiboot;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.InputStreamReader;
8 import java.net.URL;
9 import java.util.ArrayList;
10 import java.util.HashMap;
11 import java.util.Iterator;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.StringTokenizer;
15
16 import org.argeo.slc.osgiboot.internal.springutil.AntPathMatcher;
17 import org.argeo.slc.osgiboot.internal.springutil.PathMatcher;
18 import org.argeo.slc.osgiboot.internal.springutil.SystemPropertyUtils;
19 import org.osgi.framework.Bundle;
20 import org.osgi.framework.BundleContext;
21 import org.osgi.framework.BundleException;
22 import org.osgi.framework.Constants;
23 import org.osgi.framework.ServiceReference;
24 import org.osgi.service.packageadmin.PackageAdmin;
25
26 public class OsgiBoot {
27 public final static String SYMBOLIC_NAME_OSGI_BOOT = "org.argeo.osgi.boot";
28 public final static String SYMBOLIC_NAME_EQUINOX = "org.eclipse.osgi";
29
30 public final static String PROP_ARGEO_OSGI_DATA_DIR = "argeo.osgi.data.dir";
31
32 public final static String PROP_ARGEO_OSGI_START = "argeo.osgi.start";
33 public final static String PROP_ARGEO_OSGI_BUNDLES = "argeo.osgi.bundles";
34 public final static String PROP_ARGEO_OSGI_LOCATIONS = "argeo.osgi.locations";
35 public final static String PROP_ARGEO_OSGI_BASE_URL = "argeo.osgi.baseUrl";
36 public final static String PROP_ARGEO_OSGI_MODULES_URL = "argeo.osgi.modulesUrl";
37
38 public final static String PROP_ARGEO_OSGI_BOOT_DEBUG = "argeo.osgi.boot.debug";
39 public final static String PROP_ARGEO_OSGI_BOOT_DEFAULT_TIMEOUT = "argeo.osgi.boot.defaultTimeout";
40 public final static String PROP_ARGEO_OSGI_BOOT_MODULES_URL_SEPARATOR = "argeo.osgi.boot.modulesUrlSeparator";
41 public final static String PROP_ARGEO_OSGI_BOOT_SYSTEM_PROPERTIES_FILE = "argeo.osgi.boot.systemPropertiesFile";
42
43 /** @deprecated */
44 public final static String PROP_SLC_OSGI_START = "slc.osgi.start";
45 /** @deprecated */
46 public final static String PROP_SLC_OSGI_BUNDLES = "slc.osgi.bundles";
47 /** @deprecated */
48 public final static String PROP_SLC_OSGI_LOCATIONS = "slc.osgi.locations";
49 /** @deprecated */
50 public final static String PROP_SLC_OSGI_BASE_URL = "slc.osgi.baseUrl";
51 /** @deprecated */
52 public final static String PROP_SLC_OSGI_MODULES_URL = "slc.osgi.modulesUrl";
53
54 /** @deprecated */
55 public final static String PROP_SLC_OSGIBOOT_DEBUG = "slc.osgiboot.debug";
56 /** @deprecated */
57 public final static String PROP_SLC_OSGIBOOT_DEFAULT_TIMEOUT = "slc.osgiboot.defaultTimeout";
58 /** @deprecated */
59 public final static String PROP_SLC_OSGIBOOT_MODULES_URL_SEPARATOR = "slc.osgiboot.modulesUrlSeparator";
60 /** @deprecated */
61 public final static String PROP_SLC_OSGIBOOT_SYSTEM_PROPERTIES_FILE = "slc.osgiboot.systemPropertiesFile";
62
63 public final static String DEFAULT_BASE_URL = "reference:file:";
64 public final static String EXCLUDES_SVN_PATTERN = "**/.svn/**";
65
66 private boolean debug = Boolean.valueOf(
67 System.getProperty(PROP_ARGEO_OSGI_BOOT_DEBUG, System.getProperty(
68 PROP_SLC_OSGIBOOT_DEBUG, "false"))).booleanValue();
69 /** Default is 10s (set in constructor) */
70 private long defaultTimeout;
71
72 private boolean excludeSvn = true;
73 /** Default is ',' (set in constructor) */
74 private String modulesUrlSeparator = ",";
75
76 private final BundleContext bundleContext;
77
78 public OsgiBoot(BundleContext bundleContext) {
79 this.bundleContext = bundleContext;
80 defaultTimeout = Long.parseLong(getPropertyCompat(
81 PROP_ARGEO_OSGI_BOOT_DEFAULT_TIMEOUT,
82 PROP_SLC_OSGIBOOT_DEFAULT_TIMEOUT, "10000"));
83 modulesUrlSeparator = getPropertyCompat(
84 PROP_ARGEO_OSGI_BOOT_MODULES_URL_SEPARATOR,
85 PROP_SLC_OSGIBOOT_MODULES_URL_SEPARATOR, ",");
86 initSystemProperties();
87 }
88
89 protected void initSystemProperties() {
90 String osgiInstanceArea = System.getProperty("osgi.instance.area");
91 String osgiInstanceAreaDefault = System
92 .getProperty("osgi.instance.area.default");
93 String tempDir = System.getProperty("java.io.tmpdir");
94
95 File dataDir = null;
96 if (osgiInstanceArea != null) {
97 // within OSGi with -data specified
98 osgiInstanceArea = removeFilePrefix(osgiInstanceArea);
99 dataDir = new File(osgiInstanceArea);
100 } else if (osgiInstanceAreaDefault != null) {
101 // within OSGi without -data specified
102 osgiInstanceAreaDefault = removeFilePrefix(osgiInstanceAreaDefault);
103 dataDir = new File(osgiInstanceAreaDefault);
104 } else {// outside OSGi
105 dataDir = new File(tempDir + File.separator + "argeoOsgiData");
106 }
107
108 System.setProperty(PROP_ARGEO_OSGI_DATA_DIR, dataDir.getAbsolutePath());
109 }
110
111 public static String removeFilePrefix(String url) {
112 if (url.startsWith("file:"))
113 return url.substring("file:".length());
114 else if (url.startsWith("reference:file:"))
115 return url.substring("reference:file:".length());
116 else
117 return url;
118 }
119
120 public void bootstrap() {
121 long begin = System.currentTimeMillis();
122 System.out.println();
123 info("OSGi bootstrap starting...");
124 info("Writable data directory : "
125 + System.getProperty(PROP_ARGEO_OSGI_DATA_DIR)
126 + " (set as system property " + PROP_ARGEO_OSGI_DATA_DIR + ")");
127 installUrls(getBundlesUrls());
128 installUrls(getLocationsUrls());
129 installUrls(getModulesUrls());
130 checkUnresolved();
131 startBundles();
132 long duration = System.currentTimeMillis() - begin;
133 info("OSGi bootstra completed in "
134 + Math.round(((double) duration) / 1000) + "s (" + duration
135 + "ms), " + bundleContext.getBundles().length + " bundles");
136 System.out.println();
137 }
138
139 public void installUrls(List urls) {
140 Map installedBundles = getInstalledBundles();
141 for (int i = 0; i < urls.size(); i++) {
142 String url = (String) urls.get(i);
143 try {
144 if (installedBundles.containsKey(url)) {
145 Bundle bundle = (Bundle) installedBundles.get(url);
146 // bundle.update();
147 if (debug)
148 debug("Bundle " + bundle.getSymbolicName()
149 + " already installed from " + url);
150 } else {
151 Bundle bundle = bundleContext.installBundle(url);
152 if (debug)
153 debug("Installed bundle " + bundle.getSymbolicName()
154 + " from " + url);
155 }
156 } catch (BundleException e) {
157 String message = e.getMessage();
158 if ((message.contains("Bundle \"" + SYMBOLIC_NAME_OSGI_BOOT
159 + "\"") || message.contains("Bundle \""
160 + SYMBOLIC_NAME_EQUINOX + "\""))
161 && message.contains("has already been installed")) {
162 // silent, in order to avoid warnings: we know that both
163 // have already been installed...
164 } else {
165 warn("Could not install bundle from " + url + ": "
166 + message);
167 }
168 if (debug)
169 e.printStackTrace();
170 }
171 }
172
173 }
174
175 public void installOrUpdateUrls(Map urls) {
176 Map installedBundles = getBundles();
177
178 for (Iterator modules = urls.keySet().iterator(); modules.hasNext();) {
179 String moduleName = (String) modules.next();
180 String urlStr = (String) urls.get(moduleName);
181 if (installedBundles.containsKey(moduleName)) {
182 Bundle bundle = (Bundle) installedBundles.get(moduleName);
183 InputStream in;
184 try {
185 URL url = new URL(urlStr);
186 in = url.openStream();
187 bundle.update(in);
188 info("Updated bundle " + moduleName + " from " + urlStr);
189 } catch (Exception e) {
190 throw new RuntimeException("Cannot update " + moduleName
191 + " from " + urlStr);
192 }
193 if (in != null)
194 try {
195 in.close();
196 } catch (IOException e) {
197 e.printStackTrace();
198 }
199 } else {
200 try {
201 Bundle bundle = bundleContext.installBundle(urlStr);
202 if (debug)
203 debug("Installed bundle " + bundle.getSymbolicName()
204 + " from " + urlStr);
205 } catch (BundleException e) {
206 warn("Could not install bundle from " + urlStr + ": "
207 + e.getMessage());
208 }
209 }
210 }
211
212 }
213
214 public void startBundles() {
215 String bundlesToStart = getPropertyCompat(PROP_ARGEO_OSGI_START,
216 PROP_SLC_OSGI_START);
217 startBundles(bundlesToStart);
218 }
219
220 public void startBundles(String bundlesToStartStr) {
221 if (bundlesToStartStr == null)
222 return;
223
224 StringTokenizer st = new StringTokenizer(bundlesToStartStr, ",");
225 List bundlesToStart = new ArrayList();
226 while (st.hasMoreTokens()) {
227 String name = st.nextToken().trim();
228 bundlesToStart.add(name);
229 }
230 startBundles(bundlesToStart);
231 }
232
233 public void startBundles(List bundlesToStart) {
234 if (bundlesToStart.size() == 0)
235 return;
236
237 // used to log the bundles not found
238 List notFoundBundles = new ArrayList(bundlesToStart);
239
240 Bundle[] bundles = bundleContext.getBundles();
241 long startBegin = System.currentTimeMillis();
242 for (int i = 0; i < bundles.length; i++) {
243 Bundle bundle = bundles[i];
244 String symbolicName = bundle.getSymbolicName();
245 if (bundlesToStart.contains(symbolicName))
246 try {
247 try {
248 bundle.start();
249 } catch (Exception e) {
250 warn("Start of bundle " + symbolicName
251 + " failed because of " + e
252 + ", maybe bundle is not yet resolved,"
253 + " waiting and trying again.");
254 waitForBundleResolvedOrActive(startBegin, bundle);
255 bundle.start();
256 }
257 notFoundBundles.remove(symbolicName);
258 } catch (Exception e) {
259 warn("Bundle " + symbolicName + " cannot be started: "
260 + e.getMessage());
261 if (debug)
262 e.printStackTrace();
263 // was found even if start failed
264 notFoundBundles.remove(symbolicName);
265 }
266 }
267
268 for (int i = 0; i < notFoundBundles.size(); i++)
269 warn("Bundle " + notFoundBundles.get(i)
270 + " not started because it was not found.");
271 }
272
273 protected void checkUnresolved() {
274 // Refresh
275 ServiceReference packageAdminRef = bundleContext
276 .getServiceReference(PackageAdmin.class.getName());
277 PackageAdmin packageAdmin = (PackageAdmin) bundleContext
278 .getService(packageAdminRef);
279 packageAdmin.resolveBundles(null);
280
281 Bundle[] bundles = bundleContext.getBundles();
282 List /* Bundle */unresolvedBundles = new ArrayList();
283 for (int i = 0; i < bundles.length; i++) {
284 int bundleState = bundles[i].getState();
285 if (!(bundleState == Bundle.ACTIVE
286 || bundleState == Bundle.RESOLVED || bundleState == Bundle.STARTING))
287 unresolvedBundles.add(bundles[i]);
288 }
289
290 if (unresolvedBundles.size() != 0) {
291 warn("Unresolved bundles " + unresolvedBundles);
292 }
293 }
294
295 protected void waitForBundleResolvedOrActive(long startBegin, Bundle bundle)
296 throws Exception {
297 int originalState = bundle.getState();
298 if ((originalState == Bundle.RESOLVED)
299 || (originalState == Bundle.ACTIVE))
300 return;
301
302 String originalStateStr = stateAsString(originalState);
303
304 int currentState = bundle.getState();
305 while (!(currentState == Bundle.RESOLVED || currentState == Bundle.ACTIVE)) {
306 long now = System.currentTimeMillis();
307 if ((now - startBegin) > defaultTimeout)
308 throw new Exception("Bundle " + bundle.getSymbolicName()
309 + " was not RESOLVED or ACTIVE after "
310 + (now - startBegin) + "ms (originalState="
311 + originalStateStr + ", currentState="
312 + stateAsString(currentState) + ")");
313
314 try {
315 Thread.sleep(100l);
316 } catch (InterruptedException e) {
317 // silent
318 }
319 currentState = bundle.getState();
320 }
321 }
322
323 public static String stateAsString(int state) {
324 switch (state) {
325 case Bundle.UNINSTALLED:
326 return "UNINSTALLED";
327 case Bundle.INSTALLED:
328 return "INSTALLED";
329 case Bundle.RESOLVED:
330 return "RESOLVED";
331 case Bundle.STARTING:
332 return "STARTING";
333 case Bundle.ACTIVE:
334 return "ACTIVE";
335 case Bundle.STOPPING:
336 return "STOPPING";
337 default:
338 return Integer.toString(state);
339 }
340 }
341
342 /** Key is location */
343 public Map getInstalledBundles() {
344 Map installedBundles = new HashMap();
345
346 Bundle[] bundles = bundleContext.getBundles();
347 for (int i = 0; i < bundles.length; i++) {
348 installedBundles.put(bundles[i].getLocation(), bundles[i]);
349 }
350 return installedBundles;
351 }
352
353 /** Key is symbolic name */
354 public Map getBundles() {
355 Map namedBundles = new HashMap();
356 Bundle[] bundles = bundleContext.getBundles();
357 for (int i = 0; i < bundles.length; i++) {
358 namedBundles.put(bundles[i].getSymbolicName(), bundles[i]);
359 }
360 return namedBundles;
361 }
362
363 public List getLocationsUrls() {
364 String baseUrl = getPropertyCompat(PROP_ARGEO_OSGI_BASE_URL,
365 PROP_SLC_OSGI_BASE_URL, DEFAULT_BASE_URL);
366 String bundleLocations = getPropertyCompat(PROP_ARGEO_OSGI_LOCATIONS,
367 PROP_SLC_OSGI_LOCATIONS);
368 return getLocationsUrls(baseUrl, bundleLocations);
369 }
370
371 public List getModulesUrls() {
372 List urls = new ArrayList();
373 String modulesUrlStr = getPropertyCompat(PROP_ARGEO_OSGI_MODULES_URL,
374 PROP_SLC_OSGI_MODULES_URL);
375 if (modulesUrlStr == null)
376 return urls;
377
378 String baseUrl = getPropertyCompat(PROP_ARGEO_OSGI_BASE_URL,
379 PROP_SLC_OSGI_BASE_URL);
380
381 Map installedBundles = getBundles();
382
383 BufferedReader reader = null;
384 try {
385 URL modulesUrl = new URL(modulesUrlStr);
386 reader = new BufferedReader(new InputStreamReader(modulesUrl
387 .openStream()));
388 String line = null;
389 while ((line = reader.readLine()) != null) {
390 StringTokenizer st = new StringTokenizer(line,
391 modulesUrlSeparator);
392 String moduleName = st.nextToken();
393 String moduleVersion = st.nextToken();
394 String url = st.nextToken();
395 if (baseUrl != null)
396 url = baseUrl + url;
397
398 if (installedBundles.containsKey(moduleName)) {
399 Bundle bundle = (Bundle) installedBundles.get(moduleName);
400 String bundleVersion = bundle.getHeaders().get(
401 Constants.BUNDLE_VERSION).toString();
402 int comp = compareVersions(bundleVersion, moduleVersion);
403 if (comp > 0) {
404 warn("Installed version " + bundleVersion
405 + " of bundle " + moduleName
406 + " is newer than provided version "
407 + moduleVersion);
408 } else if (comp < 0) {
409 urls.add(url);
410 info("Updated bundle " + moduleName + " with version "
411 + moduleVersion + " (old version was "
412 + bundleVersion + ")");
413 } else {
414 // do nothing
415 }
416 } else {
417 urls.add(url);
418 }
419 }
420 } catch (Exception e1) {
421 throw new RuntimeException("Cannot read url " + modulesUrlStr, e1);
422 } finally {
423 if (reader != null)
424 try {
425 reader.close();
426 } catch (IOException e) {
427 e.printStackTrace();
428 }
429 }
430 return urls;
431 }
432
433 /**
434 * @return ==0: versions are identical, <0: tested version is newer, >0:
435 * currentVersion is newer.
436 */
437 protected int compareVersions(String currentVersion, String testedVersion) {
438 List cToks = new ArrayList();
439 StringTokenizer cSt = new StringTokenizer(currentVersion, ".");
440 while (cSt.hasMoreTokens())
441 cToks.add(cSt.nextToken());
442 List tToks = new ArrayList();
443 StringTokenizer tSt = new StringTokenizer(currentVersion, ".");
444 while (tSt.hasMoreTokens())
445 tToks.add(tSt.nextToken());
446
447 int comp = 0;
448 comp: for (int i = 0; i < cToks.size(); i++) {
449 if (tToks.size() <= i) {
450 // equals until then, tested shorter
451 comp = 1;
452 break comp;
453 }
454
455 String c = (String) cToks.get(i);
456 String t = (String) tToks.get(i);
457
458 try {
459 int cInt = Integer.parseInt(c);
460 int tInt = Integer.parseInt(t);
461 if (cInt == tInt)
462 continue comp;
463 else {
464 comp = (cInt - tInt);
465 break comp;
466 }
467 } catch (NumberFormatException e) {
468 if (c.equals(t))
469 continue comp;
470 else {
471 comp = c.compareTo(t);
472 break comp;
473 }
474 }
475 }
476
477 if (comp == 0 && tToks.size() > cToks.size()) {
478 // equals until then, current shorter
479 comp = -1;
480 }
481
482 return comp;
483 }
484
485 public List getLocationsUrls(String baseUrl, String bundleLocations) {
486 List urls = new ArrayList();
487
488 if (bundleLocations == null)
489 return urls;
490 bundleLocations = SystemPropertyUtils
491 .resolvePlaceholders(bundleLocations);
492 if (debug)
493 debug(PROP_ARGEO_OSGI_LOCATIONS + "=" + bundleLocations);
494
495 StringTokenizer st = new StringTokenizer(bundleLocations,
496 File.pathSeparator);
497 while (st.hasMoreTokens()) {
498 urls.add(locationToUrl(baseUrl, st.nextToken().trim()));
499 }
500 return urls;
501 }
502
503 public List getBundlesUrls() {
504 String baseUrl = getPropertyCompat(PROP_ARGEO_OSGI_BASE_URL,
505 PROP_SLC_OSGI_BASE_URL, DEFAULT_BASE_URL);
506 String bundlePatterns = getPropertyCompat(PROP_ARGEO_OSGI_BUNDLES,
507 PROP_SLC_OSGI_BUNDLES);
508 return getBundlesUrls(baseUrl, bundlePatterns);
509 }
510
511 public List getBundlesUrls(String baseUrl, String bundlePatterns) {
512 List urls = new ArrayList();
513
514 List bundlesSets = new ArrayList();
515 if (bundlePatterns == null)
516 return urls;
517 bundlePatterns = SystemPropertyUtils
518 .resolvePlaceholders(bundlePatterns);
519 if (debug)
520 debug(PROP_ARGEO_OSGI_BUNDLES + "=" + bundlePatterns
521 + " (excludeSvn=" + excludeSvn + ")");
522
523 StringTokenizer st = new StringTokenizer(bundlePatterns, ",");
524 while (st.hasMoreTokens()) {
525 bundlesSets.add(new BundlesSet(st.nextToken()));
526 }
527
528 List included = new ArrayList();
529 PathMatcher matcher = new AntPathMatcher();
530 for (int i = 0; i < bundlesSets.size(); i++) {
531 BundlesSet bundlesSet = (BundlesSet) bundlesSets.get(i);
532 for (int j = 0; j < bundlesSet.getIncludes().size(); j++) {
533 String pattern = (String) bundlesSet.getIncludes().get(j);
534 match(matcher, included, bundlesSet.getDir(), null, pattern);
535 }
536 }
537
538 List excluded = new ArrayList();
539 for (int i = 0; i < bundlesSets.size(); i++) {
540 BundlesSet bundlesSet = (BundlesSet) bundlesSets.get(i);
541 for (int j = 0; j < bundlesSet.getExcludes().size(); j++) {
542 String pattern = (String) bundlesSet.getExcludes().get(j);
543 match(matcher, excluded, bundlesSet.getDir(), null, pattern);
544 }
545 }
546
547 for (int i = 0; i < included.size(); i++) {
548 String fullPath = (String) included.get(i);
549 if (!excluded.contains(fullPath))
550 urls.add(locationToUrl(baseUrl, fullPath));
551 }
552
553 return urls;
554 }
555
556 protected void match(PathMatcher matcher, List matched, String base,
557 String currentPath, String pattern) {
558 if (currentPath == null) {
559 // Init
560 File baseDir = new File(base.replace('/', File.separatorChar));
561 File[] files = baseDir.listFiles();
562
563 if (files == null) {
564 warn("Base dir " + baseDir + " has no children, exists="
565 + baseDir.exists() + ", isDirectory="
566 + baseDir.isDirectory());
567 return;
568 }
569
570 for (int i = 0; i < files.length; i++)
571 match(matcher, matched, base, files[i].getName(), pattern);
572 } else {
573 String fullPath = base + '/' + currentPath;
574 if (matched.contains(fullPath))
575 return;// don't try deeper if already matched
576
577 boolean ok = matcher.match(pattern, currentPath);
578 if (debug)
579 debug(currentPath + " " + (ok ? "" : " not ")
580 + " matched with " + pattern);
581 if (ok) {
582 matched.add(fullPath);
583 return;
584 } else {
585 String newFullPath = relativeToFullPath(base, currentPath);
586 File newFile = new File(newFullPath);
587 File[] files = newFile.listFiles();
588 if (files != null) {
589 for (int i = 0; i < files.length; i++) {
590 String newCurrentPath = currentPath + '/'
591 + files[i].getName();
592 if (files[i].isDirectory()) {
593 if (matcher.matchStart(pattern, newCurrentPath)) {
594 // recurse only if start matches
595 match(matcher, matched, base, newCurrentPath,
596 pattern);
597 } else {
598 if (debug)
599 debug(newCurrentPath
600 + " does not start match with "
601 + pattern);
602
603 }
604 } else {
605 boolean nonDirectoryOk = matcher.match(pattern,
606 newCurrentPath);
607 if (debug)
608 debug(currentPath + " " + (ok ? "" : " not ")
609 + " matched with " + pattern);
610 if (nonDirectoryOk)
611 matched.add(relativeToFullPath(base,
612 newCurrentPath));
613 }
614 }
615 }
616 }
617 }
618 }
619
620 protected String locationToUrl(String baseUrl, String location) {
621 int extInd = location.lastIndexOf('.');
622 String ext = null;
623 if (extInd > 0)
624 ext = location.substring(extInd);
625
626 if (baseUrl.startsWith("reference:") && ".jar".equals(ext))
627 return "file:" + location;
628 else
629 return baseUrl + location;
630 }
631
632 /** Transforms a relative path in a full system path. */
633 protected String relativeToFullPath(String basePath, String relativePath) {
634 return (basePath + '/' + relativePath).replace('/', File.separatorChar);
635 }
636
637 protected static void info(Object obj) {
638 System.out.println("# OSGiBOOT # " + obj);
639 }
640
641 protected void debug(Object obj) {
642 if (debug)
643 System.out.println("# OSGiBOOT DBG # " + obj);
644 }
645
646 protected void warn(Object obj) {
647 System.out.println("# OSGiBOOT WARN # " + obj);
648 // Because of a weird bug under Windows when starting it in a forked VM
649 // if (System.getProperty("os.name").contains("Windows"))
650 // System.out.println("# WARN " + obj);
651 // else
652 // System.err.println("# WARN " + obj);
653 }
654
655 protected String getProperty(String name, String defaultValue) {
656 final String value;
657 if (defaultValue != null)
658 value = System.getProperty(name, defaultValue);
659 else
660 value = System.getProperty(name);
661
662 if (value == null || value.equals(""))
663 return null;
664 else
665 return value;
666 }
667
668 protected String getProperty(String name) {
669 return getProperty(name, null);
670 }
671
672 protected String getPropertyCompat(String name, String oldName) {
673 return getPropertyCompat(name, oldName, null);
674 }
675
676 protected String getPropertyCompat(String name, String oldName,
677 String defaultValue) {
678 String res = null;
679
680 if (defaultValue != null) {
681 res = getProperty(name, defaultValue);
682 if (res.equals(defaultValue)) {
683 res = getProperty(oldName, defaultValue);
684 if (!res.equals(defaultValue))
685 warnDeprecated(name, oldName);
686 }
687 } else {
688 res = getProperty(name, null);
689 if (res == null) {
690 res = getProperty(oldName, null);
691 if (res != null)
692 warnDeprecated(name, oldName);
693 }
694 }
695 return res;
696 }
697
698 protected void warnDeprecated(String name, String oldName) {
699 warn("Property '" + oldName
700 + "' is deprecated and will be removed soon, use '" + name
701 + "' instead.");
702 }
703
704 public boolean getDebug() {
705 return debug;
706 }
707
708 public void setDebug(boolean debug) {
709 this.debug = debug;
710 }
711
712 public BundleContext getBundleContext() {
713 return bundleContext;
714 }
715
716 /** Whether to exclude Subversion directories (true by default) */
717 public boolean isExcludeSvn() {
718 return excludeSvn;
719 }
720
721 public void setExcludeSvn(boolean excludeSvn) {
722 this.excludeSvn = excludeSvn;
723 }
724
725 protected class BundlesSet {
726 private String baseUrl = "reference:file";// not used yet
727 private final String dir;
728 private List includes = new ArrayList();
729 private List excludes = new ArrayList();
730
731 public BundlesSet(String def) {
732 StringTokenizer st = new StringTokenizer(def, ";");
733
734 if (!st.hasMoreTokens())
735 throw new RuntimeException("Base dir not defined.");
736 try {
737 String dirPath = st.nextToken();
738
739 if (dirPath.startsWith("file:"))
740 dirPath = dirPath.substring("file:".length());
741
742 dir = new File(dirPath.replace('/', File.separatorChar))
743 .getCanonicalPath();
744 if (debug)
745 debug("Base dir: " + dir);
746 } catch (IOException e) {
747 throw new RuntimeException("Cannot convert to absolute path", e);
748 }
749
750 while (st.hasMoreTokens()) {
751 String tk = st.nextToken();
752 StringTokenizer stEq = new StringTokenizer(tk, "=");
753 String type = stEq.nextToken();
754 String pattern = stEq.nextToken();
755 if ("in".equals(type) || "include".equals(type)) {
756 includes.add(pattern);
757 } else if ("ex".equals(type) || "exclude".equals(type)) {
758 excludes.add(pattern);
759 } else if ("baseUrl".equals(type)) {
760 baseUrl = pattern;
761 } else {
762 System.err.println("Unkown bundles pattern type " + type);
763 }
764 }
765
766 if (excludeSvn && !excludes.contains(EXCLUDES_SVN_PATTERN)) {
767 excludes.add(EXCLUDES_SVN_PATTERN);
768 }
769 }
770
771 public String getDir() {
772 return dir;
773 }
774
775 public List getIncludes() {
776 return includes;
777 }
778
779 public List getExcludes() {
780 return excludes;
781 }
782
783 public String getBaseUrl() {
784 return baseUrl;
785 }
786
787 }
788
789 public void setDefaultTimeout(long defaultTimeout) {
790 this.defaultTimeout = defaultTimeout;
791 }
792
793 public void setModulesUrlSeparator(String modulesUrlSeparator) {
794 this.modulesUrlSeparator = modulesUrlSeparator;
795 }
796
797 }