ctkPluginStorageSQL_p.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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. #ifndef ctkPluginStorageSQL_P_H
  16. #define ctkPluginStorageSQL_P_H
  17. #include "ctkPluginStorage_p.h"
  18. #include <QMutex>
  19. #include <QLibrary>
  20. #include <QSqlQuery>
  21. #include <QDebug>
  22. #include <QSqlError>
  23. #include <QPluginLoader>
  24. #include <QDirIterator>
  25. #include <QThreadStorage>
  26. // CTK class forward declarations
  27. class ctkPluginFrameworkContext;
  28. class ctkPluginArchiveSQL;
  29. /**
  30. * \ingroup PluginFramework
  31. */
  32. class ctkPluginStorageSQL : public ctkPluginStorage
  33. {
  34. public:
  35. /**
  36. * Create a container for all plugin data in this framework.
  37. * Try to restore all saved plugin archive state.
  38. *
  39. */
  40. ctkPluginStorageSQL(ctkPluginFrameworkContext* framework);
  41. virtual ~ctkPluginStorageSQL();
  42. /**
  43. * Inserts a new plugin into the database. This method assumes that
  44. * the an entry with the same \a location and \a localPath does not
  45. * yet exist in the database.
  46. *
  47. * @param location The URL to the plugin.
  48. * @param updateLocation Location of the updated plugin.
  49. * @param localPath The path to the plugin library on the local file system.
  50. * @param createArchive If \c true (default) a new ctkPluginArchive instance is returned.
  51. *
  52. * @throws ctkPluginDatabaseException
  53. */
  54. QSharedPointer<ctkPluginArchive> insertPlugin(const QUrl& location, const QString& localPath);
  55. /**
  56. * Insert a new plugin (shared library) into the persistent
  57. * storagedata as an update
  58. * to an existing plugin archive. To commit this data a call to
  59. * <code>replacePluginArchive</code> is needed.
  60. *
  61. * @param old ctkPluginArchive to be replaced.
  62. * @param localPath Path to a plugin on the local file system.
  63. * @return Plugin archive object.
  64. */
  65. QSharedPointer<ctkPluginArchive> updatePluginArchive(QSharedPointer<ctkPluginArchive> old,
  66. const QUrl& updateLocation, const QString& localPath);
  67. /**
  68. * Replace old plugin archive with a new updated plugin archive, that
  69. * was created with updatePluginArchive.
  70. *
  71. * @param oldPA ctkPluginArchive to be replaced.
  72. * @param newPA new ctkPluginArchive.
  73. */
  74. void replacePluginArchive(QSharedPointer<ctkPluginArchive> oldPA, QSharedPointer<ctkPluginArchive> newPA);
  75. /**
  76. * Removes all persisted data related to the given ctkPluginArchive.
  77. *
  78. * @throws ctkPluginDatabaseException
  79. */
  80. bool removeArchive(QSharedPointer<ctkPluginArchive> pa);
  81. /**
  82. * Get all plugin archive objects.
  83. *
  84. * @return QList of all PluginArchives.
  85. */
  86. QList<QSharedPointer<ctkPluginArchive> > getAllPluginArchives() const;
  87. /**
  88. * Get all plugins to start at next launch of framework.
  89. * This list is sorted in increasing plugin id order.
  90. *
  91. * @return A List with plugin locations.
  92. */
  93. QList<QString> getStartOnLaunchPlugins() const;
  94. /**
  95. * Closes the plugin database. Throws a ctkPluginDatabaseException
  96. * of type DB_CONNECTION_INVALID if the database is invalid.
  97. *
  98. * @throws ctkPluginDatabaseException
  99. */
  100. void close(); // Satisfy abstract interface
  101. void close() const;
  102. // -------------------------------------------------------------
  103. // end ctkPluginStorage interface
  104. // -------------------------------------------------------------
  105. /**
  106. * Sets the path of the service database to \a databasePath
  107. */
  108. void setDatabasePath(const QString &databasePath);
  109. /**
  110. * Returns the path of the plugin database
  111. */
  112. QString getDatabasePath() const;
  113. /**
  114. * Get a Qt resource cached in the database. The resource path \a res
  115. * must be relative to the plugin specific resource prefix, but may
  116. * start with a '/'.
  117. *
  118. * @param pluginId The id of the plugin from which to get the resource
  119. * @param res The path to the resource in the plugin
  120. * @return The byte array of the cached resource
  121. *
  122. * @throws ctkPluginDatabaseException
  123. */
  124. QByteArray getPluginResource(int key, const QString& res) const;
  125. /**
  126. * Get a list of resource entries under the given path.
  127. *
  128. * @param pluginId The id of the plugin from which to get the entries
  129. * @param path A resource path relative to the plugin specific resource prefix.
  130. * @return A QStringList containing the cached resource entries.
  131. *
  132. * @throws ctkPluginDatabaseException
  133. */
  134. QStringList findResourcesPath(int archiveKey, const QString& path) const;
  135. /**
  136. * Persist the start level
  137. *
  138. * @param pluginId The Plugin id
  139. * @param startLevel The new start level
  140. */
  141. void setStartLevel(int key, int startLevel);
  142. /**
  143. * Persist the last modification (state change) time
  144. *
  145. * @param pluginId The Plugin id
  146. * @param lastModified The modification time
  147. */
  148. void setLastModified(int key, const QDateTime& lastModified);
  149. /**
  150. * Persist the auto start setting.
  151. *
  152. * @param pluginId The Plugin id
  153. * @param autostart The new auto start setting
  154. */
  155. void setAutostartSetting(int key, int autostart);
  156. /**
  157. * Removes all persisted data related to the given ctkPluginArchiveSQL.
  158. * This is identical to removeArchive(QSharedPointer<ctkPluginArchive>).
  159. *
  160. * @throws ctkPluginDatabaseException
  161. */
  162. bool removeArchive(ctkPluginArchiveSQL* pa);
  163. private:
  164. enum TransactionType{Read, Write};
  165. /**
  166. * Opens the plugin database. If the database does not
  167. * yet exist, it is created using the path from getDatabasePath().
  168. *
  169. * @see setDatabasePath(const QString&)
  170. * @see getDatabasePath()
  171. * @see ctkPluginDatabaseException
  172. *
  173. * @throws ctkPluginDatabaseException
  174. */
  175. void open();
  176. /**
  177. * Checks if the database is open
  178. */
  179. bool isOpen() const;
  180. /**
  181. * Find position for ctkPluginArchive with specified id
  182. *
  183. * @param id Plugin archive id to find.
  184. * @return Position in the m_archives List.
  185. */
  186. int find(long id) const;
  187. /**
  188. * Find position for ctkPluginArchive
  189. *
  190. * @param id Plugin archive id to find.
  191. * @return Position in the m_archives List.
  192. */
  193. int find(ctkPluginArchive* pa) const;
  194. void initNextFreeIds();
  195. /**
  196. * Reads the persisted plugin data and creates a ctkPluginArchive object
  197. * for each plugin which is not in state UNINSTALLED.
  198. *
  199. * @throws ctkPluginDatabaseException
  200. */
  201. void restorePluginArchives();
  202. /**
  203. * Get load hints from the framework for plugins.
  204. */
  205. QLibrary::LoadHints getPluginLoadHints() const;
  206. /**
  207. * Helper method that creates the database tables:
  208. *
  209. * @throws ctkPluginDatabaseException
  210. */
  211. void createTables();
  212. bool dropTables();
  213. /**
  214. * Remove all plugins which have been marked as uninstalled
  215. * (startLevel == -2).
  216. */
  217. void cleanupDB();
  218. /**
  219. * Helper method that checks if all the expected tables exist in the database.
  220. *
  221. * Returns true if they all exist and false if any of them don't
  222. */
  223. bool checkTables() const;
  224. /**
  225. * Creates or returns an existing, thread-local database connection.
  226. *
  227. * @param open Create and open connection.
  228. * @return Database connection.
  229. * @throws ctkPluginDatabaseException
  230. */
  231. QSqlDatabase getConnection(bool create = true) const;
  232. /**
  233. * Creates a thread-unique database connection name.
  234. *
  235. * @return Database connection name.
  236. */
  237. QString getConnectionName() const;
  238. /**
  239. * Creates the directory for the database.
  240. *
  241. * @throws ctkPluginDatabaseException
  242. */
  243. void createDatabaseDirectory() const;
  244. /**
  245. * Compares the persisted plugin modification time with the
  246. * file system modification time and updates the database
  247. * if the persisted data is outdated.
  248. *
  249. * This should only be called once when the database is initially opened.
  250. */
  251. void updateDB();
  252. void insertArchive(QSharedPointer<ctkPluginArchiveSQL> pa);
  253. void insertArchive(QSharedPointer<ctkPluginArchiveSQL> pa, QSqlQuery* query);
  254. void removeArchiveFromDB(ctkPluginArchiveSQL *pa, QSqlQuery *query);
  255. /**
  256. * Helper function that executes the sql query specified in \a statement.
  257. * It is assumed that the \a statement uses positional placeholders and
  258. * corresponding parameters are placed in the list of \a bindValues.
  259. *
  260. * Aside: This function may be safely called standalone or within an explicit
  261. * transaction. If called standalone, it's single query is implicitly
  262. * wrapped in it's own transaction.
  263. *
  264. * @throws ctkPluginDatabaseException
  265. */
  266. void executeQuery(QSqlQuery* query, const QString &statement, const QList<QVariant> &bindValues = QList<QVariant>()) const;
  267. /**
  268. * Begins a transcaction based on the \a type which can be Read or Write.
  269. *
  270. * @throws ctkPluginDatabaseException
  271. */
  272. void beginTransaction(QSqlQuery* query, TransactionType);
  273. /**
  274. * Commits a transaction
  275. *
  276. * @throws ctkPluginDatabaseException
  277. */
  278. void commitTransaction(QSqlQuery* query);
  279. /**
  280. * Rolls back a transaction
  281. *
  282. * @throws ctkPluginDatabaseException
  283. */
  284. void rollbackTransaction(QSqlQuery* query);
  285. /**
  286. * Returns a string representation of a QDateTime instance.
  287. */
  288. QString getStringFromQDateTime(const QDateTime& dateTime) const;
  289. /**
  290. * Returns a QDateTime from a string representation.
  291. */
  292. QDateTime getQDateTimeFromString(const QString& dateTimeString) const;
  293. QString m_databasePath;
  294. mutable QThreadStorage<QString> m_connectionNames;
  295. QMutex m_archivesLock;
  296. /**
  297. * Plugin id sorted list of all active plugin archives.
  298. */
  299. QList<QSharedPointer<ctkPluginArchive> > m_archives;
  300. /**
  301. * Framework handle.
  302. */
  303. ctkPluginFrameworkContext* m_framework;
  304. /**
  305. * Keep track of the next free plug-in id
  306. */
  307. long m_nextFreeId;
  308. /**
  309. * Keep track of the next free generation for each plugin
  310. */
  311. QHash<int,int> /* <plugin id, generation> */ m_generations;
  312. };
  313. #endif // ctkPluginStorageSQL_P_H