1 /*=============================================================================
2 
3   Library: CTK
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 "ctkConfigurationImpl_p.h"
24 
25 #include "ctkConfigurationAdminFactory_p.h"
26 #include "ctkConfigurationStore_p.h"
27 
28 #include <service/cm/ctkConfigurationAdmin.h>
29 #include <ctkPluginConstants.h>
30 
31 #include <QThread>
32 
ctkConfigurationImpl(ctkConfigurationAdminFactory * configurationAdminFactory,ctkConfigurationStore * configurationStore,const QString & factoryPid,const QString & pid,const QString & pluginLocation)33 ctkConfigurationImpl::ctkConfigurationImpl(ctkConfigurationAdminFactory* configurationAdminFactory,
34                                            ctkConfigurationStore* configurationStore,
35                                            const QString& factoryPid, const QString& pid,
36                                            const QString& pluginLocation)
37   : configurationAdminFactory(configurationAdminFactory),
38     configurationStore(configurationStore), pluginLocation(pluginLocation),
39     factoryPid(factoryPid), pid(pid), deleted(false), lockedCount(0), lockHolder(0)
40 {
41 
42 }
43 
ctkConfigurationImpl(ctkConfigurationAdminFactory * configurationAdminFactory,ctkConfigurationStore * configurationStore,const ctkDictionary & dictionary)44 ctkConfigurationImpl::ctkConfigurationImpl(ctkConfigurationAdminFactory* configurationAdminFactory,
45                                            ctkConfigurationStore* configurationStore,
46                                            const ctkDictionary& dictionary)
47   : configurationAdminFactory(configurationAdminFactory),
48     configurationStore(configurationStore), deleted(false), lockedCount(0),
49     lockHolder(0)
50 {
51   pid = dictionary.value(ctkPluginConstants::SERVICE_PID).toString();
52   factoryPid = dictionary.value(ctkConfigurationAdmin::SERVICE_FACTORYPID).toString();
53   pluginLocation = dictionary.value(ctkConfigurationAdmin::SERVICE_PLUGINLOCATION).toString();
54   updateDictionary(dictionary);
55 }
56 
remove()57 void ctkConfigurationImpl::remove()
58 {
59   {
60     ctkConfigurationImplLocker l(this);
61     checkDeleted();
62     deleted = true;
63     configurationAdminFactory->notifyConfigurationDeleted(this, !factoryPid.isEmpty());
64     configurationAdminFactory->dispatchEvent(ctkConfigurationEvent::CM_DELETED, factoryPid, pid);
65   }
66   configurationStore->removeConfiguration(pid);
67 }
68 
getPluginLocation() const69 QString ctkConfigurationImpl::getPluginLocation() const
70 {
71   return getPluginLocation(true);
72 }
73 
getFactoryPid() const74 QString ctkConfigurationImpl::getFactoryPid() const
75 {
76   return getFactoryPid(true);
77 }
78 
getPid() const79 QString ctkConfigurationImpl::getPid() const
80 {
81   return getPid(true);
82 }
83 
getProperties() const84 ctkDictionary ctkConfigurationImpl::getProperties() const
85 {
86   ctkConfigurationImplLocker l(this);
87   checkDeleted();
88   if (dictionary.isEmpty())
89       return dictionary;
90 
91   ctkDictionary copy = dictionary;
92   copy.insert(ctkPluginConstants::SERVICE_PID, pid);
93   if (!factoryPid.isEmpty())
94   {
95     copy.insert(ctkConfigurationAdmin::SERVICE_FACTORYPID, factoryPid);
96   }
97 
98   return copy;
99 }
100 
setPluginLocation(const QString & pluginLocation)101 void ctkConfigurationImpl::setPluginLocation(const QString& pluginLocation)
102 {
103   ctkConfigurationImplLocker l(this);
104   checkDeleted();
105   configurationAdminFactory->checkConfigurationPermission();
106   this->pluginLocation = pluginLocation;
107   boundPlugin.clear(); // always reset the boundPlugin when setPluginLocation is called
108 }
109 
update()110 void ctkConfigurationImpl::update()
111 {
112   ctkConfigurationImplLocker l(this);
113   checkDeleted();
114   configurationStore->saveConfiguration(pid, this);
115   configurationAdminFactory->notifyConfigurationUpdated(this, !factoryPid.isEmpty());
116 }
117 
update(const ctkDictionary & properties)118 void ctkConfigurationImpl::update(const ctkDictionary& properties)
119 {
120   ctkConfigurationImplLocker l(this);
121   checkDeleted();
122   updateDictionary(properties);
123   configurationStore->saveConfiguration(pid, this);
124   configurationAdminFactory->notifyConfigurationUpdated(this, !factoryPid.isEmpty());
125   configurationAdminFactory->dispatchEvent(ctkConfigurationEvent::CM_UPDATED, factoryPid, pid);
126 }
127 
lock() const128 void ctkConfigurationImpl::lock() const
129 {
130   QMutexLocker lock(&mutex);
131   QThread* current = QThread::currentThread();
132   if (lockHolder != current)
133   {
134     while (lockedCount != 0)
135     {
136       waitCond.wait(&mutex);
137     }
138   }
139   ++lockedCount;
140   lockHolder = current;
141 }
142 
unlock() const143 void ctkConfigurationImpl::unlock() const
144 {
145   QMutexLocker lock(&mutex);
146   QThread* current = QThread::currentThread();
147   if (lockHolder != current)
148   {
149     throw ctkIllegalStateException("Thread not lock owner");
150   }
151 
152   --lockedCount;
153   if (lockedCount == 0)
154   {
155     lockHolder = 0;
156     waitCond.wakeOne();
157   }
158 }
159 
checkLocked() const160 void ctkConfigurationImpl::checkLocked() const
161 {
162   QMutexLocker lock(&mutex);
163   QThread* current = QThread::currentThread();
164   if (lockHolder != current)
165   {
166     throw ctkIllegalStateException("Thread not lock owner");
167   }
168 }
169 
bind(QSharedPointer<ctkPlugin> plugin)170 bool ctkConfigurationImpl::bind(QSharedPointer<ctkPlugin> plugin)
171 {
172   ctkConfigurationImplLocker l(this);
173   if (boundPlugin.isNull() && (pluginLocation.isEmpty() || pluginLocation == plugin->getLocation()))
174   {
175     boundPlugin = plugin;
176   }
177   return (boundPlugin == plugin);
178 }
179 
unbind(QSharedPointer<ctkPlugin> plugin)180 void ctkConfigurationImpl::unbind(QSharedPointer<ctkPlugin> plugin)
181 {
182   ctkConfigurationImplLocker l(this);
183   if (boundPlugin == plugin)
184   {
185     boundPlugin.clear();
186   }
187 }
188 
getPluginLocation(bool checkPermission) const189 QString ctkConfigurationImpl::getPluginLocation(bool checkPermission) const
190 {
191   ctkConfigurationImplLocker l(this);
192   checkDeleted();
193   if (checkPermission)
194   {
195     configurationAdminFactory->checkConfigurationPermission();
196   }
197 
198   if (!pluginLocation.isEmpty())
199   {
200     return pluginLocation;
201   }
202 
203   if (boundPlugin)
204   {
205     return boundPlugin->getLocation();
206   }
207 
208   return QString();
209 }
210 
getFactoryPid(bool checkDel) const211 QString ctkConfigurationImpl::getFactoryPid(bool checkDel) const
212 {
213   ctkConfigurationImplLocker l(this);
214   if (checkDel)
215   {
216     checkDeleted();
217   }
218   return factoryPid;
219 }
220 
getPid(bool checkDel) const221 QString ctkConfigurationImpl::getPid(bool checkDel) const
222 {
223   ctkConfigurationImplLocker l(this);
224   if (checkDel)
225   {
226     checkDeleted();
227   }
228   return pid;
229 }
230 
getAllProperties() const231 ctkDictionary ctkConfigurationImpl::getAllProperties() const
232 {
233   ctkConfigurationImplLocker l(this);
234   if (deleted)
235   {
236     return ctkDictionary();
237   }
238   ctkDictionary copy = getProperties();
239   if (copy.isEmpty())
240   {
241     return copy;
242   }
243 
244   QString boundLocation = getPluginLocation(false);
245   if (!boundLocation.isEmpty())
246   {
247     copy.insert(ctkConfigurationAdmin::SERVICE_PLUGINLOCATION, boundLocation);
248   }
249   return copy;
250 }
251 
isDeleted() const252 bool ctkConfigurationImpl::isDeleted() const
253 {
254   ctkConfigurationImplLocker l(this);
255   return deleted;
256 }
257 
checkDeleted() const258 void ctkConfigurationImpl::checkDeleted() const
259 {
260   if (deleted)
261     throw ctkIllegalStateException("deleted");
262 }
263 
updateDictionary(const ctkDictionary & properties)264 void ctkConfigurationImpl::updateDictionary(const ctkDictionary& properties)
265 {
266   ctkConfigurationDictionary newDictionary = properties;
267   newDictionary.remove(ctkPluginConstants::SERVICE_PID);
268   newDictionary.remove(ctkConfigurationAdmin::SERVICE_FACTORYPID);
269   newDictionary.remove(ctkConfigurationAdmin::SERVICE_PLUGINLOCATION);
270   dictionary = newDictionary;
271 }
272 
ctkConfigurationImplLocker(const ctkConfigurationImpl * impl)273 ctkConfigurationImplLocker::ctkConfigurationImplLocker(const ctkConfigurationImpl* impl)
274   : impl(impl)
275 {
276   if (impl) impl->lock();
277 }
278 
ctkConfigurationImplLocker(const QList<ctkConfigurationImplPtr> & implList)279 ctkConfigurationImplLocker::ctkConfigurationImplLocker(const QList<ctkConfigurationImplPtr>& implList)
280   : impl(0), implList(implList)
281 {
282   foreach(ctkConfigurationImplPtr i, this->implList)
283   {
284     if (i) i->lock();
285   }
286 }
287 
~ctkConfigurationImplLocker()288 ctkConfigurationImplLocker::~ctkConfigurationImplLocker()
289 {
290   if (impl) impl->unlock();
291   foreach(ctkConfigurationImplPtr i, implList)
292   {
293     if (i) i->unlock();
294   }
295 }
296