Ignore:
Timestamp:
13/04/10 16:39:31 (11 years ago)
Author:
pjkersha
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/NDG_XACML/ndg/xacml/core/functions/__init__.py

    r6802 r6803  
    1 """NDG XACML package for match functions 
     1"""NDG XACML package for functions 
    22 
    33NERC DataGrid Project 
     
    1111__revision__ = "$Id: $" 
    1212from abc import ABCMeta, abstractmethod 
    13  
     13from datetime import datetime, timedelta 
     14import traceback 
     15import logging 
     16log = logging.getLogger(__name__) 
     17 
     18from ndg.xacml.core.attributevalue import AttributeValue 
    1419from ndg.xacml.utils import VettedDict 
    1520from ndg.xacml.utils.factory import callModuleObject 
    16  
    17 from datetime import datetime, timedelta 
    1821 
    1922 
     
    3033            raise TypeError('"FUNCTION_NS" class variable must be defined in ' 
    3134                            'derived classes') 
    32 #    @classmethod 
    33 #    def __subclasshook__(cls, C): 
    34 #        if cls is AbstractFunction: 
    35 #            if  
    36 #            return True 
    37 #        else: 
    38 #            return NotImplemented 
    3935             
    4036    @abstractmethod 
     
    265261 
    266262 
     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     
    267373class FunctionMapError(Exception): 
    268374    """Generic Error exception class for FunctionMap""" 
     
    284390        AbstractFunction.V2_0_FUNCTION_NS: V2_0_PKG_PREFIX 
    285391    } 
     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' 
    286396     
    287397    def __init__(self): 
     
    300410            raise TypeError('Expecting %r type for key; got %r' %  
    301411                            (basestring, type(key)))  
     412             
    302413        return True  
    303414     
     
    305416    def valueFilter(value): 
    306417        """Enforce AbstractFunction derived types for match functions""" 
    307  
    308         if not isinstance(value,  
    309                           (AbstractFunction, NotImplemented.__class__)): 
     418        if value is NotImplemented: 
     419            return True 
     420         
     421        elif not issubclass(value, AbstractFunction): 
    310422            raise TypeError('Expecting %r derived type for value; got %r' %  
    311                             (AbstractFunction, type(value)))  
     423                            (AbstractFunction, value))  
     424             
    312425        return True  
    313426            
     
    334447        if functionNs == "urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of": 
    335448            pass 
     449#        else: 
     450#            self[functionNs] = NotImplemented 
     451#            return 
    336452 
    337453        for namespacePrefix, pkgNamePrefix in cls.SUPPORTED_NSS.items(): 
     
    347463                    moduleName = '_'.join(functionNameParts[1:]).lower() 
    348464                     
    349                 className = ''.join([n[0].upper() + n[1:]  
    350                                      for n in functionNameParts]) 
    351                 classPath = pkgNamePrefix + moduleName + '.' + className 
     465                classPath = pkgNamePrefix + moduleName + '.' + \ 
     466                            cls.FUNCTION_CLASS_FACTORY_CLASSNAME 
    352467                break 
    353468 
     
    359474        # map 
    360475        try: 
    361             matchFunctionObj = callModuleObject(classPath) 
    362             self[functionNs] = matchFunctionObj 
    363         except ImportError: 
     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             
    364483            # No implementation exists - default to Abstract function 
    365484            self[functionNs] = NotImplemented 
    366485             
    367  
    368  
    369          
     486        self[functionNs] = functionFactory(functionNs) 
     487             
     488 
     489 
     490         
Note: See TracChangeset for help on using the changeset viewer.