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
;
30 import java
.util
.StringTokenizer
;
32 import org
.argeo
.osgi
.boot
.internal
.springutil
.AntPathMatcher
;
33 import org
.argeo
.osgi
.boot
.internal
.springutil
.PathMatcher
;
34 import org
.argeo
.osgi
.boot
.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
;
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";
46 public final static String PROP_ARGEO_OSGI_DATA_DIR
= "argeo.osgi.data.dir";
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";
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";
62 public final static String PROP_SLC_OSGI_START
= "slc.osgi.start";
64 public final static String PROP_SLC_OSGI_BUNDLES
= "slc.osgi.bundles";
66 public final static String PROP_SLC_OSGI_LOCATIONS
= "slc.osgi.locations";
68 public final static String PROP_SLC_OSGI_BASE_URL
= "slc.osgi.baseUrl";
70 public final static String PROP_SLC_OSGI_MODULES_URL
= "slc.osgi.modulesUrl";
73 public final static String PROP_SLC_OSGIBOOT_DEBUG
= "slc.osgiboot.debug";
75 public final static String PROP_SLC_OSGIBOOT_DEFAULT_TIMEOUT
= "slc.osgiboot.defaultTimeout";
77 public final static String PROP_SLC_OSGIBOOT_MODULES_URL_SEPARATOR
= "slc.osgiboot.modulesUrlSeparator";
79 public final static String PROP_SLC_OSGIBOOT_SYSTEM_PROPERTIES_FILE
= "slc.osgiboot.systemPropertiesFile";
81 public final static String PROP_SLC_OSGIBOOT_APPCLASS
= "slc.osgiboot.appclass";
83 public final static String PROP_SLC_OSGIBOOT_APPARGS
= "slc.osgiboot.appargs";
87 public final static String DEFAULT_BASE_URL
= "reference:file:";
88 public final static String EXCLUDES_SVN_PATTERN
= "**/.svn/**";
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
;
96 private boolean excludeSvn
= true;
97 /** Default is ',' (set in constructor) */
98 private String modulesUrlSeparator
= ",";
100 private final BundleContext bundleContext
;
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();
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");
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");
132 System
.setProperty(PROP_ARGEO_OSGI_DATA_DIR
, dataDir
.getAbsolutePath());
134 // TODO: Load additional system properties from file
135 // Properties additionalSystemProperties = new Properties();
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());
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());
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();
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
);
172 if (installedBundles
.containsKey(url
)) {
173 Bundle bundle
= (Bundle
) installedBundles
.get(url
);
176 debug("Bundle " + bundle
.getSymbolicName()
177 + " already installed from " + url
);
179 Bundle bundle
= bundleContext
.installBundle(url
);
181 debug("Installed bundle " + bundle
.getSymbolicName()
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...
193 OsgiBootUtils
.warn("Could not install bundle from " + url
+ ": "
203 public void installOrUpdateUrls(Map urls
) {
204 Map installedBundles
= getBundles();
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
);
213 URL url
= new URL(urlStr
);
214 in
= url
.openStream();
216 OsgiBootUtils
.info("Updated bundle " + moduleName
+ " from " + urlStr
);
217 } catch (Exception e
) {
218 throw new RuntimeException("Cannot update " + moduleName
219 + " from " + urlStr
);
224 } catch (IOException e
) {
229 Bundle bundle
= bundleContext
.installBundle(urlStr
);
231 debug("Installed bundle " + bundle
.getSymbolicName()
232 + " from " + urlStr
);
233 } catch (BundleException e
) {
234 OsgiBootUtils
.warn("Could not install bundle from " + urlStr
+ ": "
242 public void startBundles() {
243 String bundlesToStart
= OsgiBootUtils
.getPropertyCompat(PROP_ARGEO_OSGI_START
,
244 PROP_SLC_OSGI_START
);
245 startBundles(bundlesToStart
);
248 public void startBundles(String bundlesToStartStr
) {
249 if (bundlesToStartStr
== null)
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
);
258 startBundles(bundlesToStart
);
261 public void startBundles(List bundlesToStart
) {
262 if (bundlesToStart
.size() == 0)
265 // used to log the bundles not found
266 List notFoundBundles
= new ArrayList(bundlesToStart
);
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
))
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
);
285 notFoundBundles
.remove(symbolicName
);
286 } catch (Exception e
) {
287 OsgiBootUtils
.warn("Bundle " + symbolicName
+ " cannot be started: "
291 // was found even if start failed
292 notFoundBundles
.remove(symbolicName
);
296 for (int i
= 0; i
< notFoundBundles
.size(); i
++)
297 OsgiBootUtils
.warn("Bundle " + notFoundBundles
.get(i
)
298 + " not started because it was not found.");
301 protected void checkUnresolved() {
303 ServiceReference packageAdminRef
= bundleContext
304 .getServiceReference(PackageAdmin
.class.getName());
305 PackageAdmin packageAdmin
= (PackageAdmin
) bundleContext
306 .getService(packageAdminRef
);
307 packageAdmin
.resolveBundles(null);
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
]);
318 if (unresolvedBundles
.size() != 0) {
319 OsgiBootUtils
.warn("Unresolved bundles " + unresolvedBundles
);
323 protected void waitForBundleResolvedOrActive(long startBegin
, Bundle bundle
)
325 int originalState
= bundle
.getState();
326 if ((originalState
== Bundle
.RESOLVED
)
327 || (originalState
== Bundle
.ACTIVE
))
330 String originalStateStr
= stateAsString(originalState
);
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
) + ")");
344 } catch (InterruptedException e
) {
347 currentState
= bundle
.getState();
351 public static String
stateAsString(int state
) {
353 case Bundle
.UNINSTALLED
:
354 return "UNINSTALLED";
355 case Bundle
.INSTALLED
:
357 case Bundle
.RESOLVED
:
359 case Bundle
.STARTING
:
363 case Bundle
.STOPPING
:
366 return Integer
.toString(state
);
370 /** Key is location */
371 public Map
getInstalledBundles() {
372 Map installedBundles
= new HashMap();
374 Bundle
[] bundles
= bundleContext
.getBundles();
375 for (int i
= 0; i
< bundles
.length
; i
++) {
376 installedBundles
.put(bundles
[i
].getLocation(), bundles
[i
]);
378 return installedBundles
;
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
]);
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
);
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)
406 String baseUrl
= OsgiBootUtils
.getPropertyCompat(PROP_ARGEO_OSGI_BASE_URL
,
407 PROP_SLC_OSGI_BASE_URL
);
409 Map installedBundles
= getBundles();
411 BufferedReader reader
= null;
413 URL modulesUrl
= new URL(modulesUrlStr
);
414 reader
= new BufferedReader(new InputStreamReader(modulesUrl
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();
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
);
432 OsgiBootUtils
.warn("Installed version " + bundleVersion
433 + " of bundle " + moduleName
434 + " is newer than provided version "
436 } else if (comp
< 0) {
438 OsgiBootUtils
.info("Updated bundle " + moduleName
+ " with version "
439 + moduleVersion
+ " (old version was "
440 + bundleVersion
+ ")");
448 } catch (Exception e1
) {
449 throw new RuntimeException("Cannot read url " + modulesUrlStr
, e1
);
454 } catch (IOException e
) {
462 * @return ==0: versions are identical, <0: tested version is newer, >0:
463 * currentVersion is newer.
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());
476 comp
: for (int i
= 0; i
< cToks
.size(); i
++) {
477 if (tToks
.size() <= i
) {
478 // equals until then, tested shorter
483 String c
= (String
) cToks
.get(i
);
484 String t
= (String
) tToks
.get(i
);
487 int cInt
= Integer
.parseInt(c
);
488 int tInt
= Integer
.parseInt(t
);
492 comp
= (cInt
- tInt
);
495 } catch (NumberFormatException e
) {
499 comp
= c
.compareTo(t
);
505 if (comp
== 0 && tToks
.size() > cToks
.size()) {
506 // equals until then, current shorter
513 public List
getLocationsUrls(String baseUrl
, String bundleLocations
) {
514 List urls
= new ArrayList();
516 if (bundleLocations
== null)
518 bundleLocations
= SystemPropertyUtils
519 .resolvePlaceholders(bundleLocations
);
521 debug(PROP_ARGEO_OSGI_LOCATIONS
+ "=" + bundleLocations
);
523 StringTokenizer st
= new StringTokenizer(bundleLocations
,
525 while (st
.hasMoreTokens()) {
526 urls
.add(locationToUrl(baseUrl
, st
.nextToken().trim()));
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
);
539 public List
getBundlesUrls(String baseUrl
, String bundlePatterns
) {
540 List urls
= new ArrayList();
542 List bundlesSets
= new ArrayList();
543 if (bundlePatterns
== null)
545 bundlePatterns
= SystemPropertyUtils
546 .resolvePlaceholders(bundlePatterns
);
548 debug(PROP_ARGEO_OSGI_BUNDLES
+ "=" + bundlePatterns
549 + " (excludeSvn=" + excludeSvn
+ ")");
551 StringTokenizer st
= new StringTokenizer(bundlePatterns
, ",");
552 while (st
.hasMoreTokens()) {
553 bundlesSets
.add(new BundlesSet(st
.nextToken()));
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
);
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
);
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
));
584 protected void match(PathMatcher matcher
, List matched
, String base
,
585 String currentPath
, String pattern
) {
586 if (currentPath
== null) {
588 File baseDir
= new File(base
.replace('/', File
.separatorChar
));
589 File
[] files
= baseDir
.listFiles();
592 OsgiBootUtils
.warn("Base dir " + baseDir
+ " has no children, exists="
593 + baseDir
.exists() + ", isDirectory="
594 + baseDir
.isDirectory());
598 for (int i
= 0; i
< files
.length
; i
++)
599 match(matcher
, matched
, base
, files
[i
].getName(), pattern
);
601 String fullPath
= base
+ '/' + currentPath
;
602 if (matched
.contains(fullPath
))
603 return;// don't try deeper if already matched
605 boolean ok
= matcher
.match(pattern
, currentPath
);
607 debug(currentPath
+ " " + (ok ?
"" : " not ")
608 + " matched with " + pattern
);
610 matched
.add(fullPath
);
613 String newFullPath
= relativeToFullPath(base
, currentPath
);
614 File newFile
= new File(newFullPath
);
615 File
[] files
= newFile
.listFiles();
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
,
628 + " does not start match with "
633 boolean nonDirectoryOk
= matcher
.match(pattern
,
636 debug(currentPath
+ " " + (ok ?
"" : " not ")
637 + " matched with " + pattern
);
639 matched
.add(relativeToFullPath(base
,
648 protected String
locationToUrl(String baseUrl
, String location
) {
649 int extInd
= location
.lastIndexOf('.');
652 ext
= location
.substring(extInd
);
654 if (baseUrl
.startsWith("reference:") && ".jar".equals(ext
))
655 return "file:" + location
;
657 return baseUrl
+ location
;
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
);
665 protected void debug(Object obj
) {
667 OsgiBootUtils
.debug(obj
);
670 public boolean getDebug() {
674 public void setDebug(boolean debug
) {
678 public BundleContext
getBundleContext() {
679 return bundleContext
;
682 /** Whether to exclude Subversion directories (true by default) */
683 public boolean isExcludeSvn() {
687 public void setExcludeSvn(boolean excludeSvn
) {
688 this.excludeSvn
= excludeSvn
;
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();
697 public BundlesSet(String def
) {
698 StringTokenizer st
= new StringTokenizer(def
, ";");
700 if (!st
.hasMoreTokens())
701 throw new RuntimeException("Base dir not defined.");
703 String dirPath
= st
.nextToken();
705 if (dirPath
.startsWith("file:"))
706 dirPath
= dirPath
.substring("file:".length());
708 dir
= new File(dirPath
.replace('/', File
.separatorChar
))
711 debug("Base dir: " + dir
);
712 } catch (IOException e
) {
713 throw new RuntimeException("Cannot convert to absolute path", e
);
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
)) {
728 System
.err
.println("Unkown bundles pattern type " + type
);
732 if (excludeSvn
&& !excludes
.contains(EXCLUDES_SVN_PATTERN
)) {
733 excludes
.add(EXCLUDES_SVN_PATTERN
);
737 public String
getDir() {
741 public List
getIncludes() {
745 public List
getExcludes() {
749 public String
getBaseUrl() {
755 public void setDefaultTimeout(long defaultTimeout
) {
756 this.defaultTimeout
= defaultTimeout
;
759 public void setModulesUrlSeparator(String modulesUrlSeparator
) {
760 this.modulesUrlSeparator
= modulesUrlSeparator
;