diff --git a/src/mapserver/qgis_map_serv.cpp b/src/mapserver/qgis_map_serv.cpp index 6095eec5f22f..65d9f9102e6f 100644 --- a/src/mapserver/qgis_map_serv.cpp +++ b/src/mapserver/qgis_map_serv.cpp @@ -37,6 +37,11 @@ #include "qgsnetworkaccessmanager.h" #include "qgsmaplayerregistry.h" #include "qgsserverlogger.h" +#ifdef MAPSERVER_HAVE_PYTHON_PLUGINS +#include "qgsserverplugins.h" +#include "qgsserverfilter.h" +#include "qgsserverinterfaceimpl.h" +#endif #include #include @@ -315,6 +320,18 @@ int main( int argc, char * argv[] ) int logLevel = QgsServerLogger::instance()->logLevel(); QTime time; //used for measuring request time if loglevel < 1 +#ifdef MAPSERVER_HAVE_PYTHON_PLUGINS + // Create the interface + QgsServerInterfaceImpl serverIface( &capabilitiesCache ); + // Init plugins + if (! QgsServerPlugins::initPlugins( &serverIface ) ) + { + QgsMessageLog::logMessage( "No server plugins are available", "Server", QgsMessageLog::INFO ); + } + // Store plugin filters for faster access + QMultiMap pluginFilters = serverIface.filters(); +#endif + while ( fcgi_accept() >= 0 ) { QgsMapLayerRegistry::instance()->removeAllMapLayers(); @@ -340,6 +357,17 @@ int main( int argc, char * argv[] ) theRequestHandler->setServiceException( e ); } +#ifdef MAPSERVER_HAVE_PYTHON_PLUGINS + // Set the request handler into the interface for plugins to manipulate it + serverIface.setRequestHandler( theRequestHandler.data() ); + // Iterate filters and call their requestReady() method + QgsServerFiltersMap::const_iterator filtersIterator; + for( filtersIterator = pluginFilters.constBegin(); filtersIterator != pluginFilters.constEnd(); ++filtersIterator) + { + filtersIterator.value()->requestReady(); + } +#endif + // Copy the parameters map QMap parameterMap( theRequestHandler->parameterMap() ); @@ -398,6 +426,14 @@ int main( int argc, char * argv[] ) } // end switch } // end if not exception raised +#ifdef MAPSERVER_HAVE_PYTHON_PLUGINS + // Call responseReady plugin filters + for(filtersIterator = pluginFilters.constBegin(); filtersIterator != pluginFilters.constEnd(); ++filtersIterator) + { + filtersIterator.value()->responseReady(); + } +#endif + theRequestHandler->sendResponse(); if ( logLevel < 1 ) diff --git a/src/mapserver/qgsserverfilter.cpp b/src/mapserver/qgsserverfilter.cpp new file mode 100644 index 000000000000..de604379eea0 --- /dev/null +++ b/src/mapserver/qgsserverfilter.cpp @@ -0,0 +1,49 @@ +/*************************************************************************** + qgsseerverfilter.cpp + Server I/O filters class for Qgis Mapserver for use by plugins + ------------------- + begin : 2014-09-10 + copyright : (C) 2014 by Alessandro Pasotti + email : a dot pasotti at itopen dot it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "qgsserverfilter.h" +#include "qgslogger.h" + +/** + * QgsServerFilter + * Class defining I/O filters for Qgis Mapserver and + * implemented in plugins + * + */ + +QgsServerFilter::QgsServerFilter(QgsServerInterface *serverInterface): + mServerInterface( serverInterface ) +{ +} + +QgsServerFilter::~QgsServerFilter() +{ +} + + +void QgsServerFilter::requestReady() +{ + QgsDebugMsg( "QgsServerFilter plugin default requestReady called"); +} + +void QgsServerFilter::responseReady() +{ + QgsDebugMsg( "QgsServerFilter plugin default responseReady called"); +} + diff --git a/src/mapserver/qgsserverfilter.h b/src/mapserver/qgsserverfilter.h new file mode 100644 index 000000000000..ebe28ff509d0 --- /dev/null +++ b/src/mapserver/qgsserverfilter.h @@ -0,0 +1,55 @@ +/*************************************************************************** + qgsseerverfilter.h + Server I/O filters class for Qgis Mapserver for use by plugins + ------------------- + begin : 2014-09-10 + copyright : (C) 2014 by Alessandro Pasotti + email : a dot pasotti at itopen dot it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 QGSSERVERFILTER_H +#define QGSSERVERFILTER_H + +#include + +class QgsServerInterface; + +/** + * QgsServerFilter + * Class defining I/O filters for Qgis Server and + * implemented in plugins + * + */ + +class QgsServerFilter +{ + +public: + + /** Constructor */ + QgsServerFilter( QgsServerInterface* serverInterface ); + /** Destructor */ + virtual ~QgsServerFilter(); + QgsServerInterface* serverInterface( ) { return mServerInterface; } + virtual void requestReady(); + virtual void responseReady(); + +private: + + QgsServerInterface* mServerInterface; + +}; + +typedef QMultiMap QgsServerFiltersMap; + + +#endif // QGSSERVERFILTER_H diff --git a/src/mapserver/qgsserverinterface.cpp b/src/mapserver/qgsserverinterface.cpp new file mode 100644 index 000000000000..6b6119cd6f78 --- /dev/null +++ b/src/mapserver/qgsserverinterface.cpp @@ -0,0 +1,29 @@ +/*************************************************************************** + * qgsserverinterface.cpp + * Abstract base class for interfaces to functions in QgsServer + * ------------------- + * begin : 2014-29-09 + * copyright : (C) 2014 by Alessandro Pasotti + * email : a dot pasotti at itopen 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 "qgsserverinterface.h" + +QgsServerInterface::QgsServerInterface() +{ + + +} + +QgsServerInterface::~QgsServerInterface() +{ +} diff --git a/src/mapserver/qgsserverinterface.h b/src/mapserver/qgsserverinterface.h new file mode 100644 index 000000000000..6beab14f95e3 --- /dev/null +++ b/src/mapserver/qgsserverinterface.h @@ -0,0 +1,52 @@ +/*************************************************************************** + qgsseerversinterface.h + Interface class for exposing functions in Qgis Server for use by plugins + ------------------- + begin : 2014-09-10 + copyright : (C) 2014 by Alessandro Pasotti + email : a dot pasotti at itopen dot it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 QGSSERVERINTERFACE_H +#define QGSSERVERINTERFACE_H + +#include "qgscapabilitiescache.h" +#include "qgsrequesthandler.h" +#include "qgsserverfilter.h" + +/** + * QgsServerInterface + * Class defining interfaces exposed by Qgis Mapserver and + * made available to plugins. + * + */ + +class QgsServerInterface +{ + + public: + + /** Constructor */ + QgsServerInterface( ); + + /** Destructor */ + virtual ~QgsServerInterface() = 0; + + virtual void setRequestHandler( QgsRequestHandler* requestHandler ) = 0; + virtual QgsCapabilitiesCache* capabiblitiesCache() = 0; + virtual QgsRequestHandler* requestHandler( ) = 0; + virtual void registerFilter( QgsServerFilter* filter, int priority = 0 ) = 0; + virtual QgsServerFiltersMap filters( ) = 0; + +}; + +#endif // QGSSERVERINTERFACE_H diff --git a/src/mapserver/qgsserverinterfaceimpl.cpp b/src/mapserver/qgsserverinterfaceimpl.cpp new file mode 100644 index 000000000000..216d3d022e38 --- /dev/null +++ b/src/mapserver/qgsserverinterfaceimpl.cpp @@ -0,0 +1,43 @@ +/*************************************************************************** + qgsseerversinterface.h + Interface class for exposing functions in Qgis Mapserver for use by plugins + ------------------- + begin : 2014-09-10 + copyright : (C) 2014 by Alessandro Pasotti + email : a dot pasotti at itopen dot it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "qgsserverinterfaceimpl.h" + + +QgsServerInterfaceImpl::QgsServerInterfaceImpl( QgsCapabilitiesCache* capCache ) : + mCapabilitiesCache( capCache ) +{ + mRequestHandler = NULL; +} + + +/** Destructor */ +QgsServerInterfaceImpl::~QgsServerInterfaceImpl() +{ +} + +void QgsServerInterfaceImpl::setRequestHandler( QgsRequestHandler * requestHandler) +{ + mRequestHandler = requestHandler; +} + +void QgsServerInterfaceImpl::registerFilter( QgsServerFilter *filter, int priority ) +{ + mFilters.insert(priority, filter); +} diff --git a/src/mapserver/qgsserverinterfaceimpl.h b/src/mapserver/qgsserverinterfaceimpl.h new file mode 100644 index 000000000000..93acc4cb17a1 --- /dev/null +++ b/src/mapserver/qgsserverinterfaceimpl.h @@ -0,0 +1,61 @@ +/*************************************************************************** + qgsseerversinterface.h + Interface class for exposing functions in Qgis Mapserver for use by plugins + ------------------- + begin : 2014-09-10 + copyright : (C) 2014 by Alessandro Pasotti + email : a dot pasotti at itopen dot it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 QGSSERVERINTERFACEIMPL_H +#define QGSSERVERINTERFACEIMPL_H + +#include "qgsserverinterface.h" +#include "qgscapabilitiescache.h" +#include "qgsgetrequesthandler.h" +#include "qgspostrequesthandler.h" +#include "qgssoaprequesthandler.h" +#include "qgsmaprenderer.h" + +/** + * QgsServerInterface + * Class defining interfaces exposed by Qgis Mapserver and + * made available to plugins. + * + */ + +class QgsServerInterfaceImpl : public QgsServerInterface +{ + +public: + + /** Constructor */ + QgsServerInterfaceImpl( QgsCapabilitiesCache *capCache ); + + /** Destructor */ + ~QgsServerInterfaceImpl(); + + void setRequestHandler( QgsRequestHandler* requestHandler ); + QgsCapabilitiesCache* capabiblitiesCache() { return mCapabilitiesCache; } + QgsRequestHandler* requestHandler( ) { return mRequestHandler; } + void registerFilter( QgsServerFilter *filter, int priority = 0 ); + QgsServerFiltersMap filters( ) { return mFilters; } + +private: + + QgsServerFiltersMap mFilters; + QgsCapabilitiesCache* mCapabilitiesCache; + QgsRequestHandler* mRequestHandler; + +}; + +#endif // QGSSERVERINTERFACEIMPL_H diff --git a/src/mapserver/qgsserverplugins.cpp b/src/mapserver/qgsserverplugins.cpp new file mode 100644 index 000000000000..9ccd748a9a56 --- /dev/null +++ b/src/mapserver/qgsserverplugins.cpp @@ -0,0 +1,113 @@ +/*************************************************************************** + QgsServerPlugins.cpp + ------------------------- + begin : August 28, 2014 + copyright : (C) 2014 by Alessandro Pasotti - ItOpen + email : apasotti at gmail 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 "qgsserverplugins.h" +#include "qgsmapserviceexception.h" +#include "qgsapplication.h" +#include "qgslogger.h" +#include "qgsserverlogger.h" +#include "qgsmsutils.h" + +#include + +QgsServerPlugins::QgsServerPlugins() +{ +} + +// Initialize static members +QgsPythonUtils* QgsServerPlugins::mPythonUtils; +// Initialize static members +QStringList QgsServerPlugins::mServerPlugins; + +// This code is mainly borrowed from QGIS desktop Python plugin initialization +bool QgsServerPlugins::initPlugins(QgsServerInterface *interface) +{ + + QString pythonlibName( "qgispython" ); +#if defined(Q_WS_MAC) || defined(Q_OS_LINUX) + pythonlibName.prepend( QgsApplication::libraryPath() ); +#endif +#ifdef __MINGW32__ + pythonlibName.prepend( "lib" ); +#endif + QString version = QString( "%1.%2.%3" ).arg( QGis::QGIS_VERSION_INT / 10000 ).arg( QGis::QGIS_VERSION_INT / 100 % 100 ).arg( QGis::QGIS_VERSION_INT % 100 ); + QgsDebugMsg( QString( "load library %1 (%2)" ).arg( pythonlibName ).arg( version ) ); + QLibrary pythonlib( pythonlibName, version ); + // It's necessary to set these two load hints, otherwise Python library won't work correctly + // see http://lists.kde.org/?l=pykde&m=117190116820758&w=2 + pythonlib.setLoadHints( QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint ); + if ( !pythonlib.load() ) + { + pythonlib.setFileName( pythonlibName ); + if ( !pythonlib.load() ) + { + QgsDebugMsg( QString( "Couldn't load Python support library: %1" ).arg( pythonlib.errorString() ) ); + return FALSE; + } + } + + QgsDebugMsg("Python support library loaded successfully."); + typedef QgsPythonUtils*( *inst )(); + inst pythonlib_inst = ( inst ) cast_to_fptr( pythonlib.resolve( "instance" ) ); + if ( !pythonlib_inst ) + { + //using stderr on purpose because we want end users to see this [TS] + QgsDebugMsg( QString( "Couldn't resolve python support library's instance() symbol." ) ); + return FALSE; + } + + QgsDebugMsg("Python support library's instance() symbol resolved."); + mPythonUtils = pythonlib_inst(); + mPythonUtils->initServerPython( interface ); + + if ( mPythonUtils && mPythonUtils->isEnabled() ) + { + QgsDebugMsg("Python support ENABLED :-)"); + } + else + { + QgsDebugMsg("Python support FAILED :-("); + return FALSE; + } + + //Init plugins: loads a list of installed plugins and filter them + //for "server" metadata + QListIterator plugins( mPythonUtils->pluginList() ); + bool atLeastOneEnabled = FALSE; + while (plugins.hasNext()) + { + QString pluginName = plugins.next(); + QString pluginService = mPythonUtils->getPluginMetadata(pluginName, "server" ); + if ( pluginService == "True" ) + { + if ( mPythonUtils->loadPlugin( pluginName ) ) + { + if ( mPythonUtils->startServerPlugin( pluginName )) + { + atLeastOneEnabled = TRUE; + mServerPlugins.append( pluginName ); + QgsMessageLog::logMessage( QString("Server plugin %1 loaded!").arg( pluginName ), "Server", QgsMessageLog::CRITICAL ); + } else { + QgsMessageLog::logMessage( QString("Error loading server plugin %1").arg( pluginName ), "Server", QgsMessageLog::CRITICAL ); + } + } else { + QgsMessageLog::logMessage( QString("Error starting server plugin %1").arg( pluginName ), "Server", QgsMessageLog::CRITICAL ); + } + } + } + return mPythonUtils && mPythonUtils->isEnabled() && atLeastOneEnabled; +} diff --git a/src/mapserver/qgsserverplugins.h b/src/mapserver/qgsserverplugins.h new file mode 100644 index 000000000000..d77f08928fce --- /dev/null +++ b/src/mapserver/qgsserverplugins.h @@ -0,0 +1,34 @@ +/*************************************************************************** + qgsserverplugins.h + ------------------------- + begin : August 28, 2014 + copyright : (C) 2014 by Alessandro Pasotti - ItOpen + email : apasotti at gmail 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 QGSSERVERPLUGINS_H +#define QGSSERVERPLUGINS_H + +#include "qgsrequesthandler.h" +#include "qgspythonutils.h" +#include "qgsserverinterface.h" + +class QgsServerPlugins +{ +public: + explicit QgsServerPlugins(); + static bool initPlugins(QgsServerInterface* interface); + static QgsPythonUtils* mPythonUtils; + static QStringList mServerPlugins; +}; + +#endif // QGSSERVERPLUGINS_H