1 package com.atlassian.plugin.osgi.container.felix;
2
3 import com.atlassian.plugin.Plugin;
4 import com.atlassian.plugin.event.PluginEventListener;
5 import com.atlassian.plugin.event.PluginEventManager;
6 import com.atlassian.plugin.event.events.*;
7 import com.atlassian.plugin.osgi.container.OsgiContainerException;
8 import com.atlassian.plugin.osgi.container.OsgiContainerManager;
9 import com.atlassian.plugin.osgi.container.OsgiContainerStartedEvent;
10 import com.atlassian.plugin.osgi.container.OsgiContainerStoppedEvent;
11 import com.atlassian.plugin.osgi.container.OsgiPersistentCache;
12 import com.atlassian.plugin.osgi.container.PackageScannerConfiguration;
13 import com.atlassian.plugin.osgi.container.impl.DefaultOsgiPersistentCache;
14 import com.atlassian.plugin.osgi.hostcomponents.HostComponentProvider;
15 import com.atlassian.plugin.osgi.hostcomponents.HostComponentRegistration;
16 import com.atlassian.plugin.osgi.hostcomponents.impl.DefaultComponentRegistrar;
17 import com.atlassian.plugin.osgi.util.OsgiHeaderUtil;
18 import com.atlassian.plugin.util.ClassLoaderUtils;
19 import com.atlassian.plugin.util.ContextClassLoaderSwitchingUtil;
20 import com.atlassian.plugin.util.PluginUtils;
21 import com.google.common.annotations.VisibleForTesting;
22 import com.google.common.base.Function;
23 import com.google.common.base.Predicate;
24 import com.google.common.collect.Lists;
25 import org.apache.commons.lang.StringUtils;
26 import org.apache.felix.framework.Felix;
27 import org.apache.felix.framework.Logger;
28 import org.apache.felix.framework.cache.BundleCache;
29 import org.apache.felix.framework.util.FelixConstants;
30 import org.apache.felix.framework.util.StringMap;
31 import org.osgi.framework.*;
32 import org.osgi.service.packageadmin.PackageAdmin;
33 import org.osgi.util.tracker.ServiceTracker;
34 import org.osgi.util.tracker.ServiceTrackerCustomizer;
35 import org.slf4j.LoggerFactory;
36
37 import java.io.File;
38 import java.io.FilenameFilter;
39 import java.io.IOException;
40 import java.net.URL;
41 import java.util.*;
42 import java.util.concurrent.CountDownLatch;
43 import java.util.concurrent.ThreadFactory;
44 import java.util.concurrent.TimeUnit;
45 import java.util.jar.JarFile;
46
47 import static com.google.common.base.Preconditions.checkNotNull;
48 import static com.google.common.collect.Iterables.filter;
49 import static com.google.common.collect.Iterables.transform;
50 import static com.google.common.collect.Sets.newHashSet;
51
52
53
54
55 public class FelixOsgiContainerManager implements OsgiContainerManager
56 {
57 public static final String OSGI_FRAMEWORK_BUNDLES_ZIP = "osgi-framework-bundles.zip";
58 public static final int REFRESH_TIMEOUT = 10;
59
60 private static final org.slf4j.Logger log = LoggerFactory.getLogger(FelixOsgiContainerManager.class);
61 private static final String OSGI_BOOTDELEGATION = "org.osgi.framework.bootdelegation";
62 private static final String ATLASSIAN_PREFIX = "atlassian.";
63
64 private final OsgiPersistentCache persistentCache;
65 private final URL frameworkBundlesUrl;
66 private final PackageScannerConfiguration packageScannerConfig;
67 private final HostComponentProvider hostComponentProvider;
68 private final List<ServiceTracker> trackers;
69 private final ExportsBuilder exportsBuilder;
70 private final ThreadFactory threadFactory = new ThreadFactory()
71 {
72 public Thread newThread(final Runnable r)
73 {
74 final Thread thread = new Thread(r, "Felix:Startup");
75 thread.setDaemon(true);
76 return thread;
77 }
78 };
79
80 private BundleRegistration registration = null;
81 private Felix felix = null;
82 private boolean felixRunning = false;
83 private boolean disableMultipleBundleVersions = true;
84 private Logger felixLogger;
85 private final PluginEventManager pluginEventManager;
86
87
88
89
90
91
92
93
94
95
96 @Deprecated
97 public FelixOsgiContainerManager(final File frameworkBundlesDir, final PackageScannerConfiguration packageScannerConfig, final HostComponentProvider provider, final PluginEventManager eventManager)
98 {
99 this(ClassLoaderUtils.getResource(OSGI_FRAMEWORK_BUNDLES_ZIP, FelixOsgiContainerManager.class), frameworkBundlesDir, packageScannerConfig,
100 provider, eventManager);
101 }
102
103
104
105
106
107
108
109
110
111
112
113 @Deprecated
114 public FelixOsgiContainerManager(final URL frameworkBundlesZip, final File frameworkBundlesDir, final PackageScannerConfiguration packageScannerConfig, final HostComponentProvider provider, final PluginEventManager eventManager)
115 {
116 this(frameworkBundlesZip, new DefaultOsgiPersistentCache(new File(frameworkBundlesDir.getParentFile(),
117 "osgi-cache")), packageScannerConfig, provider, eventManager);
118 }
119
120
121
122
123
124
125
126
127
128
129 public FelixOsgiContainerManager(final OsgiPersistentCache persistentCache, final PackageScannerConfiguration packageScannerConfig, final HostComponentProvider provider, final PluginEventManager eventManager)
130 {
131 this(ClassLoaderUtils.getResource(OSGI_FRAMEWORK_BUNDLES_ZIP, FelixOsgiContainerManager.class), persistentCache, packageScannerConfig,
132 provider, eventManager);
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146
147 public FelixOsgiContainerManager(final URL frameworkBundlesZip, OsgiPersistentCache persistentCache,
148 final PackageScannerConfiguration packageScannerConfig,
149 final HostComponentProvider provider, final PluginEventManager eventManager)
150 throws OsgiContainerException
151 {
152 checkNotNull(frameworkBundlesZip, "The framework bundles zip is required");
153 checkNotNull(persistentCache, "The framework bundles directory must not be null");
154 checkNotNull(packageScannerConfig, "The package scanner configuration must not be null");
155 checkNotNull(eventManager, "The plugin event manager is required");
156
157 frameworkBundlesUrl = frameworkBundlesZip;
158 this.packageScannerConfig = packageScannerConfig;
159 this.persistentCache = persistentCache;
160 hostComponentProvider = provider;
161 trackers = Collections.synchronizedList(new ArrayList<ServiceTracker>());
162 this.pluginEventManager = eventManager;
163 eventManager.register(this);
164 felixLogger = new FelixLoggerBridge(log);
165 exportsBuilder = new ExportsBuilder();
166 }
167
168 public void setFelixLogger(final Logger logger)
169 {
170 felixLogger = logger;
171 }
172
173 public void setDisableMultipleBundleVersions(final boolean val)
174 {
175 disableMultipleBundleVersions = val;
176 }
177
178 @VisibleForTesting
179 public void runWithListener(Runnable runnable, BundleListener listener)
180 {
181 felix.getBundleContext().addBundleListener(listener);
182 try
183 {
184 runnable.run();
185 }
186 finally
187 {
188 felix.getBundleContext().removeBundleListener(listener);
189 }
190 }
191
192
193
194
195
196
197 public void clearExportCache()
198 {
199 exportsBuilder.clearExportCache();
200 }
201
202 @SuppressWarnings ({ "UnusedDeclaration" })
203 @PluginEventListener
204 public void onStart(final PluginFrameworkStartingEvent event)
205 {
206 start();
207 }
208
209 @SuppressWarnings ({ "UnusedDeclaration" })
210 @PluginEventListener
211 public void onShutdown(final PluginFrameworkShutdownEvent event)
212 {
213 stop();
214 }
215
216 @SuppressWarnings ({ "UnusedDeclaration" })
217 @PluginEventListener
218 public void onPluginUninstallation(PluginUninstalledEvent event)
219 {
220 final String pluginKey = event.getPlugin().getKey();
221 for (Bundle bundle : felix.getBundleContext().getBundles())
222 {
223 if (pluginKey.equals(OsgiHeaderUtil.getPluginKey(bundle)))
224 {
225 registration.refreshPackages(Arrays.asList(bundle));
226 break;
227 }
228 }
229 }
230
231 @SuppressWarnings ({ "UnusedDeclaration" })
232 @PluginEventListener
233 public void onPluginListUpgrade(PluginListUpgradedEvent event)
234 {
235 registration.refreshOldBundleOf(event.getPlugins());
236 }
237
238 @SuppressWarnings ({ "UnusedDeclaration" })
239 @PluginEventListener
240 public void onPluginFrameworkWarmRestarting(PluginFrameworkWarmRestartingEvent event)
241 {
242 registration.loadHostComponents(collectHostComponents(hostComponentProvider));
243 }
244
245 public void start() throws OsgiContainerException
246 {
247 if (isRunning())
248 {
249 return;
250 }
251
252 final DefaultComponentRegistrar registrar = collectHostComponents(hostComponentProvider);
253
254 final StringMap configMap = new StringMap(false);
255
256
257
258 configMap.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, exportsBuilder.getExports(registrar.getRegistry(), packageScannerConfig));
259
260
261 configMap.put(BundleCache.CACHE_ROOTDIR_PROP, persistentCache.getOsgiBundleCache().getAbsolutePath());
262
263 configMap.put(FelixConstants.LOG_LEVEL_PROP, String.valueOf(felixLogger.getLogLevel()));
264 configMap.put(FelixConstants.LOG_LOGGER_PROP, felixLogger);
265 String bootDelegation = getAtlassianSpecificOsgiSystemProperty(OSGI_BOOTDELEGATION);
266 if ((bootDelegation == null) || (bootDelegation.trim().length() == 0))
267 {
268
269
270
271 bootDelegation = "weblogic,weblogic.*," +
272 "META-INF.services," +
273 "com.yourkit,com.yourkit.*," +
274 "com.chronon,com.chronon.*," +
275 "com.jprofiler,com.jprofiler.*," +
276 "org.apache.xerces,org.apache.xerces.*," +
277 "org.apache.xalan,org.apache.xalan.*," +
278 "org.apache.xml.serializer," +
279 "sun.*," +
280 "com.sun.xml.bind.v2," +
281 "com.icl.saxon";
282 }
283
284 configMap.put(FelixConstants.FRAMEWORK_BOOTDELEGATION, bootDelegation);
285 configMap.put(FelixConstants.IMPLICIT_BOOT_DELEGATION_PROP, "false");
286
287 configMap.put(FelixConstants.FRAMEWORK_BUNDLE_PARENT, FelixConstants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK);
288 if (log.isDebugEnabled())
289 {
290 log.debug("Felix configuration: " + configMap);
291 }
292
293 validateConfiguration(configMap);
294
295 try
296 {
297
298 registration = new BundleRegistration(frameworkBundlesUrl, persistentCache.getFrameworkBundleCache(), registrar);
299 final List<BundleActivator> list = new ArrayList<BundleActivator>();
300 list.add(registration);
301 configMap.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, list);
302
303
304
305 felix = new Felix(configMap);
306
307
308 final Runnable start = new Runnable()
309 {
310 public void run()
311 {
312 try
313 {
314 Thread.currentThread().setContextClassLoader(null);
315 felix.start();
316 felixRunning = true;
317 }
318 catch (final BundleException e)
319 {
320 throw new OsgiContainerException("Unable to start felix", e);
321 }
322 }
323 };
324 final Thread t = threadFactory.newThread(start);
325 t.start();
326
327
328 t.join(10 * 60 * 1000);
329
330 }
331 catch (final Exception ex)
332 {
333 throw new OsgiContainerException("Unable to start OSGi container", ex);
334 }
335 pluginEventManager.broadcast(new OsgiContainerStartedEvent(this));
336 }
337
338
339
340
341
342
343 private void validateConfiguration(StringMap configMap) throws OsgiContainerException
344 {
345 String systemExports = (String) configMap.get(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
346
347 String cacheKeySource = StringUtils.join(new Object[] {this.getRuntimeEnvironment(), systemExports }, ',');
348
349 validateCaches(cacheKeySource);
350
351 detectIncorrectOsgiVersion();
352 detectXercesOverride(systemExports);
353 }
354
355
356
357
358
359
360
361
362 void detectXercesOverride(String systemExports) throws OsgiContainerException
363 {
364 int pos = systemExports.indexOf("org.apache.xerces.util");
365 if (pos > -1)
366 {
367 if (pos == 0 || (pos > 0 && systemExports.charAt(pos - 1) == ','))
368 {
369 pos += "org.apache.xerces.util".length();
370
371
372 if (pos >= systemExports.length() || ';' != systemExports.charAt(pos))
373 {
374 throw new OsgiContainerException(
375 "Detected an incompatible version of Apache Xerces on the classpath. If using Tomcat, you may have " +
376 "an old version of Xerces in $TOMCAT_HOME/common/lib/endorsed that will need to be removed.");
377 }
378 }
379 }
380 }
381
382
383
384
385
386
387
388 private void validateCaches(String cacheKeySource)
389 {
390 log.info("Using Felix bundle cacheKey source: {}", cacheKeySource);
391 persistentCache.validate(cacheKeySource);
392 log.debug("Using Felix bundle cache directory: {}", persistentCache.getOsgiBundleCache().getAbsolutePath());
393 }
394
395
396
397
398 private void detectIncorrectOsgiVersion()
399 {
400 try
401 {
402 Bundle.class.getMethod("getBundleContext");
403 }
404 catch (final NoSuchMethodException e)
405 {
406 throw new OsgiContainerException(
407 "Detected older version (4.0 or earlier) of OSGi. If using WebSphere " + "6.1, please enable application-first (parent-last) classloading and the 'Single classloader for " + "application' WAR classloader policy.");
408 }
409 }
410
411 public void stop() throws OsgiContainerException
412 {
413 if (felixRunning)
414 {
415 for (final ServiceTracker tracker : new HashSet<ServiceTracker>(trackers))
416 {
417 tracker.close();
418 }
419 try
420 {
421 felix.stop();
422 felix.waitForStop(5000);
423 }
424 catch (InterruptedException e)
425 {
426 log.warn("Interrupting Felix shutdown", e);
427 }
428 catch (BundleException ex)
429 {
430 log.error("An error occurred while stopping the Felix OSGi Container. ", ex);
431 }
432 }
433
434 felixRunning = false;
435 felix = null;
436 pluginEventManager.broadcast(new OsgiContainerStoppedEvent(this));
437 }
438
439 public Bundle[] getBundles()
440 {
441 if (isRunning())
442 {
443 return registration.getBundles();
444 }
445 else
446 {
447 throw new IllegalStateException(
448 "Cannot retrieve the bundles if the Felix container isn't running. Check earlier in the logs for the possible cause as to why Felix didn't start correctly.");
449 }
450 }
451
452 public ServiceReference[] getRegisteredServices()
453 {
454 return felix.getRegisteredServices();
455 }
456
457 public ServiceTracker getServiceTracker(final String interfaceClassName)
458 {
459 return getServiceTracker(interfaceClassName, null);
460 }
461
462 @Override
463 public ServiceTracker getServiceTracker(String interfaceClassName, ServiceTrackerCustomizer serviceTrackerCustomizer)
464 {
465 if (!isRunning())
466 {
467 throw new IllegalStateException("Unable to create a tracker when osgi is not running");
468 }
469
470 final ServiceTracker tracker = registration.getServiceTracker(interfaceClassName, trackers, serviceTrackerCustomizer);
471 tracker.open();
472 trackers.add(tracker);
473 return tracker;
474 }
475
476 public Bundle installBundle(final File file) throws OsgiContainerException
477 {
478 try
479 {
480 return registration.install(file, disableMultipleBundleVersions);
481 }
482 catch (final BundleException e)
483 {
484 throw new OsgiContainerException("Unable to install bundle", e);
485 }
486 }
487
488 DefaultComponentRegistrar collectHostComponents(final HostComponentProvider provider)
489 {
490 final DefaultComponentRegistrar registrar = new DefaultComponentRegistrar();
491 if (provider != null)
492 {
493 provider.provide(registrar);
494 }
495 return registrar;
496 }
497
498 public boolean isRunning()
499 {
500 return felixRunning;
501 }
502
503 public List<HostComponentRegistration> getHostComponentRegistrations()
504 {
505 return registration.getHostComponentRegistrations();
506 }
507
508 private String getAtlassianSpecificOsgiSystemProperty(final String originalSystemProperty)
509 {
510 return System.getProperty(ATLASSIAN_PREFIX + originalSystemProperty);
511 }
512
513
514
515
516
517 @VisibleForTesting
518 String getRuntimeEnvironment()
519 {
520
521
522
523 return String.format("java.version=%s,plugin.enable.timeout=%d", System.getProperty("java.version"), PluginUtils.getDefaultEnablingWaitPeriod());
524 }
525
526 public void runWithListener(Runnable runnable, SynchronousBundleListener bundleListener)
527 {
528 felix.getBundleContext().addBundleListener(bundleListener);
529 try
530 {
531 runnable.run();
532 }
533 finally
534 {
535 felix.getBundleContext().removeBundleListener(bundleListener);
536 }
537 }
538
539
540
541
542
543 static class BundleRegistration implements BundleActivator, BundleListener, FrameworkListener
544 {
545 private BundleContext bundleContext;
546 private DefaultComponentRegistrar registrar;
547 private List<ServiceRegistration> hostServicesReferences;
548 private List<HostComponentRegistration> hostComponentRegistrations;
549 private final URL frameworkBundlesUrl;
550 private final File frameworkBundlesDir;
551 private ClassLoader initializedClassLoader;
552 private PackageAdmin packageAdmin;
553
554 public BundleRegistration(final URL frameworkBundlesUrl, final File frameworkBundlesDir, final DefaultComponentRegistrar registrar)
555 {
556 this.registrar = registrar;
557 this.frameworkBundlesUrl = frameworkBundlesUrl;
558 this.frameworkBundlesDir = frameworkBundlesDir;
559 this.initializedClassLoader = Thread.currentThread().getContextClassLoader();
560 }
561
562 public void start(final BundleContext context) throws Exception
563 {
564 bundleContext = context;
565 final ServiceReference ref = context.getServiceReference(org.osgi.service.packageadmin.PackageAdmin.class.getName());
566 packageAdmin = (PackageAdmin) context.getService(ref);
567
568 context.addBundleListener(this);
569 context.addFrameworkListener(this);
570
571 loadHostComponents(registrar);
572 extractAndInstallFrameworkBundles();
573 }
574
575 public void stop(final BundleContext ctx) throws Exception
576 {
577 ctx.removeBundleListener(this);
578 ctx.removeFrameworkListener(this);
579 if (hostServicesReferences != null)
580 {
581 for (ServiceRegistration ref : hostServicesReferences)
582 {
583 ref.unregister();
584 }
585 }
586 bundleContext = null;
587 packageAdmin = null;
588 hostServicesReferences = null;
589 hostComponentRegistrations = null;
590 registrar = null;
591 initializedClassLoader = null;
592 }
593
594 public void bundleChanged(final BundleEvent evt)
595 {
596 switch (evt.getType())
597 {
598 case BundleEvent.INSTALLED:
599 log.info("Installed bundle " + evt.getBundle().getSymbolicName() + " (" + evt.getBundle().getBundleId() + ")");
600 break;
601 case BundleEvent.RESOLVED:
602 log.info("Resolved bundle " + evt.getBundle().getSymbolicName() + " (" + evt.getBundle().getBundleId() + ")");
603 break;
604 case BundleEvent.UNRESOLVED:
605 log.info("Unresolved bundle " + evt.getBundle().getSymbolicName() + " (" + evt.getBundle().getBundleId() + ")");
606 break;
607 case BundleEvent.STARTED:
608 log.info("Started bundle " + evt.getBundle().getSymbolicName() + " (" + evt.getBundle().getBundleId() + ")");
609 break;
610 case BundleEvent.STOPPED:
611 log.info("Stopped bundle " + evt.getBundle().getSymbolicName() + " (" + evt.getBundle().getBundleId() + ")");
612 break;
613 case BundleEvent.UNINSTALLED:
614 log.info("Uninstalled bundle " + evt.getBundle().getSymbolicName() + " (" + evt.getBundle().getBundleId() + ")");
615 break;
616 }
617 }
618
619 public Bundle install(final File path, final boolean uninstallOtherVersions) throws BundleException
620 {
621 if (uninstallOtherVersions)
622 {
623 try
624 {
625 JarFile jar = new JarFile(path);
626 String pluginKey = null;
627 try
628 {
629 pluginKey = OsgiHeaderUtil.getPluginKey(jar.getManifest());
630 }
631 finally
632 {
633 jar.close();
634 }
635 for (final Bundle bundle : bundleContext.getBundles())
636 {
637 if (pluginKey.equals(OsgiHeaderUtil.getPluginKey(bundle)))
638 {
639
640
641
642 log.info("Uninstalling existing version " + bundle.getHeaders().get(
643 Constants.BUNDLE_VERSION));
644 bundle.uninstall();
645
646
647 }
648 }
649 }
650 catch (final IOException e)
651 {
652 throw new BundleException("Invalid bundle format", e);
653 }
654 }
655 return bundleContext.installBundle(path.toURI().toString());
656 }
657
658 public Bundle[] getBundles()
659 {
660 return bundleContext.getBundles();
661 }
662
663 public ServiceTracker getServiceTracker(final String clazz,
664 final Collection<ServiceTracker> trackedTrackers)
665 {
666 return getServiceTracker(clazz, trackedTrackers, null);
667 }
668
669 public ServiceTracker getServiceTracker(final String clazz,
670 final Collection<ServiceTracker> trackedTrackers,
671 final ServiceTrackerCustomizer customizer)
672 {
673 return new ServiceTracker(bundleContext, clazz, customizer)
674 {
675 @Override
676 public void close()
677 {
678 super.close();
679 trackedTrackers.remove(this);
680 }
681 };
682 }
683
684 public List<HostComponentRegistration> getHostComponentRegistrations()
685 {
686 return hostComponentRegistrations;
687 }
688
689 void loadHostComponents(final DefaultComponentRegistrar registrar)
690 {
691
692 if (hostServicesReferences != null)
693 {
694 for (final ServiceRegistration reg : hostServicesReferences)
695 {
696 reg.unregister();
697 }
698 }
699
700 ContextClassLoaderSwitchingUtil.runInContext(initializedClassLoader, new Runnable()
701 {
702 public void run()
703 {
704 hostServicesReferences = registrar.writeRegistry(bundleContext);
705 hostComponentRegistrations = registrar.getRegistry();
706 }
707 });
708 }
709
710 private void extractAndInstallFrameworkBundles() throws BundleException
711 {
712 final List<Bundle> bundles = new ArrayList<Bundle>();
713 com.atlassian.plugin.util.FileUtils.conditionallyExtractZipFile(frameworkBundlesUrl, frameworkBundlesDir);
714 for (final File bundleFile : frameworkBundlesDir.listFiles(new FilenameFilter()
715 {
716 public boolean accept(final File file, final String s)
717 {
718 return s.endsWith(".jar");
719 }
720 }))
721 {
722 bundles.add(install(bundleFile, false));
723 }
724
725 packageAdmin.refreshPackages(bundles.toArray(new Bundle[bundles.size()]));
726
727 for (final Bundle bundle : bundles)
728 {
729 if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) == null)
730 {
731 bundle.start();
732 }
733 }
734 }
735
736
737
738 public void refreshPackages(Collection<Bundle> bundles)
739 {
740 final CountDownLatch latch = new CountDownLatch(1);
741 FrameworkListener refreshListener = new FrameworkListener()
742 {
743
744 public void frameworkEvent(FrameworkEvent event)
745 {
746 if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED)
747 {
748 log.info("Packages refreshed");
749 latch.countDown();
750 }
751 }
752 };
753
754 bundleContext.addFrameworkListener(refreshListener);
755 try
756 {
757 packageAdmin.refreshPackages(null);
758 boolean refreshed = false;
759 try
760 {
761 refreshed = latch.await(REFRESH_TIMEOUT, TimeUnit.SECONDS);
762 }
763 catch (InterruptedException e)
764 {
765
766 }
767 if (!refreshed)
768 {
769 log.warn("Timeout exceeded waiting for package refresh");
770 }
771 }
772 finally
773 {
774 bundleContext.removeFrameworkListener(refreshListener);
775 }
776 }
777
778 @SuppressWarnings ({ "ThrowableResultOfMethodCallIgnored" })
779 public void frameworkEvent(FrameworkEvent event)
780 {
781 String bundleBits = "";
782 if (event.getBundle() != null)
783 {
784 bundleBits = " in bundle " + event.getBundle().getSymbolicName();
785 }
786 switch (event.getType())
787 {
788 case FrameworkEvent.ERROR:
789 log.error("Framework error" + bundleBits, event.getThrowable());
790 break;
791 case FrameworkEvent.WARNING:
792 log.warn("Framework warning" + bundleBits, event.getThrowable());
793 break;
794 case FrameworkEvent.INFO:
795 log.info("Framework info" + bundleBits, event.getThrowable());
796 break;
797 }
798 }
799
800 public void refreshOldBundleOf(Iterable<Plugin> plugins)
801 {
802
803 final Set<String> upgradedPluginKeys = newHashSet(transform(plugins, new Function<Plugin, String>()
804 {
805 public String apply(Plugin input)
806 {
807 return input.getKey();
808 }
809 }));
810
811
812 refreshPackages(Lists.newArrayList(filter(Arrays.asList(bundleContext.getBundles()), new Predicate<Bundle>()
813 {
814 public boolean apply(Bundle input)
815 {
816 return upgradedPluginKeys.contains(OsgiHeaderUtil.getPluginKey(input));
817 }
818 })));
819 }
820 }
821
822 }