KDECore
kpluginloader.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "kpluginloader.h"
00020
00021 #include "kaboutdata.h"
00022 #include <kcomponentdata.h>
00023 #include <kstandarddirs.h>
00024 #include <klocale.h>
00025 #include "kpluginfactory.h"
00026 #include <kservice.h>
00027 #include "klibrary.h"
00028 #include <kdebug.h>
00029
00030 #include <QtCore/QLibrary>
00031 #include <QtCore/QDir>
00032 #include <QtCore/QFileInfo>
00033
00034
00035 class KPluginLoaderPrivate
00036 {
00037 Q_DECLARE_PUBLIC(KPluginLoader)
00038 protected:
00039 KPluginLoaderPrivate(const QString &libname)
00040 : name(libname), pluginVersion(~0U), verificationData(0), lib(0)
00041 {}
00042 ~KPluginLoaderPrivate()
00043 {
00044 delete lib;
00045 }
00046
00047 KPluginLoader *q_ptr;
00048 const QString name;
00049 quint32 pluginVersion;
00050 KDEPluginVerificationData *verificationData;
00051 QString errorString;
00052
00053 KLibrary *lib;
00054 };
00055
00056 inline QString makeLibName( const QString &libname )
00057 {
00058 #ifdef Q_OS_WIN
00059 if (!libname.endsWith(".dll"))
00060 return libname + ".dll";
00061 return libname;
00062 #else
00063 int pos = libname.lastIndexOf('/');
00064 if (pos < 0)
00065 pos = 0;
00066 if (libname.indexOf('.', pos) < 0) {
00067 const char* const extList[] = { ".so", ".dylib", ".bundle", ".sl" };
00068 for (uint i = 0; i < sizeof(extList) / sizeof(*extList); ++i) {
00069 if (QLibrary::isLibrary(libname + extList[i]))
00070 return libname + extList[i];
00071 }
00072 }
00073 return libname;
00074 #endif
00075 }
00076
00077 #ifdef Q_OS_WIN
00078 extern QString fixLibPrefix(const QString& libname);
00079 #endif
00080
00081 QString findLibraryInternal(const QString &name, const KComponentData &cData)
00082 {
00083
00084 QString libname = makeLibName(name);
00085
00086 QFileInfo fileinfo(name);
00087 bool hasPrefix = fileinfo.fileName().startsWith("lib");
00088 bool kdeinit = fileinfo.fileName().startsWith("libkdeinit4_");
00089
00090 if (hasPrefix && !kdeinit)
00091 kDebug(150) << "plugins should not have a 'lib' prefix:" << libname;
00092 #ifdef Q_CC_MSVC
00093
00094 libname = fixLibPrefix(libname);
00095 #endif
00096
00097
00098 if (!QDir::isRelativePath(libname))
00099 return libname;
00100
00101
00102 QString libfile;
00103
00104
00105 libfile = cData.dirs()->findResource("module", libname);
00106 if (!libfile.isEmpty())
00107 return libfile;
00108
00109
00110 #ifndef Q_CC_MSVC
00111 if (!hasPrefix)
00112 libname = fileinfo.path() + QLatin1String("/lib") + fileinfo.fileName();
00113 #endif
00114
00115 libfile = cData.dirs()->findResource("lib", libname);
00116 if (!libfile.isEmpty()) {
00117 if (!kdeinit) {
00118 kDebug(150) << "library" << libname << "not found under 'module' but under 'lib'";
00119 }
00120 return libfile;
00121 }
00122
00123
00124 return QString();
00125 }
00126
00127 bool KPluginLoader::isLoaded() const
00128 {
00129 return QPluginLoader::isLoaded() || d_ptr->lib;
00130 }
00131
00132 KPluginLoader::KPluginLoader(const QString &plugin, const KComponentData &componentdata, QObject *parent)
00133 : QPluginLoader(findLibraryInternal(plugin, componentdata), parent), d_ptr(new KPluginLoaderPrivate(plugin))
00134 {
00135 d_ptr->q_ptr = this;
00136
00137
00138 if (fileName().isEmpty()) {
00139 kWarning(150) << "Could not find plugin" << plugin;
00140 return;
00141 }
00142
00143 load();
00144 }
00145
00146 KPluginLoader::KPluginLoader(const KService &service, const KComponentData &componentdata, QObject *parent)
00147 : QPluginLoader(findLibraryInternal(service.library(), componentdata), parent), d_ptr(new KPluginLoaderPrivate(service.library()))
00148 {
00149 d_ptr->q_ptr = this;
00150 Q_D(KPluginLoader);
00151
00152
00153
00154 if (!service.isValid()) {
00155 kWarning(150) << "Invalid service provided for KPluginLoader::KPluginLoader()";
00156 return;
00157 }
00158
00159
00160 if (service.library().isEmpty()) {
00161 d->errorString = i18n("The service '%1' provides no library or the Library key is missing in the .desktop file.", service.name());
00162 kWarning(150) << "The service" << service.entryPath() <<"provided no library or the Library key is missing";
00163 return;
00164 }
00165
00166
00167
00168 if (fileName().isEmpty()) {
00169 kWarning(150) << "Could not find plugin/library for" << service.entryPath()
00170 << "library name:" << service.library();
00171 return;
00172 }
00173
00174 load();
00175 }
00176
00177 KPluginLoader::~KPluginLoader()
00178 {
00179 delete d_ptr;
00180 }
00181
00182 KPluginFactory *KPluginLoader::factory()
00183 {
00184 Q_D(KPluginLoader);
00185
00186 if (!isLoaded())
00187 return 0;
00188
00189
00190 if (d->lib) {
00191 return d->lib->factory(d->name.toUtf8());
00192 }
00193
00194 QObject *obj = instance();
00195
00196 if (!obj)
00197 return 0;
00198
00199 KPluginFactory *factory = qobject_cast<KPluginFactory *>(obj);
00200
00201 if (factory == 0) {
00202 kDebug(150) << "Expected a KPluginFactory, got a" << obj->metaObject()->className();
00203 delete obj;
00204 d->errorString = i18n("The library %1 does not offer a KDE 4 compatible factory." , d->name);
00205 }
00206
00207 return factory;
00208 }
00209
00210 bool KPluginLoader::load()
00211 {
00212 Q_D(KPluginLoader);
00213 if (!QPluginLoader::load()) {
00214 d->lib = new KLibrary(d->name);
00215 if (d->lib->load())
00216 return true;
00217
00218 return false;
00219 }
00220
00221 Q_ASSERT(!fileName().isEmpty());
00222 QLibrary lib(fileName());
00223 lib.load();
00224 Q_ASSERT(lib.isLoaded());
00225
00226 d->verificationData = (KDEPluginVerificationData *) lib.resolve("kde_plugin_verification_data");
00227 if (d->verificationData) {
00228 if (d->verificationData->dataVersion < KDEPluginVerificationData::PluginVerificationDataVersion
00229 || (d->verificationData->KDEVersion > KDE_VERSION)
00230 || (KDE_VERSION_MAJOR << 16 != (d->verificationData->KDEVersion & 0xFF0000)))
00231 {
00232 d->errorString = i18n("The plugin '%1' uses an incompatible KDE library (%2).", d->name, d->verificationData->KDEVersionString);
00233 lib.unload();
00234 unload();
00235 return false;
00236 }
00237 } else {
00238 kDebug(150) << "The plugin" << d->name << "doesn't contain a kde_plugin_verification_data structure";
00239 }
00240
00241 quint32 *version = (quint32 *) lib.resolve("kde_plugin_version");
00242 if (version)
00243 d->pluginVersion = *version;
00244 else
00245 d->pluginVersion = ~0U;
00246
00247 lib.unload();
00248
00249 return true;
00250 }
00251
00252 QString KPluginLoader::errorString() const
00253 {
00254 Q_D(const KPluginLoader);
00255 if (!d->errorString.isEmpty())
00256 return d->errorString;
00257
00258 return QPluginLoader::errorString();
00259 }
00260
00261 quint32 KPluginLoader::pluginVersion() const
00262 {
00263 Q_D(const KPluginLoader);
00264 return d->pluginVersion;
00265 }
00266
00267 QString KPluginLoader::pluginName() const
00268 {
00269 Q_D(const KPluginLoader);
00270 return d->name;
00271 }
00272
00273 #include "kpluginloader.moc"