Expose QgsServerInterface to service modules

* Instanciate QgsServerInterface even if HAVE_SERVER_PYTHON_PLUGINS is
      not defined
    * Pass QgsServerInterface in module registration methods.
    * Add QgsServer initialisation test

 #Please enter the commit message for your changes. Lines starting
This commit is contained in:
David Marteau 2016-12-16 11:24:43 +01:00
parent 2adbaf0899
commit 689f3b1ab2
22 changed files with 84 additions and 133 deletions

View File

@ -521,7 +521,8 @@ ELSE (WIN32)
SET (QGIS_PLUGIN_SUBDIR_REV ../../MacOS) SET (QGIS_PLUGIN_SUBDIR_REV ../../MacOS)
SET (DEFAULT_INCLUDE_SUBDIR include/qgis) SET (DEFAULT_INCLUDE_SUBDIR include/qgis)
SET (DEFAULT_SERVER_MODULE_SUBDIR ../PlugIns/server) # Set server moodules path to DEFAULT_LIBEXEC_SUBDIR+'/server'
SET (DEFAULT_SERVER_MODULE_SUBDIR ${DEFAULT_LIBEXEC_SUBDIR}/server)
# path for framework references when running from build directory # path for framework references when running from build directory
# changed later to reference in-app resources upon install # changed later to reference in-app resources upon install
@ -547,7 +548,7 @@ ELSE (WIN32)
SET (DEFAULT_PLUGIN_SUBDIR lib${LIB_SUFFIX}/qgis/plugins) SET (DEFAULT_PLUGIN_SUBDIR lib${LIB_SUFFIX}/qgis/plugins)
SET (DEFAULT_INCLUDE_SUBDIR include/qgis) SET (DEFAULT_INCLUDE_SUBDIR include/qgis)
SET (DEFAULT_SERVER_MODULE_SUBDIR lib${LIB_SUFFIX}/qgis/server) SET (DEFAULT_SERVER_MODULE_SUBDIR ${DEFAULT_LIBEXEC_SUBDIR}/qgis/server)
ENDIF (APPLE) ENDIF (APPLE)
ENDIF (WIN32) ENDIF (WIN32)

View File

@ -28,6 +28,8 @@
#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" #define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
#define CMAKE_SOURCE_DIR "${CMAKE_SOURCE_DIR}" #define CMAKE_SOURCE_DIR "${CMAKE_SOURCE_DIR}"
#define QGIS_SERVER_MODULE_SUBDIR "${QGIS_SERVER_MODULE_SUBDIR}"
#define QSCINTILLA_VERSION_STR "${QSCINTILLA_VERSION_STR}" #define QSCINTILLA_VERSION_STR "${QSCINTILLA_VERSION_STR}"
#if defined( __APPLE__ ) #if defined( __APPLE__ )

View File

@ -34,6 +34,7 @@ SET (QGIS_PLUGIN_SUBDIR "@QGIS_PLUGIN_SUBDIR@")
SET (QGIS_PLUGIN_SUBDIR_REV "@QGIS_PLUGIN_SUBDIR_REV@") SET (QGIS_PLUGIN_SUBDIR_REV "@QGIS_PLUGIN_SUBDIR_REV@")
SET (QGIS_DATA_SUBDIR "@QGIS_DATA_SUBDIR@") SET (QGIS_DATA_SUBDIR "@QGIS_DATA_SUBDIR@")
SET (QGIS_DATA_SUBDIR_REV "@QGIS_DATA_SUBDIR_REV@") SET (QGIS_DATA_SUBDIR_REV "@QGIS_DATA_SUBDIR_REV@")
SET (QGIS_SERVER_MODULE_SUBDIR "@QGIS_SERVER_MODULE_SUBDIR@")
# optional components # optional components
SET (WITH_GLOBE "@WITH_GLOBE@") SET (WITH_GLOBE "@WITH_GLOBE@")

View File

