14 #include <QApplication> 15 #include <QStringList> 16 #include <QDirIterator> 20 #include "ctkPluginFrameworkFactory.h" 21 #include "ctkPluginFramework.h" 22 #include "ctkPluginContext.h" 23 #include "ctkPluginException.h" 25 #include <ctkConfig.h> 42 mSettingsBase =
"pluginFramework";
43 mSettingsSearchPaths = mSettingsBase +
"/searchPaths";
45 ctkProperties fwProps;
48 fwProps[ctkPluginConstants::FRAMEWORK_STORAGE] = storagePath;
52 fwProps[ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN] = ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT;
54 mFrameworkFactory.reset(
new ctkPluginFrameworkFactory(fwProps));
55 mPluginLibFilter <<
"*.dll" <<
"*.so" <<
"*.dylib";
60 if(mFramework->getState() == ctkPlugin::ACTIVE)
62 CX_LOG_CHANNEL_WARNING(
"plugin") <<
"This should not happen: PluginFrameworkManager destructor stopping plugin framework";
67 QString PluginFrameworkManager::convertToRelativePath(QString path)
const 69 QDir base = qApp->applicationDirPath();
70 return base.relativeFilePath(path);
73 QString PluginFrameworkManager::convertToAbsolutePath(QString path)
const 75 if (QDir(path).isAbsolute())
76 return QDir(path).absolutePath();
78 QDir base = qApp->applicationDirPath();
79 return QDir(base.path() +
"/" + path).absolutePath();
84 std::vector<PluginFrameworkManager::PluginLoadInfo> PluginFrameworkManager::getPluginLoadInfo(QStringList symbolicNames)
86 std::vector<PluginLoadInfo> retval;
88 for (
unsigned i=0; i<symbolicNames.size(); ++i)
91 info.symbolicName = symbolicNames[i];
92 info.storedState =
settings()->
value(mSettingsBase+
"/"+info.symbolicName).toString();
94 if (info.storedState.isEmpty())
106 retval.push_back(info);
114 QStringList paths =
settings()->
value(mSettingsSearchPaths, QStringList()).toStringList();
118 std::vector<PluginLoadInfo> info = this->getPluginLoadInfo(names);
122 for (
unsigned i=0; i< info.size(); ++i)
124 if (info[i].targetState != ctkPlugin::UNINSTALLED)
126 this->
install(info[i].symbolicName);
131 for (
unsigned i=0; i< info.size(); ++i)
133 if (info[i].targetState == ctkPlugin::ACTIVE)
136 CX_LOG_CHANNEL_INFO(
"plugin") << QString(
"Autostarting plugin %1").arg(info[i].symbolicName);
140 this->
start(info[i].symbolicName, ctkPlugin::START_TRANSIENT);
145 .arg(info[i].symbolicName)
146 .arg(info[i].storedState);
152 void PluginFrameworkManager::saveState()
154 QStringList relativePaths;
155 for (
int i=0; i<mPluginSearchPaths.size(); ++i)
156 relativePaths << this->convertToRelativePath(mPluginSearchPaths[i]);
160 for (
unsigned i=0; i<names.size(); ++i)
162 QString name = names[i];
170 ctkPlugin::State state = ctkPlugin::UNINSTALLED;
173 state = plugin->getState();
179 mPluginSearchPaths.clear();
181 for (
int i=0; i<searchPath.size(); ++i)
182 mPluginSearchPaths << this->convertToAbsolutePath(searchPath[i]);
185 for (
unsigned i=0; i<defPaths.size(); ++i)
187 QString defPath = this->convertToAbsolutePath(defPaths[i]);
188 if (!mPluginSearchPaths.count(defPath))
189 mPluginSearchPaths << defPath;
192 mPluginSearchPaths.removeDuplicates();
194 for (
int i=0; i<searchPath.size(); ++i)
196 QApplication::addLibraryPath(searchPath[i]);
204 return mPluginSearchPaths;
209 return mFramework->getPluginContext();
217 void PluginFrameworkManager::initializeFramework()
219 if (this->frameworkInitialized())
224 QSharedPointer<ctkPluginFramework> framework = mFrameworkFactory->getFramework();
229 }
catch (
const ctkException& exc)
231 this->handlePluginException(
"Failed to initialize the plug-in framework", exc);
233 mFramework = framework;
236 bool PluginFrameworkManager::frameworkInitialized()
const 238 return mFramework != 0;
241 bool PluginFrameworkManager::frameworkStarted()
const 243 return mFramework && (mFramework->getState() == ctkPlugin::ACTIVE);
246 void PluginFrameworkManager::startFramework()
248 if (!this->frameworkInitialized())
249 this->initializeFramework();
251 if (this->frameworkStarted())
258 catch (
const ctkException& exc)
260 this->handlePluginException(
"Failed to start the plug-in framework", exc);
266 this->initializeFramework();
267 if (!this->frameworkInitialized())
270 QString pluginPath = this->getPluginPath(symbolicName);
271 if (pluginPath.isEmpty())
277 pc->installPlugin(QUrl::fromLocalFile(pluginPath))->getPluginId();
279 catch (
const ctkException& exc)
281 this->handlePluginException(QString(
"Failed to install plugin %1").arg(symbolicName), exc);
287 this->startFramework();
288 return this->frameworkStarted();
303 for (
int i=0; i<plugins.size(); ++i)
305 this->
stop(plugins[i]);
312 ctkPluginFrameworkEvent fe = mFramework->waitForStop(5000);
321 if (fe.getType() == ctkPluginFrameworkEvent::FRAMEWORK_WAIT_TIMEDOUT)
327 catch (
const ctkException& exc)
329 this->handlePluginException(
"Failed to stop the plug-in framework", exc);
332 return !this->frameworkStarted();
337 QString pluginPath = getPluginPath(symbolicName);
338 if (pluginPath.isEmpty())
344 pc->installPlugin(QUrl::fromLocalFile(pluginPath))->uninstall();
346 catch (
const ctkException& exc)
348 this->handlePluginException(QString(
"Failed to uninstall plugin %1.").arg(symbolicName), exc);
357 this->startFramework();
359 QString pluginPath = getPluginPath(symbolicName);
360 if (pluginPath.isEmpty())
362 CX_LOG_CHANNEL_ERROR(
"plugin") << QString(
"Failed to find plugin %1 in search path.").arg(symbolicName);
369 QSharedPointer<ctkPlugin> plugin = pc->installPlugin(QUrl::fromLocalFile(pluginPath));
370 plugin->start(options);
372 catch (ctkException& exc)
374 this->handlePluginException(QString(
"Failed to stop plugin %1.").arg(symbolicName), exc);
381 void PluginFrameworkManager::handlePluginException(
const QString& message,
const ctkException& exc)
384 const ctkException* nest = &exc;
388 nest = nest->cause();
394 if (!this->frameworkStarted())
396 QString pluginPath = this->getPluginPath(symbolicName);
397 if (pluginPath.isEmpty())
410 plugin->stop(options);
412 catch (
const ctkException& exc)
414 this->handlePluginException(QString(
"Failed to stop plugin %1").arg(symbolicName), exc);
423 QSharedPointer<ctkPlugin> empty;
425 if (!this->frameworkInitialized())
428 QString pluginPath = this->getPluginPath(symbolicName);
429 if (pluginPath.isEmpty())
433 QList < QSharedPointer<ctkPlugin> > plugins = pc->getPlugins();
434 foreach(QSharedPointer<ctkPlugin> plugin, plugins)
436 if (plugin->getSymbolicName() == symbolicName)
446 QString PluginFrameworkManager::getPluginPath(
const QString& symbolicName)
448 QString pluginFileName(symbolicName);
449 pluginFileName.replace(
".",
"_");
450 foreach(QString searchPath, mPluginSearchPaths)
452 QDirIterator dirIter(searchPath, mPluginLibFilter, QDir::Files, QDirIterator::Subdirectories);
453 while(dirIter.hasNext())
456 QFileInfo fileInfo = dirIter.fileInfo();
457 QString fileBaseName = fileInfo.baseName();
458 if (fileBaseName.startsWith(
"lib")) fileBaseName = fileBaseName.mid(3);
460 if (fileBaseName == pluginFileName)
462 return fileInfo.canonicalFilePath();
473 foreach(QString searchPath, mPluginSearchPaths)
477 result.removeDuplicates();
484 QDirIterator dirIter(searchPath, mPluginLibFilter, QDir::Files, QDirIterator::Subdirectories);
485 while (dirIter.hasNext())
488 QFileInfo fileInfo = dirIter.fileInfo();
489 QString fileBaseName = fileInfo.baseName();
490 if (fileBaseName.startsWith(
"lib"))
491 fileBaseName = fileBaseName.mid(3);
492 QString name = fileBaseName.replace(
"_",
".");
493 if (this->nameIsProbablyPlugin(name))
500 bool PluginFrameworkManager::nameIsProbablyPlugin(QString name)
const 503 return name.startsWith(
"org.custusx");
#define CX_LOG_CHANNEL_INFO(channel)
~PluginFrameworkManager()
QStringList getPluginSymbolicNames()
ctkPlugin::State getStateFromSymbolicName(QString name)
#define CX_LOG_CHANNEL_WARNING(channel)
QStringList getSearchPaths() const
static ProfileManager * getInstance(QString defaultProfile=QString("Laboratory"))
returns the only instance of this class
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)
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)
Namespace for all CustusX production code.