Scripting support
authorMathieu Baudier <mbaudier@argeo.org>
Sat, 3 Feb 2018 20:44:28 +0000 (21:44 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Sat, 3 Feb 2018 20:44:28 +0000 (21:44 +0100)
demo/argeo_node.js [new file with mode: 0755]
dist/argeo-node/pom.xml
dist/argeo-node/rpm/usr/share/node/jjs/cms.js [new file with mode: 0755]
dist/osgi-boot/pom.xml
dist/osgi-boot/src/main/rpm/usr/bin/a2jjs [new file with mode: 0755]
org.argeo.osgi.boot/bnd.bnd
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/OsgiBuilder.java [new file with mode: 0644]

diff --git a/demo/argeo_node.js b/demo/argeo_node.js
new file mode 100755 (executable)
index 0000000..4dc012b
--- /dev/null
@@ -0,0 +1,16 @@
+#!/home/mbaudier/dev/git/apache2/argeo-commons/dist/osgi-boot/src/main/rpm/usr/bin/a2jjs
+
+// demo specific
+var app = "node";
+var demoHome = $ENV.HOME + "/dev/git/apache2/argeo-commons/demo";
+var appHome = demoHome + "/exec/argeo_node.js";
+var appConf = demoHome;
+var policyFile = "all.policy";
+load("../dist/argeo-node/rpm/usr/share/node/jjs/cms.js");
+
+var distribution = "org.argeo.commons:org.argeo.dep.cms.platform:2.1.71-SNAPSHOT";
+osgi.install(distribution);
+osgi.conf("org.osgi.service.http.port", "7070");
+
+// osgi.conf("osgi.clean", true);
+osgi.launch();
index da1c8cf5b5e5f36477f0ea5669d89b7b41a0e216..7d13069e546bcf9becadbe40b9bfedeb00ce8697 100644 (file)
@@ -1,4 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
                <groupId>org.argeo.commons</groupId>
                                                                                                </source>
                                                                                        </sources>
                                                                                </mapping>
+                                                                               <mapping>
+                                                                                       <directory>/usr/share/node/jjs</directory>
+                                                                                       <username>root</username>
+                                                                                       <groupname>root</groupname>
+                                                                                       <filemode>644</filemode>
+                                                                                       <directoryIncluded>false</directoryIncluded>
+                                                                                       <sources>
+                                                                                               <source>
+                                                                                                       <location>rpm/usr/share/node/jjs</location>
+                                                                                                       <includes>
+                                                                                                               <include>*.js</include>
+                                                                                                       </includes>
+                                                                                               </source>
+                                                                                       </sources>
+                                                                               </mapping>
                                                                                <mapping>
                                                                                        <directory>/usr/sbin</directory>
                                                                                        <username>root</username>
diff --git a/dist/argeo-node/rpm/usr/share/node/jjs/cms.js b/dist/argeo-node/rpm/usr/share/node/jjs/cms.js
new file mode 100755 (executable)
index 0000000..b78fe0b
--- /dev/null
@@ -0,0 +1,36 @@
+var System = Java.type("java.lang.System")
+var OsgiBuilder = Java.type("org.argeo.osgi.boot.OsgiBuilder");
+
+var osgi = new OsgiBuilder();
+osgi.start(2, "org.eclipse.equinox.http.servlet");
+osgi.start(2, "org.eclipse.equinox.http.jetty");
+osgi.start(2, "org.eclipse.equinox.metatype");
+osgi.start(2, "org.eclipse.equinox.cm");
+osgi.start(2, "org.eclipse.rap.rwt.osgi");
+osgi.start(3, "org.argeo.cms");
+osgi.start(4, "org.eclipse.gemini.blueprint.extender");
+osgi.start(4, "org.eclipse.equinox.http.registry");
+osgi.conf("org.eclipse.rap.workbenchAutostart", "false");
+osgi.conf("org.eclipse.equinox.http.jetty.autostart", "false");
+osgi.conf("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");
+
+if (typeof app !== 'undefined') {
+       if (typeof appHome == 'undefined') {
+               var appHome = $ENV.HOME + "/.a2/var/lib/" + app;
+       }
+       if (typeof appConf == 'undefined') {
+               var appConf = $ENV.HOME + "/.a2/etc/" + app;
+       }
+       if (typeof policyFile == 'undefined') {
+               var policyFile = app + ".policy";
+       }
+       osgi.conf("osgi.configuration.area", appHome + "/state");
+       osgi.conf("osgi.instance.area", appHome + "/data");
+       System.setProperty("java.security.manager", "");
+       System.setProperty("java.security.policy", "file://" + appConf + "/"
+                       + policyFile);
+       System.setProperty("log4j.configuration", "file://" + appConf
+                       + "/log4j.properties");
+}
\ No newline at end of file
index 82b93b910c5f9019124b99b3875153c7728679a9..89fd1cff9afccc29a0a1fd129c12fcb8d407d9fb 100644 (file)
                                                                                                </source>
                                                                                        </sources>
                                                                                </mapping>
+                                                                               <mapping>
+                                                                                       <directory>/usr/bin</directory>
+                                                                                       <username>root</username>
+                                                                                       <groupname>root</groupname>
+                                                                                       <filemode>755</filemode>
+                                                                                       <directoryIncluded>false</directoryIncluded>
+                                                                                       <sources>
+                                                                                               <source>
+                                                                                                       <location>src/main/rpm/usr/sbin</location>
+                                                                                                       <includes>
+                                                                                                               <include>*</include>
+                                                                                                       </includes>
+                                                                                               </source>
+                                                                                       </sources>
+                                                                               </mapping>
                                                                                <mapping>
                                                                                        <directory>/usr/sbin</directory>
                                                                                        <username>root</username>
diff --git a/dist/osgi-boot/src/main/rpm/usr/bin/a2jjs b/dist/osgi-boot/src/main/rpm/usr/bin/a2jjs
new file mode 100755 (executable)
index 0000000..4ffab9f
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+PREFIX=$HOME/.a2
+#PREFIX=/usr
+
+/usr/bin/jjs \
+ -cp "$PREFIX/share/osgi/boot/org.eclipse.osgi.jar:$PREFIX/share/osgi/boot/org.argeo.osgi.boot.jar" \
+ $*
+
index 9fb5d87be67b2218b9c0ad80e2336cc138d22b40..f0fa329c80ac32e93c2784bd01c2ff8b5fdf0e67 100644 (file)
@@ -1,4 +1,5 @@
 Bundle-Activator: org.argeo.osgi.boot.Activator
 Import-Package: org.eclipse.*;resolution:=optional,\
+org.eclipse.osgi.launch.*;resolution:=optional,\
 org.osgi.*;version=0.0.0,\
 *
index f8bee95deea112bce179c26fecfb71a07196e389..bdf7134b85441df762d5ca3120e4e51b43e6f768 100644 (file)
@@ -67,9 +67,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";
@@ -277,7 +278,7 @@ public class OsgiBoot implements OsgiBootConstants {
                });
        }
 