@ -193,9 +193,7 @@ class QgsServer
*/ */
/** Returns a pointer to the server interface */ /** Returns a pointer to the server interface */
%If (HAVE_SERVER_PYTHON_PLUGINS) QgsServerInterface* serverInterface();
QgsServerInterface* serverInterface();
%End
private: private:
QgsServer( const QgsServer& ); QgsServer( const QgsServer& );

View File

@ -124,6 +124,12 @@ class QgsServerInterface
*/ */
virtual void removeProjectLayers( const QString& path ) = 0; virtual void removeProjectLayers( const QString& path ) = 0;
/**
* Return the service registry
* @return QgsServiceResgistry
*/
virtual QgsServiceRegistry* serviceRegistry() = 0 /KeepReference/;
private: private:
/** Constructor */ /** Constructor */
QgsServerInterface(); QgsServerInterface();

View File

@ -44,7 +44,8 @@ class QgsServiceModule
* Ask module to registe all provided services * Ask module to registe all provided services
* @param registry QgsServiceRegistry * @param registry QgsServiceRegistry
*/ */
virtual void registerSelf( QgsServiceRegistry& registry ) = 0; virtual void registerSelf( QgsServiceRegistry& registry,
QgsServerInterface* serverIface = nullptr ) = 0;
}; };

View File

