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

KDECore

  • sources
  • kde-4.14
  • kdelibs
  • kdecore
  • util
kpluginloader.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE project
2  Copyright (C) 2007 Bernhard Loos <nhuh.put@web.de>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License version 2 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Library General Public License for more details.
12 
13  You should have received a copy of the GNU Library General Public License
14  along with this library; see the file COPYING.LIB. If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  Boston, MA 02110-1301, USA.
17 */
18 
19 #include "kpluginloader.h"
20 
21 #include "kaboutdata.h"
22 #include <kcomponentdata.h>
23 #include <kstandarddirs.h>
24 #include <klocale.h>
25 #include "kpluginfactory.h"
26 #include <kservice.h>
27 #include "klibrary.h"
28 #include <kdebug.h>
29 
30 #include <QtCore/QLibrary>
31 #include <QtCore/QDir>
32 #include <QtCore/QFileInfo>
33 
34 extern int kLibraryDebugArea();
35 
36 class KPluginLoaderPrivate
37 {
38  Q_DECLARE_PUBLIC(KPluginLoader)
39 protected:
40  KPluginLoaderPrivate(const QString &libname)
41  : name(libname), pluginVersion(~0U), verificationData(0), lib(0)
42  {}
43  ~KPluginLoaderPrivate()
44  {
45  delete lib;
46  }
47 
48  KPluginLoader *q_ptr;
49  const QString name;
50  quint32 pluginVersion;
51  KDEPluginVerificationData *verificationData;
52  QString errorString;
53 
54  KLibrary *lib;
55 };
56 
57 inline QString makeLibName( const QString &libname )
58 {
59 #if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
60  if (!libname.endsWith(QLatin1String(".dll")))
61  return libname + QLatin1String(".dll");
62  return libname;
63 #else
64  int pos = libname.lastIndexOf(QLatin1Char('/'));
65  if (pos < 0)
66  pos = 0;
67  if (libname.indexOf(QLatin1Char('.'), pos) < 0) {
68  const char* const extList[] = { ".so", ".dylib", ".bundle", ".sl" };
69  for (uint i = 0; i < sizeof(extList) / sizeof(*extList); ++i) {
70  const QString lib = libname + QString::fromLatin1(extList[i]);
71  if (QLibrary::isLibrary(lib))
72  return lib;
73  }
74  }
75  return libname;
76 #endif
77 }
78 
79 #ifdef Q_OS_WIN
80 extern QString fixLibPrefix(const QString& libname);
81 #endif
82 
83 QString findLibraryInternal(const QString &name, const KComponentData &cData)
84 {
85  // Convert name to a valid platform libname
86  QString libname = makeLibName(name);
87  QFileInfo fileinfo(name);
88  bool hasPrefix = fileinfo.fileName().startsWith(QLatin1String("lib"));
89  bool kdeinit = fileinfo.fileName().startsWith(QLatin1String("libkdeinit4_"));
90 
91  if (hasPrefix && !kdeinit)
92  kDebug(kLibraryDebugArea()) << "plugins should not have a 'lib' prefix:" << libname;
93 #ifdef Q_CC_MSVC
94  // first remove the 'lib' prefix in front of windows plugins
95  libname = fixLibPrefix(libname);
96 #endif
97 
98  // If it is a absolute path just return it
99  if (!QDir::isRelativePath(libname))
100  return libname;
101 
102  // Start looking
103  QString libfile;
104 
105  // Check for kde modules/plugins?
106  libfile = cData.dirs()->findResource("module", libname);
107  if (!libfile.isEmpty())
108  return libfile;
109 
110  // Now look where they don't belong but sometimes are
111 #ifndef Q_CC_MSVC
112  if (!hasPrefix)
113  libname = fileinfo.path() + QLatin1String("/lib") + fileinfo.fileName();
114 #endif
115 
116  libfile = cData.dirs()->findResource("lib", libname);
117  if (!libfile.isEmpty()) {
118  if (!kdeinit) {
119  kDebug(kLibraryDebugArea()) << "library" << libname << "not found under 'module' but under 'lib'";
120  }
121  return libfile;
122  }
123 
124  // Nothing found
125  return QString();
126 }
127 
128 bool KPluginLoader::isLoaded() const
129 {
130  return QPluginLoader::isLoaded() || d_ptr->lib;
131 }
132 
133 KPluginLoader::KPluginLoader(const QString &plugin, const KComponentData &componentdata, QObject *parent)
134  : QPluginLoader(findLibraryInternal(plugin, componentdata), parent), d_ptr(new KPluginLoaderPrivate(plugin))
135 {
136  d_ptr->q_ptr = this;
137  Q_D(KPluginLoader);
138 
139  // No lib, no fun.
140  if (fileName().isEmpty()) {
141  d->errorString = i18n(
142  "Could not find plugin '%1' for application '%2'",
143  plugin,
144  componentdata.aboutData()->appName());
145  return;
146  }
147 }
148 
149 
150 KPluginLoader::KPluginLoader(const KService &service, const KComponentData &componentdata, QObject *parent)
151 : QPluginLoader(findLibraryInternal(service.library(), componentdata), parent), d_ptr(new KPluginLoaderPrivate(service.library()))
152 {
153  d_ptr->q_ptr = this;
154  Q_D(KPluginLoader);
155 
156  // It's probably to late to check this because service.library() is used
157  // above.
158  if (!service.isValid()) {
159  d->errorString = i18n("The provided service is not valid");
160  return;
161  }
162 
163  // service.library() is used to find the lib. So first check if it is empty.
164  if (service.library().isEmpty()) {
165  d->errorString = i18n("The service '%1' provides no library or the Library key is missing", service.entryPath());
166  return;
167  }
168 
169  // No lib, no fun. service.library() was set but we were still unable to
170  // find the lib.
171  if (fileName().isEmpty()) {
172  d->errorString = i18n(
173  "Could not find plugin '%1' for application '%2'",
174  service.name(),
175  componentdata.aboutData()->appName());
176  return;
177  }
178 }
179 
180 KPluginLoader::~KPluginLoader()
181 {
182  delete d_ptr;
183 }
184 
185 KPluginFactory *KPluginLoader::factory()
186 {
187  Q_D(KPluginLoader);
188 
189  if (!load())
190  return 0;
191 
192 #ifndef KDE_NO_DEPRECATED
193  if (d->lib) {
194  // Calling a deprecated method, but this is the only way to
195  // support both new and old-style factories for now.
196  // KDE5: remove the whole if().
197  return d->lib->factory(d->name.toUtf8());
198  }
199 #endif
200 
201  QObject *obj = instance();
202 
203  if (!obj)
204  return 0;
205 
206  KPluginFactory *factory = qobject_cast<KPluginFactory *>(obj);
207 
208  if (factory == 0) {
209  kDebug(kLibraryDebugArea()) << "Expected a KPluginFactory, got a" << obj->metaObject()->className();
210  delete obj;
211  d->errorString = i18n("The library %1 does not offer a KDE 4 compatible factory." , d->name);
212  }
213 
214  return factory;
215 }
216 
217 bool KPluginLoader::load()
218 {
219  Q_D(KPluginLoader);
220 
221  if (isLoaded())
222  return true;
223 
224  if (!QPluginLoader::load()) {
225  d->lib = new KLibrary(d->name);
226  if (d->lib->load())
227  return true;
228 
229  return false;
230  }
231 
232  Q_ASSERT(!fileName().isEmpty());
233  QLibrary lib(fileName());
234  Q_ASSERT(lib.isLoaded()); // already loaded by QPluginLoader::load()
235 
236  d->verificationData = (KDEPluginVerificationData *) lib.resolve("kde_plugin_verification_data");
237  if (d->verificationData) {
238  if (d->verificationData->dataVersion < KDEPluginVerificationData::PluginVerificationDataVersion
239  || ((d->verificationData->KDEVersion & 0xFFFF00) > (KDE_VERSION & 0xFFFF00)) // newer minor version
240  || (KDE_VERSION_MAJOR << 16 != (d->verificationData->KDEVersion & 0xFF0000))) // different major version
241  {
242  d->errorString = i18n("The plugin '%1' uses an incompatible KDE library (%2).", d->name, QString::fromLatin1(d->verificationData->KDEVersionString));
243  unload();
244  return false;
245  }
246  } else {
247  kDebug(kLibraryDebugArea()) << "The plugin" << d->name << "doesn't contain a kde_plugin_verification_data structure";
248  }
249 
250  quint32 *version = (quint32 *) lib.resolve("kde_plugin_version");
251  if (version)
252  d->pluginVersion = *version;
253  else
254  d->pluginVersion = ~0U;
255 
256  return true;
257 }
258 
259 QString KPluginLoader::errorString() const
260 {
261  Q_D(const KPluginLoader);
262 
263  if (!d->errorString.isEmpty())
264  return d->errorString;
265 
266  return QPluginLoader::errorString();
267 }
268 
269 quint32 KPluginLoader::pluginVersion() const
270 {
271  Q_D(const KPluginLoader);
272  const_cast<KPluginLoader*>(this)->load();
273  return d->pluginVersion;
274 }
275 
276 QString KPluginLoader::pluginName() const
277 {
278  Q_D(const KPluginLoader);
279  const_cast<KPluginLoader*>(this)->load();
280  return d->name;
281 }
282 
283 #include "kpluginloader.moc"
i18n
QString i18n(const char *text)
Returns a localized version of a string.
Definition: klocalizedstring.h:630
QPluginLoader::load
bool load()
QString::indexOf
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QFileInfo::path
QString path() const
KPluginLoader::pluginName
QString pluginName() const
The name of this plugin as given to the constructor.
kdebug.h
KAboutData::appName
QString appName() const
Returns the application's internal name.
Definition: kaboutdata.cpp:678
KService
Represent a service, like an application or plugin bound to one or several mimetypes (or servicetypes...
Definition: kservice.h:58
QObject::metaObject
virtual const QMetaObject * metaObject() const
makeLibName
QString makeLibName(const QString &libname)
Definition: kpluginloader.cpp:57
KComponentData::aboutData
const KAboutData * aboutData() const
Returns the about data of this component.
Definition: kcomponentdata.cpp:215
quint32
KDEPluginVerificationData
Definition: kexportplugin.h:32
QPluginLoader::fileName
QString fileName() const
klocale.h
QPluginLoader::unload
bool unload()
QString::lastIndexOf
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
KSycocaEntry::isValid
bool isValid() const
Definition: ksycocaentry.cpp:151
KPluginLoader::load
bool load()
Performs the loading of the plugin.
Definition: kpluginloader.cpp:217
KSycocaEntry::entryPath
QString entryPath() const
Definition: ksycocaentry.cpp:104
KPluginLoader::errorString
QString errorString() const
Queries the last error.
Definition: kpluginloader.cpp:259
KPluginLoader
This class can be used to dynamically load a plugin library at runtime.
Definition: kpluginloader.h:79
KPluginLoader::~KPluginLoader
~KPluginLoader()
Destroys the plugin loader.
Definition: kpluginloader.cpp:180
QFileInfo::fileName
QString fileName() const
QObject
kpluginloader.h
KPluginLoader::KPluginLoader
KPluginLoader(const QString &plugin, const KComponentData &componentdata=KGlobal::mainComponent(), QObject *parent=0)
Used this constructor to load a plugin with a given library name.
Definition: kpluginloader.cpp:133
QString::isEmpty
bool isEmpty() const
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
QPluginLoader::instance
QObject * instance()
KLibrary
Thin wrapper around QLibrary; you should rarely use this directly, see KPluginLoader for higher-level...
Definition: klibrary.h:38
QString::endsWith
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QPluginLoader::errorString
QString errorString() const
QString
kservice.h
QLibrary::isLoaded
bool isLoaded() const
QFileInfo
QLatin1Char
KService::library
QString library() const
Returns the name of the service's library.
Definition: kservice.cpp:857
QMetaObject::className
const char * className() const
QDir::isRelativePath
bool isRelativePath(const QString &path)
KPluginLoader::factory
KPluginFactory * factory()
Used to obtain the factory object of the plugin.
Definition: kpluginloader.cpp:185
KPluginLoader::pluginVersion
quint32 pluginVersion() const
Queries the plugin version.
Definition: kpluginloader.cpp:269
KDE_VERSION
#define KDE_VERSION
Version of KDE as number, at compile time.
Definition: kdeversion.h.cmake:85
QLibrary::resolve
void * resolve(const char *symbol)
QLatin1String
kstandarddirs.h
KDE::version
unsigned int version()
Returns the encoded number of KDE's version, see the KDE_VERSION macro.
Definition: kdeversion.cpp:24
kpluginfactory.h
KDEPluginVerificationData::PluginVerificationDataVersion
Definition: kexportplugin.h:34
QLibrary
KStandardDirs::findResource
QString findResource(const char *type, const QString &filename) const
Tries to find a resource in the following order:
Definition: kstandarddirs.cpp:458
KDE_VERSION_MAJOR
#define KDE_VERSION_MAJOR
Major version of KDE, at compile time.
Definition: kdeversion.h.cmake:54
QString::fromLatin1
QString fromLatin1(const char *str, int size)
kDebug
#define kDebug
Definition: kdebug.h:316
KPluginLoader::isLoaded
bool isLoaded() const
Definition: kpluginloader.cpp:128
fixLibPrefix
QString fixLibPrefix(const QString &libname)
Definition: klibloader.cpp:66
kaboutdata.h
findLibraryInternal
QString findLibraryInternal(const QString &name, const KComponentData &cData)
Definition: kpluginloader.cpp:83
kLibraryDebugArea
int kLibraryDebugArea()
Definition: klibrary.cpp:33
kcomponentdata.h
QPluginLoader
QPluginLoader::isLoaded
bool isLoaded() const
klibrary.h
KPluginFactory
If you develop a library that is to be loaded dynamically at runtime, then you should return a pointe...
Definition: kpluginfactory.h:232
KSycocaEntry::name
QString name() const
Definition: ksycocaentry.cpp:157
KComponentData
Per component data.
Definition: kcomponentdata.h:46
QLibrary::isLibrary
bool isLibrary(const QString &fileName)
KComponentData::dirs
KStandardDirs * dirs() const
Returns the application standard dirs object.
Definition: kcomponentdata.cpp:193
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:11 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

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

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • 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

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal