]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.launcher/src/main/java/org/argeo/slc/cli/SlcMain.java
Introduce remote launching of agents
[gpl/argeo-slc.git] / runtime / org.argeo.slc.launcher / src / main / java / org / argeo / slc / cli / SlcMain.java
1 package org.argeo.slc.cli;
2
3 import java.io.FileInputStream;
4 import java.io.IOException;
5 import java.util.Properties;
6
7 import org.apache.commons.cli.CommandLine;
8 import org.apache.commons.cli.CommandLineParser;
9 import org.apache.commons.cli.GnuParser;
10 import org.apache.commons.cli.HelpFormatter;
11 import org.apache.commons.cli.Option;
12 import org.apache.commons.cli.OptionBuilder;
13 import org.apache.commons.cli.Options;
14 import org.apache.commons.cli.ParseException;
15 import org.apache.commons.io.IOUtils;
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.argeo.slc.SlcException;
19 import org.argeo.slc.logging.Log4jUtils;
20 import org.argeo.slc.runtime.SlcExecutionContext;
21 import org.argeo.slc.runtime.SlcRuntime;
22 import org.springframework.context.ConfigurableApplicationContext;
23 import org.springframework.context.support.ClassPathXmlApplicationContext;
24 import org.springframework.context.support.FileSystemXmlApplicationContext;
25
26 public class SlcMain {
27 public enum Mode {
28 single, agent
29 }
30
31 private static Log log = null;
32
33 private final static String BOOTSTRAP_LOG4J_CONFIG = "org/argeo/slc/cli/bootstrapLog4j.properties";
34 private final static String DEFAULT_AGENT_CONTEXT = "classpath:org/argeo/slc/cli/spring-agent-default.xml";
35
36 private final static Option modeOpt = OptionBuilder.withLongOpt("mode")
37 .withArgName("mode").hasArg().withDescription(
38 "SLC execution mode, one of: " + listModeValues()).create(
39 'm');
40
41 private final static Option propertyOpt = OptionBuilder.withLongOpt(
42 "property").withArgName("prop1=val1,prop2=val2").hasArgs()
43 .withValueSeparator(',').withDescription(
44 "use value for given property").create('p');
45
46 private final static Option propertiesOpt = OptionBuilder.withLongOpt(
47 "properties").withArgName("properties file").hasArgs()
48 .withValueSeparator(',').withDescription(
49 "load properties from file (-p has priority)").create('P');
50
51 private final static Option scriptOpt = OptionBuilder.withLongOpt("script")
52 .withArgName("script").hasArg().withDescription(
53 "SLC script to execute").create('s');
54
55 private final static Option targetsOpt = OptionBuilder.withLongOpt(
56 "targets").withArgName("targets").hasArg().withDescription(
57 "Targets to execute").create('t');
58
59 private final static Option runtimeOpt = OptionBuilder.withLongOpt(
60 "runtime").withArgName("runtime").hasArg().withDescription(
61 "Runtime to use, either a full path or relative to slc app conf dir: "
62 + "<conf dir>/runtime/<runtime>/.xml").create('r');
63
64 private final static Options options;
65
66 private final static String commandName = "slc";
67
68 static {
69 options = new Options();
70 options.addOption(modeOpt);
71 options.addOption(scriptOpt);
72 options.addOption(targetsOpt);
73 options.addOption(propertyOpt);
74 options.addOption(propertiesOpt);
75 options.addOption(runtimeOpt);
76 }
77
78 public static void main(String[] args) {
79 Mode mode = null;
80 Properties properties = new Properties();
81 String script = null;
82 String targets = null;
83 String runtimeStr = null;
84
85 try {
86
87 CommandLineParser clParser = new GnuParser();
88 CommandLine cl = clParser.parse(options, args);
89
90 // Mode
91 String modeStr = cl.getOptionValue(modeOpt.getOpt());
92 if (modeStr == null) {
93 mode = Mode.single;
94 } else {
95 try {
96 mode = Mode.valueOf(modeStr);
97 } catch (IllegalArgumentException e) {
98 throw new SlcException("Unrecognized mode '" + modeStr
99 + "'", e);
100 }
101 }
102
103 // Script
104 if (mode.equals(Mode.single)) {
105 if (!cl.hasOption(scriptOpt.getOpt()))
106 throw new SlcException("Mode " + Mode.single
107 + " requires option '" + scriptOpt.getLongOpt()
108 + "'");
109 script = cl.getOptionValue(scriptOpt.getOpt());
110
111 // Targets
112 if (cl.hasOption(targetsOpt.getOpt()))
113 targets = cl.getOptionValue(targetsOpt.getOpt());
114 }
115
116 // Properties
117 if (cl.hasOption(propertiesOpt.getOpt())) {
118 for (String propertyFile : cl.getOptionValues(propertiesOpt
119 .getOpt())) {
120 loadPropertyFile(properties, propertyFile);
121 }
122 }
123 if (cl.hasOption(propertyOpt.getOpt())) {
124 for (String property : cl.getOptionValues(propertyOpt.getOpt())) {
125 addProperty(properties, property);
126 }
127 }
128
129 // Runtime
130 if (cl.hasOption(runtimeOpt.getOpt())) {
131 runtimeStr = cl.getOptionValue(runtimeOpt.getOpt());
132 }
133 } catch (ParseException e) {
134 System.err.println("Problem with command line arguments. "
135 + e.getMessage());
136 badExit();
137 } catch (SlcException e) {
138 System.err.println(e.getMessage());
139 badExit();
140 } catch (Exception e) {
141 System.err.println("Unexpected exception when bootstrapping.");
142 e.printStackTrace();
143 badExit();
144 }
145
146 // Initializes logging and log arguments
147 initLogging(properties);
148 if (log.isDebugEnabled()) {
149 log.debug("Mode: " + mode);
150 if (runtimeStr != null)
151 log.debug("Runtime: " + runtimeStr);
152 log.debug("User properties: " + properties);
153 if (script != null)
154 log.debug("Script: " + script);
155 if (targets != null)
156 log.debug("Targets: " + targets);
157 }
158
159 // Execution
160 if (mode.equals(Mode.single)) {
161 try {
162 // DefaultSlcRuntime runtime = new DefaultSlcRuntime();
163 // FIXME: inject this more cleanly
164 ClassLoader cl = Thread.currentThread().getContextClassLoader();
165 Class clss = cl.loadClass("org.argeo.slc.ant.AntSlcRuntime");
166 SlcRuntime<? extends SlcExecutionContext> runtime = (SlcRuntime<? extends SlcExecutionContext>) clss
167 .newInstance();
168 runtime.executeScript(runtimeStr, script, targets, properties,
169 null, null);
170 // System.exit(0);
171 } catch (Exception e) {
172 log.error("SLC client terminated with an error: ", e);
173 System.exit(1);
174 }
175 }
176 // Agent
177 else if (mode.equals(Mode.agent)) {
178 final ConfigurableApplicationContext applicationContext;
179 if (runtimeStr == null) {
180 applicationContext = new ClassPathXmlApplicationContext(
181 DEFAULT_AGENT_CONTEXT);
182 } else {
183 applicationContext = new FileSystemXmlApplicationContext(
184 runtimeStr);
185 }
186 applicationContext.registerShutdownHook();
187 applicationContext.start();
188 log.info("SLC Agent context started.");
189 }
190 }
191
192 public static void printUsage() {
193 new HelpFormatter().printHelp(commandName, options, true);
194 }
195
196 private static String listModeValues() {
197 StringBuffer buf = new StringBuffer("");
198 for (Mode mode : Mode.values()) {
199 buf.append(mode).append(", ");
200 }
201 String str = buf.toString();
202 // unsafe, but there will be at least one value in the enum
203 return str.substring(0, str.length() - 2);
204 }
205
206 protected static void addProperty(Properties properties, String property) {
207 int eqIndex = property.indexOf('=');
208 if (eqIndex == 0)
209 throw new SlcException("Badly formatted property " + property);
210
211 if (eqIndex > 0) {
212 String key = property.substring(0, eqIndex);
213 String value = property.substring(eqIndex + 1);
214 properties.setProperty(key, value);
215
216 } else {
217 properties.setProperty(property, "true");
218 }
219 }
220
221 protected static void loadPropertyFile(Properties properties,
222 String propertyFile) {
223 FileInputStream in = null;
224 try {
225 in = new FileInputStream(propertyFile);
226 properties.load(in);
227 } catch (Exception e) {
228 throw new SlcException("Could not load proeprty file "
229 + propertyFile);
230 } finally {
231 IOUtils.closeQuietly(in);
232 }
233 }
234
235 private static void initLogging(Properties userProperties) {
236 System.setProperty("log4j.defaultInitOverride", "true");
237
238 // Add log4j user properties to System properties
239 for (Object obj : userProperties.keySet()) {
240 String key = obj.toString();
241 if (key.startsWith("log4j.")) {
242 System.setProperty(key, userProperties.getProperty(key));
243 }
244 }
245 Log4jUtils.initLog4j(System.getProperty("log4j.configuration",
246 "classpath:" + BOOTSTRAP_LOG4J_CONFIG));
247 log = LogFactory.getLog(SlcMain.class);
248
249 }
250
251 private static void badExit() {
252 printUsage();
253 System.exit(1);
254 }
255 }