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