KDb

KDbDriverManager.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2003 Daniel Molkentin <[email protected]>
3  Copyright (C) 2003 Joseph Wenninger <[email protected]>
4  Copyright (C) 2003-2015 JarosÅ‚aw Staniek <[email protected]>
5  Copyright (C) 2012 Dimitrios T. Tanis <[email protected]>
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 
37 Q_GLOBAL_STATIC(DriverManagerInternal, s_self)
38 
39 DriverManagerInternal::DriverManagerInternal()
40  : m_lookupDriversNeeded(true)
41 {
42  qsrand(QTime::currentTime().msec()); // needed e.g. to create random table names
43 }
44 
45 DriverManagerInternal::~DriverManagerInternal()
46 {
47  drivermanagerDebug();
48  clear();
49  drivermanagerDebug() << "ok";
50 }
51 
52 void 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 
61 void 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
71 DriverManagerInternal *DriverManagerInternal::self()
72 {
73  return s_self;
74 }
75 
76 bool 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 
93 void DriverManagerInternal::lookupDriversInternal()
94 {
95  if (qApp) {
96  connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(slotAppQuits()));
97  }
98 
99  clearResult();
100 
101  //drivermanagerDebug() << "Load all plugins";
102  QList<QPluginLoader*> offers
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 (qgetenv("KDB_NO_DUPLICATED_DRIVER_WARNINGS").isEmpty()) {
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 
149 QStringList 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 
160 const 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 
173 QStringList 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 
191 QStringList DriverManagerInternal::possibleProblems() const
192 {
193  return m_possibleProblems;
194 }
195 
196 KDbDriver* 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 
245 KDbDriverManager::KDbDriverManager()
246 {
247 }
248 
249 KDbDriverManager::~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 }
void append(const T &value)
T * create(const QString &keyword, QObject *parent=nullptr, const QVariantList &args=QVariantList())
Provides information about a single driver plugin.
QObject * instantiate() const
KGuiItem clear()
QString fileName() const
Database driver's abstraction.
Definition: KDbDriver.h:49
KDbResultable * resultable() const
KCALUTILS_EXPORT QString mimeType()
void reserve(int size)
Q_GLOBAL_STATIC(Internal::StaticControl, s_instance) class ControlPrivate
KDbResult result() const
Interface for classes providing a result.
QTime currentTime()
QStringList driverIds()
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
bool isValid() const const
bool value(const QString &key, bool defaultValue) const
QString possibleProblemsMessage() const
QString toLower() const const
QString id() const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromLatin1(const char *str, int size)
const KDbDriverMetaData * driverMetaData(const QString &id)
void clear()
QSet::iterator insert(const T &value)
QStringList driverIdsForMimeType(const QString &mimeType)
Returns list of driver IDs for mimeType MIME type.
void setMetaData(const KDbDriverMetaData *metaData)
Definition: KDbDriver.cpp:311
bool isFileBased() const
QString errorString() const const
KDbDriver * driver(const QString &id)
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sat Jun 25 2022 06:21:33 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.