]> git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.detached.launcher/src/main/java/org/argeo/slc/detached/launcher/Main.java
Improve execution specs
[gpl/argeo-slc.git] / org.argeo.slc.detached.launcher / src / main / java / org / argeo / slc / detached / launcher / Main.java
1 package org.argeo.slc.detached.launcher;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.InputStream;
6 import java.lang.reflect.Method;
7 import java.util.ArrayList;
8 import java.util.Hashtable;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Properties;
13 import java.util.StringTokenizer;
14 import java.util.Vector;
15
16 import org.eclipse.core.runtime.adaptor.EclipseStarter;
17 import org.osgi.framework.Bundle;
18 import org.osgi.framework.BundleContext;
19 import org.osgi.framework.BundleException;
20
21 public class Main {
22 public final static String PROP_SLC_HOME = "slc.home";
23 public final static String PROP_SLC_OSGI_START = "slc.osgi.start";
24 public final static String PROP_SLC_OSGI_SCAN_CLASSPATH = "slc.osgi.scanClasspath";
25 public final static String PROP_SLC_OSGI_EQUINOX_ARGS = "slc.osgi.equinox.args";
26
27 private final static String DEV_BUNDLE_PREFIX = "slc.osgi.devbundle.";
28
29 public static void main(String[] args) {
30 info("Argeo SLC Detached launcher starting...");
31 try {
32 // Load properties
33 String propertyPath = "slc-detached.properties";
34 Properties config = prepareConfig(propertyPath);
35
36 // Start app (in main class loader)
37 startApp(config);
38
39 // Start OSGi framework
40 try {
41 startEquinox(config);
42 } catch (Exception e) {
43 // TODO Auto-generated catch block
44 e.printStackTrace();
45 }
46 info("Argeo SLC Detached launcher started.");
47 } catch (Exception e) {
48 e.printStackTrace();
49 System.exit(-1);
50 }
51 }
52
53 protected static Properties prepareConfig(String propertyFilePath)
54 throws Exception {
55 // Format slc.home
56 String slcHome = System.getProperty(PROP_SLC_HOME);
57 if (slcHome != null) {
58 slcHome = new File(slcHome).getCanonicalPath();
59 System.setProperty(PROP_SLC_HOME, slcHome);
60 }
61
62 // Load config
63 Properties config = new Properties();
64 InputStream in = null;
65 try {
66 File file = new File(propertyFilePath);
67 if (file.exists()) {
68 in = new FileInputStream(propertyFilePath);
69 config.load(in);
70 }
71 } finally {
72 if (in != null)
73 in.close();
74 }
75
76 // System properties have priority.
77 config.putAll(System.getProperties());
78 return config;
79 }
80
81 public static void startEquinox(Properties config) throws Exception {
82 info("java.class.path=" + System.getProperty("java.class.path"));
83
84 File baseDir = new File(System.getProperty("user.dir"))
85 .getCanonicalFile();
86 String equinoxConfigurationPath = baseDir.getPath() + File.separator
87 + "slc-detached" + File.separator + "equinoxConfiguration";
88
89 String equinoxArgsLineDefault = "-console -noExit -clean -debug -configuration "
90 + equinoxConfigurationPath;
91 String equinoxArgsLine = config.getProperty(PROP_SLC_OSGI_EQUINOX_ARGS,
92 equinoxArgsLineDefault);
93 // String[] equinoxArgs = { "-console", "-noExit", "-clean", "-debug",
94 // "-configuration", equinoxConfigurationPath };
95 String[] equinoxArgs = equinoxArgsLine.split(" ");
96
97 BundleContext context = EclipseStarter.startup(equinoxArgs, null);
98
99 List installBundleNames = new ArrayList();
100
101 // Load from class path (dev environment, maven)
102 if (config.getProperty(PROP_SLC_OSGI_SCAN_CLASSPATH, "false").equals(
103 "true")) {
104 StringTokenizer st = new StringTokenizer(System
105 .getProperty("java.class.path"), File.pathSeparator);
106 while (st.hasMoreTokens()) {
107 try {
108 String path = st.nextToken();
109 String url = "reference:file:"
110 + new File(path).getCanonicalPath();
111 Bundle bundle = context.installBundle(url);
112 installBundleNames.add(bundle.getSymbolicName());
113 info("Installed from classpath " + url);
114 } catch (Exception e) {
115 bundleInstallWarn(e.getMessage());
116 }
117 }
118 }
119
120 // Load from dev bundles
121 Map devBundleUrls = getDevBundleUrls(config);
122 Iterator devBundles = devBundleUrls.keySet().iterator();
123 while (devBundles.hasNext()) {
124 try {
125 String bundleName = (String) devBundles.next();
126 String url = (String) devBundleUrls.get(bundleName);
127 Bundle bundle = context.installBundle(url);
128 installBundleNames.add(bundle.getSymbolicName());
129 info("Installed as dev bundle " + url);
130 } catch (Exception e) {
131 bundleInstallWarn(e.getMessage());
132 }
133 }
134
135 // Load from distribution
136 String slcHome = config.getProperty(PROP_SLC_HOME);
137 if (slcHome != null) {
138 File libDir = new File(slcHome + File.separator + "lib");
139 File[] bundleFiles = libDir.listFiles();
140 for (int i = 0; i < bundleFiles.length; i++) {
141 try {
142 String url = "reference:file:"
143 + bundleFiles[i].getCanonicalPath();
144 Bundle bundle = context.installBundle(url);
145 installBundleNames.add(bundle.getSymbolicName());
146 info("INFO: Installed from SLC home " + url);
147 } catch (Exception e) {
148 bundleInstallWarn(e.getMessage());
149 }
150
151 }
152 }
153
154 // Start bundles
155 String bundleStart = config.getProperty(PROP_SLC_OSGI_START,
156 "org.springframework.osgi.extender,org.argeo.slc.detached");
157
158 if (bundleStart.trim().equals("*")) {
159 for (int i = 0; i < installBundleNames.size(); i++) {
160 String bundleSymbolicName = installBundleNames.get(i)
161 .toString();
162 try {
163 startBundle(context, bundleSymbolicName);
164 } catch (Exception e) {
165 bundleInstallWarn(e.getMessage());
166 }
167 }
168 } else {
169 StringTokenizer stBundleStart = new StringTokenizer(bundleStart,
170 ",");
171 while (stBundleStart.hasMoreTokens()) {
172 String bundleSymbolicName = stBundleStart.nextToken();
173 startBundle(context, bundleSymbolicName);
174 }
175 }
176 }
177
178 private static Map getDevBundleUrls(Properties config) {
179 Map bundles = new Hashtable();
180 Iterator keys = config.keySet().iterator();
181 while (keys.hasNext()) {
182 String key = (String) keys.next();
183 if (key.startsWith(DEV_BUNDLE_PREFIX)) {
184 String bundle = key.substring(DEV_BUNDLE_PREFIX.length());
185 String path = config.getProperty(key);
186 bundles.put(bundle, path);
187 }
188 }
189 return bundles;
190 }
191
192 private static void startBundle(BundleContext bundleContext,
193 String symbolicName) throws BundleException {
194 info("Starting bundle " + symbolicName + "...");
195 Bundle bundle = findBundleBySymbolicName(bundleContext, symbolicName);
196 if (bundle != null)
197 bundle.start();
198 else
199 throw new RuntimeException("Bundle " + symbolicName + " not found");
200 info("Started " + symbolicName);
201 }
202
203 /** WARNING: return the first one found! */
204 private static Bundle findBundleBySymbolicName(BundleContext bundleContext,
205 String symbolicName) {
206 Bundle[] bundles = bundleContext.getBundles();
207 for (int i = 0; i < bundles.length; i++) {
208 Bundle bundle = bundles[i];
209 String bundleSymbolicName = bundle.getSymbolicName();
210 if (bundleSymbolicName == null)
211 throw new RuntimeException("Bundle " + bundle.getBundleId()
212 + " (" + bundle.getLocation()
213 + ") has no symbolic name.");
214
215 if (bundleSymbolicName.equals(symbolicName)) {
216 return bundle;
217 }
218 }
219 return null;
220 }
221
222 public static void startApp(Properties config) throws Exception {
223 String className = config.getProperty("slc.detached.appclass");
224 String[] uiArgs = readArgumentsFromLine(config.getProperty(
225 "slc.detached.appargs", ""));
226
227 if (className == null) {
228 info("No slc.detached.appclass property define: does not try to launch an app from the standard classpath.");
229 } else {
230 // Launch main method using reflection
231 Class clss = Class.forName(className);
232 Class[] mainArgsClasses = new Class[] { uiArgs.getClass() };
233 Object[] mainArgs = { uiArgs };
234 Method mainMethod = clss.getMethod("main", mainArgsClasses);
235 mainMethod.invoke(null, mainArgs);
236 }
237 }
238
239 /* UTILITIES */
240
241 /**
242 * Transform a line into an array of arguments, taking "" as single
243 * arguments. (nested \" are not supported)
244 */
245 private static String[] readArgumentsFromLine(String lineOrig) {
246
247 String line = lineOrig.trim();// remove trailing spaces
248 // System.out.println("line=" + line);
249 List args = new Vector();
250 StringBuffer curr = new StringBuffer("");
251 boolean inQuote = false;
252 char[] arr = line.toCharArray();
253 for (int i = 0; i < arr.length; i++) {
254 char c = arr[i];
255 switch (c) {
256 case '\"':
257 inQuote = !inQuote;
258 break;
259 case ' ':
260 if (!inQuote) {// otherwise, no break: goes to default
261 if (curr.length() > 0) {
262 args.add(curr.toString());
263 curr = new StringBuffer("");
264 }
265 break;
266 }
267 default:
268 curr.append(c);
269 break;
270 }
271 }
272
273 // Add last arg
274 if (curr.length() > 0) {
275 args.add(curr.toString());
276 curr = null;
277 }
278
279 String[] res = new String[args.size()];
280 for (int i = 0; i < args.size(); i++) {
281 res[i] = args.get(i).toString();
282 // System.out.println("res[i]=" + res[i]);
283 }
284 return res;
285 }
286
287 private static void info(Object obj) {
288 //System.out.println("[INFO] " + obj);
289 }
290
291 private static void bundleInstallWarn(Object obj) {
292 System.err.println("[WARN] " + obj);
293 }
294 }