]> git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.detached.launcher/src/main/java/org/argeo/slc/detached/launcher/Main.java
1319750885eab2ba0e658670d640ff47114c1aea
[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.home=" + System.getProperty("java.home"));
83 info("java.class.path=" + System.getProperty("java.class.path"));
84
85 File baseDir = new File(System.getProperty("user.dir"))
86 .getCanonicalFile();
87 String equinoxConfigurationPath = baseDir.getPath() + File.separator
88 + "slc-detached" + File.separator + "equinoxConfiguration";
89
90 String equinoxArgsLineDefault = "-console -noExit -clean -debug -configuration "
91 + equinoxConfigurationPath;
92 String equinoxArgsLine = config.getProperty(PROP_SLC_OSGI_EQUINOX_ARGS,
93 equinoxArgsLineDefault);
94 // String[] equinoxArgs = { "-console", "-noExit", "-clean", "-debug",
95 // "-configuration", equinoxConfigurationPath };
96 String[] equinoxArgs = equinoxArgsLine.split(" ");
97
98 BundleContext context = EclipseStarter.startup(equinoxArgs, null);
99
100 List installBundleNames = new ArrayList();
101
102 // Load from class path (dev environment, maven)
103 if (config.getProperty(PROP_SLC_OSGI_SCAN_CLASSPATH, "false").equals(
104 "true")) {
105 StringTokenizer st = new StringTokenizer(System
106 .getProperty("java.class.path"), File.pathSeparator);
107 while (st.hasMoreTokens()) {
108 try {
109 String path = st.nextToken();
110 String url = "reference:file:"
111 + new File(path).getCanonicalPath();
112 Bundle bundle = context.installBundle(url);
113 if (bundle.getSymbolicName() != null)
114 installBundleNames.add(bundle.getSymbolicName());
115 info("Installed from classpath " + url);
116 } catch (Exception e) {
117 bundleInstallWarn(e.getMessage());
118 }
119 }
120 }
121
122 // Load from dev bundles
123 Map devBundleUrls = getDevBundleUrls(config);
124 Iterator devBundles = devBundleUrls.keySet().iterator();
125 while (devBundles.hasNext()) {
126 try {
127 String bundleName = (String) devBundles.next();
128 String url = (String) devBundleUrls.get(bundleName);
129 Bundle bundle = context.installBundle(url);
130 installBundleNames.add(bundle.getSymbolicName());
131 info("Installed as dev bundle " + url);
132 } catch (Exception e) {
133 bundleInstallWarn(e.getMessage());
134 }
135 }
136
137 // Load from distribution
138 String slcHome = config.getProperty(PROP_SLC_HOME);
139 if (slcHome != null) {
140 File libDir = new File(slcHome + File.separator + "lib");
141 File[] bundleFiles = libDir.listFiles();
142 for (int i = 0; i < bundleFiles.length; i++) {
143 try {
144 String url = "reference:file:"
145 + bundleFiles[i].getCanonicalPath();
146 Bundle bundle = context.installBundle(url);
147 installBundleNames.add(bundle.getSymbolicName());
148 info("INFO: Installed from SLC home " + url);
149 } catch (Exception e) {
150 bundleInstallWarn(e.getMessage());
151 }
152
153 }
154 }
155
156 // Start bundles
157 String bundleStart = config.getProperty(PROP_SLC_OSGI_START,
158 "org.springframework.osgi.extender,org.argeo.slc.detached");
159
160 if (bundleStart.trim().equals("*")) {
161 for (int i = 0; i < installBundleNames.size(); i++) {
162 Object obj = installBundleNames.get(i);
163 if (obj != null) {
164 String bundleSymbolicName = obj.toString();
165 try {
166 startBundle(context, bundleSymbolicName);
167 } catch (Exception e) {
168 bundleInstallWarn("Cannot start " + bundleSymbolicName
169 + ": " + e.getMessage());
170 }
171 }
172 }
173 } else {
174 StringTokenizer stBundleStart = new StringTokenizer(bundleStart,
175 ",");
176 while (stBundleStart.hasMoreTokens()) {
177 String bundleSymbolicName = stBundleStart.nextToken();
178 startBundle(context, bundleSymbolicName);
179 }
180 }
181 }
182
183 private static Map getDevBundleUrls(Properties config) {
184 Map bundles = new Hashtable();
185 Iterator keys = config.keySet().iterator();
186 while (keys.hasNext()) {
187 String key = (String) keys.next();
188 if (key.startsWith(DEV_BUNDLE_PREFIX)) {
189 String bundle = key.substring(DEV_BUNDLE_PREFIX.length());
190 String path = config.getProperty(key);
191 bundles.put(bundle, path);
192 }
193 }
194 return bundles;
195 }
196
197 private static void startBundle(BundleContext bundleContext,
198 String symbolicName) throws BundleException {
199 info("Starting bundle " + symbolicName + "...");
200 Bundle bundle = findBundleBySymbolicName(bundleContext, symbolicName);
201 if (bundle != null)
202 bundle.start();
203 else
204 throw new RuntimeException("Bundle " + symbolicName + " not found");
205 info("Started " + symbolicName);
206 }
207
208 /** WARNING: return the first one found! */
209 private static Bundle findBundleBySymbolicName(BundleContext bundleContext,
210 String symbolicName) {
211 Bundle[] bundles = bundleContext.getBundles();
212 for (int i = 0; i < bundles.length; i++) {
213 Bundle bundle = bundles[i];
214 String bundleSymbolicName = bundle.getSymbolicName();
215 if (bundleSymbolicName != null) {
216 // throw new RuntimeException("Bundle " + bundle.getBundleId()
217 // + " (" + bundle.getLocation()
218 // + ") has no symbolic name.");
219
220 if (bundleSymbolicName.equals(symbolicName)) {
221 return bundle;
222 }
223 }
224 }
225 return null;
226 }
227
228 public static void startApp(Properties config) throws Exception {
229 String className = config.getProperty("slc.detached.appclass");
230 String[] uiArgs = readArgumentsFromLine(config.getProperty(
231 "slc.detached.appargs", ""));
232
233 if (className == null) {
234 info("No slc.detached.appclass property define: does not try to launch an app from the standard classpath.");
235 } else {
236 // Launch main method using reflection
237 Class clss = Class.forName(className);
238 Class[] mainArgsClasses = new Class[] { uiArgs.getClass() };
239 Object[] mainArgs = { uiArgs };
240 Method mainMethod = clss.getMethod("main", mainArgsClasses);
241 mainMethod.invoke(null, mainArgs);
242 }
243 }
244
245 /* UTILITIES */
246
247 /**
248 * Transform a line into an array of arguments, taking "" as single
249 * arguments. (nested \" are not supported)
250 */
251 private static String[] readArgumentsFromLine(String lineOrig) {
252
253 String line = lineOrig.trim();// remove trailing spaces
254 // System.out.println("line=" + line);
255 List args = new Vector();
256 StringBuffer curr = new StringBuffer("");
257 boolean inQuote = false;
258 char[] arr = line.toCharArray();
259 for (int i = 0; i < arr.length; i++) {
260 char c = arr[i];
261 switch (c) {
262 case '\"':
263 inQuote = !inQuote;
264 break;
265 case ' ':
266 if (!inQuote) {// otherwise, no break: goes to default
267 if (curr.length() > 0) {
268 args.add(curr.toString());
269 curr = new StringBuffer("");
270 }
271 break;
272 }
273 default:
274 curr.append(c);
275 break;
276 }
277 }
278
279 // Add last arg
280 if (curr.length() > 0) {
281 args.add(curr.toString());
282 curr = null;
283 }
284
285 String[] res = new String[args.size()];
286 for (int i = 0; i < args.size(); i++) {
287 res[i] = args.get(i).toString();
288 // System.out.println("res[i]=" + res[i]);
289 }
290 return res;
291 }
292
293 private static void info(Object obj) {
294 System.out.println("[INFO] " + obj);
295 }
296
297 private static void bundleInstallWarn(Object obj) {
298 System.err.println("[WARN] " + obj);
299 //Thread.dumpStack();
300 }
301 }