X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=runtime%2Forg.argeo.slc.launcher%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Fcli%2FSlcMain.java;h=4c5c82dd136f65493791e61941ec908136ebd8c2;hb=7e3da04a2593e3949edce627bd945bbaacc3480b;hp=15b42cd743529d444b775e58030dae2c6321f82e;hpb=fbcd3e375c8f4d3ce265297f2006c46b1fe36a6f;p=gpl%2Fargeo-slc.git diff --git a/runtime/org.argeo.slc.launcher/src/main/java/org/argeo/slc/cli/SlcMain.java b/runtime/org.argeo.slc.launcher/src/main/java/org/argeo/slc/cli/SlcMain.java index 15b42cd74..4c5c82dd1 100644 --- a/runtime/org.argeo.slc.launcher/src/main/java/org/argeo/slc/cli/SlcMain.java +++ b/runtime/org.argeo.slc.launcher/src/main/java/org/argeo/slc/cli/SlcMain.java @@ -1,236 +1,215 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.argeo.slc.cli; -import java.io.FileInputStream; -import java.util.Properties; - -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLineParser; -import org.apache.commons.cli.GnuParser; -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.OptionBuilder; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.core.SlcException; -import org.argeo.slc.logging.Log4jUtils; -import org.argeo.slc.runtime.SlcExecutionContext; -import org.argeo.slc.runtime.SlcRuntime; - -public class SlcMain { - public enum Mode { - single, agent +import java.io.File; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.UUID; + +import javax.security.auth.Subject; +import javax.security.auth.login.LoginContext; + +import org.argeo.osgi.boot.OsgiBoot; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.launch.Framework; +import org.osgi.framework.launch.FrameworkFactory; + +/** Configures an SLC runtime and runs a process. */ +public class SlcMain implements Runnable { + public final static String NIX = "NIX"; + public final static String WINDOWS = "WINDOWS"; + public final static String SOLARIS = "SOLARIS"; + + public final static String os; + static { + String osName = System.getProperty("os.name"); + if (osName.startsWith("Win")) + os = WINDOWS; + else if (osName.startsWith("Solaris")) + os = SOLARIS; + else + os = NIX; } - private static Log log = null; - - private final static String BOOTSTRAP_LOG4J_CONFIG = "org/argeo/slc/cli/bootstrapLog4j.properties"; - - private final static Option modeOpt = OptionBuilder.withLongOpt("mode") - .withArgName("mode").hasArg().withDescription( - "SLC execution mode, one of: " + listModeValues()).create( - 'm'); - - private final static Option propertyOpt = OptionBuilder.withLongOpt( - "property").withArgName("prop1=val1,prop2=val2").hasArgs() - .withValueSeparator(',').withDescription( - "use value for given property").create('p'); - - private final static Option propertiesOpt = OptionBuilder.withLongOpt( - "properties").withArgName("properties file").hasArgs() - .withValueSeparator(',').withDescription( - "load properties from file (-p has priority)").create('P'); - - private final static Option scriptOpt = OptionBuilder.withLongOpt("script") - .withArgName("script").hasArg().withDescription( - "SLC script to execute").create('s'); - - private final static Option targetsOpt = OptionBuilder.withLongOpt( - "targets").withArgName("targets").hasArg().withDescription( - "Targets to execute").create('t'); - - private final static Option runtimeOpt = OptionBuilder.withLongOpt( - "runtime").withArgName("runtime").hasArg().withDescription( - "Runtime to use, either a full path or relative to slc app conf dir: " - + "/runtime//.xml").create('r'); - - private final static Options options; - - private final static String commandName = "slc"; - - static { - options = new Options(); - options.addOption(modeOpt); - options.addOption(scriptOpt); - options.addOption(targetsOpt); - options.addOption(propertyOpt); - options.addOption(propertiesOpt); - options.addOption(runtimeOpt); + // private final DateFormat dateFormat = new + // SimpleDateFormat("HH:mm:ss,SSS"); + private Long timeout = 30 * 1000l; + private final String[] args; + + // private static String bundlesToInstall = "/usr/share/osgi;in=*.jar"; + private String bundlesToInstall = System.getProperty("user.home") + + "/dev/src/slc/dep/org.argeo.slc.dep.minimal/target/dependency;in=*.jar," + + System.getProperty("user.home") + + "/dev/src/slc/demo/modules;in=*;ex=pom.xml;ex=.svn"; + + private final List bundlesToStart = new ArrayList(); + + public SlcMain(String[] args) { + this.args = args; + bundlesToStart.add("org.springframework.osgi.extender"); + bundlesToStart.add("org.argeo.node.repo.jackrabbit"); + bundlesToStart.add("org.argeo.security.dao.os"); + bundlesToStart.add("org.argeo.slc.node.jackrabbit"); + bundlesToStart.add("org.argeo.slc.agent"); + bundlesToStart.add("org.argeo.slc.agent.jcr"); + // bundlesToStart.add("org.argeo.slc.agent.cli"); } - public static void main(String[] args) { - Mode mode = null; - Properties properties = new Properties(); - String script = null; - String targets = null; - String runtimeStr = null; + public void run() { + long begin = System.currentTimeMillis(); + // System.out.println(dateFormat.format(new Date())); + Boolean isTransient = false; + File dataDir = null; + final LoginContext lc; try { - - CommandLineParser clParser = new GnuParser(); - CommandLine cl = clParser.parse(options, args); - - // Mode - String modeStr = cl.getOptionValue(modeOpt.getOpt()); - if (modeStr == null) { - mode = Mode.single; - } else { - try { - mode = Mode.valueOf(modeStr); - } catch (IllegalArgumentException e) { - throw new SlcException("Unrecognized mode '" + modeStr - + "'", e); - } + // Authenticate + lc = new LoginContext(os); + lc.login(); + + // Prepare directories + String executionDir = System.getProperty("user.dir"); + File slcDir = new File(executionDir, ".slc"); + File tempDir = new File(System.getProperty("java.io.tmpdir")); + + if (isTransient) + dataDir = new File(tempDir, "slc-data-" + + UUID.randomUUID().toString()); + else + dataDir = new File(slcDir, "data"); + if (!dataDir.exists()) + dataDir.mkdirs(); + + File confDir = new File(slcDir, "conf"); + if (!confDir.exists()) + confDir.mkdirs(); + + System.setProperty("log4j.configuration", "file:./log4j.properties"); + if (isTransient) + System.setProperty("argeo.node.repo.configuration", + "osgibundle:repository-memory.xml"); + + // Start Equinox + ServiceLoader ff = ServiceLoader + .load(FrameworkFactory.class); + FrameworkFactory frameworkFactory = ff.iterator().next(); + Map configuration = new HashMap(); + configuration.put("osgi.configuration.area", + confDir.getCanonicalPath()); + configuration.put("osgi.instance.area", dataDir.getCanonicalPath()); + // configuration.put("osgi.clean", "true"); + // configuration.put("osgi.console", ""); + + // Spring configs currently require System properties + System.getProperties().putAll(configuration); + + Framework framework = frameworkFactory.newFramework(configuration); + framework.start(); + BundleContext bundleContext = framework.getBundleContext(); + // String[] osgiRuntimeArgs = { "-configuration", + // confDir.getCanonicalPath(), "-data", + // dataDir.getCanonicalPath(), "-clean" }; + // BundleContext bundleContext = EclipseStarter.startup( + // osgiRuntimeArgs, null); + + // OSGi bootstrap + OsgiBoot osgiBoot = new OsgiBoot(bundleContext); + osgiBoot.installUrls(osgiBoot.getBundlesUrls(bundlesToInstall)); + + // Start runtime + osgiBoot.startBundles(bundlesToStart); + + // Find SLC Agent + ServiceReference sr = null; + while (sr == null) { + sr = bundleContext + .getServiceReference("org.argeo.slc.execution.SlcAgentCli"); + if (System.currentTimeMillis() - begin > timeout) + throw new RuntimeException("Cannot find SLC agent CLI"); + Thread.sleep(100); } - - // Script - if (mode.equals(Mode.single)) { - if (!cl.hasOption(scriptOpt.getOpt())) - throw new SlcException("Mode " + Mode.single - + " requires option '" + scriptOpt.getLongOpt() - + "'"); - script = cl.getOptionValue(scriptOpt.getOpt()); - - // Targets - if (cl.hasOption(targetsOpt.getOpt())) - targets = cl.getOptionValue(targetsOpt.getOpt()); - } - - // Properties - if (cl.hasOption(propertiesOpt.getOpt())) { - for (String propertyFile : cl.getOptionValues(propertiesOpt - .getOpt())) { - loadPropertyFile(properties, propertyFile); - } - } - if (cl.hasOption(propertyOpt.getOpt())) { - for (String property : cl.getOptionValues(propertyOpt.getOpt())) { - addProperty(properties, property); - } - } - - // Runtime - if (cl.hasOption(runtimeOpt.getOpt())) { - runtimeStr = cl.getOptionValue(runtimeOpt.getOpt()); - } - } catch (ParseException e) { - System.err.println("Problem with command line arguments. " - + e.getMessage()); - badExit(); - } catch (SlcException e) { - System.err.println(e.getMessage()); - badExit(); + final Object agentCli = bundleContext.getService(sr); + + // ServiceTracker agentTracker = new ServiceTracker(bundleContext, + // "org.argeo.slc.execution.SlcAgentCli", null); + // agentTracker.open(); + // final Object agentCli = agentTracker.waitForService(30 * 1000); + // if (agentCli == null) + // throw new RuntimeException("Cannot find SLC agent CLI"); + + long duration = System.currentTimeMillis() - begin; + System.out.println("Initialized in " + (duration / 1000) + "s " + + (duration % 1000) + "ms"); + // Run as a privileged action + Subject.doAs(Subject.getSubject(AccessController.getContext()), + new PrivilegedAction() { + + public String run() { + try { + Class[] parameterTypes = { String[].class }; + Method method = agentCli.getClass().getMethod( + "process", parameterTypes); + Object[] methodArgs = { args }; + Object ret = method + .invoke(agentCli, methodArgs); + return ret.toString(); + } catch (Exception e) { + throw new RuntimeException("Cannot run " + + Arrays.toString(args) + " on " + + agentCli, e); + } + } + + }); + + // Shutdown OSGi runtime + framework.stop(); + framework.waitForStop(60 * 1000); + + System.exit(0); } catch (Exception e) { - System.err.println("Unexpected exception when bootstrapping."); e.printStackTrace(); - badExit(); - } - - // Initializes logging and log arguments - initLogging(properties); - if (log.isDebugEnabled()) { - log.debug("Mode: " + mode); - if (runtimeStr != null) - log.debug("Runtime: " + runtimeStr); - log.debug("User properties: " + properties); - if (script != null) - log.debug("Script: " + script); - if (targets != null) - log.debug("Targets: " + targets); - } - - // Execution - if (mode.equals(Mode.single)) { - try { - // DefaultSlcRuntime runtime = new DefaultSlcRuntime(); - // FIXME: inject this more cleanly - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - Class clss = cl.loadClass("org.argeo.slc.ant.AntSlcRuntime"); - SlcRuntime runtime = (SlcRuntime) clss - .newInstance(); - runtime.executeScript(runtimeStr, script, targets, properties, - null, null); - // System.exit(0); - } catch (Exception e) { - log.error("SLC client terminated with an error: ", e); - System.exit(1); + System.exit(1); + } finally { + if (isTransient && dataDir != null && dataDir.exists()) { + // TODO clean up transient data dir } - } - } - public static void printUsage() { - new HelpFormatter().printHelp(commandName, options, true); - } - - private static String listModeValues() { - StringBuffer buf = new StringBuffer(""); - for (Mode mode : Mode.values()) { - buf.append(mode).append(", "); } - String str = buf.toString(); - // unsafe, but there will be at least one value in the enum - return str.substring(0, str.length() - 2); } - protected static void addProperty(Properties properties, String property) { - int eqIndex = property.indexOf('='); - if (eqIndex == 0) - throw new SlcException("Badly formatted property " + property); - - if (eqIndex > 0) { - String key = property.substring(0, eqIndex); - String value = property.substring(eqIndex + 1); - properties.setProperty(key, value); - - } else { - properties.setProperty(property, "true"); - } + public static void main(String[] args) { + new SlcMain(args).run(); } - protected static void loadPropertyFile(Properties properties, - String propertyFile) { - FileInputStream in = null; - try { - in = new FileInputStream(propertyFile); - properties.load(in); - } catch (Exception e) { - throw new SlcException("Could not load proeprty file " - + propertyFile); - } finally { - IOUtils.closeQuietly(in); - } + protected static void info(Object msg) { + System.out.println(msg); } - private static void initLogging(Properties userProperties) { - System.setProperty("log4j.defaultInitOverride", "true"); - - // Add log4j user properties to System properties - for (Object obj : userProperties.keySet()) { - String key = obj.toString(); - if (key.startsWith("log4j.")) { - System.setProperty(key, userProperties.getProperty(key)); - } - } - Log4jUtils.initLog4j(System.getProperty("log4j.configuration", - "classpath:" + BOOTSTRAP_LOG4J_CONFIG)); - log = LogFactory.getLog(SlcMain.class); - + protected static void debug(Object msg) { + System.out.println(msg); } - private static void badExit() { - printUsage(); - System.exit(1); - } }