source: TI12-security/trunk/NDG_XACML/ndg/xacml/core/functions/__init__.py @ 6803

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDG_XACML/ndg/xacml/core/functions/__init__.py@6803
Revision 6803, 24.3 KB checked in by pjkersha, 9 years ago (diff)

Refactored function modules with class factories to generate classes for each variable type.

Line 
1"""NDG XACML package for functions
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "26/03/10"
7__copyright__ = "(C) 2010 Science and Technology Facilities Council"
8__contact__ = "Philip.Kershaw@stfc.ac.uk"
9__license__ = "BSD - see LICENSE file in top-level directory"
10__contact__ = "Philip.Kershaw@stfc.ac.uk"
11__revision__ = "$Id: $"
12from abc import ABCMeta, abstractmethod
13from datetime import datetime, timedelta
14import traceback
15import logging
16log = logging.getLogger(__name__)
17
18from ndg.xacml.core.attributevalue import AttributeValue
19from ndg.xacml.utils import VettedDict
20from ndg.xacml.utils.factory import callModuleObject
21
22
23class AbstractFunction(object):
24    """Base class for all XACML matching functions"""
25   
26    __metaclass__ = ABCMeta
27    FUNCTION_NS = None
28    V1_0_FUNCTION_NS = "urn:oasis:names:tc:xacml:1.0:function:"
29    V2_0_FUNCTION_NS = "urn:oasis:names:tc:xacml:2.0:function:"
30   
31    def __init__(self):
32        if self.__class__.FUNCTION_NS is None:
33            raise TypeError('"FUNCTION_NS" class variable must be defined in '
34                            'derived classes')
35           
36    @abstractmethod
37    def evaluate(self, *inputs):
38        """Evaluate the function from the given input arguments and context
39        @param inputs: input arguments need to evaluate the function
40        @type inputs: tuple
41        @return: True for match, False otherwise
42        @rtype: bool
43        """
44       
45class XacmlFunctionNames(object):
46    """XACML standard match function names"""
47    FUNCTION_NAMES = (
48        'urn:oasis:names:tc:xacml:1.0:function:string-equal',
49        'urn:oasis:names:tc:xacml:1.0:function:boolean-equal',
50        'urn:oasis:names:tc:xacml:1.0:function:integer-equal',
51        'urn:oasis:names:tc:xacml:1.0:function:double-equal',
52        'urn:oasis:names:tc:xacml:1.0:function:date-equal',
53        'urn:oasis:names:tc:xacml:1.0:function:time-equal',
54        'urn:oasis:names:tc:xacml:1.0:function:dateTime-equal',
55        'urn:oasis:names:tc:xacml:1.0:function:dayTimeDuration-equal',
56        'urn:oasis:names:tc:xacml:1.0:function:yearMonthDuration-equal',
57        'urn:oasis:names:tc:xacml:1.0:function:anyURI-equal',
58        'urn:oasis:names:tc:xacml:1.0:function:x500Name-equal',
59        'urn:oasis:names:tc:xacml:1.0:function:rfc822Name-equal',
60        'urn:oasis:names:tc:xacml:1.0:function:hexBinary-equal',
61        'urn:oasis:names:tc:xacml:1.0:function:base64Binary-equal',
62        'urn:oasis:names:tc:xacml:1.0:function:integer-add',
63        'urn:oasis:names:tc:xacml:1.0:function:double-add',
64        'urn:oasis:names:tc:xacml:1.0:function:integer-subtract',
65        'urn:oasis:names:tc:xacml:1.0:function:double-subtract',
66        'urn:oasis:names:tc:xacml:1.0:function:integer-multiply',
67        'urn:oasis:names:tc:xacml:1.0:function:double-multiply',
68        'urn:oasis:names:tc:xacml:1.0:function:integer-divide',
69        'urn:oasis:names:tc:xacml:1.0:function:double-divide',
70        'urn:oasis:names:tc:xacml:1.0:function:integer-mod',
71        'urn:oasis:names:tc:xacml:1.0:function:integer-abs',
72        'urn:oasis:names:tc:xacml:1.0:function:double-abs',
73        'urn:oasis:names:tc:xacml:1.0:function:round',
74        'urn:oasis:names:tc:xacml:1.0:function:floor',
75        'urn:oasis:names:tc:xacml:1.0:function:string-normalize-space',
76        'urn:oasis:names:tc:xacml:1.0:function:string-normalize-to-lower-case',
77        'urn:oasis:names:tc:xacml:1.0:function:double-to-integer',
78        'urn:oasis:names:tc:xacml:1.0:function:integer-to-double',
79        'urn:oasis:names:tc:xacml:1.0:function:or',
80        'urn:oasis:names:tc:xacml:1.0:function:and',
81        'urn:oasis:names:tc:xacml:1.0:function:n-of',
82        'urn:oasis:names:tc:xacml:1.0:function:not',
83        'urn:oasis:names:tc:xacml:1.0:function:integer-greater-than',
84        'urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal',
85        'urn:oasis:names:tc:xacml:1.0:function:integer-less-than',
86        'urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal',
87        'urn:oasis:names:tc:xacml:1.0:function:double-greater-than',
88        'urn:oasis:names:tc:xacml:1.0:function:double-greater-than-or-equal',
89        'urn:oasis:names:tc:xacml:1.0:function:double-less-than',
90        'urn:oasis:names:tc:xacml:1.0:function:double-less-than-or-equal',
91        'urn:oasis:names:tc:xacml:1.0:function:dateTime-add-dayTimeDuration',
92        'urn:oasis:names:tc:xacml:1.0:function:dateTime-add-yearMonthDuration',
93        'urn:oasis:names:tc:xacml:1.0:function:dateTime-subtract-dayTimeDuration',
94        'urn:oasis:names:tc:xacml:1.0:function:dateTime-subtract-yearMonthDuration', 
95        'urn:oasis:names:tc:xacml:1.0:function:date-add-yearMonthDuration',
96        'urn:oasis:names:tc:xacml:1.0:function:date-subtract-yearMonthDuration',
97        'urn:oasis:names:tc:xacml:1.0:function:string-greater-than',
98        'urn:oasis:names:tc:xacml:1.0:function:string-greater-than-or-equal',
99        'urn:oasis:names:tc:xacml:1.0:function:string-less-than',
100        'urn:oasis:names:tc:xacml:1.0:function:string-less-than-or-equal',
101        'urn:oasis:names:tc:xacml:1.0:function:time-greater-than',
102        'urn:oasis:names:tc:xacml:1.0:function:time-greater-than-or-equal',
103        'urn:oasis:names:tc:xacml:1.0:function:time-less-than',
104        'urn:oasis:names:tc:xacml:1.0:function:time-less-than-or-equal',
105        'urn:oasis:names:tc:xacml:2.0:function:time-in-range',
106        'urn:oasis:names:tc:xacml:1.0:function:dateTime-greater-than',
107        'urn:oasis:names:tc:xacml:1.0:function:dateTime-greater-than-or-equal',
108        'urn:oasis:names:tc:xacml:1.0:function:dateTime-less-than',
109        'urn:oasis:names:tc:xacml:1.0:function:dateTime-less-than-or-equal',
110        'urn:oasis:names:tc:xacml:1.0:function:date-greater-than',
111        'urn:oasis:names:tc:xacml:1.0:function:date-greater-than-or-equal',
112        'urn:oasis:names:tc:xacml:1.0:function:date-less-than',
113        'urn:oasis:names:tc:xacml:1.0:function:date-less-than-or-equal',
114        'urn:oasis:names:tc:xacml:1.0:function:string-one-and-only',
115        'urn:oasis:names:tc:xacml:1.0:function:string-bag-size',
116        'urn:oasis:names:tc:xacml:1.0:function:string-is-in',
117        'urn:oasis:names:tc:xacml:1.0:function:string-bag',
118        'urn:oasis:names:tc:xacml:1.0:function:boolean-one-and-only',
119        'urn:oasis:names:tc:xacml:1.0:function:boolean-bag-size',
120        'urn:oasis:names:tc:xacml:1.0:function:boolean-is-in',
121        'urn:oasis:names:tc:xacml:1.0:function:boolean-bag',
122        'urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only',
123        'urn:oasis:names:tc:xacml:1.0:function:integer-bag-size',
124        'urn:oasis:names:tc:xacml:1.0:function:integer-is-in',
125        'urn:oasis:names:tc:xacml:1.0:function:integer-bag',
126        'urn:oasis:names:tc:xacml:1.0:function:double-one-and-only',
127        'urn:oasis:names:tc:xacml:1.0:function:double-bag-size',
128        'urn:oasis:names:tc:xacml:1.0:function:double-is-in',
129        'urn:oasis:names:tc:xacml:1.0:function:double-bag',
130        'urn:oasis:names:tc:xacml:1.0:function:time-one-and-only',
131        'urn:oasis:names:tc:xacml:1.0:function:time-bag-size',
132        'urn:oasis:names:tc:xacml:1.0:function:time-is-in',
133        'urn:oasis:names:tc:xacml:1.0:function:time-bag',
134        'urn:oasis:names:tc:xacml:1.0:function:date-one-and-only',
135        'urn:oasis:names:tc:xacml:1.0:function:date-bag-size',
136        'urn:oasis:names:tc:xacml:1.0:function:date-is-in',
137        'urn:oasis:names:tc:xacml:1.0:function:date-bag',
138        'urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only',
139        'urn:oasis:names:tc:xacml:1.0:function:dateTime-bag-size',
140        'urn:oasis:names:tc:xacml:1.0:function:dateTime-is-in',
141        'urn:oasis:names:tc:xacml:1.0:function:dateTime-bag',
142        'urn:oasis:names:tc:xacml:1.0:function:anyURI-one-and-only',
143        'urn:oasis:names:tc:xacml:1.0:function:anyURI-bag-size',
144        'urn:oasis:names:tc:xacml:1.0:function:anyURI-is-in',
145        'urn:oasis:names:tc:xacml:1.0:function:anyURI-bag',
146        'urn:oasis:names:tc:xacml:1.0:function:hexBinary-one-and-only',
147        'urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag-size',
148        'urn:oasis:names:tc:xacml:1.0:function:hexBinary-is-in',
149        'urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag',
150        'urn:oasis:names:tc:xacml:1.0:function:base64Binary-one-and-only',
151        'urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag-size',
152        'urn:oasis:names:tc:xacml:1.0:function:base64Binary-is-in',
153        'urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag',
154        'urn:oasis:names:tc:xacml:1.0:function:dayTimeDuration-one-and-only',
155        'urn:oasis:names:tc:xacml:1.0:function:dayTimeDuration-bag-size',
156        'urn:oasis:names:tc:xacml:1.0:function:dayTimeDuration-is-in',
157        'urn:oasis:names:tc:xacml:1.0:function:dayTimeDuration-bag',
158        'urn:oasis:names:tc:xacml:1.0:function:yearMonthDuration-one-and-only',
159        'urn:oasis:names:tc:xacml:1.0:function:yearMonthDuration-bag-size',
160        'urn:oasis:names:tc:xacml:1.0:function:yearMonthDuration-is-in',
161        'urn:oasis:names:tc:xacml:1.0:function:yearMonthDuration-bag',
162        'urn:oasis:names:tc:xacml:1.0:function:x500Name-one-and-only',
163        'urn:oasis:names:tc:xacml:1.0:function:x500Name-bag-size',
164        'urn:oasis:names:tc:xacml:1.0:function:x500Name-is-in',
165        'urn:oasis:names:tc:xacml:1.0:function:x500Name-bag',
166        'urn:oasis:names:tc:xacml:1.0:function:rfc822Name-one-and-only',
167        'urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag-size',
168        'urn:oasis:names:tc:xacml:1.0:function:rfc822Name-is-in',
169        'urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag',
170        'urn:oasis:names:tc:xacml:2.0:function:string-concatenate',
171        'urn:oasis:names:tc:xacml:2.0:function:uri-string-concatenate',
172        'urn:oasis:names:tc:xacml:1.0:function:any-of',
173        'urn:oasis:names:tc:xacml:1.0:function:all-of',
174        'urn:oasis:names:tc:xacml:1.0:function:any-of-any',
175        'urn:oasis:names:tc:xacml:1.0:function:all-of-any',
176        'urn:oasis:names:tc:xacml:1.0:function:any-of-all',
177        'urn:oasis:names:tc:xacml:1.0:function:all-of-all',
178        'urn:oasis:names:tc:xacml:1.0:function:map',
179        'urn:oasis:names:tc:xacml:1.0:function:x500Name-match',
180        'urn:oasis:names:tc:xacml:1.0:function:rfc822Name-match',
181        'urn:oasis:names:tc:xacml:1.0:function:string-regexp-match',
182        'urn:oasis:names:tc:xacml:2.0:function:anyURI-regexp-match',
183        'urn:oasis:names:tc:xacml:2.0:function:ipAddress-regexp-match',
184        'urn:oasis:names:tc:xacml:2.0:function:dnsName-regexp-match',
185        'urn:oasis:names:tc:xacml:2.0:function:rfc822Name-regexp-match',
186        'urn:oasis:names:tc:xacml:2.0:function:x500Name-regexp-match',
187        'urn:oasis:names:tc:xacml:1.0:function:xpath-node-count',
188        'urn:oasis:names:tc:xacml:1.0:function:xpath-node-equal',
189        'urn:oasis:names:tc:xacml:1.0:function:xpath-node-match',
190        'urn:oasis:names:tc:xacml:1.0:function:string-intersection',
191        'urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of',
192        'urn:oasis:names:tc:xacml:1.0:function:string-union',
193        'urn:oasis:names:tc:xacml:1.0:function:string-subset',
194        'urn:oasis:names:tc:xacml:1.0:function:string-set-equals',
195        'urn:oasis:names:tc:xacml:1.0:function:boolean-intersection',
196        'urn:oasis:names:tc:xacml:1.0:function:boolean-at-least-one-member-of',
197        'urn:oasis:names:tc:xacml:1.0:function:boolean-union',
198        'urn:oasis:names:tc:xacml:1.0:function:boolean-subset',
199        'urn:oasis:names:tc:xacml:1.0:function:boolean-set-equals',
200        'urn:oasis:names:tc:xacml:1.0:function:integer-intersection',
201        'urn:oasis:names:tc:xacml:1.0:function:integer-at-least-one-member-of',
202        'urn:oasis:names:tc:xacml:1.0:function:integer-union',
203        'urn:oasis:names:tc:xacml:1.0:function:integer-subset',
204        'urn:oasis:names:tc:xacml:1.0:function:integer-set-equals',
205        'urn:oasis:names:tc:xacml:1.0:function:double-intersection',
206        'urn:oasis:names:tc:xacml:1.0:function:double-at-least-one-member-of',
207        'urn:oasis:names:tc:xacml:1.0:function:double-union',
208        'urn:oasis:names:tc:xacml:1.0:function:double-subset',
209        'urn:oasis:names:tc:xacml:1.0:function:double-set-equals',
210        'urn:oasis:names:tc:xacml:1.0:function:time-intersection',
211        'urn:oasis:names:tc:xacml:1.0:function:time-at-least-one-member-of',
212        'urn:oasis:names:tc:xacml:1.0:function:time-union',
213        'urn:oasis:names:tc:xacml:1.0:function:time-subset',
214        'urn:oasis:names:tc:xacml:1.0:function:time-set-equals',
215        'urn:oasis:names:tc:xacml:1.0:function:date-intersection',
216        'urn:oasis:names:tc:xacml:1.0:function:date-at-least-one-member-of',
217        'urn:oasis:names:tc:xacml:1.0:function:date-union',
218        'urn:oasis:names:tc:xacml:1.0:function:date-subset',
219        'urn:oasis:names:tc:xacml:1.0:function:date-set-equals',
220        'urn:oasis:names:tc:xacml:1.0:function:dateTime-intersection',
221        'urn:oasis:names:tc:xacml:1.0:function:dateTime-at-least-one-member-of',
222        'urn:oasis:names:tc:xacml:1.0:function:dateTime-union',
223        'urn:oasis:names:tc:xacml:1.0:function:dateTime-subset',
224        'urn:oasis:names:tc:xacml:1.0:function:dateTime-set-equals',
225        'urn:oasis:names:tc:xacml:1.0:function:anyURI-intersection',
226        'urn:oasis:names:tc:xacml:1.0:function:anyURI-at-least-one-member-of',
227        'urn:oasis:names:tc:xacml:1.0:function:anyURI-union',
228        'urn:oasis:names:tc:xacml:1.0:function:anyURI-subset',
229        'urn:oasis:names:tc:xacml:1.0:function:anyURI-set-equals',
230        'urn:oasis:names:tc:xacml:1.0:function:hexBinary-intersection',
231        'urn:oasis:names:tc:xacml:1.0:function:hexBinary-at-least-one-member-of',
232        'urn:oasis:names:tc:xacml:1.0:function:hexBinary-union',
233        'urn:oasis:names:tc:xacml:1.0:function:hexBinary-subset',
234        'urn:oasis:names:tc:xacml:1.0:function:hexBinary-set-equals',
235        'urn:oasis:names:tc:xacml:1.0:function:base64Binary-intersection',
236        'urn:oasis:names:tc:xacml:1.0:function:base64Binary-at-least-one-member-of',
237        'urn:oasis:names:tc:xacml:1.0:function:base64Binary-union',
238        'urn:oasis:names:tc:xacml:1.0:function:base64Binary-subset',
239        'urn:oasis:names:tc:xacml:1.0:function:base64Binary-set-equals',
240        'urn:oasis:names:tc:xacml:1.0:function:dayTimeDuration-intersection',
241        'urn:oasis:names:tc:xacml:1.0:function:dayTimeDuration-at-least-one-member-of',
242        'urn:oasis:names:tc:xacml:1.0:function:dayTimeDuration-union',
243        'urn:oasis:names:tc:xacml:1.0:function:dayTimeDuration-subset',
244        'urn:oasis:names:tc:xacml:1.0:function:dayTimeDuration-set-equals',
245        'urn:oasis:names:tc:xacml:1.0:function:yearMonthDuration-intersection',
246        'urn:oasis:names:tc:xacml:1.0:function:yearMonthDuration-at-least-one-member-of',
247        'urn:oasis:names:tc:xacml:1.0:function:yearMonthDuration-union',
248        'urn:oasis:names:tc:xacml:1.0:function:yearMonthDuration-subset',
249        'urn:oasis:names:tc:xacml:1.0:function:yearMonthDuration-set-equals',
250        'urn:oasis:names:tc:xacml:1.0:function:x500Name-intersection',
251        'urn:oasis:names:tc:xacml:1.0:function:x500Name-at-least-one-member-of',
252        'urn:oasis:names:tc:xacml:1.0:function:x500Name-union',
253        'urn:oasis:names:tc:xacml:1.0:function:x500Name-subset',
254        'urn:oasis:names:tc:xacml:1.0:function:x500Name-set-equals',
255        'urn:oasis:names:tc:xacml:1.0:function:rfc822Name-intersection',
256        'urn:oasis:names:tc:xacml:1.0:function:rfc822Name-at-least-one-member-of',
257        'urn:oasis:names:tc:xacml:1.0:function:rfc822Name-union',
258        'urn:oasis:names:tc:xacml:1.0:function:rfc822Name-subset',
259        'urn:oasis:names:tc:xacml:1.0:function:rfc822Name-set-equals',
260    )
261
262
263class ClassFactoryInterface(object):
264    """Interface class for function module class factory class
265    """
266    __meta__ = ABCMeta
267   
268    @abstractmethod
269    def __call__(self, identifier):
270        '''Create class for the given XACML function identifier
271       
272        @param identifier: XACML *-at-least-one-member-of type function
273        identifier
274        @type identifier: basestring
275        @return: at least one member of class corresponding to the given input
276        identifier
277        @rtype: AtLeastOneMemberOfBase derived type or None if no match is
278        found
279        '''
280        return None
281   
282
283class FunctionClassFactoryBase(ClassFactoryInterface):
284    """Base implementation for XACML Function Class Factory.  Derived types
285    should be implemented in sub-modules of ndg.xacml.core.functions e.g.
286    for urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of a
287    class factory should exist,
288   
289    ndg.xacml.core.functions.v1.at_least_one_member_of.FunctionClassFactory
290   
291    which
292    StringAtLeastOneMemberOf   
293   
294    Derived classes MUST define these two class variables:
295   
296    @cvar FUNCTION_NS_SUFFIX: urn suffix for the family of function to define
297    e.g. -at-least-one-member-of is the suffix for the URN:
298   
299    urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of
300    @type FUNCTION_NS_SUFFIX: NoneType (but basestring in derived class)
301   
302    @cvar FUNCTION_BASE_CLASS: base class for this family of functions e.g for
303    urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of,
304    ndg.xacml.core.functions.v1.at_least_one_member_of.AtLeastOneMemberOfBase
305    @type FUNCTION_BASE_CLASS: NoneType (but AbstractFunction derived type in
306    derived function facotry class)
307    """
308   
309   
310    FUNCTION_NS_SUFFIX = None
311    FUNCTION_BASE_CLASS = None
312   
313    URN_SEP = ':'
314    FUNCTION_NAME_SEP = '-'
315
316    def __init__(self):
317        """Create classes for each <type>-at-least-one-member-of function and
318        place in a look-up table
319        """
320        if None in (self.__class__.FUNCTION_NS_SUFFIX, 
321                    self.__class__.FUNCTION_BASE_CLASS):
322            raise TypeError('"FUNCTION_NS_SUFFIX" and "FUNCTION_BASE_CLASS" '
323                            'must be defined in a derived implementation of '
324                            'this class.  See this classes __doc__ contents')
325           
326        self.__map = {}
327        functionSuffixParts = self.__class__.FUNCTION_NS_SUFFIX.split(
328                                            self.__class__.FUNCTION_NAME_SEP)
329        functionSuffix = ''.join([n[0].upper() + n[1:] 
330                                  for n in functionSuffixParts if n])
331       
332        functionNames = [n for n in XacmlFunctionNames.FUNCTION_NAMES
333                         if n.endswith(self.__class__.FUNCTION_NS_SUFFIX)]
334       
335        for identifier in functionNames:
336            # Extract the function name and the type portion of the function
337            # name in order to make an implementation of a class to handle it
338            functionName = identifier.split(self.__class__.URN_SEP)[-1]
339            typePart = functionName.split(self.__class__.FUNCTION_NAME_SEP)[0]
340           
341            typeName = typePart[0].upper() + typePart[1:]
342            _type = AttributeValue.TYPE_MAP.get(typeName)
343            if _type is None:
344                raise TypeError('No AttributeValue.TYPE_MAP entry for %r type' %
345                                typeName)
346             
347            className = typeName + functionSuffix
348            classVars = {
349                'TYPE': _type,
350                'FUNCTION_NS': identifier
351            }
352           
353            functionClass = type(className, 
354                                 (self.__class__.FUNCTION_BASE_CLASS, ), 
355                                 classVars)
356           
357            self.__map[identifier] = functionClass
358           
359    def __call__(self, identifier):
360        """Return the class for the given XACML *-at-least-one-member-of type
361        function identifier
362        @param identifier: XACML *-at-least-one-member-of type function
363        identifier
364        @type identifier: basestring
365        @return: at least one member of class corresponding to the given input
366        identifier
367        @rtype: AtLeastOneMemberOfBase derived type or None if no match is
368        found
369        """
370        return self.__map.get(identifier)
371       
372   
373class FunctionMapError(Exception):
374    """Generic Error exception class for FunctionMap"""
375   
376   
377class FunctionMapConfigError(FunctionMapError):
378    """Configuration related exception for FunctionMap"""
379       
380       
381class FunctionMap(VettedDict):
382    """Map function IDs to their implementations"""
383    FUNCTION_PKG_PREFIX = 'ndg.xacml.core.functions.'
384   
385    V1_0_PKG_PREFIX = FUNCTION_PKG_PREFIX + 'v1.'
386    V2_0_PKG_PREFIX = FUNCTION_PKG_PREFIX + 'v2.'
387   
388    SUPPORTED_NSS = {
389        AbstractFunction.V1_0_FUNCTION_NS: V1_0_PKG_PREFIX,
390        AbstractFunction.V2_0_FUNCTION_NS: V2_0_PKG_PREFIX
391    }
392   
393    # Each function module is expected to have a class factory for obtaining
394    # a class for the given function identifier associated with that module
395    FUNCTION_CLASS_FACTORY_CLASSNAME = 'FunctionClassFactory'
396   
397    def __init__(self):
398        """Force function entries to derive from AbstractFunction and IDs to
399        be string type
400        """       
401        # Filters are defined as staticmethods but reference via self here to
402        # enable derived class to override them as standard methods without
403        # needing to redefine this __init__ method           
404        super(FunctionMap, self).__init__(self.keyFilter, self.valueFilter)
405       
406    @staticmethod
407    def keyFilter(key):
408        """Enforce string type keys"""
409        if not isinstance(key, basestring):
410            raise TypeError('Expecting %r type for key; got %r' % 
411                            (basestring, type(key))) 
412           
413        return True 
414   
415    @staticmethod
416    def valueFilter(value):
417        """Enforce AbstractFunction derived types for match functions"""
418        if value is NotImplemented:
419            return True
420       
421        elif not issubclass(value, AbstractFunction):
422            raise TypeError('Expecting %r derived type for value; got %r' % 
423                            (AbstractFunction, value)) 
424           
425        return True 
426           
427    def load(self):
428        """Load function map with implementations from the relevant function
429        package"""
430       
431        for functionNs in XacmlFunctionNames.FUNCTION_NAMES:
432            self._loadFunction(functionNs)
433           
434    @classmethod
435    def withLoadedMap(cls):
436        """Return a pre-loaded map"""
437        functionMap = cls()
438        functionMap.load()
439        return functionMap
440           
441    def _loadFunction(self, functionNs):
442        """Get package to retrieve function class from for given namespace
443        """
444        cls = FunctionMap
445        classPath = None
446       
447        if functionNs == "urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of":
448            pass
449#        else:
450#            self[functionNs] = NotImplemented
451#            return
452
453        for namespacePrefix, pkgNamePrefix in cls.SUPPORTED_NSS.items():
454            if functionNs.startswith(namespacePrefix):
455                # Namespace is recognised - translate into a path to a function
456                # class in the right functions package
457                functionName = functionNs.split(namespacePrefix)[-1]
458                functionNameParts = functionName.split('-')
459               
460                if len(functionNameParts) == 1:
461                    moduleName = functionNameParts[0]
462                else:
463                    moduleName = '_'.join(functionNameParts[1:]).lower()
464                   
465                classPath = pkgNamePrefix + moduleName + '.' + \
466                            cls.FUNCTION_CLASS_FACTORY_CLASSNAME
467                break
468
469        if classPath is None:
470            raise FunctionMapConfigError('Namespace for function not '
471                                         'recognised: %r' % functionNs) 
472                       
473        # Try instantiating the function class and loading it into the
474        # map
475        try:
476            functionFactory = callModuleObject(classPath)
477           
478        except (ImportError, AttributeError):
479            log.error("Error importing function factory class %r for function "
480                      "identifier %r: %s", classPath, functionNs, 
481                      traceback.format_exc())
482           
483            # No implementation exists - default to Abstract function
484            self[functionNs] = NotImplemented
485           
486        self[functionNs] = functionFactory(functionNs)
487           
488
489
490       
Note: See TracBrowser for help on using the repository browser.