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