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