@ -78,7 +78,8 @@ class QgsServiceRegistry
* Initialize registry, load modules and auto register services * Initialize registry, load modules and auto register services
* @param nativeModulepath the native module path * @param nativeModulepath the native module path
*/ */
void init( const QString& nativeModulepath ); // XXX Do we want this exposed to python ?
void init( const QString& nativeModulepath, QgsServerInterface* serverIface = nullptr );
/** /**
* Clean up registered service and unregister modules * Clean up registered service and unregister modules

View File

@ -53,7 +53,6 @@ SET ( qgis_mapserv_SRCS
qgsserver.cpp qgsserver.cpp
qgsservice.cpp qgsservice.cpp
qgsservicemodule.cpp qgsservicemodule.cpp
qgsserviceloader.cpp
qgsservicenativeloader.cpp qgsservicenativeloader.cpp
qgsserviceregistry.cpp qgsserviceregistry.cpp
qgsserverrequest.cpp qgsserverrequest.cpp

View File

@ -39,9 +39,7 @@
#include "qgsnetworkaccessmanager.h" #include "qgsnetworkaccessmanager.h"
#include "qgsserverlogger.h" #include "qgsserverlogger.h"
#include "qgseditorwidgetregistry.h" #include "qgseditorwidgetregistry.h"
#ifdef HAVE_SERVER_PYTHON_PLUGINS
#include "qgsaccesscontrolfilter.h" #include "qgsaccesscontrolfilter.h"
#endif
#include <QDomDocument> #include <QDomDocument>
#include <QNetworkDiskCache> #include <QNetworkDiskCache>
@ -61,14 +59,12 @@
QString* QgsServer::sConfigFilePath = nullptr; QString* QgsServer::sConfigFilePath = nullptr;
QgsCapabilitiesCache* QgsServer::sCapabilitiesCache = nullptr; QgsCapabilitiesCache* QgsServer::sCapabilitiesCache = nullptr;
#ifdef HAVE_SERVER_PYTHON_PLUGINS QgsServerInterfaceImpl* QgsServer::sServerInterface = nullptr;
QgsServerInterfaceImpl*QgsServer::sServerInterface = nullptr;
#endif
// Initialization must run once for all servers // Initialization must run once for all servers
bool QgsServer::sInitialised = false; bool QgsServer::sInitialised = false;
bool QgsServer::sCaptureOutput = true; bool QgsServer::sCaptureOutput = true;
QgsServiceRegistry QgsServer::sServiceRegistry;
QgsServer::QgsServer( bool captureOutput ) QgsServer::QgsServer( bool captureOutput )
{ {
@ -348,9 +344,10 @@ bool QgsServer::init( )
QgsEditorWidgetRegistry::initEditors(); QgsEditorWidgetRegistry::initEditors();
#ifdef HAVE_SERVER_PYTHON_PLUGINS sServerInterface = new QgsServerInterfaceImpl( sCapabilitiesCache, &sServiceRegistry );
sServerInterface = new QgsServerInterfaceImpl( sCapabilitiesCache );
#endif // Load service modules
sServiceRegistry.init( QgsApplication::libexecPath() + "/server", sServerInterface );
sInitialised = true; sInitialised = true;
QgsMessageLog::logMessage( QStringLiteral( "Server initialized" ), QStringLiteral( "Server" ), QgsMessageLog::INFO ); QgsMessageLog::logMessage( QStringLiteral( "Server initialized" ), QStringLiteral( "Server" ), QgsMessageLog::INFO );

View File

@ -34,14 +34,15 @@
#include "qgscapabilitiescache.h" #include "qgscapabilitiescache.h"
#include "qgsmapsettings.h" #include "qgsmapsettings.h"
#include "qgsmessagelog.h" #include "qgsmessagelog.h"
#include "qgsserviceregistry.h"
#ifdef HAVE_SERVER_PYTHON_PLUGINS #ifdef HAVE_SERVER_PYTHON_PLUGINS
#include "qgsserverplugins.h" #include "qgsserverplugins.h"
#include "qgsserverfilter.h" #include "qgsserverfilter.h"
#include "qgsserverinterfaceimpl.h"
#include "qgis_server.h" #include "qgis_server.h"
#endif #endif
#include "qgsserverinterfaceimpl.h"
/** \ingroup server /** \ingroup server
* The QgsServer class provides OGC web services. * The QgsServer class provides OGC web services.
@ -59,7 +60,7 @@ class SERVER_EXPORT QgsServer
* @param var environment variable name * @param var environment variable name
* @param val value * @param val value
* @note added in 2.14 * @note added in 2.14
*/ / */
void putenv( const QString &var, const QString &val ); void putenv( const QString &var, const QString &val );
/** Handles the request. The output is normally printed trough FCGI printf /** Handles the request. The output is normally printed trough FCGI printf
@ -75,10 +76,10 @@ class SERVER_EXPORT QgsServer
*/ */
QPair<QByteArray, QByteArray> handleRequest( const QString& queryString = QString() ); QPair<QByteArray, QByteArray> handleRequest( const QString& queryString = QString() );
#ifdef HAVE_SERVER_PYTHON_PLUGINS
//! Returns a pointer to the server interface //! Returns a pointer to the server interface
QgsServerInterfaceImpl* serverInterface() { return sServerInterface; } QgsServerInterfaceImpl* serverInterface() { return sServerInterface; }
#ifdef HAVE_SERVER_PYTHON_PLUGINS
//! Intialize python //! Intialize python
//! Note: not in python bindings //! Note: not in python bindings
void initPython( ); void initPython( );
@ -125,6 +126,10 @@ class SERVER_EXPORT QgsServer
//! Initialization must run once for all servers //! Initialization must run once for all servers
static bool sInitialised; static bool sInitialised;
static bool sCaptureOutput; static bool sCaptureOutput;
//! service registry
static QgsServiceRegistry sServiceRegistry;
}; };
#endif // QGSSERVER_H #endif // QGSSERVER_H

View File

@ -27,6 +27,7 @@
#include "qgsaccesscontrolfilter.h" #include "qgsaccesscontrolfilter.h"
#include "qgsaccesscontrol.h" #include "qgsaccesscontrol.h"
#include "qgis_server.h" #include "qgis_server.h"
#include "qgsserviceregistry.h"
/** /**
* \ingroup server * \ingroup server
@ -132,6 +133,12 @@ class SERVER_EXPORT QgsServerInterface
*/ */
virtual void removeProjectLayers( const QString& path ) = 0; virtual void removeProjectLayers( const QString& path ) = 0;
/**
* Return the service registry
* @return QgsServiceResgistry
*/
virtual QgsServiceRegistry* serviceRegistry() = 0;
private: private:
QString mConfigFilePath; QString mConfigFilePath;
}; };

View File

