1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.osgi.boot.utils.internal;
20
21 import java.util.ArrayList;
22 import java.util.LinkedHashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.StringTokenizer;
26
27 import org.osgi.framework.Bundle;
28 import org.osgi.framework.BundleActivator;
29 import org.osgi.framework.BundleContext;
30 import org.osgi.framework.InvalidSyntaxException;
31 import org.osgi.framework.ServiceEvent;
32 import org.osgi.framework.ServiceListener;
33 import org.osgi.framework.ServiceReference;
34 import org.osgi.service.packageadmin.PackageAdmin;
35 import org.osgi.service.startlevel.StartLevel;
36
37
38
39
40
41
42
43
44
45
46
47 public class PackageAdminServiceTracker implements ServiceListener
48 {
49 private BundleContext _context;
50
51 private List<BundleActivator> _activatedFragments = new ArrayList<BundleActivator>();
52
53 private boolean _fragmentsWereActivated = false;
54
55
56
57 private StartLevel _startLevel;
58
59 private int _maxStartLevel = 6;
60
61 public static PackageAdminServiceTracker INSTANCE = null;
62
63 public PackageAdminServiceTracker(BundleContext context)
64 {
65 INSTANCE = this;
66 _context = context;
67 if (!setup())
68 {
69 try
70 {
71 _context.addServiceListener(this, "(objectclass=" + PackageAdmin.class.getName() + ")");
72 }
73 catch (InvalidSyntaxException e)
74 {
75 e.printStackTrace();
76 }
77 }
78 }
79
80
81
82
83 private boolean setup()
84 {
85 ServiceReference sr = _context.getServiceReference(PackageAdmin.class.getName());
86 _fragmentsWereActivated = sr != null;
87 if (sr != null) invokeFragmentActivators(sr);
88
89 sr = _context.getServiceReference(StartLevel.class.getName());
90 if (sr != null)
91 {
92 _startLevel = (StartLevel) _context.getService(sr);
93 try
94 {
95 _maxStartLevel = Integer.parseInt(System.getProperty("osgi.startLevel", "6"));
96 }
97 catch (Exception e)
98 {
99
100 _maxStartLevel = 6;
101 }
102 }
103 return _fragmentsWereActivated;
104 }
105
106
107
108
109
110
111
112
113
114 public void serviceChanged(ServiceEvent event)
115 {
116 if (event.getType() == ServiceEvent.REGISTERED)
117 {
118 invokeFragmentActivators(event.getServiceReference());
119 }
120 }
121
122
123
124
125
126
127
128
129
130 public Bundle[] getFragments(Bundle bundle)
131 {
132 ServiceReference sr = _context.getServiceReference(PackageAdmin.class.getName());
133 if (sr == null)
134 {
135 return null;
136 }
137 PackageAdmin admin = (PackageAdmin) _context.getService(sr);
138 return admin.getFragments(bundle);
139 }
140
141
142
143
144
145
146
147
148
149
150 public Bundle[] getFragmentsAndRequiredBundles(Bundle bundle)
151 {
152 ServiceReference sr = _context.getServiceReference(PackageAdmin.class.getName());
153 if (sr == null)
154 {
155 return null;
156 }
157 PackageAdmin admin = (PackageAdmin) _context.getService(sr);
158 LinkedHashMap<String, Bundle> deps = new LinkedHashMap<String, Bundle>();
159 collectFragmentsAndRequiredBundles(bundle, admin, deps, false);
160 return deps.values().toArray(new Bundle[deps.size()]);
161 }
162
163
164
165
166
167
168
169
170
171
172 protected void collectFragmentsAndRequiredBundles(Bundle bundle, PackageAdmin admin, Map<String, Bundle> deps, boolean onlyReexport)
173 {
174 Bundle[] fragments = admin.getFragments(bundle);
175 if (fragments != null)
176 {
177
178
179
180 for (Bundle f : fragments)
181 {
182 if (!deps.keySet().contains(f.getSymbolicName()))
183 {
184 deps.put(f.getSymbolicName(), f);
185 collectRequiredBundles(f, admin, deps, onlyReexport);
186 }
187 }
188 }
189 collectRequiredBundles(bundle, admin, deps, onlyReexport);
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203 protected void collectRequiredBundles(Bundle bundle, PackageAdmin admin, Map<String, Bundle> deps, boolean onlyReexport)
204 {
205 String requiredBundleHeader = (String) bundle.getHeaders().get("Require-Bundle");
206 if (requiredBundleHeader == null) { return; }
207 StringTokenizer tokenizer = new ManifestTokenizer(requiredBundleHeader);
208 while (tokenizer.hasMoreTokens())
209 {
210 String tok = tokenizer.nextToken().trim();
211 StringTokenizer tokenizer2 = new StringTokenizer(tok, ";");
212 String symbolicName = tokenizer2.nextToken().trim();
213 if (deps.keySet().contains(symbolicName))
214 {
215
216
217 continue;
218 }
219 String versionRange = null;
220 boolean reexport = false;
221 while (tokenizer2.hasMoreTokens())
222 {
223 String next = tokenizer2.nextToken().trim();
224 if (next.startsWith("bundle-version="))
225 {
226 if (next.startsWith("bundle-version=\"") || next.startsWith("bundle-version='"))
227 {
228 versionRange = next.substring("bundle-version=\"".length(), next.length() - 1);
229 }
230 else
231 {
232 versionRange = next.substring("bundle-version=".length());
233 }
234 }
235 else if (next.equals("visibility:=reexport"))
236 {
237 reexport = true;
238 }
239 }
240 if (!reexport && onlyReexport) { return; }
241 Bundle[] reqBundles = admin.getBundles(symbolicName, versionRange);
242 if (reqBundles != null && reqBundles.length != 0)
243 {
244 Bundle reqBundle = null;
245 for (Bundle b : reqBundles)
246 {
247 if (b.getState() == Bundle.ACTIVE || b.getState() == Bundle.STARTING)
248 {
249 reqBundle = b;
250 break;
251 }
252 }
253 if (reqBundle == null)
254 {
255
256
257 reqBundle = reqBundles[0];
258 }
259 deps.put(reqBundle.getSymbolicName(), reqBundle);
260 collectFragmentsAndRequiredBundles(reqBundle, admin, deps, true);
261 }
262 }
263 }
264
265 private void invokeFragmentActivators(ServiceReference sr)
266 {
267 PackageAdmin admin = (PackageAdmin) _context.getService(sr);
268 Bundle[] fragments = admin.getFragments(_context.getBundle());
269 if (fragments == null) { return; }
270 for (Bundle frag : fragments)
271 {
272
273 try
274 {
275 String fragmentActivator = frag.getSymbolicName() + ".FragmentActivator";
276 Class<?> c = Class.forName(fragmentActivator);
277 if (c != null)
278 {
279 BundleActivator bActivator = (BundleActivator) c.newInstance();
280 bActivator.start(_context);
281 _activatedFragments.add(bActivator);
282 }
283 }
284 catch (NullPointerException e)
285 {
286
287 }
288 catch (InstantiationException e)
289 {
290
291 }
292 catch (IllegalAccessException e)
293 {
294
295 }
296 catch (ClassNotFoundException e)
297 {
298
299 }
300 catch (Exception e)
301 {
302 e.printStackTrace();
303 }
304 }
305 }
306
307 public void stop()
308 {
309 INSTANCE = null;
310 for (BundleActivator fragAct : _activatedFragments)
311 {
312 try
313 {
314 fragAct.stop(_context);
315 }
316 catch (Exception e)
317 {
318 e.printStackTrace();
319 }
320 }
321 }
322
323
324
325
326 public boolean frameworkHasCompletedAutostarts()
327 {
328 return _startLevel == null ? true : _startLevel.getStartLevel() >= _maxStartLevel;
329 }
330
331 private static class ManifestTokenizer extends StringTokenizer
332 {
333
334 public ManifestTokenizer(String header)
335 {
336 super(header, ",");
337 }
338
339 @Override
340 public String nextToken()
341 {
342 String token = super.nextToken();
343
344 while (hasOpenQuote(token) && hasMoreTokens())
345 {
346 token += "," + super.nextToken();
347 }
348 return token;
349 }
350
351 private boolean hasOpenQuote(String token)
352 {
353 int i = -1;
354 do
355 {
356 int quote = getQuote(token, i + 1);
357 if (quote < 0) { return false; }
358
359 i = token.indexOf(quote, i + 1);
360 i = token.indexOf(quote, i + 1);
361 }
362 while (i >= 0);
363 return true;
364 }
365
366 private int getQuote(String token, int offset)
367 {
368 int i = token.indexOf('"', offset);
369 int j = token.indexOf('\'', offset);
370 if (i < 0)
371 {
372 if (j < 0)
373 {
374 return -1;
375 }
376 else
377 {
378 return '\'';
379 }
380 }
381 if (j < 0) { return '"'; }
382 if (i < j) { return '"'; }
383 return '\'';
384 }
385
386 }
387
388 }
389