File indexing completed on 2024-12-01 07:24:55
0001 /* This file is part of the KDE project 0002 Copyright (C) 2003 Daniel Molkentin <molkentin@kde.org> 0003 Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org> 0004 Copyright (C) 2003-2015 Jarosław Staniek <staniek@kde.org> 0005 Copyright (C) 2012 Dimitrios T. Tanis <dimitrios.tanis@kdemail.net> 0006 0007 This program is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Library General Public 0009 License as published by the Free Software Foundation; either 0010 version 2 of the License, or (at your option) any later version. 0011 0012 This program 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 Library General Public License for more details. 0016 0017 You should have received a copy of the GNU Library General Public License 0018 along with this program; see the file COPYING. If not, write to 0019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 * Boston, MA 02110-1301, USA. 0021 */ 0022 0023 #include "KDbDriverManager.h" 0024 #include "KDbDriverManager_p.h" 0025 #include "KDbJsonTrader_p.h" 0026 #include "KDbDriver.h" 0027 #include "KDbDriverMetaData.h" 0028 #include "kdb_debug.h" 0029 0030 #include <KPluginFactory> 0031 0032 #include <QApplication> 0033 #include <QMimeDatabase> 0034 #include <QTime> 0035 #include <QWidget> 0036 0037 Q_GLOBAL_STATIC(DriverManagerInternal, s_self) 0038 0039 DriverManagerInternal::DriverManagerInternal() 0040 : m_lookupDriversNeeded(true) 0041 { 0042 qsrand(QTime::currentTime().msec()); // needed e.g. to create random table names 0043 } 0044 0045 DriverManagerInternal::~DriverManagerInternal() 0046 { 0047 drivermanagerDebug(); 0048 clear(); 0049 drivermanagerDebug() << "ok"; 0050 } 0051 0052 void DriverManagerInternal::clear() 0053 { 0054 drivermanagerDebug() << "Clearing drivers..."; 0055 qDeleteAll(m_drivers); 0056 m_drivers.clear(); 0057 qDeleteAll(m_driversMetaData); 0058 m_driversMetaData.clear(); 0059 } 0060 0061 void DriverManagerInternal::slotAppQuits() 0062 { 0063 if (qApp && !qApp->topLevelWidgets().isEmpty() 0064 && qApp->topLevelWidgets().first()->isVisible()) { 0065 return; //what a hack! - we give up when app is still there 0066 } 0067 clear(); 0068 } 0069 0070 //static 0071 DriverManagerInternal *DriverManagerInternal::self() 0072 { 0073 return s_self; 0074 } 0075 0076 bool DriverManagerInternal::lookupDrivers() 0077 { 0078 if (!m_lookupDriversNeeded) 0079 return true; 0080 0081 if (!forceEmpty) { 0082 lookupDriversInternal(); 0083 m_lookupDriversNeeded = false; 0084 } 0085 if (m_driversMetaData.isEmpty()) { 0086 m_result = KDbResult(ERR_DRIVERMANAGER, 0087 tr("Could not find any database drivers.")); 0088 return false; 0089 } 0090 return true; 0091 } 0092 0093 void DriverManagerInternal::lookupDriversInternal() 0094 { 0095 if (qApp) { 0096 connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(slotAppQuits())); 0097 } 0098 0099 clearResult(); 0100 0101 //drivermanagerDebug() << "Load all plugins"; 0102 QList<QPluginLoader*> offers 0103 = KDbJsonTrader::self()->query(QLatin1String("KDb/Driver")); 0104 const QString expectedVersion = QString::fromLatin1("%1.%2") 0105 .arg(KDB_STABLE_VERSION_MAJOR).arg(KDB_STABLE_VERSION_MINOR); 0106 QMimeDatabase mimedb; 0107 foreach(const QPluginLoader *loader, offers) { 0108 //QJsonObject json = loader->metaData(); 0109 //drivermanagerDebug() << json; 0110 QScopedPointer<KDbDriverMetaData> metaData(new KDbDriverMetaData(*loader)); 0111 //qDebug() << "VER:" << metaData->version(); 0112 if (metaData->version() != expectedVersion) { 0113 kdbWarning() << "Driver with ID" << metaData->id() 0114 << "(" << metaData->fileName() << ")" 0115 << "has version" << metaData->version() << "but expected version is" 0116 << expectedVersion 0117 << "-- skipping it"; 0118 continue; 0119 } 0120 if (m_driversMetaData.contains(metaData->id())) { 0121 if (qEnvironmentVariableIsEmpty("KDB_NO_DUPLICATED_DRIVER_WARNINGS")) { 0122 kdbWarning() << "Driver with ID" << metaData->id() << "already found at" 0123 << m_driversMetaData.value(metaData->id())->fileName() 0124 << "-- skipping another at" << metaData->fileName(); 0125 } 0126 continue; 0127 } 0128 QSet<QString> resolvedMimeTypes; 0129 for (const QString &mimeType : metaData->mimeTypes()) { 0130 const QMimeType mime = mimedb.mimeTypeForName(mimeType); 0131 if (!mime.isValid()) { 0132 kdbWarning() << "Driver with ID" << metaData->id() 0133 << "specifies the unknown MIME type" 0134 << mimeType; 0135 continue; 0136 } 0137 resolvedMimeTypes.insert(mime.name()); 0138 } 0139 for (const QString &mimeType : resolvedMimeTypes) { 0140 m_metadata_by_mimetype.insertMulti(mimeType, metaData.data()); 0141 } 0142 m_driversMetaData.insert(metaData->id(), metaData.data()); 0143 metaData.take(); 0144 } 0145 qDeleteAll(offers); 0146 offers.clear(); 0147 } 0148 0149 QStringList DriverManagerInternal::driverIds() 0150 { 0151 if (!lookupDrivers()) { 0152 return QStringList(); 0153 } 0154 if (m_driversMetaData.isEmpty() && result().isError()) { 0155 return QStringList(); 0156 } 0157 return m_driversMetaData.keys(); 0158 } 0159 0160 const KDbDriverMetaData* DriverManagerInternal::driverMetaData(const QString &id) 0161 { 0162 if (!lookupDrivers()) { 0163 return nullptr; 0164 } 0165 const KDbDriverMetaData *metaData = m_driversMetaData.value(id.toLower()); 0166 if (!metaData || m_result.isError()) { 0167 m_result = KDbResult(ERR_DRIVERMANAGER, 0168 tr("Could not find database driver \"%1\".").arg(id)); 0169 } 0170 return metaData; 0171 } 0172 0173 QStringList DriverManagerInternal::driverIdsForMimeType(const QString &mimeType) 0174 { 0175 if (!lookupDrivers()) { 0176 return QStringList(); 0177 } 0178 QMimeDatabase mimedb; 0179 const QMimeType mime = mimedb.mimeTypeForName(mimeType.toLower()); 0180 if (!mime.isValid()) { 0181 return QStringList(); 0182 } 0183 const QList<KDbDriverMetaData*> metaDatas(m_metadata_by_mimetype.values(mime.name())); 0184 QStringList result; 0185 foreach (const KDbDriverMetaData* metaData, metaDatas) { 0186 result.append(metaData->id()); 0187 } 0188 return result; 0189 } 0190 0191 QStringList DriverManagerInternal::possibleProblems() const 0192 { 0193 return m_possibleProblems; 0194 } 0195 0196 KDbDriver* DriverManagerInternal::driver(const QString& id) 0197 { 0198 if (!lookupDrivers()) 0199 return nullptr; 0200 0201 clearResult(); 0202 drivermanagerDebug() << "loading" << id; 0203 0204 KDbDriver *driver = nullptr; 0205 if (!id.isEmpty()) { 0206 driver = m_drivers.value(id.toLower()); 0207 } 0208 if (driver) 0209 return driver; //cached 0210 0211 if (!m_driversMetaData.contains(id.toLower())) { 0212 m_result = KDbResult(ERR_DRIVERMANAGER, 0213 tr("Could not find database driver \"%1\".").arg(id)); 0214 return nullptr; 0215 } 0216 0217 const KDbDriverMetaData *metaData = m_driversMetaData.value(id.toLower()); 0218 KPluginFactory *factory = qobject_cast<KPluginFactory*>(metaData->instantiate()); 0219 if (!factory) { 0220 m_result = KDbResult(ERR_DRIVERMANAGER, 0221 tr("Could not load database driver's plugin file \"%1\".") 0222 .arg(metaData->fileName())); 0223 QPluginLoader loader(metaData->fileName()); // use this to get the message 0224 (void)loader.load(); 0225 m_result.setServerMessage(loader.errorString()); 0226 kdbWarning() << m_result.message() << m_result.serverMessage(); 0227 return nullptr; 0228 } 0229 driver = factory->create<KDbDriver>(); 0230 if (!driver) { 0231 m_result = KDbResult(ERR_DRIVERMANAGER, 0232 tr("Could not open database driver \"%1\" from plugin file \"%2\".") 0233 .arg(metaData->id(), 0234 metaData->fileName())); 0235 kdbWarning() << m_result.message(); 0236 return nullptr; 0237 } 0238 driver->setMetaData(metaData); 0239 m_drivers.insert(id.toLower(), driver); 0240 return driver; 0241 } 0242 0243 // --------------------------- 0244 0245 KDbDriverManager::KDbDriverManager() 0246 { 0247 } 0248 0249 KDbDriverManager::~KDbDriverManager() 0250 { 0251 } 0252 0253 KDbResult KDbDriverManager::result() const 0254 { 0255 return s_self->result(); 0256 } 0257 0258 KDbResultable* KDbDriverManager::resultable() const 0259 { 0260 return s_self; 0261 } 0262 0263 QStringList KDbDriverManager::driverIds() 0264 { 0265 return s_self->driverIds(); 0266 } 0267 0268 const KDbDriverMetaData* KDbDriverManager::driverMetaData(const QString &id) 0269 { 0270 return s_self->driverMetaData(id); 0271 } 0272 0273 QStringList KDbDriverManager::driverIdsForMimeType(const QString &mimeType) 0274 { 0275 return s_self->driverIdsForMimeType(mimeType); 0276 } 0277 0278 KDbDriver* KDbDriverManager::driver(const QString& id) 0279 { 0280 return s_self->driver(id); 0281 } 0282 0283 QString KDbDriverManager::possibleProblemsMessage() const 0284 { 0285 if (s_self->possibleProblems().isEmpty()) { 0286 return QString(); 0287 } 0288 QString str; 0289 str.reserve(1024); 0290 str = QLatin1String("<ul>"); 0291 foreach (const QString& problem, s_self->possibleProblems()) 0292 str += (QLatin1String("<li>") + problem + QLatin1String("</li>")); 0293 str += QLatin1String("</ul>"); 0294 return str; 0295 } 0296 0297 bool KDbDriverManager::hasDatabaseServerDrivers() 0298 { 0299 foreach(const QString& id, driverIds()) { 0300 const KDbDriverMetaData *metaData = s_self->driverMetaData(id); 0301 if (!metaData->isFileBased()) { 0302 return true; 0303 } 0304 } 0305 return false; 0306 }