KDb

KDbDriverManager.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2003 Daniel Molkentin <molkentin@kde.org>
3 Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org>
4 Copyright (C) 2003-2015 Jarosław Staniek <staniek@kde.org>
5 Copyright (C) 2012 Dimitrios T. Tanis <dimitrios.tanis@kdemail.net>
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21*/
22
23#include "KDbDriverManager.h"
24#include "KDbDriverManager_p.h"
25#include "KDbJsonTrader_p.h"
26#include "KDbDriver.h"
27#include "KDbDriverMetaData.h"
28#include "kdb_debug.h"
29
30#include <KPluginFactory>
31
32#include <QApplication>
33#include <QMimeDatabase>
34#include <QTime>
35#include <QWidget>
36
37Q_GLOBAL_STATIC(DriverManagerInternal, s_self)
38
39DriverManagerInternal::DriverManagerInternal()
40 : m_lookupDriversNeeded(true)
41{
42 qsrand(QTime::currentTime().msec()); // needed e.g. to create random table names
43}
44
45DriverManagerInternal::~DriverManagerInternal()
46{
47 drivermanagerDebug();
48 clear();
49 drivermanagerDebug() << "ok";
50}
51
52void DriverManagerInternal::clear()
53{
54 drivermanagerDebug() << "Clearing drivers...";
55 qDeleteAll(m_drivers);
56 m_drivers.clear();
57 qDeleteAll(m_driversMetaData);
58 m_driversMetaData.clear();
59}
60
61void DriverManagerInternal::slotAppQuits()
62{
63 if (qApp && !qApp->topLevelWidgets().isEmpty()
64 && qApp->topLevelWidgets().first()->isVisible()) {
65 return; //what a hack! - we give up when app is still there
66 }
67 clear();
68}
69
70//static
71DriverManagerInternal *DriverManagerInternal::self()
72{
73 return s_self;
74}
75
76bool DriverManagerInternal::lookupDrivers()
77{
78 if (!m_lookupDriversNeeded)
79 return true;
80
81 if (!forceEmpty) {
82 lookupDriversInternal();
83 m_lookupDriversNeeded = false;
84 }
85 if (m_driversMetaData.isEmpty()) {
86 m_result = KDbResult(ERR_DRIVERMANAGER,
87 tr("Could not find any database drivers."));
88 return false;
89 }
90 return true;
91}
92
93void DriverManagerInternal::lookupDriversInternal()
94{
95 if (qApp) {
96 connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(slotAppQuits()));
97 }
98
99 clearResult();
100
101 //drivermanagerDebug() << "Load all plugins";
103 = KDbJsonTrader::self()->query(QLatin1String("KDb/Driver"));
104 const QString expectedVersion = QString::fromLatin1("%1.%2")
105 .arg(KDB_STABLE_VERSION_MAJOR).arg(KDB_STABLE_VERSION_MINOR);
106 QMimeDatabase mimedb;
107 foreach(const QPluginLoader *loader, offers) {
108 //QJsonObject json = loader->metaData();
109 //drivermanagerDebug() << json;
111 //qDebug() << "VER:" << metaData->version();
112 if (metaData->version() != expectedVersion) {
113 kdbWarning() << "Driver with ID" << metaData->id()
114 << "(" << metaData->fileName() << ")"
115 << "has version" << metaData->version() << "but expected version is"
116 << expectedVersion
117 << "-- skipping it";
118 continue;
119 }
120 if (m_driversMetaData.contains(metaData->id())) {
121 if (qEnvironmentVariableIsEmpty("KDB_NO_DUPLICATED_DRIVER_WARNINGS")) {
122 kdbWarning() << "Driver with ID" << metaData->id() << "already found at"
123 << m_driversMetaData.value(metaData->id())->fileName()
124 << "-- skipping another at" << metaData->fileName();
125 }
126 continue;
127 }
128 QSet<QString> resolvedMimeTypes;
129 for (const QString &mimeType : metaData->mimeTypes()) {
130 const QMimeType mime = mimedb.mimeTypeForName(mimeType);
131 if (!mime.isValid()) {
132 kdbWarning() << "Driver with ID" << metaData->id()
133 << "specifies the unknown MIME type"
134 << mimeType;
135 continue;
136 }
137 resolvedMimeTypes.insert(mime.name());
138 }
139 for (const QString &mimeType : resolvedMimeTypes) {
140 m_metadata_by_mimetype.insertMulti(mimeType, metaData.data());
141 }
142 m_driversMetaData.insert(metaData->id(), metaData.data());
143 metaData.take();
144 }
145 qDeleteAll(offers);
146 offers.clear();
147}
148
149QStringList DriverManagerInternal::driverIds()
150{
151 if (!lookupDrivers()) {
152 return QStringList();
153 }
154 if (m_driversMetaData.isEmpty() && result().isError()) {
155 return QStringList();
156 }
157 return m_driversMetaData.keys();
158}
159
160const KDbDriverMetaData* DriverManagerInternal::driverMetaData(const QString &id)
161{
162 if (!lookupDrivers()) {
163 return nullptr;
164 }
165 const KDbDriverMetaData *metaData = m_driversMetaData.value(id.toLower());
166 if (!metaData || m_result.isError()) {
167 m_result = KDbResult(ERR_DRIVERMANAGER,
168 tr("Could not find database driver \"%1\".").arg(id));
169 }
170 return metaData;
171}
172
173QStringList DriverManagerInternal::driverIdsForMimeType(const QString &mimeType)
174{
175 if (!lookupDrivers()) {
176 return QStringList();
177 }
178 QMimeDatabase mimedb;
179 const QMimeType mime = mimedb.mimeTypeForName(mimeType.toLower());
180 if (!mime.isValid()) {
181 return QStringList();
182 }
183 const QList<KDbDriverMetaData*> metaDatas(m_metadata_by_mimetype.values(mime.name()));
184 QStringList result;
185 foreach (const KDbDriverMetaData* metaData, metaDatas) {
186 result.append(metaData->id());
187 }
188 return result;
189}
190
191QStringList DriverManagerInternal::possibleProblems() const
192{
193 return m_possibleProblems;
194}
195
196KDbDriver* DriverManagerInternal::driver(const QString& id)
197{
198 if (!lookupDrivers())
199 return nullptr;
200
201 clearResult();
202 drivermanagerDebug() << "loading" << id;
203
204 KDbDriver *driver = nullptr;
205 if (!id.isEmpty()) {
206 driver = m_drivers.value(id.toLower());
207 }
208 if (driver)
209 return driver; //cached
210
211 if (!m_driversMetaData.contains(id.toLower())) {
212 m_result = KDbResult(ERR_DRIVERMANAGER,
213 tr("Could not find database driver \"%1\".").arg(id));
214 return nullptr;
215 }
216
217 const KDbDriverMetaData *metaData = m_driversMetaData.value(id.toLower());
218 KPluginFactory *factory = qobject_cast<KPluginFactory*>(metaData->instantiate());
219 if (!factory) {
220 m_result = KDbResult(ERR_DRIVERMANAGER,
221 tr("Could not load database driver's plugin file \"%1\".")
222 .arg(metaData->fileName()));
223 QPluginLoader loader(metaData->fileName()); // use this to get the message
224 (void)loader.load();
225 m_result.setServerMessage(loader.errorString());
226 kdbWarning() << m_result.message() << m_result.serverMessage();
227 return nullptr;
228 }
229 driver = factory->create<KDbDriver>();
230 if (!driver) {
231 m_result = KDbResult(ERR_DRIVERMANAGER,
232 tr("Could not open database driver \"%1\" from plugin file \"%2\".")
233 .arg(metaData->id(),
234 metaData->fileName()));
235 kdbWarning() << m_result.message();
236 return nullptr;
237 }
238 driver->setMetaData(metaData);
239 m_drivers.insert(id.toLower(), driver);
240 return driver;
241}
242
243// ---------------------------
244
245KDbDriverManager::KDbDriverManager()
246{
247}
248
249KDbDriverManager::~KDbDriverManager()
250{
251}
252
254{
255 return s_self->result();
256}
257
259{
260 return s_self;
261}
262
264{
265 return s_self->driverIds();
266}
267
269{
270 return s_self->driverMetaData(id);
271}
272
274{
275 return s_self->driverIdsForMimeType(mimeType);
276}
277
279{
280 return s_self->driver(id);
281}
282
284{
285 if (s_self->possibleProblems().isEmpty()) {
286 return QString();
287 }
288 QString str;
289 str.reserve(1024);
290 str = QLatin1String("<ul>");
291 foreach (const QString& problem, s_self->possibleProblems())
292 str += (QLatin1String("<li>") + problem + QLatin1String("</li>"));
293 str += QLatin1String("</ul>");
294 return str;
295}
296
298{
299 foreach(const QString& id, driverIds()) {
300 const KDbDriverMetaData *metaData = s_self->driverMetaData(id);
301 if (!metaData->isFileBased()) {
302 return true;
303 }
304 }
305 return false;
306}
KDbResult result() const
QStringList driverIdsForMimeType(const QString &mimeType)
Returns list of driver IDs for mimeType MIME type.
const KDbDriverMetaData * driverMetaData(const QString &id)
KDbResultable * resultable() const
QStringList driverIds()
QString possibleProblemsMessage() const
KDbDriver * driver(const QString &id)
Provides information about a single driver plugin.
Database driver's abstraction.
Definition KDbDriver.h:50
void setMetaData(const KDbDriverMetaData *metaData)
Interface for classes providing a result.
T * create(QObject *parent=nullptr, const QVariantList &args={})
bool value(QStringView key, bool defaultValue) const
QString fileName() const
KCALUTILS_EXPORT QString mimeType()
void append(QList< T > &&value)
void clear()
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
bool isValid() const const
QString errorString() const const
iterator insert(const T &value)
QString arg(Args &&... args) const const
QString fromLatin1(QByteArrayView str)
void reserve(qsizetype size)
QString toLower() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QTime currentTime()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 17:00:42 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.