void BundleHooks::FilterBundles(const BundleContext& context, std::vector<Bundle>& bundles) const { std::vector<ServiceRegistrationBase> srl; coreCtx->services.Get(us_service_interface_iid<BundleFindHook>(), srl); ShrinkableVector<Bundle> filtered(bundles); auto selfBundle = GetBundleContext().GetBundle(); std::sort(srl.begin(), srl.end()); for (auto srBaseIter = srl.rbegin(), srBaseEnd = srl.rend(); srBaseIter != srBaseEnd; ++srBaseIter) { ServiceReference<BundleFindHook> sr = srBaseIter->GetReference(); std::shared_ptr<BundleFindHook> fh = std::static_pointer_cast<BundleFindHook>( sr.d.load()->GetService(GetPrivate(selfBundle).get())); if (fh) { try { fh->Find(context, filtered); } catch (...) { std::string message("Failed to call Bundle FindHook # " + sr.GetProperty(Constants::SERVICE_ID).ToString()); coreCtx->listeners.SendFrameworkEvent( FrameworkEvent(FrameworkEvent::Type::FRAMEWORK_WARNING, selfBundle, message, std::current_exception())); } } } }
void ServiceListeners::ServiceChanged(ServiceListenerEntries& receivers, const ServiceEvent& evt, ServiceListenerEntries& matchBefore) { int n = 0; if (!matchBefore.empty()) { for (auto& l : receivers) { matchBefore.erase(l); } } for (auto& l : receivers) { if (!l.IsRemoved()) { try { ++n; l.CallDelegate(evt); } catch (...) { std::string message("Service listener in " + l.GetBundleContext().GetBundle().GetSymbolicName() + " threw an exception!"); SendFrameworkEvent(FrameworkEvent( FrameworkEvent::Type::FRAMEWORK_ERROR, l.GetBundleContext().GetBundle(), message, std::current_exception())); } } } }
void ServiceListeners::BundleChanged(const BundleEvent& evt) { BundleListenerMap filteredBundleListeners; coreCtx->bundleHooks.FilterBundleEventReceivers(evt, filteredBundleListeners); for(auto& bundleListeners : filteredBundleListeners) { for (auto& bundleListener : bundleListeners.second) { try { std::get<0>(bundleListener.second)(evt); } catch (...) { SendFrameworkEvent(FrameworkEvent( FrameworkEvent::Type::FRAMEWORK_ERROR, MakeBundle(bundleListeners.first->bundle->shared_from_this()), std::string("Bundle listener threw an exception"), std::current_exception())); } } } }
void BundleHooks::FilterBundleEventReceivers( const BundleEvent& evt, ServiceListeners::BundleListenerMap& bundleListeners) { std::vector<ServiceRegistrationBase> eventHooks; coreCtx->services.Get(us_service_interface_iid<BundleEventHook>(), eventHooks); { auto l = coreCtx->listeners.bundleListenerMap.Lock(); US_UNUSED(l); bundleListeners = coreCtx->listeners.bundleListenerMap.value; } if (!eventHooks.empty()) { std::vector<BundleContext> bundleContexts; for (auto& le : bundleListeners) { bundleContexts.push_back(MakeBundleContext(le.first->shared_from_this())); } std::sort(bundleContexts.begin(), bundleContexts.end()); bundleContexts.erase( std::unique(bundleContexts.begin(), bundleContexts.end()), bundleContexts.end()); const std::size_t unfilteredSize = bundleContexts.size(); ShrinkableVector<BundleContext> filtered(bundleContexts); std::sort(eventHooks.begin(), eventHooks.end()); for (auto iter = eventHooks.rbegin(), iterEnd = eventHooks.rend(); iter != iterEnd; ++iter) { ServiceReference<BundleEventHook> sr; try { sr = iter->GetReference(); } catch (const std::logic_error&) { std::string message("Failed to get event hook service reference"); coreCtx->listeners.SendFrameworkEvent( FrameworkEvent(FrameworkEvent::Type::FRAMEWORK_WARNING, GetBundleContext().GetBundle(), message, std::current_exception())); continue; } std::shared_ptr<BundleEventHook> eh = std::static_pointer_cast<BundleEventHook>(sr.d.load()->GetService( GetPrivate(GetBundleContext().GetBundle()).get())); if (eh) { try { eh->Event(evt, filtered); } catch (...) { std::string message("Failed to call Bundle EventHook # " + sr.GetProperty(Constants::SERVICE_ID).ToString()); coreCtx->listeners.SendFrameworkEvent( FrameworkEvent(FrameworkEvent::Type::FRAMEWORK_WARNING, GetBundleContext().GetBundle(), message, std::current_exception())); } } } if (unfilteredSize != bundleContexts.size()) { for (ServiceListeners::BundleListenerMap::iterator le = bundleListeners.begin(); le != bundleListeners.end();) { if (std::find_if(bundleContexts.begin(), bundleContexts.end(), [&le](const BundleContext& bc) { return GetPrivate(bc) == le->first; }) == bundleContexts.end()) { bundleListeners.erase(le++); } else { ++le; } } } } }