File indexing completed on 2024-05-12 05:26:03

0001 /*
0002  * Copyright (C) 2014 Aaron Seigo <aseigo@kde.org>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Lesser General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2.1 of the License, or (at your option) version 3, or any
0008  * later version accepted by the membership of KDE e.V. (or its
0009  * successor approved by the membership of KDE e.V.), which shall
0010  * act as a proxy defined in Section 6 of version 3 of the license.
0011  *
0012  * This library is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Lesser General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Lesser General Public
0018  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0019  */
0020 
0021 #include "resource.h"
0022 
0023 #include <QCoreApplication>
0024 #include <QDir>
0025 #include <QPluginLoader>
0026 #include <QPointer>
0027 
0028 #include "facadefactory.h"
0029 #include "adaptorfactoryregistry.h"
0030 
0031 namespace Sink {
0032 
0033 Resource::Resource() : QObject(), d(nullptr)
0034 {
0035     Q_UNUSED(d);
0036 }
0037 
0038 Resource::~Resource()
0039 {
0040     // delete d;
0041 }
0042 
0043 void Resource::processCommand(int commandId, const QByteArray &data)
0044 {
0045     Q_UNUSED(commandId)
0046     Q_UNUSED(data)
0047 }
0048 
0049 void Resource::setLowerBoundRevision(qint64 revision)
0050 {
0051     Q_UNUSED(revision)
0052 }
0053 
0054 void Resource::setSecret(const QString &s)
0055 {
0056     Q_UNUSED(s)
0057 }
0058 
0059 bool Resource::checkForUpgrade()
0060 {
0061     return false;
0062 }
0063 
0064 
0065 class ResourceFactory::Private
0066 {
0067 public:
0068     QByteArrayList capabilities;
0069 };
0070 
0071 typedef QHash<QString, QPointer<ResourceFactory>> FactoryRegistry;
0072 Q_GLOBAL_STATIC(FactoryRegistry, s_loadedFactories);
0073 
0074 ResourceFactory::ResourceFactory(QObject *parent, const QByteArrayList &capabilities) : QObject(parent), d(new ResourceFactory::Private)
0075 {
0076     d->capabilities = capabilities;
0077 }
0078 
0079 ResourceFactory::~ResourceFactory()
0080 {
0081     delete d;
0082 }
0083 
0084 ResourceFactory *ResourceFactory::load(const QByteArray &resourceName)
0085 {
0086     ResourceFactory *factory = s_loadedFactories->value(resourceName);
0087     if (factory) {
0088         return factory;
0089     }
0090 
0091     for (auto const &path : QCoreApplication::instance()->libraryPaths()) {
0092         QDir pluginDir(path);
0093         // TODO: centralize this so that it is easy to change centrally
0094         //      also ref'd in cmake as ${SINK_RESOURCE_PLUGINS_PATH}
0095         if (!pluginDir.cd(QStringLiteral("sink")) || !pluginDir.cd(QStringLiteral("resources"))) {
0096             continue;
0097         }
0098 
0099         for (const QString &fileName : pluginDir.entryList(QDir::Files)) {
0100             const QString path = pluginDir.absoluteFilePath(fileName);
0101             QPluginLoader loader(path);
0102 
0103             const QString id = loader.metaData()[QStringLiteral("IID")].toString();
0104             if (id == resourceName) {
0105                 QObject *object = loader.instance();
0106                 if (object) {
0107                     factory = qobject_cast<ResourceFactory *>(object);
0108                     if (factory) {
0109                         s_loadedFactories->insert(resourceName, factory);
0110                         //TODO: Instead of always loading both facades and adaptorfactories into the respective singletons, we could also leave this up to the caller. (ResourceFactory::loadFacades(...))
0111                         factory->registerFacades(resourceName, FacadeFactory::instance());
0112                         factory->registerAdaptorFactories(resourceName, AdaptorFactoryRegistry::instance());
0113                         // TODO: if we need more data on it const QJsonObject json = loader.metaData()[QStringLiteral("MetaData")].toObject();
0114                         return factory;
0115                     } else {
0116                         qWarning() << "Plugin for" << resourceName << "from plugin" << loader.fileName() << "produced the wrong object type:" << object;
0117                         delete object;
0118                     }
0119                 } else {
0120                     qWarning() << "Could not load factory for" << resourceName << "from plugin" << loader.fileName() << "due to the following error:" << loader.errorString();
0121                 }
0122             }
0123         }
0124     }
0125 
0126     qWarning() << "Failed to find factory for resource:" << resourceName;
0127     qWarning() << "Looked into the following directories: " << QCoreApplication::instance()->libraryPaths();
0128     return nullptr;
0129 }
0130 
0131 QByteArrayList ResourceFactory::capabilities() const
0132 {
0133     return d->capabilities;
0134 }
0135 
0136 } // namespace Sink
0137 
0138 // Ignore warning I don't know how to fix in a moc file
0139 #pragma clang diagnostic push
0140 #pragma clang diagnostic ignored "-Wundefined-reinterpret-cast"
0141 #include "moc_resource.cpp"
0142 #pragma clang diagnostic pop