• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDECore

kpluginloader.cpp

Go to the documentation of this file.
00001 /*  This file is part of the KDE project
00002     Copyright (C) 2007 Bernhard Loos <nhuh.put@web.de>
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License version 2 as published by the Free Software Foundation.
00007 
00008     This library is distributed in the hope that it will be useful,
00009     but WITHOUT ANY WARRANTY; without even the implied warranty of
00010     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011     Library General Public License for more details.
00012 
00013     You should have received a copy of the GNU Library General Public License
00014     along with this library; see the file COPYING.LIB.  If not, write to
00015     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016     Boston, MA 02110-1301, USA.
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 extern int kLibraryDebugArea();
00035 
00036 class KPluginLoaderPrivate
00037 {
00038     Q_DECLARE_PUBLIC(KPluginLoader)
00039 protected:
00040     KPluginLoaderPrivate(const QString &libname)
00041         : name(libname), pluginVersion(~0U), verificationData(0), lib(0)
00042     {}
00043     ~KPluginLoaderPrivate()
00044     {
00045         delete lib;
00046     }
00047 
00048     KPluginLoader *q_ptr;
00049     const QString name;
00050     quint32 pluginVersion;
00051     KDEPluginVerificationData *verificationData;
00052     QString errorString;
00053 
00054     KLibrary *lib;
00055 };
00056 
00057 inline QString makeLibName( const QString &libname )
00058 {
00059 #if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
00060     if (!libname.endsWith(QLatin1String(".dll")))
00061         return libname + QLatin1String(".dll");
00062     return libname;
00063 #else
00064     int pos = libname.lastIndexOf(QLatin1Char('/'));
00065     if (pos < 0)
00066       pos = 0;
00067     if (libname.indexOf(QLatin1Char('.'), pos) < 0) {
00068         const char* const extList[] = { ".so", ".dylib", ".bundle", ".sl" };
00069         for (uint i = 0; i < sizeof(extList) / sizeof(*extList); ++i) {
00070             const QString lib = libname + QString::fromLatin1(extList[i]);
00071             if (QLibrary::isLibrary(lib))
00072                 return lib;
00073         }
00074     }
00075     return libname;
00076 #endif
00077 }
00078 
00079 #ifdef Q_OS_WIN
00080 extern QString fixLibPrefix(const QString& libname);
00081 #endif
00082 
00083 QString findLibraryInternal(const QString &name, const KComponentData &cData)
00084 {
00085     // Convert name to a valid platform libname
00086     QString libname = makeLibName(name);
00087     QFileInfo fileinfo(name);
00088     bool hasPrefix = fileinfo.fileName().startsWith(QLatin1String("lib"));
00089     bool kdeinit = fileinfo.fileName().startsWith(QLatin1String("libkdeinit4_"));
00090 
00091     if (hasPrefix && !kdeinit)
00092         kDebug(kLibraryDebugArea()) << "plugins should not have a 'lib' prefix:" << libname;
00093 #ifdef Q_CC_MSVC
00094     // first remove the 'lib' prefix in front of windows plugins
00095     libname = fixLibPrefix(libname);
00096 #endif
00097 
00098     // If it is a absolute path just return it
00099     if (!QDir::isRelativePath(libname))
00100         return libname;
00101 
00102     // Start looking
00103     QString libfile;
00104 
00105     // Check for kde modules/plugins?
00106     libfile = cData.dirs()->findResource("module", libname);
00107     if (!libfile.isEmpty())
00108         return libfile;
00109 
00110     // Now look where they don't belong but sometimes are
00111 #ifndef Q_CC_MSVC
00112     if (!hasPrefix)
00113         libname = fileinfo.path() + QLatin1String("/lib") + fileinfo.fileName();
00114 #endif
00115 
00116     libfile = cData.dirs()->findResource("lib", libname);
00117     if (!libfile.isEmpty()) {
00118         if (!kdeinit) {
00119             kDebug(kLibraryDebugArea()) << "library" << libname << "not found under 'module' but under 'lib'";
00120         }
00121         return libfile;
00122     }
00123 
00124     // Nothing found
00125     return QString();
00126 }
00127 
00128 bool KPluginLoader::isLoaded() const
00129 {
00130     return QPluginLoader::isLoaded() || d_ptr->lib;
00131 }
00132 
00133 KPluginLoader::KPluginLoader(const QString &plugin, const KComponentData &componentdata, QObject *parent)
00134     : QPluginLoader(findLibraryInternal(plugin, componentdata), parent), d_ptr(new KPluginLoaderPrivate(plugin))
00135 {
00136     d_ptr->q_ptr = this;
00137     Q_D(KPluginLoader);
00138 
00139     // No lib, no fun.
00140     if (fileName().isEmpty()) {
00141         d->errorString = i18n(
00142                 "Could not find plugin '%1' for application '%2'",
00143                 plugin,
00144                 componentdata.aboutData()->appName());
00145         return;
00146     }
00147 }
00148 
00149 
00150 KPluginLoader::KPluginLoader(const KService &service, const KComponentData &componentdata, QObject *parent)
00151 : QPluginLoader(findLibraryInternal(service.library(), componentdata), parent), d_ptr(new KPluginLoaderPrivate(service.library()))
00152 {
00153     d_ptr->q_ptr = this;
00154     Q_D(KPluginLoader);
00155 
00156     // It's probably to late to check this because service.library() is used
00157     // above.
00158     if (!service.isValid()) {
00159         d->errorString = i18n("The provided service is not valid", service.entryPath());
00160         return;
00161     }
00162 
00163     // service.library() is used to find the lib. So first check if it is empty.
00164     if (service.library().isEmpty()) {
00165         d->errorString = i18n("The service '%1' provides no library or the Library key is missing in ", service.entryPath());
00166         return;
00167     }
00168 
00169     // No lib, no fun. service.library() was set but we were still unable to
00170     // find the lib.
00171     if (fileName().isEmpty()) {
00172         d->errorString = i18n(
00173                 "Could not find plugin '%1' for application '%2'",
00174                 service.name(),
00175                 componentdata.aboutData()->appName());
00176         return;
00177     }
00178 }
00179 
00180 KPluginLoader::~KPluginLoader()
00181 {
00182     delete d_ptr;
00183 }
00184 
00185 KPluginFactory *KPluginLoader::factory()
00186 {
00187     Q_D(KPluginLoader);
00188 
00189     if (!load())
00190         return 0;
00191 
00192 #ifndef KDE_NO_DEPRECATED
00193     if (d->lib) {
00194         // Calling a deprecated method, but this is the only way to
00195         // support both new and old-style factories for now.
00196         // KDE5: remove the whole if().
00197         return d->lib->factory(d->name.toUtf8());
00198     }
00199 #endif
00200 
00201     QObject *obj = instance();
00202 
00203     if (!obj)
00204         return 0;
00205 
00206     KPluginFactory *factory = qobject_cast<KPluginFactory *>(obj);
00207 
00208     if (factory == 0) {
00209         kDebug(kLibraryDebugArea()) << "Expected a KPluginFactory, got a" << obj->metaObject()->className();
00210         delete obj;
00211         d->errorString = i18n("The library %1 does not offer a KDE 4 compatible factory." , d->name);
00212     }
00213 
00214     return factory;
00215 }
00216 
00217 bool KPluginLoader::load()
00218 {
00219     Q_D(KPluginLoader);
00220 
00221     if (isLoaded())
00222         return true;
00223 
00224     if (!QPluginLoader::load()) {
00225         d->lib = new KLibrary(d->name);
00226         if (d->lib->load())
00227             return true;
00228 
00229         return false;
00230     }
00231 
00232     Q_ASSERT(!fileName().isEmpty());
00233     QLibrary lib(fileName());
00234     Q_ASSERT(lib.isLoaded()); // already loaded by QPluginLoader::load()
00235 
00236     d->verificationData = (KDEPluginVerificationData *) lib.resolve("kde_plugin_verification_data");
00237     if (d->verificationData) {
00238         if (d->verificationData->dataVersion < KDEPluginVerificationData::PluginVerificationDataVersion
00239             || (d->verificationData->KDEVersion > KDE_VERSION)
00240             || (KDE_VERSION_MAJOR << 16 != (d->verificationData->KDEVersion & 0xFF0000)))
00241         {
00242             d->errorString = i18n("The plugin '%1' uses an incompatible KDE library (%2).", d->name, QString::fromLatin1(d->verificationData->KDEVersionString));
00243             unload();
00244             return false;
00245         }
00246     } else {
00247         kDebug(kLibraryDebugArea()) << "The plugin" << d->name << "doesn't contain a kde_plugin_verification_data structure";
00248     }
00249 
00250     quint32 *version = (quint32 *) lib.resolve("kde_plugin_version");
00251     if (version)
00252         d->pluginVersion = *version;
00253     else
00254         d->pluginVersion = ~0U;
00255 
00256     return true;
00257 }
00258 
00259 QString KPluginLoader::errorString() const
00260 {
00261     Q_D(const KPluginLoader);
00262     const_cast<KPluginLoader*>(this)->load();
00263 
00264     if (!d->errorString.isEmpty())
00265         return d->errorString;
00266 
00267     return QPluginLoader::errorString();
00268 }
00269 
00270 quint32 KPluginLoader::pluginVersion() const
00271 {
00272     Q_D(const KPluginLoader);
00273     const_cast<KPluginLoader*>(this)->load();
00274     return d->pluginVersion;
00275 }
00276 
00277 QString KPluginLoader::pluginName() const
00278 {
00279     Q_D(const KPluginLoader);
00280     const_cast<KPluginLoader*>(this)->load();
00281     return d->name;
00282 }
00283 
00284 #include "kpluginloader.moc"

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal