Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
usServiceTracker.tpp
Go to the documentation of this file.
1 /*=============================================================================
2 
3  Library: CppMicroServices
4 
5  Copyright (c) German Cancer Research Center,
6  Division of Medical and Biological Informatics
7 
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
11 
12  http://www.apache.org/licenses/LICENSE-2.0
13 
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.
19 
20 =============================================================================*/
21 
22 
23 #include "usServiceTrackerPrivate.h"
24 #include "usTrackedService_p.h"
25 #include "usServiceException.h"
26 #include "usModuleContext.h"
27 
28 #include <string>
29 #include <stdexcept>
30 #include <limits>
31 
32 US_BEGIN_NAMESPACE
33 
34 template<class S, class TTT>
35 ServiceTracker<S,TTT>::~ServiceTracker()
36 {
37  Close();
38  delete d;
39 }
40 
41 #ifdef _MSC_VER
42 #pragma warning(push)
43 #pragma warning(disable:4355)
44 #endif
45 
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))
51 {
52 }
53 
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))
58 {
59 }
60 
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))
65 {
66 }
67 
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))
71 {
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");
74 }
75 
76 #ifdef _MSC_VER
77 #pragma warning(pop)
78 #endif
79 
80 template<class S, class TTT>
81 void ServiceTracker<S,TTT>::Open()
82 {
83  _TrackedService* t;
84  {
85  US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
86  if (d->trackedService)
87  {
88  return;
89  }
90 
91  US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker<S,TTT>::Open: " << d->filter;
92 
93  t = new _TrackedService(this, d->customizer);
94  {
95  US_UNUSED(typename _TrackedService::Lock(*t));
96  try {
97  d->context->AddServiceListener(t, &_TrackedService::ServiceChanged, d->listenerFilter);
98  std::vector<ServiceReferenceType> references;
99  if (!d->trackClass.empty())
100  {
101  references = d->GetInitialReferences(d->trackClass, std::string());
102  }
103  else
104  {
105  if (d->trackReference.GetModule() != 0)
106  {
107  references.push_back(d->trackReference);
108  }
109  else
110  { /* user supplied filter */
111  references = d->GetInitialReferences(std::string(),
112  (d->listenerFilter.empty()) ? d->filter.ToString() : d->listenerFilter);
113  }
114  }
115  /* set tracked with the initial references */
116  t->SetInitial(references);
117  }
118  catch (const std::invalid_argument& e)
119  {
120  throw std::runtime_error(std::string("unexpected std::invalid_argument exception: ")
121  + e.what());
122  }
123  }
124  d->trackedService = t;
125  }
126  /* Call tracked outside of synchronized region */
127  t->TrackInitial(); /* process the initial references */
128 }
129 
130 template<class S, class TTT>
131 void ServiceTracker<S,TTT>::Close()
132 {
133  _TrackedService* outgoing;
134  std::vector<ServiceReferenceType> references;
135  {
136  US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
137  outgoing = d->trackedService;
138  if (outgoing == 0)
139  {
140  return;
141  }
142  US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker<S,TTT>::close:" << d->filter;
143  outgoing->Close();
144  references = GetServiceReferences();
145  d->trackedService = 0;
146  try
147  {
148  d->context->RemoveServiceListener(outgoing, &_TrackedService::ServiceChanged);
149  }
150  catch (const std::logic_error& /*e*/)
151  {
152  /* In case the context was stopped. */
153  }
154  }
155  d->Modified(); /* clear the cache */
156  {
157  US_UNUSED(typename _TrackedService::Lock(outgoing));
158  outgoing->NotifyAll(); /* wake up any waiters */
159  }
160  for(typename std::vector<ServiceReferenceType>::const_iterator ref = references.begin();
161  ref != references.end(); ++ref)
162  {
163  outgoing->Untrack(*ref, ServiceEvent());
164  }
165 
166  if (d->DEBUG_OUTPUT)
167  {
168  US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
169  if ((d->cachedReference.GetModule() == 0) && !TTT::IsValid(d->cachedService))
170  {
171  US_DEBUG(true) << "ServiceTracker<S,TTT>::close[cached cleared]:"
172  << d->filter;
173  }
174  }
175 
176  delete outgoing;
177  d->trackedService = 0;
178 }
179 
180 template<class S, class TTT>
181 typename ServiceTracker<S,TTT>::T
182 ServiceTracker<S,TTT>::WaitForService(unsigned long timeoutMillis)
183 {
184  T object = GetService();
185  while (!TTT::IsValid(object))
186  {
187  _TrackedService* t = d->Tracked();
188  if (t == 0)
189  { /* if ServiceTracker is not open */
190  return TTT::DefaultValue();
191  }
192  {
193  US_UNUSED(typename _TrackedService::Lock(t));
194  if (t->Size() == 0)
195  {
196  t->Wait(timeoutMillis);
197  }
198  }
199  object = GetService();
200  }
201  return object;
202 }
203 
204 template<class S, class TTT>
205 std::vector<typename ServiceTracker<S,TTT>::ServiceReferenceType>
206 ServiceTracker<S,TTT>::GetServiceReferences() const
207 {
208  std::vector<ServiceReferenceType> refs;
209  _TrackedService* t = d->Tracked();
210  if (t == 0)
211  { /* if ServiceTracker is not open */
212  return refs;
213  }
214  {
215  US_UNUSED(typename _TrackedService::Lock(t));
216  d->GetServiceReferences_unlocked(refs, t);
217  }
218  return refs;
219 }
220 
221 template<class S, class TTT>
222 typename ServiceTracker<S,TTT>::ServiceReferenceType
223 ServiceTracker<S,TTT>::GetServiceReference() const
224 {
225  ServiceReferenceType reference;
226  {
227  US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
228  reference = d->cachedReference;
229  }
230  if (reference.GetModule() != 0)
231  {
232  US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker<S,TTT>::getServiceReference[cached]:"
233  << d->filter;
234  return reference;
235  }
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();
239  if (length == 0)
240  { /* if no service is being tracked */
241  throw ServiceException("No service is being tracked");
242  }
243  typename std::vector<ServiceReferenceType>::const_iterator selectedRef = references.begin();
244  if (length > 1)
245  { /* if more than one service, select highest ranking */
246  std::vector<int> rankings(length);
247  int count = 0;
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++)
251  {
252  Any rankingAny = refIter->GetProperty(ServiceConstants::SERVICE_RANKING());
253  int ranking = 0;
254  if (rankingAny.Type() == typeid(int))
255  {
256  ranking = any_cast<int>(rankingAny);
257  }
258 
259  rankings[i] = ranking;
260  if (ranking > maxRanking)
261  {
262  selectedRef = refIter;
263  maxRanking = ranking;
264  count = 1;
265  }
266  else
267  {
268  if (ranking == maxRanking)
269  {
270  count++;
271  }
272  }
273  ++refIter;
274  }
275  if (count > 1)
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++)
280  {
281  if (rankings[i] == maxRanking)
282  {
283  Any idAny = refIter->GetProperty(ServiceConstants::SERVICE_ID());
284  long int id = 0;
285  if (idAny.Type() == typeid(long int))
286  {
287  id = any_cast<long int>(idAny);
288  }
289  if (id < minId)
290  {
291  selectedRef = refIter;
292  minId = id;
293  }
294  }
295  ++refIter;
296  }
297  }
298  }
299 
300  {
301  US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
302  d->cachedReference = *selectedRef;
303  return d->cachedReference;
304  }
305 }
306 
307 template<class S, class TTT>
308 typename ServiceTracker<S,TTT>::T
309 ServiceTracker<S,TTT>::GetService(const ServiceReferenceType& reference) const
310 {
311  _TrackedService* t = d->Tracked();
312  if (t == 0)
313  { /* if ServiceTracker is not open */
314  return TTT::DefaultValue();
315  }
316  {
317  US_UNUSED(typename _TrackedService::Lock(t));
318  return t->GetCustomizedObject(reference);
319  }
320 }
321 
322 template<class S, class TTT>
323 std::vector<typename ServiceTracker<S,TTT>::T> ServiceTracker<S,TTT>::GetServices() const
324 {
325  std::vector<T> services;
326  _TrackedService* t = d->Tracked();
327  if (t == 0)
328  { /* if ServiceTracker is not open */
329  return services;
330  }
331  {
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)
337  {
338  services.push_back(t->GetCustomizedObject(*ref));
339  }
340  }
341  return services;
342 }
343 
344 template<class S, class TTT>
345 typename ServiceTracker<S,TTT>::T
346 ServiceTracker<S,TTT>::GetService() const
347 {
348  {
349  US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
350  const T& service = d->cachedService;
351  if (TTT::IsValid(service))
352  {
353  US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker<S,TTT>::getService[cached]:"
354  << d->filter;
355  return service;
356  }
357  }
358  US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker<S,TTT>::getService:" << d->filter;
359 
360  try
361  {
362  ServiceReferenceType reference = GetServiceReference();
363  if (reference.GetModule() == 0)
364  {
365  return TTT::DefaultValue();
366  }
367  {
368  US_UNUSED(typename _ServiceTrackerPrivate::Lock(d));
369  return d->cachedService = GetService(reference);
370  }
371  }
372  catch (const ServiceException&)
373  {
374  return TTT::DefaultValue();
375  }
376 }
377 
378 template<class S, class TTT>
379 void ServiceTracker<S,TTT>::Remove(const ServiceReferenceType& reference)
380 {
381  _TrackedService* t = d->Tracked();
382  if (t == 0)
383  { /* if ServiceTracker is not open */
384  return;
385  }
386  t->Untrack(reference, ServiceEvent());
387 }
388 
389 template<class S, class TTT>
390 int ServiceTracker<S,TTT>::Size() const
391 {
392  _TrackedService* t = d->Tracked();
393  if (t == 0)
394  { /* if ServiceTracker is not open */
395  return 0;
396  }
397  {
398  US_UNUSED(typename _TrackedService::Lock(t));
399  return static_cast<int>(t->Size());
400  }
401 }
402 
403 template<class S, class TTT>
404 int ServiceTracker<S,TTT>::GetTrackingCount() const
405 {
406  _TrackedService* t = d->Tracked();
407  if (t == 0)
408  { /* if ServiceTracker is not open */
409  return -1;
410  }
411  {
412  US_UNUSED(typename _TrackedService::Lock(t));
413  return t->GetTrackingCount();
414  }
415 }
416 
417 template<class S, class TTT>
418 void ServiceTracker<S,TTT>::GetTracked(TrackingMap& map) const
419 {
420  _TrackedService* t = d->Tracked();
421  if (t == 0)
422  { /* if ServiceTracker is not open */
423  return;
424  }
425  {
426  US_UNUSED(typename _TrackedService::Lock(t));
427  t->CopyEntries(map);
428  }
429 }
430 
431 template<class S, class TTT>
432 bool ServiceTracker<S,TTT>::IsEmpty() const
433 {
434  _TrackedService* t = d->Tracked();
435  if (t == 0)
436  { /* if ServiceTracker is not open */
437  return true;
438  }
439  {
440  US_UNUSED(typename _TrackedService::Lock(t));
441  return t->IsEmpty();
442  }
443 }
444 
445 template<class S, class TTT>
446 typename ServiceTracker<S,TTT>::T
447 ServiceTracker<S,TTT>::AddingService(const ServiceReferenceType& reference)
448 {
449  return TTT::ConvertToTrackedType(d->context->GetService(reference));
450 }
451 
452 template<class S, class TTT>
453 void ServiceTracker<S,TTT>::ModifiedService(const ServiceReferenceType& /*reference*/, T /*service*/)
454 {
455  /* do nothing */
456 }
457 
458 template<class S, class TTT>
459 void ServiceTracker<S,TTT>::RemovedService(const ServiceReferenceType& reference, T /*service*/)
460 {
461  d->context->UngetService(reference);
462 }
463 
464 US_END_NAMESPACE