diff --git a/Core/Code/Service/mitkModuleAbstractTracked.tpp b/Core/Code/Service/mitkModuleAbstractTracked.tpp index 9a79d0b3ec..fe18c72dfb 100644 --- a/Core/Code/Service/mitkModuleAbstractTracked.tpp +++ b/Core/Code/Service/mitkModuleAbstractTracked.tpp @@ -1,325 +1,327 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include +#include + namespace mitk { typedef itk::MutexLockHolder MutexLocker; template const bool ModuleAbstractTracked::DEBUG = false; template ModuleAbstractTracked::ModuleAbstractTracked() : waitCond(itk::ConditionVariable::New()) { closed = false; } template ModuleAbstractTracked::~ModuleAbstractTracked() { } template void ModuleAbstractTracked::Wait() { waitCond->Wait(this); } template void ModuleAbstractTracked::WakeAll() { waitCond->Broadcast(); } template void ModuleAbstractTracked::SetInitial(const std::list& initiallist) { initial = initiallist; if (DEBUG) { for(typename std::list::const_iterator item = initiallist.begin(); item != initiallist.end(); ++item) { MITK_DEBUG(true) << "ModuleAbstractTracked::setInitial: " << (*item); } } } template void ModuleAbstractTracked::TrackInitial() { while (true) { S item(0); { itk::MutexLockHolder lock(*this); if (closed || (initial.size() == 0)) { /* * if there are no more initial items */ return; /* we are done */ } /* * move the first item from the initial list to the adding list * within this synchronized block. */ item = initial.front(); initial.pop_front(); if (tracked[item]) { /* if we are already tracking this item */ MITK_DEBUG(DEBUG) << "ModuleAbstractTracked::trackInitial[already tracked]: " << item; continue; /* skip this item */ } if (std::find(adding.begin(), adding.end(), item) != adding.end()) { /* * if this item is already in the process of being added. */ MITK_DEBUG(DEBUG) << "ModuleAbstractTracked::trackInitial[already adding]: " << item; continue; /* skip this item */ } adding.push_back(item); } MITK_DEBUG(DEBUG) << "ModuleAbstractTracked::trackInitial: " << item; TrackAdding(item, R()); /* * Begin tracking it. We call trackAdding * since we have already put the item in the * adding list. */ } } template void ModuleAbstractTracked::Close() { closed = true; } template void ModuleAbstractTracked::Track(S item, R related) { T object(0); { itk::MutexLockHolder lock(*this); if (closed) { return; } object = tracked[item]; if (!object) { /* we are not tracking the item */ if (std::find(adding.begin(), adding.end(),item) != adding.end()) { /* if this item is already in the process of being added. */ MITK_DEBUG(DEBUG) << "ModuleAbstractTracked::track[already adding]: " << item; return; } adding.push_back(item); /* mark this item is being added */ } else { /* we are currently tracking this item */ MITK_DEBUG(DEBUG) << "ModuleAbstractTracked::track[modified]: " << item; Modified(); /* increment modification count */ } } if (!object) { /* we are not tracking the item */ TrackAdding(item, related); } else { /* Call customizer outside of synchronized region */ CustomizerModified(item, related, object); /* * If the customizer throws an unchecked exception, it is safe to * let it propagate */ } } template void ModuleAbstractTracked::Untrack(S item, R related) { T object(0); { itk::MutexLockHolder lock(*this); std::size_t initialSize = initial.size(); initial.remove(item); if (initialSize != initial.size()) { /* if this item is already in the list * of initial references to process */ MITK_DEBUG(DEBUG) << "ModuleAbstractTracked::untrack[removed from initial]: " << item; return; /* we have removed it from the list and it will not be * processed */ } std::size_t addingSize = adding.size(); adding.remove(item); if (addingSize != adding.size()) { /* if the item is in the process of * being added */ MITK_DEBUG(DEBUG) << "ModuleAbstractTracked::untrack[being added]: " << item; return; /* * in case the item is untracked while in the process of * adding */ } object = tracked[item]; /* * must remove from tracker before * calling customizer callback */ tracked.erase(item); if (!object) { /* are we actually tracking the item */ return; } Modified(); /* increment modification count */ } MITK_DEBUG(DEBUG) << "ModuleAbstractTracked::untrack[removed]: " << item; /* Call customizer outside of synchronized region */ CustomizerRemoved(item, related, object); /* * If the customizer throws an unchecked exception, it is safe to let it * propagate */ } template std::size_t ModuleAbstractTracked::Size() const { return tracked.size(); } template bool ModuleAbstractTracked::IsEmpty() const { return tracked.empty(); } template T ModuleAbstractTracked::GetCustomizedObject(S item) const { typename TrackingMap::const_iterator i = tracked.find(item); if (i != tracked.end()) return i->second; return T(); } template void ModuleAbstractTracked::GetTracked(std::list& items) const { for (typename TrackingMap::const_iterator i = tracked.begin(); i != tracked.end(); ++i) { items.push_back(i->first); } } template void ModuleAbstractTracked::Modified() { trackingCount.Ref(); } template int ModuleAbstractTracked::GetTrackingCount() const { return trackingCount; } template void ModuleAbstractTracked::CopyEntries(TrackingMap& map) const { map.insert(tracked.begin(), tracked.end()); } template bool ModuleAbstractTracked::CustomizerAddingFinal(S item, const T& custom) { itk::MutexLockHolder lock(*this); std::size_t addingSize = adding.size(); adding.remove(item); if (addingSize != adding.size() && !closed) { /* * if the item was not untracked during the customizer * callback */ if (custom) { tracked[item] = custom; Modified(); /* increment modification count */ waitCond->Broadcast(); /* notify any waiters */ } return false; } else { return true; } } template void ModuleAbstractTracked::TrackAdding(S item, R related) { MITK_DEBUG(DEBUG) << "ModuleAbstractTracked::trackAdding:" << item; T object(0); bool becameUntracked = false; /* Call customizer outside of synchronized region */ try { object = CustomizerAdding(item, related); becameUntracked = this->CustomizerAddingFinal(item, object); } catch (...) { /* * If the customizer throws an exception, it will * propagate after the cleanup code. */ this->CustomizerAddingFinal(item, object); throw; } /* * The item became untracked during the customizer callback. */ if (becameUntracked && object) { MITK_DEBUG(DEBUG) << "ModuleAbstractTracked::trackAdding[removed]: " << item; /* Call customizer outside of synchronized region */ CustomizerRemoved(item, related, object); /* * If the customizer throws an unchecked exception, it is safe to * let it propagate */ } } } diff --git a/Core/Code/Service/mitkServiceTracker.tpp b/Core/Code/Service/mitkServiceTracker.tpp index 54871059f7..05490a2028 100644 --- a/Core/Code/Service/mitkServiceTracker.tpp +++ b/Core/Code/Service/mitkServiceTracker.tpp @@ -1,436 +1,438 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkServiceTrackerPrivate.h" #include "mitkTrackedService.h" #include "mitkServiceException.h" #include "mitkModuleContext.h" +#include + #include #include namespace mitk { template ServiceTracker::~ServiceTracker() { delete d; } template ServiceTracker::ServiceTracker(ModuleContext* context, const ServiceReference& reference, _ServiceTrackerCustomizer* customizer) : d(new _ServiceTrackerPrivate(this, context, reference, customizer)) { } template ServiceTracker::ServiceTracker(ModuleContext* context, const std::string& clazz, _ServiceTrackerCustomizer* customizer) : d(new _ServiceTrackerPrivate(this, context, clazz, customizer)) { } template ServiceTracker::ServiceTracker(ModuleContext* context, const LDAPFilter& filter, _ServiceTrackerCustomizer* customizer) : d(new _ServiceTrackerPrivate(this, context, filter, customizer)) { } template ServiceTracker::ServiceTracker(ModuleContext *context, ServiceTrackerCustomizer *customizer) : d(new _ServiceTrackerPrivate(this, context, mitk_service_interface_iid(), customizer)) { const char* clazz = mitk_service_interface_iid(); if (clazz == 0) throw ServiceException("The service interface class has no MITK_DECLARE_SERVICE_INTERFACE macro"); } template void ServiceTracker::Open() { itk::SmartPointer<_TrackedService> t; { MutexLocker lock(d->mutex); if (d->trackedService) { return; } MITK_DEBUG(d->DEBUG) << "ServiceTracker::Open: " << d->filter; t = itk::SmartPointer<_TrackedService>( new _TrackedService(this, d->customizer)); { itk::MutexLockHolder lockT(*t); try { d->context->AddServiceListener(t.GetPointer(), &_TrackedService::ServiceChanged, d->listenerFilter); std::list references; if (!d->trackClass.empty()) { references = d->GetInitialReferences(d->trackClass, std::string()); } else { if (d->trackReference.GetModule() != 0) { references.push_back(d->trackReference); } else { /* user supplied filter */ references = d->GetInitialReferences(std::string(), (d->listenerFilter.empty()) ? d->filter.ToString() : d->listenerFilter); } } /* set tracked with the initial references */ t->SetInitial(references); } catch (const std::invalid_argument& e) { throw std::runtime_error(std::string("unexpected std::invalid_argument exception: ") + e.what()); } } d->trackedService = t; } /* Call tracked outside of synchronized region */ t->TrackInitial(); /* process the initial references */ } template void ServiceTracker::Close() { itk::SmartPointer<_TrackedService> outgoing; std::list references; { MutexLocker lock(d->mutex); outgoing = d->trackedService; if (outgoing.IsNull()) { return; } MITK_DEBUG(d->DEBUG) << "ServiceTracker::close:" << d->filter; outgoing->Close(); GetServiceReferences(references); d->trackedService = 0; try { d->context->RemoveServiceListener(outgoing.GetPointer(), &_TrackedService::ServiceChanged); } catch (const std::logic_error& /*e*/) { /* In case the context was stopped. */ } } d->Modified(); /* clear the cache */ { itk::MutexLockHolder lockT(*outgoing); outgoing->WakeAll(); /* wake up any waiters */ } for(std::list::const_iterator ref = references.begin(); ref != references.end(); ++ref) { outgoing->Untrack(*ref, ServiceEvent()); } if (d->DEBUG) { MutexLocker lock(d->mutex); if ((d->cachedReference.GetModule() == 0) && (d->cachedService == 0)) { MITK_DEBUG(true) << "ServiceTracker::close[cached cleared]:" << d->filter; } } } template T ServiceTracker::WaitForService() { T object = GetService(); while (object == 0) { itk::SmartPointer<_TrackedService> t = d->Tracked(); if (t.IsNull()) { /* if ServiceTracker is not open */ return 0; } { itk::MutexLockHolder lockT(*t); if (t->Size() == 0) { t->Wait(); } } object = GetService(); } return object; } template void ServiceTracker::GetServiceReferences(std::list& refs) const { itk::SmartPointer<_TrackedService> t = d->Tracked(); if (t.IsNull()) { /* if ServiceTracker is not open */ return; } { itk::MutexLockHolder lockT(*t); if (t->Size() == 0) { return; } t->GetTracked(refs); } } template ServiceReference ServiceTracker::GetServiceReference() const { ServiceReference reference(0); { MutexLocker lock(d->mutex); reference = d->cachedReference; } if (reference.GetModule() != 0) { MITK_DEBUG(d->DEBUG) << "ServiceTracker::getServiceReference[cached]:" << d->filter; return reference; } MITK_DEBUG(d->DEBUG) << "ServiceTracker::getServiceReference:" << d->filter; std::list references; GetServiceReferences(references); int length = references.size(); if (length == 0) { /* if no service is being tracked */ throw ServiceException("No service is being tracked"); } std::list::const_iterator selectedRef; if (length > 1) { /* if more than one service, select highest ranking */ std::vector rankings(length); int count = 0; int maxRanking = std::numeric_limits::min(); std::list::const_iterator refIter = references.begin(); for (int i = 0; i < length; i++) { bool ok = false; Any rankingAny = refIter->GetProperty(ServiceConstants::SERVICE_RANKING()); int ranking = 0; if (rankingAny.Type() == typeid(int)) { ranking = any_cast(rankingAny); ok = true; } rankings[i] = ranking; if (ranking > maxRanking) { selectedRef = refIter; maxRanking = ranking; count = 1; } else { if (ranking == maxRanking) { count++; } } } if (count > 1) { /* if still more than one service, select lowest id */ long int minId = std::numeric_limits::max(); for (int i = 0; i < length; i++) { if (rankings[i] == maxRanking) { Any idAny = refIter->GetProperty(ServiceConstants::SERVICE_ID()); long int id = 0; if (idAny.Type() == typeid(long int)) { id = any_cast(idAny); } if (id < minId) { selectedRef = refIter; minId = id; } } } } ++refIter; } { MutexLocker lock(d->mutex); d->cachedReference = *selectedRef; return d->cachedReference; } } template T ServiceTracker::GetService(const ServiceReference& reference) const { itk::SmartPointer<_TrackedService> t = d->Tracked(); if (t.IsNull()) { /* if ServiceTracker is not open */ return 0; } { itk::MutexLockHolder lockT(*t); return t->GetCustomizedObject(reference); } } template void ServiceTracker::GetServices(std::list& services) const { itk::SmartPointer<_TrackedService> t = d->Tracked(); if (t.IsNull()) { /* if ServiceTracker is not open */ return; } { itk::MutexLockHolder lockT(*t); std::list references; GetServiceReferences(references); for(std::list::const_iterator ref = references.begin(); ref != references.end(); ++ref) { services.push_back(GetService(*ref)); } } } template T ServiceTracker::GetService() const { T service = d->cachedService; if (service != 0) { MITK_DEBUG(d->DEBUG) << "ServiceTracker::getService[cached]:" << d->filter; return service; } MITK_DEBUG(d->DEBUG) << "ServiceTracker::getService:" << d->filter; try { ServiceReference reference = GetServiceReference(); if (reference.GetModule() == 0) { return 0; } return d->cachedService = GetService(reference); } catch (const ServiceException&) { return 0; } } template void ServiceTracker::Remove(const ServiceReference& reference) { itk::SmartPointer<_TrackedService> t = d->Tracked(); if (t.IsNull()) { /* if ServiceTracker is not open */ return; } t->Untrack(reference, ServiceEvent()); } template int ServiceTracker::Size() const { itk::SmartPointer<_TrackedService> t = d->Tracked(); if (t.IsNull()) { /* if ServiceTracker is not open */ return 0; } { itk::MutexLockHolder lockT(*t); return t->Size(); } } template int ServiceTracker::GetTrackingCount() const { itk::SmartPointer<_TrackedService> t = d->Tracked(); if (t.IsNull()) { /* if ServiceTracker is not open */ return -1; } { itk::MutexLockHolder lockT(*t); return t->GetTrackingCount(); } } template void ServiceTracker::GetTracked(TrackingMap& map) const { itk::SmartPointer<_TrackedService> t = d->Tracked(); if (t.IsNull()) { /* if ServiceTracker is not open */ return; } { itk::MutexLockHolder lockT(*t); t->CopyEntries(map); } } template bool ServiceTracker::IsEmpty() const { itk::SmartPointer<_TrackedService> t = d->Tracked(); if (t.IsNull()) { /* if ServiceTracker is not open */ return true; } { itk::MutexLockHolder lockT(*t); return t->IsEmpty(); } } template T ServiceTracker::AddingService(const ServiceReference& reference) { return dynamic_cast(d->context->GetService(reference)); } template void ServiceTracker::ModifiedService(const ServiceReference& /*reference*/, T /*service*/) { /* do nothing */ } template void ServiceTracker::RemovedService(const ServiceReference& reference, T /*service*/) { d->context->UngetService(reference); } } // end namespace mitk diff --git a/Core/Code/Testing/TestModules/libA/mitkTestModuleA.cpp b/Core/Code/Testing/TestModules/libA/mitkTestModuleA.cpp index a9baa930c1..0757d3d60a 100644 --- a/Core/Code/Testing/TestModules/libA/mitkTestModuleA.cpp +++ b/Core/Code/Testing/TestModules/libA/mitkTestModuleA.cpp @@ -1,60 +1,62 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkTestModuleAService.h" #include #include #include +#include + namespace mitk { struct TestModuleA : public itk::LightObject, public TestModuleAService { TestModuleA(ModuleContext* mc) { MITK_INFO << "Registering TestModuleAService"; mc->RegisterService(this); } }; class TestModuleAActivator : public ModuleActivator { public: void Load(ModuleContext* context) { s = new TestModuleA(context); } void Unload(ModuleContext*) { } private: itk::SmartPointer s; }; } MITK_EXPORT_MODULE_ACTIVATOR(TestModuleA, mitk::TestModuleAActivator) diff --git a/Core/Code/Testing/TestModules/libA2/mitkTestModuleA2.cpp b/Core/Code/Testing/TestModules/libA2/mitkTestModuleA2.cpp index 8e9f778b4d..283f7cee6b 100644 --- a/Core/Code/Testing/TestModules/libA2/mitkTestModuleA2.cpp +++ b/Core/Code/Testing/TestModules/libA2/mitkTestModuleA2.cpp @@ -1,71 +1,73 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkTestModuleA2Service.h" #include #include #include +#include + namespace mitk { struct TestModuleA2 : public itk::LightObject, public TestModuleA2Service { TestModuleA2(ModuleContext* mc) { MITK_INFO << "Registering TestModuleA2Service"; sr = mc->RegisterService(this); } void Unregister() { if (sr) { sr.Unregister(); } } private: ServiceRegistration sr; }; class TestModuleA2Activator : public ModuleActivator { public: void Load(ModuleContext* context) { s = new TestModuleA2(context); } void Unload(ModuleContext* /*context*/) { s->Unregister(); } private: itk::SmartPointer s; }; } MITK_EXPORT_MODULE_ACTIVATOR(TestModuleA2, mitk::TestModuleA2Activator) diff --git a/Core/Code/Testing/TestModules/libSL4/mitkActivatorSL4.cpp b/Core/Code/Testing/TestModules/libSL4/mitkActivatorSL4.cpp index ad45511ece..95bb71363f 100644 --- a/Core/Code/Testing/TestModules/libSL4/mitkActivatorSL4.cpp +++ b/Core/Code/Testing/TestModules/libSL4/mitkActivatorSL4.cpp @@ -1,60 +1,62 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include #include #include #include #include +#include + namespace mitk { class ActivatorSL4 : public itk::LightObject, public ModuleActivator, public FooService { public: ~ActivatorSL4() { --m_ReferenceCount; } void foo() { MITK_INFO << "TestModuleSL4: Doing foo"; } void Load(ModuleContext* context) { ServiceRegistration registration = context->RegisterService(this); MITK_INFO << "TestModuleSL4: Registered" << registration; } void Unload(ModuleContext* /*context*/) { //unregister will be done automagically } }; } MITK_EXPORT_MODULE_ACTIVATOR(TestModuleSL4, mitk::ActivatorSL4) diff --git a/Core/Code/Testing/mitkModuleTest.cpp b/Core/Code/Testing/mitkModuleTest.cpp index e8b7d68bad..ddb65f35d6 100644 --- a/Core/Code/Testing/mitkModuleTest.cpp +++ b/Core/Code/Testing/mitkModuleTest.cpp @@ -1,353 +1,354 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include #include #include #include #include "mitkTestUtilSharedLibrary.cpp" #include +#include class ModuleListener { public: ModuleListener(mitk::ModuleContext* mc) : mc(mc) {} void ModuleChanged(const mitk::ModuleEvent& event) { moduleEvents.push_back(event); MITK_DEBUG << "ModuleEvent:" << event; } void ServiceChanged(const mitk::ServiceEvent& event) { serviceEvents.push_back(event); MITK_DEBUG << "ServiceEvent:" << event; } mitk::ModuleEvent GetModuleEvent() const { if (moduleEvents.empty()) { return mitk::ModuleEvent(); } return moduleEvents.back(); } mitk::ServiceEvent GetServiceEvent() const { if (serviceEvents.empty()) { return mitk::ServiceEvent(); } return serviceEvents.back(); } bool CheckListenerEvents( bool pexp, mitk::ModuleEvent::Type ptype, bool sexp, mitk::ServiceEvent::Type stype, mitk::Module* moduleX, mitk::ServiceReference* servX) { std::vector pEvts; std::vector seEvts; if (pexp) pEvts.push_back(mitk::ModuleEvent(ptype, moduleX)); if (sexp) seEvts.push_back(mitk::ServiceEvent(stype, *servX)); return CheckListenerEvents(pEvts, seEvts); } bool CheckListenerEvents( const std::vector& pEvts, const std::vector& seEvts) { bool listenState = true; // assume everything will work if (pEvts.size() != moduleEvents.size()) { listenState = false; MITK_DEBUG << "*** Module event mismatch: expected " << pEvts.size() << " event(s), found " << moduleEvents.size() << " event(s)."; const std::size_t max = pEvts.size() > moduleEvents.size() ? pEvts.size() : moduleEvents.size(); for (std::size_t i = 0; i < max; ++i) { const mitk::ModuleEvent& pE = i < pEvts.size() ? pEvts[i] : mitk::ModuleEvent(); const mitk::ModuleEvent& pR = i < moduleEvents.size() ? moduleEvents[i] : mitk::ModuleEvent(); MITK_DEBUG << " " << pE << " - " << pR; } } else { for (std::size_t i = 0; i < pEvts.size(); ++i) { const mitk::ModuleEvent& pE = pEvts[i]; const mitk::ModuleEvent& pR = moduleEvents[i]; if (pE.GetType() != pR.GetType() || pE.GetModule() != pR.GetModule()) { listenState = false; MITK_DEBUG << "*** Wrong module event: " << pR << " expected " << pE; } } } if (seEvts.size() != serviceEvents.size()) { listenState = false; MITK_DEBUG << "*** Service event mismatch: expected " << seEvts.size() << " event(s), found " << serviceEvents.size() << " event(s)."; const std::size_t max = seEvts.size() > serviceEvents.size() ? seEvts.size() : serviceEvents.size(); for (std::size_t i = 0; i < max; ++i) { const mitk::ServiceEvent& seE = i < seEvts.size() ? seEvts[i] : mitk::ServiceEvent(); const mitk::ServiceEvent& seR = i < serviceEvents.size() ? serviceEvents[i] : mitk::ServiceEvent(); MITK_DEBUG << " " << seE << " - " << seR; } } else { for (std::size_t i = 0; i < seEvts.size(); ++i) { const mitk::ServiceEvent& seE = seEvts[i]; const mitk::ServiceEvent& seR = serviceEvents[i]; if (seE.GetType() != seR.GetType() || (!(seE.GetServiceReference() == seR.GetServiceReference()))) { listenState = false; MITK_DEBUG << "*** Wrong service event: " << seR << " expected " << seE; } } } moduleEvents.clear(); serviceEvents.clear(); return listenState; } private: mitk::ModuleContext* const mc; std::vector serviceEvents; std::vector moduleEvents; }; // Verify information from the ModuleInfo struct void frame005a(mitk::ModuleContext* mc) { mitk::Module* m = mc->GetModule(); // check expected headers MITK_TEST_CONDITION("MitkTestDriver" == m->GetName(), "Test module name"); // MITK_DEBUG << "Version: " << m->GetVersion(); MITK_TEST_CONDITION(mitk::ModuleVersion(0,1,0) == m->GetVersion(), "Test module version") } // Get context id, location and status of the module void frame010a(mitk::ModuleContext* mc) { mitk::Module* m = mc->GetModule(); long int contextid = m->GetModuleId(); MITK_DEBUG << "CONTEXT ID:" << contextid; std::string location = m->GetLocation(); MITK_DEBUG << "LOCATION:" << location; MITK_TEST_CONDITION(!location.empty(), "Test for non-empty module location") MITK_TEST_CONDITION(m->IsLoaded(), "Test for loaded flag") } //---------------------------------------------------------------------------- //Test result of GetService(mitk::ServiceReference()). Should throw std::invalid_argument void frame018a(mitk::ModuleContext* mc) { try { itk::LightObject* obj = mc->GetService(mitk::ServiceReference()); MITK_DEBUG << "Got service object = " << obj->GetNameOfClass() << ", excpected std::invalid_argument exception"; MITK_TEST_FAILED_MSG(<< "Got service object, excpected std::invalid_argument exception") } catch (const std::invalid_argument& ) {} catch (...) { MITK_TEST_FAILED_MSG(<< "Got wrong exception, expected std::invalid_argument") } } // Load libA and check that it exists and that the service it registers exists, // also check that the expected events occur void frame020a(mitk::ModuleContext* mc, ModuleListener& listener, mitk::SharedLibraryHandle& libA) { try { libA.Load(); } catch (const std::exception& e) { MITK_TEST_FAILED_MSG(<< "Load module exception: " << e.what()) } mitk::Module* moduleA = mitk::ModuleRegistry::GetModule("TestModuleA"); MITK_TEST_CONDITION_REQUIRED(moduleA != 0, "Test for existing moudle TestModuleA") MITK_TEST_CONDITION(moduleA->GetName() == "TestModuleA", "Test module name") // Check if libA registered the expected service try { mitk::ServiceReference sr1 = mc->GetServiceReference("org.mitk.TestModuleAService"); itk::LightObject* o1 = mc->GetService(sr1); MITK_TEST_CONDITION(o1 != 0, "Test if service object found"); try { MITK_TEST_CONDITION(mc->UngetService(sr1), "Test if Service UnGet returns true"); } catch (const std::logic_error le) { MITK_TEST_FAILED_MSG(<< "UnGetService exception: " << le.what()) } // check the listeners for events std::vector pEvts; pEvts.push_back(mitk::ModuleEvent(mitk::ModuleEvent::LOADING, moduleA)); pEvts.push_back(mitk::ModuleEvent(mitk::ModuleEvent::LOADED, moduleA)); std::vector seEvts; seEvts.push_back(mitk::ServiceEvent(mitk::ServiceEvent::REGISTERED, sr1)); MITK_TEST_CONDITION(listener.CheckListenerEvents(pEvts, seEvts), "Test for unexpected events"); } catch (const mitk::ServiceException& /*se*/) { MITK_TEST_FAILED_MSG(<< "test moudle, expected service not found"); } MITK_TEST_CONDITION(moduleA->IsLoaded() == true, "Test if loaded correctly"); } // Unload libA and check for correct events void frame030b(mitk::ModuleContext* mc, ModuleListener& listener, mitk::SharedLibraryHandle& libA) { mitk::Module* moduleA = mitk::ModuleRegistry::GetModule("TestModuleA"); MITK_TEST_CONDITION_REQUIRED(moduleA != 0, "Test for non-null module") mitk::ServiceReference sr1 = mc->GetServiceReference("org.mitk.TestModuleAService"); MITK_TEST_CONDITION(sr1, "Test for valid service reference") try { libA.Unload(); MITK_TEST_CONDITION(moduleA->IsLoaded() == false, "Test for unloaded state") } catch (const std::exception& e) { MITK_TEST_FAILED_MSG(<< "UnLoad module exception: " << e.what()) } std::vector pEvts; pEvts.push_back(mitk::ModuleEvent(mitk::ModuleEvent::UNLOADING, moduleA)); pEvts.push_back(mitk::ModuleEvent(mitk::ModuleEvent::UNLOADED, moduleA)); std::vector seEvts; seEvts.push_back(mitk::ServiceEvent(mitk::ServiceEvent::UNREGISTERING, sr1)); MITK_TEST_CONDITION(listener.CheckListenerEvents(pEvts, seEvts), "Test for unexpected events"); } struct LocalListener { void ServiceChanged(const mitk::ServiceEvent&) {} }; // Add a service listener with a broken LDAP filter to Get an exception void frame045a(mitk::ModuleContext* mc) { LocalListener sListen1; std::string brokenFilter = "A broken LDAP filter"; try { mc->AddServiceListener(&sListen1, &LocalListener::ServiceChanged, brokenFilter); } catch (const std::invalid_argument& /*ia*/) { //assertEquals("InvalidSyntaxException.GetFilter should be same as input string", brokenFilter, ise.GetFilter()); } catch (...) { MITK_TEST_FAILED_MSG(<< "test module, wrong exception on broken LDAP filter:"); } } int mitkModuleTest(int /*argc*/, char* /*argv*/[]) { MITK_TEST_BEGIN("ModuleTest"); mitk::ModuleContext* mc = mitk::GetModuleContext(); ModuleListener listener(mc); try { mc->AddModuleListener(&listener, &ModuleListener::ModuleChanged); } catch (const std::logic_error& ise) { MITK_TEST_OUTPUT( << "module listener registration failed " << ise.what() ); throw; } try { mc->AddServiceListener(&listener, &ModuleListener::ServiceChanged); } catch (const std::logic_error& ise) { MITK_TEST_OUTPUT( << "service listener registration failed " << ise.what() ); throw; } frame005a(mc); frame010a(mc); frame018a(mc); mitk::SharedLibraryHandle libA("TestModuleA"); frame020a(mc, listener, libA); frame030b(mc, listener, libA); frame045a(mc); mc->RemoveModuleListener(&listener, &ModuleListener::ModuleChanged); mc->RemoveServiceListener(&listener, &ModuleListener::ServiceChanged); MITK_TEST_END() }