@ -22,8 +22,9 @@
#include "qgsmslayercache.h" #include "qgsmslayercache.h"
//! Constructor //! Constructor
QgsServerInterfaceImpl::QgsServerInterfaceImpl( QgsCapabilitiesCache* capCache ) QgsServerInterfaceImpl::QgsServerInterfaceImpl( QgsCapabilitiesCache* capCache, QgsServiceRegistry* srvRegistry )
: mCapabilitiesCache( capCache ) : mCapabilitiesCache( capCache )
, mServiceRegistry(srvRegistry)
{ {
mRequestHandler = nullptr; mRequestHandler = nullptr;
mAccessControls = new QgsAccessControl(); mAccessControls = new QgsAccessControl();
@ -89,5 +90,8 @@ void QgsServerInterfaceImpl::removeProjectLayers( const QString& path )
QgsMSLayerCache::instance()->removeProjectLayers( path ); QgsMSLayerCache::instance()->removeProjectLayers( path );
} }
QgsServiceRegistry* QgsServerInterfaceImpl::serviceRegistry()
{
return mServiceRegistry;
}

View File

@ -37,7 +37,8 @@ class QgsServerInterfaceImpl : public QgsServerInterface
public: public:
//! Constructor //! Constructor
explicit QgsServerInterfaceImpl( QgsCapabilitiesCache *capCache ); explicit QgsServerInterfaceImpl( QgsCapabilitiesCache *capCache,
QgsServiceRegistry* srvRegistry );
~QgsServerInterfaceImpl(); ~QgsServerInterfaceImpl();
@ -50,6 +51,7 @@ class QgsServerInterfaceImpl : public QgsServerInterface
void registerFilter( QgsServerFilter *filter, int priority = 0 ) override; void registerFilter( QgsServerFilter *filter, int priority = 0 ) override;
QgsServerFiltersMap filters() override { return mFilters; } QgsServerFiltersMap filters() override { return mFilters; }
//! Register an access control filter //! Register an access control filter
//
void registerAccessControl( QgsAccessControlFilter *accessControl, int priority = 0 ) override; void registerAccessControl( QgsAccessControlFilter *accessControl, int priority = 0 ) override;
/** Gets the helper over all the registered access control filters /** Gets the helper over all the registered access control filters
@ -63,6 +65,8 @@ class QgsServerInterfaceImpl : public QgsServerInterface
void removeConfigCacheEntry( const QString& path ) override; void removeConfigCacheEntry( const QString& path ) override;
void removeProjectLayers( const QString& path ) override; void removeProjectLayers( const QString& path ) override;
QgsServiceRegistry* serviceRegistry() override;
private: private:
QString mConfigFilePath; QString mConfigFilePath;
@ -70,7 +74,7 @@ class QgsServerInterfaceImpl : public QgsServerInterface
QgsAccessControl* mAccessControls; QgsAccessControl* mAccessControls;
QgsCapabilitiesCache* mCapabilitiesCache; QgsCapabilitiesCache* mCapabilitiesCache;
QgsRequestHandler* mRequestHandler; QgsRequestHandler* mRequestHandler;
QgsServiceRegistry* mServiceRegistry;
}; };
#endif // QGSSERVERINTERFACEIMPL_H #endif // QGSSERVERINTERFACEIMPL_H

View File

@ -1,34 +0,0 @@
/***************************************************************************
qgsserviceloader.cpp
Define abstract loader class for service modules
-------------------
begin : 2016-12-05
copyright : (C) 2016 by David Marteau
email : david dot marteau at 3liz dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsserviceloader.h"
//! Constructor
QgsServiceLoader::QgsServiceLoader()
{
}
//! Destructor
QgsServiceLoader::~QgsServiceLoader()
{
}

View File

@ -1,58 +0,0 @@
/***************************************************************************
qgsserviceloader.h
Define abstract loader class for service modules
-------------------
begin : 2016-12-05
copyright : (C) 2016 by David Marteau
email : david dot marteau at 3liz dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSSERVICELOADER_H
#define QGSSERVICELOADER_H
#include <QString>
class QgsServiceModule;
class QgsServiceRegistry;
/**
* \ingroup server
* QgsServiceLoader
* Abstract base Class defining the native service module loader for QGIS server services
*/
class SERVER_EXPORT QgsServiceLoader
{
public:
//! Constructor
// XXX if not defined then dynamic linker complains about missing symbol
QgsServiceLoader();
//! Destructor
virtual ~QgsServiceLoader() = 0;
/**
* Lead all medules from path
* @param modulePath the path to look for module
* @param registrar QgsServiceRegistry instance for registering services
*/
virtual void loadModules( const QString& modulePath, QgsServiceRegistry& registrar ) = 0;
/**
* Unload all modules
*/
virtual void unloadModules() = 0;
};
#endif

