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