From: Mathieu Baudier Date: Fri, 7 Apr 2017 11:17:46 +0000 (+0200) Subject: Introduce node runner X-Git-Tag: argeo-commons-2.1.68~17 X-Git-Url: https://git.argeo.org/?p=lgpl%2Fargeo-commons.git;a=commitdiff_plain;h=ebd927da42511bb5959000c50a39974c6cfa5f49 Introduce node runner --- diff --git a/org.argeo.osgi.boot/src/org/argeo/osgi/boot/Launcher.java b/org.argeo.osgi.boot/src/org/argeo/osgi/boot/Launcher.java index b13e066b8..7fd3e7609 100644 --- a/org.argeo.osgi.boot/src/org/argeo/osgi/boot/Launcher.java +++ b/org.argeo.osgi.boot/src/org/argeo/osgi/boot/Launcher.java @@ -29,17 +29,14 @@ public class Launcher { public static void main(String[] args) { // Try to load system properties - String systemPropertiesFilePath = OsgiBootUtils - .getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_SYSTEM_PROPERTIES_FILE); + String systemPropertiesFilePath = getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_SYSTEM_PROPERTIES_FILE); if (systemPropertiesFilePath != null) { FileInputStream in; try { in = new FileInputStream(systemPropertiesFilePath); System.getProperties().load(in); } catch (IOException e1) { - throw new RuntimeException( - "Cannot load system properties from " - + systemPropertiesFilePath, e1); + throw new RuntimeException("Cannot load system properties from " + systemPropertiesFilePath, e1); } if (in != null) { try { @@ -67,13 +64,11 @@ public class Launcher { } protected static void startMainClass() { - String className = OsgiBootUtils - .getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_APPCLASS); + String className = getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_APPCLASS); if (className == null) return; - String line = System.getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_APPARGS, - ""); + String line = System.getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_APPARGS, ""); String[] uiArgs = readArgumentsFromLine(line); @@ -133,4 +128,21 @@ public class Launcher { return res; } + public static String getProperty(String name, String defaultValue) { + final String value; + if (defaultValue != null) + value = System.getProperty(name, defaultValue); + else + value = System.getProperty(name); + + if (value == null || value.equals("")) + return null; + else + return value; + } + + public static String getProperty(String name) { + return getProperty(name, null); + } + } diff --git a/org.argeo.osgi.boot/src/org/argeo/osgi/boot/NodeRunner.java b/org.argeo.osgi.boot/src/org/argeo/osgi/boot/NodeRunner.java new file mode 100644 index 000000000..94fd1fd45 --- /dev/null +++ b/org.argeo.osgi.boot/src/org/argeo/osgi/boot/NodeRunner.java @@ -0,0 +1,225 @@ +package org.argeo.osgi.boot; + +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.ServiceLoader; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.launch.Framework; +import org.osgi.framework.launch.FrameworkFactory; + +/** Launch an OSGi framework and deploy a CMS Node into it. */ +public class NodeRunner { + private Long timeout = 30 * 1000l; + private final Path baseDir; + private final Path confDir; + private final Path dataDir; + + private String baseUrl = "http://forge.argeo.org/data/java/argeo-2.1/"; + private String distributionUrl = null; + + private Framework framework = null; + + public NodeRunner(String distributionUrl, Path baseDir) { + this.distributionUrl = distributionUrl; + Path mavenBase = Paths.get(System.getProperty("user.home") + "/.m2/repository"); + Path osgiBase = Paths.get("/user/share/osgi"); + if (Files.exists(mavenBase)) { + Path mavenPath = mavenBase.resolve(distributionUrl); + if (Files.exists(mavenPath)) + baseUrl = mavenBase.toUri().toString(); + } else if (Files.exists(osgiBase)) { + Path osgiPath = osgiBase.resolve(distributionUrl); + if (Files.exists(osgiPath)) + baseUrl = osgiBase.toUri().toString(); + } + + this.baseDir = baseDir; + this.confDir = baseDir.resolve("state"); + this.dataDir = baseDir.resolve("data"); + + } + + public void start() { + long begin = System.currentTimeMillis(); + // log4j + Path log4jFile = confDir.resolve("log4j.properties"); + if (!Files.exists(log4jFile)) + copyResource("/org/argeo/osgi/boot/log4j.properties", log4jFile); + System.setProperty("log4j.configuration", "file://" + log4jFile.toAbsolutePath()); + + // Start Equinox + try { + ServiceLoader ff = ServiceLoader.load(FrameworkFactory.class); + FrameworkFactory frameworkFactory = ff.iterator().next(); + Map configuration = new HashMap(); + configuration.put("osgi.configuration.area", confDir.toAbsolutePath().toString()); + configuration.put("osgi.instance.area", dataDir.toAbsolutePath().toString()); + defaultConfiguration(configuration); + + framework = frameworkFactory.newFramework(configuration); + framework.start(); + info("## Date : " + new Date()); + info("## Data : " + dataDir.toAbsolutePath()); + } catch (Exception e) { + throw new IllegalStateException("Cannot start OSGi framework", e); + } + BundleContext bundleContext = framework.getBundleContext(); + try { + + // Spring configs currently require System properties + // System.getProperties().putAll(configuration); + + // expected by JAAS as System.property FIXME + System.setProperty("osgi.instance.area", bundleContext.getProperty("osgi.instance.area")); + + // OSGi bootstrap + OsgiBoot osgiBoot = new OsgiBoot(bundleContext); + + osgiBoot.installUrls(osgiBoot.getDistributionUrls(distributionUrl, baseUrl)); + + // Start runtime + Properties startProperties = new Properties(); + // TODO make it possible to override it + startProperties.put("argeo.osgi.start.2.node", + "org.eclipse.equinox.http.servlet,org.eclipse.equinox.http.jetty," + + "org.eclipse.equinox.metatype,org.eclipse.equinox.cm,org.eclipse.rap.rwt.osgi"); + startProperties.put("argeo.osgi.start.3.node", "org.argeo.cms"); + startProperties.put("argeo.osgi.start.4.node", + "org.eclipse.gemini.blueprint.extender,org.eclipse.equinox.http.registry"); + osgiBoot.startBundles(startProperties); + + // Find node repository + ServiceReference sr = null; + while (sr == null) { + sr = bundleContext.getServiceReference("javax.jcr.Repository"); + if (System.currentTimeMillis() - begin > timeout) + throw new RuntimeException("Could find node after " + timeout + "ms"); + Thread.sleep(100); + } + Object nodeDeployment = bundleContext.getService(sr); + info("Node Deployment " + nodeDeployment); + + // Initialization completed + long duration = System.currentTimeMillis() - begin; + info("## CMS Launcher initialized in " + (duration / 1000) + "s " + (duration % 1000) + "ms"); + } catch (Exception e) { + shutdown(); + throw new RuntimeException("Cannot start CMS", e); + } finally { + + } + } + + private void defaultConfiguration(Map configuration) { + // all permissions to OSGi security manager + Path policyFile = confDir.resolve("osgi.policy"); + if (!Files.exists(policyFile)) + copyResource("/org/argeo/osgi/boot/osgi.policy", policyFile); + configuration.put("java.security.policy", "file://" + policyFile.toAbsolutePath()); + + configuration.put("org.eclipse.rap.workbenchAutostart", "false"); + configuration.put("org.eclipse.equinox.http.jetty.autostart", "false"); + configuration.put("org.osgi.framework.bootdelegation", + "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"); + + // Do clean + // configuration.put("osgi.clean", "true"); + // if (args.length == 0) { + // configuration.put("osgi.console", ""); + // } + } + + public void shutdown() { + try { + framework.stop(); + framework.waitForStop(15 * 1000); + } catch (Exception silent) { + } + } + + public Path getConfDir() { + return confDir; + } + + public Path getDataDir() { + return dataDir; + } + + public Framework getFramework() { + return framework; + } + + public static void main(String[] args) { + try { + // Prepare directories + Path executionDir = Paths.get(System.getProperty("user.dir")); + + String distributionUrl; + if (args.length == 0) { + distributionUrl = "org/argeo/commons/org.argeo.dep.cms.sdk/2.1.65/org.argeo.dep.cms.sdk-2.1.65.jar"; + } else { + distributionUrl = args[0]; + } + + NodeRunner nodeRunner = new NodeRunner(distributionUrl, executionDir); + nodeRunner.start(); + if (args.length != 0) + System.exit(0); + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + } + + protected static void info(Object msg) { + System.out.println(msg); + } + + protected static void err(Object msg) { + System.err.println(msg); + } + + protected static void debug(Object msg) { + System.out.println(msg); + } + + protected static void copyResource(String resource, Path targetFile) { + InputStream input = null; + OutputStream output = null; + try { + input = NodeRunner.class.getResourceAsStream(resource); + Files.createDirectories(targetFile.getParent()); + output = Files.newOutputStream(targetFile); + byte[] buf = new byte[8192]; + while (true) { + int length = input.read(buf); + if (length < 0) + break; + output.write(buf, 0, length); + } + } catch (Exception e) { + throw new RuntimeException("Cannot write " + resource + " file to " + targetFile, e); + } finally { + try { + input.close(); + } catch (Exception ignore) { + } + try { + output.close(); + } catch (Exception ignore) { + } + } + + } + +} 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 2d24cc881..bd49d99d4 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 @@ -232,15 +232,19 @@ public class OsgiBoot implements OsgiBootConstants { * START */ public void startBundles() { + startBundles(System.getProperties()); + } + + public void startBundles(Properties properties) { FrameworkStartLevel frameworkStartLevel = bundleContext.getBundle(0).adapt(FrameworkStartLevel.class); // default and active start levels from System properties Integer defaultStartLevel = new Integer( - Integer.parseInt(OsgiBootUtils.getProperty(PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "4"))); - Integer activeStartLevel = new Integer(OsgiBootUtils.getProperty(PROP_OSGI_STARTLEVEL, "6")); + Integer.parseInt(getProperty(PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "4"))); + Integer activeStartLevel = new Integer(getProperty(PROP_OSGI_STARTLEVEL, "6")); SortedMap> startLevels = new TreeMap>(); - computeStartLevels(startLevels, System.getProperties(), defaultStartLevel); + computeStartLevels(startLevels, properties, defaultStartLevel); // inverts the map for the time being, TODO optimise Map bundleStartLevels = new HashMap<>(); for (Integer level : startLevels.keySet()) { @@ -445,7 +449,7 @@ public class OsgiBoot implements OsgiBootConstants { * effects. */ public List getBundlesUrls() { - String bundlePatterns = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BUNDLES); + String bundlePatterns = getProperty(PROP_ARGEO_OSGI_BUNDLES); return getBundlesUrls(bundlePatterns); } @@ -454,7 +458,7 @@ public class OsgiBoot implements OsgiBootConstants { * default base url */ public List getBundlesUrls(String bundlePatterns) { - String baseUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BASE_URL, DEFAULT_BASE_URL); + String baseUrl = getProperty(PROP_ARGEO_OSGI_BASE_URL, DEFAULT_BASE_URL); return getBundlesUrls(baseUrl, bundlePatterns); } @@ -514,11 +518,15 @@ public class OsgiBoot implements OsgiBootConstants { * DISTRIBUTION JAR INSTALLATION */ public List getDistributionUrls() { + String distributionUrl = getProperty(PROP_ARGEO_OSGI_DISTRIBUTION_URL); + String baseUrl = getProperty(PROP_ARGEO_OSGI_BASE_URL); + return getDistributionUrls(distributionUrl, baseUrl); + } + + public List getDistributionUrls(String distributionUrl, String baseUrl) { List urls = new ArrayList(); - String distributionUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_DISTRIBUTION_URL); if (distributionUrl == null) return urls; - String baseUrl = OsgiBootUtils.getProperty(PROP_ARGEO_OSGI_BASE_URL); DistributionBundle distributionBundle; if (baseUrl != null && !(distributionUrl.startsWith("http") || distributionUrl.startsWith("file"))) { @@ -646,6 +654,33 @@ public class OsgiBoot implements OsgiBootConstants { // return url; // } + /** + * Gets a property value + * + * @return null when defaultValue is "" + */ + public String getProperty(String name, String defaultValue) { + String value = bundleContext.getProperty(name); + if (value == null) + return defaultValue; // may be null + else + return value; + +// if (defaultValue != null) +// value = System.getProperty(name, defaultValue); +// else +// value = System.getProperty(name); +// +// if (value == null || value.equals("")) +// return null; +// else +// return value; + } + + public String getProperty(String name) { + return getProperty(name, null); + } + /* * BEAN METHODS */ diff --git a/org.argeo.osgi.boot/src/org/argeo/osgi/boot/OsgiBootUtils.java b/org.argeo.osgi.boot/src/org/argeo/osgi/boot/OsgiBootUtils.java index 54efffc80..da142cfe9 100644 --- a/org.argeo.osgi.boot/src/org/argeo/osgi/boot/OsgiBootUtils.java +++ b/org.argeo.osgi.boot/src/org/argeo/osgi/boot/OsgiBootUtils.java @@ -47,27 +47,6 @@ public class OsgiBootUtils { e.printStackTrace(); } - /** - * Gets a property value - * - * @return null when defaultValue is "" - */ - public static String getProperty(String name, String defaultValue) { - final String value; - if (defaultValue != null) - value = System.getProperty(name, defaultValue); - else - value = System.getProperty(name); - - if (value == null || value.equals("")) - return null; - else - return value; - } - - public static String getProperty(String name) { - return getProperty(name, null); - } public static String stateAsString(int state) { switch (state) { diff --git a/org.argeo.osgi.boot/src/org/argeo/osgi/boot/log4j.properties b/org.argeo.osgi.boot/src/org/argeo/osgi/boot/log4j.properties new file mode 100644 index 000000000..1fcf25e3b --- /dev/null +++ b/org.argeo.osgi.boot/src/org/argeo/osgi/boot/log4j.properties @@ -0,0 +1,12 @@ +log4j.rootLogger=WARN, console + +log4j.logger.org.argeo=INFO + +## Appenders +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c - [%t]%n + +log4j.appender.development=org.apache.log4j.ConsoleAppender +log4j.appender.development.layout=org.apache.log4j.PatternLayout +log4j.appender.development.layout.ConversionPattern=%d{ABSOLUTE} %m (%F:%L) [%t] %p %n diff --git a/org.argeo.osgi.boot/src/org/argeo/osgi/boot/osgi.policy b/org.argeo.osgi.boot/src/org/argeo/osgi/boot/osgi.policy new file mode 100644 index 000000000..facb61327 --- /dev/null +++ b/org.argeo.osgi.boot/src/org/argeo/osgi/boot/osgi.policy @@ -0,0 +1,3 @@ +grant { + permission java.security.AllPermission; +}; \ No newline at end of file