File indexing completed on 2024-05-12 16:39:56
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() : pluginPathFound(false) 0038 { 0039 } 0040 QString subDir; 0041 bool pluginPathFound; 0042 QStringList pluginPaths; 0043 }; 0044 0045 // --- 0046 0047 KexiJsonTrader::KexiJsonTrader(const QString& subDir) 0048 : d(new Private) 0049 { 0050 Q_ASSERT(!subDir.isEmpty()); 0051 Q_ASSERT(!subDir.contains(' ')); 0052 d->subDir = subDir; 0053 } 0054 0055 KexiJsonTrader::~KexiJsonTrader() 0056 { 0057 delete d; 0058 } 0059 0060 //! @return true if at least one service type from @a serviceTypeNames exists in @a foundServiceTypes 0061 static bool supportsAtLeastServiceType(const QStringList &foundServiceTypes, 0062 const QStringList &serviceTypeNames) 0063 { 0064 foreach(const QString &serviceTypeName, serviceTypeNames) { 0065 if (foundServiceTypes.contains(serviceTypeName)) { 0066 return true; 0067 } 0068 } 0069 return false; 0070 } 0071 0072 //static 0073 QJsonObject KexiJsonTrader::metaDataObjectForPluginLoader(const QPluginLoader &pluginLoader) 0074 { 0075 return pluginLoader.metaData().value(QLatin1String("MetaData")).toObject(); 0076 } 0077 0078 //static 0079 QJsonObject KexiJsonTrader::rootObjectForPluginLoader(const QPluginLoader &pluginLoader) 0080 { 0081 QJsonObject json = metaDataObjectForPluginLoader(pluginLoader); 0082 if (json.isEmpty()) { 0083 return QJsonObject(); 0084 } 0085 return json.value(QLatin1String("KPlugin")).toObject(); 0086 } 0087 0088 //! Checks loader @a loader 0089 static bool checkLoader(QPluginLoader *loader, const QStringList &servicetypes, 0090 const QString &mimetype) 0091 { 0092 const QJsonObject pluginData = KexiJsonTrader::rootObjectForPluginLoader(*loader); 0093 if (pluginData.isEmpty()) { 0094 //qDebug() << dirIter.filePath() << "has no json!"; 0095 return false; 0096 } 0097 const QJsonArray foundServiceTypesAray = pluginData.value(QLatin1String("ServiceTypes")).toArray(); 0098 if (foundServiceTypesAray.isEmpty()) { 0099 qWarning() << "No ServiceTypes defined for plugin" << loader->fileName() << "-- skipping!"; 0100 return false; 0101 } 0102 QStringList foundServiceTypes = KexiUtils::convertTypesUsingMethod<QVariant, QString, &QVariant::toString>(foundServiceTypesAray.toVariantList()); 0103 if (!supportsAtLeastServiceType(foundServiceTypes, servicetypes)) { 0104 return false; 0105 } 0106 0107 if (!mimetype.isEmpty()) { 0108 QJsonObject json = KexiJsonTrader::metaDataObjectForPluginLoader(*loader); 0109 QStringList mimeTypes = json.value(QLatin1String("X-KDE-ExtraNativeMimeTypes")) 0110 .toString().split(QLatin1Char(',')); 0111 mimeTypes += json.value(QLatin1String("MimeType")).toString().split(QLatin1Char(';')); 0112 mimeTypes += json.value(QLatin1String("X-KDE-NativeMimeType")).toString(); 0113 if (! mimeTypes.contains(mimetype)) { 0114 return false; 0115 } 0116 } 0117 return true; 0118 } 0119 0120 static QList<QPluginLoader *> findPlugins(const QString &path, const QStringList &servicetypes, 0121 const QString &mimetype) 0122 { 0123 QList<QPluginLoader*> list; 0124 QDirIterator dirIter(path, 0125 /* QDirIterator::Subdirectories -- Since 3.0.1: Don't look into subdirs 0126 because there may be 3.x dirs from 0127 future Kexi versions. We will look 0128 into subdirs since 3.1 again. */ 0129 QDirIterator::FollowSymlinks); 0130 while (dirIter.hasNext()) { 0131 dirIter.next(); 0132 if (dirIter.fileInfo().isFile()) { 0133 QPluginLoader *loader = new QPluginLoader(dirIter.filePath()); 0134 if (checkLoader(loader, servicetypes, mimetype)) { 0135 list.append(loader); 0136 } else { 0137 delete loader; 0138 } 0139 } 0140 } 0141 return list; 0142 } 0143 0144 QList<QPluginLoader *> KexiJsonTrader::query(const QStringList &servicetypes, 0145 const QString &mimetype) 0146 { 0147 if (!d->pluginPathFound) { 0148 QStringList searchDirs; 0149 searchDirs += QCoreApplication::libraryPaths(); 0150 foreach(const QString &dir, searchDirs) { 0151 //qDebug() << dir; 0152 QString possiblePath = dir + QLatin1Char('/') + d->subDir; 0153 if (QDir(possiblePath).exists()) { 0154 d->pluginPaths += possiblePath; 0155 } 0156 } 0157 d->pluginPathFound = true; 0158 } 0159 0160 QList<QPluginLoader *> list; 0161 foreach(const QString &path, d->pluginPaths) { 0162 list += findPlugins(path, servicetypes, mimetype); 0163 } 0164 return list; 0165 } 0166 0167 QList<QPluginLoader *> KexiJsonTrader::query(const QString &servicetype, const QString &mimetype) 0168 { 0169 QStringList servicetypes; 0170 servicetypes << servicetype; 0171 return query(servicetypes, mimetype); 0172 }