ctkManagedServiceTracker.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*=============================================================================
  2. Library: CTK
  3. Copyright (c) German Cancer Research Center,
  4. Division of Medical and Biological Informatics
  5. Licensed under the Apache License, Version 2.0 (the "License");
  6. you may not use this file except in compliance with the License.
  7. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. =============================================================================*/
  15. #include "ctkManagedServiceTracker_p.h"
  16. #include <service/cm/ctkConfigurationException.h>
  17. #include <ctkLogService.h>
  18. #include "ctkConfigurationImpl_p.h"
  19. #include "ctkConfigurationAdminFactory_p.h"
  20. #include <QRunnable>
  21. ctkManagedServiceTracker::ctkManagedServiceTracker(ctkConfigurationAdminFactory* configurationAdminFactory,
  22. ctkConfigurationStore* configurationStore,
  23. ctkPluginContext* context)
  24. : ctkServiceTracker<ctkManagedService*>(context),
  25. context(context),
  26. configurationAdminFactory(configurationAdminFactory),
  27. configurationStore(configurationStore),
  28. queue("ctkManagedService Update Queue")
  29. {
  30. }
  31. ctkManagedService* ctkManagedServiceTracker::addingService(const ctkServiceReference& reference)
  32. {
  33. QString pid = reference.getProperty(ctkPluginConstants::SERVICE_PID).toString();
  34. if (pid.isEmpty())
  35. return 0;
  36. ctkManagedService* service = context->getService<ctkManagedService>(reference);
  37. if (service == 0)
  38. return 0;
  39. {
  40. QMutexLocker lock(&configurationStoreMutex);
  41. addManagedService(reference, pid, service);
  42. }
  43. return service;
  44. }
  45. void ctkManagedServiceTracker::modifiedService(const ctkServiceReference& reference, ctkManagedService* service)
  46. {
  47. QString pid = reference.getProperty(ctkPluginConstants::SERVICE_PID).toString();
  48. {
  49. QMutexLocker lock(&configurationStoreMutex);
  50. if (getManagedService(pid) == service)
  51. return;
  52. QString previousPid = getPidForManagedService(service);
  53. removeManagedService(reference, previousPid);
  54. addingService(reference);
  55. }
  56. }
  57. void ctkManagedServiceTracker::removedService(const ctkServiceReference& reference, ctkManagedService* service)
  58. {
  59. Q_UNUSED(service)
  60. QString pid = reference.getProperty(ctkPluginConstants::SERVICE_PID).toString();
  61. {
  62. QMutexLocker lock(&configurationStoreMutex);
  63. removeManagedService(reference, pid);
  64. }
  65. context->ungetService(reference);
  66. }
  67. void ctkManagedServiceTracker::notifyDeleted(ctkConfigurationImpl* config)
  68. {
  69. config->checkLocked();
  70. QString pid = config->getPid(false);
  71. ctkServiceReference reference = getManagedServiceReference(pid);
  72. if (reference && config->bind(reference.getPlugin()))
  73. asynchUpdated(getManagedService(pid), ctkDictionary());
  74. }
  75. void ctkManagedServiceTracker::notifyUpdated(ctkConfigurationImpl* config) {
  76. config->checkLocked();
  77. QString pid = config->getPid();
  78. ctkServiceReference reference = getManagedServiceReference(pid);
  79. if (reference && config->bind(reference.getPlugin()))
  80. {
  81. ctkDictionary properties = config->getProperties();
  82. configurationAdminFactory->modifyConfiguration(reference, properties);
  83. asynchUpdated(getManagedService(pid), properties);
  84. }
  85. }
  86. void ctkManagedServiceTracker::addManagedService(const ctkServiceReference& reference,
  87. const QString& pid,
  88. ctkManagedService* service)
  89. {
  90. ctkConfigurationImplPtr config = configurationStore->findConfiguration(pid);
  91. if (config.isNull() && trackManagedService(pid, reference, service))
  92. {
  93. asynchUpdated(service, ctkDictionary());
  94. }
  95. else
  96. {
  97. ctkConfigurationImplLocker lock(config.data());
  98. if (trackManagedService(pid, reference, service))
  99. {
  100. if (!config->getFactoryPid().isEmpty())
  101. {
  102. CTK_WARN(configurationAdminFactory->getLogService())
  103. << "Configuration for " << ctkPluginConstants::SERVICE_PID << "="
  104. << pid << " should only be used by a ctkManagedServiceFactory";
  105. }
  106. else if (config->isDeleted())
  107. {
  108. asynchUpdated(service, ctkDictionary());
  109. }
  110. else if (config->bind(reference.getPlugin()))
  111. {
  112. ctkDictionary properties = config->getProperties();
  113. configurationAdminFactory->modifyConfiguration(reference, properties);
  114. asynchUpdated(service, properties);
  115. }
  116. else
  117. {
  118. CTK_WARN(configurationAdminFactory->getLogService())
  119. << "Configuration for " << ctkPluginConstants::SERVICE_PID << "="
  120. << pid << " could not be bound to " << reference.getPlugin()->getLocation();
  121. }
  122. }
  123. }
  124. }
  125. void ctkManagedServiceTracker::removeManagedService(const ctkServiceReference& reference,
  126. const QString& pid)
  127. {
  128. ctkConfigurationImplPtr config = configurationStore->findConfiguration(pid);
  129. if (config.isNull())
  130. {
  131. untrackManagedService(pid, reference);
  132. }
  133. else
  134. {
  135. ctkConfigurationImplLocker lock(config.data());
  136. untrackManagedService(pid, reference);
  137. }
  138. }
  139. bool ctkManagedServiceTracker::trackManagedService(const QString& pid, const ctkServiceReference& reference,
  140. ctkManagedService* service)
  141. {
  142. QMutexLocker lock(&managedServiceMutex);
  143. if (managedServiceReferences.contains(pid))
  144. {
  145. CTK_WARN(configurationAdminFactory->getLogService())
  146. << "ctkManagedService already registered for " << ctkPluginConstants::SERVICE_PID
  147. << "=" << pid;
  148. return false;
  149. }
  150. managedServiceReferences.insert(pid, reference);
  151. managedServices.insert(pid, service);
  152. return true;
  153. }
  154. void ctkManagedServiceTracker::untrackManagedService(const QString& pid, const ctkServiceReference& reference)
  155. {
  156. Q_UNUSED(reference)
  157. QMutexLocker lock(&managedServiceMutex);
  158. managedServiceReferences.remove(pid);
  159. managedServices.remove(pid);
  160. }
  161. ctkManagedService* ctkManagedServiceTracker::getManagedService(const QString& pid) const
  162. {
  163. QMutexLocker lock(&managedServiceMutex);
  164. return managedServices.value(pid);
  165. }
  166. ctkServiceReference ctkManagedServiceTracker::getManagedServiceReference(const QString& pid) const
  167. {
  168. QMutexLocker lock(&managedServiceMutex);
  169. return managedServiceReferences.value(pid);
  170. }
  171. QString ctkManagedServiceTracker::getPidForManagedService(ctkManagedService* service) const
  172. {
  173. QMutexLocker lock(&managedServiceMutex);
  174. QHash<QString, ctkManagedService*>::ConstIterator end = managedServices.end();
  175. QHash<QString, ctkManagedService*>::ConstIterator it;
  176. for (it = managedServices.begin(); it != end; ++it)
  177. {
  178. if (it.value() == service)
  179. return it.key();
  180. }
  181. return QString();
  182. }
  183. class _AsynchUpdateRunnable : public QRunnable
  184. {
  185. public:
  186. _AsynchUpdateRunnable(ctkManagedService* service,
  187. const ctkDictionary& properties,
  188. ctkLogService* log)
  189. : service(service), properties(properties), log(log)
  190. {
  191. }
  192. void run()
  193. {
  194. try
  195. {
  196. service->updated(properties);
  197. }
  198. catch (const ctkConfigurationException* e)
  199. {
  200. // we might consider doing more for ctkConfigurationExceptions
  201. CTK_ERROR_EXC(log, e);
  202. }
  203. catch (const std::exception* e)
  204. {
  205. CTK_ERROR_EXC(log, e);
  206. }
  207. }
  208. private:
  209. ctkManagedService* service;
  210. const ctkDictionary properties;
  211. ctkLogService * const log;
  212. };
  213. void ctkManagedServiceTracker::asynchUpdated(ctkManagedService* service, const ctkDictionary& properties)
  214. {
  215. queue.put(new _AsynchUpdateRunnable(service, properties, configurationAdminFactory->getLogService()));
  216. }