ctkPluginContext.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /*=============================================================================
  2. Library: CTK
  3. Copyright (c) 2010 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. #ifndef CTKPLUGINCONTEXT_H_
  16. #define CTKPLUGINCONTEXT_H_
  17. #include <QHash>
  18. #include <QString>
  19. #include <QVariant>
  20. #include <QUrl>
  21. #include "ctkPluginFramework_global.h"
  22. #include "ctkPluginEvent.h"
  23. #include "CTKPluginFrameworkExport.h"
  24. // CTK class forward declarations
  25. class ctkPlugin;
  26. class ctkPluginPrivate;
  27. class ctkServiceRegistration;
  28. class ctkServiceReference;
  29. class ctkPluginContextPrivate;
  30. /**
  31. * A plugin's execution context within the Framework. The context is used to
  32. * grant access to other methods so that this plugin can interact with the
  33. * Framework.
  34. *
  35. * <p>
  36. * <code>ctkPluginContext</code> methods allow a plugin to:
  37. * <ul>
  38. * <li>Subscribe to events published by the Framework.
  39. * <li>Register service objects with the Framework service registry.
  40. * <li>Retrieve <code>ServiceReferences</code> from the Framework service
  41. * registry.
  42. * <li>Get and release service objects for a referenced service.
  43. * <li>Install new plugins in the Framework.
  44. * <li>Get the list of plugins installed in the Framework.
  45. * <li>Get the {@link ctkPlugin} object for a plugin.
  46. * <li>Create <code>QFile</code> objects for files in a persistent storage
  47. * area provided for the plugin by the Framework.
  48. * </ul>
  49. *
  50. * <p>
  51. * A <code>ctkPluginContext</code> object will be created and provided to the
  52. * plugin associated with this context when it is started using the
  53. * {@link ctkPluginActivator::start} method. The same <code>ctkPluginContext</code>
  54. * object will be passed to the plugin associated with this context when it is
  55. * stopped using the {@link ctkPluginActivator::stop} method. A
  56. * <code>ctkPluginContext</code> object is generally for the private use of its
  57. * associated plugin and is not meant to be shared with other plugins in the
  58. * plugin environment.
  59. *
  60. * <p>
  61. * The <code>ctkPlugin</code> object associated with a <code>ctkPluginContext</code>
  62. * object is called the <em>context plugin</em>.
  63. *
  64. * <p>
  65. * The <code>ctkPluginContext</code> object is only valid during the execution of
  66. * its context plugin; that is, during the period from when the context plugin
  67. * is in the <code>STARTING</code>, <code>STOPPING</code>, and
  68. * <code>ACTIVE</code> plugin states. If the <code>ctkPluginContext</code>
  69. * object is used subsequently, a <code>std::logic_error</code> must be
  70. * thrown. The <code>ctkPluginContext</code> object must never be reused after
  71. * its context plugin is stopped.
  72. *
  73. * <p>
  74. * The Framework is the only entity that can create <code>ctkPluginContext</code>
  75. * objects and they are only valid within the Framework that created them.
  76. *
  77. * @threadsafe
  78. */
  79. class CTK_PLUGINFW_EXPORT ctkPluginContext
  80. {
  81. Q_DECLARE_PRIVATE(ctkPluginContext)
  82. public:
  83. ~ctkPluginContext();
  84. /**
  85. * Returns the <code>ctkPlugin</code> object associated with this
  86. * <code>ctkPluginContext</code>. This plugin is called the context plugin.
  87. *
  88. * @return The <code>ctkPlugin</code> object associated with this
  89. * <code>ctkPluginContext</code>.
  90. * @throws std::logic_error If this ctkPluginContext is no
  91. * longer valid.
  92. */
  93. ctkPlugin* getPlugin() const;
  94. /**
  95. * Returns the plugin with the specified identifier.
  96. *
  97. * @param id The identifier of the plugin to retrieve.
  98. * @return A <code>ctkPlugin</code> object or <code>0</code> if the
  99. * identifier does not match any installed plugin.
  100. */
  101. ctkPlugin* getPlugin(long id) const;
  102. /**
  103. * Returns a list of all installed plugins.
  104. * <p>
  105. * This method returns a list of all plugins installed in the plugin
  106. * environment at the time of the call to this method. However, since the
  107. * Framework is a very dynamic environment, plugins can be installed or
  108. * uninstalled at anytime.
  109. *
  110. * @return A QList of <code>ctkPlugin</code> objects, one object per
  111. * installed plugin.
  112. */
  113. QList<ctkPlugin*> getPlugins() const;
  114. /**
  115. * Registers the specified service object with the specified properties
  116. * under the specified class names into the Framework. A
  117. * <code>ctkServiceRegistration</code> object is returned. The
  118. * <code>ctkServiceRegistration</code> object is for the private use of the
  119. * plugin registering the service and should not be shared with other
  120. * plugins. The registering plugin is defined to be the context plugin.
  121. * Other plugins can locate the service by using either the
  122. * {@link #getServiceReferences} or {@link #getServiceReference} method.
  123. *
  124. * <p>
  125. * A plugin can register a service object that implements the
  126. * {@link ctkServiceFactory} interface to have more flexibility in providing
  127. * service objects to other plugins.
  128. *
  129. * <p>
  130. * The following steps are required to register a service:
  131. * <ol>
  132. * <li>If <code>service</code> is not a <code>ctkServiceFactory</code>, an
  133. * <code>std::invalid_argument</code> is thrown if <code>service</code>
  134. * is not an instance of all the specified class names.
  135. * <li>The Framework adds the following service properties to the service
  136. * properties from the specified <code>ServiceProperties</code> (which may be
  137. * omitted): <br/>
  138. * A property named {@link ctkPluginConstants#SERVICE_ID} identifying the
  139. * registration number of the service <br/>
  140. * A property named {@link ctkPluginConstants#OBJECTCLASS} containing all the
  141. * specified classes. <br/>
  142. * Properties with these names in the specified <code>ServiceProperties</code> will
  143. * be ignored.
  144. * <li>The service is added to the Framework service registry and may now be
  145. * used by other plugins.
  146. * <li>A service event of type {@link ServiceEvent#REGISTERED} is fired.
  147. * <li>A <code>ctkServiceRegistration</code> object for this registration is
  148. * returned.
  149. * </ol>
  150. *
  151. * @param clazzes The class names under which the service can be located.
  152. * The class names will be stored in the service's
  153. * properties under the key {@link ctkPluginConstants#OBJECTCLASS}.
  154. * @param service The service object or a <code>ctkServiceFactory</code>
  155. * object.
  156. * @param properties The properties for this service. The keys in the
  157. * properties object must all be <code>QString</code> objects. See
  158. * {@link ctkPluginConstants} for a list of standard service property keys.
  159. * Changes should not be made to this object after calling this
  160. * method. To update the service's properties the
  161. * {@link ctkServiceRegistration::setProperties} method must be called.
  162. * The set of properties may be omitted if the service has
  163. * no properties.
  164. * @return A <code>ctkServiceRegistration</code> object for use by the plugin
  165. * registering the service to update the service's properties or to
  166. * unregister the service.
  167. * @throws std::invalid_argument If one of the following is true:
  168. * <ul>
  169. * <li><code>service</code> is <code>0</code>. <li><code>service
  170. * </code> is not a <code>ctkServiceFactory</code> object and is not an
  171. * instance of all the named classes in <code>clazzes</code>. <li>
  172. * <code>properties</code> contains case variants of the same key
  173. * name.
  174. * </ul>
  175. * @throws std::logic_error If this ctkPluginContext is no longer valid.
  176. * @see ctkServiceRegistration
  177. * @see ctkServiceFactory
  178. */
  179. ctkServiceRegistration* registerService(const QStringList& clazzes, QObject* service, const ServiceProperties& properties = ServiceProperties());
  180. /**
  181. * Returns a list of <code>ctkServiceReference</code> objects. The returned
  182. * list contains services that
  183. * were registered under the specified class and match the specified filter
  184. * expression.
  185. *
  186. * <p>
  187. * The list is valid at the time of the call to this method. However since
  188. * the Framework is a very dynamic environment, services can be modified or
  189. * unregistered at any time.
  190. *
  191. * <p>
  192. * The specified <code>filter</code> expression is used to select the
  193. * registered services whose service properties contain keys and values
  194. * which satisfy the filter expression. See {@link Filter} for a description
  195. * of the filter syntax. If the specified <code>filter</code> is
  196. * empty, all registered services are considered to match the
  197. * filter. If the specified <code>filter</code> expression cannot be parsed,
  198. * an {@link std::invalid_argument} will be thrown with a human readable
  199. * message where the filter became unparsable.
  200. *
  201. * <p>
  202. * The result is a list of <code>ctkServiceReference</code> objects for all
  203. * services that meet all of the following conditions:
  204. * <ul>
  205. * <li>If the specified class name, <code>clazz</code>, is not
  206. * empty, the service must have been registered with the
  207. * specified class name. The complete list of class names with which a
  208. * service was registered is available from the service's
  209. * {@link PlugincConstants::OBJECTCLASS objectClass} property.
  210. * <li>If the specified <code>filter</code> is not empty, the
  211. * filter expression must match the service.
  212. * </ul>
  213. *
  214. * @param clazz The class name with which the service was registered or
  215. * an empty string for all services.
  216. * @param filter The filter expression or empty for all
  217. * services.
  218. * @return A list of <code>ctkServiceReference</code> objects or
  219. * an empty list if no services are registered which satisfy the
  220. * search.
  221. * @throws std::invalid_argument If the specified <code>filter</code>
  222. * contains an invalid filter expression that cannot be parsed.
  223. * @throws std::logic_error If this ctkPluginContext is no longer valid.
  224. */
  225. QList<ctkServiceReference> getServiceReferences(const QString& clazz, const QString& filter = QString());
  226. /**
  227. * Returns a <code>ctkServiceReference</code> object for a service that
  228. * implements and was registered under the specified class.
  229. *
  230. * <p>
  231. * The returned <code>ctkServiceReference</code> object is valid at the time of
  232. * the call to this method. However as the Framework is a very dynamic
  233. * environment, services can be modified or unregistered at any time.
  234. *
  235. * <p>
  236. * This method is the same as calling
  237. * {@link ctkPluginContext::getServiceReferences(const QString&, const QString&)} with an
  238. * empty filter expression. It is provided as a convenience for
  239. * when the caller is interested in any service that implements the
  240. * specified class.
  241. * <p>
  242. * If multiple such services exist, the service with the highest ranking (as
  243. * specified in its {@link ctkPluginConstants::SERVICE_RANKING} property) is returned.
  244. * <p>
  245. * If there is a tie in ranking, the service with the lowest service ID (as
  246. * specified in its {@link ctkPluginConstants::SERVICE_ID} property); that is, the
  247. * service that was registered first is returned.
  248. *
  249. * @param clazz The class name with which the service was registered.
  250. * @return A <code>ctkServiceReference</code> object, or <code>0</code> if
  251. * no services are registered which implement the named class.
  252. * @throws std::logic_error If this ctkPluginContext is no longer valid.
  253. * @throws ctkServiceException It no service was registered under the given class name.
  254. * @see #getServiceReferences(const QString&, const QString&)
  255. */
  256. ctkServiceReference getServiceReference(const QString& clazz);
  257. /**
  258. * Returns the service object referenced by the specified
  259. * <code>ctkServiceReference</code> object.
  260. * <p>
  261. * A plugin's use of a service is tracked by the plugin's use count of that
  262. * service. Each time a service's service object is returned by
  263. * {@link #getService(ctkServiceReference*)} the context plugin's use count for
  264. * that service is incremented by one. Each time the service is released by
  265. * {@link #ungetService(ctkServiceReference*)} the context plugin's use count
  266. * for that service is decremented by one.
  267. * <p>
  268. * When a plugin's use count for a service drops to zero, the plugin should
  269. * no longer use that service.
  270. *
  271. * <p>
  272. * This method will always return <code>0</code> when the service
  273. * associated with this <code>reference</code> has been unregistered.
  274. *
  275. * <p>
  276. * The following steps are required to get the service object:
  277. * <ol>
  278. * <li>If the service has been unregistered, <code>0</code> is returned.
  279. * <li>The context plugin's use count for this service is incremented by
  280. * one.
  281. * <li>If the context plugin's use count for the service is currently one
  282. * and the service was registered with an object implementing the
  283. * <code>ctkServiceFactory</code> interface, the
  284. * {@link ctkServiceFactory::getService(ctkPlugin*, ctkServiceRegistration*)} method is
  285. * called to create a service object for the context plugin. This service
  286. * object is cached by the Framework. While the context plugin's use count
  287. * for the service is greater than zero, subsequent calls to get the
  288. * services's service object for the context plugin will return the cached
  289. * service object. <br>
  290. * If the service object returned by the <code>ctkServiceFactory</code> object
  291. * is not an instance of all the classes named when the service
  292. * was registered or the <code>ctkServiceFactory</code> object throws an
  293. * exception, <code>0</code> is returned and a Framework event of type
  294. * {@link ctkPluginFrameworkEvent::ERROR} containing a {@link ctkServiceException}
  295. * describing the error is fired.
  296. * <li>The service object for the service is returned.
  297. * </ol>
  298. *
  299. * @param reference A reference to the service.
  300. * @return A service object for the service associated with
  301. * <code>reference</code> or <code>0</code> if the service is not
  302. * registered, the service object returned by a
  303. * <code>ctkServiceFactory</code> does not implement the classes under
  304. * which it was registered or the <code>ctkServiceFactory</code> threw
  305. * an exception.
  306. * @throws std::logic_error If this ctkPluginContext is no
  307. * longer valid.
  308. * @throws std::invalid_argument If the specified
  309. * <code>ctkServiceReference</code> was not created by the same
  310. * framework instance as this <code>ctkPluginContext</code>.
  311. * @see #ungetService(ctkServiceReference*)
  312. * @see ctkServiceFactory
  313. */
  314. QObject* getService(ctkServiceReference reference);
  315. /**
  316. * Installs a plugin from the specified <code>QIODevice</code> object.
  317. *
  318. * <p>
  319. * If the specified <code>QIODevice</code> is <code>null</code>, the
  320. * Framework must create the <code>QIODevice</code> from which to read the
  321. * plugin by interpreting, in an implementation dependent manner, the
  322. * specified <code>location</code>.
  323. *
  324. * <p>
  325. * The specified <code>location</code> identifier will be used as the
  326. * identity of the plugin. Every installed plugin is uniquely identified by
  327. * its location identifier which is typically in the form of a URL.
  328. *
  329. * <p>
  330. * The following steps are required to install a plugin:
  331. * <ol>
  332. * <li>If a plugin containing the same location identifier is already
  333. * installed, the <code>ctkPlugin</code> object for that plugin is returned.
  334. *
  335. * <li>The plugin's content is read from the input stream. If this fails, a
  336. * {@link ctkPluginException} is thrown.
  337. *
  338. * <li>The plugin's associated resources are allocated. The associated
  339. * resources minimally consist of a unique identifier and a persistent
  340. * storage area. If this step fails, a <code>ctkPluginException</code>
  341. * is thrown.
  342. *
  343. * <li>The plugin's state is set to <code>INSTALLED</code>.
  344. *
  345. * <li>A plugin event of type {@link ctkPluginEvent#INSTALLED} is fired.
  346. *
  347. * <li>The <code>ctkPlugin</code> object for the newly or previously installed
  348. * plugin is returned.
  349. * </ol>
  350. *
  351. * <b>Postconditions, no exceptions thrown </b>
  352. * <ul>
  353. * <li><code>getState()</code> in &#x007B; <code>INSTALLED</code>,
  354. * <code>RESOLVED</code> &#x007D;.
  355. * <li>Plugin has a unique ID.
  356. * </ul>
  357. * <b>Postconditions, when an exception is thrown </b>
  358. * <ul>
  359. * <li>Plugin is not installed and no trace of the plugin exists.
  360. * </ul>
  361. *
  362. * @param location The location identifier of the plugin to install.
  363. * @param input The <code>QIODevice</code> object from which this plugin
  364. * will be read or <code>null</code> to indicate the Framework must
  365. * create the I/O device from the specified location identifier.
  366. * The I/O device must always be closed when this method completes,
  367. * even if an exception is thrown.
  368. * @return The <code>ctkPlugin</code> object of the installed plugin.
  369. * @throws ctkPluginException If the I/O device cannot be read or the
  370. * installation failed.
  371. * @throws std::logic_error If this ctkPluginContext is no longer valid.
  372. */
  373. ctkPlugin* installPlugin(const QUrl& location, QIODevice* in = 0);
  374. bool connectPluginListener(const QObject* receiver, const char* method, Qt::ConnectionType type = Qt::QueuedConnection);
  375. bool connectFrameworkListener(const QObject* receiver, const char* method, Qt::ConnectionType type = Qt::QueuedConnection);
  376. protected:
  377. friend class ctkPluginFrameworkPrivate;
  378. friend class ctkPlugin;
  379. friend class ctkPluginPrivate;
  380. ctkPluginContext(ctkPluginPrivate* plugin);
  381. ctkPluginContextPrivate * const d_ptr;
  382. };
  383. #endif /* CTKPLUGINCONTEXT_H_ */