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