X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=osgi%2Fruntime%2Forg.argeo.osgi.boot%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fosgi%2Fboot%2FOsgiBoot.java;h=94fccdcee2058cfa913c3f5f97194a8aaeb98175;hb=aacd48dc5f6d3e748e9dd8058b19beac5b367939;hp=7c37986974f3be30ccb0679dd642b49ab417396c;hpb=00afc91938be9ee8b2b6dcea6e052b2595a0c87e;p=lgpl%2Fargeo-commons.git diff --git a/osgi/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBoot.java b/osgi/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBoot.java index 7c3798697..94fccdcee 100644 --- a/osgi/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBoot.java +++ b/osgi/runtime/org.argeo.osgi.boot/src/main/java/org/argeo/osgi/boot/OsgiBoot.java @@ -19,7 +19,6 @@ package org.argeo.osgi.boot; import java.io.BufferedReader; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.ArrayList; @@ -28,6 +27,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.SortedMap; import java.util.StringTokenizer; import java.util.TreeMap; import java.util.TreeSet; @@ -43,6 +43,12 @@ import org.osgi.framework.ServiceReference; import org.osgi.service.packageadmin.ExportedPackage; import org.osgi.service.packageadmin.PackageAdmin; +/** + * Basic provisioning of an OSGi runtime via file path patterns and system + * properties. Java 1.4 compatible.
+ * The approach is to generate list of URLs based on various methods, configured + * via system properties. + */ public class OsgiBoot { public final static String SYMBOLIC_NAME_OSGI_BOOT = "org.argeo.osgi.boot"; public final static String SYMBOLIC_NAME_EQUINOX = "org.eclipse.osgi"; @@ -53,70 +59,76 @@ public class OsgiBoot { public final static String PROP_ARGEO_OSGI_BUNDLES = "argeo.osgi.bundles"; public final static String PROP_ARGEO_OSGI_LOCATIONS = "argeo.osgi.locations"; public final static String PROP_ARGEO_OSGI_BASE_URL = "argeo.osgi.baseUrl"; + /** Use org.argeo.osgi */ public final static String PROP_ARGEO_OSGI_MODULES_URL = "argeo.osgi.modulesUrl"; + // booleans public final static String PROP_ARGEO_OSGI_BOOT_DEBUG = "argeo.osgi.boot.debug"; + public final static String PROP_ARGEO_OSGI_BOOT_EXCLUDE_SVN = "argeo.osgi.boot.excludeSvn"; + public final static String PROP_ARGEO_OSGI_BOOT_INSTALL_IN_LEXICOGRAPHIC_ORDER = "argeo.osgi.boot.installInLexicographicOrder"; + public final static String PROP_ARGEO_OSGI_BOOT_DEFAULT_TIMEOUT = "argeo.osgi.boot.defaultTimeout"; public final static String PROP_ARGEO_OSGI_BOOT_MODULES_URL_SEPARATOR = "argeo.osgi.boot.modulesUrlSeparator"; public final static String PROP_ARGEO_OSGI_BOOT_SYSTEM_PROPERTIES_FILE = "argeo.osgi.boot.systemPropertiesFile"; public final static String PROP_ARGEO_OSGI_BOOT_APPCLASS = "argeo.osgi.boot.appclass"; public final static String PROP_ARGEO_OSGI_BOOT_APPARGS = "argeo.osgi.boot.appargs"; - /** @deprecated */ - public final static String PROP_SLC_OSGI_START = "slc.osgi.start"; - /** @deprecated */ - public final static String PROP_SLC_OSGI_BUNDLES = "slc.osgi.bundles"; - /** @deprecated */ - public final static String PROP_SLC_OSGI_LOCATIONS = "slc.osgi.locations"; - /** @deprecated */ - public final static String PROP_SLC_OSGI_BASE_URL = "slc.osgi.baseUrl"; - /** @deprecated */ - public final static String PROP_SLC_OSGI_MODULES_URL = "slc.osgi.modulesUrl"; - - /** @deprecated */ - public final static String PROP_SLC_OSGIBOOT_DEBUG = "slc.osgiboot.debug"; - /** @deprecated */ - public final static String PROP_SLC_OSGIBOOT_DEFAULT_TIMEOUT = "slc.osgiboot.defaultTimeout"; - /** @deprecated */ - public final static String PROP_SLC_OSGIBOOT_MODULES_URL_SEPARATOR = "slc.osgiboot.modulesUrlSeparator"; - /** @deprecated */ - public final static String PROP_SLC_OSGIBOOT_SYSTEM_PROPERTIES_FILE = "slc.osgiboot.systemPropertiesFile"; - /** @deprecated */ - public final static String PROP_SLC_OSGIBOOT_APPCLASS = "slc.osgiboot.appclass"; - /** @deprecated */ - public final static String PROP_SLC_OSGIBOOT_APPARGS = "slc.osgiboot.appargs"; - public final static String DEFAULT_BASE_URL = "reference:file:"; public final static String EXCLUDES_SVN_PATTERN = "**/.svn/**"; + // OSGi system properties + public final static String INSTANCE_AREA_PROP = "osgi.instance.area"; + public final static String INSTANCE_AREA_DEFAULT_PROP = "osgi.instance.area.default"; + private boolean debug = Boolean.valueOf( - System.getProperty(PROP_ARGEO_OSGI_BOOT_DEBUG, - System.getProperty(PROP_SLC_OSGIBOOT_DEBUG, "false"))) + System.getProperty(PROP_ARGEO_OSGI_BOOT_DEBUG, "false")) + .booleanValue(); + /** Exclude svn metadata implicitely(a bit costly) */ + private boolean excludeSvn = Boolean.valueOf( + System.getProperty(PROP_ARGEO_OSGI_BOOT_EXCLUDE_SVN, "false")) .booleanValue(); + + /** + * The {@link #installUrls(List)} methods won't follow the list order but + * order the urls according to the alphabetical order of the file names + * (last part of the URL). The goal is to stay closer from Eclipse PDE way + * of installing target platform bundles. + */ + private boolean installInLexicographicOrder = Boolean + .valueOf( + System.getProperty( + PROP_ARGEO_OSGI_BOOT_INSTALL_IN_LEXICOGRAPHIC_ORDER, + "true")).booleanValue();; + /** Default is 10s (set in constructor) */ private long defaultTimeout; - private boolean excludeSvn = true; /** Default is ',' (set in constructor) */ private String modulesUrlSeparator = ","; private final BundleContext bundleContext; + /* + * INITIALIZATION + */ + /** Constructor */ public OsgiBoot(BundleContext bundleContext) { this.bundleContext = bundleContext; - defaultTimeout = Long.parseLong(OsgiBootUtils.getPropertyCompat( - PROP_ARGEO_OSGI_BOOT_DEFAULT_TIMEOUT, - PROP_SLC_OSGIBOOT_DEFAULT_TIMEOUT, "10000")); - modulesUrlSeparator = OsgiBootUtils.getPropertyCompat( - PROP_ARGEO_OSGI_BOOT_MODULES_URL_SEPARATOR, - PROP_SLC_OSGIBOOT_MODULES_URL_SEPARATOR, ","); + defaultTimeout = Long.parseLong(OsgiBootUtils.getProperty( + PROP_ARGEO_OSGI_BOOT_DEFAULT_TIMEOUT, "10000")); + modulesUrlSeparator = OsgiBootUtils.getProperty( + PROP_ARGEO_OSGI_BOOT_MODULES_URL_SEPARATOR, ","); initSystemProperties(); } + /** + * Set additional system properties, especially ${argeo.osgi.data.dir} as an + * OS file path (and not a file:// URL) + */ protected void initSystemProperties() { - String osgiInstanceArea = System.getProperty("osgi.instance.area"); + String osgiInstanceArea = System.getProperty(INSTANCE_AREA_PROP); String osgiInstanceAreaDefault = System - .getProperty("osgi.instance.area.default"); + .getProperty(INSTANCE_AREA_DEFAULT_PROP); String tempDir = System.getProperty("java.io.tmpdir"); File dataDir = null; @@ -131,23 +143,13 @@ public class OsgiBoot { } else {// outside OSGi dataDir = new File(tempDir + File.separator + "argeoOsgiData"); } - System.setProperty(PROP_ARGEO_OSGI_DATA_DIR, dataDir.getAbsolutePath()); - - // TODO: Load additional system properties from file - // Properties additionalSystemProperties = new Properties(); - - } - - public static String removeFilePrefix(String url) { - if (url.startsWith("file:")) - return url.substring("file:".length()); - else if (url.startsWith("reference:file:")) - return url.substring("reference:file:".length()); - else - return url; } + /* + * HIGH-LEVEL METHODS + */ + /** Bootstraps the OSGi runtime */ public void bootstrap() { long begin = System.currentTimeMillis(); System.out.println(); @@ -185,88 +187,125 @@ public class OsgiBoot { System.out.println(); } + /* + * INSTALLATION + */ + /** Install the bundles at this URL list. */ public void installUrls(List urls) { - Map installedBundles = getInstalledBundles(); - for (int i = 0; i < urls.size(); i++) { - String url = (String) urls.get(i); - try { - if (installedBundles.containsKey(url)) { - Bundle bundle = (Bundle) installedBundles.get(url); - // bundle.update(); - if (debug) - debug("Bundle " + bundle.getSymbolicName() - + " already installed from " + url); - } else { - Bundle bundle = bundleContext.installBundle(url); - if (debug) - debug("Installed bundle " + bundle.getSymbolicName() - + " from " + url); - } - } catch (BundleException e) { - String message = e.getMessage(); - if ((message.contains("Bundle \"" + SYMBOLIC_NAME_OSGI_BOOT - + "\"") || message.contains("Bundle \"" - + SYMBOLIC_NAME_EQUINOX + "\"")) - && message.contains("has already been installed")) { - // silent, in order to avoid warnings: we know that both - // have already been installed... - } else { - OsgiBootUtils.warn("Could not install bundle from " + url - + ": " + message); - } - if (debug) - e.printStackTrace(); + Map installedBundles = getBundlesByLocation(); + + if (installInLexicographicOrder) { + SortedMap map = new TreeMap(); + // reorder + for (int i = 0; i < urls.size(); i++) { + String url = (String) urls.get(i); + int index = url.lastIndexOf('/'); + String fileName; + if (index >= 0) + fileName = url.substring(index + 1); + else + fileName = url; + map.put(fileName, url); + } + + // install + Iterator keys = map.keySet().iterator(); + while (keys.hasNext()) { + Object key = keys.next(); + String url = map.get(key).toString(); + installUrl(url, installedBundles); + } + } else { + for (int i = 0; i < urls.size(); i++) { + String url = (String) urls.get(i); + installUrl(url, installedBundles); } } } - public void installOrUpdateUrls(Map urls) { - Map installedBundles = getBundles(); - - for (Iterator modules = urls.keySet().iterator(); modules.hasNext();) { - String moduleName = (String) modules.next(); - String urlStr = (String) urls.get(moduleName); - if (installedBundles.containsKey(moduleName)) { - Bundle bundle = (Bundle) installedBundles.get(moduleName); - InputStream in; - try { - URL url = new URL(urlStr); - in = url.openStream(); - bundle.update(in); - OsgiBootUtils.info("Updated bundle " + moduleName - + " from " + urlStr); - } catch (Exception e) { - throw new RuntimeException("Cannot update " + moduleName - + " from " + urlStr); - } - if (in != null) - try { - in.close(); - } catch (IOException e) { - e.printStackTrace(); - } + /** Actually install the provided URL */ + protected void installUrl(String url, Map installedBundles) { + try { + if (installedBundles.containsKey(url)) { + Bundle bundle = (Bundle) installedBundles.get(url); + // bundle.update(); + if (debug) + debug("Bundle " + bundle.getSymbolicName() + + " already installed from " + url); } else { - try { - Bundle bundle = bundleContext.installBundle(urlStr); - if (debug) - debug("Installed bundle " + bundle.getSymbolicName() - + " from " + urlStr); - } catch (BundleException e) { - OsgiBootUtils.warn("Could not install bundle from " - + urlStr + ": " + e.getMessage()); - } + Bundle bundle = bundleContext.installBundle(url); + if (debug) + debug("Installed bundle " + bundle.getSymbolicName() + + " from " + url); + } + } catch (BundleException e) { + String message = e.getMessage(); + if ((message.contains("Bundle \"" + SYMBOLIC_NAME_OSGI_BOOT + "\"") || message + .contains("Bundle \"" + SYMBOLIC_NAME_EQUINOX + "\"")) + && message.contains("has already been installed")) { + // silent, in order to avoid warnings: we know that both + // have already been installed... + } else { + OsgiBootUtils.warn("Could not install bundle from " + url + + ": " + message); } + if (debug) + e.printStackTrace(); } - } + /* @deprecated Doesn't seem to be used anymore. */ + // public void installOrUpdateUrls(Map urls) { + // Map installedBundles = getBundles(); + // + // for (Iterator modules = urls.keySet().iterator(); modules.hasNext();) { + // String moduleName = (String) modules.next(); + // String urlStr = (String) urls.get(moduleName); + // if (installedBundles.containsKey(moduleName)) { + // Bundle bundle = (Bundle) installedBundles.get(moduleName); + // InputStream in; + // try { + // URL url = new URL(urlStr); + // in = url.openStream(); + // bundle.update(in); + // OsgiBootUtils.info("Updated bundle " + moduleName + // + " from " + urlStr); + // } catch (Exception e) { + // throw new RuntimeException("Cannot update " + moduleName + // + " from " + urlStr); + // } + // if (in != null) + // try { + // in.close(); + // } catch (IOException e) { + // e.printStackTrace(); + // } + // } else { + // try { + // Bundle bundle = bundleContext.installBundle(urlStr); + // if (debug) + // debug("Installed bundle " + bundle.getSymbolicName() + // + " from " + urlStr); + // } catch (BundleException e) { + // OsgiBootUtils.warn("Could not install bundle from " + // + urlStr + ": " + e.getMessage()); + // } + // } + // } + // + // } + + /* + * START + */ public void startBundles() { - String bundlesToStart = OsgiBootUtils.getPropertyCompat( - PROP_ARGEO_OSGI_START, PROP_SLC_OSGI_START); + String bundlesToStart = OsgiBootUtils + .getProperty(PROP_ARGEO_OSGI_START); startBundles(bundlesToStart); } + /** Convenience method accepting a comma-separated list of bundle to start */ public void startBundles(String bundlesToStartStr) { if (bundlesToStartStr == null) return; @@ -280,6 +319,7 @@ public class OsgiBoot { startBundles(bundlesToStart); } + /** Start the provided list of bundles */ public void startBundles(List bundlesToStart) { if (bundlesToStart.size() == 0) return; @@ -296,6 +336,8 @@ public class OsgiBoot { try { try { bundle.start(); + if (debug) + debug("Bundle " + symbolicName + " started"); } catch (Exception e) { OsgiBootUtils.warn("Start of bundle " + symbolicName + " failed because of " + e @@ -320,6 +362,10 @@ public class OsgiBoot { + " not started because it was not found."); } + /* + * DIAGNOSTICS + */ + /** Check unresolved bundles */ protected void checkUnresolved() { // Refresh ServiceReference packageAdminRef = bundleContext @@ -342,10 +388,10 @@ public class OsgiBoot { } } + /** List packages exported twice. */ public Map findPackagesExportedTwice() { ServiceReference paSr = bundleContext .getServiceReference(PackageAdmin.class.getName()); - // TODO: make a cleaner referencing PackageAdmin packageAdmin = (PackageAdmin) bundleContext .getService(paSr); @@ -376,6 +422,7 @@ public class OsgiBoot { return duplicatePackages; } + /** Waits for a bundle to become active or resolved */ protected void waitForBundleResolvedOrActive(long startBegin, Bundle bundle) throws Exception { int originalState = bundle.getState(); @@ -383,7 +430,7 @@ public class OsgiBoot { || (originalState == Bundle.ACTIVE)) return; - String originalStateStr = stateAsString(originalState); + String originalStateStr = OsgiBootUtils.stateAsString(originalState); int currentState = bundle.getState(); while (!(currentState == Bundle.RESOLVED || currentState == Bundle.ACTIVE)) { @@ -393,7 +440,7 @@ public class OsgiBoot { + " was not RESOLVED or ACTIVE after " + (now - startBegin) + "ms (originalState=" + originalStateStr + ", currentState=" - + stateAsString(currentState) + ")"); + + OsgiBootUtils.stateAsString(currentState) + ")"); try { Thread.sleep(100l); @@ -404,169 +451,22 @@ public class OsgiBoot { } } - public static String stateAsString(int state) { - switch (state) { - case Bundle.UNINSTALLED: - return "UNINSTALLED"; - case Bundle.INSTALLED: - return "INSTALLED"; - case Bundle.RESOLVED: - return "RESOLVED"; - case Bundle.STARTING: - return "STARTING"; - case Bundle.ACTIVE: - return "ACTIVE"; - case Bundle.STOPPING: - return "STOPPING"; - default: - return Integer.toString(state); - } - } - - /** Key is location */ - public Map getInstalledBundles() { - Map installedBundles = new HashMap(); - - Bundle[] bundles = bundleContext.getBundles(); - for (int i = 0; i < bundles.length; i++) { - installedBundles.put(bundles[i].getLocation(), bundles[i]); - } - return installedBundles; - } - - /** Key is symbolic name */ - public Map getBundles() { - Map namedBundles = new HashMap(); - Bundle[] bundles = bundleContext.getBundles(); - for (int i = 0; i < bundles.length; i++) { - namedBundles.put(bundles[i].getSymbolicName(), bundles[i]); - } - return namedBundles; - } - + /* + * EXPLICIT LOCATIONS INSTALLATION + */ + /** Gets the list of resolved explicit URL locations. */ public List getLocationsUrls() { - String baseUrl = OsgiBootUtils.getPropertyCompat( - PROP_ARGEO_OSGI_BASE_URL, PROP_SLC_OSGI_BASE_URL, + String baseUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BASE_URL, DEFAULT_BASE_URL); - String bundleLocations = OsgiBootUtils.getPropertyCompat( - PROP_ARGEO_OSGI_LOCATIONS, PROP_SLC_OSGI_LOCATIONS); + String bundleLocations = OsgiBootUtils + .getProperty(PROP_ARGEO_OSGI_LOCATIONS); return getLocationsUrls(baseUrl, bundleLocations); } - public List getModulesUrls() { - List urls = new ArrayList(); - String modulesUrlStr = OsgiBootUtils.getPropertyCompat( - PROP_ARGEO_OSGI_MODULES_URL, PROP_SLC_OSGI_MODULES_URL); - if (modulesUrlStr == null) - return urls; - - String baseUrl = OsgiBootUtils.getPropertyCompat( - PROP_ARGEO_OSGI_BASE_URL, PROP_SLC_OSGI_BASE_URL); - - Map installedBundles = getBundles(); - - BufferedReader reader = null; - try { - URL modulesUrl = new URL(modulesUrlStr); - reader = new BufferedReader(new InputStreamReader( - modulesUrl.openStream())); - String line = null; - while ((line = reader.readLine()) != null) { - StringTokenizer st = new StringTokenizer(line, - modulesUrlSeparator); - String moduleName = st.nextToken(); - String moduleVersion = st.nextToken(); - String url = st.nextToken(); - if (baseUrl != null) - url = baseUrl + url; - - if (installedBundles.containsKey(moduleName)) { - Bundle bundle = (Bundle) installedBundles.get(moduleName); - String bundleVersion = bundle.getHeaders() - .get(Constants.BUNDLE_VERSION).toString(); - int comp = compareVersions(bundleVersion, moduleVersion); - if (comp > 0) { - OsgiBootUtils.warn("Installed version " + bundleVersion - + " of bundle " + moduleName - + " is newer than provided version " - + moduleVersion); - } else if (comp < 0) { - urls.add(url); - OsgiBootUtils.info("Updated bundle " + moduleName - + " with version " + moduleVersion - + " (old version was " + bundleVersion + ")"); - } else { - // do nothing - } - } else { - urls.add(url); - } - } - } catch (Exception e1) { - throw new RuntimeException("Cannot read url " + modulesUrlStr, e1); - } finally { - if (reader != null) - try { - reader.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - return urls; - } - /** - * @return ==0: versions are identical, <0: tested version is newer, >0: - * currentVersion is newer. + * Gets a list of URLs based on explicit locations, resolving placeholder + * ${...} containing system properties, e.g. ${user.home}. */ - protected int compareVersions(String currentVersion, String testedVersion) { - List cToks = new ArrayList(); - StringTokenizer cSt = new StringTokenizer(currentVersion, "."); - while (cSt.hasMoreTokens()) - cToks.add(cSt.nextToken()); - List tToks = new ArrayList(); - StringTokenizer tSt = new StringTokenizer(currentVersion, "."); - while (tSt.hasMoreTokens()) - tToks.add(tSt.nextToken()); - - int comp = 0; - comp: for (int i = 0; i < cToks.size(); i++) { - if (tToks.size() <= i) { - // equals until then, tested shorter - comp = 1; - break comp; - } - - String c = (String) cToks.get(i); - String t = (String) tToks.get(i); - - try { - int cInt = Integer.parseInt(c); - int tInt = Integer.parseInt(t); - if (cInt == tInt) - continue comp; - else { - comp = (cInt - tInt); - break comp; - } - } catch (NumberFormatException e) { - if (c.equals(t)) - continue comp; - else { - comp = c.compareTo(t); - break comp; - } - } - } - - if (comp == 0 && tToks.size() > cToks.size()) { - // equals until then, current shorter - comp = -1; - } - - return comp; - } - public List getLocationsUrls(String baseUrl, String bundleLocations) { List urls = new ArrayList(); @@ -585,21 +485,31 @@ public class OsgiBoot { return urls; } + /* + * BUNDLE PATTERNS INSTALLATION + */ + /** + * Computes a list of URLs based on Ant-like incluide/exclude patterns + * defined by ${argeo.osgi.bundles} with the following format:
+ * /base/directory;in=*.jar;in=**;ex=org.eclipse.osgi_*;jar
+ * WARNING: /base/directory;in=*.jar,\ at the end of a file, + * without a new line causes a '.' to be appended with unexpected side + * effects. + */ public List getBundlesUrls() { - String baseUrl = OsgiBootUtils.getPropertyCompat( - PROP_ARGEO_OSGI_BASE_URL, PROP_SLC_OSGI_BASE_URL, + String baseUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BASE_URL, DEFAULT_BASE_URL); - String bundlePatterns = OsgiBootUtils.getPropertyCompat( - PROP_ARGEO_OSGI_BUNDLES, PROP_SLC_OSGI_BUNDLES); + String bundlePatterns = OsgiBootUtils + .getProperty(PROP_ARGEO_OSGI_BUNDLES); return getBundlesUrls(baseUrl, bundlePatterns); } + /** Implements the path matching logic */ public List getBundlesUrls(String baseUrl, String bundlePatterns) { List urls = new ArrayList(); - - List bundlesSets = new ArrayList(); if (bundlePatterns == null) return urls; + bundlePatterns = SystemPropertyUtils .resolvePlaceholders(bundlePatterns); if (debug) @@ -607,10 +517,12 @@ public class OsgiBoot { + " (excludeSvn=" + excludeSvn + ")"); StringTokenizer st = new StringTokenizer(bundlePatterns, ","); + List bundlesSets = new ArrayList(); while (st.hasMoreTokens()) { bundlesSets.add(new BundlesSet(st.nextToken())); } + // find included List included = new ArrayList(); PathMatcher matcher = new AntPathMatcher(); for (int i = 0; i < bundlesSets.size(); i++) { @@ -621,6 +533,7 @@ public class OsgiBoot { } } + // find excluded List excluded = new ArrayList(); for (int i = 0; i < bundlesSets.size(); i++) { BundlesSet bundlesSet = (BundlesSet) bundlesSets.get(i); @@ -630,6 +543,7 @@ public class OsgiBoot { } } + // construct list for (int i = 0; i < included.size(); i++) { String fullPath = (String) included.get(i); if (!excluded.contains(fullPath)) @@ -639,6 +553,82 @@ public class OsgiBoot { return urls; } + /* + * MODULES LIST INSTALLATION (${argeo.osgi.modulesUrl}) + */ + /** + * Downloads a list of URLs in CSV format from ${argeo.osgi.modulesUrl}:
+ * Bundle-SymbolicName,Bundle-Version,url)
+ * If ${argeo.osgi.baseUrl} is set, URLs will be considered relative paths + * and be concatenated with the base URL, typically the root of a Maven + * repository. + */ + public List getModulesUrls() { + List urls = new ArrayList(); + String modulesUrlStr = OsgiBootUtils + .getProperty(PROP_ARGEO_OSGI_MODULES_URL); + if (modulesUrlStr == null) + return urls; + + String baseUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BASE_URL); + + Map installedBundles = getBundlesBySymbolicName(); + + BufferedReader reader = null; + try { + URL modulesUrl = new URL(modulesUrlStr); + reader = new BufferedReader(new InputStreamReader( + modulesUrl.openStream())); + String line = null; + while ((line = reader.readLine()) != null) { + StringTokenizer st = new StringTokenizer(line, + modulesUrlSeparator); + String moduleName = st.nextToken(); + String moduleVersion = st.nextToken(); + String url = st.nextToken(); + if (baseUrl != null) + url = baseUrl + url; + + if (installedBundles.containsKey(moduleName)) { + Bundle bundle = (Bundle) installedBundles.get(moduleName); + String bundleVersion = bundle.getHeaders() + .get(Constants.BUNDLE_VERSION).toString(); + int comp = OsgiBootUtils.compareVersions(bundleVersion, + moduleVersion); + if (comp > 0) { + OsgiBootUtils.warn("Installed version " + bundleVersion + + " of bundle " + moduleName + + " is newer than provided version " + + moduleVersion); + } else if (comp < 0) { + urls.add(url); + OsgiBootUtils.info("Updated bundle " + moduleName + + " with version " + moduleVersion + + " (old version was " + bundleVersion + ")"); + } else { + // do nothing + } + } else { + urls.add(url); + } + } + } catch (Exception e1) { + throw new RuntimeException("Cannot read url " + modulesUrlStr, e1); + } finally { + if (reader != null) + try { + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return urls; + } + + /* + * HIGH LEVEL UTILITIES + */ + /** Actually performs the matching logic. */ protected void match(PathMatcher matcher, List matched, String base, String currentPath, String pattern) { if (currentPath == null) { @@ -646,7 +636,7 @@ public class OsgiBoot { File baseDir = new File(base.replace('/', File.separatorChar)); File[] files = baseDir.listFiles(); - if (files == null) { + if (files == null && debug) { OsgiBootUtils.warn("Base dir " + baseDir + " has no children, exists=" + baseDir.exists() + ", isDirectory=" + baseDir.isDirectory()); @@ -661,9 +651,9 @@ public class OsgiBoot { return;// don't try deeper if already matched boolean ok = matcher.match(pattern, currentPath); - if (debug) - debug(currentPath + " " + (ok ? "" : " not ") - + " matched with " + pattern); + // if (debug) + // debug(currentPath + " " + (ok ? "" : " not ") + // + " matched with " + pattern); if (ok) { matched.add(fullPath); return; @@ -703,6 +693,40 @@ public class OsgiBoot { } } + protected void matchFile() { + + } + + /* + * LOW LEVEL UTILITIES + */ + /** + * The bundles already installed. Key is location (String) , value is a + * {@link Bundle} + */ + public Map getBundlesByLocation() { + Map installedBundles = new HashMap(); + Bundle[] bundles = bundleContext.getBundles(); + for (int i = 0; i < bundles.length; i++) { + installedBundles.put(bundles[i].getLocation(), bundles[i]); + } + return installedBundles; + } + + /** + * The bundles already installed. Key is symbolic name (String) , value is a + * {@link Bundle} + */ + public Map getBundlesBySymbolicName() { + Map namedBundles = new HashMap(); + Bundle[] bundles = bundleContext.getBundles(); + for (int i = 0; i < bundles.length; i++) { + namedBundles.put(bundles[i].getSymbolicName(), bundles[i]); + } + return namedBundles; + } + + /** Creates an URL from a location */ protected String locationToUrl(String baseUrl, String location) { int extInd = location.lastIndexOf('.'); String ext = null; @@ -720,11 +744,27 @@ public class OsgiBoot { return (basePath + '/' + relativePath).replace('/', File.separatorChar); } + private String removeFilePrefix(String url) { + if (url.startsWith("file:")) + return url.substring("file:".length()); + else if (url.startsWith("reference:file:")) + return url.substring("reference:file:".length()); + else + return url; + } + + /** + * Convenience method to avoid cluttering the code with + * OsgiBootUtils.debug() + */ protected void debug(Object obj) { - if (debug) - OsgiBootUtils.debug(obj); + OsgiBootUtils.debug(obj); } + /* + * BEAN METHODS + */ + public boolean getDebug() { return debug; } @@ -737,7 +777,23 @@ public class OsgiBoot { return bundleContext; } - /** Whether to exclude Subversion directories (true by default) */ + public void setInstallInLexicographicOrder( + boolean installInAlphabeticalOrder) { + this.installInLexicographicOrder = installInAlphabeticalOrder; + } + + public boolean isInstallInLexicographicOrder() { + return installInLexicographicOrder; + } + + public void setDefaultTimeout(long defaultTimeout) { + this.defaultTimeout = defaultTimeout; + } + + public void setModulesUrlSeparator(String modulesUrlSeparator) { + this.modulesUrlSeparator = modulesUrlSeparator; + } + public boolean isExcludeSvn() { return excludeSvn; } @@ -746,6 +802,11 @@ public class OsgiBoot { this.excludeSvn = excludeSvn; } + /* + * INTERNAL CLASSES + */ + + /** Intermediary structure used by path matching */ protected class BundlesSet { private String baseUrl = "reference:file";// not used yet private final String dir; @@ -810,12 +871,4 @@ public class OsgiBoot { } - public void setDefaultTimeout(long defaultTimeout) { - this.defaultTimeout = defaultTimeout; - } - - public void setModulesUrlSeparator(String modulesUrlSeparator) { - this.modulesUrlSeparator = modulesUrlSeparator; - } - }