]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/OsgiBoot.java
fdcb77df07abfb513572dce2165b32e55886414c
[gpl/argeo-slc.git] / runtime / org.argeo.slc.osgiboot / src / main / java / org / argeo / slc / osgiboot / OsgiBoot.java
1 package org.argeo.slc.osgiboot;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.StringTokenizer;
10
11 import org.argeo.slc.osgiboot.internal.springutil.AntPathMatcher;
12 import org.argeo.slc.osgiboot.internal.springutil.PathMatcher;
13 import org.argeo.slc.osgiboot.internal.springutil.SystemPropertyUtils;
14 import org.osgi.framework.Bundle;
15 import org.osgi.framework.BundleContext;
16 import org.osgi.framework.BundleException;
17
18 public class OsgiBoot {
19 public final static String PROP_SLC_OSGI_START = "slc.osgi.start";
20 public final static String PROP_SLC_OSGI_BUNDLES = "slc.osgi.bundles";
21 public final static String PROP_SLC_OSGI_LOCATIONS = "slc.osgi.locations";
22 public final static String PROP_SLC_OSGI_BASE_URL = "slc.osgi.baseUrl";
23 public final static String PROP_SLC_OSGIBOOT_DEBUG = "slc.osgiboot.debug";
24
25 public final static String DEFAULT_BASE_URL = "reference:file:";
26
27 private Boolean debug = Boolean.parseBoolean(System.getProperty(
28 PROP_SLC_OSGIBOOT_DEBUG, "false"));
29
30 private final BundleContext bundleContext;
31
32 public OsgiBoot(BundleContext bundleContext) {
33 this.bundleContext = bundleContext;
34 }
35
36 public void installUrls(List<String> urls) {
37 Map<String, Bundle> installedBundles = getInstalledBundles();
38 for (String url : urls) {
39 try {
40 if (installedBundles.containsKey(url)) {
41 Bundle bundle = installedBundles.get(url);
42 // bundle.update();
43 if (debug)
44 debug("Bundle " + bundle.getSymbolicName()
45 + " already installed from " + url);
46 } else {
47 Bundle bundle = bundleContext.installBundle(url);
48 if (debug)
49 debug("Installed bundle " + bundle.getSymbolicName()
50 + " from " + url);
51 }
52 } catch (BundleException e) {
53 warn("Could not install bundle from " + url + ": "
54 + e.getMessage());
55 }
56 }
57
58 }
59
60 public void startBundles() throws Exception {
61 String bundlesToStart = getProperty(PROP_SLC_OSGI_START);
62 startBundles(bundlesToStart);
63 }
64
65 public void startBundles(String bundlesToStart) throws Exception {
66 if (bundlesToStart == null)
67 return;
68
69 StringTokenizer st = new StringTokenizer(bundlesToStart, ",");
70 Map<String, Bundle> bundles = getBundles();
71 while (st.hasMoreTokens()) {
72 String name = st.nextToken().trim();
73 Bundle bundle = bundles.get(name);
74 if (bundle != null)
75 try {
76 bundle.start();
77 } catch (Exception e) {
78 warn("Bundle " + name + " cannot be started: "
79 + e.getMessage());
80 }
81 else
82 warn("Bundle " + name + " not installed.");
83
84 }
85 }
86
87 /** Key is location */
88 public Map<String, Bundle> getInstalledBundles() {
89 Map<String, Bundle> installedBundles = new HashMap<String, Bundle>();
90
91 for (Bundle bundle : bundleContext.getBundles()) {
92 installedBundles.put(bundle.getLocation(), bundle);
93 }
94 return installedBundles;
95 }
96
97 /** Key is symbolic name */
98 public Map<String, Bundle> getBundles() {
99 Map<String, Bundle> installedBundles = new HashMap<String, Bundle>();
100 for (Bundle bundle : bundleContext.getBundles())
101 installedBundles.put(bundle.getSymbolicName(), bundle);
102 return installedBundles;
103 }
104
105 public List<String> getLocationsUrls() {
106 String baseUrl = getProperty(PROP_SLC_OSGI_BASE_URL, DEFAULT_BASE_URL);
107 String bundleLocations = getProperty(PROP_SLC_OSGI_LOCATIONS);
108 return getLocationsUrls(baseUrl, bundleLocations);
109 }
110
111 public List<String> getLocationsUrls(String baseUrl, String bundleLocations) {
112 List<String> urls = new ArrayList<String>();
113
114 if (bundleLocations == null)
115 return urls;
116 bundleLocations = SystemPropertyUtils
117 .resolvePlaceholders(bundleLocations);
118
119 StringTokenizer st = new StringTokenizer(bundleLocations,
120 File.pathSeparator);
121 while (st.hasMoreTokens()) {
122 urls.add(baseUrl + st.nextToken().trim());
123 }
124 return urls;
125 }
126
127 public List<String> getBundlesUrls() {
128 String baseUrl = getProperty(PROP_SLC_OSGI_BASE_URL, DEFAULT_BASE_URL);
129 String bundlePatterns = getProperty(PROP_SLC_OSGI_BUNDLES);
130 return getBundlesUrls(baseUrl, bundlePatterns);
131 }
132
133 public List<String> getBundlesUrls(String baseUrl, String bundlePatterns) {
134 List<String> urls = new ArrayList<String>();
135
136 List<BundlesSet> bundlesSets = new ArrayList<BundlesSet>();
137 if (bundlePatterns == null)
138 return urls;
139 // TODO: resolve placeholders
140 info(PROP_SLC_OSGI_BUNDLES + "=" + bundlePatterns);
141
142 StringTokenizer st = new StringTokenizer(bundlePatterns, ",");
143 while (st.hasMoreTokens()) {
144 bundlesSets.add(new BundlesSet(st.nextToken()));
145 }
146
147 List<String> included = new ArrayList<String>();
148 PathMatcher matcher = new AntPathMatcher();
149 for (BundlesSet bundlesSet : bundlesSets)
150 for (String pattern : bundlesSet.getIncludes())
151 match(matcher, included, bundlesSet.getDir(), null, pattern);
152
153 List<String> excluded = new ArrayList<String>();
154 for (BundlesSet bundlesSet : bundlesSets)
155 for (String pattern : bundlesSet.getExcludes())
156 match(matcher, excluded, bundlesSet.getDir(), null, pattern);
157
158 for (String fullPath : included) {
159 if (!excluded.contains(fullPath))
160 urls.add(baseUrl + fullPath);
161 }
162
163 return urls;
164 }
165
166 protected void match(PathMatcher matcher, List<String> matched,
167 String base, String currentPath, String pattern) {
168 if (currentPath == null) {
169 // Init
170 File baseDir = new File(base.replace('/', File.separatorChar));
171 File[] files = baseDir.listFiles();
172
173 if (files == null) {
174 warn("Base dir " + baseDir + " has no children, exists="
175 + baseDir.exists() + ", isDirectory="
176 + baseDir.isDirectory());
177 return;
178 }
179
180 for (File file : files)
181 match(matcher, matched, base, file.getName(), pattern);
182 } else {
183 String fullPath = base + '/' + currentPath;
184 if (matched.contains(fullPath))
185 return;// don't try deeper if already matched
186
187 boolean ok = matcher.match(pattern, currentPath);
188 if (debug)
189 debug(currentPath + " " + (ok ? "" : " not ")
190 + " matched with " + pattern);
191 if (ok) {
192 matched.add(fullPath);
193 return;
194 } else {
195 String newFullPath = (base + '/' + currentPath).replace('/',
196 File.separatorChar);
197 File[] files = new File(newFullPath).listFiles();
198 if (files != null) {
199 for (File file : files)
200 if (file.isDirectory()) {
201 String newCurrentPath = currentPath + '/'
202 + file.getName();
203 if (matcher.matchStart(pattern, newCurrentPath)) {
204 // recurse only if start matches
205 match(matcher, matched, base, newCurrentPath,
206 pattern);
207 } else {
208 if (debug)
209 debug(newCurrentPath
210 + " does not start match with "
211 + pattern);
212
213 }
214 }
215 } else {
216 warn("Not a directory: " + newFullPath);
217 }
218 }
219 }
220 }
221
222 protected void info(Object obj) {
223 System.out.println("# INFO " + obj);
224 }
225
226 protected void debug(Object obj) {
227 if (debug)
228 System.out.println("# DBUG " + obj);
229 }
230
231 protected void warn(Object obj) {
232 System.out.println("# WARN " + obj);
233 // Because of a weird bug under Windows when starting it in a forked VM
234 // if (System.getProperty("os.name").contains("Windows"))
235 // System.out.println("# WARN " + obj);
236 // else
237 // System.err.println("# WARN " + obj);
238 }
239
240 protected String getProperty(String name, String defaultValue) {
241 final String value;
242 if (defaultValue != null)
243 value = System.getProperty(name, defaultValue);
244 else
245 value = System.getProperty(name);
246
247 if (value == null || value.equals(""))
248 return null;
249 else
250 return value;
251 }
252
253 protected String getProperty(String name) {
254 return getProperty(name, null);
255 }
256
257 public Boolean getDebug() {
258 return debug;
259 }
260
261 public void setDebug(Boolean debug) {
262 this.debug = debug;
263 }
264
265 public BundleContext getBundleContext() {
266 return bundleContext;
267 }
268
269 private class BundlesSet {
270 private String baseUrl = "reference:file";// not used yet
271 private final String dir;
272 private List<String> includes = new ArrayList<String>();
273 private List<String> excludes = new ArrayList<String>();
274
275 public BundlesSet(String def) {
276 StringTokenizer st = new StringTokenizer(def, ";");
277
278 if (!st.hasMoreTokens())
279 throw new RuntimeException("Base dir not defined.");
280 try {
281 String dirPath = st.nextToken();
282 dir = new File(dirPath.replace('/', File.separatorChar))
283 .getCanonicalPath();
284 if (debug)
285 debug("Base dir: " + dir);
286 } catch (IOException e) {
287 throw new RuntimeException("Cannot convert to absolute path", e);
288 }
289
290 while (st.hasMoreTokens()) {
291 String tk = st.nextToken();
292 StringTokenizer stEq = new StringTokenizer(tk, "=");
293 String type = stEq.nextToken();
294 String pattern = stEq.nextToken();
295 if ("in".equals(type) || "include".equals(type)) {
296 includes.add(pattern);
297 } else if ("ex".equals(type) || "exclude".equals(type)) {
298 excludes.add(pattern);
299 } else if ("baseUrl".equals(type)) {
300 baseUrl = pattern;
301 } else {
302 System.err.println("Unkown bundles pattern type " + type);
303 }
304 }
305 }
306
307 public String getDir() {
308 return dir;
309 }
310
311 public List<String> getIncludes() {
312 return includes;
313 }
314
315 public List<String> getExcludes() {
316 return excludes;
317 }
318
319 public String getBaseUrl() {
320 return baseUrl;
321 }
322
323 }
324
325 }