1 package org
.argeo
.init
.osgi
;
3 import static org
.argeo
.init
.osgi
.OsgiBootUtils
.debug
;
4 import static org
.argeo
.init
.osgi
.OsgiBootUtils
.warn
;
7 import java
.nio
.file
.FileSystems
;
8 import java
.nio
.file
.Files
;
9 import java
.nio
.file
.Path
;
10 import java
.nio
.file
.PathMatcher
;
11 import java
.nio
.file
.Paths
;
12 import java
.util
.ArrayList
;
13 import java
.util
.HashMap
;
14 import java
.util
.Iterator
;
15 import java
.util
.List
;
17 import java
.util
.Properties
;
19 import java
.util
.SortedMap
;
20 import java
.util
.StringTokenizer
;
21 import java
.util
.TreeMap
;
23 import org
.argeo
.init
.a2
.A2Source
;
24 import org
.argeo
.init
.a2
.ProvisioningManager
;
25 import org
.osgi
.framework
.Bundle
;
26 import org
.osgi
.framework
.BundleContext
;
27 import org
.osgi
.framework
.BundleException
;
28 import org
.osgi
.framework
.FrameworkEvent
;
29 import org
.osgi
.framework
.Version
;
30 import org
.osgi
.framework
.startlevel
.BundleStartLevel
;
31 import org
.osgi
.framework
.startlevel
.FrameworkStartLevel
;
32 import org
.osgi
.framework
.wiring
.FrameworkWiring
;
35 * Basic provisioning of an OSGi runtime via file path patterns and system
36 * properties. The approach is to generate list of URLs based on various
37 * methods, configured via properties.
39 public class OsgiBoot
implements OsgiBootConstants
{
40 public final static String PROP_ARGEO_OSGI_START
= "argeo.osgi.start";
41 public final static String PROP_ARGEO_OSGI_SOURCES
= "argeo.osgi.sources";
43 public final static String PROP_ARGEO_OSGI_BUNDLES
= "argeo.osgi.bundles";
44 public final static String PROP_ARGEO_OSGI_BASE_URL
= "argeo.osgi.baseUrl";
45 public final static String PROP_ARGEO_OSGI_LOCAL_CACHE
= "argeo.osgi.localCache";
46 public final static String PROP_ARGEO_OSGI_DISTRIBUTION_URL
= "argeo.osgi.distributionUrl";
49 public final static String PROP_ARGEO_OSGI_BOOT_DEBUG
= "argeo.osgi.boot.debug";
50 // public final static String PROP_ARGEO_OSGI_BOOT_EXCLUDE_SVN =
51 // "argeo.osgi.boot.excludeSvn";
53 public final static String PROP_ARGEO_OSGI_BOOT_SYSTEM_PROPERTIES_FILE
= "argeo.osgi.boot.systemPropertiesFile";
54 public final static String PROP_ARGEO_OSGI_BOOT_APPCLASS
= "argeo.osgi.boot.appclass";
55 public final static String PROP_ARGEO_OSGI_BOOT_APPARGS
= "argeo.osgi.boot.appargs";
57 public final static String DEFAULT_BASE_URL
= "reference:file:";
58 // public final static String EXCLUDES_SVN_PATTERN = "**/.svn/**";
60 // OSGi system properties
61 final static String PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL
= "osgi.bundles.defaultStartLevel";
62 final static String PROP_OSGI_STARTLEVEL
= "osgi.startLevel";
63 final static String INSTANCE_AREA_PROP
= "osgi.instance.area";
64 final static String CONFIGURATION_AREA_PROP
= "osgi.configuration.area";
67 public final static String SYMBOLIC_NAME_OSGI_BOOT
= "org.argeo.osgi.boot";
68 public final static String SYMBOLIC_NAME_EQUINOX
= "org.eclipse.osgi";
70 /** Exclude svn metadata implicitely(a bit costly) */
71 // private boolean excludeSvn =
72 // Boolean.valueOf(System.getProperty(PROP_ARGEO_OSGI_BOOT_EXCLUDE_SVN,
78 private long defaultTimeout
= 10000l;
80 private final BundleContext bundleContext
;
81 private final String localCache
;
83 private final ProvisioningManager provisioningManager
;
89 public OsgiBoot(BundleContext bundleContext
) {
90 this.bundleContext
= bundleContext
;
91 Path homePath
= Paths
.get(System
.getProperty("user.home")).toAbsolutePath();
92 String homeUri
= homePath
.toUri().toString();
93 localCache
= getProperty(PROP_ARGEO_OSGI_LOCAL_CACHE
, homeUri
+ ".m2/repository/");
95 provisioningManager
= new ProvisioningManager(bundleContext
);
96 String sources
= getProperty(PROP_ARGEO_OSGI_SOURCES
);
97 if (sources
== null) {
98 provisioningManager
.registerDefaultSource();
100 for (String source
: sources
.split(",")) {
101 if (source
.trim().equals(A2Source
.DEFAULT_A2_URI
)) {
102 if (Files
.exists(homePath
))
103 provisioningManager
.registerSource(
104 A2Source
.SCHEME_A2
+ "://" + homePath
.toString() + "/.local/share/a2");
105 provisioningManager
.registerSource(A2Source
.SCHEME_A2
+ ":///usr/local/share/a2");
106 provisioningManager
.registerSource(A2Source
.SCHEME_A2
+ ":///usr/share/a2");
108 provisioningManager
.registerSource(source
);
114 ProvisioningManager
getProvisioningManager() {
115 return provisioningManager
;
121 /** Bootstraps the OSGi runtime */
122 public void bootstrap() {
124 long begin
= System
.currentTimeMillis();
125 System
.out
.println();
126 String osgiInstancePath
= bundleContext
.getProperty(INSTANCE_AREA_PROP
);
128 .info("OSGi bootstrap starting" + (osgiInstancePath
!= null ?
" (" + osgiInstancePath
+ ")" : ""));
129 installUrls(getBundlesUrls());
130 installUrls(getDistributionUrls());
131 provisioningManager
.install(null);
133 long duration
= System
.currentTimeMillis() - begin
;
134 OsgiBootUtils
.info("OSGi bootstrap completed in " + Math
.round(((double) duration
) / 1000) + "s ("
135 + duration
+ "ms), " + bundleContext
.getBundles().length
+ " bundles");
136 } catch (RuntimeException e
) {
137 OsgiBootUtils
.error("OSGi bootstrap FAILED", e
);
142 if (OsgiBootUtils
.debug
) {
143 OsgiBootDiagnostics diagnostics
= new OsgiBootDiagnostics(bundleContext
);
144 diagnostics
.checkUnresolved();
145 Map
<String
, Set
<String
>> duplicatePackages
= diagnostics
.findPackagesExportedTwice();
146 if (duplicatePackages
.size() > 0) {
147 OsgiBootUtils
.info("Packages exported twice:");
148 Iterator
<String
> it
= duplicatePackages
.keySet().iterator();
149 while (it
.hasNext()) {
150 String pkgName
= it
.next();
151 OsgiBootUtils
.info(pkgName
);
152 Set
<String
> bdles
= duplicatePackages
.get(pkgName
);
153 Iterator
<String
> bdlesIt
= bdles
.iterator();
154 while (bdlesIt
.hasNext())
155 OsgiBootUtils
.info(" " + bdlesIt
.next());
159 System
.out
.println();
162 public void update() {
163 provisioningManager
.update();
169 /** Install a single url. Convenience method. */
170 public Bundle
installUrl(String url
) {
171 List
<String
> urls
= new ArrayList
<String
>();
174 return (Bundle
) getBundlesByLocation().get(url
);
177 /** Install the bundles at this URL list. */
178 public void installUrls(List
<String
> urls
) {
179 Map
<String
, Bundle
> installedBundles
= getBundlesByLocation();
180 for (int i
= 0; i
< urls
.size(); i
++) {
181 String url
= (String
) urls
.get(i
);
182 installUrl(url
, installedBundles
);
187 /** Actually install the provided URL */
188 protected void installUrl(String url
, Map
<String
, Bundle
> installedBundles
) {
190 if (installedBundles
.containsKey(url
)) {
191 Bundle bundle
= (Bundle
) installedBundles
.get(url
);
192 if (OsgiBootUtils
.debug
)
193 debug("Bundle " + bundle
.getSymbolicName() + " already installed from " + url
);
194 } else if (url
.contains("/" + SYMBOLIC_NAME_EQUINOX
+ "/")
195 || url
.contains("/" + SYMBOLIC_NAME_OSGI_BOOT
+ "/")) {
196 if (OsgiBootUtils
.debug
)
200 Bundle bundle
= bundleContext
.installBundle(url
);
201 if (url
.startsWith("http"))
203 .info("Installed " + bundle
.getSymbolicName() + "-" + bundle
.getVersion() + " from " + url
);
204 else if (OsgiBootUtils
.debug
)
206 "Installed " + bundle
.getSymbolicName() + "-" + bundle
.getVersion() + " from " + url
);
207 assert bundle
.getSymbolicName() != null;
208 // uninstall previous versions
209 bundles
: for (Bundle b
: bundleContext
.getBundles()) {
210 if (b
.getSymbolicName() == null)
212 if (bundle
.getSymbolicName().equals(b
.getSymbolicName())) {
213 Version bundleV
= bundle
.getVersion();
214 Version bV
= b
.getVersion();
217 if (bundleV
.getMajor() == bV
.getMajor() && bundleV
.getMinor() == bV
.getMinor()) {
218 if (bundleV
.getMicro() > bV
.getMicro()) {
219 // uninstall older bundles
221 OsgiBootUtils
.debug("Uninstalled " + b
);
222 } else if (bundleV
.getMicro() < bV
.getMicro()) {
223 // uninstall just installed bundle if newer
225 OsgiBootUtils
.debug("Uninstalled " + bundle
);
228 // uninstall any other with same major/minor
229 if (!bundleV
.getQualifier().equals(bV
.getQualifier())) {
231 OsgiBootUtils
.debug("Uninstalled " + b
);
238 } catch (BundleException e
) {
239 final String ALREADY_INSTALLED
= "is already installed";
240 String message
= e
.getMessage();
241 if ((message
.contains("Bundle \"" + SYMBOLIC_NAME_OSGI_BOOT
+ "\"")
242 || message
.contains("Bundle \"" + SYMBOLIC_NAME_EQUINOX
+ "\""))
243 && message
.contains(ALREADY_INSTALLED
)) {
244 // silent, in order to avoid warnings: we know that both
245 // have already been installed...
247 if (message
.contains(ALREADY_INSTALLED
)) {
248 if (OsgiBootUtils
.isDebug())
249 OsgiBootUtils
.warn("Duplicate install from " + url
+ ": " + message
);
251 OsgiBootUtils
.warn("Could not install bundle from " + url
+ ": " + message
);
253 if (OsgiBootUtils
.debug
&& !message
.contains(ALREADY_INSTALLED
))
261 public void startBundles() {
262 startBundles(System
.getProperties());
265 public void startBundles(Properties properties
) {
266 FrameworkStartLevel frameworkStartLevel
= bundleContext
.getBundle(0).adapt(FrameworkStartLevel
.class);
268 // default and active start levels from System properties
269 Integer defaultStartLevel
= Integer
.parseInt(getProperty(PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL
, "4"));
270 Integer activeStartLevel
= Integer
.parseInt(getProperty(PROP_OSGI_STARTLEVEL
, "6"));
272 SortedMap
<Integer
, List
<String
>> startLevels
= new TreeMap
<Integer
, List
<String
>>();
273 computeStartLevels(startLevels
, properties
, defaultStartLevel
);
274 // inverts the map for the time being, TODO optimise
275 Map
<String
, Integer
> bundleStartLevels
= new HashMap
<>();
276 for (Integer level
: startLevels
.keySet()) {
277 for (String bsn
: startLevels
.get(level
))
278 bundleStartLevels
.put(bsn
, level
);
280 for (Bundle bundle
: bundleContext
.getBundles()) {
281 String bsn
= bundle
.getSymbolicName();
282 if (bundleStartLevels
.containsKey(bsn
)) {
283 BundleStartLevel bundleStartLevel
= bundle
.adapt(BundleStartLevel
.class);
284 Integer level
= bundleStartLevels
.get(bsn
);
285 if (bundleStartLevel
.getStartLevel() != level
|| !bundleStartLevel
.isPersistentlyStarted()) {
286 bundleStartLevel
.setStartLevel(level
);
289 } catch (BundleException e
) {
290 OsgiBootUtils
.error("Cannot mark " + bsn
+ " as started", e
);
293 OsgiBootUtils
.debug(bsn
+ " starts at level " + level
);
297 frameworkStartLevel
.setStartLevel(activeStartLevel
, (FrameworkEvent event
) -> {
299 OsgiBootUtils
.debug("Framework event: " + event
);
300 int initialStartLevel
= frameworkStartLevel
.getInitialBundleStartLevel();
301 int startLevel
= frameworkStartLevel
.getStartLevel();
302 OsgiBootUtils
.debug("Framework start level: " + startLevel
+ " (initial: " + initialStartLevel
+ ")");
306 private static void computeStartLevels(SortedMap
<Integer
, List
<String
>> startLevels
, Properties properties
,
307 Integer defaultStartLevel
) {
309 // default (and previously, only behaviour)
310 appendToStartLevels(startLevels
, defaultStartLevel
, properties
.getProperty(PROP_ARGEO_OSGI_START
, ""));
312 // list argeo.osgi.start.* system properties
313 Iterator
<Object
> keys
= properties
.keySet().iterator();
314 final String prefix
= PROP_ARGEO_OSGI_START
+ ".";
315 while (keys
.hasNext()) {
316 String key
= keys
.next().toString();
317 if (key
.startsWith(prefix
)) {
319 String suffix
= key
.substring(prefix
.length());
320 String
[] tokens
= suffix
.split("\\.");
321 if (tokens
.length
> 0 && !tokens
[0].trim().equals(""))
323 // first token is start level
324 startLevel
= Integer
.parseInt(tokens
[0]);
325 } catch (NumberFormatException e
) {
326 startLevel
= defaultStartLevel
;
329 startLevel
= defaultStartLevel
;
331 // append bundle names
332 String bundleNames
= properties
.getProperty(key
);
333 appendToStartLevels(startLevels
, startLevel
, bundleNames
);
338 /** Append a comma-separated list of bundles to the start levels. */
339 private static void appendToStartLevels(SortedMap
<Integer
, List
<String
>> startLevels
, Integer startLevel
,
341 if (str
== null || str
.trim().equals(""))
344 if (!startLevels
.containsKey(startLevel
))
345 startLevels
.put(startLevel
, new ArrayList
<String
>());
346 String
[] bundleNames
= str
.split(",");
347 for (int i
= 0; i
< bundleNames
.length
; i
++) {
348 if (bundleNames
[i
] != null && !bundleNames
[i
].trim().equals(""))
349 (startLevels
.get(startLevel
)).add(bundleNames
[i
]);
354 * Start the provided list of bundles
356 * @return whether all bundles are now in active state
360 public boolean startBundles(List
<String
> bundlesToStart
) {
361 if (bundlesToStart
.size() == 0)
364 // used to monitor ACTIVE states
365 List
<Bundle
> startedBundles
= new ArrayList
<Bundle
>();
366 // used to log the bundles not found
367 List
<String
> notFoundBundles
= new ArrayList
<String
>(bundlesToStart
);
369 Bundle
[] bundles
= bundleContext
.getBundles();
370 long startBegin
= System
.currentTimeMillis();
371 for (int i
= 0; i
< bundles
.length
; i
++) {
372 Bundle bundle
= bundles
[i
];
373 String symbolicName
= bundle
.getSymbolicName();
374 if (bundlesToStart
.contains(symbolicName
))
378 if (OsgiBootUtils
.debug
)
379 debug("Bundle " + symbolicName
+ " started");
380 } catch (Exception e
) {
381 OsgiBootUtils
.warn("Start of bundle " + symbolicName
+ " failed because of " + e
382 + ", maybe bundle is not yet resolved," + " waiting and trying again.");
383 waitForBundleResolvedOrActive(startBegin
, bundle
);
385 startedBundles
.add(bundle
);
387 notFoundBundles
.remove(symbolicName
);
388 } catch (Exception e
) {
389 OsgiBootUtils
.warn("Bundle " + symbolicName
+ " cannot be started: " + e
.getMessage());
390 if (OsgiBootUtils
.debug
)
392 // was found even if start failed
393 notFoundBundles
.remove(symbolicName
);
397 for (int i
= 0; i
< notFoundBundles
.size(); i
++)
398 OsgiBootUtils
.warn("Bundle '" + notFoundBundles
.get(i
) + "' not started because it was not found.");
400 // monitors that all bundles are started
401 long beginMonitor
= System
.currentTimeMillis();
402 boolean allStarted
= !(startedBundles
.size() > 0);
403 List
<String
> notStarted
= new ArrayList
<String
>();
404 while (!allStarted
&& (System
.currentTimeMillis() - beginMonitor
) < defaultTimeout
) {
405 notStarted
= new ArrayList
<String
>();
407 for (int i
= 0; i
< startedBundles
.size(); i
++) {
408 Bundle bundle
= (Bundle
) startedBundles
.get(i
);
409 // TODO check behaviour of lazs bundles
410 if (bundle
.getState() != Bundle
.ACTIVE
) {
412 notStarted
.add(bundle
.getSymbolicName());
417 } catch (InterruptedException e
) {
421 long duration
= System
.currentTimeMillis() - beginMonitor
;
424 for (int i
= 0; i
< notStarted
.size(); i
++)
425 OsgiBootUtils
.warn("Bundle '" + notStarted
.get(i
) + "' not ACTIVE after " + (duration
/ 1000) + "s");
430 /** Waits for a bundle to become active or resolved */
432 private void waitForBundleResolvedOrActive(long startBegin
, Bundle bundle
) throws Exception
{
433 int originalState
= bundle
.getState();
434 if ((originalState
== Bundle
.RESOLVED
) || (originalState
== Bundle
.ACTIVE
))
437 String originalStateStr
= OsgiBootUtils
.stateAsString(originalState
);
439 int currentState
= bundle
.getState();
440 while (!(currentState
== Bundle
.RESOLVED
|| currentState
== Bundle
.ACTIVE
)) {
441 long now
= System
.currentTimeMillis();
442 if ((now
- startBegin
) > defaultTimeout
* 10)
443 throw new Exception("Bundle " + bundle
.getSymbolicName() + " was not RESOLVED or ACTIVE after "
444 + (now
- startBegin
) + "ms (originalState=" + originalStateStr
+ ", currentState="
445 + OsgiBootUtils
.stateAsString(currentState
) + ")");
449 } catch (InterruptedException e
) {
452 currentState
= bundle
.getState();
457 * BUNDLE PATTERNS INSTALLATION
460 * Computes a list of URLs based on Ant-like include/exclude patterns defined by
461 * ${argeo.osgi.bundles} with the following format:<br>
462 * <code>/base/directory;in=*.jar;in=**;ex=org.eclipse.osgi_*;jar</code><br>
463 * WARNING: <code>/base/directory;in=*.jar,\</code> at the end of a file,
464 * without a new line causes a '.' to be appended with unexpected side effects.
466 public List
<String
> getBundlesUrls() {
467 String bundlePatterns
= getProperty(PROP_ARGEO_OSGI_BUNDLES
);
468 return getBundlesUrls(bundlePatterns
);
472 * Compute a list of URLs to install based on the provided patterns, with
475 public List
<String
> getBundlesUrls(String bundlePatterns
) {
476 String baseUrl
= getProperty(PROP_ARGEO_OSGI_BASE_URL
, DEFAULT_BASE_URL
);
477 return getBundlesUrls(baseUrl
, bundlePatterns
);
480 /** Implements the path matching logic */
481 public List
<String
> getBundlesUrls(String baseUrl
, String bundlePatterns
) {
482 List
<String
> urls
= new ArrayList
<String
>();
483 if (bundlePatterns
== null)
486 // bundlePatterns = SystemPropertyUtils.resolvePlaceholders(bundlePatterns);
487 if (OsgiBootUtils
.debug
)
488 debug(PROP_ARGEO_OSGI_BUNDLES
+ "=" + bundlePatterns
);
490 StringTokenizer st
= new StringTokenizer(bundlePatterns
, ",");
491 List
<BundlesSet
> bundlesSets
= new ArrayList
<BundlesSet
>();
492 while (st
.hasMoreTokens()) {
493 String token
= st
.nextToken();
494 if (new File(token
).exists()) {
495 String url
= locationToUrl(baseUrl
, token
);
498 bundlesSets
.add(new BundlesSet(token
));
502 List
<String
> included
= new ArrayList
<String
>();
503 // PathMatcher matcher = new AntPathMatcher();
504 for (int i
= 0; i
< bundlesSets
.size(); i
++) {
505 BundlesSet bundlesSet
= (BundlesSet
) bundlesSets
.get(i
);
506 for (int j
= 0; j
< bundlesSet
.getIncludes().size(); j
++) {
507 String pattern
= (String
) bundlesSet
.getIncludes().get(j
);
508 match(included
, bundlesSet
.getDir(), null, pattern
);
513 List
<String
> excluded
= new ArrayList
<String
>();
514 for (int i
= 0; i
< bundlesSets
.size(); i
++) {
515 BundlesSet bundlesSet
= (BundlesSet
) bundlesSets
.get(i
);
516 for (int j
= 0; j
< bundlesSet
.getExcludes().size(); j
++) {
517 String pattern
= (String
) bundlesSet
.getExcludes().get(j
);
518 match(excluded
, bundlesSet
.getDir(), null, pattern
);
523 for (int i
= 0; i
< included
.size(); i
++) {
524 String fullPath
= (String
) included
.get(i
);
525 if (!excluded
.contains(fullPath
))
526 urls
.add(locationToUrl(baseUrl
, fullPath
));
533 * DISTRIBUTION JAR INSTALLATION
535 public List
<String
> getDistributionUrls() {
536 String distributionUrl
= getProperty(PROP_ARGEO_OSGI_DISTRIBUTION_URL
);
537 String baseUrl
= getProperty(PROP_ARGEO_OSGI_BASE_URL
);
538 return getDistributionUrls(distributionUrl
, baseUrl
);
541 public List
<String
> getDistributionUrls(String distributionUrl
, String baseUrl
) {
542 List
<String
> urls
= new ArrayList
<String
>();
543 if (distributionUrl
== null)
546 DistributionBundle distributionBundle
;
547 if (distributionUrl
.startsWith("http") || distributionUrl
.startsWith("file")) {
548 distributionBundle
= new DistributionBundle(distributionUrl
);
550 distributionBundle
.setBaseUrl(baseUrl
);
553 if (baseUrl
== null) {
554 baseUrl
= localCache
;
557 if (distributionUrl
.contains(":")) {
558 // TODO make it safer
559 String
[] parts
= distributionUrl
.trim().split(":");
560 String
[] categoryParts
= parts
[0].split("\\.");
561 String artifactId
= parts
[1];
562 String version
= parts
[2];
563 StringBuilder sb
= new StringBuilder();
564 for (String categoryPart
: categoryParts
) {
565 sb
.append(categoryPart
).append('/');
567 sb
.append(artifactId
).append('/');
568 sb
.append(version
).append('/');
569 sb
.append(artifactId
).append('-').append(version
).append(".jar");
570 distributionUrl
= sb
.toString();
573 distributionBundle
= new DistributionBundle(baseUrl
, distributionUrl
, localCache
);
575 // if (baseUrl != null && !(distributionUrl.startsWith("http") ||
576 // distributionUrl.startsWith("file"))) {
578 // distributionBundle = new DistributionBundle(baseUrl, distributionUrl,
581 // distributionBundle = new DistributionBundle(distributionUrl);
582 // if (baseUrl != null)
583 // distributionBundle.setBaseUrl(baseUrl);
585 distributionBundle
.processUrl();
586 return distributionBundle
.listUrls();
590 * HIGH LEVEL UTILITIES
592 /** Actually performs the matching logic. */
593 protected void match(List
<String
> matched
, String base
, String currentPath
, String pattern
) {
594 if (currentPath
== null) {
596 File baseDir
= new File(base
.replace('/', File
.separatorChar
));
597 File
[] files
= baseDir
.listFiles();
600 if (OsgiBootUtils
.debug
)
601 OsgiBootUtils
.warn("Base dir " + baseDir
+ " has no children, exists=" + baseDir
.exists()
602 + ", isDirectory=" + baseDir
.isDirectory());
606 for (int i
= 0; i
< files
.length
; i
++)
607 match(matched
, base
, files
[i
].getName(), pattern
);
609 PathMatcher matcher
= FileSystems
.getDefault().getPathMatcher(pattern
);
610 String fullPath
= base
+ '/' + currentPath
;
611 if (matched
.contains(fullPath
))
612 return;// don't try deeper if already matched
614 boolean ok
= matcher
.matches(Paths
.get(currentPath
));
616 // debug(currentPath + " " + (ok ? "" : " not ")
617 // + " matched with " + pattern);
619 matched
.add(fullPath
);
622 String newFullPath
= relativeToFullPath(base
, currentPath
);
623 File newFile
= new File(newFullPath
);
624 File
[] files
= newFile
.listFiles();
626 for (int i
= 0; i
< files
.length
; i
++) {
627 String newCurrentPath
= currentPath
+ '/' + files
[i
].getName();
628 if (files
[i
].isDirectory()) {
629 // if (matcher.matchStart(pattern, newCurrentPath)) {
630 // FIXME recurse only if start matches ?
631 match(matched
, base
, newCurrentPath
, pattern
);
633 // if (OsgiBootUtils.debug)
634 // debug(newCurrentPath + " does not start match with " + pattern);
638 boolean nonDirectoryOk
= matcher
.matches(Paths
.get(newCurrentPath
));
639 if (OsgiBootUtils
.debug
)
640 debug(currentPath
+ " " + (ok ?
"" : " not ") + " matched with " + pattern
);
642 matched
.add(relativeToFullPath(base
, newCurrentPath
));
650 protected void matchFile() {
655 * LOW LEVEL UTILITIES
658 * The bundles already installed. Key is location (String) , value is a
661 public Map
<String
, Bundle
> getBundlesByLocation() {
662 Map
<String
, Bundle
> installedBundles
= new HashMap
<String
, Bundle
>();
663 Bundle
[] bundles
= bundleContext
.getBundles();
664 for (int i
= 0; i
< bundles
.length
; i
++) {
665 installedBundles
.put(bundles
[i
].getLocation(), bundles
[i
]);
667 return installedBundles
;
671 * The bundles already installed. Key is symbolic name (String) , value is a
674 public Map
<String
, Bundle
> getBundlesBySymbolicName() {
675 Map
<String
, Bundle
> namedBundles
= new HashMap
<String
, Bundle
>();
676 Bundle
[] bundles
= bundleContext
.getBundles();
677 for (int i
= 0; i
< bundles
.length
; i
++) {
678 namedBundles
.put(bundles
[i
].getSymbolicName(), bundles
[i
]);
683 /** Creates an URL from a location */
684 protected String
locationToUrl(String baseUrl
, String location
) {
685 return baseUrl
+ location
;
688 /** Transforms a relative path in a full system path. */
689 protected String
relativeToFullPath(String basePath
, String relativePath
) {
690 return (basePath
+ '/' + relativePath
).replace('/', File
.separatorChar
);
693 private void refreshFramework() {
694 Bundle systemBundle
= bundleContext
.getBundle(0);
695 FrameworkWiring frameworkWiring
= systemBundle
.adapt(FrameworkWiring
.class);
696 frameworkWiring
.refreshBundles(null);
700 * Gets a property value
702 * @return null when defaultValue is ""
704 public String
getProperty(String name
, String defaultValue
) {
705 String value
= bundleContext
.getProperty(name
);
707 return defaultValue
; // may be null
712 public String
getProperty(String name
) {
713 return getProperty(name
, null);
720 public boolean getDebug() {
721 return OsgiBootUtils
.debug
;
724 // public void setDebug(boolean debug) {
725 // this.debug = debug;
728 public BundleContext
getBundleContext() {
729 return bundleContext
;
732 public String
getLocalCache() {
736 // public void setDefaultTimeout(long defaultTimeout) {
737 // this.defaultTimeout = defaultTimeout;
740 // public boolean isExcludeSvn() {
741 // return excludeSvn;
744 // public void setExcludeSvn(boolean excludeSvn) {
745 // this.excludeSvn = excludeSvn;