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

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@3236
Revision 3236, 5.3 KB checked in by spascoe, 12 years ago (diff)

Made OwsController? consistent with new OWS Protocol (untested)

Line 
1"""
2Base controller for OGC Web Services (OWS).
3
4@author: Stephen Pascoe
5"""
6
7
8from pylons import Response, c, g, cache, request, session
9from pylons.controllers import WSGIController
10from pylons.decorators import jsonify, validate
11from pylons.templating import render, render_response
12from pylons.helpers import abort, redirect_to, etag_cache
13
14import webhelpers as h
15
16#!TODO: Replace this with a pluggable security system
17from ows_server.lib.security_util import setSecuritySession, LoginServiceQuery
18
19from ows_common import exceptions as OWS_E
20from ows_common.operations_metadata import OperationsMetadata, Operation, RequestMethod
21from ows_common.get_capabilities import ServiceMetadata
22import ows_common.xml
23
24
25try:
26    from xml.etree import ElementTree as ET
27except ImportError:
28    from elementtree import ElementTree as ET
29
30import logging
31logger = logging.getLogger(__name__)
32
33# Configure
34#!TODO: rename this configuration object to something non-NDG specific
35EXCEPTION_TYPE = request.environ['ndgConfig'].get('OWS_SERVER', 'exception_type', 'ogc').lower()
36
37
38
39class OwsController(WSGIController):
40    def __call__(self, environ, start_response):
41
42        # All OWS parameter names are case insensitive.
43        req = request._current_obj()
44        self.ows_params = {}
45        for k in req.params:
46            self.ows_params[k.lower()] = req.params[k]       
47
48        # If the EXCEPTION_TYPE is 'pylons' let Pylons catch any exceptions.
49        # Otherwise send an OGC exception report for any OWS_E.OwsError
50        if 'pylons' in EXCEPTION_TYPE:
51            self._fixOwsAction(environ)
52            return super(OwsController, self).__call__(environ, start_response)
53        else:
54            try:
55                self._fixOwsAction(environ)
56                return super(OwsController, self).__call__(environ, start_response)
57            except OWS_E.OwsError, e:
58                logger.exception(e)
59
60                r=render_response('exception_report', report=e.report, format='xml')
61                r.headers['content-type'] = 'text/xml'
62                return r
63
64
65    def _fixOwsAction(self, environ):
66        # Override the Routes action from the request query parameter
67        try:
68            action = self.ows_params['request']
69        except KeyError:
70            raise OWS_E.MissingParameterValue('REQUEST parameter not specified',
71                                              'REQUEST')
72
73        # Check action is a method in self and is defined as an OWS operation
74        try:
75            op = getattr(self, action)
76            name = op._ows_name
77        except AttributeError:
78            raise OWS_E.InvalidParameterValue('request=%s not supported' % action,
79                                              'REQUEST')
80
81        # Check all required parameters are present
82        for param in op._ows_required_parameters:
83            if param.lower() not in self.ows_params:
84                raise OWS_E.MissingParameterValue('%s parameter not specified'%param,
85                                                  param)
86
87        # override routes action with request
88        environ['pylons.routes_dict']['action'] = action
89        del self.ows_params['request']
90
91
92    def _loadCapabilities(self):
93        """
94        creates an ows_common.get_capabilities.ServiceMetadata object
95        by consulting the paste configuration and annotations in the
96        controller definition.
97
98        """
99        # Deduce ows_endpoint from routes
100        ows_endpoint = h.url_for(controller=request.environ['pylons.routes_dict']['controller'])
101       
102        #Deduce base_url from config
103        base_url =request.environ['ndgConfig'].get('DEFAULT','server')
104
105       
106        # Get the server-level configuration data from an XML file
107        config = request.environ['paste.config']
108        sm_tree = ET.parse(config['ows_common_config'])
109        sm = ows_common.xml.service_metadata(sm_tree.getroot())
110       
111        # Extract service-level parameters and constraint
112        parameters = getattr(self, '_ows_parameters', {})
113        constraints = getattr(self, '_ows_constraints', {})
114        versions = getattr(self, '_ows_versions', [])
115       
116        # Extract operation-level parameters and constraints
117        od = {}
118        for attr in dir(self):
119            op = getattr(self, attr)
120            if hasattr(op, '_ows_name'):
121                p = getattr(op, '_ows_parameters', {})
122                c = getattr(op, '_ows_constraints', {})
123                od[op._ows_name] = Operation(get=RequestMethod(href=base_url+ows_endpoint),
124                                             post=None,
125                                             parameters=p,
126                                             constraints=c,
127                                             name=op._ows_name)
128       
129        sm.operationsMetadata = OperationsMetadata(od, constraints, parameters)
130        sm.serviceIdentification.serviceTypeVersions = versions
131        return sm
132
133    def _renderCapabilities(self, template='ows/get_capabilities'):
134        """
135        The standard way of returning a Capabilities document.
136
137        Each subclass should implement self._load_capabilities() and call
138        this method to return a response object.
139
140        """
141        c.service_metadata = self._loadCapabilities()       
142        r = render_response(template, format='xml')
143        r.headers['content-type'] = 'text/xml'
144        return r
145
Note: See TracBrowser for help on using the repository browser.