Changeset 7072
- Timestamp:
- 24/06/10 14:30:12 (11 years ago)
- Location:
- TI12-security/trunk/NDG_XACML/ndg/xacml
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/NDG_XACML/ndg/xacml/core/apply.py
r7064 r7072 34 34 self.__functionId = None 35 35 self.__function = None 36 self.__functionMap = FunctionMap .withLoadedMap()36 self.__functionMap = FunctionMap() 37 37 self.__loadFunctionFromId = True 38 38 self.__expressions = TypedList(Expression) -
TI12-security/trunk/NDG_XACML/ndg/xacml/core/attributevalue.py
r7064 r7072 135 135 # enable derived class to override them as standard methods without 136 136 # needing to redefine this __init__ method 137 super(AttributeValueClassMap, self).__init__(self.keyFilter, 138 self.valueFilter) 137 VettedDict.__init__(self, self.keyFilter, self.valueFilter) 139 138 140 139 @staticmethod -
TI12-security/trunk/NDG_XACML/ndg/xacml/core/context/handler.py
r7064 r7072 11 11 __revision__ = "$Id$" 12 12 from abc import ABCMeta, abstractmethod 13 from ndg.xacml.core.context.pdpinterface import PDPInterface14 13 15 14 … … 18 17 __metaclass__ = ABCMeta 19 18 __slots__ = () 20 21 @classmethod22 def __subclasshook__(cls, C):23 """Derived class must implement __call__"""24 if cls is PEPInterface:25 if any("handlePEPRequest" in B.__dict__ for B in C.__mro__):26 return True27 19 28 return NotImplemented29 30 20 @abstractmethod 31 21 def handlePEPRequest(self, pepRequest): … … 46 36 __slots__ = () 47 37 48 def p epQuery(self, request, designator):38 def pipQuery(self, request, designator): 49 39 """Query a Policy Information Point to retrieve the attribute values 50 40 corresponding to the specified input designator. Optionally, update the -
TI12-security/trunk/NDG_XACML/ndg/xacml/core/functions/__init__.py
r7064 r7072 282 282 283 283 class FunctionClassFactoryBase(FunctionClassFactoryInterface): 284 """Base implementation for XACML Function Class Factory. Derived types 285 should be implemented in sub-modules of ndg.xacml.core.functions 284 """Base implementation for XACML Function Class Factory. There should be 285 one derived type for each function family implemented in sub-modules of 286 ndg.xacml.core.functions 286 287 287 288 e.g. 288 289 289 for urn:oasis:names:tc:xacml:1.0:function: string-at-least-one-member-of a290 for urn:oasis:names:tc:xacml:1.0:function:<type>-at-least-one-member-of a 290 291 class factory should exist, 291 292 292 293 ndg.xacml.core.functions.v1.at_least_one_member_of.FunctionClassFactory 293 294 294 which will be capable of returning an AbstractFunction derived type: 295 296 StringAtLeastOneMemberOf 295 which will be capable of returning a type derived from AbstractFunction: 296 297 <type>AtLeastOneMemberOf 298 299 e.g. StringAtLeastOneMemberOf, BooleanAtLeastOneMemberOf. 297 300 298 301 This class is for convenience only some function factories are better … … 318 321 ndg.xacml.core.functions.v1.at_least_one_member_of.AtLeastOneMemberOfBase 319 322 @type FUNCTION_BASE_CLASS: NoneType (but AbstractFunction derived type in 320 derived function fac otry class)323 derived function factory class) 321 324 """ 322 325 … … 327 330 URN_SEP = ':' 328 331 FUNCTION_NAME_SEP = '-' 329 332 __slots__ = ('__map', 'attributeValueClassFactory', 'functionSuffix') 333 330 334 def __init__(self): 331 """Create classes for each <type>-at-least-one-member-of function and332 place in a look-up table333 """335 '''This class is in fact abstract - derived types must define the 336 FUNCTION_NS_SUFFIX and FUNCTION_BASE_CLASS class variables 337 ''' 334 338 if None in (self.__class__.FUNCTION_NS_SUFFIX, 335 339 self.__class__.FUNCTION_BASE_CLASS): … … 343 347 'iterable of string type function identifiers; got ' 344 348 '%r' % self.__class__.FUNCTION_NAMES) 345 346 self.__map = {} 349 350 self.__map = {} 351 352 # Enables creation of matching attribute types to relevant to the 353 # function classes 354 self.attributeValueClassFactory = AttributeValueClassFactory() 355 356 347 357 functionSuffixParts = self.__class__.FUNCTION_NS_SUFFIX.split( 348 358 self.__class__.FUNCTION_NAME_SEP) 349 functionSuffix = ''.join([n[0].upper() + n[1:]359 self.functionSuffix = ''.join([n[0].upper() + n[1:] 350 360 for n in functionSuffixParts if n]) 351 361 352 attributeValueClassFactory = AttributeValueClassFactory() 353 354 for identifier in self.__class__.FUNCTION_NAMES: 355 # Extract the function name and the type portion of the function 356 # name in order to make an implementation of a class to handle it 357 functionName = identifier.split(self.__class__.URN_SEP)[-1] 358 if functionName == 'xpath-node-match': 359 pass 360 typePart = functionName.split(self.__class__.FUNCTION_NS_SUFFIX)[0] 361 362 # Attempt to infer from the function name the associated type 363 typeName = typePart[0].upper() + typePart[1:] 364 365 # Remove any hyphens converting to camel case 366 if '-' in typeName: 367 typeName = ''.join([i[0].upper() + i[1:] 368 for i in typeName.split('-')]) 369 370 typeURI = AttributeValue.TYPE_URI_MAP.get(typeName) 371 if typeURI is None: 372 # Ugly hack to allow for XPath node functions 373 if typePart == 'xpath-node': 374 typeURI = AttributeValue.TYPE_URI_MAP['String'] 375 else: 376 raise TypeError('No AttributeValue.TYPE_URI_MAP entry for ' 377 '%r type' % typePart) 378 379 _type = attributeValueClassFactory(typeURI) 380 if _type is None: 381 raise TypeError('No AttributeValue.TYPE_MAP entry for %r type' % 382 typeName) 383 384 className = typeName + functionSuffix 385 classVars = { 386 'TYPE': _type, 387 'FUNCTION_NS': identifier 388 } 389 390 functionClass = type(className, 391 (self.__class__.FUNCTION_BASE_CLASS, ), 392 classVars) 393 394 self.__map[identifier] = functionClass 362 def initAllFunctionClasses(self): 363 """Create classes for all functions for a data type e.g. a derived class 364 could implement a factory for <type>-at-least-one-member-of functions: 365 string-at-least-one-member-of, boolean-at-least-one-member-of, etc. 366 367 Function classes are placed in a look-up table __map for the __call__() 368 method to access 369 370 In practice, there shouldn't be a need to load all the functions in 371 one go. The __call__ method loads functions and caches them as needed. 372 """ 373 for identifier in self.__class__.FUNCTION_NAMES: 374 self.loadFunction(identifier) 375 376 def loadFunction(self, identifier): 377 """Create a class for the given function namespace and cache it in the 378 function class look-up table for future requests. Note that this call 379 overwrites any existing entry in the cache whereas __call__ will try 380 to use an entry in the cache if it already exists 381 382 @param identifier: XACML function namespace 383 @type identifier: basestring 384 """ 385 386 # str.capitalize doesn't do what's required: need to capitalize the 387 # first letter of the word BUT retain camel case for the rest of it 388 _capitalize = lambda s: s[0].upper() + s[1:] 389 390 # Extract the function name and the type portion of the function 391 # name in order to make an implementation of a class to handle it 392 functionName = identifier.split(self.__class__.URN_SEP)[-1] 393 typePart = functionName.split(self.__class__.FUNCTION_NS_SUFFIX)[0] 394 395 # Attempt to infer from the function name the associated type 396 typeName = _capitalize(typePart) 397 398 # Remove any hyphens converting to camel case 399 if '-' in typeName: 400 typeName = ''.join([_capitalize(i) for i in typeName.split('-')]) 401 402 typeURI = AttributeValue.TYPE_URI_MAP.get(typeName) 403 if typeURI is None: 404 # Ugly hack to allow for XPath node functions 405 if typePart == 'xpath-node': 406 typeURI = AttributeValue.TYPE_URI_MAP['String'] 407 else: 408 raise TypeError('No AttributeValue.TYPE_URI_MAP entry for ' 409 '%r type' % typePart) 410 411 _type = self.attributeValueClassFactory(typeURI) 412 if _type is None: 413 raise TypeError('No AttributeValue.TYPE_MAP entry for %r type' % 414 typeName) 415 416 className = typeName + self.functionSuffix 417 classVars = { 418 'TYPE': _type, 419 'FUNCTION_NS': identifier 420 } 421 422 functionClass = type(className, 423 (self.__class__.FUNCTION_BASE_CLASS, ), 424 classVars) 425 426 self.__map[identifier] = functionClass 395 427 396 428 def __call__(self, identifier): … … 405 437 found 406 438 """ 439 # Check the cache first 440 functionClass = self.__map.get(identifier) 441 if functionClass is None: 442 # No class set in the cache - try loading the new class and updating 443 # the cache. 444 self.loadFunction(identifier) 445 446 # This should result in a safe retrieval from the cache because of the 447 # above check - None return would result otherwise. 407 448 return self.__map.get(identifier) 408 449 … … 417 458 418 459 class FunctionMap(VettedDict): 419 """Map function IDs to their implementations""" 460 """Map function IDs to their class implementations in the various function 461 sub-modules. It provide a layer over the various 462 FunctionClassFactoryInterface implementations so that a function class can 463 be obtained directly from a given XACML function URN. 464 """ 420 465 FUNCTION_PKG_PREFIX = 'ndg.xacml.core.functions.' 421 466 … … 433 478 434 479 def __init__(self): 435 """Force function entries to derive from AbstractFunction and IDs to436 bestring type480 """Force type for dictionary key value pairs: function values must be 481 of AbstractFunction derived type and ID keys string type 437 482 """ 438 483 # Filters are defined as staticmethods but reference via self here to 439 484 # enable derived class to override them as standard methods without 440 485 # needing to redefine this __init__ method 441 super(FunctionMap, self).__init__(self.keyFilter, self.valueFilter) 486 VettedDict.__init__(self, self.keyFilter, self.valueFilter) 487 488 # This classes maintains a list of XACML function URN -> Function class 489 # mappings. This additional dict enables caching of class factories 490 # used to obtain the function classes. There is one class factory per 491 # function module e.g. ndg.xacml.core.functions.v1.equal contains a 492 # class factory which creates the various 493 # urn:oasis:names:tc:xacml:1.0:function:<type>-equal function classes 494 self.__classFactoryMap = {} 442 495 443 496 @staticmethod … … 462 515 return True 463 516 464 def load (self):517 def loadAll(self): 465 518 """Load function map with implementations from the relevant function 466 519 package""" 467 520 468 521 for functionNs in XacmlFunctionNames.FUNCTION_NAMES: 469 self._loadFunction(functionNs) 470 471 @classmethod 472 def withLoadedMap(cls): 473 """Return a pre-loaded map""" 474 functionMap = cls() 475 functionMap.load() 476 return functionMap 477 478 def _loadFunction(self, functionNs): 479 """Get package to retrieve function class from for given namespace 522 self.loadFunction(functionNs) 523 524 def loadFunction(self, functionNs): 525 """Get package to retrieve function class for the given XACML function 526 namespace 527 528 @param functionNs: XACML function namespace 529 @type functionNs: basestring 480 530 """ 531 functionFactory = self.__classFactoryMap.get(functionNs) 532 if functionFactory is not None: 533 # Get function class from previously cached factory 534 self[functionNs] = functionFactory(functionNs) 535 return 536 537 # No Factory has been cached for this function yet 481 538 cls = FunctionMap 482 539 classPath = None … … 484 541 for namespacePrefix, pkgNamePrefix in cls.SUPPORTED_NSS.items(): 485 542 if functionNs.startswith(namespacePrefix): 486 # Namespace is recognised - translate into a path to a function487 # class in the right functions package543 # Namespace is recognised - translate into a path to a 544 # function class in the right functions package 488 545 functionName = functionNs.split(namespacePrefix)[-1] 489 546 functionNameParts = functionName.split('-') … … 506 563 'recognised: %r' % functionNs) 507 564 508 # Try instantiating the function class and loading it into the 509 # map 565 # Try instantiating the function class and loading it into the map 510 566 try: 511 567 functionFactory = callModuleObject(classPath) 512 568 513 except (ImportError, AttributeError) :569 except (ImportError, AttributeError), e: 514 570 log.error("Error importing function factory class %r for function " 515 "identifier %r: %s", classPath, functionNs, 516 traceback.format_exc()) 571 "identifier %r: %s", classPath, functionNs, str(e)) 517 572 518 573 # No implementation exists - default to Abstract function … … 520 575 else: 521 576 self[functionNs] = functionFactory(functionNs) 522 523 524 525 526 527 577 self.__classFactoryMap[functionNs] = functionFactory 578 579 def __getitem__(self, key): 580 """Override base class implementation to load and cache function classes 581 if they don't otherwise exist 582 """ 583 functionClass = VettedDict.get(self, key) 584 if functionClass is None: 585 self.loadFunction(key) 586 587 return VettedDict.__getitem__(self, key) 588 589 def get(self, key, *arg): 590 """Likewise to __getitem__, enable loading and caching of function 591 classes if they don't otherwise exist 592 """ 593 functionClass = VettedDict.get(self, key, *arg) 594 if functionClass is None: 595 self.loadFunction(key) 596 return VettedDict.get(self, key, *arg) 597 else: 598 return functionClass 599 600 601 -
TI12-security/trunk/NDG_XACML/ndg/xacml/core/match.py
r7064 r7072 54 54 55 55 self.__function = None 56 self.__functionMap = FunctionMap .withLoadedMap()56 self.__functionMap = FunctionMap() 57 57 self.__loadFunctionFromId = True 58 58 -
TI12-security/trunk/NDG_XACML/ndg/xacml/parsers/etree/factory.py
r7064 r7072 51 51 xacmlTypeName) 52 52 readerClass = importModuleObject(readerClassName) 53 54 log.debug('Returning %r ElementTree based reader for %r type',55 readerClass, xacmlType)56 53 return readerClass 57 54 -
TI12-security/trunk/NDG_XACML/ndg/xacml/test/test_context.py
r7064 r7072 20 20 from ndg.xacml.core.context.pdpinterface import PDPInterface 21 21 from ndg.xacml.core.context.pdp import PDP 22 from ndg.xacml.core.context.handler import AbstractContextHandler22 from ndg.xacml.core.context.handler import CtxHandlerInterface 23 23 from ndg.xacml.core.attribute import Attribute 24 24 from ndg.xacml.core.attributevalue import AttributeValueClassFactory … … 31 31 32 32 33 class TestContextHandler( AbstractContextHandler):33 class TestContextHandler(CtxHandlerInterface): 34 34 """Test implementation of Context Handler""" 35 35 36 36 def __init__(self): 37 """Add an attribute to hold a reference to a policy information point""" 38 37 39 super(TestContextHandler, self).__init__() 38 40 self.pip = None 39 41 40 42 def handlePEPRequest(self, myRequest): 43 """Handle request from Policy Enforcement Point 41 44 42 # Convert myRequest to XACML context request 45 @param pepRequest: request from PEP, derived class determines its type 46 e.g. SAML AuthzDecisionQuery 47 @type pepRequest: type 48 @return: PEP response - derived class determines type 49 @rtype: None 50 """ 51 52 # Convert myRequest to XACML context request - var assignment here is 53 # representative of this process rather than actually doing anything. 43 54 request = myRequest 44 55 … … 128 139 129 140 def test03AbstractCtxHandler(self): 130 self.assertRaises(TypeError, AbstractContextHandler) 141 self.assertRaises(TypeError, CtxHandlerInterface, 142 "Context handler is an abstract base class") 131 143 132 144 def test04CreateCtxHandler(self): -
TI12-security/trunk/NDG_XACML/ndg/xacml/test/test_matchfunctions.py
r7064 r7072 17 17 18 18 from ndg.xacml.core.functions import FunctionMap 19 from ndg.xacml.core.functions.v2. anyuri_regexp_match import AnyURIRegexpMatch19 from ndg.xacml.core.functions.v2.regexp_match import RegexpMatchBase 20 20 21 21 … … 29 29 'urn:oasis:names:tc:xacml:2.0:function:anyURI-regexp-match' 30 30 31 self.assert_(is instance(funcMap.get(anyUriMatchNs), AnyURIRegexpMatch))31 self.assert_(issubclass(funcMap.get(anyUriMatchNs), RegexpMatchBase)) 32 32 33 33 -
TI12-security/trunk/NDG_XACML/ndg/xacml/utils/__init__.py
r7064 r7072 9 9 __contact__ = "Philip.Kershaw@stfc.ac.uk" 10 10 __revision__ = '$Id$' 11 import UserDict 11 12 12 13 # Interpret a string as a boolean … … 114 115 115 116 116 class VettedDict( dict):117 """Enforce custom checking on keys and items before addition to the117 class VettedDict(UserDict.DictMixin): 118 """Enforce custom checking on keys and items before addition to a 118 119 dictionary""" 119 120 … … 126 127 @type args: tuple 127 128 """ 128 super(VettedDict, self).__init__()129 130 129 if len(args) != 2: 131 130 raise TypeError('__init__() takes 2 arguments, KeyFilter and ' … … 139 138 140 139 self.__KeyFilter, self.__valueFilter = args 140 141 self.__map = {} 141 142 142 143 def _verifyKeyValPair(self, key, val): … … 155 156 156 157 def __setitem__(self, key, val): 157 """ Override base class implementation to enforce type checking"""158 """Enforce type checking when setting new items""" 158 159 if self._verifyKeyValPair(key, val): 159 dict.__setitem__(self, key, val)160 self.__map[key] = val 160 161 161 def update(self, d, **kw): 162 """Override base class implementation to enforce type checking""" 163 for dictArg in (d, kw): 164 for key, val in dictArg.items(): 165 if not self._verifyKeyValPair(key, val): 166 del dictArg[key] 162 def __getitem__(self, key): 163 """Provde implementation for getting items""" 164 if key not in self.__map: 165 raise KeyError('%r key not found in dict' % key) 167 166 168 dict.update(self, d, **kw)167 return self.__map[key] 169 168 169 def get(self, key, *arg): 170 """Provide implementation of get item with default""" 171 if key in self.__map: 172 return self.__map[key] 173 174 elif len(arg) > 1: 175 # Default value set 176 return arg[1] 177 else: 178 return None 179 180 181 -
TI12-security/trunk/NDG_XACML/ndg/xacml/utils/factory.py
r7064 r7072 41 41 objectName = [objectName] 42 42 43 log.debug("Importing %r ..." % objectName)44 45 43 module = __import__(_moduleName, globals(), locals(), []) 46 44 components = _moduleName.split('.') … … 50 48 except AttributeError, e: 51 49 raise AttributeError("Error importing %r: %s" % 52 (objectName , traceback.format_exc()))50 (objectName[0], traceback.format_exc())) 53 51 54 52 importedObject = module … … 61 59 (objectName, objectType, importedObject)) 62 60 63 log.info('Imported %r from module , %r', objectName, _moduleName)61 log.info('Imported %r from module %r', objectName[0], _moduleName) 64 62 return importedObject 65 63 … … 121 119 122 120 except Exception, e: 123 log. error('%r module import raised %r type exception: %r' %124 (moduleName, e.__class__, traceback.format_exc()))121 log.debug('%r module import raised %r type exception: %s', 122 moduleName, e.__class__, traceback.format_exc()) 125 123 raise 126 124 127 125 # Instantiate class 128 log.debug('Instantiating object "%s"' % importedObject.__name__) 129 try: 130 if objectArgs: 131 object = importedObject(*objectArgs, **objectProperties) 132 else: 133 object = importedObject(**objectProperties) 134 135 return object 136 137 except Exception, e: 138 log.error("Instantiating module object, %r: %r" % 139 (importedObject.__name__, 140 traceback.format_exc())) 141 raise 126 if objectArgs: 127 object = importedObject(*objectArgs, **objectProperties) 128 else: 129 object = importedObject(**objectProperties) 130 131 return object
Note: See TracChangeset
for help on using the changeset viewer.