ctkPlugin.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  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 CTKPLUGIN_H
  16. #define CTKPLUGIN_H
  17. #include "ctkPluginContext.h"
  18. #include "ctkVersion.h"
  19. namespace ctk {
  20. class PluginArchive;
  21. class PluginFrameworkContext;
  22. class PluginPrivate;
  23. /**
  24. * An installed plugin in the Framework.
  25. *
  26. * <p>
  27. * A <code>%Plugin</code> object is the access point to define the lifecycle of
  28. * an installed plugin. Each plugin installed in the plugin environment must have
  29. * an associated <code>%Plugin</code> object.
  30. *
  31. * <p>
  32. * A plugin must have a unique identity, a <code>long</code>, chosen by the
  33. * Framework. This identity must not change during the lifecycle of a plugin,
  34. * even when the plugin is updated. Uninstalling and then reinstalling the
  35. * plugin must create a new unique identity.
  36. *
  37. * <p>
  38. * A plugin can be in one of six states:
  39. * <ul>
  40. * <li>{@link #UNINSTALLED}
  41. * <li>{@link #INSTALLED}
  42. * <li>{@link #RESOLVED}
  43. * <li>{@link #STARTING}
  44. * <li>{@link #STOPPING}
  45. * <li>{@link #ACTIVE}
  46. * </ul>
  47. * <p>
  48. * They can be ORed together using the <code>States</code> type to
  49. * determine if a plugin is in one of the valid states.
  50. *
  51. * <p>
  52. * A plugin should only execute code when its state is one of
  53. * <code>STARTING</code>, <code>ACTIVE</code>, or <code>STOPPING</code>.
  54. * An <code>UNINSTALLED</code> plugin can not be set to another state; it is a
  55. * zombie and can only be reached because references are kept somewhere.
  56. *
  57. * <p>
  58. * The Framework is the only entity that is allowed to create
  59. * <code>%Plugin</code> objects, and these objects are only valid within the
  60. * Framework that created them.
  61. *
  62. * @threadsafe
  63. */
  64. class CTK_PLUGINFW_EXPORT Plugin {
  65. Q_DECLARE_PRIVATE(Plugin)
  66. public:
  67. enum State {
  68. /**
  69. * The plugin is uninstalled and may not be used.
  70. *
  71. * <p>
  72. * The <code>UNINSTALLED</code> state is only visible after a plugin is
  73. * uninstalled; the plugin is in an unusable state but references to the
  74. * <code>%Plugin</code> object may still be available and used for
  75. * introspection.
  76. */
  77. UNINSTALLED,
  78. /**
  79. * The plugin is installed but not yet resolved.
  80. *
  81. * <p>
  82. * A plugin is in the <code>INSTALLED</code> state when it has been
  83. * installed in the Framework but is not or cannot be resolved.
  84. * <p>
  85. * This state is visible if the plugin's code dependencies are not resolved.
  86. * The Framework may attempt to resolve an <code>INSTALLED</code> plugin's
  87. * code dependencies and move the plugin to the <code>RESOLVED</code>
  88. * state.
  89. */
  90. INSTALLED,
  91. /**
  92. * The plugin is resolved and is able to be started.
  93. *
  94. * <p>
  95. * A plugin is in the <code>RESOLVED</code> state when the Framework has
  96. * successfully resolved the plugin's code dependencies. These dependencies
  97. * include:
  98. * <ul>
  99. * <li>The plugin's required plugin dependencies from its
  100. * {@link PluginConstants::REQUIRE_PLUGIN} Manifest header.
  101. * </ul>
  102. * <p>
  103. * Note that the plugin is not active yet. A plugin must be put in the
  104. * <code>RESOLVED</code> state before it can be started. The Framework may
  105. * attempt to resolve a plugin at any time.
  106. */
  107. RESOLVED,
  108. /**
  109. * The plugin is in the process of starting.
  110. *
  111. * <p>
  112. * A plugin is in the <code>STARTING</code> state when its
  113. * {@link #start(const Options&) start} method is active. A plugin must be in this
  114. * state when the plugin's {@link PluginActivator::start} method is called. If the
  115. * <code>PluginActivator::start</code> method completes without exception,
  116. * then the plugin has successfully started and must move to the
  117. * <code>ACTIVE</code> state.
  118. * <p>
  119. * If the plugin does not have a
  120. * {@link PluginConstants#ACTIVATION_EAGER eager activation policy}, then the
  121. * plugin may remain in this state for some time until the activation is
  122. * triggered.
  123. */
  124. STARTING,
  125. /**
  126. * The plugin is in the process of stopping.
  127. *
  128. * <p>
  129. * A plugin is in the <code>STOPPING</code> state when its
  130. * {@link #stop(const Option&) stop} method is active. A plugin must be in this state
  131. * when the plugin's {@link PluginActivator::stop} method is called. When the
  132. * <code>PluginActivator::stop</code> method completes the plugin is
  133. * stopped and must move to the <code>RESOLVED</code> state.
  134. */
  135. STOPPING,
  136. /**
  137. * The plugin is now running.
  138. *
  139. * <p>
  140. * A plugin is in the <code>ACTIVE</code> state when it has been
  141. * successfully started and activated.
  142. */
  143. ACTIVE
  144. };
  145. /**
  146. * Represents an ORed combination of plugin states.
  147. *
  148. * @see #State
  149. */
  150. Q_DECLARE_FLAGS(States, State)
  151. enum StartOption {
  152. /**
  153. * The plugin start operation is transient and the persistent autostart
  154. * setting of the plugin is not modified.
  155. *
  156. * <p>
  157. * This option may be set when calling {@link #start(const StartOptions&)} to notify the
  158. * framework that the autostart setting of the plugin must not be modified.
  159. * If this option is not set, then the autostart setting of the plugin is
  160. * modified.
  161. *
  162. * @see #start(const StartOptions&)
  163. */
  164. START_TRANSIENT,
  165. /**
  166. * The plugin start operation must activate the plugin according to the
  167. * plugin's declared
  168. * {@link PluginConstants#PLUGIN_ACTIVATIONPOLICY activation policy}.
  169. *
  170. * <p>
  171. * This bit may be set when calling {@link #start(const StartOptions&)} to notify the
  172. * framework that the plugin must be activated using the plugin's declared
  173. * activation policy.
  174. *
  175. * @see PluginConstants#PLUGIN_ACTIVATIONPOLICY
  176. * @see #start(const StartOptions&)
  177. */
  178. START_ACTIVATION_POLICY
  179. };
  180. /**
  181. * Represents an ORed combination of start options.
  182. *
  183. * @see #StartOption
  184. */
  185. Q_DECLARE_FLAGS(StartOptions, StartOption)
  186. enum StopOption {
  187. /**
  188. * The plugin stop is transient and the persistent autostart setting of the
  189. * plugin is not modified.
  190. *
  191. * <p>
  192. * This option may be set when calling {@link #stop(const StopOptions&)} to notify the
  193. * framework that the autostart setting of the plugin must not be modified.
  194. * If this option is not set, then the autostart setting of the plugin is
  195. * modified.
  196. *
  197. * @see #stop(const StopOptions&)
  198. */
  199. STOP_TRANSIENT
  200. };
  201. /**
  202. * Represents an ORed combination of stop options.
  203. *
  204. * @see #StopOption
  205. */
  206. Q_DECLARE_FLAGS(StopOptions, StopOption)
  207. virtual ~Plugin();
  208. /**
  209. * Returns this plugin's current state.
  210. *
  211. * <p>
  212. * A plugin can be in only one state at any time.
  213. *
  214. * @return An element of <code>UNINSTALLED</code>,<code>INSTALLED</code>,
  215. * <code>RESOLVED</code>,<code>STARTING</code>,
  216. * <code>STOPPING</code>,<code>ACTIVE</code>.
  217. */
  218. State getState() const;
  219. /**
  220. * Starts this plugin.
  221. *
  222. * <p>
  223. * If this plugin's state is <code>UNINSTALLED</code> then an
  224. * <code>std::logic_error</code> is thrown.
  225. * <p>
  226. * The following steps are required to start this bundle:
  227. * <ol>
  228. * <li>If this plugin is in the process of being activated or deactivated
  229. * then this method must wait for activation or deactivation to complete
  230. * before continuing. If this does not occur in a reasonable time, a
  231. * <code>PluginException</code> is thrown to indicate this plugin was unable
  232. * to be started.
  233. *
  234. * <li>If this plugin's state is <code>ACTIVE</code> then this method
  235. * returns immediately.
  236. *
  237. * <li>If the {@link #START_TRANSIENT} option is not set then set this
  238. * plugin's autostart setting to <em>Started with declared activation</em>
  239. * if the {@link #START_ACTIVATION_POLICY} option is set or
  240. * <em>Started with lazy activation</em> if not set. When the Framework is
  241. * restarted and this plugin's autostart setting is not <em>Stopped</em>,
  242. * this plugin must be automatically started.
  243. *
  244. * <li>If this plugin's state is not <code>RESOLVED</code>, an attempt is
  245. * made to resolve this plugin. If the Framework cannot resolve this plugin,
  246. * a <code>PluginException</code> is thrown.
  247. *
  248. * <li>If the {@link #START_ACTIVATION_POLICY} option is not set then:
  249. * <ul>
  250. * <li>If this plugin's state is <code>STARTING</code> then this method
  251. * returns immediately.
  252. * <li>This plugin's state is set to <code>STARTING</code>.
  253. * <li>A plugin event of type {@link PluginEvent::LAZY_ACTIVATION} is fired.
  254. * <li>This method returns immediately and the remaining steps will be
  255. * followed when this plugin's activation is later triggered.
  256. * </ul>
  257. * If the {@link #START_ACTIVATION_POLICY} option is set and this
  258. * plugin's declared activation policy is {@link PluginConstants#ACTIVATION_EAGER
  259. * eager} then:
  260. * <i></i>
  261. * <li>This plugin's state is set to <code>STARTING</code>.
  262. *
  263. * <li>A plugin event of type {@link PluginEvent::STARTING} is fired.
  264. *
  265. * <li>The {@link PluginActivator::start} method of this plugin's
  266. * <code>PluginActivator</code>, is called. If the
  267. * <code>PluginActivator</code> throws an exception then:
  268. * <ul>
  269. * <li>This plugin's state is set to <code>STOPPING</code>.
  270. * <li>A plugin event of type {@link PluginEvent::STOPPING} is fired.
  271. * <li>Any services registered by this plugin must be unregistered.
  272. * <li>Any services used by this plugin must be released.
  273. * <li>Any listeners registered by this plugin must be removed.
  274. * <li>This plugin's state is set to <code>RESOLVED</code>.
  275. * <li>A plugin event of type {@link PluginEvent::STOPPED} is fired.
  276. * <li>A <code>PluginException</code> is then thrown.
  277. * </ul>
  278. * <i></i>
  279. * <li>If this plugin's state is <code>UNINSTALLED</code>, because this
  280. * plugin was uninstalled while the <code>PluginActivator::start</code>
  281. * method was running, a <code>PluginException</code> is thrown.
  282. *
  283. * <li>This plugin's state is set to <code>ACTIVE</code>.
  284. *
  285. * <li>A plugin event of type {@link PluginEvent::STARTED} is fired.
  286. * </ol>
  287. *
  288. * <b>Preconditions </b>
  289. * <ul>
  290. * <li><code>getState()</code> in { <code>INSTALLED</code>,
  291. * <code>RESOLVED</code>, <code>STARTING</code> }
  292. * or { <code>INSTALLED</code>, <code>RESOLVED</code> }
  293. * if this plugin has a eager activation policy.
  294. * </ul>
  295. * <b>Postconditions, no exceptions thrown </b>
  296. * <ul>
  297. * <li>%Plugin autostart setting is modified unless the
  298. * {@link #START_TRANSIENT} option was set.
  299. * <li><code>getState()</code> in { <code>ACTIVE</code> }
  300. * if the eager activation policy was used.
  301. * <li><code>PluginActivator::start()</code> has been called and did not
  302. * throw an exception if the eager policy was used.
  303. * </ul>
  304. * <b>Postconditions, when an exception is thrown </b>
  305. * <ul>
  306. * <li>Depending on when the exception occurred, plugin autostart setting is
  307. * modified unless the {@link #START_TRANSIENT} option was set.
  308. * <li><code>getState()</code> not in { <code>STARTING</code>,
  309. * <code>ACTIVE</code> }.
  310. * </ul>
  311. *
  312. * @param options The options for starting this plugin. See
  313. * {@link #START_TRANSIENT} and {@link #START_ACTIVATION_POLICY}. The
  314. * Framework must ignore unrecognized options.
  315. * @throws PluginException If this plugin could not be started. This could
  316. * be because a code dependency could not be resolved or the
  317. * <code>PluginActivator</code> could not be loaded or
  318. * threw an exception.
  319. * @throws std::logic_error If this plugin has been uninstalled or this
  320. * plugin tries to change its own state.
  321. */
  322. virtual void start(const StartOptions& options = 0);
  323. /**
  324. * Stops this plugin.
  325. *
  326. * <p>
  327. * The following steps are required to stop a plugin:
  328. * <ol>
  329. * <li>If this plugin's state is <code>UNINSTALLED</code> then an
  330. * <code>std::logic_error</code> is thrown.
  331. *
  332. * <li>If this plugin is in the process of being activated or deactivated
  333. * then this method must wait for activation or deactivation to complete
  334. * before continuing. If this does not occur in a reasonable time, a
  335. * <code>PluginException</code> is thrown to indicate this plugin was unable
  336. * to be stopped.
  337. * <li>If the {@link #STOP_TRANSIENT} option is not set then then set this
  338. * plugin's persistent autostart setting to <em>Stopped</em>. When the
  339. * Framework is restarted and this plugin's autostart setting is
  340. * <em>Stopped</em>, this bundle must not be automatically started.
  341. *
  342. * <li>If this plugin's state is not <code>STARTING</code> or
  343. * <code>ACTIVE</code> then this method returns immediately.
  344. *
  345. * <li>This plugin's state is set to <code>STOPPING</code>.
  346. *
  347. * <li>A plugin event of type {@link PluginEvent::STOPPING} is fired.
  348. *
  349. * <li>If this plugin's state was <code>ACTIVE</code> prior to setting the
  350. * state to <code>STOPPING</code>, the {@link PluginActivator#stop} method
  351. * of this plugin's <code>PluginActivator</code> is
  352. * called. If that method throws an exception, this method must continue to
  353. * stop this plugin and a <code>PluginException</code> must be thrown after
  354. * completion of the remaining steps.
  355. *
  356. * <li>Any services registered by this plugin must be unregistered.
  357. * <li>Any services used by this plugin must be released.
  358. * <li>Any listeners registered by this plugin must be removed.
  359. *
  360. * <li>If this plugin's state is <code>UNINSTALLED</code>, because this
  361. * plugin was uninstalled while the <code>PluginActivator::stop</code> method
  362. * was running, a <code>PluginException</code> must be thrown.
  363. *
  364. * <li>This plugin's state is set to <code>RESOLVED</code>.
  365. *
  366. * <li>A plugin event of type {@link PluginEvent::STOPPED} is fired.
  367. * </ol>
  368. *
  369. * <b>Preconditions </b>
  370. * <ul>
  371. * <li><code>getState()</code> in { <code>ACTIVE</code> }.
  372. * </ul>
  373. * <b>Postconditions, no exceptions thrown </b>
  374. * <ul>
  375. * <li>Plugin autostart setting is modified unless the
  376. * {@link #STOP_TRANSIENT} option was set.
  377. * <li><code>getState()</code> not in &#x007B; <code>ACTIVE</code>,
  378. * <code>STOPPING</code> &#x007D;.
  379. * <li><code>PluginActivator::stop</code> has been called and did not throw
  380. * an exception.
  381. * </ul>
  382. * <b>Postconditions, when an exception is thrown </b>
  383. * <ul>
  384. * <li>Plugin autostart setting is modified unless the
  385. * {@link #STOP_TRANSIENT} option was set.
  386. * </ul>
  387. *
  388. * @param options The options for stoping this bundle. See
  389. * {@link #STOP_TRANSIENT}.
  390. * @throws PluginException If this plugin's <code>PluginActivator</code>
  391. * threw an exception.
  392. * @throws std::logic_error If this plugin has been uninstalled or this
  393. * plugin tries to change its own state.
  394. */
  395. virtual void stop(const StopOptions& options = 0);
  396. /**
  397. * Returns this plugin's {@link PluginContext}. The returned
  398. * <code>PluginContext</code> can be used by the caller to act on behalf
  399. * of this plugin.
  400. *
  401. * <p>
  402. * If this plugin is not in the {@link #STARTING}, {@link #ACTIVE}, or
  403. * {@link #STOPPING} states, then this
  404. * plugin has no valid <code>PluginContext</code>. This method will
  405. * return <code>0</code> if this plugin has no valid
  406. * <code>PluginContext</code>.
  407. *
  408. * @return A <code>PluginContext</code> for this plugin or
  409. * <code>0</code> if this plugin has no valid
  410. * <code>PluginContext</code>.
  411. */
  412. PluginContext* getPluginContext() const;
  413. /**
  414. * Returns this plugin's unique identifier. This plugin is assigned a unique
  415. * identifier by the Framework when it was installed in the plugin
  416. * environment.
  417. *
  418. * <p>
  419. * A plugin's unique identifier has the following attributes:
  420. * <ul>
  421. * <li>Is unique and persistent.
  422. * <li>Is a <code>long</code>.
  423. * <li>Its value is not reused for another plugin, even after a plugin is
  424. * uninstalled.
  425. * <li>Does not change while a plugin remains installed.
  426. * <li>Does not change when a plugin is updated.
  427. * </ul>
  428. *
  429. * <p>
  430. * This method must continue to return this plugin's unique identifier while
  431. * this plugin is in the <code>UNINSTALLED</code> state.
  432. *
  433. * @return The unique identifier of this plugin.
  434. */
  435. long getPluginId() const;
  436. /**
  437. * Returns this plugin's location identifier.
  438. *
  439. * <p>
  440. * The location identifier is the location passed to
  441. * <code>PluginContext::installPlugin</code> when a plugin is installed.
  442. * The location identifier does not change while this plugin remains
  443. * installed, even if this plugin is updated.
  444. *
  445. * <p>
  446. * This method must continue to return this plugin's location identifier
  447. * while this plugin is in the <code>UNINSTALLED</code> state.
  448. *
  449. * @return The string representation of this plugin's location identifier.
  450. */
  451. QString getLocation() const;
  452. /**
  453. * Returns this plugin's Manifest headers and values. This method returns
  454. * all the Manifest headers and values from the main section of this
  455. * bundle's Manifest file; that is, all lines prior to the first named section.
  456. *
  457. * TODO: documentation about manifest value internationalization
  458. *
  459. * <p>
  460. * For example, the following Manifest headers and values are included if
  461. * they are present in the Manifest file:
  462. *
  463. * <pre>
  464. * Plugin-Name
  465. * Plugin-Vendor
  466. * Plugin-Version
  467. * Plugin-Description
  468. * Plugin-DocURL
  469. * Plugin-ContactAddress
  470. * </pre>
  471. *
  472. * <p>
  473. * This method must continue to return Manifest header information while
  474. * this plugin is in the <code>UNINSTALLED</code> state.
  475. *
  476. * @return A <code>QHash<Qstring, QString></code> object containing this plugin's
  477. * Manifest headers and values.
  478. */
  479. virtual QHash<QString, QString> getHeaders();
  480. /**
  481. * Returns the symbolic name of this plugin as specified by its
  482. * <code>Plugin-SymbolicName</code> manifest header. The plugin symbolic
  483. * name together with a version must identify a unique plugin. The plugin
  484. * symbolic name should be based on the reverse domain name naming
  485. * convention like that used for java packages.
  486. *
  487. * <p>
  488. * This method must continue to return this plugin's symbolic name while
  489. * this plugin is in the <code>UNINSTALLED</code> state.
  490. *
  491. * @return The symbolic name of this plugin or a null QString if this
  492. * plugin does not have a symbolic name.
  493. */
  494. QString getSymbolicName() const;
  495. /**
  496. * Returns a list of all the files and directories
  497. * within this plugin whose longest sub-path matches the
  498. * specified path.
  499. * <p>
  500. * The specified path is always relative to the root of this plugin
  501. * (the plugins symbolic name) and may begin with a &quot;/&quot;.
  502. * A path value of &quot;/&quot; indicates the root of this plugin.
  503. * <p>
  504. * Returned paths indicating subdirectory paths end with a &quot;/&quot;.
  505. * The returned paths are all relative to the root of this plugin and must
  506. * not begin with &quot;/&quot;.
  507. * <p>
  508. *
  509. * @param path The path name for which to return resource paths.
  510. * @return A list of the resource paths (<code>QString</code>
  511. * objects) or an empty list if no entry could be found.
  512. * @throws std::logic_error If this plugin has been
  513. * uninstalled.
  514. */
  515. virtual QStringList getResourceList(const QString& path) const;
  516. /**
  517. * Returns a QByteArray containing a Qt resource located at the
  518. * specified path in this plugin.
  519. * <p>
  520. * The specified path is always relative to the root of this plugin
  521. * (the plugins symbolic name) and may
  522. * begin with &quot;/&quot;. A path value of &quot;/&quot; indicates the
  523. * root of this plugin.
  524. * <p>
  525. *
  526. * @param path The path name of the resource.
  527. * @return A QString to the resource, or a null QString if no resource could be
  528. * found.
  529. * @throws std::logic_error If this plugin has been
  530. * uninstalled.
  531. */
  532. virtual QByteArray getResource(const QString& path) const;
  533. /**
  534. * Returns the version of this plugin as specified by its
  535. * <code>Plugin-Version</code> manifest header. If this plugin does not have a
  536. * specified version then {@link Version#emptyVersion} is returned.
  537. *
  538. * <p>
  539. * This method must continue to return this plugin's version while
  540. * this plugin is in the <code>UNINSTALLED</code> state.
  541. *
  542. * @return The version of this plugin.
  543. */
  544. Version getVersion() const;
  545. protected:
  546. friend class PluginFramework;
  547. friend class PluginFrameworkContext;
  548. friend class Plugins;
  549. PluginPrivate * const d_ptr;
  550. Plugin(PluginFrameworkContext* fw, PluginArchive* ba);
  551. Plugin(PluginPrivate& dd);
  552. };
  553. }
  554. Q_DECLARE_OPERATORS_FOR_FLAGS(ctk::Plugin::States)
  555. #endif // CTKPLUGIN_H