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

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@3408
Revision 3408, 5.7 KB checked in by spascoe, 13 years ago (diff)

Trying without any decorators

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, check_updatesequence
16
17from genshi.template import TemplateLoader
18
19try:
20    from xml.etree import ElementTree as ET
21except ImportError:
22    from elementtree import ElementTree as ET
23
24import logging
25logger = logging.getLogger(__name__)
26
27# Instantiate Genshi template loader
28genshiLoader = TemplateLoader(
29    resource_filename('ows_common.pylons', 'templates')
30    auto_reload=True
31    )
32
33# Configure
34#!TODO: rename this configuration object to something non-NDG specific
35#EXCEPTION_TYPE = request.environ['ndgConfig'].get('OWS_SERVER', 'exception_type', 'ogc').lower()
36EXCEPTION_TYPE = config.get('ows_server.exception_type', 'ogc')
37
38
39
40class OwsControllerBase(WSGIController):
41    """
42    @ivar owsParams: A dictionary of parameters passed to the service.
43        Initially these comes from the query string but could come from
44        a HTTP POST in future.
45    @cvar owsOperations: A dictionary of operation configuration options.
46   
47    """
48
49    owsOperations = {}
50   
51    def __call__(self, environ, start_response):
52
53        self._loadOwsParams()
54
55        # If the EXCEPTION_TYPE is 'pylons' let Pylons catch any exceptions.
56        # Otherwise send an OGC exception report for any OWS_E.OwsError
57        if 'pylons' in EXCEPTION_TYPE:
58            self._fixOwsAction(environ)
59            return super(OwsControllerBase, self).__call__(environ, start_response)
60        else:
61            try:
62                self._fixOwsAction(environ)
63                return super(OwsControllerBase, self).__call__(environ, start_response)
64            except OWS_E.OwsError, e:
65                logger.exception(e)
66
67                tmpl = genshiLoader.load('exception_report.xml')
68                response.write(tmpl.generate(report=e.report).render('xml'))
69                response.headers['content-type'] = 'text/xml'
70                return response
71
72    def _loadOwsParams(self):
73        # All OWS parameter names are case insensitive.
74        self._owsParams = {}
75        for k in request.params:
76            self._owsParams[k.lower()] = request.params[k]
77
78    def _fixOwsAction(self, environ):
79        rdict = environ['pylons.routes_dict']
80       
81        # Override the Routes action from the request query parameter
82        action = self.getOwsParam('request')
83
84        # Check action is a method in self and is defined as an OWS operation
85        try:
86            self.opConfig = self.owsOperations[action]
87        except AttributeError:
88            raise OWS_E.InvalidParameterValue('request=%s not supported' % action,
89                                              'REQUEST')
90        rdict['action'] = action
91
92    def getOwsParam(self, param, **kwargs):
93        """
94        Returns the value of a OWS parameter passed to the operation.
95        If argv['default'] is given it is taken to be the default
96        value otherwise the parameter is treated as manditory and an
97        exception is raised if the parameter is not present.
98
99        """
100        try:
101            return self._owsParams[param.lower()]
102        except KeyError:
103            if 'default' in kwargs:
104                return kwargs['default']
105            else:
106                raise OWS_E.MissingParameterValue('%s parameter is not specified' % param,
107                                                  param)
108
109
110class OwsController(OwsControllerBase):
111    """
112    Adds basic GetCapabilities response to OwsControllerBase.
113
114    @ivar service: If None does not enforce the SERVICE parameter.  Otherwise
115        raises exception if SERVICE is not correct on GetCapabilities request.
116    @ivar validCapabilitiesFormats: Sequence of supported Capabilities
117        mime-types.
118    @cvar validVersions: A list of supported version numbers.  Automatic
119        version negotiation is performed according to this attribute.
120   
121    @ivar updateSequence: None if cache-control is not supported or an
122        updateSequence identifier.  This attribute should be set in the
123        controller's __before__() method.
124    """
125
126    # Override these attributes to control how OwsController responds to
127    # GetCapabilities
128    service = None
129    validVersions = NotImplemented
130
131    owsOperations = dict(
132        GetCapabilities = dict(formats=('text/xml',))
133        )
134
135    updateSequence = None
136
137    def renderCapabilities(self, version, format):
138        """
139        Override in subclases to render the capabilities document.
140        The response mime-type will already have been set.
141
142        @param version: the version as a sequence of numbers
143        @param format: the format as a string
144       
145        @return: a template as expected by pylons.render()
146        """
147        raise NotImplementedError
148   
149    def GetCapabilities(self):
150
151        # Retrieve Operation parameters
152        service = self.getOwsParam('service')
153        version = self.getOwsParam('version', default=None)
154        format = self.getOwsParam('format', default='text/xml')
155        updatesequence = self.getOwsParam('updatesequence', default=None)
156
157        # Check update sequence
158        check_updatesequence(self.updateSequence, updateSequence)
159
160        # Do version negotiation
161        version = negotiate_version(version, self.validVersions)
162
163        # Get information required for the capabilities document
164       
165       
166        # Render the capabilities document       
167        response.headers['content-type'] = format
168        return self.renderCapabilities(version, format)
169       
170
Note: See TracBrowser for help on using the repository browser.