X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.init%2Fsrc%2Forg%2Fargeo%2Finit%2Fosgi%2FOsgiBoot.java;h=963bab4d495e4349bcc7ba409141deb7e2fa94b7;hb=faeeb8f0ba92b640942d88782ca6f5cfc332597e;hp=67ee7b6dffd32189e316f365afbbef6ecc38f7a8;hpb=722dc6b20b15014e3d963bd09617ddfd9b63a89f;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.init/src/org/argeo/init/osgi/OsgiBoot.java b/org.argeo.init/src/org/argeo/init/osgi/OsgiBoot.java index 67ee7b6df..963bab4d4 100644 --- a/org.argeo.init/src/org/argeo/init/osgi/OsgiBoot.java +++ b/org.argeo.init/src/org/argeo/init/osgi/OsgiBoot.java @@ -1,20 +1,26 @@ package org.argeo.init.osgi; -import static org.argeo.init.osgi.OsgiBootUtils.debug; -import static org.argeo.init.osgi.OsgiBootUtils.warn; +import static java.lang.System.Logger.Level.DEBUG; +import static java.lang.System.Logger.Level.ERROR; +import static java.lang.System.Logger.Level.TRACE; +import static java.lang.System.Logger.Level.WARNING; import java.io.File; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.PathMatcher; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Properties; +import java.util.Optional; +import java.util.ServiceLoader; import java.util.Set; import java.util.SortedMap; import java.util.StringTokenizer; @@ -28,6 +34,8 @@ import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.FrameworkEvent; import org.osgi.framework.Version; +import org.osgi.framework.launch.Framework; +import org.osgi.framework.launch.FrameworkFactory; import org.osgi.framework.startlevel.BundleStartLevel; import org.osgi.framework.startlevel.FrameworkStartLevel; import org.osgi.framework.wiring.FrameworkWiring; @@ -37,7 +45,9 @@ import org.osgi.framework.wiring.FrameworkWiring; * properties. The approach is to generate list of URLs based on various * methods, configured via properties. */ -public class OsgiBoot implements OsgiBootConstants { +public class OsgiBoot { + private final static Logger logger = System.getLogger(OsgiBoot.class.getName()); + @Deprecated final static String PROP_ARGEO_OSGI_BUNDLES = "argeo.osgi.bundles"; final static String PROP_ARGEO_OSGI_BASE_URL = "argeo.osgi.baseUrl"; @@ -89,19 +99,19 @@ public class OsgiBoot implements OsgiBootConstants { provisioningManager.registerSource( A2Source.SCHEME_A2 + "://" + homePath.toString() + "/.local/share/a2" + queryPart); provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/local/share/a2" + queryPart); - provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/local/lib/a2" + queryPart); +// provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/local/lib/a2" + queryPart); provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/share/a2" + queryPart); - provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/lib/a2" + queryPart); +// provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/lib/a2" + queryPart); } else if (source.trim().equals(A2Source.DEFAULT_A2_REFERENCE_URI)) { if (Files.exists(homePath)) provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + "://" + homePath.toString() + "/.local/share/a2" + queryPart); provisioningManager .registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/local/share/a2" + queryPart); - provisioningManager - .registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/local/lib/a2" + queryPart); +// provisioningManager +// .registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/local/lib/a2" + queryPart); provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/share/a2" + queryPart); - provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/lib/a2" + queryPart); +// provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/lib/a2" + queryPart); } else { provisioningManager.registerSource(source + queryPart); } @@ -121,74 +131,61 @@ public class OsgiBoot implements OsgiBootConstants { * with {@link BundleContext#getProperty(String)}. If these properties are * null, system properties are used instead. */ - public void bootstrap(Map properties) { + public void bootstrap() { try { long begin = System.currentTimeMillis(); - - // notify start - String osgiInstancePath = getProperty(InitConstants.PROP_OSGI_INSTANCE_AREA); - String osgiConfigurationPath = getProperty(InitConstants.PROP_OSGI_CONFIGURATION_AREA); - String osgiSharedConfigurationPath = getProperty(InitConstants.PROP_OSGI_CONFIGURATION_AREA); - OsgiBootUtils.info("OSGi bootstrap starting" // - + (osgiInstancePath != null ? " data: " + osgiInstancePath + "" : "") // - + (osgiConfigurationPath != null ? " state: " + osgiConfigurationPath + "" : "") // - + (osgiSharedConfigurationPath != null ? " config: " + osgiSharedConfigurationPath + "" : "") // - ); - - // legacy install bundles - installUrls(getBundlesUrls()); - installUrls(getDistributionUrls()); - - // A2 install bundles - provisioningManager.install(null); - + // Install bundles + install(); // Make sure fragments are properly considered by refreshing - refreshFramework(); - - // start bundles -// if (properties != null && !Boolean.parseBoolean(properties.get(PROP_OSGI_USE_SYSTEM_PROPERTIES))) - startBundles(properties); -// else -// startBundles(); - - // complete + refresh(); + // Start bundles + startBundles(); long duration = System.currentTimeMillis() - begin; - OsgiBootUtils.info("OSGi bootstrap completed in " + Math.round(((double) duration) / 1000) + "s (" + logger.log(DEBUG, () -> "OSGi bootstrap completed in " + Math.round(((double) duration) / 1000) + "s (" + duration + "ms), " + bundleContext.getBundles().length + " bundles"); } catch (RuntimeException e) { - OsgiBootUtils.error("OSGi bootstrap FAILED", e); + logger.log(ERROR, "OSGi bootstrap FAILED", e); throw e; } // diagnostics - if (OsgiBootUtils.isDebug()) { + if (logger.isLoggable(TRACE)) { OsgiBootDiagnostics diagnostics = new OsgiBootDiagnostics(bundleContext); diagnostics.checkUnresolved(); Map> duplicatePackages = diagnostics.findPackagesExportedTwice(); if (duplicatePackages.size() > 0) { - OsgiBootUtils.info("Packages exported twice:"); + logger.log(TRACE, "Packages exported twice:"); Iterator it = duplicatePackages.keySet().iterator(); while (it.hasNext()) { String pkgName = it.next(); - OsgiBootUtils.info(pkgName); + logger.log(TRACE, pkgName); Set bdles = duplicatePackages.get(pkgName); Iterator bdlesIt = bdles.iterator(); while (bdlesIt.hasNext()) - OsgiBootUtils.info(" " + bdlesIt.next()); + logger.log(TRACE, " " + bdlesIt.next()); } } } System.out.println(); } - /** - * Calls {@link #bootstrap(Map)} with null. - * - * @see #bootstrap(Map) - */ - @Deprecated - public void bootstrap() { - bootstrap(null); + public void install() { + String osgiInstancePath = getProperty(InitConstants.PROP_OSGI_INSTANCE_AREA); + String osgiConfigurationPath = getProperty(InitConstants.PROP_OSGI_CONFIGURATION_AREA); + String osgiSharedConfigurationPath = getProperty(InitConstants.PROP_OSGI_CONFIGURATION_AREA); + logger.log(DEBUG, () -> "OSGi bootstrap starting" // + + (osgiInstancePath != null ? " data: " + osgiInstancePath + "" : "") // + + (osgiConfigurationPath != null ? " state: " + osgiConfigurationPath + "" : "") // + + (osgiSharedConfigurationPath != null ? " config: " + osgiSharedConfigurationPath + "" : "") // + ); + + // legacy install bundles + installUrls(getBundlesUrls()); + installUrls(getDistributionUrls()); + + // A2 install bundles + provisioningManager.install(null); + } public void update() { @@ -221,21 +218,20 @@ public class OsgiBoot implements OsgiBootConstants { try { if (installedBundles.containsKey(url)) { Bundle bundle = (Bundle) installedBundles.get(url); - if (OsgiBootUtils.isDebug()) - debug("Bundle " + bundle.getSymbolicName() + " already installed from " + url); + logger.log(TRACE, () -> "Bundle " + bundle.getSymbolicName() + " already installed from " + url); } else if (url.contains("/" + InitConstants.SYMBOLIC_NAME_EQUINOX + "/") || url.contains("/" + InitConstants.SYMBOLIC_NAME_INIT + "/")) { - if (OsgiBootUtils.isDebug()) - warn("Skip " + url); + if (logger.isLoggable(TRACE)) + logger.log(WARNING, "Skip " + url); return; } else { Bundle bundle = bundleContext.installBundle(url); if (url.startsWith("http")) - OsgiBootUtils - .info("Installed " + bundle.getSymbolicName() + "-" + bundle.getVersion() + " from " + url); - else if (OsgiBootUtils.isDebug()) - OsgiBootUtils.debug( - "Installed " + bundle.getSymbolicName() + "-" + bundle.getVersion() + " from " + url); + logger.log(DEBUG, + () -> "Installed " + bundle.getSymbolicName() + "-" + bundle.getVersion() + " from " + url); + else + logger.log(TRACE, + () -> "Installed " + bundle.getSymbolicName() + "-" + bundle.getVersion() + " from " + url); assert bundle.getSymbolicName() != null; // uninstall previous versions bundles: for (Bundle b : bundleContext.getBundles()) { @@ -250,17 +246,17 @@ public class OsgiBoot implements OsgiBootConstants { if (bundleV.getMicro() > bV.getMicro()) { // uninstall older bundles b.uninstall(); - OsgiBootUtils.debug("Uninstalled " + b); + logger.log(TRACE, () -> "Uninstalled " + b); } else if (bundleV.getMicro() < bV.getMicro()) { // uninstall just installed bundle if newer bundle.uninstall(); - OsgiBootUtils.debug("Uninstalled " + bundle); + logger.log(TRACE, () -> "Uninstalled " + bundle); break bundles; } else { // uninstall any other with same major/minor if (!bundleV.getQualifier().equals(bV.getQualifier())) { b.uninstall(); - OsgiBootUtils.debug("Uninstalled " + b); + logger.log(TRACE, () -> "Uninstalled " + b); } } } @@ -277,12 +273,12 @@ public class OsgiBoot implements OsgiBootConstants { // have already been installed... } else { if (message.contains(ALREADY_INSTALLED)) { - if (OsgiBootUtils.isDebug()) - OsgiBootUtils.warn("Duplicate install from " + url + ": " + message); + if (logger.isLoggable(TRACE)) + logger.log(WARNING, "Duplicate install from " + url + ": " + message); } else - OsgiBootUtils.warn("Could not install bundle from " + url + ": " + message); + logger.log(WARNING, "Could not install bundle from " + url + ": " + message); } - if (OsgiBootUtils.isDebug() && !message.contains(ALREADY_INSTALLED)) + if (logger.isLoggable(TRACE) && !message.contains(ALREADY_INSTALLED)) e.printStackTrace(); } } @@ -296,19 +292,20 @@ public class OsgiBoot implements OsgiBootConstants { * * @see OsgiBoot#doStartBundles(Map) */ - public void startBundles(Map properties) { + public void startBundles() { Map map = new TreeMap<>(); // first use properties - if (properties != null) { - for (String key : properties.keySet()) { - String property = key; - if (property.startsWith(InitConstants.PROP_ARGEO_OSGI_START)) { - map.put(property, properties.get(property)); - } - } - } +// if (properties != null) { +// for (String key : properties.keySet()) { +// String property = key; +// if (property.startsWith(InitConstants.PROP_ARGEO_OSGI_START)) { +// map.put(property, properties.get(property)); +// } +// } +// } // then try all start level until a maximum - int maxStartLevel = Integer.parseInt(getProperty(InitConstants.PROP_ARGEO_OSGI_MAX_START_LEVEL, DEFAULT_MAX_START_LEVEL)); + int maxStartLevel = Integer + .parseInt(getProperty(InitConstants.PROP_ARGEO_OSGI_MAX_START_LEVEL, DEFAULT_MAX_START_LEVEL)); for (int i = 1; i <= maxStartLevel; i++) { String key = InitConstants.PROP_ARGEO_OSGI_START + "." + i; String value = getProperty(key); @@ -317,31 +314,33 @@ public class OsgiBoot implements OsgiBootConstants { } // finally, override with system properties - for (Object key : System.getProperties().keySet()) { - if (key.toString().startsWith(InitConstants.PROP_ARGEO_OSGI_START)) { - map.put(key.toString(), System.getProperty(key.toString())); - } - } +// for (Object key : System.getProperties().keySet()) { +// if (key.toString().startsWith(InitConstants.PROP_ARGEO_OSGI_START)) { +// map.put(key.toString(), System.getProperty(key.toString())); +// } +// } // start doStartBundles(map); } - @Deprecated - public void startBundles(Properties properties) { - Map map = new TreeMap<>(); - // first use properties - if (properties != null) { - for (Object key : properties.keySet()) { - String property = key.toString(); - if (property.startsWith(InitConstants.PROP_ARGEO_OSGI_START)) { - map.put(property, properties.get(property).toString()); - } - } - } - startBundles(map); - } +// void startBundles(Properties properties) { +// Map map = new TreeMap<>(); +// // first use properties +// if (properties != null) { +// for (Object key : properties.keySet()) { +// String property = key.toString(); +// if (property.startsWith(InitConstants.PROP_ARGEO_OSGI_START)) { +// map.put(property, properties.get(property).toString()); +// } +// } +// } +// startBundles(map); +// } - /** Start bundle based on keys starting with {@link InitConstants#PROP_ARGEO_OSGI_START}. */ + /** + * Start bundle based on keys starting with + * {@link InitConstants#PROP_ARGEO_OSGI_START}. + */ protected void doStartBundles(Map properties) { FrameworkStartLevel frameworkStartLevel = bundleContext.getBundle(0).adapt(FrameworkStartLevel.class); @@ -349,12 +348,14 @@ public class OsgiBoot implements OsgiBootConstants { int initialStartLevel = frameworkStartLevel.getInitialBundleStartLevel(); int defaultStartLevel = Integer.parseInt(getProperty(InitConstants.PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "4")); int activeStartLevel = Integer.parseInt(getProperty(InitConstants.PROP_OSGI_STARTLEVEL, "6")); - if (OsgiBootUtils.isDebug()) { - OsgiBootUtils.debug("OSGi default start level: " - + getProperty(InitConstants.PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "") + ", using " + defaultStartLevel); - OsgiBootUtils.debug("OSGi active start level: " + getProperty(InitConstants.PROP_OSGI_STARTLEVEL, "") + if (logger.isLoggable(TRACE)) { + logger.log(TRACE, + "OSGi default start level: " + + getProperty(InitConstants.PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "") + ", using " + + defaultStartLevel); + logger.log(TRACE, "OSGi active start level: " + getProperty(InitConstants.PROP_OSGI_STARTLEVEL, "") + ", using " + activeStartLevel); - OsgiBootUtils.debug("Framework start level: " + frameworkStartLevel.getStartLevel() + " (initial: " + logger.log(TRACE, "Framework start level: " + frameworkStartLevel.getStartLevel() + " (initial: " + initialStartLevel + ")"); } @@ -392,23 +393,20 @@ public class OsgiBoot implements OsgiBootConstants { try { bundle.start(); } catch (BundleException e) { - OsgiBootUtils.error("Cannot mark " + bsn + " as started", e); + logger.log(ERROR, "Cannot mark " + bsn + " as started", e); } - if (OsgiBootUtils.isDebug()) - OsgiBootUtils.debug(bsn + " v" + bundle.getVersion() + " starts at level " + level); + logger.log(TRACE, () -> bsn + " v" + bundle.getVersion() + " starts at level " + level); } } } - if (OsgiBootUtils.isDebug()) - OsgiBootUtils.debug("About to set framework start level to " + activeStartLevel + " ..."); + logger.log(TRACE, () -> "About to set framework start level to " + activeStartLevel + " ..."); frameworkStartLevel.setStartLevel(activeStartLevel, (FrameworkEvent event) -> { if (event.getType() == FrameworkEvent.ERROR) { - OsgiBootUtils.error("Start sequence failed", event.getThrowable()); + logger.log(ERROR, "Start sequence failed", event.getThrowable()); } else { - if (OsgiBootUtils.isDebug()) - OsgiBootUtils.debug("Framework started at level " + frameworkStartLevel.getStartLevel()); + logger.log(TRACE, () -> "Framework started at level " + frameworkStartLevel.getStartLevel()); } }); @@ -439,7 +437,8 @@ public class OsgiBoot implements OsgiBootConstants { Integer defaultStartLevel) { // default (and previously, only behaviour) - appendToStartLevels(startLevels, defaultStartLevel, properties.getOrDefault(InitConstants.PROP_ARGEO_OSGI_START, "")); + appendToStartLevels(startLevels, defaultStartLevel, + properties.getOrDefault(InitConstants.PROP_ARGEO_OSGI_START, "")); // list argeo.osgi.start.* system properties Iterator keys = properties.keySet().iterator(); @@ -514,8 +513,7 @@ public class OsgiBoot implements OsgiBootConstants { return urls; // bundlePatterns = SystemPropertyUtils.resolvePlaceholders(bundlePatterns); - if (OsgiBootUtils.isDebug()) - debug(PROP_ARGEO_OSGI_BUNDLES + "=" + bundlePatterns); + logger.log(TRACE, () -> PROP_ARGEO_OSGI_BUNDLES + "=" + bundlePatterns); StringTokenizer st = new StringTokenizer(bundlePatterns, ","); List bundlesSets = new ArrayList(); @@ -617,8 +615,8 @@ public class OsgiBoot implements OsgiBootConstants { File[] files = baseDir.listFiles(); if (files == null) { - if (OsgiBootUtils.isDebug()) - OsgiBootUtils.warn("Base dir " + baseDir + " has no children, exists=" + baseDir.exists() + if (logger.isLoggable(TRACE)) + logger.log(Level.WARNING, "Base dir " + baseDir + " has no children, exists=" + baseDir.exists() + ", isDirectory=" + baseDir.isDirectory()); return; } @@ -656,8 +654,8 @@ public class OsgiBoot implements OsgiBootConstants { // } } else { boolean nonDirectoryOk = matcher.matches(Paths.get(newCurrentPath)); - if (OsgiBootUtils.isDebug()) - debug(currentPath + " " + (ok ? "" : " not ") + " matched with " + pattern); + logger.log(TRACE, + () -> currentPath + " " + (ok ? "" : " not ") + " matched with " + pattern); if (nonDirectoryOk) matched.add(relativeToFullPath(base, newCurrentPath)); } @@ -706,7 +704,7 @@ public class OsgiBoot implements OsgiBootConstants { return (basePath + '/' + relativePath).replace('/', File.separatorChar); } - private void refreshFramework() { + public void refresh() { Bundle systemBundle = bundleContext.getBundle(0); FrameworkWiring frameworkWiring = systemBundle.adapt(FrameworkWiring.class); // TODO deal with refresh breaking native loading (e.g SWT) @@ -738,4 +736,47 @@ public class OsgiBoot implements OsgiBootConstants { return bundleContext; } + /* + * PLAIN OSGI LAUNCHER + */ + /** Launch an OSGi framework. OSGi Boot initialisation is NOT performed. */ + public static Framework defaultOsgiLaunch(Map configuration) { + Optional frameworkFactory = ServiceLoader.load(FrameworkFactory.class).findFirst(); + if (frameworkFactory.isEmpty()) + throw new IllegalStateException("No framework factory found"); + return defaultOsgiLaunch(frameworkFactory.get(), configuration); + } + + /** Launch an OSGi framework. OSGi Boot initialisation is NOT performed. */ + public static Framework defaultOsgiLaunch(FrameworkFactory frameworkFactory, Map configuration) { + // start OSGi + Framework framework = frameworkFactory.newFramework(configuration); + try { + framework.start(); + } catch (BundleException e) { + throw new IllegalStateException("Cannot start OSGi framework", e); + } + return framework; + } + + /* + * OSGI UTILITIES + */ + /** Uninstall all bundles with these symbolic names */ + public static void uninstallBundles(BundleContext bc, String... symbolicNames) { + List lst = Arrays.asList(symbolicNames); + for (Bundle b : bc.getBundles()) { + String sn = b.getSymbolicName(); + if (sn == null) + continue; + if (lst.contains(sn)) { + try { + b.uninstall(); + } catch (BundleException e) { + logger.log(ERROR, "Cannot uninstall " + sn, e); + } + } + } + + } }