2 * Copyright (C) 2007-2012 Argeo GmbH
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.
16 package org
.argeo
.osgi
.boot
;
18 import static org
.argeo
.osgi
.boot
.OsgiBootUtils
.debug
;
19 import static org
.argeo
.osgi
.boot
.OsgiBootUtils
.warn
;
22 import java
.io
.IOException
;
23 import java
.util
.ArrayList
;
24 import java
.util
.HashMap
;
25 import java
.util
.Iterator
;
26 import java
.util
.List
;
28 import java
.util
.Properties
;
30 import java
.util
.SortedMap
;
31 import java
.util
.StringTokenizer
;
32 import java
.util
.TreeMap
;
34 import org
.argeo
.osgi
.boot
.internal
.springutil
.AntPathMatcher
;
35 import org
.argeo
.osgi
.boot
.internal
.springutil
.PathMatcher
;
36 import org
.argeo
.osgi
.boot
.internal
.springutil
.SystemPropertyUtils
;
37 import org
.osgi
.framework
.Bundle
;
38 import org
.osgi
.framework
.BundleContext
;
39 import org
.osgi
.framework
.BundleException
;
40 import org
.osgi
.framework
.FrameworkEvent
;
41 import org
.osgi
.framework
.startlevel
.BundleStartLevel
;
42 import org
.osgi
.framework
.startlevel
.FrameworkStartLevel
;
45 * Basic provisioning of an OSGi runtime via file path patterns and system
46 * properties. The approach is to generate list of URLs based on various
47 * methods, configured via properties.
49 public class OsgiBoot
implements OsgiBootConstants
{
50 // public final static String PROP_ARGEO_OSGI_DATA_DIR =
51 // "argeo.osgi.data.dir";
52 public final static String PROP_ARGEO_OSGI_START
= "argeo.osgi.start";
53 public final static String PROP_ARGEO_OSGI_BUNDLES
= "argeo.osgi.bundles";
54 public final static String PROP_ARGEO_OSGI_BASE_URL
= "argeo.osgi.baseUrl";
55 public final static String PROP_ARGEO_OSGI_DISTRIBUTION_URL
= "argeo.osgi.distributionUrl";
58 public final static String PROP_ARGEO_OSGI_BOOT_DEBUG
= "argeo.osgi.boot.debug";
59 public final static String PROP_ARGEO_OSGI_BOOT_EXCLUDE_SVN
= "argeo.osgi.boot.excludeSvn";
61 // public final static String PROP_ARGEO_OSGI_BOOT_DEFAULT_TIMEOUT =
62 // "argeo.osgi.boot.defaultTimeout";
63 public final static String PROP_ARGEO_OSGI_BOOT_SYSTEM_PROPERTIES_FILE
= "argeo.osgi.boot.systemPropertiesFile";
64 public final static String PROP_ARGEO_OSGI_BOOT_APPCLASS
= "argeo.osgi.boot.appclass";
65 public final static String PROP_ARGEO_OSGI_BOOT_APPARGS
= "argeo.osgi.boot.appargs";
67 public final static String DEFAULT_BASE_URL
= "reference:file:";
68 public final static String EXCLUDES_SVN_PATTERN
= "**/.svn/**";
70 // OSGi system properties
71 public final static String PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL
= "osgi.bundles.defaultStartLevel";
72 public final static String PROP_OSGI_STARTLEVEL
= "osgi.startLevel";
73 public final static String INSTANCE_AREA_PROP
= "osgi.instance.area";
74 // public final static String INSTANCE_AREA_DEFAULT_PROP =
75 // "osgi.instance.area.default";
78 public final static String SYMBOLIC_NAME_OSGI_BOOT
= "org.argeo.osgi.boot";
79 public final static String SYMBOLIC_NAME_EQUINOX
= "org.eclipse.osgi";
81 private boolean debug
= Boolean
.valueOf(System
.getProperty(PROP_ARGEO_OSGI_BOOT_DEBUG
, "false")).booleanValue();
82 /** Exclude svn metadata implicitely(a bit costly) */
83 private boolean excludeSvn
= Boolean
.valueOf(System
.getProperty(PROP_ARGEO_OSGI_BOOT_EXCLUDE_SVN
, "false"))
87 private long defaultTimeout
= 10000l;
89 private final BundleContext bundleContext
;
95 public OsgiBoot(BundleContext bundleContext
) {
96 this.bundleContext
= bundleContext
;
98 // Long.parseLong(OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BOOT_DEFAULT_TIMEOUT,
100 // initSystemProperties();
104 // * Set additional system properties, especially ${argeo.osgi.data.dir} as
106 // * OS file path (and not a file:// URL)
108 // private void initSystemProperties() {
109 // String osgiInstanceArea = System.getProperty(INSTANCE_AREA_PROP);
110 // String osgiInstanceAreaDefault =
111 // System.getProperty(INSTANCE_AREA_DEFAULT_PROP);
112 // String tempDir = System.getProperty("java.io.tmpdir");
114 // File dataDir = null;
115 // if (osgiInstanceArea != null) {
116 // // within OSGi with -data specified
117 // osgiInstanceArea = removeFilePrefix(osgiInstanceArea);
118 // dataDir = new File(osgiInstanceArea);
119 // } else if (osgiInstanceAreaDefault != null) {
120 // // within OSGi without -data specified
121 // osgiInstanceAreaDefault = removeFilePrefix(osgiInstanceAreaDefault);
122 // dataDir = new File(osgiInstanceAreaDefault);
123 // } else {// outside OSGi
124 // dataDir = new File(tempDir + File.separator + "argeoOsgiData");
126 // System.setProperty(PROP_ARGEO_OSGI_DATA_DIR, dataDir.getAbsolutePath());
132 /** Bootstraps the OSGi runtime */
133 public void bootstrap() {
135 long begin
= System
.currentTimeMillis();
136 System
.out
.println();
137 String osgiInstancePath
= bundleContext
.getProperty(INSTANCE_AREA_PROP
);
139 .info("OSGi bootstrap starting" + (osgiInstancePath
!= null ?
" (" + osgiInstancePath
+ ")" : ""));
140 // OsgiBootUtils.info("Writable data directory : " +
141 // System.getProperty(PROP_ARGEO_OSGI_DATA_DIR)
142 // + " (set as system property " + PROP_ARGEO_OSGI_DATA_DIR + ")");
143 installUrls(getBundlesUrls());
144 installUrls(getDistributionUrls());
146 long duration
= System
.currentTimeMillis() - begin
;
147 OsgiBootUtils
.info("OSGi bootstrap completed in " + Math
.round(((double) duration
) / 1000) + "s ("
148 + duration
+ "ms), " + bundleContext
.getBundles().length
+ " bundles");
149 } catch (RuntimeException e
) {
150 OsgiBootUtils
.error("OSGi bootstrap FAILED", e
);
156 OsgiBootDiagnostics diagnostics
= new OsgiBootDiagnostics(bundleContext
);
157 diagnostics
.checkUnresolved();
158 Map
<String
, Set
<String
>> duplicatePackages
= diagnostics
.findPackagesExportedTwice();
159 if (duplicatePackages
.size() > 0) {
160 OsgiBootUtils
.info("Packages exported twice:");
161 Iterator
<String
> it
= duplicatePackages
.keySet().iterator();
162 while (it
.hasNext()) {
163 String pkgName
= it
.next();
164 OsgiBootUtils
.info(pkgName
);
165 Set
<String
> bdles
= duplicatePackages
.get(pkgName
);
166 Iterator
<String
> bdlesIt
= bdles
.iterator();
167 while (bdlesIt
.hasNext())
168 OsgiBootUtils
.info(" " + bdlesIt
.next());
172 System
.out
.println();
178 /** Install a single url. Convenience method. */
179 public Bundle
installUrl(String url
) {
180 List
<String
> urls
= new ArrayList
<String
>();
183 return (Bundle
) getBundlesByLocation().get(url
);
186 /** Install the bundles at this URL list. */
187 public void installUrls(List
<String
> urls
) {
188 Map
<String
, Bundle
> installedBundles
= getBundlesByLocation();
189 for (int i
= 0; i
< urls
.size(); i
++) {
190 String url
= (String
) urls
.get(i
);
191 installUrl(url
, installedBundles
);
195 /** Actually install the provided URL */
196 protected void installUrl(String url
, Map
<String
, Bundle
> installedBundles
) {
198 if (installedBundles
.containsKey(url
)) {
199 Bundle bundle
= (Bundle
) installedBundles
.get(url
);
201 debug("Bundle " + bundle
.getSymbolicName() + " already installed from " + url
);
202 } else if (url
.contains("/" + SYMBOLIC_NAME_EQUINOX
+ "/")
203 || url
.contains("/" + SYMBOLIC_NAME_OSGI_BOOT
+ "/")) {
208 Bundle bundle
= bundleContext
.installBundle(url
);
209 if (url
.startsWith("http"))
211 .info("Installed " + bundle
.getSymbolicName() + "-" + bundle
.getVersion() + " from " + url
);
214 "Installed " + bundle
.getSymbolicName() + "-" + bundle
.getVersion() + " from " + url
);
216 } catch (BundleException e
) {
217 String message
= e
.getMessage();
218 if ((message
.contains("Bundle \"" + SYMBOLIC_NAME_OSGI_BOOT
+ "\"")
219 || message
.contains("Bundle \"" + SYMBOLIC_NAME_EQUINOX
+ "\""))
220 && message
.contains("is already 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
+ ": " + message
);
234 public void startBundles() {
235 startBundles(System
.getProperties());
238 public void startBundles(Properties properties
) {
239 FrameworkStartLevel frameworkStartLevel
= bundleContext
.getBundle(0).adapt(FrameworkStartLevel
.class);
241 // default and active start levels from System properties
242 Integer defaultStartLevel
= new Integer(
243 Integer
.parseInt(getProperty(PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL
, "4")));
244 Integer activeStartLevel
= new Integer(getProperty(PROP_OSGI_STARTLEVEL
, "6"));
246 SortedMap
<Integer
, List
<String
>> startLevels
= new TreeMap
<Integer
, List
<String
>>();
247 computeStartLevels(startLevels
, properties
, defaultStartLevel
);
248 // inverts the map for the time being, TODO optimise
249 Map
<String
, Integer
> bundleStartLevels
= new HashMap
<>();
250 for (Integer level
: startLevels
.keySet()) {
251 for (String bsn
: startLevels
.get(level
))
252 bundleStartLevels
.put(bsn
, level
);
254 for (Bundle bundle
: bundleContext
.getBundles()) {
255 String bsn
= bundle
.getSymbolicName();
256 if (bundleStartLevels
.containsKey(bsn
)) {
257 BundleStartLevel bundleStartLevel
= bundle
.adapt(BundleStartLevel
.class);
258 Integer level
= bundleStartLevels
.get(bsn
);
259 if (bundleStartLevel
.getStartLevel() != level
|| !bundleStartLevel
.isPersistentlyStarted()) {
260 bundleStartLevel
.setStartLevel(level
);
263 } catch (BundleException e
) {
264 OsgiBootUtils
.error("Cannot mark " + bsn
+ " as started", e
);
267 OsgiBootUtils
.debug(bsn
+ " starts at level " + level
);
271 frameworkStartLevel
.setStartLevel(activeStartLevel
, (FrameworkEvent event
) -> {
273 OsgiBootUtils
.debug("Framework event: " + event
);
274 int initialStartLevel
= frameworkStartLevel
.getInitialBundleStartLevel();
275 int startLevel
= frameworkStartLevel
.getStartLevel();
276 OsgiBootUtils
.debug("Framework start level: " + startLevel
+ " (initial: " + initialStartLevel
+ ")");
279 // Iterator<Integer> levels = startLevels.keySet().iterator();
280 // while (levels.hasNext()) {
281 // Integer level = (Integer) levels.next();
282 // boolean allStarted = startBundles(startLevels.get(level));
284 // OsgiBootUtils.warn("Not all bundles started for level " + level);
285 // if (level.equals(activeStartLevel))
286 // break;// active start level reached
291 public static void computeStartLevels(SortedMap
<Integer
, List
<String
>> startLevels
, Properties properties
,
292 Integer defaultStartLevel
) {
294 // default (and previously, only behaviour)
295 appendToStartLevels(startLevels
, defaultStartLevel
, properties
.getProperty(PROP_ARGEO_OSGI_START
, ""));
297 // list argeo.osgi.start.* system properties
298 Iterator
<Object
> keys
= properties
.keySet().iterator();
299 final String prefix
= PROP_ARGEO_OSGI_START
+ ".";
300 while (keys
.hasNext()) {
301 String key
= keys
.next().toString();
302 if (key
.startsWith(prefix
)) {
304 String suffix
= key
.substring(prefix
.length());
305 String
[] tokens
= suffix
.split("\\.");
306 if (tokens
.length
> 0 && !tokens
[0].trim().equals(""))
308 // first token is start level
309 startLevel
= new Integer(tokens
[0]);
310 } catch (NumberFormatException e
) {
311 startLevel
= defaultStartLevel
;
314 startLevel
= defaultStartLevel
;
316 // append bundle names
317 String bundleNames
= properties
.getProperty(key
);
318 appendToStartLevels(startLevels
, startLevel
, bundleNames
);
323 /** Append a comma-separated list of bundles to the start levels. */
324 private static void appendToStartLevels(SortedMap
<Integer
, List
<String
>> startLevels
, Integer startLevel
,
326 if (str
== null || str
.trim().equals(""))
329 if (!startLevels
.containsKey(startLevel
))
330 startLevels
.put(startLevel
, new ArrayList
<String
>());
331 String
[] bundleNames
= str
.split(",");
332 for (int i
= 0; i
< bundleNames
.length
; i
++) {
333 if (bundleNames
[i
] != null && !bundleNames
[i
].trim().equals(""))
334 (startLevels
.get(startLevel
)).add(bundleNames
[i
]);
339 * Start the provided list of bundles
341 * @return whether all bundles are now in active state
345 public boolean startBundles(List
<String
> bundlesToStart
) {
346 if (bundlesToStart
.size() == 0)
349 // used to monitor ACTIVE states
350 List
<Bundle
> startedBundles
= new ArrayList
<Bundle
>();
351 // used to log the bundles not found
352 List
<String
> notFoundBundles
= new ArrayList
<String
>(bundlesToStart
);
354 Bundle
[] bundles
= bundleContext
.getBundles();
355 long startBegin
= System
.currentTimeMillis();
356 for (int i
= 0; i
< bundles
.length
; i
++) {
357 Bundle bundle
= bundles
[i
];
358 String symbolicName
= bundle
.getSymbolicName();
359 if (bundlesToStart
.contains(symbolicName
))
364 debug("Bundle " + symbolicName
+ " started");
365 } catch (Exception e
) {
366 OsgiBootUtils
.warn("Start of bundle " + symbolicName
+ " failed because of " + e
367 + ", maybe bundle is not yet resolved," + " waiting and trying again.");
368 waitForBundleResolvedOrActive(startBegin
, bundle
);
370 startedBundles
.add(bundle
);
372 notFoundBundles
.remove(symbolicName
);
373 } catch (Exception e
) {
374 OsgiBootUtils
.warn("Bundle " + symbolicName
+ " cannot be started: " + e
.getMessage());
377 // was found even if start failed
378 notFoundBundles
.remove(symbolicName
);
382 for (int i
= 0; i
< notFoundBundles
.size(); i
++)
383 OsgiBootUtils
.warn("Bundle '" + notFoundBundles
.get(i
) + "' not started because it was not found.");
385 // monitors that all bundles are started
386 long beginMonitor
= System
.currentTimeMillis();
387 boolean allStarted
= !(startedBundles
.size() > 0);
388 List
<String
> notStarted
= new ArrayList
<String
>();
389 while (!allStarted
&& (System
.currentTimeMillis() - beginMonitor
) < defaultTimeout
) {
390 notStarted
= new ArrayList
<String
>();
392 for (int i
= 0; i
< startedBundles
.size(); i
++) {
393 Bundle bundle
= (Bundle
) startedBundles
.get(i
);
394 // TODO check behaviour of lazs bundles
395 if (bundle
.getState() != Bundle
.ACTIVE
) {
397 notStarted
.add(bundle
.getSymbolicName());
402 } catch (InterruptedException e
) {
406 long duration
= System
.currentTimeMillis() - beginMonitor
;
409 for (int i
= 0; i
< notStarted
.size(); i
++)
410 OsgiBootUtils
.warn("Bundle '" + notStarted
.get(i
) + "' not ACTIVE after " + (duration
/ 1000) + "s");
415 /** Waits for a bundle to become active or resolved */
416 private void waitForBundleResolvedOrActive(long startBegin
, Bundle bundle
) throws Exception
{
417 int originalState
= bundle
.getState();
418 if ((originalState
== Bundle
.RESOLVED
) || (originalState
== Bundle
.ACTIVE
))
421 String originalStateStr
= OsgiBootUtils
.stateAsString(originalState
);
423 int currentState
= bundle
.getState();
424 while (!(currentState
== Bundle
.RESOLVED
|| currentState
== Bundle
.ACTIVE
)) {
425 long now
= System
.currentTimeMillis();
426 if ((now
- startBegin
) > defaultTimeout
* 10)
427 throw new Exception("Bundle " + bundle
.getSymbolicName() + " was not RESOLVED or ACTIVE after "
428 + (now
- startBegin
) + "ms (originalState=" + originalStateStr
+ ", currentState="
429 + OsgiBootUtils
.stateAsString(currentState
) + ")");
433 } catch (InterruptedException e
) {
436 currentState
= bundle
.getState();
441 * BUNDLE PATTERNS INSTALLATION
444 * Computes a list of URLs based on Ant-like include/exclude patterns
445 * defined by ${argeo.osgi.bundles} with the following format:<br>
446 * <code>/base/directory;in=*.jar;in=**;ex=org.eclipse.osgi_*;jar</code><br>
447 * WARNING: <code>/base/directory;in=*.jar,\</code> at the end of a file,
448 * without a new line causes a '.' to be appended with unexpected side
451 public List
<String
> getBundlesUrls() {
452 String bundlePatterns
= getProperty(PROP_ARGEO_OSGI_BUNDLES
);
453 return getBundlesUrls(bundlePatterns
);
457 * Compute alist of URLs to install based on the provided patterns, with
460 public List
<String
> getBundlesUrls(String bundlePatterns
) {
461 String baseUrl
= getProperty(PROP_ARGEO_OSGI_BASE_URL
, DEFAULT_BASE_URL
);
462 return getBundlesUrls(baseUrl
, bundlePatterns
);
465 /** Implements the path matching logic */
466 List
<String
> getBundlesUrls(String baseUrl
, String bundlePatterns
) {
467 List
<String
> urls
= new ArrayList
<String
>();
468 if (bundlePatterns
== null)
471 bundlePatterns
= SystemPropertyUtils
.resolvePlaceholders(bundlePatterns
);
473 debug(PROP_ARGEO_OSGI_BUNDLES
+ "=" + bundlePatterns
+ " (excludeSvn=" + excludeSvn
+ ")");
475 StringTokenizer st
= new StringTokenizer(bundlePatterns
, ",");
476 List
<BundlesSet
> bundlesSets
= new ArrayList
<BundlesSet
>();
477 while (st
.hasMoreTokens()) {
478 String token
= st
.nextToken();
479 if (new File(token
).exists()) {
480 String url
= locationToUrl(baseUrl
, token
);
483 bundlesSets
.add(new BundlesSet(token
));
487 List
<String
> included
= new ArrayList
<String
>();
488 PathMatcher matcher
= new AntPathMatcher();
489 for (int i
= 0; i
< bundlesSets
.size(); i
++) {
490 BundlesSet bundlesSet
= (BundlesSet
) bundlesSets
.get(i
);
491 for (int j
= 0; j
< bundlesSet
.getIncludes().size(); j
++) {
492 String pattern
= (String
) bundlesSet
.getIncludes().get(j
);
493 match(matcher
, included
, bundlesSet
.getDir(), null, pattern
);
498 List
<String
> excluded
= new ArrayList
<String
>();
499 for (int i
= 0; i
< bundlesSets
.size(); i
++) {
500 BundlesSet bundlesSet
= (BundlesSet
) bundlesSets
.get(i
);
501 for (int j
= 0; j
< bundlesSet
.getExcludes().size(); j
++) {
502 String pattern
= (String
) bundlesSet
.getExcludes().get(j
);
503 match(matcher
, excluded
, bundlesSet
.getDir(), null, pattern
);
508 for (int i
= 0; i
< included
.size(); i
++) {
509 String fullPath
= (String
) included
.get(i
);
510 if (!excluded
.contains(fullPath
))
511 urls
.add(locationToUrl(baseUrl
, fullPath
));
518 * DISTRIBUTION JAR INSTALLATION
520 public List
<String
> getDistributionUrls() {
521 String distributionUrl
= getProperty(PROP_ARGEO_OSGI_DISTRIBUTION_URL
);
522 String baseUrl
= getProperty(PROP_ARGEO_OSGI_BASE_URL
);
523 return getDistributionUrls(distributionUrl
, baseUrl
);
526 public List
<String
> getDistributionUrls(String distributionUrl
, String baseUrl
) {
527 List
<String
> urls
= new ArrayList
<String
>();
528 if (distributionUrl
== null)
531 DistributionBundle distributionBundle
;
532 if (baseUrl
!= null && !(distributionUrl
.startsWith("http") || distributionUrl
.startsWith("file"))) {
534 distributionBundle
= new DistributionBundle(baseUrl
, distributionUrl
);
536 distributionBundle
= new DistributionBundle(distributionUrl
);
538 distributionBundle
.setBaseUrl(baseUrl
);
541 distributionBundle
.processUrl();
542 return distributionBundle
.listUrls();
546 * HIGH LEVEL UTILITIES
548 /** Actually performs the matching logic. */
549 protected void match(PathMatcher matcher
, List
<String
> matched
, String base
, String currentPath
, String pattern
) {
550 if (currentPath
== null) {
552 File baseDir
= new File(base
.replace('/', File
.separatorChar
));
553 File
[] files
= baseDir
.listFiles();
557 OsgiBootUtils
.warn("Base dir " + baseDir
+ " has no children, exists=" + baseDir
.exists()
558 + ", isDirectory=" + baseDir
.isDirectory());
562 for (int i
= 0; i
< files
.length
; i
++)
563 match(matcher
, matched
, base
, files
[i
].getName(), pattern
);
565 String fullPath
= base
+ '/' + currentPath
;
566 if (matched
.contains(fullPath
))
567 return;// don't try deeper if already matched
569 boolean ok
= matcher
.match(pattern
, currentPath
);
571 // debug(currentPath + " " + (ok ? "" : " not ")
572 // + " matched with " + pattern);
574 matched
.add(fullPath
);
577 String newFullPath
= relativeToFullPath(base
, currentPath
);
578 File newFile
= new File(newFullPath
);
579 File
[] files
= newFile
.listFiles();
581 for (int i
= 0; i
< files
.length
; i
++) {
582 String newCurrentPath
= currentPath
+ '/' + files
[i
].getName();
583 if (files
[i
].isDirectory()) {
584 if (matcher
.matchStart(pattern
, newCurrentPath
)) {
585 // recurse only if start matches
586 match(matcher
, matched
, base
, newCurrentPath
, pattern
);
589 debug(newCurrentPath
+ " does not start match with " + pattern
);
593 boolean nonDirectoryOk
= matcher
.match(pattern
, newCurrentPath
);
595 debug(currentPath
+ " " + (ok ?
"" : " not ") + " matched with " + pattern
);
597 matched
.add(relativeToFullPath(base
, newCurrentPath
));
605 protected void matchFile() {
610 * LOW LEVEL UTILITIES
613 * The bundles already installed. Key is location (String) , value is a
616 public Map
<String
, Bundle
> getBundlesByLocation() {
617 Map
<String
, Bundle
> installedBundles
= new HashMap
<String
, Bundle
>();
618 Bundle
[] bundles
= bundleContext
.getBundles();
619 for (int i
= 0; i
< bundles
.length
; i
++) {
620 installedBundles
.put(bundles
[i
].getLocation(), bundles
[i
]);
622 return installedBundles
;
626 * The bundles already installed. Key is symbolic name (String) , value is a
629 public Map
<String
, Bundle
> getBundlesBySymbolicName() {
630 Map
<String
, Bundle
> namedBundles
= new HashMap
<String
, Bundle
>();
631 Bundle
[] bundles
= bundleContext
.getBundles();
632 for (int i
= 0; i
< bundles
.length
; i
++) {
633 namedBundles
.put(bundles
[i
].getSymbolicName(), bundles
[i
]);
638 /** Creates an URL from a location */
639 protected String
locationToUrl(String baseUrl
, String location
) {
640 return baseUrl
+ location
;
643 /** Transforms a relative path in a full system path. */
644 protected String
relativeToFullPath(String basePath
, String relativePath
) {
645 return (basePath
+ '/' + relativePath
).replace('/', File
.separatorChar
);
648 // private String removeFilePrefix(String url) {
649 // if (url.startsWith("file:"))
650 // return url.substring("file:".length());
651 // else if (url.startsWith("reference:file:"))
652 // return url.substring("reference:file:".length());
658 * Gets a property value
660 * @return null when defaultValue is ""
662 public String
getProperty(String name
, String defaultValue
) {
663 String value
= bundleContext
.getProperty(name
);
665 return defaultValue
; // may be null
669 // if (defaultValue != null)
670 // value = System.getProperty(name, defaultValue);
672 // value = System.getProperty(name);
674 // if (value == null || value.equals(""))
680 public String
getProperty(String name
) {
681 return getProperty(name
, null);
688 public boolean getDebug() {
692 public void setDebug(boolean debug
) {
696 public BundleContext
getBundleContext() {
697 return bundleContext
;
700 // public void setDefaultTimeout(long defaultTimeout) {
701 // this.defaultTimeout = defaultTimeout;
704 public boolean isExcludeSvn() {
708 public void setExcludeSvn(boolean excludeSvn
) {
709 this.excludeSvn
= excludeSvn
;
716 /** Intermediary structure used by path matching */
717 protected class BundlesSet
{
718 private String baseUrl
= "reference:file";// not used yet
719 private final String dir
;
720 private List
<String
> includes
= new ArrayList
<String
>();
721 private List
<String
> excludes
= new ArrayList
<String
>();
723 public BundlesSet(String def
) {
724 StringTokenizer st
= new StringTokenizer(def
, ";");
726 if (!st
.hasMoreTokens())
727 throw new RuntimeException("Base dir not defined.");
729 String dirPath
= st
.nextToken();
731 if (dirPath
.startsWith("file:"))
732 dirPath
= dirPath
.substring("file:".length());
734 dir
= new File(dirPath
.replace('/', File
.separatorChar
)).getCanonicalPath();
736 debug("Base dir: " + dir
);
737 } catch (IOException e
) {
738 throw new RuntimeException("Cannot convert to absolute path", e
);
741 while (st
.hasMoreTokens()) {
742 String tk
= st
.nextToken();
743 StringTokenizer stEq
= new StringTokenizer(tk
, "=");
744 String type
= stEq
.nextToken();
745 String pattern
= stEq
.nextToken();
746 if ("in".equals(type
) || "include".equals(type
)) {
747 includes
.add(pattern
);
748 } else if ("ex".equals(type
) || "exclude".equals(type
)) {
749 excludes
.add(pattern
);
750 } else if ("baseUrl".equals(type
)) {
753 System
.err
.println("Unkown bundles pattern type " + type
);
757 if (excludeSvn
&& !excludes
.contains(EXCLUDES_SVN_PATTERN
)) {
758 excludes
.add(EXCLUDES_SVN_PATTERN
);
762 public String
getDir() {
766 public List
<String
> getIncludes() {
770 public List
<String
> getExcludes() {
774 public String
getBaseUrl() {