X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;ds=sidebyside;f=org.argeo.osgi.boot%2Fsrc%2Forg%2Fargeo%2Fosgi%2Fboot%2FOsgiBoot.java;h=4c3ee40f0c2095da9860af6f4ef4316a72ae5c59;hb=9257c2d88d0900a10cb69fe4985df335b475ac20;hp=f44642d526fd8c8a2e429ffa1144aac042c52a1f;hpb=86e5f79860a8b3013b40a36c1f06c828d52f5249;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.osgi.boot/src/org/argeo/osgi/boot/OsgiBoot.java b/org.argeo.osgi.boot/src/org/argeo/osgi/boot/OsgiBoot.java index f44642d52..4c3ee40f0 100644 --- a/org.argeo.osgi.boot/src/org/argeo/osgi/boot/OsgiBoot.java +++ b/org.argeo.osgi.boot/src/org/argeo/osgi/boot/OsgiBoot.java @@ -19,6 +19,7 @@ import static org.argeo.osgi.boot.OsgiBootUtils.debug; import static org.argeo.osgi.boot.OsgiBootUtils.warn; import java.io.File; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -30,6 +31,7 @@ import java.util.SortedMap; import java.util.StringTokenizer; import java.util.TreeMap; +import org.argeo.osgi.boot.a2.ProvisioningManager; import org.argeo.osgi.boot.internal.springutil.AntPathMatcher; import org.argeo.osgi.boot.internal.springutil.PathMatcher; import org.argeo.osgi.boot.internal.springutil.SystemPropertyUtils; @@ -49,6 +51,8 @@ import org.osgi.framework.wiring.FrameworkWiring; */ public class OsgiBoot implements OsgiBootConstants { public final static String PROP_ARGEO_OSGI_START = "argeo.osgi.start"; + public final static String PROP_ARGEO_OSGI_SOURCES = "argeo.osgi.sources"; + public final static String PROP_ARGEO_OSGI_BUNDLES = "argeo.osgi.bundles"; public final static String PROP_ARGEO_OSGI_BASE_URL = "argeo.osgi.baseUrl"; public final static String PROP_ARGEO_OSGI_LOCAL_CACHE = "argeo.osgi.localCache"; @@ -67,9 +71,10 @@ public class OsgiBoot implements OsgiBootConstants { // public final static String EXCLUDES_SVN_PATTERN = "**/.svn/**"; // OSGi system properties - public final static String PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL = "osgi.bundles.defaultStartLevel"; - public final static String PROP_OSGI_STARTLEVEL = "osgi.startLevel"; - public final static String INSTANCE_AREA_PROP = "osgi.instance.area"; + final static String PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL = "osgi.bundles.defaultStartLevel"; + final static String PROP_OSGI_STARTLEVEL = "osgi.startLevel"; + final static String INSTANCE_AREA_PROP = "osgi.instance.area"; + final static String CONFIGURATION_AREA_PROP = "osgi.configuration.area"; // Symbolic names public final static String SYMBOLIC_NAME_OSGI_BOOT = "org.argeo.osgi.boot"; @@ -82,19 +87,36 @@ public class OsgiBoot implements OsgiBootConstants { // .booleanValue(); /** Default is 10s */ - // private long defaultTimeout = 10000l; + @Deprecated + private long defaultTimeout = 10000l; private final BundleContext bundleContext; private final String localCache; + private final ProvisioningManager provisioningManager; + /* * INITIALIZATION */ /** Constructor */ public OsgiBoot(BundleContext bundleContext) { this.bundleContext = bundleContext; - localCache = getProperty(PROP_ARGEO_OSGI_LOCAL_CACHE, - "file://" + System.getProperty("user.home") + "/.m2/repository/"); + String homeUri = Paths.get(System.getProperty("user.home")).toUri().toString(); + localCache = getProperty(PROP_ARGEO_OSGI_LOCAL_CACHE, homeUri + ".m2/repository/"); + + provisioningManager = new ProvisioningManager(bundleContext); + String sources = getProperty(PROP_ARGEO_OSGI_SOURCES); + if (sources == null) { + provisioningManager.registerDefaultSource(); + } else { + for (String source : sources.split(",")) { + provisioningManager.registerSource(source); + } + } + } + + ProvisioningManager getProvisioningManager() { + return provisioningManager; } /* @@ -110,6 +132,7 @@ public class OsgiBoot implements OsgiBootConstants { .info("OSGi bootstrap starting" + (osgiInstancePath != null ? " (" + osgiInstancePath + ")" : "")); installUrls(getBundlesUrls()); installUrls(getDistributionUrls()); + provisioningManager.install(null); startBundles(); long duration = System.currentTimeMillis() - begin; OsgiBootUtils.info("OSGi bootstrap completed in " + Math.round(((double) duration) / 1000) + "s (" @@ -140,6 +163,10 @@ public class OsgiBoot implements OsgiBootConstants { System.out.println(); } + public void update() { + provisioningManager.update(); + } + /* * INSTALLATION */ @@ -181,11 +208,16 @@ public class OsgiBoot implements OsgiBootConstants { else if (OsgiBootUtils.debug) OsgiBootUtils.debug( "Installed " + bundle.getSymbolicName() + "-" + bundle.getVersion() + " from " + url); + assert bundle.getSymbolicName() != null; // uninstall previous versions bundles: for (Bundle b : bundleContext.getBundles()) { + if (b.getSymbolicName() == null) + continue bundles; if (bundle.getSymbolicName().equals(b.getSymbolicName())) { Version bundleV = bundle.getVersion(); Version bV = b.getVersion(); + if (bV == null) + continue bundles; if (bundleV.getMajor() == bV.getMajor() && bundleV.getMinor() == bV.getMinor()) { if (bundleV.getMicro() > bV.getMicro()) { // uninstall older bundles @@ -208,16 +240,21 @@ public class OsgiBoot implements OsgiBootConstants { } } } catch (BundleException e) { + final String ALREADY_INSTALLED = "is already installed"; String message = e.getMessage(); if ((message.contains("Bundle \"" + SYMBOLIC_NAME_OSGI_BOOT + "\"") || message.contains("Bundle \"" + SYMBOLIC_NAME_EQUINOX + "\"")) - && message.contains("is already installed")) { + && message.contains(ALREADY_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 (message.contains(ALREADY_INSTALLED)) { + if (OsgiBootUtils.isDebug()) + OsgiBootUtils.warn("Duplicate install from " + url + ": " + message); + } else + OsgiBootUtils.warn("Could not install bundle from " + url + ": " + message); } - if (OsgiBootUtils.debug && !message.contains("is already installed")) + if (OsgiBootUtils.debug && !message.contains(ALREADY_INSTALLED)) e.printStackTrace(); } } @@ -271,7 +308,7 @@ public class OsgiBoot implements OsgiBootConstants { }); } - public static void computeStartLevels(SortedMap> startLevels, Properties properties, + private static void computeStartLevels(SortedMap> startLevels, Properties properties, Integer defaultStartLevel) { // default (and previously, only behaviour) @@ -324,122 +361,112 @@ public class OsgiBoot implements OsgiBootConstants { * @return whether all bundles are now in active state * @deprecated */ - // @Deprecated - // public boolean startBundles(List bundlesToStart) { - // if (bundlesToStart.size() == 0) - // return true; - // - // // used to monitor ACTIVE states - // List startedBundles = new ArrayList(); - // // used to log the bundles not found - // List notFoundBundles = new ArrayList(bundlesToStart); - // - // Bundle[] bundles = bundleContext.getBundles(); - // long startBegin = System.currentTimeMillis(); - // for (int i = 0; i < bundles.length; i++) { - // Bundle bundle = bundles[i]; - // String symbolicName = bundle.getSymbolicName(); - // if (bundlesToStart.contains(symbolicName)) - // try { - // try { - // bundle.start(); - // if (OsgiBootUtils.debug) - // debug("Bundle " + symbolicName + " started"); - // } catch (Exception e) { - // OsgiBootUtils.warn("Start of bundle " + symbolicName + " failed because - // of " + e - // + ", maybe bundle is not yet resolved," + " waiting and trying again."); - // waitForBundleResolvedOrActive(startBegin, bundle); - // bundle.start(); - // startedBundles.add(bundle); - // } - // notFoundBundles.remove(symbolicName); - // } catch (Exception e) { - // OsgiBootUtils.warn("Bundle " + symbolicName + " cannot be started: " + - // e.getMessage()); - // if (OsgiBootUtils.debug) - // e.printStackTrace(); - // // was found even if start failed - // notFoundBundles.remove(symbolicName); - // } - // } - // - // for (int i = 0; i < notFoundBundles.size(); i++) - // OsgiBootUtils.warn("Bundle '" + notFoundBundles.get(i) + "' not started - // because it was not found."); - // - // // monitors that all bundles are started - // long beginMonitor = System.currentTimeMillis(); - // boolean allStarted = !(startedBundles.size() > 0); - // List notStarted = new ArrayList(); - // while (!allStarted && (System.currentTimeMillis() - beginMonitor) < - // defaultTimeout) { - // notStarted = new ArrayList(); - // allStarted = true; - // for (int i = 0; i < startedBundles.size(); i++) { - // Bundle bundle = (Bundle) startedBundles.get(i); - // // TODO check behaviour of lazs bundles - // if (bundle.getState() != Bundle.ACTIVE) { - // allStarted = false; - // notStarted.add(bundle.getSymbolicName()); - // } - // } - // try { - // Thread.sleep(100); - // } catch (InterruptedException e) { - // // silent - // } - // } - // long duration = System.currentTimeMillis() - beginMonitor; - // - // if (!allStarted) - // for (int i = 0; i < notStarted.size(); i++) - // OsgiBootUtils.warn("Bundle '" + notStarted.get(i) + "' not ACTIVE after " - // + (duration / 1000) + "s"); - // - // return allStarted; - // } + @Deprecated + public boolean startBundles(List bundlesToStart) { + if (bundlesToStart.size() == 0) + return true; + + // used to monitor ACTIVE states + List startedBundles = new ArrayList(); + // used to log the bundles not found + List notFoundBundles = new ArrayList(bundlesToStart); + + Bundle[] bundles = bundleContext.getBundles(); + long startBegin = System.currentTimeMillis(); + for (int i = 0; i < bundles.length; i++) { + Bundle bundle = bundles[i]; + String symbolicName = bundle.getSymbolicName(); + if (bundlesToStart.contains(symbolicName)) + try { + try { + bundle.start(); + if (OsgiBootUtils.debug) + debug("Bundle " + symbolicName + " started"); + } catch (Exception e) { + OsgiBootUtils.warn("Start of bundle " + symbolicName + " failed because of " + e + + ", maybe bundle is not yet resolved," + " waiting and trying again."); + waitForBundleResolvedOrActive(startBegin, bundle); + bundle.start(); + startedBundles.add(bundle); + } + notFoundBundles.remove(symbolicName); + } catch (Exception e) { + OsgiBootUtils.warn("Bundle " + symbolicName + " cannot be started: " + e.getMessage()); + if (OsgiBootUtils.debug) + e.printStackTrace(); + // was found even if start failed + notFoundBundles.remove(symbolicName); + } + } + + for (int i = 0; i < notFoundBundles.size(); i++) + OsgiBootUtils.warn("Bundle '" + notFoundBundles.get(i) + "' not started because it was not found."); + + // monitors that all bundles are started + long beginMonitor = System.currentTimeMillis(); + boolean allStarted = !(startedBundles.size() > 0); + List notStarted = new ArrayList(); + while (!allStarted && (System.currentTimeMillis() - beginMonitor) < defaultTimeout) { + notStarted = new ArrayList(); + allStarted = true; + for (int i = 0; i < startedBundles.size(); i++) { + Bundle bundle = (Bundle) startedBundles.get(i); + // TODO check behaviour of lazs bundles + if (bundle.getState() != Bundle.ACTIVE) { + allStarted = false; + notStarted.add(bundle.getSymbolicName()); + } + } + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // silent + } + } + long duration = System.currentTimeMillis() - beginMonitor; + + if (!allStarted) + for (int i = 0; i < notStarted.size(); i++) + OsgiBootUtils.warn("Bundle '" + notStarted.get(i) + "' not ACTIVE after " + (duration / 1000) + "s"); + + return allStarted; + } /** Waits for a bundle to become active or resolved */ - // private void waitForBundleResolvedOrActive(long startBegin, Bundle - // bundle) throws Exception { - // int originalState = bundle.getState(); - // if ((originalState == Bundle.RESOLVED) || (originalState == - // Bundle.ACTIVE)) - // return; - // - // String originalStateStr = OsgiBootUtils.stateAsString(originalState); - // - // int currentState = bundle.getState(); - // while (!(currentState == Bundle.RESOLVED || currentState == - // Bundle.ACTIVE)) { - // long now = System.currentTimeMillis(); - // if ((now - startBegin) > defaultTimeout * 10) - // throw new Exception("Bundle " + bundle.getSymbolicName() + " was not - // RESOLVED or ACTIVE after " - // + (now - startBegin) + "ms (originalState=" + originalStateStr + ", - // currentState=" - // + OsgiBootUtils.stateAsString(currentState) + ")"); - // - // try { - // Thread.sleep(100l); - // } catch (InterruptedException e) { - // // silent - // } - // currentState = bundle.getState(); - // } - // } + @Deprecated + private void waitForBundleResolvedOrActive(long startBegin, Bundle bundle) throws Exception { + int originalState = bundle.getState(); + if ((originalState == Bundle.RESOLVED) || (originalState == Bundle.ACTIVE)) + return; + + String originalStateStr = OsgiBootUtils.stateAsString(originalState); + + int currentState = bundle.getState(); + while (!(currentState == Bundle.RESOLVED || currentState == Bundle.ACTIVE)) { + long now = System.currentTimeMillis(); + if ((now - startBegin) > defaultTimeout * 10) + throw new Exception("Bundle " + bundle.getSymbolicName() + " was not RESOLVED or ACTIVE after " + + (now - startBegin) + "ms (originalState=" + originalStateStr + ", currentState=" + + OsgiBootUtils.stateAsString(currentState) + ")"); + + try { + Thread.sleep(100l); + } catch (InterruptedException e) { + // silent + } + currentState = bundle.getState(); + } + } /* * BUNDLE PATTERNS INSTALLATION */ /** - * Computes a list of URLs based on Ant-like include/exclude patterns - * defined by ${argeo.osgi.bundles} with the following format:
+ * Computes a list of URLs based on Ant-like include/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. + * without a new line causes a '.' to be appended with unexpected side effects. */ public List getBundlesUrls() { String bundlePatterns = getProperty(PROP_ARGEO_OSGI_BUNDLES); @@ -447,7 +474,7 @@ public class OsgiBoot implements OsgiBootConstants { } /** - * Compute alist of URLs to install based on the provided patterns, with + * Compute a list of URLs to install based on the provided patterns, with * default base url */ public List getBundlesUrls(String bundlePatterns) { @@ -456,7 +483,7 @@ public class OsgiBoot implements OsgiBootConstants { } /** Implements the path matching logic */ - List getBundlesUrls(String baseUrl, String bundlePatterns) { + public List getBundlesUrls(String baseUrl, String bundlePatterns) { List urls = new ArrayList(); if (bundlePatterns == null) return urls; @@ -522,15 +549,44 @@ public class OsgiBoot implements OsgiBootConstants { return urls; DistributionBundle distributionBundle; - if (baseUrl != null && !(distributionUrl.startsWith("http") || distributionUrl.startsWith("file"))) { - // relative url - distributionBundle = new DistributionBundle(baseUrl, distributionUrl, localCache); - } else { + if (distributionUrl.startsWith("http") || distributionUrl.startsWith("file")) { distributionBundle = new DistributionBundle(distributionUrl); if (baseUrl != null) distributionBundle.setBaseUrl(baseUrl); + } else { + // relative url + if (baseUrl == null) { + baseUrl = localCache; + } + + if (distributionUrl.contains(":")) { + // TODO make it safer + String[] parts = distributionUrl.trim().split(":"); + String[] categoryParts = parts[0].split("\\."); + String artifactId = parts[1]; + String version = parts[2]; + StringBuilder sb = new StringBuilder(); + for (String categoryPart : categoryParts) { + sb.append(categoryPart).append('/'); + } + sb.append(artifactId).append('/'); + sb.append(version).append('/'); + sb.append(artifactId).append('-').append(version).append(".jar"); + distributionUrl = sb.toString(); + } + distributionBundle = new DistributionBundle(baseUrl, distributionUrl, localCache); } + // if (baseUrl != null && !(distributionUrl.startsWith("http") || + // distributionUrl.startsWith("file"))) { + // // relative url + // distributionBundle = new DistributionBundle(baseUrl, distributionUrl, + // localCache); + // } else { + // distributionBundle = new DistributionBundle(distributionUrl); + // if (baseUrl != null) + // distributionBundle.setBaseUrl(baseUrl); + // } distributionBundle.processUrl(); return distributionBundle.listUrls(); } @@ -677,6 +733,10 @@ public class OsgiBoot implements OsgiBootConstants { return bundleContext; } + public String getLocalCache() { + return localCache; + } + // public void setDefaultTimeout(long defaultTimeout) { // this.defaultTimeout = defaultTimeout; // }