00001 /**************************************************************************** 00002 ** 00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved. 00004 ** 00005 ** This file is part of the QtCore module of the Qt Toolkit. 00006 ** 00007 ** This file may be used under the terms of the GNU General Public 00008 ** License version 2.0 as published by the Free Software Foundation 00009 ** and appearing in the file LICENSE.GPL included in the packaging of 00010 ** this file. Please review the following information to ensure GNU 00011 ** General Public Licensing requirements will be met: 00012 ** http://www.trolltech.com/products/qt/opensource.html 00013 ** 00014 ** If you are unsure which license is appropriate for your use, please 00015 ** review the following information: 00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the 00017 ** sales department at sales@trolltech.com. 00018 ** 00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00021 ** 00022 ****************************************************************************/ 00023 00024 #include "qfactoryloader_p.h" 00025 00026 #ifndef QT_NO_LIBRARY 00027 #include "qfactoryinterface.h" 00028 #include "qmap.h" 00029 #include <qdir.h> 00030 #include <qsettings.h> 00031 #include <qdebug.h> 00032 #include "qmutex.h" 00033 #include "qplugin.h" 00034 #include "qpluginloader.h" 00035 #include "private/qobject_p.h" 00036 #include "private/qcoreapplication_p.h" 00037 00038 class QFactoryLoaderPrivate : public QObjectPrivate 00039 { 00040 Q_DECLARE_PUBLIC(QFactoryLoader) 00041 public: 00042 QFactoryLoaderPrivate(){} 00043 mutable QMutex mutex; 00044 QByteArray iid; 00045 QList<QLibraryPrivate*> libraryList; 00046 QMap<QString,QLibraryPrivate*> keyMap; 00047 QStringList keyList; 00048 }; 00049 00050 QFactoryLoader::QFactoryLoader(const char *iid, 00051 const QStringList &paths, const QString &suffix, 00052 Qt::CaseSensitivity cs) 00053 : QObject(*new QFactoryLoaderPrivate) 00054 { 00055 moveToThread(QCoreApplicationPrivate::mainThread()); 00056 Q_D(QFactoryLoader); 00057 d->iid = iid; 00058 00059 QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); 00060 00061 for (int i = 0; i < paths.count(); ++i) { 00062 QString path = paths.at(i) + suffix; 00063 if (!QDir(path).exists(QLatin1String("."))) 00064 continue; 00065 QStringList plugins = QDir(path).entryList(QDir::Files); 00066 QLibraryPrivate *library = 0; 00067 for (int j = 0; j < plugins.count(); ++j) { 00068 QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j)); 00069 if (qt_debug_component()) { 00070 qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName; 00071 } 00072 library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath()); 00073 if (!library->isPlugin()) { 00074 library->release(); 00075 if (qt_debug_component()) { 00076 qDebug() << " not a plugin"; 00077 } 00078 continue; 00079 } 00080 QString regkey = QString::fromLatin1("Qt Factory Cache %1.%2/%3:/%4") 00081 .arg((QT_VERSION & 0xff0000) >> 16) 00082 .arg((QT_VERSION & 0xff00) >> 8) 00083 .arg(QLatin1String(iid)) 00084 .arg(fileName); 00085 QStringList reg, keys; 00086 reg = settings.value(regkey).toStringList(); 00087 if (reg.count() && library->lastModified == reg[0]) { 00088 keys = reg; 00089 keys.removeFirst(); 00090 } else { 00091 if (!library->loadPlugin()) { 00092 if (qt_debug_component()) { 00093 qDebug() << " could not load"; 00094 } 00095 library->release(); 00096 continue; 00097 } 00098 QObject *instance = library->instance(); 00099 if (!instance) 00100 // ignore plugins that have a valid signature but cannot be loaded. 00101 continue; 00102 QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance); 00103 if (instance && factory && instance->qt_metacast(iid)) 00104 keys = factory->keys(); 00105 if (keys.isEmpty()) 00106 library->unload(); 00107 reg.clear(); 00108 reg << library->lastModified; 00109 reg += keys; 00110 settings.setValue(regkey, reg); 00111 } 00112 if (qt_debug_component()) { 00113 qDebug() << "keys" << keys; 00114 } 00115 00116 if (keys.isEmpty()) { 00117 library->release(); 00118 continue; 00119 } 00120 d->libraryList += library; 00121 for (int k = 0; k < keys.count(); ++k) { 00122 // first come first serve, unless the first 00123 // library was built with a future Qt version, 00124 // whereas the new one has a Qt version that fits 00125 // better 00126 QString key = keys.at(k); 00127 if (!cs) 00128 key = key.toLower(); 00129 QLibraryPrivate *previous = d->keyMap.value(key); 00130 if (!previous || (previous->qt_version > QT_VERSION && library->qt_version <= QT_VERSION)) { 00131 d->keyMap[key] = library; 00132 d->keyList += keys.at(k); 00133 } 00134 } 00135 } 00136 } 00137 } 00138 00139 QFactoryLoader::~QFactoryLoader() 00140 { 00141 Q_D(QFactoryLoader); 00142 for (int i = 0; i < d->libraryList.count(); ++i) 00143 d->libraryList.at(i)->release(); 00144 } 00145 00146 QStringList QFactoryLoader::keys() const 00147 { 00148 Q_D(const QFactoryLoader); 00149 QMutexLocker locker(&d->mutex); 00150 QStringList keys = d->keyList; 00151 QObjectList instances = QPluginLoader::staticInstances(); 00152 for (int i = 0; i < instances.count(); ++i) 00153 if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instances.at(i))) 00154 if (instances.at(i)->qt_metacast(d->iid)) 00155 keys += factory->keys(); 00156 return keys; 00157 } 00158 00159 QObject *QFactoryLoader::instance(const QString &key) const 00160 { 00161 Q_D(const QFactoryLoader); 00162 QMutexLocker locker(&d->mutex); 00163 QObjectList instances = QPluginLoader::staticInstances(); 00164 for (int i = 0; i < instances.count(); ++i) 00165 if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instances.at(i))) 00166 if (instances.at(i)->qt_metacast(d->iid) && factory->keys().contains(key, Qt::CaseInsensitive)) 00167 return instances.at(i); 00168 00169 if (QLibraryPrivate* library = d->keyMap.value(key)) { 00170 if (library->instance || library->loadPlugin()) { 00171 if (QObject *obj = library->instance()) { 00172 if (obj && !obj->parent()) 00173 obj->moveToThread(QCoreApplicationPrivate::mainThread()); 00174 return obj; 00175 } 00176 } 00177 } 00178 return 0; 00179 } 00180 #endif // QT_NO_LIBRARY
1.5.1