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