source: TI05-delivery/ows_framework/trunk/ows_server/ows_server/lib/ndgInterface.py @ 2754

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/ows_framework/trunk/ows_server/ows_server/lib/ndgInterface.py@2754
Revision 2754, 7.0 KB checked in by lawrence, 12 years ago (diff)

Turning of security in ndgInterface for now ...

Line 
1# Copyright (C) 2007 STFC & NERC (Science and Technology Facilities Council).
2# This software may be distributed under the terms of the
3# Q Public License, version 1.0 or later.
4# http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt
5"""
6Manages interface to NDG documents and data, including caching
7"""
8
9from cache import Cache
10import os, tempfile
11import cdms, csml
12from ows_server.models import ndgRetrieve, ndgObject
13from pylons import request,session
14import logging
15logger = logging.getLogger('ndgInterface')
16from ows_server.models.ndgSecurity import HandleSecurity
17
18class CDMSEntry(object):
19    """
20    A reference to a CDMS file that will delete the file when it is
21    garbage collected.
22
23    Instances of this class are used as Cache entry values.  When entries are
24    automatically removed from the cache the CDMSEntry object will be
25    garbage collected unless it is being accessed by another thread.
26
27    """
28
29    __slots__ = ['_f', 'var']
30   
31    def __init__(self, filename, varname):
32        logger.info('Caching file variable %s in %s' % (varname, filename))
33        self._f = cdms.open(filename)
34        self.var = self._f[varname]
35    def __del__(self):
36        filename = self._f.id
37        logger.info('Removing file %s' % filename)
38        self._f.close()
39        os.remove(filename)
40 
41
42class CSMLExtractCache(Cache):
43   
44    def __init__(self, cache_dir, max_size=0):
45        super(CSMLExtractCache, self).__init__(max_size)
46        self._cache_dir = cache_dir
47
48    def _extract(self, feature, sel):
49        (fd, filename) = tempfile.mkstemp('.nc', 'csml_wxs_', self._cache_dir)
50        os.close(fd)
51        (outputdir, ncname) = os.path.split(filename)
52
53        # Workarround until ticket:778 (TestExtractAll) is fixed
54        sel.update(longitude=(-180, 180), latitude=(-90, 90))
55
56        feature.subsetToGridSeries(ncname=ncname, outputdir=outputdir, **sel)
57
58        return filename
59   
60    def key(self, name):
61        """
62        Cache provides this method to map externally visible entry names
63        to internal keys.  We use it here to turn selectors into hashable
64        values.
65
66        """
67        (feature, sel) = name
68       
69        return (feature.id, tuple(sorted(sel.items())))
70
71    def build(self, key, name, opened, entry):
72        (feature, sel) = name
73        filename = self._extract(feature, sel)
74
75        return CDMSEntry(filename, feature.name.CONTENT)
76
77    def __getitem__(self, name):
78        """
79        Returns the opened CDMS object.
80
81        """
82        return super(CSMLExtractCache, self).__getitem__(name).var
83
84class ndgInterface:
85   
86    def __init__(self):
87        ''' Instantiate with three level cache:
88                - a file cache
89                - a xmlhandler object cache, and
90                - a parsed CSML object cache.'''
91               
92        self.CSMLDataCache=CSMLExtractCache(
93                request.environ['paste.config']['app_conf']['tmp_dir'],max_size=10)
94        self.CSMLDocCache=Cache(max_size=10)
95        self.XMLHCache=Cache(max_size=10)
96       
97
98    def GetXML(self,uri,format=''):
99        ''' This method provides a secure interface to the server
100        document cache and a remote NDG exist. It is assumed that
101        the local filesystem is protected in that you can't get to
102        files except via the CSML api '''
103        #    Note that this method should not be used to obtain
104        #unsecured discovery documents, these are called directly
105        #in the retrieve controller!
106       
107        try:
108            ndgO=ndgObject.ndgObject(uri)
109            localFile=0
110        except ValueError:
111            ''' It's a local file not an ndg identifier '''
112            ndg0=uri
113            localFile=1
114       
115        if 'ndgCleared' in session:
116            cleared=session['ndgCleared']
117        else:
118            cleared=None
119         
120        try:
121            xmlh=self.XMLHCache[uri]
122            status=1
123            logging.info('XMLH Cache hit for [%s]'%uri)
124        except:
125            logging.info('XMLH Cache miss for [%s]'%uri)
126            if localFile:
127                status,xmlH=self.__getLocal(uri)
128            else:   
129                status,xmlh=ndgRetrieve.ndgRetrieve(ndgO,request.environ['ndgConfig'],logger,format)
130            if status: self.XMLHCache[uri]=xmlh
131       
132        # valid values of the return objects SHOULD BE
133        #   ok:         status=1, xmlh=an xml handler instance.
134        #   exceptions, status=0, xmlh='Exception(e)'
135       
136        status,xmlh=self.__GateKeep(ndgO,xmlh)
137        if status:
138            if cleared is None:
139                session['ndgCleared']=[uri]
140            else:
141                session['ndgCleared'].append(uri)
142            session.save()
143       
144        return status,xmlh
145           
146    def GetParsedCSML(self,uri):
147       
148        ''' This method gets a parsed CSML object corresponding to the URI '''
149       
150        # do we need an xml handler instance to test the security?
151        if 'ndgCleared' not in session:
152            status,xmlh=self.GetXML(uri)
153        else: 
154            if uri not in session['ndgCleared']: 
155                status,xmlh=self.GetXML(uri)
156            else: status=1
157        if not status: return status,xmlh
158       
159        try:
160            d=self.CSMLDocCache[uri]
161            logging.info('CSML Cache hit for [%s]'%uri)
162        except:
163            logging.info('CSML Cache miss for [%s]'%uri)
164            status,xmlh=self.GetXML(uri)
165            if not status: return status,xmlh   
166            d=csml.parser.Dataset()
167            d.parseElemTree(xmlh.tree)
168            self.CSMLDocCache[uri]=d
169        status=1
170        return status,d
171       
172    def __GateKeep(self,uri,x):
173        ''' This is the NDG gatekeeper '''
174        if 'ndgSec' in session:
175            securityTokens=session['ndgSec']
176        else:
177            securityTokens=None
178       
179        if uri.schema=='DIF':
180            pass # no access control
181        elif uri.schema =='NDG-B0':
182            #cred=x.find('dgSecurityCondition/simpleCondition')
183            #if cred:
184            #    return 0,'<p> Access Control: <br/>[<![CDAT[%s]]> </p>'
185            pass
186        elif uri.schema =='NDG-B1':
187            pass # for the moment
188        elif uri.schema =='NDG-A0':
189            if 0:
190                # turn off security for now
191                s=x.tree.find('{http://ndg.nerc.ac.uk/csml}AccessControlPolicy/{http://ndg.nerc.ac.uk/csml}dgSecurityCondition')
192                if s is not None:
193                    status,message=HandleSecurity(s,securityTokens)
194                    if not status: return 0,'<p> Access Denied </p><p>%s</p>'%message
195        return 1,x
196               
197    def __getLocal(self,uri):
198        ''' Returns a local csml file (used for testing) '''
199        csml_dir = request.environ['paste.config']['app_conf']['csml_dir']
200        path = os.path.join(csml_dir, file)
201        if os.path.exists(path+'.csml'):
202            f = path+'.csml'
203        elif os.path.exists(path+'.xml'):
204            f = path +'.xml'
205        else:
206            return 0, '<p>Cannot find CSML file %s</p>' % file
207        r=f.read()
208        return 1,r     
209       
210
211
212interface=ndgInterface()
Note: See TracBrowser for help on using the repository browser.