| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 | /*=============================================================================  Library: CTK  Copyright (c) German Cancer Research Center,    Division of Medical and Biological Informatics  Licensed under the Apache License, Version 2.0 (the "License");  you may not use this file except in compliance with the License.  You may obtain a copy of the License at    http://www.apache.org/licenses/LICENSE-2.0  Unless required by applicable law or agreed to in writing, software  distributed under the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and  limitations under the License.=============================================================================*/#include <QStringList>#include <QDirIterator>#include <QFileInfo>#include <QDebug>#include "ctkPluginFrameworkLauncher.h"#include "ctkPluginFrameworkFactory.h"#include "ctkPluginFramework.h"#include "ctkPluginContext.h"#include "ctkPluginException.h"#ifdef _WIN32#include <windows.h>#include <cstdlib>#endif // _WIN32#include <ctkConfig.h>class ctkPluginFrameworkLauncherPrivate{public:  ctkPluginFrameworkLauncherPrivate()    : fwFactory(0)  {#ifdef CMAKE_INTDIR    QString pluginPath = CTK_PLUGIN_DIR CMAKE_INTDIR "/";#else    QString pluginPath = CTK_PLUGIN_DIR;#endif    pluginSearchPaths.append(pluginPath);    pluginLibFilter << "*.dll" << "*.so" << "*.dylib";  }  QStringList pluginSearchPaths;  QStringList pluginLibFilter;  ctkProperties fwProps;  ctkPluginFrameworkFactory* fwFactory;};const QScopedPointer<ctkPluginFrameworkLauncherPrivate> ctkPluginFrameworkLauncher::d(  new ctkPluginFrameworkLauncherPrivate());//----------------------------------------------------------------------------void ctkPluginFrameworkLauncher::setFrameworkProperties(const ctkProperties& props){  d->fwProps = props;}//----------------------------------------------------------------------------long ctkPluginFrameworkLauncher::install(const QString& symbolicName, ctkPluginContext* context){  QString pluginPath = getPluginPath(symbolicName);  if (pluginPath.isEmpty()) return -1;  ctkPluginContext* pc = context;  if (pc == 0 && d->fwFactory == 0) {    d->fwFactory = new ctkPluginFrameworkFactory(d->fwProps);    try    {      d->fwFactory->getFramework()->init();      pc = getPluginContext();    }    catch (const ctkPluginException& exc)    {      qCritical() << "Failed to initialize the plug-in framework:" << exc;      delete d->fwFactory;      d->fwFactory = 0;      return -1;    }  }  try  {    return pc->installPlugin(QUrl::fromLocalFile(pluginPath))->getPluginId();  }  catch (const ctkPluginException& exc)  {    qWarning() << "Failed to install plugin:" << exc;    return -1;  }}//----------------------------------------------------------------------------bool ctkPluginFrameworkLauncher::start(const QString& symbolicName, ctkPlugin::StartOptions options,                                       ctkPluginContext* context){  // instantiate and start the framework  if (context == 0 && d->fwFactory == 0) {    d->fwFactory = new ctkPluginFrameworkFactory(d->fwProps);    try    {      d->fwFactory->getFramework()->start();    }    catch (const ctkPluginException& exc)    {      qCritical() << "Failed to start the plug-in framework:" << exc;      delete d->fwFactory;      d->fwFactory = 0;      return false;    }  }  else if (context == 0 && d->fwFactory->getFramework()->getState() != ctkPlugin::ACTIVE)  {    try    {      d->fwFactory->getFramework()->start(options);    }    catch (const ctkPluginException& exc)    {      qCritical() << "Failed to start the plug-in framework:" << exc;      delete d->fwFactory;      d->fwFactory = 0;      return false;    }  }  if(!symbolicName.isEmpty())  {    QString pluginPath = getPluginPath(symbolicName);    if (pluginPath.isEmpty()) return false;    ctkPluginContext* pc = context ? context : getPluginContext();    try    {      pc->installPlugin(QUrl::fromLocalFile(pluginPath))->start(options);    }    catch (const ctkPluginException& exc)    {      qWarning() << "Failed to install plugin:" << exc;      return false;    }  }  return true;}//----------------------------------------------------------------------------bool ctkPluginFrameworkLauncher::stop(const QString& symbolicName,                                      ctkPlugin::StopOptions options, ctkPluginContext* context){  if (d->fwFactory == 0) return true;  ctkPluginContext* pc = context ? context : getPluginContext();  if (pc == 0)  {    qWarning() << "No valid plug-in context available";    return false;  }  if(!symbolicName.isEmpty())  {    QString pluginPath = getPluginPath(symbolicName);    if (pluginPath.isEmpty()) return false;    try    {      QList<QSharedPointer<ctkPlugin> > plugins = pc->getPlugins();      foreach(QSharedPointer<ctkPlugin> plugin, plugins)      {        if (plugin->getSymbolicName() == symbolicName)        {          plugin->stop(options);          return true;        }      }      qWarning() << "Plug-in" << symbolicName << "not found";      return false;    }    catch (const ctkPluginException& exc)    {      qWarning() << "Failed to stop plug-in:" << exc;      return false;    }  }  else  {    // stop the framework    QSharedPointer<ctkPluginFramework> fw =        qSharedPointerCast<ctkPluginFramework>(pc->getPlugin(0));    try    {      fw->stop();      ctkPluginFrameworkEvent fe = fw->waitForStop(5000);      if (fe.getType() == ctkPluginFrameworkEvent::FRAMEWORK_WAIT_TIMEDOUT)      {        qWarning() << "Stopping the plugin framework timed out";        return false;      }    }    catch (const ctkRuntimeException& e)    {      qWarning() << "Stopping the plugin framework failed: " << e;      return false;    }    return true;  }}//----------------------------------------------------------------------------ctkPluginContext* ctkPluginFrameworkLauncher::getPluginContext(){  if (d->fwFactory == 0) return 0;  return d->fwFactory->getFramework()->getPluginContext();}//----------------------------------------------------------------------------QSharedPointer<ctkPluginFramework> ctkPluginFrameworkLauncher::getPluginFramework(){  if (d->fwFactory)    return d->fwFactory->getFramework();  return QSharedPointer<ctkPluginFramework>();}//----------------------------------------------------------------------------void ctkPluginFrameworkLauncher::appendPathEnv(const QString& path){#ifdef _WIN32#ifdef __MINGW32__  QString pathVar("PATH");  QString oldPath(getenv("PATH"));  pathVar += "=" + oldPath + ";" + path;  if(_putenv(qPrintable(pathVar)))#else  std::size_t bufferLength;  getenv_s(&bufferLength, NULL, 0, "PATH");  QString newPath = path;  if (bufferLength > 0)  {    char* oldPath = new char[bufferLength];    getenv_s(&bufferLength, oldPath, bufferLength, "PATH");    newPath.append(";").append(oldPath);    delete[] oldPath;  }  qDebug() << "new PATH:" << newPath;  if(_putenv_s("PATH", qPrintable(newPath)))#endif  {    LPVOID lpMsgBuf;    DWORD dw = GetLastError();    FormatMessage(        FORMAT_MESSAGE_ALLOCATE_BUFFER |        FORMAT_MESSAGE_FROM_SYSTEM |        FORMAT_MESSAGE_IGNORE_INSERTS,        NULL,        dw,        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),        (LPTSTR) &lpMsgBuf,        0, NULL );    QString msg = QString("Adding '%1' to the PATH environment variable failed: %2")      .arg(path).arg(QString((LPCTSTR)lpMsgBuf));    qWarning() << msg;    LocalFree(lpMsgBuf);  }#else  Q_UNUSED(path)#endif}//----------------------------------------------------------------------------void ctkPluginFrameworkLauncher::addSearchPath(const QString& searchPath, bool addToPathEnv){  d->pluginSearchPaths.prepend(searchPath);  if (addToPathEnv) appendPathEnv(searchPath);}//----------------------------------------------------------------------------QString ctkPluginFrameworkLauncher::getPluginPath(const QString& symbolicName){  QString pluginFileName(symbolicName);  pluginFileName.replace(".", "_");  foreach(QString searchPath, d->pluginSearchPaths)  {    QDirIterator dirIter(searchPath, d->pluginLibFilter, QDir::Files);    while(dirIter.hasNext())    {      dirIter.next();      QFileInfo fileInfo = dirIter.fileInfo();      QString fileBaseName = fileInfo.baseName();      if (fileBaseName.startsWith("lib")) fileBaseName = fileBaseName.mid(3);      if (fileBaseName == pluginFileName)      {        return fileInfo.canonicalFilePath();      }    }  }  return QString();}//----------------------------------------------------------------------------QStringList ctkPluginFrameworkLauncher::getPluginSymbolicNames(const QString& searchPath){  QStringList result;  QDirIterator dirIter(searchPath, d->pluginLibFilter, QDir::Files);  while(dirIter.hasNext())  {    dirIter.next();    QFileInfo fileInfo = dirIter.fileInfo();    QString fileBaseName = fileInfo.baseName();    if (fileBaseName.startsWith("lib")) fileBaseName = fileBaseName.mid(3);    result << fileBaseName.replace("_", ".");  }  return result;}
 |