void ServiceHooks::FilterServiceReferences(ModuleContext* mc, const std::string& service, const std::string& filter, std::vector<ServiceReferenceBase>& refs) { std::vector<ServiceRegistrationBase> srl; coreCtx->services.Get_unlocked(us_service_interface_iid<ServiceFindHook>(), srl); if (!srl.empty()) { ShrinkableVector<ServiceReferenceBase> filtered(refs); std::sort(srl.begin(), srl.end()); for (std::vector<ServiceRegistrationBase>::reverse_iterator fhrIter = srl.rbegin(), fhrEnd = srl.rend(); fhrIter != fhrEnd; ++fhrIter) { ServiceReference<ServiceFindHook> sr = fhrIter->GetReference(); ServiceFindHook* const fh = reinterpret_cast<ServiceFindHook*>(sr.d->GetService(GetModuleContext()->GetModule())); if (fh != NULL) { try { fh->Find(mc, service, filter, filtered); } catch (const std::exception& e) { US_WARN << "Failed to call find hook #" << sr.GetProperty(ServiceConstants::SERVICE_ID()).ToString() << ": " << e.what(); } catch (...) { US_WARN << "Failed to call find hook #" << sr.GetProperty(ServiceConstants::SERVICE_ID()).ToString() << ": unknown exception type"; } } } } }
void ModuleHooks::FilterModules(const ModuleContext* mc, std::vector<Module*>& modules) const { std::vector<ServiceRegistrationBase> srl; coreCtx->services.Get(us_service_interface_iid<ModuleFindHook>(), srl); ShrinkableVector<Module*> filtered(modules); std::sort(srl.begin(), srl.end()); for (std::vector<ServiceRegistrationBase>::reverse_iterator srBaseIter = srl.rbegin(), srBaseEnd = srl.rend(); srBaseIter != srBaseEnd; ++srBaseIter) { ServiceReference<ModuleFindHook> sr = srBaseIter->GetReference(); ModuleFindHook* const fh = reinterpret_cast<ModuleFindHook*>(sr.d->GetService(GetModuleContext()->GetModule())); if (fh != nullptr) { try { fh->Find(mc, filtered); } catch (const std::exception& e) { US_WARN << "Failed to call Module FindHook #" << sr.GetProperty(ServiceConstants::SERVICE_ID()).ToString() << ": " << e.what(); } catch (...) { US_WARN << "Failed to call Module FindHook #" << sr.GetProperty(ServiceConstants::SERVICE_ID()).ToString() << ": unknown exception type"; } } } }
void ServiceHooks::FilterServiceEventReceivers(const ServiceEvent& evt, ServiceListeners::ServiceListenerEntries& receivers) { std::vector<ServiceRegistrationBase> eventListenerHooks; coreCtx->services.Get_unlocked(us_service_interface_iid<ServiceEventListenerHook>(), eventListenerHooks); if (!eventListenerHooks.empty()) { std::sort(eventListenerHooks.begin(), eventListenerHooks.end()); std::map<ModuleContext*, std::vector<ServiceListenerHook::ListenerInfo> > listeners; for (ServiceListeners::ServiceListenerEntries::iterator sleIter = receivers.begin(), sleEnd = receivers.end(); sleIter != sleEnd; ++sleIter) { listeners[sleIter->GetModuleContext()].push_back(*sleIter); } std::map<ModuleContext*, ShrinkableVector<ServiceListenerHook::ListenerInfo> > shrinkableListeners; for (std::map<ModuleContext*, std::vector<ServiceListenerHook::ListenerInfo> >::iterator iter = listeners.begin(), iterEnd = listeners.end(); iter != iterEnd; ++iter) { shrinkableListeners.insert(std::make_pair(iter->first, ShrinkableVector<ServiceListenerHook::ListenerInfo>(iter->second))); } ShrinkableMap<ModuleContext*, ShrinkableVector<ServiceListenerHook::ListenerInfo> > filtered(shrinkableListeners); for(std::vector<ServiceRegistrationBase>::reverse_iterator sriIter = eventListenerHooks.rbegin(), sriEnd = eventListenerHooks.rend(); sriIter != sriEnd; ++sriIter) { ServiceReference<ServiceEventListenerHook> sr = sriIter->GetReference(); ServiceEventListenerHook* elh = reinterpret_cast<ServiceEventListenerHook*>(sr.d->GetService(GetModuleContext()->GetModule())); if(elh != NULL) { try { elh->Event(evt, filtered); } catch(const std::exception& e) { US_WARN << "Failed to call event hook #" << sr.GetProperty(ServiceConstants::SERVICE_ID()).ToString() << ": " << e.what(); } catch(...) { US_WARN << "Failed to call event hook #" << sr.GetProperty(ServiceConstants::SERVICE_ID()).ToString() << ": unknown exception type"; } } } receivers.clear(); for(std::map<ModuleContext*, std::vector<ServiceListenerHook::ListenerInfo> >::iterator iter = listeners.begin(), iterEnd = listeners.end(); iter != iterEnd; ++iter) { receivers.insert(iter->second.begin(), iter->second.end()); } } }
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 TestServiceFactoryPrototypeScope() { // Install and start test module H, a service factory and test that the methods // in that interface works. SharedLibrary target(LIB_PATH, "TestModuleH"); #ifdef US_BUILD_SHARED_LIBS try { target.Load(); } catch (const std::exception& e) { US_TEST_FAILED_MSG( << "Failed to load module, got exception: " << e.what()) } Module* moduleH = ModuleRegistry::GetModule("TestModuleH"); US_TEST_CONDITION_REQUIRED(moduleH != 0, "Test for existing module TestModuleH") #endif ModuleContext* mc = GetModuleContext(); // Check that a service reference exist const ServiceReference<TestModuleH2> sr1 = mc->GetServiceReference<TestModuleH2>(); US_TEST_CONDITION_REQUIRED(sr1, "Service shall be present.") US_TEST_CONDITION(sr1.GetProperty(ServiceConstants::SERVICE_SCOPE()).ToString() == ServiceConstants::SCOPE_PROTOTYPE(), "service scope") ServiceObjects<TestModuleH2> svcObjects = mc->GetServiceObjects(sr1); TestModuleH2* prototypeServiceH2 = svcObjects.GetService(); const ServiceReferenceU sr1void = mc->GetServiceReference(us_service_interface_iid<TestModuleH2>()); ServiceObjects<void> svcObjectsVoid = mc->GetServiceObjects(sr1void); InterfaceMap prototypeServiceH2Void = svcObjectsVoid.GetService(); US_TEST_CONDITION_REQUIRED(prototypeServiceH2Void.find(us_service_interface_iid<TestModuleH2>()) != prototypeServiceH2Void.end(), "ServiceObjects<void>::GetService()") #ifdef US_BUILD_SHARED_LIBS // There should be only one service in use US_TEST_CONDITION_REQUIRED(mc->GetModule()->GetServicesInUse().size() == 1, "services in use") #endif TestModuleH2* moduleScopeService = mc->GetService(sr1); US_TEST_CONDITION_REQUIRED(moduleScopeService && moduleScopeService != prototypeServiceH2, "GetService()") US_TEST_CONDITION_REQUIRED(prototypeServiceH2 != prototypeServiceH2Void.find(us_service_interface_iid<TestModuleH2>())->second, "GetService()") svcObjectsVoid.UngetService(prototypeServiceH2Void); TestModuleH2* moduleScopeService2 = mc->GetService(sr1); US_TEST_CONDITION(moduleScopeService == moduleScopeService2, "Same service pointer") #ifdef US_BUILD_SHARED_LIBS std::vector<ServiceReferenceU> usedRefs = mc->GetModule()->GetServicesInUse(); US_TEST_CONDITION_REQUIRED(usedRefs.size() == 1, "services in use") US_TEST_CONDITION(usedRefs[0] == sr1, "service ref in use") #endif std::string filter = "(" + ServiceConstants::SERVICE_ID() + "=" + sr1.GetProperty(ServiceConstants::SERVICE_ID()).ToString() + ")"; const ServiceReference<TestModuleH> sr2 = mc->GetServiceReferences<TestModuleH>(filter).front(); US_TEST_CONDITION_REQUIRED(sr2, "Service shall be present.") US_TEST_CONDITION(sr2.GetProperty(ServiceConstants::SERVICE_SCOPE()).ToString() == ServiceConstants::SCOPE_PROTOTYPE(), "service scope") US_TEST_CONDITION(any_cast<long>(sr2.GetProperty(ServiceConstants::SERVICE_ID())) == any_cast<long>(sr1.GetProperty(ServiceConstants::SERVICE_ID())), "same service id") try { svcObjects.UngetService(moduleScopeService2); US_TEST_FAILED_MSG(<< "std::invalid_argument exception expected") } catch (const std::invalid_argument&) { // this is expected } #ifdef US_BUILD_SHARED_LIBS // There should still be only one service in use usedRefs = mc->GetModule()->GetServicesInUse(); US_TEST_CONDITION_REQUIRED(usedRefs.size() == 1, "services in use") #endif ServiceObjects<TestModuleH2> svcObjects2 = svcObjects; ServiceObjects<TestModuleH2> svcObjects3 = mc->GetServiceObjects(sr1); try { svcObjects3.UngetService(prototypeServiceH2); US_TEST_FAILED_MSG(<< "std::invalid_argument exception expected") } catch (const std::invalid_argument&) { // this is expected } svcObjects2.UngetService(prototypeServiceH2); prototypeServiceH2 = svcObjects2.GetService(); TestModuleH2* prototypeServiceH2_2 = svcObjects3.GetService(); US_TEST_CONDITION_REQUIRED(prototypeServiceH2_2 && prototypeServiceH2_2 != prototypeServiceH2, "prototype service") svcObjects2.UngetService(prototypeServiceH2); svcObjects3.UngetService(prototypeServiceH2_2); US_TEST_CONDITION_REQUIRED(mc->UngetService(sr1) == false, "ungetService()") US_TEST_CONDITION_REQUIRED(mc->UngetService(sr1) == true, "ungetService()") target.Unload(); }
void ModuleHooks::FilterModuleEventReceivers(const ModuleEvent& evt, ServiceListeners::ModuleListenerMap& moduleListeners) { std::vector<ServiceRegistrationBase> eventHooks; coreCtx->services.Get(us_service_interface_iid<ModuleEventHook>(), eventHooks); { MutexLock lock(coreCtx->listeners.moduleListenerMapMutex); moduleListeners = coreCtx->listeners.moduleListenerMap; } if(!eventHooks.empty()) { std::vector<ModuleContext*> moduleContexts; for (ServiceListeners::ModuleListenerMap::iterator le = moduleListeners.begin(), leEnd = moduleListeners.end(); le != leEnd; ++le) { moduleContexts.push_back(le->first); } std::sort(moduleContexts.begin(), moduleContexts.end()); moduleContexts.erase(std::unique(moduleContexts.begin(), moduleContexts.end()), moduleContexts.end()); const std::size_t unfilteredSize = moduleContexts.size(); ShrinkableVector<ModuleContext*> filtered(moduleContexts); std::sort(eventHooks.begin(), eventHooks.end()); for (std::vector<ServiceRegistrationBase>::reverse_iterator iter = eventHooks.rbegin(), iterEnd = eventHooks.rend(); iter != iterEnd; ++iter) { ServiceReference<ModuleEventHook> sr; try { sr = iter->GetReference(); } catch (const std::logic_error& e) { US_WARN << "Failed to get event hook service reference: " << e.what(); continue; } ModuleEventHook* eh = reinterpret_cast<ModuleEventHook*>(sr.d->GetService(GetModuleContext()->GetModule())); if (eh != nullptr) { try { eh->Event(evt, filtered); } catch (const std::exception& e) { US_WARN << "Failed to call Module EventHook #" << sr.GetProperty(ServiceConstants::SERVICE_ID()).ToString() << ": " << e.what(); } catch (...) { US_WARN << "Failed to call Module EventHook #" << sr.GetProperty(ServiceConstants::SERVICE_ID()).ToString() << ": unknown exception type"; } } } if (unfilteredSize != moduleContexts.size()) { for (ServiceListeners::ModuleListenerMap::iterator le = moduleListeners.begin(); le != moduleListeners.end();) { if(std::find(moduleContexts.begin(), moduleContexts.end(), le->first) == moduleContexts.end()) { moduleListeners.erase(le++); } else { ++le; } } } } }
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; } } } } }