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

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

Completed moving of matching and rule evaluation code out of the PDP class and into the Target, Match, Apply, AttributeDesignator? and Condition classes. Policy evaluation is now working apart from the rule combining algorithm.

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    IDENTIFIER = None
24    TYPE_MAP = {
25        'String': basestring,
26        'AnyURI': basestring,
27        'Integer': int,
28        'Boolean': bool,
29        'Double': float,
30        'Date': datetime,
31        'DateTime': datetime,
32        'Time': datetime,
33        'DayTimeDuration': timedelta,
34        'YearMonthDuration': timedelta,
35        'X500Name': basestring,
36        'Rfc822Name': basestring,
37        'HexBinary': int,
38        'Base64Binary': NotImplemented,
39        'IpAddress': basestring,
40        'DnsName': basestring
41    }
42    TYPE = None
43   
44    __slots__ = ('__value',) 
45   
46    def __init__(self):
47        super(AttributeValue, self).__init__()
48        if self.__class__.TYPE is None:
49            raise TypeError('TYPE class variable must be set to a valid type '
50                            'in a derived class')
51           
52        self.__value = None
53       
54        # Allow derived classes to make an implicit data type setting
55        self.dataType = self.__class__.IDENTIFIER
56
57    def __repr__(self):
58        return "%s = %r " % (super(AttributeValue, self).__repr__(),
59                             self.__value)
60   
61    def _get_value(self):
62        return self.__value
63
64    def _set_value(self, value):
65        if not isinstance(value, self.__class__.TYPE):
66            raise TypeError('Expecting %r type for "value" '
67                            'attribute; got %r' % (self.__class__.TYPE, 
68                                                   type(value)))
69           
70        self.__value = value 
71
72    value = property(_get_value, _set_value, None, "expression value") 
73   
74    def evaluate(self, context):
75        """Evaluate the result of the expression in a condition.  In the case of
76        an attribute value it's simply itself
77       
78        @param context: the request context
79        @type context: ndg.xacml.core.context.request.Request
80        @return: this attribute value
81        @rtype: AttributeValue 
82        """ 
83        return self
84
85
86class AttributeValueClassMap(VettedDict):
87    """Specialised dictionary to hold mappings of XML attribute type URIs to
88    their equivalent classes
89    """
90   
91    def __init__(self):
92        """Force entries to derive from AttributeValue and IDs to
93        be string type
94        """       
95        # Filters are defined as staticmethods but reference via self here to
96        # enable derived class to override them as standard methods without
97        # needing to redefine this __init__ method           
98        super(AttributeValueClassMap, self).__init__(self.keyFilter, 
99                                                     self.valueFilter)
100       
101    @staticmethod
102    def keyFilter(key):
103        """Enforce string type keys"""
104        if not isinstance(key, basestring):
105            raise TypeError('Expecting %r type for key; got %r' % 
106                            (basestring, type(key))) 
107        return True 
108   
109    @staticmethod
110    def valueFilter(value):
111        """Enforce AttributeValue derived types for values"""
112
113        if not issubclass(value, AttributeValue):
114            raise TypeError('Expecting %r derived type for value; got %r' % 
115                            (AttributeValue, type(value))) 
116        return True 
117
118
119# Dynamically Create classes based on AttributeValue for all the XACML primitive
120# types
121_IDENTIFIER2CLASS_MAP = AttributeValueClassMap()
122
123for typeName, _type in AttributeValue.TYPE_MAP.items():
124    identifier = AttributeValue.IDENTIFIER_PREFIX + typeName[0
125                                                        ].lower() + typeName[1:]
126
127    className = typeName + AttributeValue.CLASS_NAME_SUFFIX               
128    classVars = {'TYPE': _type, 'IDENTIFIER': identifier}
129   
130    attributeValueClass = type(className, (AttributeValue, ), classVars)
131    AttributeValue.register(attributeValueClass)
132    _IDENTIFIER2CLASS_MAP[identifier] = attributeValueClass
133   
134   
135class AttributeValueClassFactory(object):
136    """Create AttributeValue types based on the XML namespace identifier
137   
138    Convenience wrapper for _IDENTIFIER2CLASS_MAP instance of
139    AttributeValueClassMap
140    """
141    def __init__(self, classMap=None):
142        if classMap is None:
143            self.__classMap = _IDENTIFIER2CLASS_MAP
144        elif isinstance(classMap, AttributeValueClassMap):
145            self.__classMap = classMap
146        else:
147            raise TypeError('Expecting %r derived type for "map" input; got %r'
148                            % (AttributeValueClassMap, type(map)))
149           
150    def __call__(self, identifier):
151        """Return <type>AttributeValue class for given identifier URI or None
152        if no match is found
153        """
154        return self.__classMap.get(identifier)
155       
Note: See TracBrowser for help on using the repository browser.