QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
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 * loadNativeModule(const QString &location)
Load the native module from path.
QgsServiceModule * serviceEntryPoint_t()
QgsServiceNativeModuleEntry(const QString &location)
Constructor for QgsServiceNativeModuleEntry.
Class defining the service module interface for QGIS server services.
void unloadModules()
Unload all modules.
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).
#define cast_to_fptr(f)
Definition: qgis.h:208
virtual void registerSelf(QgsServiceRegistry &registry, QgsServerInterface *serverIface=nullptr)=0
Asks the module to register all provided services.
void unloadHook_t(QgsServiceModule *)
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins...
QgsServiceRegistry Class defining the registry manager for QGIS server services.
Native module (location, the module itself and the unload function).
void loadModules(const QString &modulePath, QgsServiceRegistry &registrar, QgsServerInterface *serverIface=nullptr)
Load all modules from path.