File indexing completed on 2024-05-19 12:54:43
0001 /* This file is part of the KDE project 0002 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> 0003 Copyright (C) 2007 David Faure <faure@kde.org> 0004 Copyright (C) 2015 Jarosław Staniek <staniek@kde.org> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "KexiJsonTrader.h" 0023 #include "utils.h" 0024 0025 #include <QDebug> 0026 #include <QList> 0027 #include <QPluginLoader> 0028 #include <QJsonObject> 0029 #include <QJsonArray> 0030 #include <QDirIterator> 0031 #include <QDir> 0032 #include <QCoreApplication> 0033 0034 class Q_DECL_HIDDEN KexiJsonTrader::Private 0035 { 0036 public: 0037 Private(const QString &subDir) : m_subDir(subDir) 0038 { 0039 } 0040 0041 QStringList pluginPaths() 0042 { 0043 if (!m_pluginPathFound) { 0044 QStringList searchDirs; 0045 searchDirs += QCoreApplication::libraryPaths(); 0046 for (const QString &dir : searchDirs) { 0047 const QString possiblePath = dir + QLatin1Char('/') + m_subDir; 0048 if (QDir(possiblePath).exists()) { 0049 m_pluginPaths += possiblePath; 0050 } 0051 } 0052 m_pluginPathFound = true; 0053 } 0054 return m_pluginPaths; 0055 } 0056 0057 private: 0058 QString m_subDir; 0059 QStringList m_pluginPaths; 0060 bool m_pluginPathFound = false; 0061 }; 0062 0063 // --- 0064 0065 KexiJsonTrader::KexiJsonTrader(const QString& subDir) 0066 : d(new Private(subDir)) 0067 { 0068 } 0069 0070 KexiJsonTrader::~KexiJsonTrader() 0071 { 0072 delete d; 0073 } 0074 0075 //! @return true if at least one service type from @a serviceTypeNames exists in @a foundServiceTypes 0076 static bool supportsAtLeastServiceType(const QStringList &foundServiceTypes, 0077 const QStringList &serviceTypeNames) 0078 { 0079 foreach(const QString &serviceTypeName, serviceTypeNames) { 0080 if (foundServiceTypes.contains(serviceTypeName)) { 0081 return true; 0082 } 0083 } 0084 return false; 0085 } 0086 0087 //static 0088 QJsonObject KexiJsonTrader::metaDataObjectForPluginLoader(const QPluginLoader &pluginLoader) 0089 { 0090 return pluginLoader.metaData().value(QLatin1String("MetaData")).toObject(); 0091 } 0092 0093 //static 0094 QJsonObject KexiJsonTrader::rootObjectForPluginLoader(const QPluginLoader &pluginLoader) 0095 { 0096 QJsonObject json = metaDataObjectForPluginLoader(pluginLoader); 0097 if (json.isEmpty()) { 0098 return QJsonObject(); 0099 } 0100 return json.value(QLatin1String("KPlugin")).toObject(); 0101 } 0102 0103 //! Checks loader @a loader 0104 static bool checkLoader(QPluginLoader *loader, const QStringList &servicetypes, 0105 const QString &mimetype) 0106 { 0107 const QJsonObject pluginData = KexiJsonTrader::rootObjectForPluginLoader(*loader); 0108 if (pluginData.isEmpty()) { 0109 //qDebug() << dirIter.filePath() << "has no json!"; 0110 return false; 0111 } 0112 const QJsonArray foundServiceTypesAray = pluginData.value(QLatin1String("ServiceTypes")).toArray(); 0113 if (foundServiceTypesAray.isEmpty()) { 0114 qWarning() << "No ServiceTypes defined for plugin" << loader->fileName() << "-- skipping!"; 0115 return false; 0116 } 0117 QStringList foundServiceTypes = KexiUtils::convertTypesUsingMethod<QVariant, QString, &QVariant::toString>(foundServiceTypesAray.toVariantList()); 0118 if (!supportsAtLeastServiceType(foundServiceTypes, servicetypes)) { 0119 return false; 0120 } 0121 0122 if (!mimetype.isEmpty()) { 0123 QJsonObject json = KexiJsonTrader::metaDataObjectForPluginLoader(*loader); 0124 QStringList mimeTypes = json.value(QLatin1String("X-KDE-ExtraNativeMimeTypes")) 0125 .toString().split(QLatin1Char(',')); 0126 mimeTypes += json.value(QLatin1String("MimeType")).toString().split(QLatin1Char(';')); 0127 mimeTypes += json.value(QLatin1String("X-KDE-NativeMimeType")).toString(); 0128 if (! mimeTypes.contains(mimetype)) { 0129 return false; 0130 } 0131 } 0132 return true; 0133 } 0134 0135 static QList<QPluginLoader *> findPlugins(const QString &path, const QStringList &servicetypes, 0136 const QString &mimetype) 0137 { 0138 QList<QPluginLoader*> list; 0139 QDirIterator dirIter(path, 0140 /* QDirIterator::Subdirectories -- Since 3.0.1: Don't look into subdirs 0141 because there may be 3.x dirs from 0142 future Kexi versions. We will look 0143 into subdirs since 3.1 again. */ 0144 QDirIterator::FollowSymlinks); 0145 while (dirIter.hasNext()) { 0146 dirIter.next(); 0147 if (dirIter.fileInfo().isFile()) { 0148 QPluginLoader *loader = new QPluginLoader(dirIter.filePath()); 0149 if (checkLoader(loader, servicetypes, mimetype)) { 0150 list.append(loader); 0151 } else { 0152 delete loader; 0153 } 0154 } 0155 } 0156 return list; 0157 } 0158 0159 QList<QPluginLoader *> KexiJsonTrader::query(const QStringList &servicetypes, 0160 const QString &mimetype) 0161 { 0162 QList<QPluginLoader *> list; 0163 foreach(const QString &path, d->pluginPaths()) { 0164 list += findPlugins(path, servicetypes, mimetype); 0165 } 0166 return list; 0167 } 0168 0169 QList<QPluginLoader *> KexiJsonTrader::query(const QString &servicetype, const QString &mimetype) 0170 { 0171 QStringList servicetypes; 0172 servicetypes << servicetype; 0173 return query(servicetypes, mimetype); 0174 } 0175 0176 QStringList KexiJsonTrader::pluginPaths() const 0177 { 0178 return d->pluginPaths(); 0179 }