X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=runtime%2Forg.argeo.slc.osgiboot%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Fosgiboot%2FOsgiBoot.java;h=fcefc8345e974986d70255920605af9619a01d46;hb=8eb028e332cb2be50ed311a0501f7efce5849d44;hp=fdcb77df07abfb513572dce2165b32e55886414c;hpb=7274972217cf5bb6772e8833c5723a5f9544ddb5;p=gpl%2Fargeo-slc.git diff --git a/runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/OsgiBoot.java b/runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/OsgiBoot.java index fdcb77df0..fcefc8345 100644 --- a/runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/OsgiBoot.java +++ b/runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/OsgiBoot.java @@ -1,9 +1,14 @@ package org.argeo.slc.osgiboot; +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; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; @@ -14,18 +19,25 @@ import org.argeo.slc.osgiboot.internal.springutil.SystemPropertyUtils; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; public class OsgiBoot { public final static String PROP_SLC_OSGI_START = "slc.osgi.start"; public final static String PROP_SLC_OSGI_BUNDLES = "slc.osgi.bundles"; public final static String PROP_SLC_OSGI_LOCATIONS = "slc.osgi.locations"; public final static String PROP_SLC_OSGI_BASE_URL = "slc.osgi.baseUrl"; + public final static String PROP_SLC_OSGI_MODULES_URL = "slc.osgi.modulesUrl"; public final static String PROP_SLC_OSGIBOOT_DEBUG = "slc.osgiboot.debug"; public final static String DEFAULT_BASE_URL = "reference:file:"; + public final static String EXCLUDES_SVN_PATTERN = "**/.svn/**"; - private Boolean debug = Boolean.parseBoolean(System.getProperty( - PROP_SLC_OSGIBOOT_DEBUG, "false")); + private boolean debug = Boolean.valueOf( + System.getProperty(PROP_SLC_OSGIBOOT_DEBUG, "false")) + .booleanValue(); + + private boolean excludeSvn = true; + private String modulesUrlSeparator = ";"; private final BundleContext bundleContext; @@ -33,12 +45,22 @@ public class OsgiBoot { this.bundleContext = bundleContext; } - public void installUrls(List urls) { - Map installedBundles = getInstalledBundles(); - for (String url : urls) { + public void bootstrap() { + info("SLC OSGi bootstrap starting..."); + installUrls(getBundlesUrls()); + installUrls(getLocationsUrls()); + installUrls(getModulesUrls()); + startBundles(); + info("SLC OSGi bootstrap completed"); + } + + 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 = installedBundles.get(url); + Bundle bundle = (Bundle) installedBundles.get(url); // bundle.update(); if (debug) debug("Bundle " + bundle.getSymbolicName() @@ -57,114 +79,293 @@ public class OsgiBoot { } - public void startBundles() throws Exception { + 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); + 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) { + warn("Could not install bundle from " + urlStr + ": " + + e.getMessage()); + } + } + } + + } + + public void startBundles() { String bundlesToStart = getProperty(PROP_SLC_OSGI_START); startBundles(bundlesToStart); } - public void startBundles(String bundlesToStart) throws Exception { - if (bundlesToStart == null) + public void startBundles(String bundlesToStartStr) { + if (bundlesToStartStr == null) return; - StringTokenizer st = new StringTokenizer(bundlesToStart, ","); - Map bundles = getBundles(); + StringTokenizer st = new StringTokenizer(bundlesToStartStr, ","); + List bundlesToStart = new ArrayList(); while (st.hasMoreTokens()) { String name = st.nextToken().trim(); - Bundle bundle = bundles.get(name); - if (bundle != null) + bundlesToStart.add(name); + } + startBundles(bundlesToStart); + } + + public void startBundles(List bundlesToStart) { + if (bundlesToStart.size() == 0) + return; + + List notStartedBundles = new ArrayList(bundlesToStart); + Bundle[] bundles = bundleContext.getBundles(); + for (int i = 0; i < bundles.length; i++) { + Bundle bundle = bundles[i]; + String symbolicName = bundle.getSymbolicName(); + if (bundlesToStart.contains(symbolicName)) try { bundle.start(); + notStartedBundles.remove(symbolicName); } catch (Exception e) { - warn("Bundle " + name + " cannot be started: " + warn("Bundle " + symbolicName + " cannot be started: " + e.getMessage()); } - else - warn("Bundle " + name + " not installed."); - } + + for (int i = 0; i < notStartedBundles.size(); i++) + warn("Bundle " + notStartedBundles.get(i) + + " not started because it was not found."); } /** Key is location */ - public Map getInstalledBundles() { - Map installedBundles = new HashMap(); + public Map getInstalledBundles() { + Map installedBundles = new HashMap(); - for (Bundle bundle : bundleContext.getBundles()) { - installedBundles.put(bundle.getLocation(), bundle); + 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 installedBundles = new HashMap(); - for (Bundle bundle : bundleContext.getBundles()) - installedBundles.put(bundle.getSymbolicName(), bundle); - return installedBundles; + 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; } - public List getLocationsUrls() { + public List getLocationsUrls() { String baseUrl = getProperty(PROP_SLC_OSGI_BASE_URL, DEFAULT_BASE_URL); String bundleLocations = getProperty(PROP_SLC_OSGI_LOCATIONS); return getLocationsUrls(baseUrl, bundleLocations); } - public List getLocationsUrls(String baseUrl, String bundleLocations) { - List urls = new ArrayList(); + public List getModulesUrls() { + List urls = new ArrayList(); + String modulesUrlStr = getProperty(PROP_SLC_OSGI_MODULES_URL); + if (modulesUrlStr == null) + return urls; + + 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 (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) { + warn("Installed version " + bundleVersion + + " of bundle " + moduleName + + " is newer than provided version " + + moduleVersion); + } else if (comp < 0) { + urls.add(url); + 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. + */ + 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(); if (bundleLocations == null) return urls; bundleLocations = SystemPropertyUtils .resolvePlaceholders(bundleLocations); + if (debug) + debug(PROP_SLC_OSGI_LOCATIONS + "=" + bundleLocations); StringTokenizer st = new StringTokenizer(bundleLocations, File.pathSeparator); while (st.hasMoreTokens()) { - urls.add(baseUrl + st.nextToken().trim()); + urls.add(locationToUrl(baseUrl, st.nextToken().trim())); } return urls; } - public List getBundlesUrls() { + public List getBundlesUrls() { String baseUrl = getProperty(PROP_SLC_OSGI_BASE_URL, DEFAULT_BASE_URL); String bundlePatterns = getProperty(PROP_SLC_OSGI_BUNDLES); return getBundlesUrls(baseUrl, bundlePatterns); } - public List getBundlesUrls(String baseUrl, String bundlePatterns) { - List urls = new ArrayList(); + public List getBundlesUrls(String baseUrl, String bundlePatterns) { + List urls = new ArrayList(); - List bundlesSets = new ArrayList(); + List bundlesSets = new ArrayList(); if (bundlePatterns == null) return urls; - // TODO: resolve placeholders - info(PROP_SLC_OSGI_BUNDLES + "=" + bundlePatterns); + bundlePatterns = SystemPropertyUtils + .resolvePlaceholders(bundlePatterns); + if (debug) + debug(PROP_SLC_OSGI_BUNDLES + "=" + bundlePatterns + + " (excludeSvn=" + excludeSvn + ")"); StringTokenizer st = new StringTokenizer(bundlePatterns, ","); while (st.hasMoreTokens()) { bundlesSets.add(new BundlesSet(st.nextToken())); } - List included = new ArrayList(); + List included = new ArrayList(); PathMatcher matcher = new AntPathMatcher(); - for (BundlesSet bundlesSet : bundlesSets) - for (String pattern : bundlesSet.getIncludes()) + for (int i = 0; i < bundlesSets.size(); i++) { + BundlesSet bundlesSet = (BundlesSet) bundlesSets.get(i); + for (int j = 0; j < bundlesSet.getIncludes().size(); j++) { + String pattern = (String) bundlesSet.getIncludes().get(j); match(matcher, included, bundlesSet.getDir(), null, pattern); + } + } - List excluded = new ArrayList(); - for (BundlesSet bundlesSet : bundlesSets) - for (String pattern : bundlesSet.getExcludes()) + List excluded = new ArrayList(); + for (int i = 0; i < bundlesSets.size(); i++) { + BundlesSet bundlesSet = (BundlesSet) bundlesSets.get(i); + for (int j = 0; j < bundlesSet.getExcludes().size(); j++) { + String pattern = (String) bundlesSet.getExcludes().get(j); match(matcher, excluded, bundlesSet.getDir(), null, pattern); + } + } - for (String fullPath : included) { + for (int i = 0; i < included.size(); i++) { + String fullPath = (String) included.get(i); if (!excluded.contains(fullPath)) - urls.add(baseUrl + fullPath); + urls.add(locationToUrl(baseUrl, fullPath)); } return urls; } - protected void match(PathMatcher matcher, List matched, - String base, String currentPath, String pattern) { + protected void match(PathMatcher matcher, List matched, String base, + String currentPath, String pattern) { if (currentPath == null) { // Init File baseDir = new File(base.replace('/', File.separatorChar)); @@ -177,8 +378,8 @@ public class OsgiBoot { return; } - for (File file : files) - match(matcher, matched, base, file.getName(), pattern); + for (int i = 0; i < files.length; i++) + match(matcher, matched, base, files[i].getName(), pattern); } else { String fullPath = base + '/' + currentPath; if (matched.contains(fullPath)) @@ -192,14 +393,14 @@ public class OsgiBoot { matched.add(fullPath); return; } else { - String newFullPath = (base + '/' + currentPath).replace('/', - File.separatorChar); - File[] files = new File(newFullPath).listFiles(); + String newFullPath = relativeToFullPath(base, currentPath); + File newFile = new File(newFullPath); + File[] files = newFile.listFiles(); if (files != null) { - for (File file : files) - if (file.isDirectory()) { - String newCurrentPath = currentPath + '/' - + file.getName(); + for (int i = 0; i < files.length; i++) { + String newCurrentPath = currentPath + '/' + + files[i].getName(); + if (files[i].isDirectory()) { if (matcher.matchStart(pattern, newCurrentPath)) { // recurse only if start matches match(matcher, matched, base, newCurrentPath, @@ -211,21 +412,46 @@ public class OsgiBoot { + pattern); } + } else { + boolean nonDirectoryOk = matcher.match(pattern, + newCurrentPath); + if (debug) + debug(currentPath + " " + (ok ? "" : " not ") + + " matched with " + pattern); + if (nonDirectoryOk) + matched.add(relativeToFullPath(base, + newCurrentPath)); } - } else { - warn("Not a directory: " + newFullPath); + } } } } } - protected void info(Object obj) { - System.out.println("# INFO " + obj); + protected String locationToUrl(String baseUrl, String location) { + int extInd = location.lastIndexOf('.'); + String ext = null; + if (extInd > 0) + ext = location.substring(extInd); + + if (baseUrl.startsWith("reference:") && ".jar".equals(ext)) + return "file:" + location; + else + return baseUrl + location; + } + + /** Transforms a relative path in a full system path. */ + protected String relativeToFullPath(String basePath, String relativePath) { + return (basePath + '/' + relativePath).replace('/', File.separatorChar); + } + + protected static void info(Object obj) { + System.out.println("#OSGiBOOT# " + obj); } protected void debug(Object obj) { if (debug) - System.out.println("# DBUG " + obj); + System.out.println("#OSGiBOOT DEBUG# " + obj); } protected void warn(Object obj) { @@ -254,11 +480,11 @@ public class OsgiBoot { return getProperty(name, null); } - public Boolean getDebug() { + public boolean getDebug() { return debug; } - public void setDebug(Boolean debug) { + public void setDebug(boolean debug) { this.debug = debug; } @@ -266,11 +492,20 @@ public class OsgiBoot { return bundleContext; } - private class BundlesSet { + /** Whether to exclude Subversion directories (true by default) */ + public boolean isExcludeSvn() { + return excludeSvn; + } + + public void setExcludeSvn(boolean excludeSvn) { + this.excludeSvn = excludeSvn; + } + + protected class BundlesSet { private String baseUrl = "reference:file";// not used yet private final String dir; - private List includes = new ArrayList(); - private List excludes = new ArrayList(); + private List includes = new ArrayList(); + private List excludes = new ArrayList(); public BundlesSet(String def) { StringTokenizer st = new StringTokenizer(def, ";"); @@ -279,6 +514,10 @@ public class OsgiBoot { throw new RuntimeException("Base dir not defined."); try { String dirPath = st.nextToken(); + + if (dirPath.startsWith("file:")) + dirPath = dirPath.substring("file:".length()); + dir = new File(dirPath.replace('/', File.separatorChar)) .getCanonicalPath(); if (debug) @@ -302,17 +541,21 @@ public class OsgiBoot { System.err.println("Unkown bundles pattern type " + type); } } + + if (excludeSvn && !excludes.contains(EXCLUDES_SVN_PATTERN)) { + excludes.add(EXCLUDES_SVN_PATTERN); + } } public String getDir() { return dir; } - public List getIncludes() { + public List getIncludes() { return includes; } - public List getExcludes() { + public List getExcludes() { return excludes; }