2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org
.argeo
.slc
.detached
.launcher
;
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
;
28 import java
.util
.Properties
;
29 import java
.util
.StringTokenizer
;
30 import java
.util
.TreeMap
;
31 import java
.util
.Vector
;
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
;
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";
45 private final static String DEV_BUNDLE_PREFIX
= "slc.osgi.devbundle.";
47 public static void main(String
[] args
) {
48 info("Argeo SLC Detached launcher starting...");
51 String propertyPath
= System
.getProperty("slc.detached.properties",
52 "slc-detached.properties");
53 Properties config
= prepareConfig(propertyPath
);
55 // Start app (in main class loader)
58 // Start OSGi framework
60 info("Argeo SLC Detached launcher started.");
61 } catch (Exception e
) {
67 protected static Properties
prepareConfig(String propertyFilePath
)
70 Properties config
= new Properties();
71 InputStream in
= null;
73 File file
= new File(propertyFilePath
);
75 in
= new FileInputStream(propertyFilePath
);
84 String slcHome
= System
.getProperty(Main
.PROP_SLC_HOME
);
85 if (slcHome
== null) {
86 slcHome
= config
.getProperty(Main
.PROP_SLC_HOME
);
88 if (slcHome
!= null) {
89 slcHome
= new File(slcHome
).getCanonicalPath();
90 System
.setProperty(Main
.PROP_SLC_HOME
, slcHome
);
93 // System properties have priority.
94 config
.putAll(System
.getProperties());
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
);
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"));
112 File baseDir
= new File(System
.getProperty("user.dir"))
114 String equinoxConfigurationPath
= baseDir
.getPath() + File
.separator
115 + "slc-detached" + File
.separator
+ "equinoxConfiguration";
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(" ");
125 BundleContext context
= EclipseStarter
.startup(equinoxArgs
, null);
127 List installBundleNames
= new ArrayList();
129 // Load from class path (dev environment, maven)
130 if (config
.getProperty(PROP_SLC_OSGI_SCAN_CLASSPATH
, "false").equals(
132 StringTokenizer st
= new StringTokenizer(System
133 .getProperty("java.class.path"), File
.pathSeparator
);
134 while (st
.hasMoreTokens()) {
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());
149 // Load from dev bundles
150 Map devBundleUrls
= getDevBundleUrls(config
);
151 Iterator devBundles
= devBundleUrls
.keySet().iterator();
152 while (devBundles
.hasNext()) {
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());
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
++) {
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());
184 String bundleStart
= config
.getProperty(PROP_SLC_OSGI_START
,
185 "org.springframework.osgi.extender,org.argeo.slc.detached");
187 if (bundleStart
.trim().equals("*")) {
188 for (int i
= 0; i
< installBundleNames
.size(); i
++) {
189 Object obj
= installBundleNames
.get(i
);
191 String bundleSymbolicName
= obj
.toString();
193 startBundle(context
, bundleSymbolicName
);
194 } catch (Exception e
) {
195 bundleInstallWarn("Cannot start " + bundleSymbolicName
196 + ": " + e
.getMessage());
201 StringTokenizer stBundleStart
= new StringTokenizer(bundleStart
,
203 while (stBundleStart
.hasMoreTokens()) {
204 String bundleSymbolicName
= stBundleStart
.nextToken();
205 startBundle(context
, bundleSymbolicName
);
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
);
224 private static void startBundle(BundleContext bundleContext
,
225 String symbolicName
) throws BundleException
{
226 // info("Starting bundle " + symbolicName + "...");
227 Bundle bundle
= findBundleBySymbolicName(bundleContext
, symbolicName
);
231 throw new RuntimeException("Bundle " + symbolicName
+ " not found");
232 info("Started " + symbolicName
);
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.");
247 if (bundleSymbolicName
.equals(symbolicName
)) {
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", ""));
260 if (className
== null) {
261 info("No slc.detached.appclass property define: does not try to launch an app from the standard classpath.");
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
);
275 * Transform a line into an array of arguments, taking "" as single
276 * arguments. (nested \" are not supported)
278 private static String
[] readArgumentsFromLine(String lineOrig
) {
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
++) {
293 if (!inQuote
) {// otherwise, no break: goes to default
294 if (curr
.length() > 0) {
295 args
.add(curr
.toString());
296 curr
= new StringBuffer("");
307 if (curr
.length() > 0) {
308 args
.add(curr
.toString());
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]);
320 private static void info(Object obj
) {
321 System
.out
.println("[INFO] " + obj
);
324 private static void bundleInstallWarn(Object obj
) {
325 System
.err
.println("[WARN] " + obj
);
326 // Thread.dumpStack();