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

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg-security/TI12-security/trunk/NDG_XACML/ndg/xacml/core/functions/__init__.py@6803
Revision 6803, 24.3 KB checked in by pjkersha, 11 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.