Пример #1
0
//----------------------------------------------------------------------------
ctkPlugin::State ctkPluginPrivate::getUpdatedState_unlocked()
{
  if (state & ctkPlugin::INSTALLED)
  {
    try
    {
      if (state == ctkPlugin::INSTALLED)
      {
        operation.fetchAndStoreOrdered(RESOLVING);
        fwCtx->resolvePlugin(this);
        state = ctkPlugin::RESOLVED;
        // TODO plugin threading
        //bundleThread().bundleChanged(new BundleEvent(BundleEvent.RESOLVED, this));
        fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::RESOLVED, this->q_func()));
        operation.fetchAndStoreOrdered(IDLE);
      }
    }
    catch (const ctkPluginException& pe)
    {
      if (resolveFailException) delete resolveFailException;
      resolveFailException = new ctkPluginException(pe);
      this->fwCtx->listeners.frameworkError(this->q_func(), pe);
    }
  }
  return state;
}
Пример #2
0
//----------------------------------------------------------------------------
void ctkPluginFrameworkPrivate::shutdown0(bool restart, bool wasActive)
{
  try
  {
    {
      Locker sync(&lock);
      waitOnOperation(&lock, QString("Framework::") + (restart ? "update" : "stop"), true);
      operation = DEACTIVATING;
      state = ctkPlugin::STOPPING;
    }

    fwCtx->listeners.emitPluginChanged(
        ctkPluginEvent(ctkPluginEvent::STOPPING, this->q_func()));

    if (wasActive)
    {
      stopAllPlugins();
    }

    {
      Locker sync(&lock);
      fwCtx->uninit();
      shuttingDown.fetchAndStoreOrdered(0);
      shutdownDone_unlocked(restart);
    }

    if (restart)
    {
      if (wasActive)
      {
        q_func().toStrongRef()->start();
      }
      else
      {
        init();
      }
    }
  }
  catch (const ctkException& e)
  {
    shuttingDown.fetchAndStoreOrdered(0);
    systemShuttingdownDone(ctkPluginFrameworkEvent(ctkPluginFrameworkEvent::PLUGIN_ERROR,
                                                   this->q_func(), e));
  }
}
Пример #3
0
//----------------------------------------------------------------------------
void ctkPluginPrivate::setStateInstalled(bool sendEvent)
{
  Locker sync(&operationLock);

  // Make sure that the context is invalid
  if (pluginContext != 0)
  {
    pluginContext->d_func()->invalidate();
    pluginContext.reset();
  }
  state = ctkPlugin::INSTALLED;
  if (sendEvent)
  {
    operation.fetchAndStoreOrdered(UNRESOLVING);
    // TODO: plugin thread
    //bundleThread().bundleChanged(new BundleEvent(BundleEvent.UNRESOLVED, this));
    fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::UNRESOLVED, this->q_func()));
  }
  operation.fetchAndStoreOrdered(IDLE);
}
Пример #4
0
//----------------------------------------------------------------------------
const ctkRuntimeException* ctkPluginPrivate::stop0()
{
  wasStarted = state == ctkPlugin::ACTIVE;
  // 5:
  state = ctkPlugin::STOPPING;
  operation.fetchAndStoreOrdered(DEACTIVATING);
  // 6-13:
  // TODO plugin threading
  //const ctkRuntimeException* savedException = pluginThread().callStop1(this);
  const ctkRuntimeException* savedException = stop1();
  if (state != ctkPlugin::UNINSTALLED)
  {
    state = ctkPlugin::RESOLVED;
    // TODO plugin threading
    //bundleThread().bundleChanged(new BundleEvent(BundleEvent.STOPPED, this));
    fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::STOPPED, this->q_func()));

    operationLock.wakeAll();
    operation.fetchAndStoreOrdered(IDLE);
  }
  return savedException;
}
Пример #5
0
void ctkPlugin::uninstall()
{
  bool wasResolved = false;

  Q_D(ctkPlugin);
  if (d->archive)
  {
    try
    {
      d->archive->setStartLevel(-2); // Mark as uninstalled
    }
    catch (...)
    { }
  }

  d->cachedHeaders = getHeaders();

  switch (d->state)
  {
  case UNINSTALLED:
    throw std::logic_error("Plugin is in UNINSTALLED state");

  case STARTING: // Lazy start
  case ACTIVE:
  case STOPPING:
    try
    {
      //TODO: If activating or deactivating, wait a litle
      // we don't use mutliple threads to start plugins for now
      //d->waitOnActivation(fwCtx.packages, "Bundle.uninstall", false);
      if (d->state & (ACTIVE | STARTING))
      {
        try
        {
          d->stop0(d->state == ACTIVE);
        }
        catch (const std::exception& exception)
        {
          // NYI! not call inside lock
          d->fwCtx->listeners.frameworkError(this, exception);
        }
      }
    }
    catch (const std::exception& e)
    {
      d->deactivating = false;
      //fwCtx.packages.notifyAll();
      d->fwCtx->listeners.frameworkError(this, e);
    }
    // Fall through
  case RESOLVED:
    wasResolved = true;
    // Fall through
  case INSTALLED:
    d->fwCtx->plugins->remove(d->location);
    d->pluginActivator = 0;

    if (d->pluginDir.exists())
    {
      if (!ctkPluginFrameworkUtil::removeDir(d->pluginDir.absolutePath()))
      {
        // Plugin dir is not deleted completely, make sure we mark
        // it as uninstalled for next framework restart
        if (d->archive)
        {
          try
          {
            d->archive->setStartLevel(-2); // Mark as uninstalled
          }
          catch (const std::exception& e)
          {
            // NYI! Generate FrameworkError if dir still exists!?
            qDebug() << "Failed to mark plugin" <<  d->id
                     << "as uninstalled," << d->pluginDir.absoluteFilePath()
                     << "must be deleted manually:" << e.what();
          }
        }
      }
      d->pluginDir.setFile("");
    }
    if (d->archive)
    {
      d->archive->purge();
    }

    // id, location and headers survive after uninstall.
    // TODO: UNRESOLVED must be sent out during installed state
    // This needs to be reviewed. See OSGi bug #1374
    d->state = INSTALLED;
    d->modified();

    // Broadcast events
    if (wasResolved)
    {
      d->fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::UNRESOLVED, d->q_ptr));
    }

    d->state = UNINSTALLED;
    d->fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::UNINSTALLED, d->q_ptr));

    break;
  }
}
Пример #6
0
//----------------------------------------------------------------------------
void ctkPluginPrivate::update0(const QUrl& updateLocation, bool wasActive)
{
  const bool wasResolved = state == ctkPlugin::RESOLVED;
  const int oldStartLevel = getStartLevel();
  QSharedPointer<ctkPluginArchive> newArchive;

  operation.fetchAndStoreOrdered(UPDATING);
  try
  {
    // New plugin as stream supplied?
    QUrl updateUrl(updateLocation);
    if (updateUrl.isEmpty())
    {
      // Try Plugin-UpdateLocation
      QString update = archive != 0 ? archive->getAttribute(ctkPluginConstants::PLUGIN_UPDATELOCATION) : QString();
      if (update.isEmpty())
      {
        // Take original location
        updateUrl = location;
      }
    }

    if(updateUrl.scheme() != "file")
    {
      QString msg = "Unsupported update URL:";
      msg += updateUrl.toString();
      throw ctkPluginException(msg);
    }

    newArchive = fwCtx->storage->updatePluginArchive(archive, updateUrl, updateUrl.toLocalFile());
    //checkCertificates(newArchive);
    checkManifestHeaders();
    newArchive->setStartLevel(oldStartLevel);
    fwCtx->storage->replacePluginArchive(archive, newArchive);
  }
  catch (const std::exception& e)
  {
    if (!newArchive.isNull())
    {
      newArchive->purge();
    }
    operation.fetchAndStoreOrdered(IDLE);
    if (wasActive)
    {
      try
      {
        this->q_func().data()->start();
      }
      catch (const ctkPluginException& pe)
      {
        fwCtx->listeners.frameworkError(this->q_func(), pe);
      }
    }
    try
    {
      const ctkPluginException& pe = dynamic_cast<const ctkPluginException&>(e);
      throw pe;
    }
    catch (std::bad_cast)
    {
      throw ctkPluginException(QString("Failed to get update plugin: ") + e.what(),
                               ctkPluginException::UNSPECIFIED);
    }
  }

  bool purgeOld = false;
  // TODO: check if dependent plug-ins are started. If not, set purgeOld to true.

  // Activate new plug-in
  QSharedPointer<ctkPluginArchive> oldArchive = archive;
  archive = newArchive;
  cachedRawHeaders.clear();
  state = ctkPlugin::INSTALLED;

  // Purge old archive
  if (purgeOld)
  {
    //secure.purge(this, oldProtectionDomain);
    if (oldArchive != 0)
    {
      oldArchive->purge();
    }
  }

  // Broadcast events
  if (wasResolved)
  {
    // TODO: use plugin threading
    //bundleThread().bundleChanged(new BundleEvent(BundleEvent.UNRESOLVED, this));
    fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::UNRESOLVED, this->q_func()));
  }
  //bundleThread().bundleChanged(new BundleEvent(BundleEvent.UPDATED, this));
  fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::UPDATED, this->q_func()));
  operation.fetchAndStoreOrdered(IDLE);

   // Restart plugin previously stopped in the operation
   if (wasActive)
   {
     try
     {
       this->q_func().data()->start();
     }
     catch (const ctkPluginException& pe)
     {
       fwCtx->listeners.frameworkError(this->q_func(), pe);
     }
   }
 }
