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