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