source: MILK/trunk/milk_server/milk_server/lib/ndgInterface.py @ 4959

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/MILK/trunk/milk_server/milk_server/lib/ndgInterface.py@4959
Revision 4959, 6.3 KB checked in by cbyrom, 11 years ago (diff)

Update MILK stack to use the new ndgCommon clients suite + improve
tests by adding scaffold to do proper tidyups after tests run.

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
10from csml_cache import CSMLExtractCache
11import os, logging
12from ndg.common.src.dal.ndgRetrieve import ndgRetrieve
13from ndg.common.src.models.ndgObject import ndgObject
14from xml.etree import ElementTree as ET
15from pylons import request, session
16
17from pylons import g # for handle to access control PEP interface
18try:
19    from ndg.security.common.authz.pdp import PDPError
20    from ndg.security.common.authz.pep import PEPError
21except ImportError, e:
22    from warnings import warn
23    warn(__name__ + ": access control is disabled: %s" % e, RuntimeWarning)
24
25class ndgInterface:
26   
27    def __init__(self):
28        '''
29        Constructor to set up object
30        '''
31        self.CSMLDataCache = None
32        self.CSMLDocCache = None
33        self.XMLHCache = None
34
35       
36    def SetupCaches(self, csmlDataCache = None, csmlDocCache = None, \
37                    xmlHCache = None):
38        '''
39        Set up the required three level cache:
40                - a file cache
41                - a xmlhandler object cache, and
42                - a parsed CSML object cache.
43        @keyword csmlDataCache: an alternative csmlDataCache to use
44        @keyword csmlDocCache: an alternative csmlDocCache to use
45        @keyword xmlHCache: an alternative xmlHCache to use
46        '''
47        logging.info("Setting up ndgInterface caches")
48        if csmlDataCache:
49            self.CSMLDataCache = csmlDataCache
50        else:
51            self.CSMLDataCache=CSMLExtractCache(
52                request.environ['paste.config']['app_conf']['tmp_dir'],max_size=10)
53       
54        if csmlDocCache:
55            self.CSMLDocCache = csmlDocCache
56        else:
57            self.CSMLDocCache=Cache(max_size=10)
58       
59        if xmlHCache:
60            self.XMLHCache = xmlHCache
61        else:
62            self.XMLHCache=Cache(max_size=10)
63        logging.info("Finished setting up caches")
64       
65
66    def GetXML(self,uri,outputSchema='', useCache=True):
67        '''
68        This method provides a secure interface to the server
69        document cache and a remote NDG exist. It is assumed that
70        the local filesystem is protected in that you can't get to
71        files except via the CSML api
72        @param uri: ndg format uri to locate doc from
73        @keyword outputSchema: format to return doc in
74        @keyword useCache: check for data in the cache and use this, if set to
75        True (the default)   
76        '''
77        #    Note that this method should not be used to obtain
78        #unsecured discovery documents, these are called directly
79        #in the retrieve controller!
80        logging.info("Getting XML from uri, '%s' (outputschema: '%s')" \
81                     %(uri, outputSchema))
82        try:
83            ndgO=ndgObject(uri)
84            localFile=0
85        except ValueError:
86            ''' It's a local file not an ndg identifier '''
87            logging.info("File appears to be local - look for it there...")
88            ndgO=uri
89            localFile=1
90       
91        if session and 'ndgCleared' in session:
92            cleared=session['ndgCleared']
93        else:
94            cleared=None
95       
96        if outputSchema or not useCache:
97            #bypass the cache ...
98            status,xmlh=ndgRetrieve(ndgO,
99                                    request.environ['ndgConfig'],
100                                    output=outputSchema,
101                                    discovery=g.standalone)
102        else:
103            try:
104                if not self.XMLHCache:
105                    self.SetupCaches()
106                   
107                xmlh=self.XMLHCache[uri]
108                status=1
109                logging.info('XMLH Cache hit for [%s]'%uri)
110            except:
111                logging.info('XMLH Cache miss for [%s]'%uri)
112                if localFile:
113                    status,xmlH=self.__getLocal(uri)
114                else:   
115                    status,xmlh=ndgRetrieve(ndgO,
116                                            request.environ['ndgConfig'],
117                                            output=outputSchema,
118                                            discovery=g.standalone)
119                if status: 
120                    self.XMLHCache[uri]=xmlh
121           
122        if not status: return status,xmlh
123       
124        # valid values of the return objects SHOULD BE
125        #   ok:         status=1, xmlh=an xml handler instance.
126        #   exceptions, status=0, xmlh='Exception(e)'
127       
128        status,xmlh=self.__gatekeep(ndgO,xmlh)
129        if status:
130            if cleared is None:
131                session['ndgCleared']=[uri]
132            else:
133                session['ndgCleared'].append(uri)
134            session.save()
135       
136        return status,xmlh
137           
138
139    def __gatekeep(self,uri,x):
140        ''' This is the NDG gatekeeper '''
141        if 'ndgSec' in session:
142            securityTokens=session['ndgSec']
143        else:
144            securityTokens=None
145
146        if not hasattr(g, 'pep'):
147            if not g.standalone:
148                raise PEPError(\
149                "Security is disabled but the standalone flag is set to False")
150               
151            logging.info("__gatekeep: access control is disabled - standalone " + \
152                     "config flag is set")
153           
154        try:
155            # Arguments are: a handle to the resource and a handle to the users
156            # security tokens
157            g.pep(dict(uri=uri, doc=x), securityTokens, None)
158            return True, x
159       
160        except PDPError, e:
161            # Caught a known access control condition
162            return False, 'Access Denied for %s %s' % (uri, e)
163
164               
165    def __getLocal(self,uri):
166        ''' Returns a local csml file (used for testing) '''
167        csml_dir = request.environ['paste.config']['app_conf']['csml_dir']
168        path = os.path.join(csml_dir, file)
169        if os.path.exists(path+'.csml'):
170            f = path+'.csml'
171        elif os.path.exists(path+'.xml'):
172            f = path +'.xml'
173        else:
174            return 0, '<p>Cannot find CSML file %s</p>' % file
175        r=f.read()
176        return 1,r     
Note: See TracBrowser for help on using the repository browser.