QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsservicenativeloader.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsservicerenativeloader.cpp
3 
4  Define Loader for native service modules
5  -------------------
6  begin : 2016-12-05
7  copyright : (C) 2016 by David Marteau
8  email : david dot marteau at 3liz dot com
9  ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  ***************************************************************************/
19 
20 #include <QLibrary>
21 #include <QDir>
22 #include <QDebug>
23 
24 #include "qgsservicenativeloader.h"
25 #include "qgsservicemodule.h"
26 #include "qgsmessagelog.h"
27 #include "qgis.h"
28 
29 
30 typedef void unloadHook_t( QgsServiceModule * );
31 
39 {
40  public:
41 
46  QgsServiceNativeModuleEntry( const QString &location )
47  : mLocation( location )
48  {}
49 
50  QString mLocation;
53 };
54 
55 void QgsServiceNativeLoader::loadModules( const QString &modulePath, QgsServiceRegistry &registrar,
56  QgsServerInterface *serverIface )
57 {
58  QDir moduleDir( modulePath );
59  moduleDir.setSorting( QDir::Name | QDir::IgnoreCase );
60  moduleDir.setFilter( QDir::Files );
61 
62 #if defined(Q_OS_WIN) || defined(__CYGWIN__)
63  moduleDir.setNameFilters( QStringList( "*.dll" ) );
64 #else
65  moduleDir.setNameFilters( QStringList( "*.so" ) );
66 #endif
67 
68  // qDebug() << QString( "Checking %1 for native services modules" ).arg( moduleDir.path() );
69 
70  for ( const QFileInfo &fi : moduleDir.entryInfoList() )
71  {
72  QgsServiceModule *module = loadNativeModule( fi.filePath() );
73  if ( module )
74  {
75  // Register services
76  module->registerSelf( registrar, serverIface );
77  }
78  }
79 }
80 
81 
83 
85 {
86  QgsServiceNativeModuleEntry *entry = findModuleEntry( location );
87  if ( entry )
88  {
89  return entry->mModule;
90  }
91 
92  QLibrary lib( location );
93  //QgsDebugMsg( QStringLiteral( "Loading native module %1" ).arg( location ) );
94  qDebug() << QString( "Loading native module %1" ).arg( location );
95  if ( !lib.load() )
96  {
97  QgsMessageLog::logMessage( QString( "Failed to load library %1: %2" ).arg( lib.fileName(), lib.errorString() ) );
98  return nullptr;
99  }
100  // Load entry point
102  entryPointFunc = reinterpret_cast<serviceEntryPoint_t *>( cast_to_fptr( lib.resolve( "QGS_ServiceModule_Init" ) ) );
103 
104  if ( entryPointFunc )
105  {
106  QgsServiceModule *module = entryPointFunc();
107  if ( module )
108  {
109  entry = new QgsServiceNativeModuleEntry( location );
110  entry->mModule = module;
111  entry->mUnloadHook = reinterpret_cast<unloadHook_t *>( cast_to_fptr( lib.resolve( "QGS_ServiceModule_Exit" ) ) );
112 
113  // Add entry
114  mModules.insert( location, ModuleTable::mapped_type( entry ) );
115  return module;
116  }
117  else
118  {
119  QgsMessageLog::logMessage( QString( "No entry point for module %1" ).arg( lib.fileName() ) );
120  }
121  }
122  else
123  {
124  QgsMessageLog::logMessage( QString( "Error: entry point returned null for %1" ).arg( lib.fileName() ) );
125  }
126 
127  // No module found: release library
128  lib.unload();
129  return nullptr;
130 }
131 
133 {
134  ModuleTable::iterator it = mModules.begin();
135  ModuleTable::iterator end = mModules.end();
136 
137  while ( it != end )
138  {
139  unloadModuleEntry( it->get() );
140  ++it;
141  }
142 
143  mModules.clear();
144 }
145 
146 QgsServiceNativeModuleEntry *QgsServiceNativeLoader::findModuleEntry( const QString &location )
147 {
148  QgsServiceNativeModuleEntry *entry = nullptr;
149  ModuleTable::iterator item = mModules.find( location );
150  if ( item != mModules.end() )
151  {
152  entry = item->get();
153  }
154  return entry;
155 }
156 
157 void QgsServiceNativeLoader::unloadModuleEntry( QgsServiceNativeModuleEntry *entry )
158 {
159  // Call cleanup function if it exists
160  if ( entry->mUnloadHook )
161  {
162  entry->mUnloadHook( entry->mModule );
163  }
164 
165  QLibrary lib( entry->mLocation );
166  lib.unload();
167 }
QgsServiceModule
Class defining the service module interface for QGIS server services.
Definition: qgsservicemodule.h:42
unloadHook_t
void unloadHook_t(QgsServiceModule *)
Definition: qgsservicenativeloader.cpp:30
qgis.h
QgsServiceModule::registerSelf
virtual void registerSelf(QgsServiceRegistry &registry, QgsServerInterface *serverIface=nullptr)=0
Asks the module to register all provided services.
QgsServiceNativeModuleEntry::QgsServiceNativeModuleEntry
QgsServiceNativeModuleEntry(const QString &location)
Constructor for QgsServiceNativeModuleEntry.
Definition: qgsservicenativeloader.cpp:46
QgsServiceNativeLoader::unloadModules
void unloadModules()
Unload all modules.
Definition: qgsservicenativeloader.cpp:132
serviceEntryPoint_t
QgsServiceModule * serviceEntryPoint_t()
Definition: qgsservicenativeloader.cpp:82
QgsServiceNativeModuleEntry::mUnloadHook
unloadHook_t * mUnloadHook
Definition: qgsservicenativeloader.cpp:52
QgsServiceNativeLoader::loadModules
void loadModules(const QString &modulePath, QgsServiceRegistry &registrar, QgsServerInterface *serverIface=nullptr)
Load all modules from path.
Definition: qgsservicenativeloader.cpp:55
QgsServiceNativeModuleEntry::mModule
QgsServiceModule * mModule
Definition: qgsservicenativeloader.cpp:51
QgsServiceNativeLoader::loadNativeModule
QgsServiceModule * loadNativeModule(const QString &location)
Load the native module from path.
Definition: qgsservicenativeloader.cpp:84
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
QgsServiceRegistry
QgsServiceRegistry Class defining the registry manager for QGIS server services.
Definition: qgsserviceregistry.h:50
cast_to_fptr
#define cast_to_fptr(f)
Definition: qgis.h:208
QgsServiceNativeModuleEntry
Native module (location, the module itself and the unload function).
Definition: qgsservicenativeloader.cpp:39
qgsservicemodule.h
qgsservicenativeloader.h
QgsServerInterface
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins.
Definition: qgsserverinterface.h:61
QgsServiceNativeModuleEntry::mLocation
QString mLocation
Definition: qgsservicenativeloader.cpp:50
qgsmessagelog.h