View File

@ -22,6 +22,7 @@
#define QGSSERVICEMODULE_H #define QGSSERVICEMODULE_H
class QgsServiceRegistry; class QgsServiceRegistry;
class QgsServerInterface;
/** /**
* \ingroup server * \ingroup server
@ -47,7 +48,8 @@ class SERVER_EXPORT QgsServiceModule
* Ask module to register all provided services * Ask module to register all provided services
* @param registry QgsServiceRegistry * @param registry QgsServiceRegistry
*/ */
virtual void registerSelf( QgsServiceRegistry& registry ) = 0; virtual void registerSelf( QgsServiceRegistry& registry,
QgsServerInterface* serverIface = nullptr ) = 0;
}; };
#endif #endif

View File

@ -54,7 +54,8 @@ QgsServiceNativeLoader::~QgsServiceNativeLoader()
} }
void QgsServiceNativeLoader::loadModules( const QString& modulePath, QgsServiceRegistry& registrar ) void QgsServiceNativeLoader::loadModules( const QString& modulePath, QgsServiceRegistry& registrar,
QgsServerInterface* serverIface )
{ {
QDir moduleDir( modulePath ); QDir moduleDir( modulePath );
moduleDir.setSorting( QDir::Name | QDir::IgnoreCase ); moduleDir.setSorting( QDir::Name | QDir::IgnoreCase );
@ -74,7 +75,7 @@ void QgsServiceNativeLoader::loadModules( const QString& modulePath, QgsServiceR
if ( module ) if ( module )
{ {
// Register services // Register services
module->registerSelf( registrar ); module->registerSelf( registrar, serverIface );
} }
} }
} }

View File

