• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • 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 
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     // Convert name to a valid platform libname
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     // first remove the 'lib' prefix in front of windows plugins
00094     libname = fixLibPrefix(libname);
00095 #endif
00096 
00097     // If it is a absolute path just return it
00098     if (!QDir::isRelativePath(libname))
00099         return libname;
00100 
00101     // Start looking
00102     QString libfile;
00103 
00104     // Check for kde modules/plugins?
00105     libfile = cData.dirs()->findResource("module", libname);
00106     if (!libfile.isEmpty())
00107         return libfile;
00108 
00109     // Now look where they don't belong but sometimes are
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     // Nothing found
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     // No lib, no fun.
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     // It's probably to late to check this because service.library() is used
00153     // above.
00154     if (!service.isValid()) {
00155         kWarning(150) << "Invalid service provided for KPluginLoader::KPluginLoader()";
00156         return;
00157     }
00158 
00159     // service.library() is used to find the lib. So first check if it is empty.
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     // No lib, no fun. service.library() was set but we were still unable to
00167     // find the lib.
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"

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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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