Introduce node runner
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 7 Apr 2017 11:17:46 +0000 (13:17 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 7 Apr 2017 11:17:46 +0000 (13:17 +0200)
org.argeo.osgi.boot/src/org/argeo/osgi/boot/Launcher.java
org.argeo.osgi.boot/src/org/argeo/osgi/boot/NodeRunner.java [new file with mode: 0644]
org.argeo.osgi.boot/src/org/argeo/osgi/boot/OsgiBoot.java
org.argeo.osgi.boot/src/org/argeo/osgi/boot/OsgiBootUtils.java
org.argeo.osgi.boot/src/org/argeo/osgi/boot/log4j.properties [new file with mode: 0644]
org.argeo.osgi.boot/src/org/argeo/osgi/boot/osgi.policy [new file with mode: 0644]

index b13e066b815cd64e8d2365956782d5f7d22a83ec..7fd3e76093767b6259bbc7cdfb829997a2afc6ed 100644 (file)
@@ -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 (file)
index 0000000..94fd1fd
--- /dev/null
@@ -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<FrameworkFactory> ff = ServiceLoader.load(FrameworkFactory.class);
+                       FrameworkFactory frameworkFactory = ff.iterator().next();
+                       Map<String, String> configuration = new HashMap<String, String>();
+                       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<String, String> 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) {
+                       }
+               }
+
+       }
+
+}
index 2d24cc8811d0be7a2fb3520f082bfca562f15c63..bd49d99d47dcd8f465bb8f4f4d70268da7e5a289 100644 (file)
@@ -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<Integer, List<String>> startLevels = new TreeMap<Integer, List<String>>();
-               computeStartLevels(startLevels, System.getProperties(), defaultStartLevel);
+               computeStartLevels(startLevels, properties, defaultStartLevel);
                // inverts the map for the time being, TODO optimise
                Map<String, Integer> bundleStartLevels = new HashMap<>();
                for (Integer level : startLevels.keySet()) {
@@ -445,7 +449,7 @@ public class OsgiBoot implements OsgiBootConstants {
         * effects.
         */
        public List<String> 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<String> 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<String> getDistributionUrls() {
+               String distributionUrl = getProperty(PROP_ARGEO_OSGI_DISTRIBUTION_URL);
+               String baseUrl = getProperty(PROP_ARGEO_OSGI_BASE_URL);
+               return getDistributionUrls(distributionUrl, baseUrl);
+       }
+
+       public List<String> getDistributionUrls(String distributionUrl, String baseUrl) {
                List<String> urls = new ArrayList<String>();
-               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
         */
index 54efffc8056504f7e15234c4791b742a7a406366..da142cfe9b79c0a7327021e737209c93596f85ff 100644 (file)
@@ -47,27 +47,6 @@ public class OsgiBootUtils {
                        e.printStackTrace();\r
        }\r
 \r
-       /**\r
-        * Gets a property value\r
-        * \r
-        * @return null when defaultValue is ""\r
-        */\r
-       public static String getProperty(String name, String defaultValue) {\r
-               final String value;\r
-               if (defaultValue != null)\r
-                       value = System.getProperty(name, defaultValue);\r
-               else\r
-                       value = System.getProperty(name);\r
-\r
-               if (value == null || value.equals(""))\r
-                       return null;\r
-               else\r
-                       return value;\r
-       }\r
-\r
-       public static String getProperty(String name) {\r
-               return getProperty(name, null);\r
-       }\r
 \r
        public static String stateAsString(int state) {\r
                switch (state) {\r
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 (file)
index 0000000..1fcf25e
--- /dev/null
@@ -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 (file)
index 0000000..facb613
--- /dev/null
@@ -0,0 +1,3 @@
+grant {
+  permission java.security.AllPermission;
+};
\ No newline at end of file