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 (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
# 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_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 (WIN32)

View File

@ -28,6 +28,8 @@
#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
#define CMAKE_SOURCE_DIR "${CMAKE_SOURCE_DIR}"
#define QGIS_SERVER_MODULE_SUBDIR "${QGIS_SERVER_MODULE_SUBDIR}"
#define QSCINTILLA_VERSION_STR "${QSCINTILLA_VERSION_STR}"
#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_DATA_SUBDIR "@QGIS_DATA_SUBDIR@")
SET (QGIS_DATA_SUBDIR_REV "@QGIS_DATA_SUBDIR_REV@")
SET (QGIS_SERVER_MODULE_SUBDIR "@QGIS_SERVER_MODULE_SUBDIR@")
# optional components
SET (WITH_GLOBE "@WITH_GLOBE@")

View File

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

View File

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

View File

@ -44,7 +44,8 @@ class QgsServiceModule
* Ask module to registe all provided services
* @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
* @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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -37,7 +37,8 @@ class QgsServerInterfaceImpl : public QgsServerInterface
public:
//! Constructor
explicit QgsServerInterfaceImpl( QgsCapabilitiesCache *capCache );
explicit QgsServerInterfaceImpl( QgsCapabilitiesCache *capCache,
QgsServiceRegistry* srvRegistry );
~QgsServerInterfaceImpl();
@ -50,6 +51,7 @@ class QgsServerInterfaceImpl : public QgsServerInterface
void registerFilter( QgsServerFilter *filter, int priority = 0 ) override;
QgsServerFiltersMap filters() override { return mFilters; }
//! Register an access control filter
//
void registerAccessControl( QgsAccessControlFilter *accessControl, int priority = 0 ) override;
/** 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 removeProjectLayers( const QString& path ) override;
QgsServiceRegistry* serviceRegistry() override;
private:
QString mConfigFilePath;
@ -70,7 +74,7 @@ class QgsServerInterfaceImpl : public QgsServerInterface
QgsAccessControl* mAccessControls;
QgsCapabilitiesCache* mCapabilitiesCache;
QgsRequestHandler* mRequestHandler;
QgsServiceRegistry* mServiceRegistry;
};
#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
class QgsServiceRegistry;
class QgsServerInterface;
/**
* \ingroup server
@ -47,7 +48,8 @@ class SERVER_EXPORT QgsServiceModule
* Ask module to register all provided services
* @param registry QgsServiceRegistry
*/
virtual void registerSelf( QgsServiceRegistry& registry ) = 0;
virtual void registerSelf( QgsServiceRegistry& registry,
QgsServerInterface* serverIface = nullptr ) = 0;
};
#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 );
moduleDir.setSorting( QDir::Name | QDir::IgnoreCase );
@ -74,7 +75,7 @@ void QgsServiceNativeLoader::loadModules( const QString& modulePath, QgsServiceR
if ( module )
{
// Register services
module->registerSelf( registrar );
module->registerSelf( registrar, serverIface );
}
}
}

View File

@ -22,10 +22,9 @@
class QgsServiceModule;
class QgsServiceRegistry;
class QgsServiceNativeModuleEntry;
class QgsServerInterface;
#include "qgsserviceloader.h"
#include <QHash>
#include <memory>
/**
@ -36,7 +35,7 @@ class QgsServiceNativeModuleEntry;
* This class provides methods for loading and managing hook for native (C++) modules
*
*/
class SERVER_EXPORT QgsServiceNativeLoader: public QgsServiceLoader
class SERVER_EXPORT QgsServiceNativeLoader
{
public:
@ -49,14 +48,16 @@ class SERVER_EXPORT QgsServiceNativeLoader: public QgsServiceLoader
/**
* Lead all medules from path
* @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
*/
void unloadModules() override;
void unloadModules();
/**
* Load the native module from path

View File

@ -79,7 +79,7 @@ namespace
QgsServiceRegistry::QgsServiceRegistry()
{
//TODO
}
QgsServiceRegistry::~QgsServiceRegistry()
@ -212,9 +212,9 @@ int QgsServiceRegistry::unregisterService( const QString& name, const QString& v
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()

View File

@ -28,6 +28,7 @@
#include <memory>
class QgsService;
class QgsServerInterface;
/**
* \ingroup server
@ -88,9 +89,10 @@ class SERVER_EXPORT QgsServiceRegistry
/**
* Initialize registry, load modules and auto register services
* @param serverIface the server interface
* @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

View File

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

View File

@ -2,7 +2,9 @@
"""
from qgis.PyQt.QtCore import QBuffer, QIODevice, QTextStream
from qgis.testing import unittest
from qgis.server import (QgsServiceRegistry,
from qgis.core import QgsApplication
from qgis.server import (QgsServer,
QgsServiceRegistry,
QgsService,
QgsServerRequest,
QgsServerResponse)
@ -76,7 +78,7 @@ class TestServices(unittest.TestCase):
self.assertEqual(QTextStream(io).readLine(), "Hello world")
def test_version_registration(self):
def test_0_version_registration(self):
reg = QgsServiceRegistry()
myserv1 = MyService("STUFF", "1.0", "Hello")
@ -92,7 +94,7 @@ class TestServices(unittest.TestCase):
service = reg.getService("STUFF", "2.0")
self.assertIsNone(service)
def test_unregister_services(self):
def test_1_unregister_services(self):
reg = QgsServiceRegistry()
serv1 = MyService("STUFF", "1.0a", "Hello")
@ -123,8 +125,16 @@ class TestServices(unittest.TestCase):
service = reg.getService("STUFF")
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)