source: TI05-delivery/ows_framework/branches/ows_framework-refactor/ows_common/ows_common/pylons/ows_controller.py @ 3368

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/ows_framework/branches/ows_framework-refactor/ows_common/ows_common/pylons/ows_controller.py@3368
Revision 3368, 4.9 KB checked in by spascoe, 12 years ago (diff)

About to change some things so commiting current state.

Line 
1"""
2Base controller for OGC Web Services (OWS).
3
4@author: Stephen Pascoe
5@todo: Add pluggable security so replicate what was previously implemented
6    for the NDG discovery portal in ows_server.lib.BaseController.
7"""
8
9
10from pylons import request, response, config
11from pylons.controllers import WSGIController
12from pylons.templating import render
13
14from ows_common import exceptions as OWS_E
15from ows_common.util import negotiate_version
16from ows_common.pylons.decorators import ows_operation
17
18# Import exceptions template
19# This won't work if you haven't enabled Kid importing (already done by pylons)
20from ows_common.pylons.templates import exception_report
21
22try:
23    from xml.etree import ElementTree as ET
24except ImportError:
25    from elementtree import ElementTree as ET
26
27import logging
28logger = logging.getLogger(__name__)
29
30# Configure
31#!TODO: rename this configuration object to something non-NDG specific
32#EXCEPTION_TYPE = request.environ['ndgConfig'].get('OWS_SERVER', 'exception_type', 'ogc').lower()
33EXCEPTION_TYPE = config.get('ows_server.exception_type', 'ogc')
34
35
36class OwsControllerBase(WSGIController):
37    def __call__(self, environ, start_response):
38
39        # All OWS parameter names are case insensitive.
40        self.ows_params = {}
41        for k in request.params:
42            self.ows_params[k.lower()] = request.params[k]       
43
44        # If the EXCEPTION_TYPE is 'pylons' let Pylons catch any exceptions.
45        # Otherwise send an OGC exception report for any OWS_E.OwsError
46        if 'pylons' in EXCEPTION_TYPE:
47            self._fixOwsAction(environ)
48            return super(OwsControllerBase, self).__call__(environ, start_response)
49        else:
50            try:
51                self._fixOwsAction(environ)
52                return super(OwsControllerBase, self).__call__(environ, start_response)
53            except OWS_E.OwsError, e:
54                logger.exception(e)
55
56                response.write(exception_report.serialize(report=e.report))
57                response.headers['content-type'] = 'text/xml'
58                return response
59
60
61    def _fixOwsAction(self, environ):
62        rdict = environ['pylons.routes_dict']
63       
64        # Override the Routes action from the request query parameter
65        try:
66            action = self.ows_params['request']
67        except KeyError:
68            raise OWS_E.MissingParameterValue('REQUEST parameter not specified',
69                                              'REQUEST')
70
71        # Check action is a method in self and is defined as an OWS operation
72        try:
73            op = getattr(self, action)
74            name = op._ows_name
75        except AttributeError:
76            raise OWS_E.InvalidParameterValue('request=%s not supported' % action,
77                                              'REQUEST')
78
79        # Check all required parameters are present
80        for param in op._ows_required_parameters:
81            if param.lower() not in self.ows_params:
82                raise OWS_E.MissingParameterValue('%s parameter not specified'%param,
83                                                  param)
84
85
86        # override routes action with request
87        rdict['action'] = action
88        del self.ows_params['request']
89
90        # Add ows parameters to routes
91        for param in self.ows_params:
92            rdict[param] = self.ows_params[param]
93
94
95
96class OwsController(OwsControllerBase):
97    """
98    Adds basic GetCapabilities response to OwsControllerBase.
99
100    @cvar validVersions: A list of version numbers supported bu this OWS.
101   
102    """
103
104    validVersions = NotImplemented
105
106    def getUpdateSequence(self, uri):
107        """
108        Override in subclasses to return a valid updateSequence for the uri.
109        """
110        return None
111
112    def getCapabilitiesTemplate(self, version, format):
113        """
114        Get the capabilities template.
115        Override in subclases to return a valid template name.
116
117        @param version: the version as a sequence of numbers
118        @param format: the format as a string
119       
120        @return: a template as expected  by pylons.render()
121        """
122        raise NotImplementedError
123
124   
125    @ows_operation(['service'], ['version', 'format', 'updateSequence'])
126    def GetCapabilities(self, url, service, version=None, format='text/xml',
127                        updatesequence=None):
128
129        # Check update sequence
130        serverUpdateSequence = self.getUpdateSequence(uri)
131        if updatesequence and serverUpdateSequence:
132            if updatesequence == serverUpdateSequence:
133                raise OWS_E.CurrentUpdateSequence
134            elif updatesequence > serverUpdateSequence:
135                raise OWS_E.InvalidUpdateSequence
136
137        # Do version negotiation
138        version = negotiate_version(version, self.validVersions)
139           
140        # Render the capabilities document
141        response.headers['content-type'] = format
142        return render(self.getCapabilitiesTemplate(version, format),
143                      format='xml')
144       
145
Note: See TracBrowser for help on using the repository browser.