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