#include "webserver.h" #include #include #include #include #include #include #include #include #include #include "webplugin.h" #include "webapplication.h" #include "weblistener.h" WebServer::WebServer(const QJsonObject &config, QObject *parent) : QObject(parent) { { QDir dir(QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(QStringLiteral("plugins/") + QCoreApplication::applicationName())); for(const auto &fileInfo : dir.entryInfoList(QDir::Files | QDir::NoSymLinks)) { if(!QLibrary::isLibrary(fileInfo.filePath())) { qWarning() << "skipping" << fileInfo.fileName() << "because no QLibrary"; continue; // to skip windows junk files } QPluginLoader pluginLoader(fileInfo.filePath()); if(!pluginLoader.load()) { qCritical() << "error loading plugin" << fileInfo.fileName() << "because" << pluginLoader.errorString(); continue; } if(auto plugin = qobject_cast(pluginLoader.instance())) { const auto pluginName = plugin->pluginName(); if(m_plugins.contains(pluginName)) throw std::runtime_error(QString("duplicate plugin %0").arg(pluginName).toStdString()); m_plugins.insert(pluginName, plugin); } else qCritical() << "plugin" << fileInfo.fileName() << "could not be casted to WebPlugin"; } } if(!config.contains(QStringLiteral("applications"))) throw std::runtime_error("settings does not contain a applications"); { const auto applicationsVal = config.value(QStringLiteral("applications")); if(!applicationsVal.isObject()) throw std::runtime_error("applications is not a json object"); const auto applicationsList = applicationsVal.toObject(); for(auto iter = applicationsList.constBegin(); iter != applicationsList.constEnd(); iter++) { const auto applicationVal = iter.value(); if(!applicationVal.isObject()) throw std::runtime_error(QString("application %0 is not a json object").arg(iter.key()).toStdString()); auto application = applicationVal.toObject(); if(!application.contains(QStringLiteral("_pluginName"))) throw std::runtime_error(QString("application %0 does not contain a _pluginName").arg(iter.key()).toStdString()); const auto pluginNameVal = application.take(QStringLiteral("_pluginName")); if(!pluginNameVal.isString()) throw std::runtime_error(QString("application %0 pluginName is not a string").arg(iter.key()).toStdString()); auto pluginName = pluginNameVal.toString(); const auto pluginsIter = m_plugins.find(pluginName); if(pluginsIter == m_plugins.constEnd()) throw std::runtime_error(QString("application %0 references not installed plugin %1").arg(iter.key(), pluginName).toStdString()); m_applications.insert(iter.key(), pluginsIter.value()->createApplication(application, *this)); } } if(!config.contains(QStringLiteral("listeners"))) throw std::runtime_error("settings does not contain a listeners"); { const auto listenersVal = config.value(QStringLiteral("listeners")); if(!listenersVal.isArray()) throw std::runtime_error("listeners is not a json array"); const auto listenersList = listenersVal.toArray(); for(auto iter = listenersList.constBegin(); iter != listenersList.constEnd(); iter++) { const auto listenerVal = *iter; if(!listenerVal.isObject()) throw std::runtime_error(QString("listener %0 is not an object").arg(std::distance(listenersList.constBegin(), iter)).toStdString()); const auto listener = listenerVal.toObject(); m_listeners.insert(new WebListener(listener, *this)); } } } void WebServer::start() { for(auto iter = m_applications.constBegin(); iter != m_applications.constEnd(); iter++) iter.value()->start(); for(auto listener : m_listeners) listener->start(); } const QHash &WebServer::plugins() const { return m_plugins; } const QHash &WebServer::applications() const { return m_applications; } const QSet &WebServer::listeners() const { return m_listeners; }