@ -22,10 +22,9 @@
class QgsServiceModule; class QgsServiceModule;
class QgsServiceRegistry; class QgsServiceRegistry;
class QgsServiceNativeModuleEntry; class QgsServiceNativeModuleEntry;
class QgsServerInterface;
#include "qgsserviceloader.h"
#include <QHash> #include <QHash>
#include <memory> #include <memory>
/** /**
@ -36,7 +35,7 @@ class QgsServiceNativeModuleEntry;
* This class provides methods for loading and managing hook for native (C++) modules * This class provides methods for loading and managing hook for native (C++) modules
* *
*/ */
class SERVER_EXPORT QgsServiceNativeLoader: public QgsServiceLoader class SERVER_EXPORT QgsServiceNativeLoader
{ {
public: public:
@ -49,14 +48,16 @@ class SERVER_EXPORT QgsServiceNativeLoader: public QgsServiceLoader
/** /**
* Lead all medules from path * Lead all medules from path
* @param modulePath the path to look for module * @param modulePath the path to look for module
* @parama registrar QgsServiceRegistry instance for registering services * @param registrar QgsServiceRegistry instance for registering services
* @param serverIface QgsServerInterface instarce
*/ */
void loadModules( const QString& modulePath, QgsServiceRegistry& registrar ) override; void loadModules( const QString& modulePath, QgsServiceRegistry& registrar,
QgsServerInterface* serverIface = nullptr );
/** /**
* Unload all modules * Unload all modules
*/ */
void unloadModules() override; void unloadModules();
/** /**
* Load the native module from path * Load the native module from path

View File

@ -79,7 +79,7 @@ namespace
QgsServiceRegistry::QgsServiceRegistry() QgsServiceRegistry::QgsServiceRegistry()
{ {
//TODO
} }
QgsServiceRegistry::~QgsServiceRegistry() QgsServiceRegistry::~QgsServiceRegistry()
@ -212,9 +212,9 @@ int QgsServiceRegistry::unregisterService( const QString& name, const QString& v
return removed; return removed;
} }
void QgsServiceRegistry::init( const QString& nativeModulePath ) void QgsServiceRegistry::init( const QString& nativeModulePath, QgsServerInterface* serverIface )
{ {
mNativeLoader.loadModules( nativeModulePath, *this ); mNativeLoader.loadModules( nativeModulePath, *this, serverIface );
} }
void QgsServiceRegistry::cleanUp() void QgsServiceRegistry::cleanUp()

View File

@ -28,6 +28,7 @@
#include <memory> #include <memory>
class QgsService; class QgsService;
class QgsServerInterface;
/** /**
* \ingroup server * \ingroup server
@ -88,9 +89,10 @@ class SERVER_EXPORT QgsServiceRegistry
/** /**
* Initialize registry, load modules and auto register services * Initialize registry, load modules and auto register services
* @param serverIface the server interface
* @param nativeModulepath the native module path * @param nativeModulepath the native module path
*/ */
void init( const QString& nativeModulepath ); void init( const QString& nativeModulepath, QgsServerInterface* serverIface =nullptr );
/** /**
* Clean up registered service and unregister modules * Clean up registered service and unregister modules

View File

@ -45,8 +45,9 @@ class SampleService: public QgsService
class QgsSampleModule: public QgsServiceModule class QgsSampleModule: public QgsServiceModule
{ {
public: public:
void registerSelf( QgsServiceRegistry& registry ) void registerSelf( QgsServiceRegistry& registry, QgsServerInterface* serverIface )
{ {
Q_UNUSED( serverIface );
QgsDebugMsg( "SampleModule::registerSelf called" ); QgsDebugMsg( "SampleModule::registerSelf called" );
registry.registerService( new SampleService() ); registry.registerService( new SampleService() );
} }

View File

@ -2,7 +2,9 @@
""" """
from qgis.PyQt.QtCore import QBuffer, QIODevice, QTextStream from qgis.PyQt.QtCore import QBuffer, QIODevice, QTextStream
from qgis.testing import unittest from qgis.testing import unittest
from qgis.server import (QgsServiceRegistry, from qgis.core import QgsApplication
from qgis.server import (QgsServer,
QgsServiceRegistry,
QgsService, QgsService,
QgsServerRequest, QgsServerRequest,
QgsServerResponse) QgsServerResponse)
@ -76,7 +78,7 @@ class TestServices(unittest.TestCase):
self.assertEqual(QTextStream(io).readLine(), "Hello world") self.assertEqual(QTextStream(io).readLine(), "Hello world")
def test_version_registration(self): def test_0_version_registration(self):
reg = QgsServiceRegistry() reg = QgsServiceRegistry()
myserv1 = MyService("STUFF", "1.0", "Hello") myserv1 = MyService("STUFF", "1.0", "Hello")
@ -92,7 +94,7 @@ class TestServices(unittest.TestCase):
service = reg.getService("STUFF", "2.0") service = reg.getService("STUFF", "2.0")
self.assertIsNone(service) self.assertIsNone(service)
def test_unregister_services(self): def test_1_unregister_services(self):
reg = QgsServiceRegistry() reg = QgsServiceRegistry()
serv1 = MyService("STUFF", "1.0a", "Hello") serv1 = MyService("STUFF", "1.0a", "Hello")
@ -123,8 +125,16 @@ class TestServices(unittest.TestCase):
service = reg.getService("STUFF") service = reg.getService("STUFF")
self.assertIsNone(service) self.assertIsNone(service)
def test_2_server_initialization(self):
qgisapp = QgsApplication([], False)
server = QgsServer()
# Check that our 'SampleService is registered
iface = server.serverInterface()
service = iface.serviceRegistry().getService('SampleService')
self.assertIsNotNone(service)