-       public static void computeStartLevels(SortedMap<Integer, List<String>> startLevels, Properties properties,
+       private static void computeStartLevels(SortedMap<Integer, List<String>> startLevels, Properties properties,
                        Integer defaultStartLevel) {
 
                // default (and previously, only behaviour)
@@ -431,12 +432,11 @@ public class OsgiBoot implements OsgiBootConstants {
         * BUNDLE PATTERNS INSTALLATION
         */
        /**
-        * Computes a list of URLs based on Ant-like include/exclude patterns
-        * defined by ${argeo.osgi.bundles} with the following format:<br>
+        * Computes a list of URLs based on Ant-like include/exclude patterns defined by
+        * ${argeo.osgi.bundles} with the following format:<br>
         * <code>/base/directory;in=*.jar;in=**;ex=org.eclipse.osgi_*;jar</code><br>
         * WARNING: <code>/base/directory;in=*.jar,\</code> 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<String> getBundlesUrls() {
                String bundlePatterns = getProperty(PROP_ARGEO_OSGI_BUNDLES);
@@ -444,7 +444,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<String> getBundlesUrls(String bundlePatterns) {
@@ -453,7 +453,7 @@ public class OsgiBoot implements OsgiBootConstants {
        }
 
        /** Implements the path matching logic */
-       List<String> getBundlesUrls(String baseUrl, String bundlePatterns) {
+       public List<String> getBundlesUrls(String baseUrl, String bundlePatterns) {
                List<String> urls = new ArrayList<String>();
                if (bundlePatterns == null)
                        return urls;
@@ -519,15 +519,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();
        }
@@ -674,6 +703,10 @@ public class OsgiBoot implements OsgiBootConstants {
                return bundleContext;
        }
 
+       public String getLocalCache() {
+               return localCache;
+       }
+
        // public void setDefaultTimeout(long defaultTimeout) {
        // this.defaultTimeout = defaultTimeout;
        // }
index e212126621b179e3326d9752cad28f36ddc660b2..455c96198b3d76f1e8c344608db3b1f08a0a6d54 100644 (file)
@@ -29,8 +29,8 @@ public class OsgiBootUtils {
        /** ISO8601 (as per log4j) and difference to UTC */\r
        private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS Z");\r
 \r
-       static boolean debug = Boolean.valueOf(System.getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_DEBUG, "false"))\r
-                       .booleanValue();\r
+       static boolean debug = System.getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_DEBUG) == null ? false\r
+                       : !System.getProperty(OsgiBoot.PROP_ARGEO_OSGI_BOOT_DEBUG).trim().equals("false");\r
 \r
        public static void info(Object obj) {\r
                System.out.println("# OSGiBOOT      # " + dateFormat.format(new Date()) + " # " + obj);\r
@@ -51,6 +51,10 @@ public class OsgiBootUtils {
                        e.printStackTrace();\r
        }\r
 \r
+       public static boolean isDebug() {\r
+               return debug;\r
+       }\r
+\r
        public static String stateAsString(int state) {\r
                switch (state) {\r
                case Bundle.UNINSTALLED:\r
diff --git a/org.argeo.osgi.boot/src/org/argeo/osgi/boot/OsgiBuilder.java b/org.argeo.osgi.boot/src/org/argeo/osgi/boot/OsgiBuilder.java
new file mode 100644 (file)
index 0000000..7a8fd96
--- /dev/null
@@ -0,0 +1,140 @@
+package org.argeo.osgi.boot;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.eclipse.osgi.launch.EquinoxFactory;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.launch.FrameworkFactory;
+
+public class OsgiBuilder {
+       private Map<Integer, StartLevel> startLevels = new TreeMap<>();
+       private List<String> distributionBundles = new ArrayList<>();
+
+       private Map<String, String> configuration = new HashMap<String, String>();
+       private Framework framework;
+
+       public OsgiBuilder() {
+               // configuration.put("osgi.clean", "true");
+               configuration.put(OsgiBoot.CONFIGURATION_AREA_PROP, System.getProperty(OsgiBoot.CONFIGURATION_AREA_PROP));
+               configuration.put(OsgiBoot.INSTANCE_AREA_PROP, System.getProperty(OsgiBoot.INSTANCE_AREA_PROP));
+       }
+
+       public Framework launch() {
+               // start OSGi
+               FrameworkFactory frameworkFactory = new EquinoxFactory();
+               framework = frameworkFactory.newFramework(configuration);
+               try {
+                       framework.start();
+               } catch (BundleException e) {
+                       throw new OsgiBootException("Cannot start OSGi framework", e);
+               }
+
+               BundleContext bc = framework.getBundleContext();
+               String osgiData = bc.getProperty(OsgiBoot.INSTANCE_AREA_PROP);
+               // String osgiConf = bc.getProperty(OsgiBoot.CONFIGURATION_AREA_PROP);
+               String osgiConf = framework.getDataFile("").getAbsolutePath();
+               if (OsgiBootUtils.isDebug())
+                       OsgiBootUtils.debug("OSGi starting - data: " + osgiData + " conf: " + osgiConf);
+
+               OsgiBoot osgiBoot = new OsgiBoot(framework.getBundleContext());
+               // install bundles
+               for (String distributionBundle : distributionBundles) {
+                       List<String> bundleUrls = osgiBoot.getDistributionUrls(distributionBundle, null);
+                       osgiBoot.installUrls(bundleUrls);
+               }
+
+               // start bundles
+               osgiBoot.startBundles(startLevelsToProperties());
+
+               // if (OsgiBootUtils.isDebug())
+               // for (Bundle bundle : bc.getBundles()) {
+               // OsgiBootUtils.debug(bundle.getLocation());
+               // }
+               return framework;
+       }
+
+       public OsgiBuilder conf(String key, String value) {
+               checkNotLaunched();
+               configuration.put(key, value);
+               return this;
+       }
+
+       public OsgiBuilder install(String uri) {
+               // TODO dynamic install
+               checkNotLaunched();
+               if (!distributionBundles.contains(uri))
+                       distributionBundles.add(uri);
+               return this;
+       }
+
+       public OsgiBuilder start(int startLevel, String bundle) {
+               // TODO dynamic start
+               checkNotLaunched();
+               StartLevel sl;
+               if (!startLevels.containsKey(startLevel))
+                       startLevels.put(startLevel, new StartLevel());
+               sl = startLevels.get(startLevel);
+               sl.add(bundle);
+               return this;
+       }
+
+       public BundleContext getBc() {
+               checkLaunched();
+               return framework.getBundleContext();
+       }
+
+       //
+       // UTILITIES
+       //
+       private Properties startLevelsToProperties() {
+               Properties properties = new Properties();
+               for (Integer startLevel : startLevels.keySet()) {
+                       String property = OsgiBoot.PROP_ARGEO_OSGI_START + "." + startLevel;
+                       StringBuilder value = new StringBuilder();
+                       for (String bundle : startLevels.get(startLevel).getBundles()) {
+                               value.append(bundle);
+                               value.append(',');
+                       }
+                       // TODO remove trailing comma
+                       properties.put(property, value.toString());
+               }
+               return properties;
+       }
+
+       private void checkLaunched() {
+               if (!isLaunched())
+                       throw new OsgiBootException("OSGi runtime is not launched");
+       }
+
+       private void checkNotLaunched() {
+               if (isLaunched())
+                       throw new OsgiBootException("OSGi runtime already launched");
+       }
+
+       private boolean isLaunched() {
+               return framework != null;
+       }
+
+       private static class StartLevel {
+               private Set<String> bundles = new HashSet<>();
+
+               public void add(String bundle) {
+                       String[] b = bundle.split(",");
+                       Collections.addAll(bundles, b);
+               }
+
+               public Set<String> getBundles() {
+                       return bundles;
+               }
+       }
+}