]> git.argeo.org Git - gpl/argeo-slc.git/blobdiff - org.argeo.slc.detached.launcher/src/main/java/org/argeo/slc/detached/launcher/Main.java
Introduce SLC Detached app launcher
[gpl/argeo-slc.git] / org.argeo.slc.detached.launcher / src / main / java / org / argeo / slc / detached / launcher / Main.java
index 423b1cbc49f3d09de8bc55ea04a8819bf108ab73..684b15493a08dd837e8ef671e47c55f4f82ef2d1 100644 (file)
@@ -2,49 +2,42 @@ package org.argeo.slc.detached.launcher;
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
+import java.util.StringTokenizer;
 import java.util.Vector;
 
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.felix.framework.Felix;
-import org.apache.felix.framework.cache.BundleCache;
-import org.apache.felix.main.AutoActivator;
+import org.eclipse.core.runtime.adaptor.EclipseStarter;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
 
 public class Main {
-       private final static Log log = LogFactory.getLog(Main.class);
+       private final static String DEV_BUNDLE_PREFIX = "slc.osgi.devbundle.";
 
        public static void main(String[] args) {
-               log.info("Argeo SLC Detached launcher starting...");
+               info("Argeo SLC Detached launcher starting...");
                try {
                        // Load properties
                        String propertyPath = "slc-detached.properties";
                        Properties config = prepareConfig(propertyPath);
 
-                       // Create cache dir
-                       if (!config.containsKey(BundleCache.CACHE_PROFILE_DIR_PROP)) {
-                               final File cachedir = createTemporaryCacheDir();
-                               config.put(BundleCache.CACHE_PROFILE_DIR_PROP, cachedir
-                                               .getAbsolutePath());
-                       }
-
                        // Start app (in main class loader)
                        startApp(config);
-                       // Thread.sleep(10000);
-
-                       // Start OSGi system
-                       Felix felix = startSystem(config);
 
-                       log.info("Argeo SLC Detached system started (Felix " + felix + ")");
-
-                       // felix.stop();
+                       // Start OSGi framework
+                       try {
+                               startEquinox(config);
+                       } catch (Exception e) {
+                               // TODO Auto-generated catch block
+                               e.printStackTrace();
+                       }
+                       info("Argeo SLC Detached launcher started.");
                } catch (Exception e) {
                        e.printStackTrace();
                        System.exit(-1);
@@ -63,15 +56,6 @@ public class Main {
                // Load config
                Properties config = new Properties();
                InputStream in = null;
-
-               try {
-                       in = Main.class
-                                       .getResourceAsStream("/org/argeo/slc/detached/launcher/felix.properties");
-                       config.load(in);
-               } finally {
-                       IOUtils.closeQuietly(in);
-               }
-
                try {
                        File file = new File(propertyFilePath);
                        if (file.exists()) {
@@ -79,50 +63,127 @@ public class Main {
                                config.load(in);
                        }
                } finally {
-                       IOUtils.closeQuietly(in);
+                       if (in != null)
+                               in.close();
                }
 
                // System properties have priority.
                config.putAll(System.getProperties());
+               return config;
+       }
+
+       public static void startEquinox(Properties config) throws Exception {
+               System.out.println("java.class.path="
+                               + System.getProperty("java.class.path"));
+
+               File baseDir = new File(System.getProperty("user.dir"))
+                               .getCanonicalFile();
+               String equinoxConfigurationPath = baseDir.getPath() + File.separator
+                               + "slc-detached" + File.separator + "equinoxConfiguration";
+               String[] equinoxArgs = { "-console", "-noExit", "-clean", "-debug",
+                               "-configuration", equinoxConfigurationPath };
 
-               // Perform variable substitution for system properties.
-               for (Enumeration e = config.propertyNames(); e.hasMoreElements();) {
-                       String name = (String) e.nextElement();
-                       config.setProperty(name, org.apache.felix.main.Main.substVars(
-                                       config.getProperty(name), name, null, config));
-                       if (log.isTraceEnabled())
-                               log.trace(name + "=" + config.getProperty(name));
+               BundleContext context = EclipseStarter.startup(equinoxArgs, null);
+
+               // Load from class path (dev environment, maven)
+               StringTokenizer st = new StringTokenizer(System
+                               .getProperty("java.class.path"), File.pathSeparator);
+               while (st.hasMoreTokens()) {
+                       try {
+                               String path = st.nextToken();
+                               String url = "reference:file:"
+                                               + new File(path).getCanonicalPath();
+                               context.installBundle(url);
+                               info("Installed from classpath " + url);
+                       } catch (Exception e) {
+                               bundleInstallWarn(e.getMessage());
+                       }
                }
 
-               return config;
+               // Load from dev bundles
+               Map devBundleUrls = getDevBundleUrls(config);
+               Iterator devBundles = devBundleUrls.keySet().iterator();
+               while (devBundles.hasNext()) {
+                       try {
+                               String bundleName = (String) devBundles.next();
+                               String url = (String) devBundleUrls.get(bundleName);
+                               context.installBundle(url);
+                               info("Installed as dev bundle " + url);
+                       } catch (Exception e) {
+                               bundleInstallWarn(e.getMessage());
+                       }
+               }
+
+               // Load from distribution
+               String slcHome = config.getProperty("slc.home");
+               if (slcHome != null) {
+                       File libDir = new File(slcHome + File.separator + "lib");
+                       File[] bundleFiles = libDir.listFiles();
+                       for (int i = 0; i < bundleFiles.length; i++) {
+                               try {
+                                       String url = "reference:file:"
+                                                       + bundleFiles[i].getCanonicalPath();
+                                       context.installBundle(url);
+                                       info("INFO: Installed from SLC home " + url);
+                               } catch (Exception e) {
+                                       bundleInstallWarn(e.getMessage());
+                               }
+
+                       }
+               }
+
+               // Start bundles
+               String bundleStart = config.getProperty("slc.osgi.start",
+                               "org.springframework.osgi.extender,org.argeo.slc.detached");
+               StringTokenizer stBundleStart = new StringTokenizer(bundleStart, ",");
+               while (stBundleStart.hasMoreTokens()) {
+                       String bundleSymbolicName = stBundleStart.nextToken();
+                       startBundle(context, bundleSymbolicName);
+               }
        }
 
-       protected static File createTemporaryCacheDir() throws IOException {
-               // Create a temporary bundle cache directory and
-               // make sure to clean it up on exit.
-               final File cachedir = File.createTempFile("argeo.slc.autoui", null);
-               cachedir.delete();
-               Runtime.getRuntime().addShutdownHook(new Thread() {
-                       public void run() {
-                               deleteFileOrDir(cachedir);
+       private static Map getDevBundleUrls(Properties config) {
+               Map bundles = new Hashtable();
+               Iterator keys = config.keySet().iterator();
+               while (keys.hasNext()) {
+                       String key = (String) keys.next();
+                       if (key.startsWith(DEV_BUNDLE_PREFIX)) {
+                               String bundle = key.substring(DEV_BUNDLE_PREFIX.length());
+                               String path = config.getProperty(key);
+                               bundles.put(bundle, path);
                        }
-               });
-               return cachedir;
+               }
+               return bundles;
        }
 
-       public static Felix startSystem(Properties config) throws Exception {
-               // Create list to hold custom framework activators.
-               List list = new ArrayList();
-               // Add activator to process auto-start/install properties.
-               list.add(new AutoActivator(config));
-               // Add our own activator.
-               // list.add(new AutoUiActivator());
+       private static void startBundle(BundleContext bundleContext,
+                       String symbolicName) throws BundleException {
+               info("Starting bundle " + symbolicName + "...");
+               Bundle bundle = findBundleBySymbolicName(bundleContext, symbolicName);
+               if (bundle != null)
+                       bundle.start();
+               else
+                       throw new RuntimeException("Bundle " + symbolicName + " not found");
+               info("Started " + symbolicName);
+       }
 
-               // Now create an instance of the framework.
-               Felix felix = new Felix(config, list);
-               felix.start();
+       /** WARNING: return the first one found! */
+       private static Bundle findBundleBySymbolicName(BundleContext bundleContext,
+                       String symbolicName) {
+               Bundle[] bundles = bundleContext.getBundles();
+               for (int i = 0; i < bundles.length; i++) {
+                       Bundle bundle = bundles[i];
+                       String bundleSymbolicName = bundle.getSymbolicName();
+                       if (bundleSymbolicName == null)
+                               throw new RuntimeException("Bundle " + bundle.getBundleId()
+                                               + " (" + bundle.getLocation()
+                                               + ") has no symbolic name.");
 
-               return felix;
+                       if (bundleSymbolicName.equals(symbolicName)) {
+                               return bundle;
+                       }
+               }
+               return null;
        }
 
        public static void startApp(Properties config) throws Exception {
@@ -130,37 +191,18 @@ public class Main {
                String[] uiArgs = readArgumentsFromLine(config.getProperty(
                                "slc.detached.appargs", ""));
 
-               if (className == null)
-                       throw new Exception(
-                                       "A main class has to be defined with teh system property slc.detached.appclass");
-
-               // Launch main method using reflection
-               Class clss = Class.forName(className);
-               Class[] mainArgsClasses = new Class[] { uiArgs.getClass() };
-               Object[] mainArgs = { uiArgs };
-               Method mainMethod = clss.getMethod("main", mainArgsClasses);
-               String[] passedArgs = (String[])mainArgs[0];
-               System.out.println("PASSED ARGS:");
-               for(int i=0;i<passedArgs.length;i++){
-                       System.out.println(passedArgs[i]);
+               if (className == null) {
+                       info("No slc.detached.appclass property define: does not try to launch an app from the standard classpath.");
+               } else {
+                       // Launch main method using reflection
+                       Class clss = Class.forName(className);
+                       Class[] mainArgsClasses = new Class[] { uiArgs.getClass() };
+                       Object[] mainArgs = { uiArgs };
+                       Method mainMethod = clss.getMethod("main", mainArgsClasses);
+                       mainMethod.invoke(null, mainArgs);
                }
-               mainMethod.invoke(null, mainArgs);
        }
 
-       // protected static void automateUi(BundleContext bundleContext)
-       // throws Exception {
-       // // Retrieve service and execute it
-       // ServiceReference ref = bundleContext
-       // .getServiceReference(DetachedExecutionServer.class.getName());
-       // Object service = bundleContext.getService(ref);
-       //
-       // log.debug("service.class=" + service.getClass());
-       // DetachedExecutionServer app = (DetachedExecutionServer) service;
-       // DetachedStepRequest request = new DetachedStepRequest();
-       // request.setStepRef("jemmyTest");
-       // app.executeStep(request);
-       // }
-
        /* UTILITIES */
 
        /**
@@ -209,14 +251,11 @@ public class Main {
                return res;
        }
 
-       private static void deleteFileOrDir(File file) {
-               if (file.isDirectory()) {
-                       File[] childs = file.listFiles();
-                       for (int i = 0; i < childs.length; i++) {
-                               deleteFileOrDir(childs[i]);
-                       }
-               }
-               file.delete();
+       private static void info(Object obj) {
+               System.out.println("[INFO] " + obj);
        }
 
+       private static void bundleInstallWarn(Object obj) {
+               System.err.println("[WARN] " + obj);
+       }
 }