source: TI12-security/trunk/NDG_XACML/ndg/xacml/core/attributevalue.py @ 7072

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

Incomplete - task 2: XACML-Security Integration

  • Major cleanup of function factories for efficiency. Only the required factories and function classes are loaded and any loaded classes are cached for future calls. All unit tests pass.
  • Property svn:keywords set to Id
Line 
1"""NDG XACML attribute type definition
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "25/02/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 datetime import datetime, timedelta
13
14from ndg.xacml.utils import VettedDict
15from ndg.xacml.core.expression import Expression
16   
17
18class AttributeValue(Expression):
19    """XACML Attribute Value type"""
20    ELEMENT_LOCAL_NAME = 'AttributeValue'
21    CLASS_NAME_SUFFIX = 'AttributeValue'
22    IDENTIFIER_PREFIX = 'http://www.w3.org/2001/XMLSchema#'
23 
24    IDENTIFIER = None
25    TYPE_URIS = (
26    'http://www.w3.org/2001/XMLSchema#string',
27    'http://www.w3.org/2001/XMLSchema#anyURI',
28    'http://www.w3.org/2001/XMLSchema#integer',
29    'http://www.w3.org/2001/XMLSchema#boolean',
30    'http://www.w3.org/2001/XMLSchema#double',
31    'http://www.w3.org/2001/XMLSchema#date',
32    'http://www.w3.org/2001/XMLSchema#dateTime',
33    'http://www.w3.org/2001/XMLSchema#time',
34    'http://www.w3.org/TR/2002/WD-xquery-operators-20020816#dayTimeDuration',
35    'http://www.w3.org/TR/2002/WD-xquery-operators-20020816#yearMonthDuration',
36    'urn:oasis:names:tc:xacml:1.0:data-type:x500Name',
37    'urn:oasis:names:tc:xacml:1.0:data-type:rfc822Name',
38    'http://www.w3.org/2001/XMLSchema#hexBinary',
39    'http://www.w3.org/2001/XMLSchema#base64Binary',
40    'urn:oasis:names:tc:xacml:2.0:data-type:ipAddress',
41    'urn:oasis:names:tc:xacml:2.0:data-type:dnsName'
42    )
43    TYPE_NAMES = (
44        'String',
45        'AnyURI',
46        'Integer',
47        'Boolean',
48        'Double',
49        'Date',
50        'DateTime',
51        'Time',
52        'DayTimeDuration',
53        'YearMonthDuration',
54        'X500Name',
55        'Rfc822Name',
56        'HexBinary',
57        'Base64Binary',
58        'IpAddress',
59        'DnsName',
60    )
61    NATIVE_TYPES = (
62        basestring,
63        basestring,
64        int,
65        bool,
66        float,
67        datetime,
68        datetime,
69        datetime,
70        timedelta,
71        timedelta,
72        basestring,
73        basestring,
74        int,
75        NotImplemented,
76        basestring,
77        basestring
78    )
79    TYPE_MAP = dict(zip(TYPE_NAMES, NATIVE_TYPES))
80    TYPE_URI_MAP = dict(zip(TYPE_NAMES, TYPE_URIS))
81    TYPE = None
82   
83    __slots__ = ('__value',) 
84   
85    def __init__(self):
86        super(AttributeValue, self).__init__()
87        if self.__class__.TYPE is None:
88            raise TypeError('TYPE class variable must be set to a valid type '
89                            'in a derived class')
90           
91        self.__value = None
92       
93        # Allow derived classes to make an implicit data type setting
94        self.dataType = self.__class__.IDENTIFIER
95
96    def __repr__(self):
97        return "%s = %r " % (super(AttributeValue, self).__repr__(),
98                             self.__value)
99   
100    def _get_value(self):
101        return self.__value
102
103    def _set_value(self, value):
104        if not isinstance(value, self.__class__.TYPE):
105            raise TypeError('Expecting %r type for "value" '
106                            'attribute; got %r' % (self.__class__.TYPE, 
107                                                   type(value)))
108           
109        self.__value = value 
110
111    value = property(_get_value, _set_value, None, "expression value") 
112   
113    def evaluate(self, context):
114        """Evaluate the result of the expression in a condition.  In the case of
115        an attribute value it's simply itself
116       
117        @param context: the request context
118        @type context: ndg.xacml.core.context.request.Request
119        @return: this attribute value
120        @rtype: AttributeValue 
121        """ 
122        return self
123
124
125class AttributeValueClassMap(VettedDict):
126    """Specialised dictionary to hold mappings of XML attribute type URIs to
127    their equivalent classes
128    """
129   
130    def __init__(self):
131        """Force entries to derive from AttributeValue and IDs to
132        be string type
133        """       
134        # Filters are defined as staticmethods but reference via self here to
135        # enable derived class to override them as standard methods without
136        # needing to redefine this __init__ method           
137        VettedDict.__init__(self, self.keyFilter, self.valueFilter)
138       
139    @staticmethod
140    def keyFilter(key):
141        """Enforce string type keys"""
142        if not isinstance(key, basestring):
143            raise TypeError('Expecting %r type for key; got %r' % 
144                            (basestring, type(key))) 
145        return True 
146   
147    @staticmethod
148    def valueFilter(value):
149        """Enforce AttributeValue derived types for values"""
150
151        if not issubclass(value, AttributeValue):
152            raise TypeError('Expecting %r derived type for value; got %r' % 
153                            (AttributeValue, type(value))) 
154        return True 
155
156
157# Dynamically Create classes based on AttributeValue for all the XACML primitive
158# types
159_IDENTIFIER2CLASS_MAP = AttributeValueClassMap()
160
161for typeName, _type in AttributeValue.TYPE_MAP.items():
162    identifier = AttributeValue.TYPE_URI_MAP[typeName]
163
164    className = typeName + AttributeValue.CLASS_NAME_SUFFIX               
165    classVars = {'TYPE': _type, 'IDENTIFIER': identifier}
166   
167    attributeValueClass = type(className, (AttributeValue, ), classVars)
168    AttributeValue.register(attributeValueClass)
169    _IDENTIFIER2CLASS_MAP[identifier] = attributeValueClass
170   
171   
172class AttributeValueClassFactory(object):
173    """Create AttributeValue types based on the XML namespace identifier
174   
175    Convenience wrapper for _IDENTIFIER2CLASS_MAP instance of
176    AttributeValueClassMap
177    """
178    def __init__(self, classMap=None):
179        if classMap is None:
180            self.__classMap = _IDENTIFIER2CLASS_MAP
181        elif isinstance(classMap, AttributeValueClassMap):
182            self.__classMap = classMap
183        else:
184            raise TypeError('Expecting %r derived type for "map" input; got %r'
185                            % (AttributeValueClassMap, type(map)))
186           
187    def __call__(self, identifier):
188        """Return <type>AttributeValue class for given identifier URI or None
189        if no match is found
190        """
191        return self.__classMap.get(identifier)
192       
Note: See TracBrowser for help on using the repository browser.