ctkPluginFrameworkLauncher.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /*=============================================================================
  2. Library: CTK
  3. Copyright (c) German Cancer Research Center,
  4. Division of Medical and Biological Informatics
  5. Licensed under the Apache License, Version 2.0 (the "License");
  6. you may not use this file except in compliance with the License.
  7. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. =============================================================================*/
  15. #include <QStringList>
  16. #include <QDirIterator>
  17. #include <QFileInfo>
  18. #include <QDebug>
  19. #include "ctkPluginFrameworkLauncher.h"
  20. #include "ctkPluginFrameworkFactory.h"
  21. #include "ctkPluginFramework.h"
  22. #include "ctkPluginContext.h"
  23. #include "ctkPluginException.h"
  24. #ifdef _WIN32
  25. #include <windows.h>
  26. #include <cstdlib>
  27. #endif // _WIN32
  28. #include <ctkConfig.h>
  29. class ctkPluginFrameworkLauncherPrivate
  30. {
  31. public:
  32. ctkPluginFrameworkLauncherPrivate()
  33. : fwFactory(0)
  34. {
  35. #ifdef CMAKE_INTDIR
  36. QString pluginPath = CTK_PLUGIN_DIR CMAKE_INTDIR "/";
  37. #else
  38. QString pluginPath = CTK_PLUGIN_DIR;
  39. #endif
  40. pluginSearchPaths.append(pluginPath);
  41. pluginLibFilter << "*.dll" << "*.so" << "*.dylib";
  42. }
  43. QStringList pluginSearchPaths;
  44. QStringList pluginLibFilter;
  45. ctkProperties fwProps;
  46. ctkPluginFrameworkFactory* fwFactory;
  47. };
  48. const QScopedPointer<ctkPluginFrameworkLauncherPrivate> ctkPluginFrameworkLauncher::d(
  49. new ctkPluginFrameworkLauncherPrivate());
  50. //----------------------------------------------------------------------------
  51. void ctkPluginFrameworkLauncher::setFrameworkProperties(const ctkProperties& props)
  52. {
  53. d->fwProps = props;
  54. }
  55. //----------------------------------------------------------------------------
  56. long ctkPluginFrameworkLauncher::install(const QString& symbolicName, ctkPluginContext* context)
  57. {
  58. QString pluginPath = getPluginPath(symbolicName);
  59. if (pluginPath.isEmpty()) return -1;
  60. ctkPluginContext* pc = context;
  61. if (pc == 0 && d->fwFactory == 0) {
  62. d->fwFactory = new ctkPluginFrameworkFactory(d->fwProps);
  63. try
  64. {
  65. d->fwFactory->getFramework()->init();
  66. pc = getPluginContext();
  67. }
  68. catch (const ctkPluginException& exc)
  69. {
  70. qCritical() << "Failed to initialize the plug-in framework:" << exc;
  71. delete d->fwFactory;
  72. d->fwFactory = 0;
  73. return -1;
  74. }
  75. }
  76. try
  77. {
  78. return pc->installPlugin(QUrl::fromLocalFile(pluginPath))->getPluginId();
  79. }
  80. catch (const ctkPluginException& exc)
  81. {
  82. qWarning() << "Failed to install plugin:" << exc;
  83. return -1;
  84. }
  85. }
  86. //----------------------------------------------------------------------------
  87. bool ctkPluginFrameworkLauncher::start(const QString& symbolicName, ctkPlugin::StartOptions options,
  88. ctkPluginContext* context)
  89. {
  90. // instantiate and start the framework
  91. if (context == 0 && d->fwFactory == 0) {
  92. d->fwFactory = new ctkPluginFrameworkFactory(d->fwProps);
  93. try
  94. {
  95. d->fwFactory->getFramework()->start();
  96. }
  97. catch (const ctkPluginException& exc)
  98. {
  99. qCritical() << "Failed to start the plug-in framework:" << exc;
  100. delete d->fwFactory;
  101. d->fwFactory = 0;
  102. return false;
  103. }
  104. }
  105. else if (context == 0 && d->fwFactory->getFramework()->getState() != ctkPlugin::ACTIVE)
  106. {
  107. try
  108. {
  109. d->fwFactory->getFramework()->start(options);
  110. }
  111. catch (const ctkPluginException& exc)
  112. {
  113. qCritical() << "Failed to start the plug-in framework:" << exc;
  114. delete d->fwFactory;
  115. d->fwFactory = 0;
  116. return false;
  117. }
  118. }
  119. if(!symbolicName.isEmpty())
  120. {
  121. QString pluginPath = getPluginPath(symbolicName);
  122. if (pluginPath.isEmpty()) return false;
  123. ctkPluginContext* pc = context ? context : getPluginContext();
  124. try
  125. {
  126. pc->installPlugin(QUrl::fromLocalFile(pluginPath))->start(options);
  127. }
  128. catch (const ctkPluginException& exc)
  129. {
  130. qWarning() << "Failed to install plugin:" << exc;
  131. return false;
  132. }
  133. }
  134. return true;
  135. }
  136. //----------------------------------------------------------------------------
  137. ctkPluginContext* ctkPluginFrameworkLauncher::getPluginContext()
  138. {
  139. if (d->fwFactory == 0) return 0;
  140. return d->fwFactory->getFramework()->getPluginContext();
  141. }
  142. //----------------------------------------------------------------------------
  143. QSharedPointer<ctkPluginFramework> ctkPluginFrameworkLauncher::getPluginFramework()
  144. {
  145. if (d->fwFactory)
  146. return d->fwFactory->getFramework();
  147. return QSharedPointer<ctkPluginFramework>();
  148. }
  149. //----------------------------------------------------------------------------
  150. void ctkPluginFrameworkLauncher::appendPathEnv(const QString& path)
  151. {
  152. #ifdef _WIN32
  153. #ifdef __MINGW32__
  154. QString pathVar("PATH");
  155. QString oldPath(getenv("PATH"));
  156. pathVar += "=" + oldPath + ";" + path;
  157. if(_putenv(qPrintable(pathVar)))
  158. #else
  159. std::size_t bufferLength;
  160. getenv_s(&bufferLength, NULL, 0, "PATH");
  161. QString newPath = path;
  162. if (bufferLength > 0)
  163. {
  164. char* oldPath = new char[bufferLength];
  165. getenv_s(&bufferLength, oldPath, bufferLength, "PATH");
  166. newPath.append(";").append(oldPath);
  167. delete[] oldPath;
  168. }
  169. qDebug() << "new PATH:" << newPath;
  170. if(_putenv_s("PATH", qPrintable(newPath)))
  171. #endif
  172. {
  173. LPVOID lpMsgBuf;
  174. DWORD dw = GetLastError();
  175. FormatMessage(
  176. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  177. FORMAT_MESSAGE_FROM_SYSTEM |
  178. FORMAT_MESSAGE_IGNORE_INSERTS,
  179. NULL,
  180. dw,
  181. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  182. (LPTSTR) &lpMsgBuf,
  183. 0, NULL );
  184. QString msg = QString("Adding '%1' to the PATH environment variable failed: %2")
  185. .arg(path).arg(QString((LPCTSTR)lpMsgBuf));
  186. qWarning() << msg;
  187. LocalFree(lpMsgBuf);
  188. }
  189. #else
  190. Q_UNUSED(path)
  191. #endif
  192. }
  193. //----------------------------------------------------------------------------
  194. void ctkPluginFrameworkLauncher::addSearchPath(const QString& searchPath, bool addToPathEnv)
  195. {
  196. d->pluginSearchPaths.prepend(searchPath);
  197. if (addToPathEnv) appendPathEnv(searchPath);
  198. }
  199. //----------------------------------------------------------------------------
  200. QString ctkPluginFrameworkLauncher::getPluginPath(const QString& symbolicName)
  201. {
  202. QString pluginFileName(symbolicName);
  203. pluginFileName.replace(".", "_");
  204. foreach(QString searchPath, d->pluginSearchPaths)
  205. {
  206. QDirIterator dirIter(searchPath, d->pluginLibFilter, QDir::Files);
  207. while(dirIter.hasNext())
  208. {
  209. dirIter.next();
  210. QFileInfo fileInfo = dirIter.fileInfo();
  211. QString fileBaseName = fileInfo.baseName();
  212. if (fileBaseName.startsWith("lib")) fileBaseName = fileBaseName.mid(3);
  213. if (fileBaseName == pluginFileName)
  214. {
  215. return fileInfo.canonicalFilePath();
  216. }
  217. }
  218. }
  219. return QString();
  220. }
  221. //----------------------------------------------------------------------------
  222. QStringList ctkPluginFrameworkLauncher::getPluginSymbolicNames(const QString& searchPath)
  223. {
  224. QStringList result;
  225. QDirIterator dirIter(searchPath, d->pluginLibFilter, QDir::Files);
  226. while(dirIter.hasNext())
  227. {
  228. dirIter.next();
  229. QFileInfo fileInfo = dirIter.fileInfo();
  230. QString fileBaseName = fileInfo.baseName();
  231. if (fileBaseName.startsWith("lib")) fileBaseName = fileBaseName.mid(3);
  232. result << fileBaseName.replace("_", ".");
  233. }
  234. return result;
  235. }