ImagingTools Core SDK
TPluginManager.h
1// SPDX-License-Identifier: LGPL-2.1-or-later OR GPL-2.0-or-later OR GPL-3.0-or-later OR LicenseRef-ImtCore-Commercial
2#pragma once
3
4
5// Qt includes
6#include <QtCore/QLibrary>
7#include <QtCore/QDir>
8
9// Windows includes
10#ifdef Q_OS_WIN
11 #include <windows.h>
12#endif
13
14// ACF includes
15#include <istd/TDelPtr.h>
16#include <ilog/CLoggerBase.h>
17
18// ImtCore includes
19#include <imtbase/IPluginStatusMonitor.h>
20
21
22namespace imtbase
23{
24
25
26template <class PluginInterface, typename CreateFunction, typename DestroyFunction>
27class TPluginManager: virtual public ilog::ILoggable
28{
29public:
30 TPluginManager() : m_pluginStatusMonitorPtr(nullptr)
31 {
32 }
33
34 TPluginManager(const QByteArray& createMethodName, const QByteArray& destroyMethodName, IPluginStatusMonitor* pluginStatusMonitorPtr);
35
36 virtual bool LoadPluginDirectory(
37 const QString& pluginDirectoryPath,
38 const QByteArray& pluginExtension,
39 const QByteArray& pluginTypeId);
40
41 // reimplemented (ilog::ILoggable)
42 virtual void SetLogPtr(ilog::IMessageConsumer* logPtr) override;
43 virtual ilog::IMessageConsumer* GetLogPtr() const override;
44
45public:
46 struct PluginInfo
47 {
48 PluginInfo()
49 :pluginPtr(nullptr)
50 {
51 }
52
53 PluginInterface* pluginPtr;
54 QString pluginPath;
55 DestroyFunction destroyFunc;
56 };
57
58 typedef QList<PluginInfo> Plugins;
59 Plugins m_plugins;
60
61protected:
62 void SetStatusManager(IPluginStatusMonitor* pluginStatusMonitorPtr);
63
69 virtual bool InitializePlugin(PluginInterface* pluginPtr);
70
71protected:
72 class Logger : public ilog::CLoggerBase
73 {
74 public:
75 typedef ilog::CLoggerBase BaseClass;
76
77 bool SendInfoMessage(
78 int id,
79 const QString& message,
80 const QString& messageSource = QString(),
81 int flags = 0) const;
82 bool SendWarningMessage(
83 int id,
84 const QString& message,
85 const QString& messageSource = QString(),
86 int flags = 0) const;
87 bool SendErrorMessage(
88 int id,
89 const QString& message,
90 const QString& messageSource = QString(),
91 int flags = 0) const;
92 bool SendCriticalMessage(
93 int id,
94 const QString& message,
95 const QString& messageSource = QString(),
96 int flags = 0) const;
97 bool SendInfoMessageOnce(
98 int id,
99 const QString& message,
100 const QString& messageSource = QString(),
101 int flags = 0) const;
102 bool SendWarningMessageOnce(
103 int id,
104 const QString& message,
105 const QString& messageSource = QString(),
106 int flags = 0) const;
107 bool SendErrorMessageOnce(
108 int id,
109 const QString& message,
110 const QString& messageSource = QString(),
111 int flags = 0) const;
112 bool SendCriticalMessageOnce(
113 int id,
114 const QString& message,
115 const QString& messageSource = QString(),
116 int flags = 0) const;
117 };
118
119protected:
120 QByteArray m_createMethodName;
121 QByteArray m_destroyMethodName;
122 IPluginStatusMonitor* m_pluginStatusMonitorPtr;
123 Logger m_logger;
124};
125
126
127// public methods
128
129template <class PluginInterface, typename CreateFunction, typename DestroyFunction>
130TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::TPluginManager(const QByteArray& createMethodName, const QByteArray& destroyMethodName, IPluginStatusMonitor* pluginStatusMonitorPtr)
131 :m_createMethodName(createMethodName),
132 m_destroyMethodName(destroyMethodName),
133 m_pluginStatusMonitorPtr(pluginStatusMonitorPtr)
134{
135 Q_ASSERT(!createMethodName.isEmpty());
136 Q_ASSERT(!destroyMethodName.isEmpty());
137}
138
139
140// public methods
141
142// reimplemented (ilog::ILoggable)
143
144template<class PluginInterface, typename CreateFunction, typename DestroyFunction>
145inline void TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::SetLogPtr(ilog::IMessageConsumer* logPtr)
146{
147 m_logger.SetLogPtr(logPtr);
148}
149
150
151template<class PluginInterface, typename CreateFunction, typename DestroyFunction>
152inline ilog::IMessageConsumer* TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::GetLogPtr() const
153{
154 return m_logger.GetLogPtr();
155}
156
157
158// protected methods
159
160template <class PluginInterface, typename CreateFunction, typename DestroyFunction>
161void TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::SetStatusManager(IPluginStatusMonitor* pluginStatusMonitorPtr)
162{
163 m_pluginStatusMonitorPtr = pluginStatusMonitorPtr;
164}
165
166
167template <class PluginInterface, typename CreateFunction, typename DestroyFunction>
168bool TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::LoadPluginDirectory(
169 const QString& pluginDirectoryPath,
170 const QByteArray& pluginExtension,
171 const QByteArray& pluginTypeId)
172{
173 m_logger.SendInfoMessage(0, QString("Looking for the plug-ins in '%1'").arg(pluginDirectoryPath));
174
175 if (!pluginDirectoryPath.isEmpty() && QFileInfo(pluginDirectoryPath).exists()){
176 QDir pluginsDirectory(pluginDirectoryPath);
177
178 QFileInfoList pluginsList = pluginsDirectory.entryInfoList(QStringList() << (QString("*.") + pluginExtension));
179
180 for (const QFileInfo& pluginPath : pluginsList){
181#ifdef Q_OS_WIN
182 std::wstring path = pluginPath.absolutePath().toStdWString();
183 SetDllDirectory(path.c_str());
184#endif
185 m_logger.SendInfoMessage(0, QString("Load: '%1'").arg(pluginPath.canonicalFilePath()));
186
187 QString pluginName;
188 QByteArray instanceTypeId;
189 istd::IInformationProvider::InformationCategory category;
190 QString statusMessage;
191
192 QLibrary library(pluginPath.canonicalFilePath());
193 if (library.load() == true){
194 CreateFunction createPluginFunc = (CreateFunction)library.resolve(m_createMethodName);
195 if (createPluginFunc != NULL){
196 istd::TDelPtr<PluginInterface> pluginInstancePtr = createPluginFunc();
197 if (pluginInstancePtr.IsValid()){
198 pluginName = pluginInstancePtr->GetPluginName();
199 instanceTypeId = pluginInstancePtr->GetPluginTypeId();
200
201 if (instanceTypeId == pluginTypeId){
202 PluginInfo pluginInfo;
203 pluginInfo.pluginPath = pluginPath.canonicalFilePath();
204 pluginInfo.pluginPtr = pluginInstancePtr.PopPtr();
205 pluginInfo.destroyFunc = (DestroyFunction)library.resolve(m_destroyMethodName);
206
207 if (InitializePlugin(pluginInfo.pluginPtr)){
208 m_plugins.push_back(pluginInfo);
209
210 category = istd::IInformationProvider::IC_INFO;
211 statusMessage = QObject::tr("Plug-in loaded");
212 }
213 else{
214 m_logger.SendInfoMessage(0, QString("Plug-in initialization failed for: '%1'").arg(pluginPath.canonicalFilePath()));
215
216 category = istd::IInformationProvider::IC_ERROR;
217 statusMessage = QObject::tr("Plug-in initialization failed");
218 }
219 }
220 else{
221 category = istd::IInformationProvider::IC_WARNING;
222 statusMessage = QObject::tr("Plug-in unsupported type-ID");
223 }
224 }
225 else{
226 category = istd::IInformationProvider::IC_ERROR;
227 statusMessage = QObject::tr("Plug-in instance creation failed");
228 }
229
230 if (m_pluginStatusMonitorPtr != nullptr){
231 m_pluginStatusMonitorPtr->OnPluginStatusChanged(
232 pluginPath.canonicalFilePath(),
233 pluginName,
234 pluginTypeId,
235 category,
236 statusMessage);
237 }
238 }
239 else{
240 m_logger.SendErrorMessage(0, QString("Plug-in entry point was not found: '%1'. %2").arg(pluginPath.canonicalFilePath()).arg(library.errorString()));
241
242 category = istd::IInformationProvider::IC_ERROR;
243 statusMessage = QObject::tr("Plug-in entry point was not found: '%1'").arg(library.errorString());
244 }
245 }
246 else{
247 m_logger.SendErrorMessage(0, QString("%1").arg(library.errorString()));
248
249 category = istd::IInformationProvider::IC_ERROR;
250 statusMessage = QObject::tr("%1").arg(library.errorString());
251 }
252 }
253
254 return true;
255 }
256
257 return false;
258}
259
260
261template <class PluginInterface, typename CreateFunction, typename DestroyFunction>
262inline bool TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::InitializePlugin(PluginInterface * pluginPtr)
263{
264 Q_UNUSED(pluginPtr);
265
266 return true;
267}
268
269
270// public methods of the embedded class Logger
271
272template<class PluginInterface, typename CreateFunction, typename DestroyFunction>
273inline bool TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::Logger::SendInfoMessage(int id, const QString& message, const QString& messageSource, int flags) const
274{
275 return BaseClass::SendInfoMessage(id, message, messageSource, flags);
276}
277
278
279template<class PluginInterface, typename CreateFunction, typename DestroyFunction>
280inline bool TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::Logger::SendWarningMessage(int id, const QString& message, const QString& messageSource, int flags) const
281{
282 return BaseClass::SendWarningMessage(id, message, messageSource, flags);
283}
284
285
286template<class PluginInterface, typename CreateFunction, typename DestroyFunction>
287inline bool TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::Logger::SendErrorMessage(int id, const QString& message, const QString& messageSource, int flags) const
288{
289 return BaseClass::SendErrorMessage(id, message, messageSource, flags);
290}
291
292
293template<class PluginInterface, typename CreateFunction, typename DestroyFunction>
294inline bool TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::Logger::SendCriticalMessage(int id, const QString& message, const QString& messageSource, int flags) const
295{
296 return BaseClass::SendCriticalMessage(id, message, messageSource, flags);
297}
298
299
300template<class PluginInterface, typename CreateFunction, typename DestroyFunction>
301inline bool TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::Logger::SendInfoMessageOnce(int id, const QString& message, const QString& messageSource, int flags) const
302{
303 return BaseClass::SendInfoMessageOnce(id, message, messageSource, flags);
304}
305
306
307template<class PluginInterface, typename CreateFunction, typename DestroyFunction>
308inline bool TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::Logger::SendWarningMessageOnce(int id, const QString& message, const QString& messageSource, int flags) const
309{
310 return BaseClass::SendWarningMessageOnce(id, message, messageSource, flags);
311}
312
313
314template<class PluginInterface, typename CreateFunction, typename DestroyFunction>
315inline bool TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::Logger::SendErrorMessageOnce(int id, const QString& message, const QString& messageSource, int flags) const
316{
317 return BaseClass::SendErrorMessageOnce(id, message, messageSource, flags);
318}
319
320
321template<class PluginInterface, typename CreateFunction, typename DestroyFunction>
322inline bool TPluginManager<PluginInterface, CreateFunction, DestroyFunction>::Logger::SendCriticalMessageOnce(int id, const QString& message, const QString& messageSource, int flags) const
323{
324 return BaseClass::SendCriticalMessageOnce(id, message, messageSource, flags);
325}
326
327
328} // namespace imtbase
329
330