summaryrefslogtreecommitdiff
path: root/libsowatch/registry.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libsowatch/registry.cpp')
-rw-r--r--libsowatch/registry.cpp259
1 files changed, 194 insertions, 65 deletions
diff --git a/libsowatch/registry.cpp b/libsowatch/registry.cpp
index 7ade260..5cbc464 100644
--- a/libsowatch/registry.cpp
+++ b/libsowatch/registry.cpp
@@ -21,99 +21,228 @@ Registry* Registry::registry()
return singleRegistry;
}
+Registry::~Registry()
+{
+}
+
Registry::Registry()
+ : _watcher(new QFileSystemWatcher(this))
{
+ _watcher->addPath(SOWATCH_DRIVERS_DIR);
+ _watcher->addPath(SOWATCH_NOTIFICATIONS_DIR);
+ _watcher->addPath(SOWATCH_WATCHLETS_DIR);
+
loadDrivers();
loadNotificationProviders();
loadWatchlets();
+
+ connect(_watcher, SIGNAL(directoryChanged(QString)),
+ this, SLOT(handlePluginDirectoryChanged(QString)));
+ connect(_watcher, SIGNAL(fileChanged(QString)),
+ this, SLOT(handlePluginFileChanged(QString)));
}
void Registry::loadDrivers()
{
QDir dir(SOWATCH_DRIVERS_DIR);
- foreach (QString file, dir.entryList(QDir::Files)) {
-#if defined(Q_OS_UNIX)
- // Temporary workaround for QtC deploy plugin issues
- if (!file.endsWith(".so")) continue;
-#endif
- QPluginLoader loader(dir.absoluteFilePath(file));
- QObject *pluginObj = loader.instance();
- if (pluginObj) {
- WatchPluginInterface *plugin = qobject_cast<WatchPluginInterface*>(pluginObj);
- if (plugin) {
- QStringList drivers = plugin->drivers();
- foreach (const QString& driver, drivers) {
- _drivers[driver] = plugin;
- }
- } else {
- qWarning() << "Invalid plugin" << file;
- loader.unload();
- }
- } else {
- qWarning() << "Invalid plugin" << file << loader.errorString();
- loader.unload();
- }
+ foreach (QString entry, dir.entryList(QDir::Files)) {
+ QString file = dir.absoluteFilePath(entry);
+ loadDriver(file);
}
- qDebug() << "loaded drivers" << _drivers.keys();
+ qDebug() << "loaded drivers" << _driverIds.keys();
}
void Registry::loadNotificationProviders()
{
QDir dir(SOWATCH_NOTIFICATIONS_DIR);
- foreach (QString file, dir.entryList(QDir::Files)) {
-#if defined(Q_OS_UNIX)
- // Temporary workaround for QtC deploy plugin issues
- if (!file.endsWith(".so")) continue;
-#endif
- QPluginLoader loader(dir.absoluteFilePath(file));
- QObject *pluginObj = loader.instance();
- if (pluginObj) {
- NotificationPluginInterface *plugin = qobject_cast<NotificationPluginInterface*>(pluginObj);
- if (plugin) {
- QStringList providers = plugin->providers();
- foreach (const QString& provider, providers) {
- _providers[provider] = plugin;
- }
- } else {
- qWarning() << "Invalid plugin" << file;
- loader.unload();
+ foreach (QString entry, dir.entryList(QDir::Files)) {
+ QString file = dir.absoluteFilePath(entry);
+ loadNotificationProvider(file);
+ }
+
+ qDebug() << "loaded notification providers" << _providerIds.keys();
+}
+
+void Registry::loadWatchlets()
+{
+ QDir dir(SOWATCH_WATCHLETS_DIR);
+ foreach (QString entry, dir.entryList(QDir::Files)) {
+ QString file = dir.absoluteFilePath(entry);
+ loadWatchlet(file);
+ }
+
+ qDebug() << "loaded watchlets" << _watchletIds.keys();
+}
+
+void Registry::loadDriver(const QString &file)
+{
+ QPluginLoader* loader = new QPluginLoader(file, this);
+ QObject *pluginObj = loader->instance();
+ if (pluginObj) {
+ WatchPluginInterface *plugin = qobject_cast<WatchPluginInterface*>(pluginObj);
+ if (plugin) {
+ _driverFiles[file] = loader;
+ _drivers += plugin;
+ QStringList drivers = plugin->drivers();
+ foreach (const QString& driver, drivers) {
+ _driverIds[driver] = plugin;
}
+ _watcher->addPath(file);
} else {
- qWarning() << "Invalid plugin" << file << loader.errorString();
- loader.unload();
+ qWarning() << "Invalid plugin" << file;
+ loader->unload();
+ delete loader;
}
+ } else {
+ qWarning() << "Invalid plugin" << file << loader->errorString();
+ loader->unload();
+ delete loader;
}
+}
- qDebug() << "loaded notification providers" << _providers.keys();
+void Registry::loadNotificationProvider(const QString &file)
+{
+ QPluginLoader* loader = new QPluginLoader(file, this);
+ QObject *pluginObj = loader->instance();
+ if (pluginObj) {
+ NotificationPluginInterface *plugin = qobject_cast<NotificationPluginInterface*>(pluginObj);
+ if (plugin) {
+ _providerFiles[file] = loader;
+ _providers += plugin;
+ QStringList providers = plugin->providers();
+ foreach (const QString& provider, providers) {
+ _providerIds[provider] = plugin;
+ }
+ _watcher->addPath(file);
+ } else {
+ qWarning() << "Invalid plugin" << file;
+ loader->unload();
+ delete loader;
+ }
+ } else {
+ qWarning() << "Invalid plugin" << file << loader->errorString();
+ loader->unload();
+ delete loader;
+ }
}
-void Registry::loadWatchlets()
+void Registry::loadWatchlet(const QString &file)
{
- QDir dir(SOWATCH_WATCHLETS_DIR);
- foreach (QString file, dir.entryList(QDir::Files)) {
-#if defined(Q_OS_UNIX)
- // Temporary workaround for QtC deploy plugin issues
- if (!file.endsWith(".so")) continue;
-#endif
- QPluginLoader loader(dir.absoluteFilePath(file));
- QObject *pluginObj = loader.instance();
- if (pluginObj) {
- WatchletPluginInterface *plugin = qobject_cast<WatchletPluginInterface*>(pluginObj);
- if (plugin) {
- QStringList watchlets = plugin->watchlets();
- foreach (const QString& watchlet, watchlets) {
- _watchlets[watchlet] = plugin;
- }
- } else {
- qWarning() << "Invalid plugin" << file;
- loader.unload();
+ QPluginLoader* loader = new QPluginLoader(file, this);
+ QObject *pluginObj = loader->instance();
+ if (pluginObj) {
+ WatchletPluginInterface *plugin = qobject_cast<WatchletPluginInterface*>(pluginObj);
+ if (plugin) {
+ _watchletFiles[file] = loader;
+ _watchlets += plugin;
+ QStringList watchlets = plugin->watchlets();
+ foreach (const QString& watchlet, watchlets) {
+ _watchletIds[watchlet] = plugin;
}
+ _watcher->addPath(file);
} else {
- qWarning() << "Invalid plugin" << file << loader.errorString();
- loader.unload();
+ qWarning() << "Invalid plugin" << file;
+ loader->unload();
+ delete loader;
}
+ } else {
+ qWarning() << "Invalid plugin" << file << loader->errorString();
+ loader->unload();
+ delete loader;
}
+}
+
+void Registry::unloadDriver(QPluginLoader *loader)
+{
+ QString file = loader->fileName();
+
+ WatchPluginInterface *plugin = qobject_cast<WatchPluginInterface*>(loader->instance());
+ QStringList drivers = plugin->drivers();
- qDebug() << "loaded watchlets" << _watchlets.keys();
+ foreach (const QString& driver, drivers) {
+ _driverIds.remove(driver);
+ }
+
+ _drivers.removeAll(plugin);
+ _driverFiles.remove(file);
+ _watcher->removePath(file);
+
+ // loader->unload();
+ // TODO : Signal loss of a plugin so that servers can remove it before
+ // we unload it.
+}
+
+void Registry::unloadNotificationProvider(QPluginLoader *loader)
+{
+ QString file = loader->fileName();
+ NotificationPluginInterface *plugin = qobject_cast<NotificationPluginInterface*>(loader->instance());
+ QStringList providers = plugin->providers();
+
+ foreach (const QString& provider, providers) {
+ _providerIds.remove(provider);
+ }
+
+ _providers.removeAll(plugin);
+ _providerFiles.remove(file);
+ _watcher->removePath(file);
+}
+
+void Registry::unloadWatchlet(QPluginLoader *loader)
+{
+ QString file = loader->fileName();
+ WatchletPluginInterface *plugin = qobject_cast<WatchletPluginInterface*>(loader->instance());
+ QStringList watchlets = plugin->watchlets();
+
+ foreach (const QString& watchlet, watchlets) {
+ _watchletIds.remove(watchlet);
+ }
+
+ _watchlets.removeAll(plugin);
+ _watchletFiles.remove(file);
+ _watcher->removePath(file);
+}
+
+void Registry::handlePluginDirectoryChanged(const QString &path)
+{
+ // If the directory changed, rescan it to load new discover new plugins.
+ if (path == SOWATCH_DRIVERS_DIR) {
+ QDir dir(path);
+ foreach (QString entry, dir.entryList(QDir::Files)) {
+ QString file = dir.absoluteFilePath(entry);
+ if (!_driverFiles.contains(file)) {
+ loadDriver(file);
+ }
+ }
+ } else if (path == SOWATCH_NOTIFICATIONS_DIR) {
+ QDir dir(path);
+ foreach (QString entry, dir.entryList(QDir::Files)) {
+ QString file = dir.absoluteFilePath(entry);
+ if (!_providerFiles.contains(file)) {
+ loadNotificationProvider(file);
+ }
+ }
+ } else if (path == SOWATCH_WATCHLETS_DIR) {
+ QDir dir(path);
+ foreach (QString entry, dir.entryList(QDir::Files)) {
+ QString file = dir.absoluteFilePath(entry);
+ if (!_watchletFiles.contains(file)) {
+ loadWatchlet(file);
+ }
+ }
+ }
+}
+
+void Registry::handlePluginFileChanged(const QString &file)
+{
+ QFile f(file);
+ if (_driverFiles.contains(file)) {
+ unloadDriver(_driverFiles[file]);
+ }
+ if (_providerFiles.contains(file)) {
+ unloadNotificationProvider(_providerFiles[file]);
+ }
+ if (_watchletFiles.contains(file)) {
+ unloadWatchlet(_watchletFiles[file]);
+ }
}