|
@@ -27,242 +27,328 @@
|
|
|
#include "ctkPluginFrameworkContext_p.h"
|
|
|
#include "ctkPluginFrameworkUtil_p.h"
|
|
|
#include "ctkPluginActivator.h"
|
|
|
+#include "ctkPluginContext_p.h"
|
|
|
|
|
|
+#include "ctkServiceReferencePrivate.h"
|
|
|
|
|
|
- const ctkPlugin::States ctkPluginPrivate::RESOLVED_FLAGS = ctkPlugin::RESOLVED | ctkPlugin::STARTING | ctkPlugin::ACTIVE | ctkPlugin::STOPPING;
|
|
|
+const ctkPlugin::States ctkPluginPrivate::RESOLVED_FLAGS = ctkPlugin::RESOLVED | ctkPlugin::STARTING | ctkPlugin::ACTIVE | ctkPlugin::STOPPING;
|
|
|
|
|
|
|
|
|
- ctkPluginPrivate::ctkPluginPrivate(
|
|
|
- ctkPlugin& qq,
|
|
|
- ctkPluginFrameworkContext* fw,
|
|
|
- ctkPluginArchive* pa)
|
|
|
- : q_ptr(&qq), fwCtx(fw), id(pa->getPluginId()),
|
|
|
- location(pa->getPluginLocation().toString()), state(ctkPlugin::INSTALLED),
|
|
|
- archive(pa), pluginContext(0), pluginActivator(0), pluginLoader(pa->getLibLocation()),
|
|
|
- lastModified(0), eagerActivation(false), activating(false), deactivating(false)
|
|
|
+ctkPluginPrivate::ctkPluginPrivate(
|
|
|
+ ctkPlugin& qq,
|
|
|
+ ctkPluginFrameworkContext* fw,
|
|
|
+ ctkPluginArchive* pa)
|
|
|
+ : q_ptr(&qq), fwCtx(fw), id(pa->getPluginId()),
|
|
|
+ location(pa->getPluginLocation().toString()), state(ctkPlugin::INSTALLED),
|
|
|
+ archive(pa), pluginContext(0), pluginActivator(0), pluginLoader(pa->getLibLocation()),
|
|
|
+ lastModified(0), eagerActivation(false), activating(false), deactivating(false)
|
|
|
+{
|
|
|
+ //TODO
|
|
|
+ //checkCertificates(pa);
|
|
|
+
|
|
|
+ checkManifestHeaders();
|
|
|
+
|
|
|
+ // fill require list
|
|
|
+ QString requireString = archive->getAttribute(PluginConstants::REQUIRE_PLUGIN);
|
|
|
+ QList<QMap<QString, QStringList> > requireList = ctkPluginFrameworkUtil::parseEntries(PluginConstants::REQUIRE_PLUGIN,
|
|
|
+ requireString, true, true, false);
|
|
|
+ QListIterator<QMap<QString, QStringList> > i(requireList);
|
|
|
+ while (i.hasNext())
|
|
|
{
|
|
|
- //TODO
|
|
|
- //checkCertificates(pa);
|
|
|
+ const QMap<QString, QStringList>& e = i.next();
|
|
|
+ const QStringList& res = e.value(PluginConstants::RESOLUTION_DIRECTIVE);
|
|
|
+ const QStringList& version = e.value(PluginConstants::PLUGIN_VERSION_ATTRIBUTE);
|
|
|
+ ctkRequirePlugin* rp = new ctkRequirePlugin(this, e.value("$key").front(),
|
|
|
+ res.empty() ? QString() : res.front(),
|
|
|
+ version.empty() ? QString() : version.front());
|
|
|
+ require.push_back(rp);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+ctkPluginPrivate::ctkPluginPrivate(ctkPlugin& qq,
|
|
|
+ ctkPluginFrameworkContext* fw,
|
|
|
+ long id, const QString& loc, const QString& sym, const ctkVersion& ver)
|
|
|
+ : q_ptr(&qq), fwCtx(fw), id(id), location(loc), symbolicName(sym), version(ver),
|
|
|
+ state(ctkPlugin::INSTALLED), archive(0), pluginContext(0),
|
|
|
+ pluginActivator(0), lastModified(0),
|
|
|
+ eagerActivation(false), activating(false), deactivating(false)
|
|
|
+{
|
|
|
+
|
|
|
+}
|
|
|
|
|
|
- checkManifestHeaders();
|
|
|
+ctkPluginPrivate::~ctkPluginPrivate()
|
|
|
+{
|
|
|
+ qDeleteAll(require);
|
|
|
+}
|
|
|
+
|
|
|
+ctkPlugin::State ctkPluginPrivate::getUpdatedState()
|
|
|
+{
|
|
|
+ if (state & ctkPlugin::INSTALLED)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (state == ctkPlugin::INSTALLED)
|
|
|
+ {
|
|
|
+ fwCtx->resolvePlugin(this);
|
|
|
+ state = ctkPlugin::RESOLVED;
|
|
|
+ fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::RESOLVED, this->q_func()));
|
|
|
+ }
|
|
|
|
|
|
- // fill require list
|
|
|
- QString requireString = archive->getAttribute(PluginConstants::REQUIRE_PLUGIN);
|
|
|
- QList<QMap<QString, QStringList> > requireList = ctkPluginFrameworkUtil::parseEntries(PluginConstants::REQUIRE_PLUGIN,
|
|
|
- requireString, true, true, false);
|
|
|
- QListIterator<QMap<QString, QStringList> > i(requireList);
|
|
|
- while (i.hasNext())
|
|
|
+ }
|
|
|
+ catch (const ctkPluginException& pe)
|
|
|
{
|
|
|
- const QMap<QString, QStringList>& e = i.next();
|
|
|
- const QStringList& res = e.value(PluginConstants::RESOLUTION_DIRECTIVE);
|
|
|
- const QStringList& version = e.value(PluginConstants::PLUGIN_VERSION_ATTRIBUTE);
|
|
|
- ctkRequirePlugin* rp = new ctkRequirePlugin(this, e.value("$key").front(),
|
|
|
- res.empty() ? QString() : res.front(),
|
|
|
- version.empty() ? QString() : version.front());
|
|
|
- require.push_back(rp);
|
|
|
+ Q_Q(ctkPlugin);
|
|
|
+ this->fwCtx->listeners.frameworkError(q, pe);
|
|
|
+ throw;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- ctkPluginPrivate::ctkPluginPrivate(ctkPlugin& qq,
|
|
|
- ctkPluginFrameworkContext* fw,
|
|
|
- long id, const QString& loc, const QString& sym, const ctkVersion& ver)
|
|
|
- : q_ptr(&qq), fwCtx(fw), id(id), location(loc), symbolicName(sym), version(ver),
|
|
|
- state(ctkPlugin::INSTALLED), archive(0), pluginContext(0),
|
|
|
- pluginActivator(0), lastModified(0),
|
|
|
- eagerActivation(false), activating(false), deactivating(false)
|
|
|
- {
|
|
|
+ return state;
|
|
|
+}
|
|
|
|
|
|
+void ctkPluginPrivate::setAutostartSetting(const ctkPlugin::StartOptions& setting) {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (archive)
|
|
|
+ {
|
|
|
+ archive->setAutostartSetting(setting);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- ctkPluginPrivate::~ctkPluginPrivate()
|
|
|
+ catch (const ctkPluginDatabaseException& e)
|
|
|
{
|
|
|
- qDeleteAll(require);
|
|
|
+ Q_Q(ctkPlugin);
|
|
|
+ this->fwCtx->listeners.frameworkError(q, e);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- ctkPlugin::State ctkPluginPrivate::getUpdatedState()
|
|
|
+void ctkPluginPrivate::ignoreAutostartSetting()
|
|
|
+{
|
|
|
+ try
|
|
|
{
|
|
|
- if (state & ctkPlugin::INSTALLED)
|
|
|
+ if (archive)
|
|
|
{
|
|
|
- try
|
|
|
- {
|
|
|
- if (state == ctkPlugin::INSTALLED)
|
|
|
- {
|
|
|
- fwCtx->resolvePlugin(this);
|
|
|
- state = ctkPlugin::RESOLVED;
|
|
|
- fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::RESOLVED, this->q_func()));
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- catch (const ctkPluginException& pe)
|
|
|
- {
|
|
|
- Q_Q(ctkPlugin);
|
|
|
- this->fwCtx->listeners.frameworkError(q, pe);
|
|
|
- throw;
|
|
|
- }
|
|
|
+ archive->setAutostartSetting(-1);
|
|
|
}
|
|
|
+ }
|
|
|
+ catch (const ctkPluginDatabaseException& e)
|
|
|
+ {
|
|
|
+ Q_Q(ctkPlugin);
|
|
|
+ this->fwCtx->listeners.frameworkError(q, e);
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- return state;
|
|
|
+void ctkPluginPrivate::checkManifestHeaders()
|
|
|
+{
|
|
|
+ symbolicName = archive->getAttribute(PluginConstants::PLUGIN_SYMBOLICNAME);
|
|
|
+
|
|
|
+ if (symbolicName.isEmpty())
|
|
|
+ {
|
|
|
+ throw std::invalid_argument(std::string("ctkPlugin has no symbolic name, location=") +
|
|
|
+ qPrintable(location));
|
|
|
}
|
|
|
|
|
|
- void ctkPluginPrivate::setAutostartSetting(const ctkPlugin::StartOptions& setting) {
|
|
|
+ QString mpv = archive->getAttribute(PluginConstants::PLUGIN_VERSION);
|
|
|
+ if (!mpv.isEmpty())
|
|
|
+ {
|
|
|
try
|
|
|
{
|
|
|
- if (archive)
|
|
|
- {
|
|
|
- archive->setAutostartSetting(setting);
|
|
|
- }
|
|
|
+ version = ctkVersion(mpv);
|
|
|
}
|
|
|
- catch (const ctkPluginDatabaseException& e)
|
|
|
+ catch (const std::exception& e)
|
|
|
{
|
|
|
- Q_Q(ctkPlugin);
|
|
|
- this->fwCtx->listeners.frameworkError(q, e);
|
|
|
+ throw std::invalid_argument(std::string("ctkPlugin does not specify a valid ") +
|
|
|
+ qPrintable(PluginConstants::PLUGIN_VERSION) + " header. Got exception: " + e.what());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- void ctkPluginPrivate::checkManifestHeaders()
|
|
|
+ QString ap = archive->getAttribute(PluginConstants::PLUGIN_ACTIVATIONPOLICY);
|
|
|
+ if (PluginConstants::ACTIVATION_EAGER == ap)
|
|
|
{
|
|
|
- symbolicName = archive->getAttribute(PluginConstants::PLUGIN_SYMBOLICNAME);
|
|
|
+ eagerActivation = true;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
|
|
|
- if (symbolicName.isEmpty())
|
|
|
+void ctkPluginPrivate::finalizeActivation()
|
|
|
+{
|
|
|
+ switch (getUpdatedState())
|
|
|
+ {
|
|
|
+ case ctkPlugin::INSTALLED:
|
|
|
+ // we shouldn't be here, getUpdatedState should have thrown
|
|
|
+ // an exception during resolving the plugin
|
|
|
+ throw ctkPluginException("Internal error: expected exception on plugin resolve not thrown!");
|
|
|
+ case ctkPlugin::STARTING:
|
|
|
+ if (activating) return; // finalization already in progress.
|
|
|
+ // Lazy activation; fall through to RESOLVED.
|
|
|
+ case ctkPlugin::RESOLVED:
|
|
|
+ //6:
|
|
|
+ state = ctkPlugin::STARTING;
|
|
|
+ activating = true;
|
|
|
+ qDebug() << "activating #" << this->id;
|
|
|
+ //7:
|
|
|
+ if (!pluginContext)
|
|
|
+ {
|
|
|
+ pluginContext = new ctkPluginContext(this);
|
|
|
+ }
|
|
|
+ try
|
|
|
{
|
|
|
- throw std::invalid_argument(std::string("ctkPlugin has no symbolic name, location=") +
|
|
|
- qPrintable(location));
|
|
|
+ //TODO maybe call this in its own thread
|
|
|
+ start0();
|
|
|
}
|
|
|
+ catch (...)
|
|
|
+ {
|
|
|
+ //8:
|
|
|
+ state = ctkPlugin::STOPPING;
|
|
|
+ // NYI, call outside lock
|
|
|
+ fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::STOPPING, this->q_func()));
|
|
|
+ removePluginResources();
|
|
|
+ delete pluginContext;
|
|
|
+
|
|
|
+ state = ctkPlugin::RESOLVED;
|
|
|
+ // NYI, call outside lock
|
|
|
+ fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::STOPPED, this->q_func()));
|
|
|
+ activating = false;
|
|
|
+ throw;
|
|
|
+ }
|
|
|
+ activating = false;
|
|
|
+ break;
|
|
|
+ case ctkPlugin::ACTIVE:
|
|
|
+ break;
|
|
|
+ case ctkPlugin::STOPPING:
|
|
|
+ // This happens if start is called from inside the ctkPluginActivator::stop method.
|
|
|
+ // Don't allow it.
|
|
|
+ throw ctkPluginException("start called from ctkPluginActivator::stop",
|
|
|
+ ctkPluginException::ACTIVATOR_ERROR);
|
|
|
+ case ctkPlugin::UNINSTALLED:
|
|
|
+ throw std::logic_error("ctkPlugin is in UNINSTALLED state");
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- QString mpv = archive->getAttribute(PluginConstants::PLUGIN_VERSION);
|
|
|
- if (!mpv.isEmpty())
|
|
|
+void ctkPluginPrivate::stop0(bool wasStarted)
|
|
|
+{
|
|
|
+ //5:
|
|
|
+ state = ctkPlugin::STOPPING;
|
|
|
+ deactivating = true;
|
|
|
+ //6-13:
|
|
|
+ const std::exception* savedException = 0;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //6:
|
|
|
+ fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::STOPPING, q_func()));
|
|
|
+
|
|
|
+ //7:
|
|
|
+ if (wasStarted && pluginActivator)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
- version = ctkVersion(mpv);
|
|
|
+ pluginActivator->stop(pluginContext);
|
|
|
}
|
|
|
catch (const std::exception& e)
|
|
|
{
|
|
|
- throw std::invalid_argument(std::string("ctkPlugin does not specify a valid ") +
|
|
|
- qPrintable(PluginConstants::PLUGIN_VERSION) + " header. Got exception: " + e.what());
|
|
|
+ savedException = new ctkPluginException("ctkPlugin::stop: PluginActivator stop failed",
|
|
|
+ ctkPluginException::ACTIVATOR_ERROR, e);
|
|
|
+ }
|
|
|
+ if (state == ctkPlugin::UNINSTALLED)
|
|
|
+ {
|
|
|
+ throw std::logic_error("Plugin is uninstalled");
|
|
|
}
|
|
|
+ pluginActivator = 0;
|
|
|
}
|
|
|
|
|
|
- QString ap = archive->getAttribute(PluginConstants::PLUGIN_ACTIVATIONPOLICY);
|
|
|
- if (PluginConstants::ACTIVATION_EAGER == ap)
|
|
|
+ // Call hooks after we've called PluginActivator::stop(), but before we've cleared all resources
|
|
|
+ // TODO service listener hooks
|
|
|
+ //fwCtx->listeners.serviceListeners.hooksBundleStopped(this);
|
|
|
+
|
|
|
+ if (pluginContext)
|
|
|
{
|
|
|
- eagerActivation = true;
|
|
|
+ pluginContext->d_func()->invalidate();
|
|
|
+ pluginContext = 0;
|
|
|
}
|
|
|
-
|
|
|
+ //8-10:
|
|
|
+ removePluginResources();
|
|
|
+ }
|
|
|
+ catch (const std::exception* exc)
|
|
|
+ {
|
|
|
+ savedException = exc;
|
|
|
}
|
|
|
|
|
|
- void ctkPluginPrivate::finalizeActivation()
|
|
|
+ if (state != ctkPlugin::UNINSTALLED)
|
|
|
{
|
|
|
- switch (getUpdatedState())
|
|
|
- {
|
|
|
- case ctkPlugin::INSTALLED:
|
|
|
- // we shouldn't be here, getUpdatedState should have thrown
|
|
|
- // an exception during resolving the plugin
|
|
|
- throw ctkPluginException("Internal error: expected exception on plugin resolve not thrown!");
|
|
|
- case ctkPlugin::STARTING:
|
|
|
- if (activating) return; // finalization already in progress.
|
|
|
- // Lazy activation; fall through to RESOLVED.
|
|
|
- case ctkPlugin::RESOLVED:
|
|
|
- //6:
|
|
|
- state = ctkPlugin::STARTING;
|
|
|
- activating = true;
|
|
|
- qDebug() << "activating #" << this->id;
|
|
|
- //7:
|
|
|
- if (!pluginContext)
|
|
|
- {
|
|
|
- pluginContext = new ctkPluginContext(this);
|
|
|
- }
|
|
|
- try
|
|
|
- {
|
|
|
- //TODO maybe call this in its own thread
|
|
|
- start0();
|
|
|
- }
|
|
|
- catch (...)
|
|
|
- {
|
|
|
- //8:
|
|
|
- state = ctkPlugin::STOPPING;
|
|
|
- // NYI, call outside lock
|
|
|
- fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::STOPPING, this->q_func()));
|
|
|
- removePluginResources();
|
|
|
- delete pluginContext;
|
|
|
-
|
|
|
- state = ctkPlugin::RESOLVED;
|
|
|
- // NYI, call outside lock
|
|
|
- fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::STOPPED, this->q_func()));
|
|
|
- activating = false;
|
|
|
- throw;
|
|
|
- }
|
|
|
- activating = false;
|
|
|
- break;
|
|
|
- case ctkPlugin::ACTIVE:
|
|
|
- break;
|
|
|
- case ctkPlugin::STOPPING:
|
|
|
- // This happens if start is called from inside the ctkPluginActivator::stop method.
|
|
|
- // Don't allow it.
|
|
|
- throw ctkPluginException("start called from ctkPluginActivator::stop",
|
|
|
- ctkPluginException::ACTIVATOR_ERROR);
|
|
|
- case ctkPlugin::UNINSTALLED:
|
|
|
- throw std::logic_error("ctkPlugin is in UNINSTALLED state");
|
|
|
- }
|
|
|
+ state = ctkPlugin::RESOLVED;
|
|
|
+ deactivating = false;
|
|
|
+ //fwCtx.packages.notifyAll();
|
|
|
}
|
|
|
|
|
|
- void ctkPluginPrivate::start0()
|
|
|
+ if (savedException)
|
|
|
{
|
|
|
- fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::STARTING, this->q_func()));
|
|
|
+ throw savedException;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- try {
|
|
|
- pluginLoader.load();
|
|
|
- if (!pluginLoader.isLoaded())
|
|
|
- {
|
|
|
- throw ctkPluginException(QString("Loading plugin %1 failed: %2").arg(pluginLoader.fileName()).arg(pluginLoader.errorString()),
|
|
|
- ctkPluginException::ACTIVATOR_ERROR);
|
|
|
- }
|
|
|
+void ctkPluginPrivate::start0()
|
|
|
+{
|
|
|
+ fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::STARTING, this->q_func()));
|
|
|
|
|
|
- pluginActivator = qobject_cast<ctkPluginActivator*>(pluginLoader.instance());
|
|
|
- if (!pluginActivator)
|
|
|
- {
|
|
|
- throw ctkPluginException(QString("Creating ctkPluginActivator instance from %1 failed: %2").arg(pluginLoader.fileName()).arg(pluginLoader.errorString()),
|
|
|
- ctkPluginException::ACTIVATOR_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- pluginActivator->start(pluginContext);
|
|
|
+ try {
|
|
|
+ pluginLoader.load();
|
|
|
+ if (!pluginLoader.isLoaded())
|
|
|
+ {
|
|
|
+ throw ctkPluginException(QString("Loading plugin %1 failed: %2").arg(pluginLoader.fileName()).arg(pluginLoader.errorString()),
|
|
|
+ ctkPluginException::ACTIVATOR_ERROR);
|
|
|
+ }
|
|
|
|
|
|
- if (ctkPlugin::UNINSTALLED == state)
|
|
|
- {
|
|
|
- throw ctkPluginException("ctkPlugin uninstalled during start()", ctkPluginException::STATECHANGE_ERROR);
|
|
|
- }
|
|
|
- state = ctkPlugin::ACTIVE;
|
|
|
+ pluginActivator = qobject_cast<ctkPluginActivator*>(pluginLoader.instance());
|
|
|
+ if (!pluginActivator)
|
|
|
+ {
|
|
|
+ throw ctkPluginException(QString("Creating ctkPluginActivator instance from %1 failed: %2").arg(pluginLoader.fileName()).arg(pluginLoader.errorString()),
|
|
|
+ ctkPluginException::ACTIVATOR_ERROR);
|
|
|
}
|
|
|
- catch (const std::exception& e)
|
|
|
+
|
|
|
+ pluginActivator->start(pluginContext);
|
|
|
+
|
|
|
+ if (ctkPlugin::UNINSTALLED == state)
|
|
|
{
|
|
|
- throw ctkPluginException("ctkPlugin start failed", ctkPluginException::ACTIVATOR_ERROR, e);
|
|
|
+ throw ctkPluginException("ctkPlugin uninstalled during start()", ctkPluginException::STATECHANGE_ERROR);
|
|
|
}
|
|
|
+ state = ctkPlugin::ACTIVE;
|
|
|
+ }
|
|
|
+ catch (const std::exception& e)
|
|
|
+ {
|
|
|
+ throw ctkPluginException("ctkPlugin start failed", ctkPluginException::ACTIVATOR_ERROR, e);
|
|
|
+ }
|
|
|
+
|
|
|
+ qDebug() << "activating #" << id << "completed.";
|
|
|
+
|
|
|
+ //10:
|
|
|
+ fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::STARTED, this->q_func()));
|
|
|
+}
|
|
|
|
|
|
- qDebug() << "activating #" << id << "completed.";
|
|
|
+void ctkPluginPrivate::removePluginResources()
|
|
|
+{
|
|
|
+ // automatic disconnect due to Qt signal slot
|
|
|
+ //fwCtx->listeners.removeAllListeners(this);
|
|
|
|
|
|
- //10:
|
|
|
- fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::STARTED, this->q_func()));
|
|
|
+ QList<ctkServiceRegistration*> srs = fwCtx->services.getRegisteredByPlugin(this);
|
|
|
+ QListIterator<ctkServiceRegistration*> i(srs);
|
|
|
+ while (i.hasNext())
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ i.next()->unregister();
|
|
|
+ }
|
|
|
+ catch (const std::logic_error& ignore)
|
|
|
+ {
|
|
|
+ // Someone has unregistered the service after stop completed.
|
|
|
+ // This should not occur, but we don't want get stuck in
|
|
|
+ // an illegal state so we catch it.
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- void ctkPluginPrivate::removePluginResources()
|
|
|
+ QList<ctkServiceRegistration*> s = fwCtx->services.getUsedByPlugin(q_func());
|
|
|
+ QListIterator<ctkServiceRegistration*> i2(s);
|
|
|
+ while (i2.hasNext())
|
|
|
{
|
|
|
- // automatic disconnect due to Qt signal slot
|
|
|
- //fwCtx->listeners.removeAllListeners(this);
|
|
|
-
|
|
|
- // TODO
|
|
|
-// Set srs = fwCtx.services.getRegisteredByBundle(this);
|
|
|
-// for (Iterator i = srs.iterator(); i.hasNext();) {
|
|
|
-// try {
|
|
|
-// ((ctkServiceRegistration)i.next()).unregister();
|
|
|
-// } catch (IllegalStateException ignore) {
|
|
|
-// // Someone has unregistered the service after stop completed.
|
|
|
-// // This should not occur, but we don't want get stuck in
|
|
|
-// // an illegal state so we catch it.
|
|
|
-// }
|
|
|
-// }
|
|
|
-// Set s = fwCtx.services.getUsedByBundle(this);
|
|
|
-// for (Iterator i = s.iterator(); i.hasNext(); ) {
|
|
|
-// ((ServiceRegistrationImpl) i.next()).reference.ungetService(this, false);
|
|
|
-// }
|
|
|
+ i2.next()->getReference().d_func()->ungetService(q_func(), false);
|
|
|
+ }
|
|
|
|
|
|
}
|