source: TI12-security/trunk/ndg_saml/ndg/soap/__init__.py @ 7662

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/ndg_saml/ndg/soap/__init__.py@7662
Revision 7662, 6.3 KB checked in by pjkersha, 10 years ago (diff)

Added SOAPFault handling for ndg.soap package. Needs integration into ndg.saml.saml2.binding.soap.server.wsgi.queryinterface to enable SAML query interface to do better error reporting.

Line 
1"""SOAP common package for NDG SAML. 
2
3Initially for use with SAML SOAP Bindings.  This itself
4uses ElementTree.  This SOAP interface provides an ElementTree interface to
5support it
6
7NERC DataGrid Project
8"""
9__author__ = "P J Kershaw"
10__date__ = "24/07/09"
11__copyright__ = "(C) 2009 Science and Technology Facilities Council"
12__license__ = "http://www.apache.org/licenses/LICENSE-2.0"
13__contact__ = "Philip.Kershaw@stfc.ac.uk"
14__revision__ = '$Id: __init__.py 7130 2010-06-30 13:33:07Z pjkersha $'
15import logging
16log = logging.getLogger(__name__)
17   
18     
19class SOAPObject(object):
20    """Base class for SOAP envelope, header and body elements"""
21   
22    ELEMENT_PREFIX = "soap11"
23    SOAP11_NS = "http://schemas.xmlsoap.org/soap/envelope/"
24    SOAP12_NS = "http://www.w3.org/2003/05/soap-envelope"
25    DEFAULT_NS = SOAP11_NS
26   
27    __slots__ = ()
28   
29    def create(self):
30        raise NotImplementedError()
31   
32    def parse(self, source):
33        raise NotImplementedError()
34   
35    def serialize(self):
36        raise NotImplementedError()
37   
38    def prettyPrint(self):
39        raise NotImplementedError()
40     
41   
42class SOAPEnvelopeBase(SOAPObject):
43    """SOAP Envelope"""
44   
45    DEFAULT_ELEMENT_LOCAL_NAME = "Envelope"
46    DEFAULT_ELEMENT_NS = SOAPObject.DEFAULT_NS
47    DEFAULT_ELEMENT_NS_PREFIX = SOAPObject.ELEMENT_PREFIX
48   
49    soapHeader = property()
50    soapBody = property()
51   
52    __slots__ = ()
53   
54   
55class SOAPHeaderBase(SOAPObject):
56    """SOAP Header base class"""
57   
58    DEFAULT_ELEMENT_LOCAL_NAME = "Header"
59    DEFAULT_ELEMENT_NS = SOAPObject.DEFAULT_NS
60    DEFAULT_ELEMENT_NS_PREFIX = SOAPObject.ELEMENT_PREFIX   
61    __slots__ = ()
62       
63       
64class SOAPBodyBase(SOAPObject):
65    """SOAP Body base class"""
66   
67    DEFAULT_ELEMENT_LOCAL_NAME = "Body"
68    DEFAULT_ELEMENT_NS = SOAPObject.DEFAULT_NS
69    DEFAULT_ELEMENT_NS_PREFIX = SOAPObject.ELEMENT_PREFIX
70    fault = property()
71    __slots__ = ()
72 
73       
74class SOAPFaultBase(SOAPObject):
75    """SOAP Fault"""
76   
77    DEFAULT_ELEMENT_LOCAL_NAME = "Fault"
78    DEFAULT_ELEMENT_NS = SOAPObject.DEFAULT_NS
79    DEFAULT_ELEMENT_NS_PREFIX = SOAPObject.ELEMENT_PREFIX
80   
81    FAULT_CODE_ELEMENT_LOCAL_NAME = "faultcode"
82    FAULT_STRING_ELEMENT_LOCAL_NAME = "faultstring"
83    FAULT_ACTOR_ELEMENT_LOCAL_NAME = "faultactor"
84    DETAIL_ELEMENT_LOCAL_NAME = "detail"
85   
86    VERSION_MISMATCH_CODE = "VersionMismatch"
87    MUST_UNDERSTAND_FAULT_CODE = "MustUnderstand"
88    CLIENT_FAULT_CODE = "Client"
89    SERVER_FAULT_CODE = "Server"
90   
91    FAULT_CODES = (
92        VERSION_MISMATCH_CODE, 
93        MUST_UNDERSTAND_FAULT_CODE, 
94        CLIENT_FAULT_CODE, 
95        SERVER_FAULT_CODE
96    )
97   
98    __slots__ = ("__faultCode", "__faultString", "__faultActor", "__detail")
99   
100    def __init__(self, faultString=None, faultCode=None, faultActor=None, 
101                 detail=None):
102        """Initialise attributes"""
103        super(SOAPFaultBase, self).__init__()
104       
105        if faultCode is None:
106            self.__faultCode = None
107        else:
108            self.faultCode = faultCode
109           
110        if faultString is None:
111            self.__faultString = None
112        else:
113            self.faultString = faultString
114           
115        if faultActor is None:
116            self.__faultActor = None
117        else:
118            self.faultActor = faultActor
119       
120        if detail is None:
121            self.__detail = None
122        else:
123            self.detail = detail
124
125    def _setFaultCode(self, value):
126        if not isinstance(value, basestring):
127            raise AttributeError('Expecting string type for "faultCode" '
128                                 'attribute; got %r' % type(value))
129           
130        qnameElems = value.split(':')
131        if len(qnameElems) == 0:
132            raise AttributeError('Expecting Qualified Name for "faultCode" '
133                                 'attribute; got %r' % value)
134       
135        faultCodeFound = [qnameElems[1].startswith(i) 
136                          for i in self.__class__.FAULT_CODES]
137        if max(faultCodeFound) == False:
138            raise AttributeError('Expecting "faultCode" prefixed with one of '
139                                 '%r; got %r' % (self.__class__.FAULT_CODES,
140                                                 value))
141           
142        self.__faultCode = value
143       
144    def _getFaultCode(self):
145        return self.__faultCode
146
147    faultCode = property(_getFaultCode, _setFaultCode, 
148                         doc="Fault Code")
149
150    def _setFaultString(self, value):
151        if not isinstance(value, basestring):
152            raise AttributeError('Expecting string type for "faultString" '
153                                 'attribute; got %r' % type(value))
154        self.__faultString = value
155       
156    def _getFaultString(self):
157        return self.__faultString
158
159    faultString = property(_getFaultString, _setFaultString, 
160                           doc="Fault String")
161
162    def _getFaultActor(self):
163        return self.__faultActor
164
165    def _setFaultActor(self, value):
166        if not isinstance(value, basestring):
167            raise AttributeError('Expecting string type for "faultActor" '
168                                 'attribute; got %r' % type(value))
169        self.__faultActor = value
170
171    faultActor = property(_getFaultActor, _setFaultActor, 
172                          doc="Fault Actor")
173
174    def _getDetail(self):
175        return self.__detail
176
177    def _setDetail(self, value):
178        """No type checking - detail could be an XML element or serialised
179        string content"""
180        self.__detail = value
181
182    detail = property(_getDetail, _setDetail, doc="Fault detail")
183
184
185class SOAPException(Exception):
186    """Base SOAP Exception class"""
187       
188   
189class SOAPFaultException(Exception):
190    """Raise an exception which also creates a fault object"""
191    SOAP_FAULT_CLASS = SOAPFaultBase
192   
193    def __init__(self, faultString, faultCode, faultActor=None, detail=None):
194        super(SOAPFaultException, self).__init__(faultString)
195        self.__fault = self.__class__.SOAP_FAULT_CLASS(faultString, faultCode, 
196                                                       faultActor=faultActor, 
197                                                       detail=detail)
198       
199    @property   
200    def fault(self):
201        """Get SOAP fault object"""
202        return self.__fault
Note: See TracBrowser for help on using the repository browser.