1 /*=============================================================================
3 Library: CppMicroServices
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics
8 Licensed under the Apache License, Version 2.0 (the "License");
9 you may not use this file except in compliance with the License.
10 You may obtain a copy of the License at
12 http://www.apache.org/licenses/LICENSE-2.0
14 Unless required by applicable law or agreed to in writing, software
15 distributed under the License is distributed on an "AS IS" BASIS,
16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 See the License for the specific language governing permissions and
18 limitations under the License.
20 =============================================================================*/
23 #include "usServiceTrackerPrivate.h"
24 #include "usTrackedService_p.h"
25 #include "usServiceException.h"
26 #include "usModuleContext.h"
34 template<class S, class TTT>
35 ServiceTracker<S,TTT>::~ServiceTracker()
43 #pragma warning(disable:4355)
46 template<class S, class TTT>
47 ServiceTracker<S,TTT>::ServiceTracker(ModuleContext* context,
48 const ServiceReferenceType& reference,
49 _ServiceTrackerCustomizer* customizer)
50 : d(new _ServiceTrackerPrivate(this, context, reference, customizer))
54 template<class S, class TTT>
55 ServiceTracker<S,TTT>::ServiceTracker(ModuleContext* context, const std::string& clazz,
56 _ServiceTrackerCustomizer* customizer)
57 : d(new _ServiceTrackerPrivate(this, context, clazz, customizer))
61 template<class S, class TTT>
62 ServiceTracker<S,TTT>::ServiceTracker(ModuleContext* context, const LDAPFilter& filter,
63 _ServiceTrackerCustomizer* customizer)
64 : d(new _ServiceTrackerPrivate(this, context, filter, customizer))
68 template<class S, class TTT>
69 ServiceTracker<S,TTT>::ServiceTracker(ModuleContext *context, _ServiceTrackerCustomizer* customizer)
70 : d(new _ServiceTrackerPrivate(this, context, us_service_interface_iid<S>(), customizer))
72 std::string clazz = us_service_interface_iid<S>();
73 if (clazz.empty()) throw ServiceException("The service interface class has no US_DECLARE_SERVICE_INTERFACE macro");
80 template<class S, class TTT>
81 void ServiceTracker<S,TTT>::Open()
85 US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
86 if (d->trackedService)
91 US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker<S,TTT>::Open: " << d->filter;
93 t = new _TrackedService(this, d->customizer);
95 US_UNUSED(typename _TrackedService::Lock(*t));
97 d->context->AddServiceListener(t, &_TrackedService::ServiceChanged, d->listenerFilter);
98 std::vector<ServiceReferenceType> references;
99 if (!d->trackClass.empty())
101 references = d->GetInitialReferences(d->trackClass, std::string());
105 if (d->trackReference.GetModule() != 0)
107 references.push_back(d->trackReference);
110 { /* user supplied filter */
111 references = d->GetInitialReferences(std::string(),
112 (d->listenerFilter.empty()) ? d->filter.ToString() : d->listenerFilter);
115 /* set tracked with the initial references */
116 t->SetInitial(references);
118 catch (const std::invalid_argument& e)
120 throw std::runtime_error(std::string("unexpected std::invalid_argument exception: ")
124 d->trackedService = t;
126 /* Call tracked outside of synchronized region */
127 t->TrackInitial(); /* process the initial references */
130 template<class S, class TTT>
131 void ServiceTracker<S,TTT>::Close()
133 _TrackedService* outgoing;
134 std::vector<ServiceReferenceType> references;
136 US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
137 outgoing = d->trackedService;
142 US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker<S,TTT>::close:" << d->filter;
144 references = GetServiceReferences();
145 d->trackedService = 0;
148 d->context->RemoveServiceListener(outgoing, &_TrackedService::ServiceChanged);
150 catch (const std::logic_error& /*e*/)
152 /* In case the context was stopped. */
155 d->Modified(); /* clear the cache */
157 US_UNUSED(typename _TrackedService::Lock(outgoing));
158 outgoing->NotifyAll(); /* wake up any waiters */
160 for(typename std::vector<ServiceReferenceType>::const_iterator ref = references.begin();
161 ref != references.end(); ++ref)
163 outgoing->Untrack(*ref, ServiceEvent());
168 US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
169 if ((d->cachedReference.GetModule() == 0) && !TTT::IsValid(d->cachedService))
171 US_DEBUG(true) << "ServiceTracker<S,TTT>::close[cached cleared]:"
177 d->trackedService = 0;
180 template<class S, class TTT>
181 typename ServiceTracker<S,TTT>::T
182 ServiceTracker<S,TTT>::WaitForService(unsigned long timeoutMillis)
184 T object = GetService();
185 while (!TTT::IsValid(object))
187 _TrackedService* t = d->Tracked();
189 { /* if ServiceTracker is not open */
190 return TTT::DefaultValue();
193 US_UNUSED(typename _TrackedService::Lock(t));
196 t->Wait(timeoutMillis);
199 object = GetService();
204 template<class S, class TTT>
205 std::vector<typename ServiceTracker<S,TTT>::ServiceReferenceType>
206 ServiceTracker<S,TTT>::GetServiceReferences() const
208 std::vector<ServiceReferenceType> refs;
209 _TrackedService* t = d->Tracked();
211 { /* if ServiceTracker is not open */
215 US_UNUSED(typename _TrackedService::Lock(t));
216 d->GetServiceReferences_unlocked(refs, t);
221 template<class S, class TTT>
222 typename ServiceTracker<S,TTT>::ServiceReferenceType
223 ServiceTracker<S,TTT>::GetServiceReference() const
225 ServiceReferenceType reference;
227 US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
228 reference = d->cachedReference;
230 if (reference.GetModule() != 0)
232 US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker<S,TTT>::getServiceReference[cached]:"
236 US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker<S,TTT>::getServiceReference:" << d->filter;
237 std::vector<ServiceReferenceType> references = GetServiceReferences();
238 std::size_t length = references.size();
240 { /* if no service is being tracked */
241 throw ServiceException("No service is being tracked");
243 typename std::vector<ServiceReferenceType>::const_iterator selectedRef = references.begin();
245 { /* if more than one service, select highest ranking */
246 std::vector<int> rankings(length);
248 int maxRanking = std::numeric_limits<int>::min();
249 typename std::vector<ServiceReferenceType>::const_iterator refIter = references.begin();
250 for (std::size_t i = 0; i < length; i++)
252 Any rankingAny = refIter->GetProperty(ServiceConstants::SERVICE_RANKING());
254 if (rankingAny.Type() == typeid(int))
256 ranking = any_cast<int>(rankingAny);
259 rankings[i] = ranking;
260 if (ranking > maxRanking)
262 selectedRef = refIter;
263 maxRanking = ranking;
268 if (ranking == maxRanking)
276 { /* if still more than one service, select lowest id */
277 long int minId = std::numeric_limits<long int>::max();
278 refIter = references.begin();
279 for (std::size_t i = 0; i < length; i++)
281 if (rankings[i] == maxRanking)
283 Any idAny = refIter->GetProperty(ServiceConstants::SERVICE_ID());
285 if (idAny.Type() == typeid(long int))
287 id = any_cast<long int>(idAny);
291 selectedRef = refIter;
301 US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
302 d->cachedReference = *selectedRef;
303 return d->cachedReference;
307 template<class S, class TTT>
308 typename ServiceTracker<S,TTT>::T
309 ServiceTracker<S,TTT>::GetService(const ServiceReferenceType& reference) const
311 _TrackedService* t = d->Tracked();
313 { /* if ServiceTracker is not open */
314 return TTT::DefaultValue();
317 US_UNUSED(typename _TrackedService::Lock(t));
318 return t->GetCustomizedObject(reference);
322 template<class S, class TTT>
323 std::vector<typename ServiceTracker<S,TTT>::T> ServiceTracker<S,TTT>::GetServices() const
325 std::vector<T> services;
326 _TrackedService* t = d->Tracked();
328 { /* if ServiceTracker is not open */
332 US_UNUSED(typename _TrackedService::Lock(t));
333 std::vector<ServiceReferenceType> references;
334 d->GetServiceReferences_unlocked(references, t);
335 for(typename std::vector<ServiceReferenceType>::const_iterator ref = references.begin();
336 ref != references.end(); ++ref)
338 services.push_back(t->GetCustomizedObject(*ref));
344 template<class S, class TTT>
345 typename ServiceTracker<S,TTT>::T
346 ServiceTracker<S,TTT>::GetService() const
349 US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
350 const T& service = d->cachedService;
351 if (TTT::IsValid(service))
353 US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker<S,TTT>::getService[cached]:"
358 US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker<S,TTT>::getService:" << d->filter;
362 ServiceReferenceType reference = GetServiceReference();
363 if (reference.GetModule() == 0)
365 return TTT::DefaultValue();
368 US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
369 return d->cachedService = GetService(reference);
372 catch (const ServiceException&)
374 return TTT::DefaultValue();
378 template<class S, class TTT>
379 void ServiceTracker<S,TTT>::Remove(const ServiceReferenceType& reference)
381 _TrackedService* t = d->Tracked();
383 { /* if ServiceTracker is not open */
386 t->Untrack(reference, ServiceEvent());
389 template<class S, class TTT>
390 int ServiceTracker<S,TTT>::Size() const
392 _TrackedService* t = d->Tracked();
394 { /* if ServiceTracker is not open */
398 US_UNUSED(typename _TrackedService::Lock(t));
399 return static_cast<int>(t->Size());
403 template<class S, class TTT>
404 int ServiceTracker<S,TTT>::GetTrackingCount() const
406 _TrackedService* t = d->Tracked();
408 { /* if ServiceTracker is not open */
412 US_UNUSED(typename _TrackedService::Lock(t));
413 return t->GetTrackingCount();
417 template<class S, class TTT>
418 void ServiceTracker<S,TTT>::GetTracked(TrackingMap& map) const
420 _TrackedService* t = d->Tracked();
422 { /* if ServiceTracker is not open */
426 US_UNUSED(typename _TrackedService::Lock(t));
431 template<class S, class TTT>
432 bool ServiceTracker<S,TTT>::IsEmpty() const
434 _TrackedService* t = d->Tracked();
436 { /* if ServiceTracker is not open */
440 US_UNUSED(typename _TrackedService::Lock(t));
445 template<class S, class TTT>
446 typename ServiceTracker<S,TTT>::T
447 ServiceTracker<S,TTT>::AddingService(const ServiceReferenceType& reference)
449 return TTT::ConvertToTrackedType(d->context->GetService(reference));
452 template<class S, class TTT>
453 void ServiceTracker<S,TTT>::ModifiedService(const ServiceReferenceType& /*reference*/, T /*service*/)
458 template<class S, class TTT>
459 void ServiceTracker<S,TTT>::RemovedService(const ServiceReferenceType& reference, T /*service*/)
461 d->context->UngetService(reference);