diff options
Diffstat (limited to 'libsowatch/registry.cpp')
-rw-r--r-- | libsowatch/registry.cpp | 259 |
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]); + } } |