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