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;
73 fwProps[ctkPluginConstants::FRAMEWORK_STORAGE] = storagePath;
76 fwProps[ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN] = ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT;
78 mFrameworkFactory.reset(
new ctkPluginFrameworkFactory(fwProps));
79 mPluginLibFilter <<
"*.dll" <<
"*.so" <<
"*.dylib";
84 if(mFramework->getState() == ctkPlugin::ACTIVE)
86 CX_LOG_CHANNEL_WARNING(
"plugin") <<
"This should not happen: PluginFrameworkManager destructor stopping plugin framework";
91 QString PluginFrameworkManager::convertToRelativePath(QString path)
const
93 QDir base = qApp->applicationDirPath();
94 return base.relativeFilePath(path);
97 QString PluginFrameworkManager::convertToAbsolutePath(QString path)
const
99 if (QDir(path).isAbsolute())
100 return QDir(path).absolutePath();
102 QDir base = qApp->applicationDirPath();
103 return QDir(base.path() +
"/" + path).absolutePath();
108 std::vector<PluginFrameworkManager::PluginLoadInfo> PluginFrameworkManager::getPluginLoadInfo(QStringList symbolicNames)
110 std::vector<PluginLoadInfo> retval;
112 for (
unsigned i=0; i<symbolicNames.size(); ++i)
115 info.symbolicName = symbolicNames[i];
116 info.storedState =
settings()->
value(mSettingsBase+
"/"+info.symbolicName).toString();
118 if (info.storedState.isEmpty())
130 retval.push_back(info);
138 QStringList paths =
settings()->
value(mSettingsSearchPaths, QStringList()).toStringList();
142 std::vector<PluginLoadInfo> info = this->getPluginLoadInfo(names);
146 for (
unsigned i=0; i< info.size(); ++i)
148 if (info[i].targetState != ctkPlugin::UNINSTALLED)
149 this->
install(info[i].symbolicName);
154 for (
unsigned i=0; i< info.size(); ++i)
156 if (info[i].targetState == ctkPlugin::ACTIVE)
159 CX_LOG_CHANNEL_INFO(
"plugin") << QString(
"Autostarting plugin %1").arg(info[i].symbolicName);
163 this->
start(info[i].symbolicName, ctkPlugin::START_TRANSIENT);
168 .arg(info[i].symbolicName)
169 .arg(info[i].storedState);
175 void PluginFrameworkManager::saveState()
177 QStringList relativePaths;
178 for (
int i=0; i<mPluginSearchPaths.size(); ++i)
179 relativePaths << this->convertToRelativePath(mPluginSearchPaths[i]);
183 for (
unsigned i=0; i<names.size(); ++i)
185 QString name = names[i];
193 ctkPlugin::State state = ctkPlugin::UNINSTALLED;
196 state = plugin->getState();
202 mPluginSearchPaths.clear();
204 for (
int i=0; i<searchPath.size(); ++i)
205 mPluginSearchPaths << this->convertToAbsolutePath(searchPath[i]);
208 for (
unsigned i=0; i<defPaths.size(); ++i)
210 QString defPath = this->convertToAbsolutePath(defPaths[i]);
211 if (!mPluginSearchPaths.count(defPath))
212 mPluginSearchPaths << defPath;
215 mPluginSearchPaths.removeDuplicates();
217 for (
int i=0; i<searchPath.size(); ++i)
219 QApplication::addLibraryPath(searchPath[i]);
227 return mPluginSearchPaths;
232 return mFramework->getPluginContext();
240 void PluginFrameworkManager::initializeFramework()
242 if (this->frameworkInitialized())
245 QSharedPointer<ctkPluginFramework> framework = mFrameworkFactory->getFramework();
250 }
catch (
const ctkPluginException& exc)
252 qCritical() <<
"Failed to initialize the plug-in framework:" << exc;
254 mFramework = framework;
257 bool PluginFrameworkManager::frameworkInitialized()
const
259 return mFramework != 0;
262 bool PluginFrameworkManager::frameworkStarted()
const
264 return mFramework && (mFramework->getState() == ctkPlugin::ACTIVE);
267 void PluginFrameworkManager::startFramework()
269 if (!this->frameworkInitialized())
270 this->initializeFramework();
272 if (this->frameworkStarted())
279 catch (
const ctkPluginException& exc)
281 qCritical() <<
"Failed to start the plug-in framework:" << exc;
288 this->initializeFramework();
289 if (!this->frameworkInitialized())
292 QString pluginPath = this->getPluginPath(symbolicName);
293 if (pluginPath.isEmpty())
299 pc->installPlugin(QUrl::fromLocalFile(pluginPath))->getPluginId();
301 catch (
const ctkPluginException& exc)
303 CX_LOG_CHANNEL_ERROR(
"plugin") <<
"Failed to install plugin:" << symbolicName <<
", " << exc.what();
305 catch (
const ctkRuntimeException& exc)
308 << QString(
"Failed to install plugin (runtime error): %1, %2")
316 this->startFramework();
317 return this->frameworkStarted();
331 ctkPluginFrameworkEvent fe = mFramework->waitForStop(5000);
332 if (fe.getType() == ctkPluginFrameworkEvent::FRAMEWORK_WAIT_TIMEDOUT)
338 catch (
const ctkRuntimeException& e)
343 return !this->frameworkStarted();
348 QString pluginPath = getPluginPath(symbolicName);
349 if (pluginPath.isEmpty())
355 pc->installPlugin(QUrl::fromLocalFile(pluginPath))->uninstall();
357 catch (
const ctkPluginException& exc)
359 CX_LOG_CHANNEL_WARNING(
"plugin") << QString(
"Failed to uninstall plugin: %1, %2").arg(symbolicName).arg(exc.what());
368 this->startFramework();
370 QString pluginPath = getPluginPath(symbolicName);
371 if (pluginPath.isEmpty())
377 pc->installPlugin(QUrl::fromLocalFile(pluginPath))->start(options);
379 catch (
const ctkPluginException& exc)
381 CX_LOG_CHANNEL_ERROR(
"plugin") << QString(
"Failed to start plugin (plugin error): %1, %2").arg(symbolicName).arg(exc.what());
384 catch (
const ctkRuntimeException& exc)
386 CX_LOG_CHANNEL_ERROR(
"plugin") << QString(
"Failed to start plugin (runtime error): %1, %2").arg(symbolicName).arg(exc.what());
395 if (!this->frameworkStarted())
397 QString pluginPath = this->getPluginPath(symbolicName);
398 if (pluginPath.isEmpty())
411 plugin->stop(options);
413 catch (
const ctkPluginException& exc)
415 CX_LOG_CHANNEL_WARNING(
"plugin") << QString(
"Failed to stop plugin %1: ").arg(symbolicName).arg(exc.what());
424 QSharedPointer<ctkPlugin> empty;
426 if (!this->frameworkInitialized())
429 QString pluginPath = this->getPluginPath(symbolicName);
430 if (pluginPath.isEmpty())
434 QList < QSharedPointer<ctkPlugin> > plugins = pc->getPlugins();
435 foreach(QSharedPointer<ctkPlugin> plugin, plugins)
437 if (plugin->getSymbolicName() == symbolicName)
447 QString PluginFrameworkManager::getPluginPath(
const QString& symbolicName)
449 QString pluginFileName(symbolicName);
450 pluginFileName.replace(
".",
"_");
451 foreach(QString searchPath, mPluginSearchPaths)
453 QDirIterator dirIter(searchPath, mPluginLibFilter, QDir::Files, QDirIterator::Subdirectories);
454 while(dirIter.hasNext())
457 QFileInfo fileInfo = dirIter.fileInfo();
458 QString fileBaseName = fileInfo.baseName();
459 if (fileBaseName.startsWith(
"lib")) fileBaseName = fileBaseName.mid(3);
461 if (fileBaseName == pluginFileName)
463 return fileInfo.canonicalFilePath();
474 foreach(QString searchPath, mPluginSearchPaths)
478 result.removeDuplicates();
485 QDirIterator dirIter(searchPath, mPluginLibFilter, QDir::Files, QDirIterator::Subdirectories);
486 while (dirIter.hasNext())
489 QFileInfo fileInfo = dirIter.fileInfo();
490 QString fileBaseName = fileInfo.baseName();
491 if (fileBaseName.startsWith(
"lib"))
492 fileBaseName = fileBaseName.mid(3);
493 QString name = fileBaseName.replace(
"_",
".");
494 if (this->nameIsProbablyPlugin(name))
501 bool PluginFrameworkManager::nameIsProbablyPlugin(QString name)
const
504 if (name.count(
".")<2)
506 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)