35 #include <QApplication>
36 #include <QStringList>
37 #include <QDirIterator>
41 #include "ctkPluginFrameworkFactory.h"
42 #include "ctkPluginFramework.h"
43 #include "ctkPluginContext.h"
44 #include "ctkPluginException.h"
46 #include <ctkConfig.h>
63 mSettingsBase =
"pluginFramework";
64 mSettingsSearchPaths = mSettingsBase +
"/searchPaths";
66 ctkProperties fwProps;
69 fwProps[ctkPluginConstants::FRAMEWORK_STORAGE] = storagePath;
73 fwProps[ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN] = ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT;
75 mFrameworkFactory.reset(
new ctkPluginFrameworkFactory(fwProps));
76 mPluginLibFilter <<
"*.dll" <<
"*.so" <<
"*.dylib";
81 if(mFramework->getState() == ctkPlugin::ACTIVE)
83 CX_LOG_CHANNEL_WARNING(
"plugin") <<
"This should not happen: PluginFrameworkManager destructor stopping plugin framework";
88 QString PluginFrameworkManager::convertToRelativePath(QString path)
const
90 QDir base = qApp->applicationDirPath();
91 return base.relativeFilePath(path);
94 QString PluginFrameworkManager::convertToAbsolutePath(QString path)
const
96 if (QDir(path).isAbsolute())
97 return QDir(path).absolutePath();
99 QDir base = qApp->applicationDirPath();
100 return QDir(base.path() +
"/" + path).absolutePath();
105 std::vector<PluginFrameworkManager::PluginLoadInfo> PluginFrameworkManager::getPluginLoadInfo(QStringList symbolicNames)
107 std::vector<PluginLoadInfo> retval;
109 for (
unsigned i=0; i<symbolicNames.size(); ++i)
112 info.symbolicName = symbolicNames[i];
113 info.storedState =
settings()->
value(mSettingsBase+
"/"+info.symbolicName).toString();
115 if (info.storedState.isEmpty())
127 retval.push_back(info);
135 QStringList paths =
settings()->
value(mSettingsSearchPaths, QStringList()).toStringList();
139 std::vector<PluginLoadInfo> info = this->getPluginLoadInfo(names);
143 for (
unsigned i=0; i< info.size(); ++i)
145 if (info[i].targetState != ctkPlugin::UNINSTALLED)
146 this->
install(info[i].symbolicName);
151 for (
unsigned i=0; i< info.size(); ++i)
153 if (info[i].targetState == ctkPlugin::ACTIVE)
156 CX_LOG_CHANNEL_INFO(
"plugin") << QString(
"Autostarting plugin %1").arg(info[i].symbolicName);
160 this->
start(info[i].symbolicName, ctkPlugin::START_TRANSIENT);
165 .arg(info[i].symbolicName)
166 .arg(info[i].storedState);
172 void PluginFrameworkManager::saveState()
174 QStringList relativePaths;
175 for (
int i=0; i<mPluginSearchPaths.size(); ++i)
176 relativePaths << this->convertToRelativePath(mPluginSearchPaths[i]);
180 for (
unsigned i=0; i<names.size(); ++i)
182 QString name = names[i];
190 ctkPlugin::State state = ctkPlugin::UNINSTALLED;
193 state = plugin->getState();
199 mPluginSearchPaths.clear();
201 for (
int i=0; i<searchPath.size(); ++i)
202 mPluginSearchPaths << this->convertToAbsolutePath(searchPath[i]);
205 for (
unsigned i=0; i<defPaths.size(); ++i)
207 QString defPath = this->convertToAbsolutePath(defPaths[i]);
208 if (!mPluginSearchPaths.count(defPath))
209 mPluginSearchPaths << defPath;
212 mPluginSearchPaths.removeDuplicates();
214 for (
int i=0; i<searchPath.size(); ++i)
216 QApplication::addLibraryPath(searchPath[i]);
224 return mPluginSearchPaths;
229 return mFramework->getPluginContext();
237 void PluginFrameworkManager::initializeFramework()
239 if (this->frameworkInitialized())
242 QSharedPointer<ctkPluginFramework> framework = mFrameworkFactory->getFramework();
247 }
catch (
const ctkPluginException& exc)
249 qCritical() <<
"Failed to initialize the plug-in framework:" << exc;
251 mFramework = framework;
254 bool PluginFrameworkManager::frameworkInitialized()
const
256 return mFramework != 0;
259 bool PluginFrameworkManager::frameworkStarted()
const
261 return mFramework && (mFramework->getState() == ctkPlugin::ACTIVE);
264 void PluginFrameworkManager::startFramework()
266 if (!this->frameworkInitialized())
267 this->initializeFramework();
269 if (this->frameworkStarted())
276 catch (
const ctkPluginException& exc)
278 qCritical() <<
"Failed to start the plug-in framework:" << exc;
285 this->initializeFramework();
286 if (!this->frameworkInitialized())
289 QString pluginPath = this->getPluginPath(symbolicName);
290 if (pluginPath.isEmpty())
296 pc->installPlugin(QUrl::fromLocalFile(pluginPath))->getPluginId();
298 catch (
const ctkPluginException& exc)
300 CX_LOG_CHANNEL_ERROR(
"plugin") <<
"Failed to install plugin:" << symbolicName <<
", " << exc.what();
302 catch (
const ctkRuntimeException& exc)
305 << QString(
"Failed to install plugin (runtime error): %1, %2")
313 this->startFramework();
314 return this->frameworkStarted();
329 for (
int i=0; i<plugins.size(); ++i)
331 this->
stop(plugins[i]);
338 ctkPluginFrameworkEvent fe = mFramework->waitForStop(5000);
347 if (fe.getType() == ctkPluginFrameworkEvent::FRAMEWORK_WAIT_TIMEDOUT)
353 catch (
const ctkRuntimeException& e)
358 return !this->frameworkStarted();
363 QString pluginPath = getPluginPath(symbolicName);
364 if (pluginPath.isEmpty())
370 pc->installPlugin(QUrl::fromLocalFile(pluginPath))->uninstall();
372 catch (
const ctkPluginException& exc)
374 CX_LOG_CHANNEL_WARNING(
"plugin") << QString(
"Failed to uninstall plugin: %1, %2").arg(symbolicName).arg(exc.what());
383 this->startFramework();
385 QString pluginPath = getPluginPath(symbolicName);
386 if (pluginPath.isEmpty())
388 CX_LOG_CHANNEL_ERROR(
"plugin") << QString(
"Failed to find plugin %1 in search path.").arg(symbolicName);
395 pc->installPlugin(QUrl::fromLocalFile(pluginPath))->start(options);
397 catch (
const ctkPluginException& exc)
399 CX_LOG_CHANNEL_ERROR(
"plugin") << QString(
"Failed to start plugin (plugin error): %1, %2").arg(symbolicName).arg(exc.what());
402 catch (
const ctkRuntimeException& exc)
404 CX_LOG_CHANNEL_ERROR(
"plugin") << QString(
"Failed to start plugin (runtime error): %1, %2").arg(symbolicName).arg(exc.what());
413 if (!this->frameworkStarted())
415 QString pluginPath = this->getPluginPath(symbolicName);
416 if (pluginPath.isEmpty())
429 plugin->stop(options);
431 catch (
const ctkPluginException& exc)
433 CX_LOG_CHANNEL_WARNING(
"plugin") << QString(
"Failed to stop plugin %1: ").arg(symbolicName).arg(exc.what());
442 QSharedPointer<ctkPlugin> empty;
444 if (!this->frameworkInitialized())
447 QString pluginPath = this->getPluginPath(symbolicName);
448 if (pluginPath.isEmpty())
452 QList < QSharedPointer<ctkPlugin> > plugins = pc->getPlugins();
453 foreach(QSharedPointer<ctkPlugin> plugin, plugins)
455 if (plugin->getSymbolicName() == symbolicName)
465 QString PluginFrameworkManager::getPluginPath(
const QString& symbolicName)
467 QString pluginFileName(symbolicName);
468 pluginFileName.replace(
".",
"_");
469 foreach(QString searchPath, mPluginSearchPaths)
471 QDirIterator dirIter(searchPath, mPluginLibFilter, QDir::Files, QDirIterator::Subdirectories);
472 while(dirIter.hasNext())
475 QFileInfo fileInfo = dirIter.fileInfo();
476 QString fileBaseName = fileInfo.baseName();
477 if (fileBaseName.startsWith(
"lib")) fileBaseName = fileBaseName.mid(3);
479 if (fileBaseName == pluginFileName)
481 return fileInfo.canonicalFilePath();
492 foreach(QString searchPath, mPluginSearchPaths)
496 result.removeDuplicates();
503 QDirIterator dirIter(searchPath, mPluginLibFilter, QDir::Files, QDirIterator::Subdirectories);
504 while (dirIter.hasNext())
507 QFileInfo fileInfo = dirIter.fileInfo();
508 QString fileBaseName = fileInfo.baseName();
509 if (fileBaseName.startsWith(
"lib"))
510 fileBaseName = fileBaseName.mid(3);
511 QString name = fileBaseName.replace(
"_",
".");
512 if (this->nameIsProbablyPlugin(name))
519 bool PluginFrameworkManager::nameIsProbablyPlugin(QString name)
const
522 if (name.count(
".")<2)
524 if (name.contains(
"cxtest"))
#define CX_LOG_CHANNEL_INFO(channel)
~PluginFrameworkManager()
QStringList getPluginSymbolicNames()
ctkPlugin::State getStateFromSymbolicName(QString name)
#define CX_LOG_CHANNEL_WARNING(channel)
QStringList getSearchPaths() const
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
QSharedPointer< ctkPluginFramework > getPluginFramework()
void uninstall(const QString &symbolicName)
void install(const QString &symbolicName)
QSharedPointer< ctkPlugin > getInstalledPluginFromSymbolicName(QString symbolicName)
void setValue(const QString &key, const QVariant &value)
static ProfileManager * getInstance()
returns the only instance of this class
ctkPluginContext * getPluginContext()
Settings * settings()
Shortcut for accessing the settings instance.
static QStringList getDefaultPluginsPath()
return the folder where plugins should be located, by default.
QString getStringForctkPluginState(const ctkPlugin::State state)
QString getSettingsPath()
ctkPlugin::State getctkPluginStateForString(QString text)
#define CX_LOG_CHANNEL_ERROR(channel)
void setSearchPaths(const QStringList &searchPath)