2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org
.argeo
.osgi
.boot
;
19 import java
.io
.BufferedReader
;
21 import java
.io
.IOException
;
22 import java
.io
.InputStream
;
23 import java
.io
.InputStreamReader
;
25 import java
.util
.ArrayList
;
26 import java
.util
.HashMap
;
27 import java
.util
.Iterator
;
28 import java
.util
.List
;
31 import java
.util
.SortedMap
;
32 import java
.util
.StringTokenizer
;
33 import java
.util
.TreeMap
;
34 import java
.util
.TreeSet
;
36 import org
.argeo
.osgi
.boot
.internal
.springutil
.AntPathMatcher
;
37 import org
.argeo
.osgi
.boot
.internal
.springutil
.PathMatcher
;
38 import org
.argeo
.osgi
.boot
.internal
.springutil
.SystemPropertyUtils
;
39 import org
.osgi
.framework
.Bundle
;
40 import org
.osgi
.framework
.BundleContext
;
41 import org
.osgi
.framework
.BundleException
;
42 import org
.osgi
.framework
.Constants
;
43 import org
.osgi
.framework
.ServiceReference
;
44 import org
.osgi
.service
.packageadmin
.ExportedPackage
;
45 import org
.osgi
.service
.packageadmin
.PackageAdmin
;
47 /** Core component, performing basic provisioning of an OSGi runtime. */
48 public class OsgiBoot
{
49 public final static String SYMBOLIC_NAME_OSGI_BOOT
= "org.argeo.osgi.boot";
50 public final static String SYMBOLIC_NAME_EQUINOX
= "org.eclipse.osgi";
52 public final static String PROP_ARGEO_OSGI_DATA_DIR
= "argeo.osgi.data.dir";
54 public final static String PROP_ARGEO_OSGI_START
= "argeo.osgi.start";
55 public final static String PROP_ARGEO_OSGI_BUNDLES
= "argeo.osgi.bundles";
56 public final static String PROP_ARGEO_OSGI_LOCATIONS
= "argeo.osgi.locations";
57 public final static String PROP_ARGEO_OSGI_BASE_URL
= "argeo.osgi.baseUrl";
58 /** Use org.argeo.osgi */
59 public final static String PROP_ARGEO_OSGI_MODULES_URL
= "argeo.osgi.modulesUrl";
61 public final static String PROP_ARGEO_OSGI_BOOT_DEBUG
= "argeo.osgi.boot.debug";
62 public final static String PROP_ARGEO_OSGI_BOOT_INSTALL_IN_LEXICOGRAPHIC_ORDER
= "argeo.osgi.boot.installInLexicographicOrder";
63 public final static String PROP_ARGEO_OSGI_BOOT_DEFAULT_TIMEOUT
= "argeo.osgi.boot.defaultTimeout";
64 public final static String PROP_ARGEO_OSGI_BOOT_MODULES_URL_SEPARATOR
= "argeo.osgi.boot.modulesUrlSeparator";
65 public final static String PROP_ARGEO_OSGI_BOOT_SYSTEM_PROPERTIES_FILE
= "argeo.osgi.boot.systemPropertiesFile";
66 public final static String PROP_ARGEO_OSGI_BOOT_APPCLASS
= "argeo.osgi.boot.appclass";
67 public final static String PROP_ARGEO_OSGI_BOOT_APPARGS
= "argeo.osgi.boot.appargs";
69 public final static String DEFAULT_BASE_URL
= "reference:file:";
70 public final static String EXCLUDES_SVN_PATTERN
= "**/.svn/**";
72 private boolean debug
= Boolean
.valueOf(
73 System
.getProperty(PROP_ARGEO_OSGI_BOOT_DEBUG
, "false"))
77 * The {@link #installUrls(List)} methods won't follow the list order but
78 * order the urls according to teh alphabetical order of the file names
79 * (last part of the URL). The goal is to stay closer from Eclipse PDE way
80 * of installing target platform bundles.
82 private boolean installInLexicographicOrder
= Boolean
.valueOf(
83 System
.getProperty(PROP_ARGEO_OSGI_BOOT_DEBUG
, "true"))
86 /** Default is 10s (set in constructor) */
87 private long defaultTimeout
;
89 private boolean excludeSvn
= true;
90 /** Default is ',' (set in constructor) */
91 private String modulesUrlSeparator
= ",";
93 private final BundleContext bundleContext
;
95 public OsgiBoot(BundleContext bundleContext
) {
96 this.bundleContext
= bundleContext
;
97 defaultTimeout
= Long
.parseLong(OsgiBootUtils
.getProperty(
98 PROP_ARGEO_OSGI_BOOT_DEFAULT_TIMEOUT
, "10000"));
99 modulesUrlSeparator
= OsgiBootUtils
.getProperty(
100 PROP_ARGEO_OSGI_BOOT_MODULES_URL_SEPARATOR
, ",");
101 initSystemProperties();
104 protected void initSystemProperties() {
105 String osgiInstanceArea
= System
.getProperty("osgi.instance.area");
106 String osgiInstanceAreaDefault
= System
107 .getProperty("osgi.instance.area.default");
108 String tempDir
= System
.getProperty("java.io.tmpdir");
111 if (osgiInstanceArea
!= null) {
112 // within OSGi with -data specified
113 osgiInstanceArea
= removeFilePrefix(osgiInstanceArea
);
114 dataDir
= new File(osgiInstanceArea
);
115 } else if (osgiInstanceAreaDefault
!= null) {
116 // within OSGi without -data specified
117 osgiInstanceAreaDefault
= removeFilePrefix(osgiInstanceAreaDefault
);
118 dataDir
= new File(osgiInstanceAreaDefault
);
119 } else {// outside OSGi
120 dataDir
= new File(tempDir
+ File
.separator
+ "argeoOsgiData");
123 System
.setProperty(PROP_ARGEO_OSGI_DATA_DIR
, dataDir
.getAbsolutePath());
125 // TODO: Load additional system properties from file
126 // Properties additionalSystemProperties = new Properties();
130 /** Boot strap the OSGi runtime */
131 public void bootstrap() {
132 long begin
= System
.currentTimeMillis();
133 System
.out
.println();
134 OsgiBootUtils
.info("OSGi bootstrap starting...");
135 OsgiBootUtils
.info("Writable data directory : "
136 + System
.getProperty(PROP_ARGEO_OSGI_DATA_DIR
)
137 + " (set as system property " + PROP_ARGEO_OSGI_DATA_DIR
+ ")");
138 installUrls(getBundlesUrls());
139 installUrls(getLocationsUrls());
140 installUrls(getModulesUrls());
143 long duration
= System
.currentTimeMillis() - begin
;
144 OsgiBootUtils
.info("OSGi bootstrap completed in "
145 + Math
.round(((double) duration
) / 1000) + "s (" + duration
146 + "ms), " + bundleContext
.getBundles().length
+ " bundles");
148 // display packages exported twice
150 Map
/* <String,Set<String>> */duplicatePackages
= findPackagesExportedTwice();
151 if (duplicatePackages
.size() > 0) {
152 OsgiBootUtils
.info("Packages exported twice:");
153 Iterator it
= duplicatePackages
.keySet().iterator();
154 while (it
.hasNext()) {
155 String pkgName
= it
.next().toString();
156 OsgiBootUtils
.info(pkgName
);
157 Set bdles
= (Set
) duplicatePackages
.get(pkgName
);
158 Iterator bdlesIt
= bdles
.iterator();
159 while (bdlesIt
.hasNext())
160 OsgiBootUtils
.info(" " + bdlesIt
.next());
165 System
.out
.println();
168 /** Install the bundles at this URL list. */
169 public void installUrls(List urls
) {
170 Map installedBundles
= getInstalledBundles();
172 if (installInLexicographicOrder
) {
173 SortedMap map
= new TreeMap();
175 for (int i
= 0; i
< urls
.size(); i
++) {
176 String url
= (String
) urls
.get(i
);
177 int index
= url
.lastIndexOf('/');
180 fileName
= url
.substring(index
+ 1);
183 map
.put(fileName
, url
);
187 Iterator keys
= map
.keySet().iterator();
188 while (keys
.hasNext()) {
189 Object key
= keys
.next();
190 String url
= map
.get(key
).toString();
191 installUrl(url
, installedBundles
);
194 for (int i
= 0; i
< urls
.size(); i
++) {
195 String url
= (String
) urls
.get(i
);
196 installUrl(url
, installedBundles
);
202 protected void installUrl(String url
, Map installedBundles
) {
204 if (installedBundles
.containsKey(url
)) {
205 Bundle bundle
= (Bundle
) installedBundles
.get(url
);
208 debug("Bundle " + bundle
.getSymbolicName()
209 + " already installed from " + url
);
211 Bundle bundle
= bundleContext
.installBundle(url
);
213 debug("Installed bundle " + bundle
.getSymbolicName()
216 } catch (BundleException e
) {
217 String message
= e
.getMessage();
218 if ((message
.contains("Bundle \"" + SYMBOLIC_NAME_OSGI_BOOT
+ "\"") || message
219 .contains("Bundle \"" + SYMBOLIC_NAME_EQUINOX
+ "\""))
220 && message
.contains("has already been installed")) {
221 // silent, in order to avoid warnings: we know that both
222 // have already been installed...
224 OsgiBootUtils
.warn("Could not install bundle from " + url
232 /** @deprecated Doesn't seem to be used anymore. */
233 public void installOrUpdateUrls(Map urls
) {
234 Map installedBundles
= getBundles();
236 for (Iterator modules
= urls
.keySet().iterator(); modules
.hasNext();) {
237 String moduleName
= (String
) modules
.next();
238 String urlStr
= (String
) urls
.get(moduleName
);
239 if (installedBundles
.containsKey(moduleName
)) {
240 Bundle bundle
= (Bundle
) installedBundles
.get(moduleName
);
243 URL url
= new URL(urlStr
);
244 in
= url
.openStream();
246 OsgiBootUtils
.info("Updated bundle " + moduleName
247 + " from " + urlStr
);
248 } catch (Exception e
) {
249 throw new RuntimeException("Cannot update " + moduleName
250 + " from " + urlStr
);
255 } catch (IOException e
) {
260 Bundle bundle
= bundleContext
.installBundle(urlStr
);
262 debug("Installed bundle " + bundle
.getSymbolicName()
263 + " from " + urlStr
);
264 } catch (BundleException e
) {
265 OsgiBootUtils
.warn("Could not install bundle from "
266 + urlStr
+ ": " + e
.getMessage());
273 public void startBundles() {
274 String bundlesToStart
= OsgiBootUtils
275 .getProperty(PROP_ARGEO_OSGI_START
);
276 startBundles(bundlesToStart
);
279 public void startBundles(String bundlesToStartStr
) {
280 if (bundlesToStartStr
== null)
283 StringTokenizer st
= new StringTokenizer(bundlesToStartStr
, ",");
284 List bundlesToStart
= new ArrayList();
285 while (st
.hasMoreTokens()) {
286 String name
= st
.nextToken().trim();
287 bundlesToStart
.add(name
);
289 startBundles(bundlesToStart
);
292 public void startBundles(List bundlesToStart
) {
293 if (bundlesToStart
.size() == 0)
296 // used to log the bundles not found
297 List notFoundBundles
= new ArrayList(bundlesToStart
);
299 Bundle
[] bundles
= bundleContext
.getBundles();
300 long startBegin
= System
.currentTimeMillis();
301 for (int i
= 0; i
< bundles
.length
; i
++) {
302 Bundle bundle
= bundles
[i
];
303 String symbolicName
= bundle
.getSymbolicName();
304 if (bundlesToStart
.contains(symbolicName
))
309 debug("Bundle " + symbolicName
+ " started");
310 } catch (Exception e
) {
311 OsgiBootUtils
.warn("Start of bundle " + symbolicName
312 + " failed because of " + e
313 + ", maybe bundle is not yet resolved,"
314 + " waiting and trying again.");
315 waitForBundleResolvedOrActive(startBegin
, bundle
);
318 notFoundBundles
.remove(symbolicName
);
319 } catch (Exception e
) {
320 OsgiBootUtils
.warn("Bundle " + symbolicName
321 + " cannot be started: " + e
.getMessage());
324 // was found even if start failed
325 notFoundBundles
.remove(symbolicName
);
329 for (int i
= 0; i
< notFoundBundles
.size(); i
++)
330 OsgiBootUtils
.warn("Bundle " + notFoundBundles
.get(i
)
331 + " not started because it was not found.");
334 protected void checkUnresolved() {
336 ServiceReference packageAdminRef
= bundleContext
337 .getServiceReference(PackageAdmin
.class.getName());
338 PackageAdmin packageAdmin
= (PackageAdmin
) bundleContext
339 .getService(packageAdminRef
);
340 packageAdmin
.resolveBundles(null);
342 Bundle
[] bundles
= bundleContext
.getBundles();
343 List
/* Bundle */unresolvedBundles
= new ArrayList();
344 for (int i
= 0; i
< bundles
.length
; i
++) {
345 int bundleState
= bundles
[i
].getState();
346 if (!(bundleState
== Bundle
.ACTIVE
347 || bundleState
== Bundle
.RESOLVED
|| bundleState
== Bundle
.STARTING
))
348 unresolvedBundles
.add(bundles
[i
]);
351 if (unresolvedBundles
.size() != 0) {
352 OsgiBootUtils
.warn("Unresolved bundles " + unresolvedBundles
);
356 /** List packages exported twice. */
357 public Map
findPackagesExportedTwice() {
358 ServiceReference paSr
= bundleContext
359 .getServiceReference(PackageAdmin
.class.getName());
360 // TODO: make a cleaner referencing
361 PackageAdmin packageAdmin
= (PackageAdmin
) bundleContext
364 // find packages exported twice
365 Bundle
[] bundles
= bundleContext
.getBundles();
366 Map
/* <String,Set<String>> */exportedPackages
= new TreeMap();
367 for (int i
= 0; i
< bundles
.length
; i
++) {
368 Bundle bundle
= bundles
[i
];
369 ExportedPackage
[] pkgs
= packageAdmin
.getExportedPackages(bundle
);
371 for (int j
= 0; j
< pkgs
.length
; j
++) {
372 String pkgName
= pkgs
[j
].getName();
373 if (!exportedPackages
.containsKey(pkgName
)) {
374 exportedPackages
.put(pkgName
, new TreeSet());
376 ((Set
) exportedPackages
.get(pkgName
)).add(bundle
377 .getSymbolicName() + "_" + bundle
.getVersion());
380 Map
/* <String,Set<String>> */duplicatePackages
= new TreeMap();
381 Iterator it
= exportedPackages
.keySet().iterator();
382 while (it
.hasNext()) {
383 String pkgName
= it
.next().toString();
384 Set bdles
= (Set
) exportedPackages
.get(pkgName
);
385 if (bdles
.size() > 1)
386 duplicatePackages
.put(pkgName
, bdles
);
388 return duplicatePackages
;
391 protected void waitForBundleResolvedOrActive(long startBegin
, Bundle bundle
)
393 int originalState
= bundle
.getState();
394 if ((originalState
== Bundle
.RESOLVED
)
395 || (originalState
== Bundle
.ACTIVE
))
398 String originalStateStr
= stateAsString(originalState
);
400 int currentState
= bundle
.getState();
401 while (!(currentState
== Bundle
.RESOLVED
|| currentState
== Bundle
.ACTIVE
)) {
402 long now
= System
.currentTimeMillis();
403 if ((now
- startBegin
) > defaultTimeout
)
404 throw new Exception("Bundle " + bundle
.getSymbolicName()
405 + " was not RESOLVED or ACTIVE after "
406 + (now
- startBegin
) + "ms (originalState="
407 + originalStateStr
+ ", currentState="
408 + stateAsString(currentState
) + ")");
412 } catch (InterruptedException e
) {
415 currentState
= bundle
.getState();
419 public static String
stateAsString(int state
) {
421 case Bundle
.UNINSTALLED
:
422 return "UNINSTALLED";
423 case Bundle
.INSTALLED
:
425 case Bundle
.RESOLVED
:
427 case Bundle
.STARTING
:
431 case Bundle
.STOPPING
:
434 return Integer
.toString(state
);
438 /** Key is location */
439 public Map
getInstalledBundles() {
440 Map installedBundles
= new HashMap();
442 Bundle
[] bundles
= bundleContext
.getBundles();
443 for (int i
= 0; i
< bundles
.length
; i
++) {
444 installedBundles
.put(bundles
[i
].getLocation(), bundles
[i
]);
446 return installedBundles
;
449 /** Key is symbolic name */
450 public Map
getBundles() {
451 Map namedBundles
= new HashMap();
452 Bundle
[] bundles
= bundleContext
.getBundles();
453 for (int i
= 0; i
< bundles
.length
; i
++) {
454 namedBundles
.put(bundles
[i
].getSymbolicName(), bundles
[i
]);
459 public List
getLocationsUrls() {
460 String baseUrl
= OsgiBootUtils
.getProperty(PROP_ARGEO_OSGI_BASE_URL
,
462 String bundleLocations
= OsgiBootUtils
463 .getProperty(PROP_ARGEO_OSGI_LOCATIONS
);
464 return getLocationsUrls(baseUrl
, bundleLocations
);
467 public List
getModulesUrls() {
468 List urls
= new ArrayList();
469 String modulesUrlStr
= OsgiBootUtils
470 .getProperty(PROP_ARGEO_OSGI_MODULES_URL
);
471 if (modulesUrlStr
== null)
474 String baseUrl
= OsgiBootUtils
.getProperty(PROP_ARGEO_OSGI_BASE_URL
);
476 Map installedBundles
= getBundles();
478 BufferedReader reader
= null;
480 URL modulesUrl
= new URL(modulesUrlStr
);
481 reader
= new BufferedReader(new InputStreamReader(
482 modulesUrl
.openStream()));
484 while ((line
= reader
.readLine()) != null) {
485 StringTokenizer st
= new StringTokenizer(line
,
486 modulesUrlSeparator
);
487 String moduleName
= st
.nextToken();
488 String moduleVersion
= st
.nextToken();
489 String url
= st
.nextToken();
493 if (installedBundles
.containsKey(moduleName
)) {
494 Bundle bundle
= (Bundle
) installedBundles
.get(moduleName
);
495 String bundleVersion
= bundle
.getHeaders()
496 .get(Constants
.BUNDLE_VERSION
).toString();
497 int comp
= compareVersions(bundleVersion
, moduleVersion
);
499 OsgiBootUtils
.warn("Installed version " + bundleVersion
500 + " of bundle " + moduleName
501 + " is newer than provided version "
503 } else if (comp
< 0) {
505 OsgiBootUtils
.info("Updated bundle " + moduleName
506 + " with version " + moduleVersion
507 + " (old version was " + bundleVersion
+ ")");
515 } catch (Exception e1
) {
516 throw new RuntimeException("Cannot read url " + modulesUrlStr
, e1
);
521 } catch (IOException e
) {
529 * @return ==0: versions are identical, <0: tested version is newer, >0:
530 * currentVersion is newer.
532 protected int compareVersions(String currentVersion
, String testedVersion
) {
533 List cToks
= new ArrayList();
534 StringTokenizer cSt
= new StringTokenizer(currentVersion
, ".");
535 while (cSt
.hasMoreTokens())
536 cToks
.add(cSt
.nextToken());
537 List tToks
= new ArrayList();
538 StringTokenizer tSt
= new StringTokenizer(currentVersion
, ".");
539 while (tSt
.hasMoreTokens())
540 tToks
.add(tSt
.nextToken());
543 comp
: for (int i
= 0; i
< cToks
.size(); i
++) {
544 if (tToks
.size() <= i
) {
545 // equals until then, tested shorter
550 String c
= (String
) cToks
.get(i
);
551 String t
= (String
) tToks
.get(i
);
554 int cInt
= Integer
.parseInt(c
);
555 int tInt
= Integer
.parseInt(t
);
559 comp
= (cInt
- tInt
);
562 } catch (NumberFormatException e
) {
566 comp
= c
.compareTo(t
);
572 if (comp
== 0 && tToks
.size() > cToks
.size()) {
573 // equals until then, current shorter
580 public List
getLocationsUrls(String baseUrl
, String bundleLocations
) {
581 List urls
= new ArrayList();
583 if (bundleLocations
== null)
585 bundleLocations
= SystemPropertyUtils
586 .resolvePlaceholders(bundleLocations
);
588 debug(PROP_ARGEO_OSGI_LOCATIONS
+ "=" + bundleLocations
);
590 StringTokenizer st
= new StringTokenizer(bundleLocations
,
592 while (st
.hasMoreTokens()) {
593 urls
.add(locationToUrl(baseUrl
, st
.nextToken().trim()));
598 public List
getBundlesUrls() {
599 String baseUrl
= OsgiBootUtils
.getProperty(PROP_ARGEO_OSGI_BASE_URL
,
601 String bundlePatterns
= OsgiBootUtils
602 .getProperty(PROP_ARGEO_OSGI_BUNDLES
);
603 return getBundlesUrls(baseUrl
, bundlePatterns
);
606 public List
getBundlesUrls(String baseUrl
, String bundlePatterns
) {
607 List urls
= new ArrayList();
609 List bundlesSets
= new ArrayList();
610 if (bundlePatterns
== null)
612 bundlePatterns
= SystemPropertyUtils
613 .resolvePlaceholders(bundlePatterns
);
615 debug(PROP_ARGEO_OSGI_BUNDLES
+ "=" + bundlePatterns
616 + " (excludeSvn=" + excludeSvn
+ ")");
618 StringTokenizer st
= new StringTokenizer(bundlePatterns
, ",");
619 while (st
.hasMoreTokens()) {
620 bundlesSets
.add(new BundlesSet(st
.nextToken()));
623 List included
= new ArrayList();
624 PathMatcher matcher
= new AntPathMatcher();
625 for (int i
= 0; i
< bundlesSets
.size(); i
++) {
626 BundlesSet bundlesSet
= (BundlesSet
) bundlesSets
.get(i
);
627 for (int j
= 0; j
< bundlesSet
.getIncludes().size(); j
++) {
628 String pattern
= (String
) bundlesSet
.getIncludes().get(j
);
629 match(matcher
, included
, bundlesSet
.getDir(), null, pattern
);
633 List excluded
= new ArrayList();
634 for (int i
= 0; i
< bundlesSets
.size(); i
++) {
635 BundlesSet bundlesSet
= (BundlesSet
) bundlesSets
.get(i
);
636 for (int j
= 0; j
< bundlesSet
.getExcludes().size(); j
++) {
637 String pattern
= (String
) bundlesSet
.getExcludes().get(j
);
638 match(matcher
, excluded
, bundlesSet
.getDir(), null, pattern
);
642 for (int i
= 0; i
< included
.size(); i
++) {
643 String fullPath
= (String
) included
.get(i
);
644 if (!excluded
.contains(fullPath
))
645 urls
.add(locationToUrl(baseUrl
, fullPath
));
652 * HIGH LEVEL UTILITIES
655 protected void match(PathMatcher matcher
, List matched
, String base
,
656 String currentPath
, String pattern
) {
657 if (currentPath
== null) {
659 File baseDir
= new File(base
.replace('/', File
.separatorChar
));
660 File
[] files
= baseDir
.listFiles();
663 OsgiBootUtils
.warn("Base dir " + baseDir
664 + " has no children, exists=" + baseDir
.exists()
665 + ", isDirectory=" + baseDir
.isDirectory());
669 for (int i
= 0; i
< files
.length
; i
++)
670 match(matcher
, matched
, base
, files
[i
].getName(), pattern
);
672 String fullPath
= base
+ '/' + currentPath
;
673 if (matched
.contains(fullPath
))
674 return;// don't try deeper if already matched
676 boolean ok
= matcher
.match(pattern
, currentPath
);
678 // debug(currentPath + " " + (ok ? "" : " not ")
679 // + " matched with " + pattern);
681 matched
.add(fullPath
);
684 String newFullPath
= relativeToFullPath(base
, currentPath
);
685 File newFile
= new File(newFullPath
);
686 File
[] files
= newFile
.listFiles();
688 for (int i
= 0; i
< files
.length
; i
++) {
689 String newCurrentPath
= currentPath
+ '/'
690 + files
[i
].getName();
691 if (files
[i
].isDirectory()) {
692 if (matcher
.matchStart(pattern
, newCurrentPath
)) {
693 // recurse only if start matches
694 match(matcher
, matched
, base
, newCurrentPath
,
699 + " does not start match with "
704 boolean nonDirectoryOk
= matcher
.match(pattern
,
707 debug(currentPath
+ " " + (ok ?
"" : " not ")
708 + " matched with " + pattern
);
710 matched
.add(relativeToFullPath(base
,
720 * LOW LEVEL UTILITIES
723 /** Creates an URL from a location */
724 protected String
locationToUrl(String baseUrl
, String location
) {
725 int extInd
= location
.lastIndexOf('.');
728 ext
= location
.substring(extInd
);
730 if (baseUrl
.startsWith("reference:") && ".jar".equals(ext
))
731 return "file:" + location
;
733 return baseUrl
+ location
;
736 /** Transforms a relative path in a full system path. */
737 protected String
relativeToFullPath(String basePath
, String relativePath
) {
738 return (basePath
+ '/' + relativePath
).replace('/', File
.separatorChar
);
741 private String
removeFilePrefix(String url
) {
742 if (url
.startsWith("file:"))
743 return url
.substring("file:".length());
744 else if (url
.startsWith("reference:file:"))
745 return url
.substring("reference:file:".length());
750 protected void debug(Object obj
) {
752 OsgiBootUtils
.debug(obj
);
755 public boolean getDebug() {
759 public void setDebug(boolean debug
) {
763 public BundleContext
getBundleContext() {
764 return bundleContext
;
767 public void setInstallInLexicographicOrder(
768 boolean installInAlphabeticalOrder
) {
769 this.installInLexicographicOrder
= installInAlphabeticalOrder
;
772 public boolean isInstallInLexicographicOrder() {
773 return installInLexicographicOrder
;
776 /** Whether to exclude Subversion directories (true by default) */
777 public boolean isExcludeSvn() {
781 public void setExcludeSvn(boolean excludeSvn
) {
782 this.excludeSvn
= excludeSvn
;
785 protected class BundlesSet
{
786 private String baseUrl
= "reference:file";// not used yet
787 private final String dir
;
788 private List includes
= new ArrayList();
789 private List excludes
= new ArrayList();
791 public BundlesSet(String def
) {
792 StringTokenizer st
= new StringTokenizer(def
, ";");
794 if (!st
.hasMoreTokens())
795 throw new RuntimeException("Base dir not defined.");
797 String dirPath
= st
.nextToken();
799 if (dirPath
.startsWith("file:"))
800 dirPath
= dirPath
.substring("file:".length());
802 dir
= new File(dirPath
.replace('/', File
.separatorChar
))
805 debug("Base dir: " + dir
);
806 } catch (IOException e
) {
807 throw new RuntimeException("Cannot convert to absolute path", e
);
810 while (st
.hasMoreTokens()) {
811 String tk
= st
.nextToken();
812 StringTokenizer stEq
= new StringTokenizer(tk
, "=");
813 String type
= stEq
.nextToken();
814 String pattern
= stEq
.nextToken();
815 if ("in".equals(type
) || "include".equals(type
)) {
816 includes
.add(pattern
);
817 } else if ("ex".equals(type
) || "exclude".equals(type
)) {
818 excludes
.add(pattern
);
819 } else if ("baseUrl".equals(type
)) {
822 System
.err
.println("Unkown bundles pattern type " + type
);
826 if (excludeSvn
&& !excludes
.contains(EXCLUDES_SVN_PATTERN
)) {
827 excludes
.add(EXCLUDES_SVN_PATTERN
);
831 public String
getDir() {
835 public List
getIncludes() {
839 public List
getExcludes() {
843 public String
getBaseUrl() {
849 public void setDefaultTimeout(long defaultTimeout
) {
850 this.defaultTimeout
= defaultTimeout
;
853 public void setModulesUrlSeparator(String modulesUrlSeparator
) {
854 this.modulesUrlSeparator
= modulesUrlSeparator
;