Qt 4.8
qfactoryloader.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qfactoryloader_p.h"
43 
44 #ifndef QT_NO_LIBRARY
45 #include "qfactoryinterface.h"
46 #include "qmap.h"
47 #include <qdir.h>
48 #include <qsettings.h>
49 #include <qdebug.h>
50 #include "qmutex.h"
51 #include "qplugin.h"
52 #include "qpluginloader.h"
53 #include "qlibraryinfo.h"
54 #include "private/qobject_p.h"
55 #include "private/qcoreapplication_p.h"
56 #ifdef Q_OS_SYMBIAN
57 #include "private/qcore_symbian_p.h"
58 #include "private/qfilesystemwatcher_symbian_p.h"
59 #endif
60 
62 
63 Q_GLOBAL_STATIC(QList<QFactoryLoader *>, qt_factory_loaders)
64 
65 Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_factoryloader_mutex, (QMutex::Recursive))
66 
67 #ifdef Q_OS_SYMBIAN
68 class QSymbianSystemPluginWatcher : public QSymbianFileSystemWatcherInterface
69 {
70 public:
71  QSymbianSystemPluginWatcher();
72  ~QSymbianSystemPluginWatcher();
73 
74  void watchForUpdates();
75  void handlePathChanged(QNotifyChangeEvent *e);
76 
78  TDriveList drives;
79 };
80 
81 Q_GLOBAL_STATIC(QSymbianSystemPluginWatcher, qt_symbian_system_plugin_watcher)
82 #endif
83 
85 {
87 public:
90  mutable QMutex mutex;
98 
99  void unloadPath(const QString &path);
100 };
101 
103 {
104  for (int i = 0; i < libraryList.count(); ++i)
105  libraryList.at(i)->release();
106 }
107 
109  const QString &suffix,
112 {
115  d->iid = iid;
116  d->cs = cs;
117  d->suffix = suffix;
118 
119 
120  QMutexLocker locker(qt_factoryloader_mutex());
121  update();
122  qt_factory_loaders()->append(this);
123 #ifdef Q_OS_SYMBIAN
124  // kick off Symbian plugin watcher for updates
125  qt_symbian_system_plugin_watcher();
126 #endif
127 }
128 
129 
130 void QFactoryLoader::updateDir(const QString &pluginDir, QSettings& settings)
131 {
133  QString path = pluginDir + d->suffix;
134  if (!QDir(path).exists(QLatin1String(".")))
135  return;
136 
137  QStringList plugins = QDir(path).entryList(QDir::Files);
139  for (int j = 0; j < plugins.count(); ++j) {
140  QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j));
141 
142  if (qt_debug_component()) {
143  qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName;
144  }
145  library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath());
146  if (!library->isPlugin(&settings)) {
147  if (qt_debug_component()) {
148  qDebug() << library->errorString;
149  qDebug() << " not a plugin";
150  }
151  library->release();
152  continue;
153  }
154  QString regkey = QString::fromLatin1("Qt Factory Cache %1.%2/%3:/%4")
155  .arg((QT_VERSION & 0xff0000) >> 16)
156  .arg((QT_VERSION & 0xff00) >> 8)
157  .arg(QLatin1String(d->iid))
158  .arg(fileName);
159  QStringList reg, keys;
160  reg = settings.value(regkey).toStringList();
161  if (reg.count() && library->lastModified == reg[0]) {
162  keys = reg;
163  keys.removeFirst();
164  } else {
165  if (!library->loadPlugin()) {
166  if (qt_debug_component()) {
167  qDebug() << library->errorString;
168  qDebug() << " could not load";
169  }
170  library->release();
171  continue;
172  }
173  QObject *instance = library->instance();
174  if (!instance) {
175  library->release();
176  // ignore plugins that have a valid signature but cannot be loaded.
177  continue;
178  }
180  if (instance && factory && instance->qt_metacast(d->iid))
181  keys = factory->keys();
182  if (keys.isEmpty())
183  library->unload();
184  reg.clear();
185  reg << library->lastModified;
186  reg += keys;
187  settings.setValue(regkey, reg);
188  }
189  if (qt_debug_component()) {
190  qDebug() << "keys" << keys;
191  }
192 
193  if (keys.isEmpty()) {
194  library->release();
195  continue;
196  }
197 
198  int keysUsed = 0;
199  for (int k = 0; k < keys.count(); ++k) {
200  // first come first serve, unless the first
201  // library was built with a future Qt version,
202  // whereas the new one has a Qt version that fits
203  // better
204  QString key = keys.at(k);
205  if (!d->cs)
206  key = key.toLower();
207  QLibraryPrivate *previous = d->keyMap.value(key);
208  if (!previous || (previous->qt_version > QT_VERSION && library->qt_version <= QT_VERSION)) {
209  d->keyMap[key] = library;
210  d->keyList += keys.at(k);
211  keysUsed++;
212  }
213  }
214  if (keysUsed)
215  d->libraryList += library;
216  else
217  library->release();
218  }
219 }
220 
222 {
223 #ifdef QT_SHARED
226  QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
227  for (int i = 0; i < paths.count(); ++i) {
228  const QString &pluginDir = paths.at(i);
229  // Already loaded, skip it...
230  if (d->loadedPaths.contains(pluginDir))
231  continue;
232  d->loadedPaths << pluginDir;
233  updateDir(pluginDir, settings);
234  }
235 #else
237  if (qt_debug_component()) {
238  qDebug() << "QFactoryLoader::QFactoryLoader() ignoring" << d->iid
239  << "since plugins are disabled in static builds";
240  }
241 #endif
242 }
243 
245 {
246  QMutexLocker locker(qt_factoryloader_mutex());
247  qt_factory_loaders()->removeAll(this);
248 }
249 
251 {
252  Q_D(const QFactoryLoader);
253  QMutexLocker locker(&d->mutex);
254  QStringList keys = d->keyList;
256  for (int i = 0; i < instances.count(); ++i)
257  if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instances.at(i)))
258  if (instances.at(i)->qt_metacast(d->iid))
259  keys += factory->keys();
260  return keys;
261 }
262 
264 {
265  Q_D(const QFactoryLoader);
266  QMutexLocker locker(&d->mutex);
268  for (int i = 0; i < instances.count(); ++i)
269  if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instances.at(i)))
270  if (instances.at(i)->qt_metacast(d->iid) && factory->keys().contains(key, Qt::CaseInsensitive))
271  return instances.at(i);
272 
273  QString lowered = d->cs ? key : key.toLower();
274  if (QLibraryPrivate* library = d->keyMap.value(lowered)) {
275  if (library->instance || library->loadPlugin()) {
276  if (QObject *obj = library->instance()) {
277  if (obj && !obj->parent())
278  obj->moveToThread(QCoreApplicationPrivate::mainThread());
279  return obj;
280  }
281  }
282  }
283  return 0;
284 }
285 
286 #ifdef Q_WS_X11
288 {
289  Q_D(const QFactoryLoader);
290  return d->keyMap.value(d->cs ? key : key.toLower());
291 }
292 #endif
293 
295 {
296  QMutexLocker locker(qt_factoryloader_mutex());
297  QList<QFactoryLoader *> *loaders = qt_factory_loaders();
299  it != loaders->constEnd(); ++it) {
300  (*it)->update();
301  }
302 }
303 
304 #ifdef Q_OS_SYMBIAN
305 QSymbianSystemPluginWatcher::QSymbianSystemPluginWatcher()
306 {
307  qt_s60GetRFs().DriveList(drives);
308  watchForUpdates();
309 }
310 
311 QSymbianSystemPluginWatcher::~QSymbianSystemPluginWatcher()
312 {
313  qDeleteAll(watchers);
314 }
315 
316 void QSymbianSystemPluginWatcher::watchForUpdates()
317 {
319  if (installPathPlugins.at(1) == QChar(QLatin1Char(':')))
320  return;
321 
322  installPathPlugins.prepend(QLatin1String("?:"));
323  installPathPlugins = QDir::toNativeSeparators(installPathPlugins);
324  RFs& fs = qt_s60GetRFs();
325  for (int i=0; i<KMaxDrives; i++) {
326  int attr = drives[i];
327  if ((attr & KDriveAttLocal) && !(attr & KDriveAttRom)) {
328  // start new watcher
329  TChar driveLetter;
330  fs.DriveToChar(i, driveLetter);
331  installPathPlugins[0] = driveLetter;
332  TPtrC ptr(qt_QString2TPtrC(installPathPlugins));
333  QNotifyChangeEvent *event = q_check_ptr(new QNotifyChangeEvent(fs, ptr, this, true));
334  watchers.push_back(event);
335  }
336  }
337 }
338 
339 void QSymbianSystemPluginWatcher::handlePathChanged(QNotifyChangeEvent *e)
340 {
341  QCoreApplicationPrivate::rebuildInstallLibraryPaths();
342  QMutexLocker locker(qt_factoryloader_mutex());
343  QString dirName(QDir::cleanPath(qt_TDesC2QString(e->watchedPath)));
344  QList<QFactoryLoader *> *loaders = qt_factory_loaders();
346  it != loaders->constEnd(); ++it) {
347  QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
348  (*it)->updateDir(dirName, settings);
349  }
350 }
351 
352 #endif
353 
355 
356 #endif // QT_NO_LIBRARY
The QDir class provides access to directory structures and their contents.
Definition: qdir.h:58
double d
Definition: qnumeric_p.h:62
T * q_check_ptr(T *p)
Definition: qglobal.h:1857
bool isPlugin(QSettings *settings=0)
Definition: qlibrary.cpp:669
static void refreshAll()
void setValue(const QString &key, const QVariant &value)
Sets the value of setting key to value.
Definition: qsettings.cpp:3328
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Returns the value for setting key.
Definition: qsettings.cpp:3460
QFactoryLoader(const char *iid, const QString &suffix=QString(), Qt::CaseSensitivity=Qt::CaseSensitive)
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
#define it(className, varName)
The QSettings class provides persistent platform-independent application settings.
Definition: qsettings.h:73
static QLibraryPrivate * findOrCreate(const QString &fileName, const QString &version=QString())
Definition: qlibrary.cpp:438
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
QString & prepend(QChar c)
Definition: qstring.h:261
QtPluginInstanceFunction instance
Definition: qlibrary_p.h:95
QString lastModified
Definition: qlibrary_p.h:97
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qlist.h:269
The QList::const_iterator class provides an STL-style const iterator for QList and QQueue...
Definition: qlist.h:228
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
The QString class provides a Unicode character string.
Definition: qstring.h:83
T * qobject_cast(QObject *object)
Definition: qobject.h:375
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
virtual bool event(QEvent *)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition: qobject.cpp:1200
#define Q_D(Class)
Definition: qglobal.h:2482
static QObjectList staticInstances()
Returns a list of static plugin instances (root components) held by the plugin loader.
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
QMap< QString, QLibraryPrivate * > keyMap
Q_CORE_EXPORT void qDebug(const char *,...)
QStringList toStringList() const
Returns the variant as a QStringList if the variant has type() StringList, String ...
Definition: qvariant.cpp:2259
QStringList keys() const
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
Definition: qglobal.h:1968
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
void updateDir(const QString &pluginDir, QSettings &settings)
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
void removeFirst()
Removes the first item in the list.
Definition: qlist.h:286
void moveToThread(QThread *thread)
Changes the thread affinity for this object and its children.
Definition: qobject.cpp:1458
const T * ptr(const T &t)
void clear()
Removes all items from the list.
Definition: qlist.h:764
static QString cleanPath(const QString &path)
Removes all multiple directory separators "/" and resolves any "."s or ".."s found in the path...
Definition: qdir.cpp:2082
Qt::CaseSensitivity cs
CaseSensitivity
Definition: qnamespace.h:1451
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
QString errorString
Definition: qlibrary_p.h:99
#define Q_DECLARE_PUBLIC(Class)
Definition: qglobal.h:2477
virtual QStringList keys() const =0
static QThread * mainThread()
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
static QStringList libraryPaths()
Returns a list of paths that the application will search when dynamically loading libraries...
QObject * instance(const QString &key) const
static QString location(LibraryLocation)
Returns the location specified by loc.
int key
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
QByteArray suffix
bool loadPlugin()
Definition: qlibrary.cpp:517
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
QList< QLibraryPrivate * > libraryList
static QString toNativeSeparators(const QString &pathName)
Returns pathName with the &#39;/&#39; separators converted to separators that are appropriate for the underly...
Definition: qdir.cpp:812
QLibraryPrivate * library(const QString &key) const
static QString fileName(const QString &fileUrl)
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
Definition: qalgorithms.h:319
QStringList entryList(Filters filters=NoFilter, SortFlags sort=NoSort) const
Returns a list of the names of all the files and directories in the directory, ordered according to t...
Definition: qdir.cpp:1290
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)
Declares a global static variable with the specified type and name.
Definition: qglobal.h:1982
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
bool qt_debug_component()
Definition: qlibrary.cpp:1319
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:272
#define QT_VERSION
This macro expands a numeric value of the form 0xMMNNPP (MM = major, NN = minor, PP = patch) that spe...
Definition: qglobal.h:51