From: Mathieu Baudier Date: Fri, 22 Jul 2022 06:48:55 +0000 (+0200) Subject: Improve init X-Git-Tag: v2.3.10~95 X-Git-Url: https://git.argeo.org/?p=lgpl%2Fargeo-commons.git;a=commitdiff_plain;h=b6ee9c8baa2650ebbca59c9f24eac3599408bf7f Improve init --- diff --git a/org.argeo.init/src/org/argeo/init/Service.java b/org.argeo.init/src/org/argeo/init/Service.java index 9dcea49d2..aa9494c91 100644 --- a/org.argeo.init/src/org/argeo/init/Service.java +++ b/org.argeo.init/src/org/argeo/init/Service.java @@ -1,31 +1,34 @@ package org.argeo.init; +import java.io.IOException; +import java.io.InputStream; import java.lang.System.Logger; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import org.argeo.init.logging.ThinLoggerFinder; +import org.argeo.init.osgi.OsgiBoot; import org.argeo.init.osgi.OsgiRuntimeContext; /** Configure and launch an Argeo service. */ -public class Service implements Runnable, AutoCloseable { - private final static Logger log = System.getLogger(Service.class.getName()); +public class Service { + private final static Logger logger = System.getLogger(Service.class.getName()); + + public final static String PROP_ARGEO_INIT_MAIN = "argeo.init.main"; private static RuntimeContext runtimeContext = null; protected Service(String[] args) { } - @Override - public void run() { - } - - @Override - public void close() throws Exception { - } - public static void main(String[] args) { - long pid = ProcessHandle.current().pid(); - log.log(Logger.Level.DEBUG, "Argeo Init starting with PID " + pid); + final long pid = ProcessHandle.current().pid(); + logger.log(Logger.Level.DEBUG, () -> "Argeo Init starting with PID " + pid); // shutdown on exit Runtime.getRuntime().addShutdownHook(new Thread(() -> { @@ -41,15 +44,52 @@ public class Service implements Runnable, AutoCloseable { } }, "Runtime shutdown")); + // TODO use args as well + String dataArea = System.getProperty(OsgiBoot.PROP_OSGI_INSTANCE_AREA); + String stateArea = System.getProperty(OsgiBoot.PROP_OSGI_CONFIGURATION_AREA); + String configArea = System.getProperty(OsgiBoot.PROP_OSGI_SHARED_CONFIGURATION_AREA); + + if (configArea != null) { + Path configAreaPath = Paths.get(configArea); + Path additionalSystemPropertiesPath = configAreaPath.resolve("system.properties"); + if (Files.exists(additionalSystemPropertiesPath)) { + Properties properties = new Properties(); + try (InputStream in = Files.newInputStream(additionalSystemPropertiesPath)) { + properties.load(in); + } catch (IOException e) { + logger.log(Logger.Level.ERROR, + "Cannot load additional system properties " + additionalSystemPropertiesPath, e); + } + + for (Object key : properties.keySet()) { + String currentValue = System.getProperty(key.toString()); + String value = properties.getProperty(key.toString()); + if (currentValue != null) { + if (!Objects.equals(value, currentValue)) + logger.log(Logger.Level.WARNING, "System property " + key + " already set with value " + + currentValue + " instead of " + value + ". Ignoring new value."); + } else { + System.setProperty(key.toString(), value); + } + } + ThinLoggerFinder.reloadConfiguration(); + } + } + Map config = new HashMap<>(); - config.put("osgi.framework.useSystemProperties", "true"); -// for (Object key : System.getProperties().keySet()) { -// config.put(key.toString(), System.getProperty(key.toString())); -// log.log(Logger.Level.DEBUG, key + "=" + System.getProperty(key.toString())); -// } + config.put(PROP_ARGEO_INIT_MAIN, "true"); + try { try { - OsgiRuntimeContext osgiRuntimeContext = new OsgiRuntimeContext((Map) config); + if (stateArea != null) + config.put(OsgiBoot.PROP_OSGI_CONFIGURATION_AREA, stateArea); + if (configArea != null) + config.put(OsgiBoot.PROP_OSGI_SHARED_CONFIGURATION_AREA, configArea); + if (dataArea != null) + config.put(OsgiBoot.PROP_OSGI_INSTANCE_AREA, dataArea); + // config.put(OsgiBoot.PROP_OSGI_USE_SYSTEM_PROPERTIES, "true"); + + OsgiRuntimeContext osgiRuntimeContext = new OsgiRuntimeContext(config); osgiRuntimeContext.run(); Service.runtimeContext = osgiRuntimeContext; Service.runtimeContext.waitForStop(0); @@ -63,10 +103,9 @@ public class Service implements Runnable, AutoCloseable { e.printStackTrace(); System.exit(1); } - log.log(Logger.Level.DEBUG, "Argeo Init stopped with PID " + pid); + logger.log(Logger.Level.DEBUG, "Argeo Init stopped with PID " + pid); } - public static RuntimeContext getRuntimeContext() { return runtimeContext; } diff --git a/org.argeo.init/src/org/argeo/init/logging/ThinLoggerFinder.java b/org.argeo.init/src/org/argeo/init/logging/ThinLoggerFinder.java index 47cb14655..e60d22fba 100644 --- a/org.argeo.init/src/org/argeo/init/logging/ThinLoggerFinder.java +++ b/org.argeo.init/src/org/argeo/init/logging/ThinLoggerFinder.java @@ -32,7 +32,13 @@ public class ThinLoggerFinder extends LoggerFinder { private static void init() { logging = new ThinLogging(); + reloadConfiguration(); + } + /** Reload configuration form system properties */ + public static void reloadConfiguration() { + if (logging == null) + return; Map configuration = new HashMap<>(); for (Object key : System.getProperties().keySet()) { Objects.requireNonNull(key); diff --git a/org.argeo.init/src/org/argeo/init/logging/ThinLogging.java b/org.argeo.init/src/org/argeo/init/logging/ThinLogging.java index 85ed9eb4f..e03b179a3 100644 --- a/org.argeo.init/src/org/argeo/init/logging/ThinLogging.java +++ b/org.argeo.init/src/org/argeo/init/logging/ThinLogging.java @@ -37,8 +37,12 @@ class ThinLogging implements Consumer> { final static String DEFAULT_LEVEL_PROPERTY = "log"; final static String LEVEL_PROPERTY_PREFIX = DEFAULT_LEVEL_PROPERTY + "."; - final static String JOURNALD_PROPERTY = "argeo.logging.journald"; - final static String CALL_LOCATION_PROPERTY = "argeo.logging.callLocation"; + final static String PROP_ARGEO_LOGGING_SYNCHRONOUS = "argeo.logging.synchronous"; + final static String PROP_ARGEO_LOGGING_JOURNALD = "argeo.logging.journald"; + final static String PROP_ARGEO_LOGGING_CALL_LOCATION = "argeo.logging.callLocation"; + + final static String ENV_INVOCATION_ID = "INVOCATION_ID"; + final static String ENV_GIO_LAUNCHED_DESKTOP_FILE_PID = "GIO_LAUNCHED_DESKTOP_FILE_PID"; private final static AtomicLong nextEntry = new AtomicLong(0l); @@ -56,7 +60,7 @@ class ThinLogging implements Consumer> { private final boolean journald; private final Level callLocationLevel; - private boolean synchronous = true; + private boolean synchronous = Boolean.parseBoolean(System.getProperty(PROP_ARGEO_LOGGING_SYNCHRONOUS)); ThinLogging() { // executor = Executors.newCachedThreadPool((r) -> { @@ -78,7 +82,7 @@ class ThinLogging implements Consumer> { } // initial default level - levels.put("", Level.WARNING); + levels.put(DEFAULT_LEVEL_NAME, Level.WARNING); // Logging system config // journald @@ -88,13 +92,13 @@ class ThinLogging implements Consumer> { // System.out.println(key + "=" + env.get(key)); // } - String journaldStr = System.getProperty(JOURNALD_PROPERTY, "auto"); + String journaldStr = System.getProperty(PROP_ARGEO_LOGGING_JOURNALD, "auto"); switch (journaldStr) { case "auto": - String systemdInvocationId = System.getenv("INVOCATION_ID"); + String systemdInvocationId = System.getenv(ENV_INVOCATION_ID); if (systemdInvocationId != null) {// in systemd - // check whether we are indirectly in a desktop app (e.g. eclipse) - String desktopFilePid = System.getenv("GIO_LAUNCHED_DESKTOP_FILE_PID"); + // check whether we are indirectly in a desktop app (typically an IDE) + String desktopFilePid = System.getenv(ENV_GIO_LAUNCHED_DESKTOP_FILE_PID); if (desktopFilePid != null) { Long javaPid = ProcessHandle.current().pid(); if (!javaPid.toString().equals(desktopFilePid)) { @@ -117,10 +121,10 @@ class ThinLogging implements Consumer> { break; default: throw new IllegalArgumentException( - "Unsupported value '" + journaldStr + "' for property " + JOURNALD_PROPERTY); + "Unsupported value '" + journaldStr + "' for property " + PROP_ARGEO_LOGGING_JOURNALD); } - String callLocationStr = System.getProperty(CALL_LOCATION_PROPERTY, Level.WARNING.getName()); + String callLocationStr = System.getProperty(PROP_ARGEO_LOGGING_CALL_LOCATION, Level.WARNING.getName()); callLocationLevel = Level.valueOf(callLocationStr); } @@ -136,7 +140,7 @@ class ThinLogging implements Consumer> { publisher.close(); try { - // we ait a bit in order to make sure all messages are flushed + // we wait a bit in order to make sure all messages are flushed // TODO synchronize more efficiently // executor.awaitTermination(300, TimeUnit.MILLISECONDS); ForkJoinPool.commonPool().awaitTermination(300, TimeUnit.MILLISECONDS); @@ -148,28 +152,13 @@ class ThinLogging implements Consumer> { private Level computeApplicableLevel(String name) { Map.Entry entry = levels.floorEntry(name); assert entry != null; - return entry.getValue(); + if (name.startsWith(entry.getKey())) + return entry.getValue(); + else + return levels.get(DEFAULT_LEVEL_NAME);// default } -// private boolean isLoggable(String name, Level level) { -// Objects.requireNonNull(name); -// Objects.requireNonNull(level); -// -// if (updatingConfiguration) { -// synchronized (levels) { -// try { -// levels.wait(); -// // TODO make exit more robust -// } catch (InterruptedException e) { -// throw new IllegalStateException(e); -// } -// } -// } -// -// return level.getSeverity() >= computeApplicableLevel(name).getSeverity(); -// } - public Logger getLogger(String name, Module module) { if (!loggers.containsKey(name)) { ThinLogger logger = new ThinLogger(name, computeApplicableLevel(name)); @@ -222,7 +211,6 @@ class ThinLogging implements Consumer> { updatingConfiguration = false; levels.notifyAll(); } - } Flow.Publisher> getLogEntryPublisher() { @@ -445,6 +433,8 @@ class ThinLogging implements Consumer> { private PrintStream err; private int writeToErrLevel = Level.WARNING.getSeverity(); + private Subscription subscription; + protected PrintStreamSubscriber() { this(System.out, System.err); } @@ -460,7 +450,8 @@ class ThinLogging implements Consumer> { @Override public void onSubscribe(Subscription subscription) { - subscription.request(Long.MAX_VALUE); + this.subscription = subscription; + this.subscription.request(1); } @Override @@ -471,6 +462,7 @@ class ThinLogging implements Consumer> { out.print(toPrint(item)); } // TODO flush for journald? + this.subscription.request(1); } @Override @@ -532,10 +524,9 @@ class ThinLogging implements Consumer> { protected String toPrint(Map logEntry) { StringBuilder sb = new StringBuilder(); StringTokenizer st = new StringTokenizer((String) logEntry.get(KEY_MSG), "\r\n"); - assert st.hasMoreTokens(); // first line - String firstLine = st.nextToken(); + String firstLine = st.hasMoreTokens() ? st.nextToken() : ""; sb.append(firstLinePrefix(logEntry)); sb.append(firstLine); sb.append(firstLineSuffix(logEntry)); diff --git a/org.argeo.init/src/org/argeo/init/osgi/Activator.java b/org.argeo.init/src/org/argeo/init/osgi/Activator.java index 518751f91..b85b248b9 100644 --- a/org.argeo.init/src/org/argeo/init/osgi/Activator.java +++ b/org.argeo.init/src/org/argeo/init/osgi/Activator.java @@ -4,6 +4,7 @@ import java.lang.System.Logger; import java.lang.System.Logger.Level; import java.util.Objects; +import org.argeo.init.Service; import org.argeo.init.logging.ThinLoggerFinder; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; @@ -18,36 +19,45 @@ public class Activator implements BundleActivator { // must be called first ThinLoggerFinder.lazyInit(); } - private Logger logger = System.getLogger(Activator.class.getName()); + private final static Logger logger = System.getLogger(Activator.class.getName()); private Long checkpoint = null; + private boolean argeoInit = false; /** Not null if we created it ourselves. */ private OsgiRuntimeContext runtimeContext; public void start(final BundleContext bundleContext) throws Exception { - if (runtimeContext == null) { - runtimeContext = new OsgiRuntimeContext(bundleContext); - } - logger.log(Level.DEBUG, () -> "Argeo init via OSGi activator"); - - // admin thread + // The OSGi runtime was created by us, and therefore already initialized + argeoInit = Boolean.parseBoolean(bundleContext.getProperty(Service.PROP_ARGEO_INIT_MAIN)); + if (!argeoInit) { + if (runtimeContext == null) { + runtimeContext = new OsgiRuntimeContext(bundleContext); + logger.log(Level.DEBUG, () -> "Argeo init via OSGi activator"); + } + + // admin thread // Thread adminThread = new AdminThread(bundleContext); // adminThread.start(); - // bootstrap + // bootstrap // OsgiBoot osgiBoot = new OsgiBoot(bundleContext); - if (checkpoint == null) { + if (checkpoint == null) { // osgiBoot.bootstrap(); - checkpoint = System.currentTimeMillis(); - } else { - runtimeContext.update(); - checkpoint = System.currentTimeMillis(); + checkpoint = System.currentTimeMillis(); + } else { + runtimeContext.update(); + checkpoint = System.currentTimeMillis(); + } } } public void stop(BundleContext context) throws Exception { - Objects.nonNull(runtimeContext); - runtimeContext.stop(context); + if (!argeoInit) { + Objects.nonNull(runtimeContext); + runtimeContext.stop(context); + runtimeContext = null; + } } + } 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 353e39c79..d9f3b3c7b 100644 --- a/org.argeo.init/src/org/argeo/init/osgi/OsgiBoot.java +++ b/org.argeo.init/src/org/argeo/init/osgi/OsgiBoot.java @@ -4,8 +4,6 @@ import static org.argeo.init.osgi.OsgiBootUtils.debug; import static org.argeo.init.osgi.OsgiBootUtils.warn; import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; @@ -39,54 +37,45 @@ import org.osgi.framework.wiring.FrameworkWiring; * methods, configured via properties. */ 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"; + final static String PROP_ARGEO_OSGI_START = "argeo.osgi.start"; + final static String PROP_ARGEO_OSGI_MAX_START_LEVEL = "argeo.osgi.maxStartLevel"; + 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"; - public final static String PROP_ARGEO_OSGI_DISTRIBUTION_URL = "argeo.osgi.distributionUrl"; + @Deprecated + final static String PROP_ARGEO_OSGI_BUNDLES = "argeo.osgi.bundles"; + final static String PROP_ARGEO_OSGI_BASE_URL = "argeo.osgi.baseUrl"; + final static String PROP_ARGEO_OSGI_LOCAL_CACHE = "argeo.osgi.localCache"; + final static String PROP_ARGEO_OSGI_DISTRIBUTION_URL = "argeo.osgi.distributionUrl"; // 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"; + @Deprecated + final static String PROP_ARGEO_OSGI_BOOT_DEBUG = "argeo.osgi.boot.debug"; - 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"; + final static String PROP_ARGEO_OSGI_BOOT_SYSTEM_PROPERTIES_FILE = "argeo.osgi.boot.systemPropertiesFile"; + final static String PROP_ARGEO_OSGI_BOOT_APPCLASS = "argeo.osgi.boot.appclass"; + final static String PROP_ARGEO_OSGI_BOOT_APPARGS = "argeo.osgi.boot.appargs"; - public final static String DEFAULT_BASE_URL = "reference:file:"; - // public final static String EXCLUDES_SVN_PATTERN = "**/.svn/**"; + final static String DEFAULT_BASE_URL = "reference:file:"; + final static String DEFAULT_MAX_START_LEVEL = "32"; // OSGi standard properties final static String PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL = "osgi.bundles.defaultStartLevel"; final static String PROP_OSGI_STARTLEVEL = "osgi.startLevel"; - final static String PROP_OSGI_INSTANCE_AREA = "osgi.instance.area"; - final static String PROP_OSGI_CONFIGURATION_AREA = "osgi.configuration.area"; - final static String PROP_OSGI_USE_SYSTEM_PROPERTIES = "osgi.framework.useSystemProperties"; + public final static String PROP_OSGI_INSTANCE_AREA = "osgi.instance.area"; + public final static String PROP_OSGI_CONFIGURATION_AREA = "osgi.configuration.area"; + public final static String PROP_OSGI_SHARED_CONFIGURATION_AREA = "osgi.sharedConfiguration.area"; + public final static String PROP_OSGI_USE_SYSTEM_PROPERTIES = "osgi.framework.useSystemProperties"; // Symbolic names - public final static String SYMBOLIC_NAME_OSGI_BOOT = "org.argeo.osgi.boot"; - public final static String SYMBOLIC_NAME_EQUINOX = "org.eclipse.osgi"; - - /** Exclude svn metadata implicitely(a bit costly) */ - // private boolean excludeSvn = - // Boolean.valueOf(System.getProperty(PROP_ARGEO_OSGI_BOOT_EXCLUDE_SVN, - // "false")) - // .booleanValue(); - -// /** Default is 10s */ -// @Deprecated -// private long defaultTimeout = 10000l; + final static String SYMBOLIC_NAME_OSGI_BOOT = "org.argeo.init"; + final static String SYMBOLIC_NAME_EQUINOX = "org.eclipse.osgi"; private final BundleContext bundleContext; private final String localCache; - private final ProvisioningManager provisioningManager; /* - * INITIALIZATION + * INITIALISATION */ /** Constructor */ public OsgiBoot(BundleContext bundleContext) { @@ -100,20 +89,22 @@ public class OsgiBoot implements OsgiBootConstants { if (sources == null) { provisioningManager.registerDefaultSource(); } else { +// OsgiBootUtils.debug("Found sources " + sources); for (String source : sources.split(",")) { + int qmIndex = source.lastIndexOf('?'); + String queryPart = ""; + if (qmIndex >= 0) { + queryPart = source.substring(qmIndex); + source = source.substring(0, qmIndex); + } if (source.trim().equals(A2Source.DEFAULT_A2_URI)) { - int qmIndex = source.lastIndexOf('?'); - String queryPart = ""; - if (qmIndex >= 0) { - queryPart = source.substring(qmIndex); - } if (Files.exists(homePath)) 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/share/a2" + queryPart); } else { - provisioningManager.registerSource(source); + provisioningManager.registerSource(source + queryPart); } } } @@ -135,46 +126,60 @@ public class OsgiBoot implements OsgiBootConstants { try { long begin = System.currentTimeMillis(); // check properties - if (properties != null) { - for (String property : properties.keySet()) { - String value = properties.get(property); - String bcValue = bundleContext.getProperty(property); - if (PROP_OSGI_CONFIGURATION_AREA.equals(property) || PROP_OSGI_INSTANCE_AREA.equals(property)) { - try { - URL uri = new URL(value); - URL bcUri = new URL(bcValue); - if (!uri.equals(bcUri)) - throw new IllegalArgumentException("Property " + property + "=" + uri - + " is inconsistent with bundle context : " + bcUri); - } catch (MalformedURLException e) { - throw new IllegalArgumentException("Malformed property " + property, e); - } - - } else { - if (!value.equals(bcValue)) - throw new IllegalArgumentException("Property " + property + "=" + value - + " is inconsistent with bundle context : " + bcValue); - } - } - } else { - String useSystemProperties = bundleContext.getProperty(PROP_OSGI_USE_SYSTEM_PROPERTIES); - if (useSystemProperties == null || !useSystemProperties.equals("true")) { - OsgiBootUtils.warn("No properties passed but " + PROP_OSGI_USE_SYSTEM_PROPERTIES + " is not set."); - } - } +// if (properties != null) { +// for (String property : properties.keySet()) { +// String value = properties.get(property); +// String bcValue = bundleContext.getProperty(property); +// if (PROP_OSGI_CONFIGURATION_AREA.equals(property) || PROP_OSGI_INSTANCE_AREA.equals(property)) { +// try { +// if (value.startsWith("/")) +// value = "file://" + value; +// URL uri = new URL(value); +// URL bcUri = new URL(bcValue); +// if (!uri.equals(bcUri)) +// throw new IllegalArgumentException("Property " + property + "=" + uri +// + " is inconsistent with bundle context : " + bcUri); +// } catch (MalformedURLException e) { +// throw new IllegalArgumentException("Malformed property " + property, e); +// } +// +// } else { +// if (!value.equals(bcValue)) +// throw new IllegalArgumentException("Property " + property + "=" + value +// + " is inconsistent with bundle context : " + bcValue); +// } +// } +// } else { +// String useSystemProperties = bundleContext.getProperty(PROP_OSGI_USE_SYSTEM_PROPERTIES); +// if (useSystemProperties == null || !useSystemProperties.equals("true")) { +// OsgiBootUtils.warn("No properties passed but " + PROP_OSGI_USE_SYSTEM_PROPERTIES + " is not set."); +// } +// } // notify start - System.out.println(); - String osgiInstancePath = bundleContext.getProperty(PROP_OSGI_INSTANCE_AREA); - OsgiBootUtils - .info("OSGi bootstrap starting" + (osgiInstancePath != null ? " (" + osgiInstancePath + ")" : "")); + String osgiInstancePath = getProperty(PROP_OSGI_INSTANCE_AREA); + String osgiConfigurationPath = getProperty(PROP_OSGI_CONFIGURATION_AREA); + String osgiSharedConfigurationPath = getProperty(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); - if (properties != null) - startBundles(properties); - else - startBundles(); + + // start bundles +// if (properties != null && !Boolean.parseBoolean(properties.get(PROP_OSGI_USE_SYSTEM_PROPERTIES))) + startBundles(properties); +// else +// startBundles(); + + // complete long duration = System.currentTimeMillis() - begin; OsgiBootUtils.info("OSGi bootstrap completed in " + Math.round(((double) duration) / 1000) + "s (" + duration + "ms), " + bundleContext.getBundles().length + " bundles"); @@ -313,34 +318,68 @@ public class OsgiBoot implements OsgiBootConstants { /* * START */ - /** - * Start bundles based on system properties. - * - * @see OsgiBoot#startBundles(Map) - */ - public void startBundles() { - Properties properties = System.getProperties(); - startBundles(properties); - } +// /** +// * Start bundles based on system properties. +// * +// * @see OsgiBoot#doStartBundles(Map) +// */ +// public void startBundles() { +// Properties properties = System.getProperties(); +// startBundles(properties); +// } /** * Start bundles based on these properties. * - * @see OsgiBoot#startBundles(Map) + * @see OsgiBoot#doStartBundles(Map) */ + public void startBundles(Map properties) { + Map map = new TreeMap<>(); + // first use properties + if (properties != null) { + for (String key : properties.keySet()) { + String property = key; + if (property.startsWith(PROP_ARGEO_OSGI_START)) { + map.put(property, properties.get(property)); + } + } + } + // then try all start level until a maximum + int maxStartLevel = Integer.parseInt(getProperty(PROP_ARGEO_OSGI_MAX_START_LEVEL, DEFAULT_MAX_START_LEVEL)); + for (int i = 1; i <= maxStartLevel; i++) { + String key = PROP_ARGEO_OSGI_START + "." + i; + String value = getProperty(key); + if (value != null) + map.put(key, value); + + } + // finally, override with system properties + for (Object key : System.getProperties().keySet()) { + if (key.toString().startsWith(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<>(); - for (Object key : properties.keySet()) { - String property = key.toString(); - if (property.startsWith(PROP_ARGEO_OSGI_START)) { - map.put(property, properties.getProperty(property)); + // first use properties + if (properties != null) { + for (Object key : properties.keySet()) { + String property = key.toString(); + if (property.startsWith(PROP_ARGEO_OSGI_START)) { + map.put(property, properties.get(property).toString()); + } } } startBundles(map); } /** Start bundle based on keys starting with {@link #PROP_ARGEO_OSGI_START}. */ - public void startBundles(Map properties) { + protected void doStartBundles(Map properties) { FrameworkStartLevel frameworkStartLevel = bundleContext.getBundle(0).adapt(FrameworkStartLevel.class); // default and active start levels from System properties @@ -725,10 +764,6 @@ public class OsgiBoot implements OsgiBootConstants { } } - protected void matchFile() { - - } - /* * LOW LEVEL UTILITIES */ @@ -807,9 +842,9 @@ public class OsgiBoot implements OsgiBootConstants { return bundleContext; } - public String getLocalCache() { - return localCache; - } +// public String getLocalCache() { +// return localCache; +// } // public void setDefaultTimeout(long defaultTimeout) { // this.defaultTimeout = defaultTimeout; diff --git a/org.argeo.init/src/org/argeo/init/osgi/OsgiBootUtils.java b/org.argeo.init/src/org/argeo/init/osgi/OsgiBootUtils.java index e0b2f1551..a782ac37b 100644 --- a/org.argeo.init/src/org/argeo/init/osgi/OsgiBootUtils.java +++ b/org.argeo.init/src/org/argeo/init/osgi/OsgiBootUtils.java @@ -20,42 +20,23 @@ import org.osgi.framework.launch.FrameworkFactory; public class OsgiBootUtils { private final static Logger logger = System.getLogger(OsgiBootUtils.class.getName()); -// /** ISO8601 (as per log4j) and difference to UTC */ -// private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS Z"); - -// static boolean debug = System.getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_DEBUG) == null ? false -// : !System.getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_DEBUG).trim().equals("false"); - - @Deprecated public static void info(Object obj) { -// System.out.println("# OSGiBOOT # " + dateFormat.format(new Date()) + " # " + obj); logger.log(Level.INFO, () -> Objects.toString(obj)); } - @Deprecated public static void debug(Object obj) { -// if (debug) -// System.out.println("# OSGiBOOT DBG # " + dateFormat.format(new Date()) + " # " + obj); logger.log(Level.TRACE, () -> Objects.toString(obj)); } - @Deprecated public static void warn(Object obj) { -// System.out.println("# OSGiBOOT WARN # " + dateFormat.format(new Date()) + " # " + obj); logger.log(Level.WARNING, () -> Objects.toString(obj)); } - @Deprecated public static void error(Object obj, Throwable e) { -// System.err.println("# OSGiBOOT ERR # " + dateFormat.format(new Date()) + " # " + obj); -// if (e != null) -// e.printStackTrace(); logger.log(Level.ERROR, () -> Objects.toString(obj), e); } - @Deprecated public static boolean isDebug() { -// return debug; return logger.isLoggable(Level.TRACE); } diff --git a/sdk/deploy/argeo-init/usr/lib/systemd/system/argeo@.service b/sdk/deploy/argeo-init/usr/lib/systemd/system/argeo@.service index 7eb311fd0..ddea4a5b7 100644 --- a/sdk/deploy/argeo-init/usr/lib/systemd/system/argeo@.service +++ b/sdk/deploy/argeo-init/usr/lib/systemd/system/argeo@.service @@ -18,7 +18,14 @@ ExecStart=/usr/lib/jvm/java-17-openjdk-amd64/bin/java \ -Dosgi.configuration.area=/var/lib/argeo.d/%I/state \ -Dosgi.instance.area=/var/lib/argeo.d/%I/data \ -Dargeo.node.repo.indexesBase=/var/cache/argeo.d/%I/indexes \ --Dorg.osgi.framework.system.packages.extra=com.sun.net.httpserver,com.sun.jndi.ldap,com.sun.jndi.ldap.sasl,com.sun.security.jgss,com.sun.jndi.dns,com.sun.nio.file,com.sun.nio.sctp \ +-Dorg.osgi.framework.system.packages.extra=\ +com.sun.net.httpserver,\ +com.sun.jndi.ldap,\ +com.sun.jndi.ldap.sasl,\ +com.sun.jndi.dns,\ +com.sun.security.jgss,\ +com.sun.nio.file,\ +com.sun.nio.sctp \ -Declipse.ignoreApp=true \ -Dosgi.noShutdown=true \ -Dorg.eclipse.equinox.http.jetty.autostart=false \