mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-06 00:07:29 -04:00
Server refactoring: implements service modules registry
Implementation for https://github.com/qgis/QGIS-Enhancement-Proposals/issues/74
This commit is contained in:
parent
3a03c98a08
commit
1e0d830529
1
Testing/Temporary/CTestCostData.txt
Normal file
1
Testing/Temporary/CTestCostData.txt
Normal file
@ -0,0 +1 @@
|
||||
---
|
76
python/server/qgsserverrequest.sip
Normal file
76
python/server/qgsserverrequest.sip
Normal file
@ -0,0 +1,76 @@
|
||||
/***************************************************************************
|
||||
qgsserverrequest.h
|
||||
|
||||
Define ruquest class for getting request contents
|
||||
-------------------
|
||||
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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* \ingroup server
|
||||
* QgsServerRequest
|
||||
* Class defining request intreface passed to services QgsService::executeRequest() method
|
||||
*
|
||||
* Note about design: this intreface must be passed along to python and thus signatures methods must be
|
||||
* compatible with pyQGS/pyQT api and rules.
|
||||
*/
|
||||
class QgsServerRequest
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include "qgsserverrequest.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
enum Method {
|
||||
HeadMethod, PutMethod, GetMethod, PostMethod, DeleteMethod
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param url the lurl string
|
||||
* @param method the request method
|
||||
*/
|
||||
QgsServerRequest( const QString& url, Method method );
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param url QUrl
|
||||
* @param method the rquest method
|
||||
*/
|
||||
QgsServerRequest( const QUrl& url, Method method );
|
||||
|
||||
//! destructor
|
||||
virtual ~QgsServerRequest();
|
||||
|
||||
/**
|
||||
* @return the request url
|
||||
*/
|
||||
virtual const QUrl& url() const;
|
||||
|
||||
/**
|
||||
* @return the rquest method
|
||||
*/
|
||||
virtual Method method() const;
|
||||
|
||||
/**
|
||||
* Return post/put data
|
||||
* The default implementation retfurn nullptr
|
||||
* @return a QByteArray pointer or nullptr
|
||||
*/
|
||||
virtual const QByteArray* data() const;
|
||||
|
||||
};
|
||||
|
77
python/server/qgsserverresponse.sip
Normal file
77
python/server/qgsserverresponse.sip
Normal file
@ -0,0 +1,77 @@
|
||||
/***************************************************************************
|
||||
qgsserverresponse.h
|
||||
|
||||
Define response class for services
|
||||
-------------------
|
||||
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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* \ingroup server
|
||||
* QgsServerResponse
|
||||
* Class defining response interface passed to services QgsService::executeRequest() method
|
||||
*
|
||||
* Note:
|
||||
* This class is intended to be used from python code: method signatures and return types should be
|
||||
* compatible with pyQGIS/pyQT types and rules.
|
||||
*
|
||||
*/
|
||||
class QgsServerResponse
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include "qgsserverresponse.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
//!constructor
|
||||
QgsServerResponse();
|
||||
|
||||
//! destructor
|
||||
virtual ~QgsServerResponse();
|
||||
|
||||
/** Set header entry
|
||||
* Add header entry to the response
|
||||
* Note that it is usually an error to set hedaer after writng data
|
||||
*/
|
||||
virtual void setHeader( const QString& key, const QString& value ) = 0;
|
||||
|
||||
/** Set the http return code
|
||||
*/
|
||||
virtual void setReturnCode( int code ) = 0;
|
||||
|
||||
/**
|
||||
* Send error
|
||||
*/
|
||||
virtual void sendError( int code, const QString& message ) = 0;
|
||||
|
||||
/**
|
||||
* Write string
|
||||
*/
|
||||
virtual void write(const QString& data );
|
||||
|
||||
/**
|
||||
* Write chunk af data
|
||||
* They are convenience method that will write directly to the
|
||||
* underlying I/O device
|
||||
*/
|
||||
virtual qint64 write(const QByteArray& byteArray );
|
||||
|
||||
|
||||
/**
|
||||
* Return the underlying QIODevice
|
||||
*/
|
||||
virtual QIODevice* io() = 0;
|
||||
|
||||
};
|
||||
|
60
python/server/qgsservice.sip
Normal file
60
python/server/qgsservice.sip
Normal file
@ -0,0 +1,60 @@
|
||||
/***************************************************************************
|
||||
qgsservice.h
|
||||
|
||||
Class defining the service interface for QGIS server services.
|
||||
-------------------
|
||||
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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* \ingroup server
|
||||
* QgsService
|
||||
* Class defining interfaces for QGIS server services
|
||||
*
|
||||
* This class provides methods for executing server requests
|
||||
* They are registered at runtime for a given service name.
|
||||
*
|
||||
*/
|
||||
class QgsService
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include "qgsservice.h"
|
||||
#include "qgsserverrequest.h"
|
||||
#include "qgsserverresponse.h"
|
||||
%End
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
QgsService();
|
||||
|
||||
//! Destructor
|
||||
virtual ~QgsService();
|
||||
|
||||
/**
|
||||
* Return true if the given method is supported for that
|
||||
* service.
|
||||
* @param method QGSMethodType the
|
||||
* @return QString containing the configuration file path
|
||||
*/
|
||||
virtual bool allowMethod( QgsServerRequest::Method ) const = 0;
|
||||
|
||||
/**
|
||||
* Execute the requests and set result in QgsServerRequest
|
||||
* @param request a QgsServerRequest instance
|
||||
* @param response a QgsServerResponse instance
|
||||
*/
|
||||
virtual void executeRequest( const QgsServerRequest& request, QgsServerResponse& response ) = 0;
|
||||
};
|
||||
|
50
python/server/qgsservicemodule.sip
Normal file
50
python/server/qgsservicemodule.sip
Normal file
@ -0,0 +1,50 @@
|
||||
/***************************************************************************
|
||||
qgsservicemodule.h
|
||||
|
||||
Class defining the service module interface for QGIS server services.
|
||||
-------------------
|
||||
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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* \ingroup server
|
||||
* QgsServiceModule
|
||||
* Class defining the service module interface for QGIS server services
|
||||
*
|
||||
* This class act as a service registrar for services.
|
||||
*
|
||||
* For dynamic modules, a QgsServiceModule instance is returned from the QGS_ServiceModule_Init() entry point
|
||||
*/
|
||||
class QgsServiceModule
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include "qgsservicemodule.h"
|
||||
#include "qgsserviceregistry.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
QgsServiceModule();
|
||||
|
||||
//! Destructor
|
||||
virtual ~QgsServiceModule() = 0;
|
||||
|
||||
/**
|
||||
* Ask module to registe all provided services
|
||||
* @param registry QgsServiceRegistry
|
||||
*/
|
||||
virtual void registerSelf( QgsServiceRegistry& registry ) = 0;
|
||||
};
|
||||
|
||||
|
83
python/server/qgsserviceregistry.sip
Normal file
83
python/server/qgsserviceregistry.sip
Normal file
@ -0,0 +1,83 @@
|
||||
/***************************************************************************
|
||||
qgsserviceregistry.h
|
||||
|
||||
Class defining the service manager for QGIS server services.
|
||||
-------------------
|
||||
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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* \ingroup server
|
||||
* QgsServiceRegistry
|
||||
* Class defining the cegistry manager for QGIS server services
|
||||
*
|
||||
* This class provides methods for registering and retrieving
|
||||
* services. Note that the regstiry does not hord ownership of
|
||||
* registered service but vill call the 'release' method on cleanup)
|
||||
*
|
||||
*/
|
||||
class QgsServiceRegistry
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include "qgsserviceregistry.h"
|
||||
#include "qgsservice.h"
|
||||
#include "qgsserverrequest.h"
|
||||
#include "qgsserverresponse.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
QgsServiceRegistry();
|
||||
|
||||
//! Destructor
|
||||
~QgsServiceRegistry();
|
||||
|
||||
/**
|
||||
* Retrieve a service from its name
|
||||
* @param name the name of the service
|
||||
* @param version the required version (optional)
|
||||
* @return QgsService
|
||||
*/
|
||||
QgsService* getService( const QString& name, const QString& version = QString() );
|
||||
|
||||
/**
|
||||
* Register a service by its name
|
||||
*
|
||||
* This method is intended to be called by modules for registering
|
||||
* services. A module may register multiple services.
|
||||
* The registry gain ownership of services.
|
||||
*
|
||||
* @param name the name of the service
|
||||
* @param service a QgsServerResponse to be registered
|
||||
* @param version the service version
|
||||
*/
|
||||
void registerService( const QString& name, QgsService* service /Transfer/, const QString& version );
|
||||
|
||||
/**
|
||||
* Initialize registry, load modules and auto register services
|
||||
* @param nativeModulepath the native module path
|
||||
* @param pythonModulePath the python module path
|
||||
*
|
||||
* If pythonModulePath is not specified the environnement variables QGIS_PYTHON_SERVICE_PATH
|
||||
* is examined.
|
||||
*/
|
||||
void init( const QString& nativeModulepath, const QString& pythonModulePath = QString() );
|
||||
|
||||
/**
|
||||
* Clean up registered service and unregister modules
|
||||
*/
|
||||
void cleanUp();
|
||||
};
|
||||
|
||||
|
@ -28,3 +28,10 @@
|
||||
%Include qgswfsprojectparser.sip
|
||||
%Include qgsconfigcache.sip
|
||||
%Include qgsserver.sip
|
||||
|
||||
%Include qgsserverrequest.sip
|
||||
%Include qgsserverresponse.sip
|
||||
%Include qgsservice.sip
|
||||
%Include qgsservicemodule.sip
|
||||
%Include qgsserviceregistry.sip
|
||||
|
||||
|
@ -49,6 +49,16 @@ SET ( qgis_mapserv_SRCS
|
||||
qgssldconfigparser.cpp
|
||||
qgsconfigparserutils.cpp
|
||||
qgsserver.cpp
|
||||
#XXX https://github.com/qgis/QGIS-Enhancement-Proposals/issues/74
|
||||
qgsservice.cpp
|
||||
qgsservicemodule.cpp
|
||||
qgsserviceloader.cpp
|
||||
qgsservicenativeloader.cpp
|
||||
qgsservicepythonloader.cpp
|
||||
qgsserviceregistry.cpp
|
||||
qgsserverrequest.cpp
|
||||
qgsserverresponse.cpp
|
||||
#----------------------------
|
||||
)
|
||||
IF("${Qt5Network_VERSION}" VERSION_LESS "5.0.0")
|
||||
SET (qgis_mapserv_SRCS ${qgis_mapserv_SRCS}
|
||||
|
58
src/server/qgsserverrequest.cpp
Normal file
58
src/server/qgsserverrequest.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
/***************************************************************************
|
||||
qgsserverrequest.cpp
|
||||
|
||||
Define ruquest class for getting request contents
|
||||
-------------------
|
||||
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 "qgsserverrequest.h"
|
||||
|
||||
|
||||
QgsServerRequest::QgsServerRequest( const QString& url, Method method )
|
||||
: mUrl(url)
|
||||
, mMethod(method)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QgsServerRequest::QgsServerRequest( const QUrl& url, Method method )
|
||||
: mUrl(url)
|
||||
, mMethod(method)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//! destructor
|
||||
QgsServerRequest::~QgsServerRequest()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const QUrl& QgsServerRequest::url() const
|
||||
{
|
||||
return mUrl;
|
||||
}
|
||||
|
||||
QgsServerRequest::Method QgsServerRequest::method() const
|
||||
{
|
||||
return mMethod;
|
||||
}
|
||||
|
||||
const QByteArray* QgsServerRequest::data() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
83
src/server/qgsserverrequest.h
Normal file
83
src/server/qgsserverrequest.h
Normal file
@ -0,0 +1,83 @@
|
||||
/***************************************************************************
|
||||
qgsserverrequest.h
|
||||
|
||||
Define ruquest class for getting request contents
|
||||
-------------------
|
||||
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 QGSSERVERREQUEST_H
|
||||
#define QGSSERVERREQUEST_H
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
/**
|
||||
* \ingroup server
|
||||
* QgsServerRequest
|
||||
* Class defining request intreface passed to services QgsService::executeRequest() method
|
||||
*
|
||||
* Note about design: this intreface must be passed along to python and thus signatures methods must be
|
||||
* compatible with pyQGS/pyQT api and rules.
|
||||
*/
|
||||
class SERVER_EXPORT QgsServerRequest
|
||||
{
|
||||
public:
|
||||
|
||||
enum Method {
|
||||
HeadMethod, PutMethod, GetMethod, PostMethod, DeleteMethod
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param url the lurl string
|
||||
* @param method the request method
|
||||
*/
|
||||
QgsServerRequest( const QString& url, Method method );
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param url QUrl
|
||||
* @param method the rquest method
|
||||
*/
|
||||
QgsServerRequest( const QUrl& url, Method method );
|
||||
|
||||
//! destructor
|
||||
virtual ~QgsServerRequest();
|
||||
|
||||
/**
|
||||
* @return the request url
|
||||
*/
|
||||
virtual const QUrl& url() const;
|
||||
|
||||
/**
|
||||
* @return the rquest method
|
||||
*/
|
||||
virtual Method method() const;
|
||||
|
||||
/**
|
||||
* Return post/put data
|
||||
* The default implementation retfurn nullptr
|
||||
* @return a QByteArray pointer or nullptr
|
||||
*/
|
||||
virtual const QByteArray* data() const;
|
||||
|
||||
protected:
|
||||
|
||||
QUrl mUrl;
|
||||
Method mMethod;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
82
src/server/qgsserverresponse.cpp
Normal file
82
src/server/qgsserverresponse.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/***************************************************************************
|
||||
qgsserverresponse.h
|
||||
|
||||
Define response class for services
|
||||
-------------------
|
||||
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 "qgsserverresponse.h"
|
||||
#include "qgsmessagelog.h"
|
||||
#include <QTextStream>
|
||||
|
||||
//! constructor
|
||||
QgsServerResponse::QgsServerResponse()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
QgsServerResponse::~QgsServerResponse()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QgsServerResponse::write( const QString& data )
|
||||
{
|
||||
QIODevice* iodev = io();
|
||||
if( iodev )
|
||||
{
|
||||
QTextStream stream(iodev);
|
||||
stream << data;
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsMessageLog::logMessage("Error: No IODevice in QgsServerResponse !!!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
qint64 QgsServerResponse::write( const QByteArray& byteArray )
|
||||
{
|
||||
QIODevice* iodev = io();
|
||||
if( iodev )
|
||||
{
|
||||
return iodev->write(byteArray);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
qint64 QgsServerResponse::write( const char* data, qint64 maxsize )
|
||||
{
|
||||
QIODevice* iodev = io();
|
||||
if( iodev )
|
||||
{
|
||||
return iodev->write(data, maxsize);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
qint64 QgsServerResponse::write( const char* data )
|
||||
{
|
||||
QIODevice* iodev = io();
|
||||
if( iodev )
|
||||
{
|
||||
return iodev->write(data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
86
src/server/qgsserverresponse.h
Normal file
86
src/server/qgsserverresponse.h
Normal file
@ -0,0 +1,86 @@
|
||||
/***************************************************************************
|
||||
qgsserverresponse.h
|
||||
|
||||
Define response class for services
|
||||
-------------------
|
||||
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 QGSSERVERRESPONSE_H
|
||||
#define QGSSERVERRESPONSE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QIODevice>
|
||||
|
||||
/**
|
||||
* \ingroup server
|
||||
* QgsServerResponse
|
||||
* Class defining response interface passed to services QgsService::executeRequest() method
|
||||
*
|
||||
* Note:
|
||||
* This class is intended to be used from python code: method signatures and return types should be
|
||||
* compatible with pyQGIS/pyQT types and rules.
|
||||
*
|
||||
*/
|
||||
class SERVER_EXPORT QgsServerResponse
|
||||
{
|
||||
public:
|
||||
|
||||
//!constructor
|
||||
QgsServerResponse();
|
||||
|
||||
//! destructor
|
||||
virtual ~QgsServerResponse();
|
||||
|
||||
/** Set header entry
|
||||
* Add header entry to the response
|
||||
* Note that it is usually an error to set hedaer after writng data
|
||||
*/
|
||||
virtual void setHeader( const QString& key, const QString& value ) = 0;
|
||||
|
||||
/** Set the http return code
|
||||
*/
|
||||
virtual void setReturnCode( int code ) = 0;
|
||||
|
||||
/**
|
||||
* Send error
|
||||
*/
|
||||
virtual void sendError( int code, const QString& message ) = 0;
|
||||
|
||||
/**
|
||||
* Write string
|
||||
* @param data string to write
|
||||
*/
|
||||
virtual void write( const QString& data );
|
||||
|
||||
/**
|
||||
* Write chunk af data
|
||||
* They are convenience method that will write directly to the
|
||||
* underlying I/O device
|
||||
*/
|
||||
virtual qint64 write( const QByteArray &byteArray );
|
||||
|
||||
// Not exposed in python
|
||||
virtual qint64 write( const char* data, qint64 maxsize);
|
||||
|
||||
// Not exposed in python
|
||||
virtual qint64 write( const char* data );
|
||||
|
||||
/**
|
||||
* Return the underlying QIODevice
|
||||
*/
|
||||
virtual QIODevice* io() = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
35
src/server/qgsservice.cpp
Normal file
35
src/server/qgsservice.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/***************************************************************************
|
||||
qgsservice.cpp
|
||||
|
||||
Class defining the service interface for QGIS server services.
|
||||
-------------------
|
||||
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 "qgsservice.h"
|
||||
|
||||
//! Constructor
|
||||
QgsService::QgsService()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QgsService::~QgsService()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
64
src/server/qgsservice.h
Normal file
64
src/server/qgsservice.h
Normal file
@ -0,0 +1,64 @@
|
||||
/***************************************************************************
|
||||
qgsservice.h
|
||||
|
||||
Class defining the service interface for QGIS server services.
|
||||
-------------------
|
||||
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 QGSSERVICECOMPONENT_H
|
||||
#define QGSSERVICECOMPONENT_H
|
||||
|
||||
#include "qgsserverrequest.h"
|
||||
#include "qgsserverresponse.h"
|
||||
|
||||
/**
|
||||
* \ingroup server
|
||||
* QgsService
|
||||
* Class defining interfaces for QGIS server services
|
||||
*
|
||||
* This class provides methods for executing server requests
|
||||
* They are registered at runtime for a given service name.
|
||||
*
|
||||
*/
|
||||
class SERVER_EXPORT QgsService
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
QgsService();
|
||||
|
||||
//! Destructor
|
||||
virtual ~QgsService();
|
||||
|
||||
/**
|
||||
* Return true if the given method is supported for that
|
||||
* service.
|
||||
* @param method QGSMethodType the
|
||||
* @return QString containing the configuration file path
|
||||
*/
|
||||
virtual bool allowMethod( QgsServerRequest::Method ) const = 0;
|
||||
|
||||
/**
|
||||
* Execute the requests and set result in QgsServerRequest
|
||||
* @param request a QgsServerRequest instance
|
||||
* @param response a QgsServerResponse instance
|
||||
*/
|
||||
virtual void executeRequest( const QgsServerRequest& request, QgsServerResponse& response ) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
34
src/server/qgsserviceloader.cpp
Normal file
34
src/server/qgsserviceloader.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/***************************************************************************
|
||||
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()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
57
src/server/qgsserviceloader.h
Normal file
57
src/server/qgsserviceloader.h
Normal file
@ -0,0 +1,57 @@
|
||||
/***************************************************************************
|
||||
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 (required by SIP bindings ???)
|
||||
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
|
||||
|
||||
|
36
src/server/qgsservicemodule.cpp
Normal file
36
src/server/qgsservicemodule.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
/***************************************************************************
|
||||
qgsservicemodule.h
|
||||
|
||||
Class defining the service module interface for QGIS server services.
|
||||
-------------------
|
||||
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 "qgsservicemodule.h"
|
||||
|
||||
//! Constructor
|
||||
QgsServiceModule::QgsServiceModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QgsServiceModule::~QgsServiceModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
54
src/server/qgsservicemodule.h
Normal file
54
src/server/qgsservicemodule.h
Normal file
@ -0,0 +1,54 @@
|
||||
/***************************************************************************
|
||||
qgsservicemodule.h
|
||||
|
||||
Class defining the service module interface for QGIS server services.
|
||||
-------------------
|
||||
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 QGSSERVICEMODULE_H
|
||||
#define QGSSERVICEMODULE_H
|
||||
|
||||
class QgsServiceRegistry;
|
||||
|
||||
/**
|
||||
* \ingroup server
|
||||
* QgsServiceModule
|
||||
* Class defining the service module interface for QGIS server services
|
||||
*
|
||||
* This class act as a service registrar for services.
|
||||
*
|
||||
* For dynamic modules, a QgsServiceModule instance is returned from the QGS_ServiceModule_Init() entry point
|
||||
*/
|
||||
class SERVER_EXPORT QgsServiceModule
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
QgsServiceModule();
|
||||
|
||||
//! Destructor
|
||||
virtual ~QgsServiceModule() = 0;
|
||||
|
||||
/**
|
||||
* Ask module to register all provided services
|
||||
* @param registry QgsServiceRegistry
|
||||
*/
|
||||
virtual void registerSelf( QgsServiceRegistry& registry ) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
168
src/server/qgsservicenativeloader.cpp
Normal file
168
src/server/qgsservicenativeloader.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
/***************************************************************************
|
||||
qgsservicerenativeloader.cpp
|
||||
|
||||
Define Loader for native 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 <QLibrary>
|
||||
#include <QDir>
|
||||
|
||||
#include "qgsservicenativeloader.h"
|
||||
#include "qgsserviceregistry.h"
|
||||
#include "qgsservicemodule.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsmessagelog.h"
|
||||
#include "qgis.h"
|
||||
|
||||
|
||||
typedef void unloadHook_t( QgsServiceModule* );
|
||||
|
||||
class QgsServiceNativeModuleEntry
|
||||
{
|
||||
public:
|
||||
QgsServiceNativeModuleEntry( const QString& location )
|
||||
: mLocation(location)
|
||||
, mModule(nullptr)
|
||||
{}
|
||||
|
||||
QString mLocation;
|
||||
QgsServiceModule* mModule;
|
||||
unloadHook_t* mUnloadHook;
|
||||
};
|
||||
|
||||
//! Constructor
|
||||
QgsServiceNativeLoader::QgsServiceNativeLoader()
|
||||
{
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QgsServiceNativeLoader::~QgsServiceNativeLoader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QgsServiceNativeLoader::loadModules( const QString& modulePath, QgsServiceRegistry& registrar )
|
||||
{
|
||||
QDir moduleDir(modulePath);
|
||||
moduleDir.setSorting( QDir::Name | QDir::IgnoreCase );
|
||||
moduleDir.setFilter( QDir::Files );
|
||||
|
||||
#if defined(Q_OS_WIN) || defined(__CYGWIN__)
|
||||
moduleDir.setNameFilters( QStringList( "*.dll" ) );
|
||||
#else
|
||||
moduleDir.setNameFilters( QStringList( "*.so" ) );
|
||||
#endif
|
||||
|
||||
QgsDebugMsg( QString( "Checking %1 for native services modules" ).arg( moduleDir.path() ) );
|
||||
|
||||
Q_FOREACH( const QFileInfo& fi, moduleDir.entryInfoList() )
|
||||
{
|
||||
QgsServiceModule* module = loadNativeModule( fi.filePath() );
|
||||
if( module )
|
||||
{
|
||||
// Register services
|
||||
module->registerSelf( registrar );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef QgsServiceModule* serviceEntryPoint_t();
|
||||
|
||||
QgsServiceModule* QgsServiceNativeLoader::loadNativeModule( const QString& location )
|
||||
{
|
||||
QgsServiceNativeModuleEntry* entry = findModuleEntry( location );
|
||||
if( entry )
|
||||
{
|
||||
return entry->mModule;
|
||||
}
|
||||
|
||||
QLibrary lib( location );
|
||||
QgsDebugMsg( QString("Loading native module %1").arg(location) );
|
||||
if( !lib.load() )
|
||||
{
|
||||
QgsMessageLog::logMessage( QString("Failed to load library %1: %2").arg(lib.fileName(), lib.errorString()) );
|
||||
return nullptr;
|
||||
}
|
||||
// Load entry point
|
||||
serviceEntryPoint_t*
|
||||
entryPointFunc = reinterpret_cast<serviceEntryPoint_t*>( cast_to_fptr( lib.resolve("QGS_ServiceModule_Init") ));
|
||||
|
||||
if( entryPointFunc )
|
||||
{
|
||||
QgsServiceModule* module = entryPointFunc();
|
||||
if( module )
|
||||
{
|
||||
entry = new QgsServiceNativeModuleEntry( location );
|
||||
entry->mModule = module;
|
||||
entry->mUnloadHook = reinterpret_cast<unloadHook_t*>( cast_to_fptr( lib.resolve("QGS_ServiceModule_Exit") ));
|
||||
|
||||
// Add entry
|
||||
mModules.insert( location, ModuleTable::mapped_type(entry) );
|
||||
return module;
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsMessageLog::logMessage( QString("No entry point for module %1").arg(lib.fileName()) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsMessageLog::logMessage( QString("Error: entry point returned null for %1").arg(lib.fileName()) );
|
||||
}
|
||||
|
||||
// No module found: release library
|
||||
lib.unload();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void QgsServiceNativeLoader::unloadModules()
|
||||
{
|
||||
ModuleTable::iterator it = mModules.begin();
|
||||
ModuleTable::iterator end = mModules.end();
|
||||
|
||||
while( it!=end )
|
||||
{
|
||||
unloadModuleEntry( it->get() );
|
||||
++it;
|
||||
}
|
||||
|
||||
mModules.clear();
|
||||
}
|
||||
|
||||
QgsServiceNativeModuleEntry* QgsServiceNativeLoader::findModuleEntry( const QString& location )
|
||||
{
|
||||
QgsServiceNativeModuleEntry* entry = nullptr;
|
||||
ModuleTable::iterator item = mModules.find(location);
|
||||
if( item != mModules.end() )
|
||||
{
|
||||
entry = item->get();
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
void QgsServiceNativeLoader::unloadModuleEntry( QgsServiceNativeModuleEntry* entry )
|
||||
{
|
||||
// Call cleanup function if it exists
|
||||
if( entry->mUnloadHook ) {
|
||||
entry->mUnloadHook( entry->mModule );
|
||||
}
|
||||
|
||||
QLibrary lib( entry->mLocation );
|
||||
lib.unload();
|
||||
}
|
||||
|
||||
|
90
src/server/qgsservicenativeloader.h
Normal file
90
src/server/qgsservicenativeloader.h
Normal file
@ -0,0 +1,90 @@
|
||||
/***************************************************************************
|
||||
qgsservicerenativeloader.h
|
||||
|
||||
Define Loader for native 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 QGSSERVICENATIVELOADER_H
|
||||
#define QGSSERVICENATIVELOADER_H
|
||||
|
||||
class QgsServiceModule;
|
||||
class QgsServiceRegistry;
|
||||
class QgsServiceNativeModuleEntry;
|
||||
|
||||
#include "qgsserviceloader.h"
|
||||
#include <QHash>
|
||||
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* \ingroup server
|
||||
* QgsServiceNativeLoader
|
||||
* Class defining the native service module loader for QGIS server services
|
||||
*
|
||||
* This class provides methods for loading and managing hook for native (C++) modules
|
||||
*
|
||||
*/
|
||||
class SERVER_EXPORT QgsServiceNativeLoader: public QgsServiceLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
QgsServiceNativeLoader();
|
||||
|
||||
//! Destructor
|
||||
~QgsServiceNativeLoader();
|
||||
|
||||
/**
|
||||
* Lead all medules from path
|
||||
* @param modulePath the path to look for module
|
||||
* @parama registrar QgsServiceRegistry instance for registering services
|
||||
*/
|
||||
void loadModules( const QString& modulePath, QgsServiceRegistry& registrar ) override;
|
||||
|
||||
/**
|
||||
* Unload all modules
|
||||
*/
|
||||
void unloadModules() override;
|
||||
|
||||
/**
|
||||
* Load the native module from path
|
||||
*
|
||||
* @param location QString location holding the module relalive path
|
||||
* @return a qgsservicemodule instance
|
||||
*/
|
||||
QgsServiceModule* loadNativeModule( const QString& location );
|
||||
|
||||
|
||||
private:
|
||||
typedef QHash<QString, std::shared_ptr<QgsServiceNativeModuleEntry> > ModuleTable;
|
||||
|
||||
/**
|
||||
* Find module
|
||||
* @param path the module path
|
||||
* @return a module hook entry
|
||||
*/
|
||||
QgsServiceNativeModuleEntry* findModuleEntry( const QString& path );
|
||||
|
||||
/**
|
||||
* Unload medule hook
|
||||
*/
|
||||
void unloadModuleEntry( QgsServiceNativeModuleEntry* entry );
|
||||
|
||||
//! Associative storage for module handles
|
||||
ModuleTable mModules;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
82
src/server/qgsservicepythonloader.cpp
Normal file
82
src/server/qgsservicepythonloader.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/***************************************************************************
|
||||
qgsservicerenativeloader.cpp
|
||||
|
||||
Define Loader for native 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 "qgsservicepythonloader.h"
|
||||
#include "qgsserviceregistry.h"
|
||||
#include "qgsmessagelog.h"
|
||||
#include <QLibrary>
|
||||
#include <QDir>
|
||||
|
||||
typedef void unloadHook_t( QgsServiceModule* );
|
||||
|
||||
class QgsServicePythonModuleEntry
|
||||
{
|
||||
public:
|
||||
QgsServicePythonModuleEntry( const QString& location )
|
||||
: mLocation(location)
|
||||
, mModule(nullptr)
|
||||
{}
|
||||
|
||||
QString mLocation;
|
||||
QgsServiceModule* mModule;
|
||||
unloadHook_t* mUnloadHook;
|
||||
};
|
||||
|
||||
|
||||
//! Constructor
|
||||
QgsServicePythonLoader::QgsServicePythonLoader()
|
||||
{
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QgsServicePythonLoader::~QgsServicePythonLoader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QgsServicePythonLoader::loadModules( const QString& modulePath, QgsServiceRegistry& registrar )
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
|
||||
void QgsServicePythonLoader::unloadModules()
|
||||
{
|
||||
ModuleTable::iterator it = mModules.begin();
|
||||
ModuleTable::iterator end = mModules.end();
|
||||
|
||||
while( it!=end )
|
||||
{
|
||||
unloadModuleEntry( it->get() );
|
||||
++it;
|
||||
}
|
||||
|
||||
mModules.clear();
|
||||
}
|
||||
|
||||
|
||||
void QgsServicePythonLoader::unloadModuleEntry( QgsServicePythonModuleEntry* entry )
|
||||
{
|
||||
// Call cleanup function if it exists
|
||||
if( entry->mUnloadHook ) {
|
||||
entry->mUnloadHook( entry->mModule );
|
||||
}
|
||||
}
|
||||
|
||||
|
73
src/server/qgsservicepythonloader.h
Normal file
73
src/server/qgsservicepythonloader.h
Normal file
@ -0,0 +1,73 @@
|
||||
/***************************************************************************
|
||||
qgsservicepythonloader.h
|
||||
|
||||
Define Loader for python 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 QGSSERVICEPYTHONLOADER_H
|
||||
#define QGSSERVICEPYTHONLOADER_H
|
||||
|
||||
class QgsServiceModule;
|
||||
class QgsServicePythonModuleEntry;
|
||||
class QgsServiceRegistry;
|
||||
|
||||
#include "qgsserviceloader.h"
|
||||
#include <QHash>
|
||||
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* \ingroup server
|
||||
* QgsServicePythonLoader
|
||||
* Class defining the python service module loader for QGIS server services
|
||||
*
|
||||
* This class provides methods for loading and managing hook for native (C++) modules
|
||||
*
|
||||
*/
|
||||
class SERVER_EXPORT QgsServicePythonLoader: public QgsServiceLoader
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
QgsServicePythonLoader();
|
||||
|
||||
//! Destructor
|
||||
~QgsServicePythonLoader();
|
||||
|
||||
/**
|
||||
* Lead all medules from path
|
||||
* @param modulePath the path to look for module
|
||||
* @parama registrar QgsServiceRegistry instance for registering services
|
||||
*/
|
||||
void loadModules( const QString& modulePath, QgsServiceRegistry& registrar ) override;
|
||||
|
||||
/**
|
||||
* Unload all modules
|
||||
*/
|
||||
void unloadModules() override;
|
||||
|
||||
private:
|
||||
typedef QHash<QString, std::shared_ptr<QgsServicePythonModuleEntry> > ModuleTable;
|
||||
|
||||
/**
|
||||
* Unload medule hook
|
||||
*/
|
||||
void unloadModuleEntry( QgsServicePythonModuleEntry* entry );
|
||||
|
||||
//! Associative storage for module handles
|
||||
ModuleTable mModules;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
185
src/server/qgsserviceregistry.cpp
Normal file
185
src/server/qgsserviceregistry.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
/***************************************************************************
|
||||
qgsserviceregistry.cpp
|
||||
|
||||
Class defining the service manager for QGIS server services.
|
||||
-------------------
|
||||
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 "qgsserviceregistry.h"
|
||||
#include "qgsservice.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsmessagelog.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Build a key entry from name and version
|
||||
QString make_service_key( const QString& name, const QString& version )
|
||||
{
|
||||
return QString( "%1_%2" ).arg(name,version);
|
||||
}
|
||||
|
||||
// Compare two version strings:
|
||||
// The strings are splitted into dot separated segment
|
||||
// Each segment are compared up to the shortest number of segment of the
|
||||
// lists. Remaining segments are dropped.
|
||||
// If both segments can be intepreted as numbers the are compared as numbers, otherwise
|
||||
// They are compared lexicographically.
|
||||
// Return true if v1 is greater than v2
|
||||
bool is_version_greater( const QString& v1, const QString& v2 )
|
||||
{
|
||||
QStringList l1 = v1.split('.');
|
||||
QStringList l2 = v2.split('.');
|
||||
QStringList::iterator it1 = l1.begin();
|
||||
QStringList::iterator it2 = l2.begin();
|
||||
bool isint;
|
||||
while( it1 != l1.end() && it2 != l2.end() )
|
||||
{
|
||||
if ( *it1 != *it2 )
|
||||
{
|
||||
// Compare as numbers
|
||||
int i1 = it1->toInt(&isint);
|
||||
if(isint)
|
||||
{
|
||||
int i2 = it2->toInt(&isint);
|
||||
if( isint && i1 != i2 )
|
||||
{
|
||||
return i1 > i2;
|
||||
}
|
||||
}
|
||||
// Compare lexicographically
|
||||
if ( !isint )
|
||||
{
|
||||
return *it1 > *it2;
|
||||
}
|
||||
}
|
||||
++it1;
|
||||
++it2;
|
||||
}
|
||||
// We reach the end of one of the list
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class QgsServiceEntry
|
||||
{
|
||||
public:
|
||||
~QgsServiceEntry()
|
||||
{
|
||||
// We have the ownership by design
|
||||
// XXX Take care of /Transfer/ decorator for registerService in sip
|
||||
QgsDebugMsg( QString("Deleting service %1 %2").arg(mName, mVersion) );
|
||||
delete mService;
|
||||
}
|
||||
|
||||
QgsServiceEntry( const QString& name, QgsService* service, const QString& version )
|
||||
: mName(name)
|
||||
, mService(service)
|
||||
, mVersion(version)
|
||||
{}
|
||||
|
||||
QString mName;
|
||||
QgsService* mService;
|
||||
QString mVersion;
|
||||
};
|
||||
|
||||
QgsServiceRegistry::QgsServiceRegistry()
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
QgsServiceRegistry::~QgsServiceRegistry()
|
||||
{
|
||||
cleanUp();
|
||||
}
|
||||
|
||||
QgsService* QgsServiceRegistry::getService( const QString& name, const QString& version )
|
||||
{
|
||||
QgsService* service = nullptr;
|
||||
QString key;
|
||||
|
||||
// Check that we have a service of that name
|
||||
VersionTable::iterator v = mVersions.find(name);
|
||||
if( v != mVersions.end() )
|
||||
{
|
||||
key = version.isEmpty() ? v->second : make_service_key(name, version );
|
||||
ServiceTable::iterator it = mServices.find(key);
|
||||
if( it != mServices.end() )
|
||||
{
|
||||
service = (*it)->mService;
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsMessageLog::logMessage( QString("Service %1 %2 not found").arg(name, version) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsMessageLog::logMessage( QString("Service %1 is not registered").arg(name) );
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
void QgsServiceRegistry::registerService( const QString& name, QgsService* service, const QString& version )
|
||||
{
|
||||
// Test if service is already registered
|
||||
QString key = make_service_key( name, version );
|
||||
if( mServices.find(key) != mServices.end() )
|
||||
{
|
||||
QgsMessageLog::logMessage( QString("Error Service %1 %2 is already registered").arg(name,version) );
|
||||
return;
|
||||
}
|
||||
|
||||
QgsMessageLog::logMessage( QString( "Adding service %1 %2").arg(name,version) );
|
||||
mServices.insert( key, std::make_shared<QgsServiceEntry>( name, service, version ) );
|
||||
|
||||
// Check the default version
|
||||
// and replace with te new one if it has a higher version
|
||||
VersionTable::iterator v = mVersions.find( name );
|
||||
if( v != mVersions.end() )
|
||||
{
|
||||
if( is_version_greater( version, v->first ) )
|
||||
{
|
||||
// Replace the default version key
|
||||
mVersions.insert( name, VersionTable::mapped_type( version, key ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Insert the service as the default one
|
||||
mVersions.insert( name, VersionTable::mapped_type( version, key ) );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsServiceRegistry::init( const QString& nativeModulePath, const QString& pythonModulePath )
|
||||
{
|
||||
mNativeLoader.loadModules(nativeModulePath, *this );
|
||||
#ifdef HAVE_SERVER_PYTHON_SERVICES
|
||||
mPythonLoader.loadModules(pythonModulePath, *this );
|
||||
#endif
|
||||
}
|
||||
|
||||
void QgsServiceRegistry::cleanUp()
|
||||
{
|
||||
// Release all services
|
||||
mServices.clear();
|
||||
|
||||
mNativeLoader.unloadModules();
|
||||
#ifdef HAVE_SERVER_PYTHON_SERVICES
|
||||
mPythonLoader.unloadModules();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
105
src/server/qgsserviceregistry.h
Normal file
105
src/server/qgsserviceregistry.h
Normal file
@ -0,0 +1,105 @@
|
||||
/***************************************************************************
|
||||
qgsserviceregstry.h
|
||||
|
||||
Class defining the service manager for QGIS server services.
|
||||
-------------------
|
||||
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 QGSSERVICEREGISTRY_H
|
||||
#define QGSSERVICEREGISTRY_H
|
||||
|
||||
#include "qgsconfig.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
|
||||
#include "qgsservicenativeloader.h"
|
||||
#include "qgsservicepythonloader.h"
|
||||
#include <memory>
|
||||
|
||||
class QgsService;
|
||||
class QgsServiceEntry;
|
||||
|
||||
/**
|
||||
* \ingroup server
|
||||
* QgsServiceRegistry
|
||||
* Class defining the cegistry manager for QGIS server services
|
||||
*
|
||||
* This class provides methods for registering and retrieving
|
||||
* services. Note that the regstiry does not hord ownership of
|
||||
* registered service but vill call the 'release' method on cleanup)
|
||||
*
|
||||
*/
|
||||
class SERVER_EXPORT QgsServiceRegistry
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
QgsServiceRegistry();
|
||||
|
||||
//! Destructor
|
||||
~QgsServiceRegistry();
|
||||
|
||||
/**
|
||||
* Retrieve a service from its name
|
||||
* @param name the name of the service
|
||||
* @param version the version string (optional)
|
||||
* @return QgsService
|
||||
*
|
||||
* If the version is not provided the higher version of the service is rerturnod
|
||||
*/
|
||||
QgsService* getService( const QString& name, const QString& version = QString() );
|
||||
|
||||
/**
|
||||
* Register a service by its name
|
||||
*
|
||||
* This method is intended to be called by modules for registering
|
||||
* services. A module may register multiple services.
|
||||
* The registry gain ownership of services.
|
||||
*
|
||||
* @param name the name of the service
|
||||
* @param service a QgsServerResponse to be registered
|
||||
* @param version the version string for the service (required)
|
||||
*/
|
||||
void registerService( const QString& name, QgsService* service, const QString& version );
|
||||
|
||||
/**
|
||||
* Initialize registry, load modules and auto register services
|
||||
* @param nativeModulepath the native module path
|
||||
* @param pythonModulePath the python module path
|
||||
*
|
||||
* If pythonModulePath is not specified the environnement variables QGIS_PYTHON_SERVICE_PATH
|
||||
* is examined.
|
||||
*/
|
||||
void init( const QString& nativeModulepath, const QString& pythonModulePath = QString() );
|
||||
|
||||
/**
|
||||
* Clean up registered service and unregister modules
|
||||
*/
|
||||
void cleanUp();
|
||||
|
||||
private:
|
||||
typedef QHash<QString, std::shared_ptr<QgsServiceEntry> > ServiceTable;
|
||||
typedef QHash<QString, QPair<QString, QString> > VersionTable;
|
||||
|
||||
QgsServiceNativeLoader mNativeLoader;
|
||||
QgsServicePythonLoader mPythonLoader;
|
||||
|
||||
ServiceTable mServices;
|
||||
VersionTable mVersions;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -172,4 +172,5 @@ IF (WITH_SERVER)
|
||||
ADD_PYTHON_TEST(PyQgsAuthManagerPasswordOWSTest test_authmanager_password_ows.py)
|
||||
ADD_PYTHON_TEST(PyQgsAuthManagerPKIOWSTest test_authmanager_pki_ows.py)
|
||||
ADD_PYTHON_TEST(PyQgsAuthManagerPKIPostgresTest test_authmanager_pki_postgres.py)
|
||||
ADD_PYTHON_TEST(PyQgsServicesTest test_services.py)
|
||||
ENDIF (WITH_SERVER)
|
||||
|
89
tests/src/python/test_services.py
Normal file
89
tests/src/python/test_services.py
Normal file
@ -0,0 +1,89 @@
|
||||
""" QGIS test for server services
|
||||
"""
|
||||
from qgis.PyQt.QtCore import QBuffer, QIODevice, QTextStream
|
||||
from qgis.testing import unittest
|
||||
from qgis.server import (QgsServiceRegistry,
|
||||
QgsService,
|
||||
QgsServerRequest,
|
||||
QgsServerResponse)
|
||||
|
||||
|
||||
class Response(QgsServerResponse):
|
||||
|
||||
def __init__( self ):
|
||||
QgsServerResponse.__init__(self)
|
||||
self._buffer = QBuffer()
|
||||
self._buffer.open(QIODevice.ReadWrite)
|
||||
|
||||
|
||||
def setReturnCode( self, code ):
|
||||
pass
|
||||
|
||||
def setHeader( self, key, val ):
|
||||
pass
|
||||
|
||||
def sendError( self, code, message ):
|
||||
pass
|
||||
|
||||
def io(self):
|
||||
return self._buffer
|
||||
|
||||
|
||||
class MyService(QgsService):
|
||||
|
||||
def __init__(self, response):
|
||||
QgsService.__init__(self)
|
||||
self._response = response
|
||||
|
||||
def executeRequest( self, request, response ):
|
||||
|
||||
url = request.url()
|
||||
|
||||
response.setReturnCode(201)
|
||||
response.write(self._response)
|
||||
|
||||
|
||||
class TestServices(unittest.TestCase):
|
||||
"""
|
||||
"""
|
||||
|
||||
def test_register(self):
|
||||
|
||||
reg = QgsServiceRegistry()
|
||||
|
||||
myserv = MyService("Hello world")
|
||||
|
||||
reg.registerService("STUFF", myserv, "1.0" )
|
||||
|
||||
# Retrieve service
|
||||
request = QgsServerRequest("http://DoStufff", QgsServerRequest.GetMethod)
|
||||
response = Response()
|
||||
|
||||
service = reg.getService("STUFF")
|
||||
if service:
|
||||
service.executeRequest(request, response)
|
||||
|
||||
io = response.io();
|
||||
io.seek(0)
|
||||
|
||||
self.assertEquals(QTextStream(io).readLine(), "Hello world")
|
||||
|
||||
def test_version_registration(self):
|
||||
|
||||
reg = QgsServiceRegistry()
|
||||
myserv1 = MyService("1.0")
|
||||
myserv2 = MyService("1.1")
|
||||
|
||||
reg.registerService("STUFF", myserv1, myserv1._response)
|
||||
reg.registerService("STUFF", myserv2, myserv2._response)
|
||||
|
||||
|
||||
service = reg.getService("STUFF")
|
||||
self.assertIsNotNone(service)
|
||||
self.assertEquals(service._response, myserv2._response)
|
||||
|
||||
service = reg.getService("STUFF", "2.0")
|
||||
self.assertIsNone(service)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user