Пример #7
0
//----------------------------------------------------------------------------
const ctkRuntimeException* ctkPluginPrivate::stop1()
{
  const ctkRuntimeException* res = 0;

  //6:
  fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::STOPPING, q_func()));

  //7:
  if (wasStarted && pluginActivator)
  {
    try
    {
      pluginActivator->stop(pluginContext.data());
      if (state != ctkPlugin::STOPPING)
      {
        if (state == ctkPlugin::UNINSTALLED)
        {
          return new ctkIllegalStateException("Plug-in is uninstalled");
        }
        else
        {
          return new ctkIllegalStateException("Plug-in changed state because of refresh during stop");
        }
      }
    }
    catch (const ctkException& e)
    {
      res = new ctkPluginException("ctkPlugin::stop: PluginActivator stop failed",
                                   ctkPluginException::ACTIVATOR_ERROR, e);
    }
    catch (...)
    {
      res = new ctkPluginException("ctkPlugin::stop: PluginActivator stop failed",
                                   ctkPluginException::ACTIVATOR_ERROR);
    }
    pluginActivator = 0;
  }

  if (operation.fetchAndAddOrdered(0) == DEACTIVATING)
  {
    // Call hooks after we've called PluginActivator::stop(), but before we've
    // cleared all resources
    if (pluginContext)
    {
      // TODO service listener hooks
      //fwCtx->listeners.serviceListeners.hooksBundleStopped(this);

      //8-10:
      removePluginResources();
      pluginContext->d_func()->invalidate();
      pluginContext.reset();
    }
  }

  // This would unload the shared library and delete the activator if
  // there are no dependencies. However, objects from the plug-in might
  // have been created via C-function symbol lookups. Hence we cannot
  // safely unload the DLL. Maybe implement a in-DLL counter later
  // (http://stackoverflow.com/questions/460809/c-dll-unloading-issue and
  // http://boost.2283326.n4.nabble.com/shared-ptr-A-smarter-smart-pointer-proposal-for-dynamic-libraries-td2649749.html).
  // The activator itself will be delete during program termination
  // (by the QPluginLoader instance).
  //pluginLoader.unload();

  return res;
}
Пример #8
0
//----------------------------------------------------------------------------
QSharedPointer<ctkPlugin> ctkPlugins::install(const QUrl& location, QIODevice* in)
{
  if (!fwCtx)
  { // This ctkPlugins instance has been closed!
    throw std::logic_error("ctkPlugins::install(location, inputStream) called on closed plugins object.");
  }

  {
    QWriteLocker lock(&pluginsLock);

    QHash<QString, QSharedPointer<ctkPlugin> >::const_iterator it = plugins.find(location.toString());
    if (it != plugins.end())
    {
      return it.value();
    }

    // install new plugin
    ctkPluginArchive* pa = 0;
    QString localPluginPath;
    try
    {
      if (!in)
      {
        // extract the input stream from the given location


        //          //TODO Support for http proxy authentication
        //          //TODO put in update as well
        //          String auth = fwCtx.props.getProperty("http.proxyAuth");
        //          if (auth != null && !"".equals(auth)) {
        //            if ("http".equals(url.getProtocol()) ||
        //                "https".equals(url.getProtocol())) {
        //              String base64 = Util.base64Encode(auth);
        //              conn.setRequestProperty("Proxy-Authorization",
        //                                      "Basic " + base64);
        //            }
        //          }
        //          // Support for http basic authentication
        //          String basicAuth = fwCtx.props.getProperty("http.basicAuth");
        //          if (basicAuth != null && !"".equals(basicAuth)) {
        //            if ("http".equals(url.getProtocol()) ||
        //                "https".equals(url.getProtocol())) {
        //              String base64 = Util.base64Encode(basicAuth);
        //              conn.setRequestProperty("Authorization",
        //                                      "Basic " +base64);
        //            }
        //          }

        if (location.scheme() != "file")
        {
          throw std::runtime_error(std::string("Unsupported url scheme: ") + qPrintable(location.scheme()));
        }
        else
        {
          qDebug() << QString("Trying to install file:") << location.path();
          localPluginPath = location.toLocalFile();
        }
      }
      else
      {
        //TODO copy the QIODevice to a local cache
      }

      pa = fwCtx->storage->insertPlugin(location, localPluginPath);

      QSharedPointer<ctkPlugin> res(new ctkPlugin());
      res->init(res, fwCtx, pa);
      plugins.insert(location.toString(), res);

      fwCtx->listeners.emitPluginChanged(ctkPluginEvent(ctkPluginEvent::INSTALLED, res));

      return res;
    }
    catch (const std::exception& e)
    {
      if (pa)
      {
        pa->purge();
      }
      //      if (dynamic_cast<const SecurityException&>(e)) {
      //        throw;
      //      }
      //      else
      //      {
      throw ctkPluginException(QString("Failed to install plugin: ") + QString(e.what()),
                               ctkPluginException::UNSPECIFIED, &e);
      //      }
    }
  }

}