source: TI12-security/trunk/python/ndg.security.common/ndg/security/common/soap/etree.py @ 5521

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.common/ndg/security/common/soap/etree.py@5521
Revision 5521, 8.3 KB checked in by pjkersha, 11 years ago (diff)

Added urllib2 based SOAP client handler class.

Line 
1"""SOAP client package - XML representation using ElementTree
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "27/07/09"
7__copyright__ = ""
8__license__ = "BSD - see LICENSE file in top-level directory"
9__contact__ = "Philip.Kershaw@stfc.ac.uk"
10__revision__ = '$Id:$'
11import logging
12log = logging.getLogger(__name__)
13   
14try: # python 2.5
15    from xml.etree import cElementTree as ElementTree
16except ImportError:
17    # if you've installed it yourself it comes this way
18    import cElementTree as ElementTree
19
20# ElementTree helper functions
21from ndg.security.common.utils import QName, canonicalize, getLocalName
22
23from ndg.security.common.soap import SOAPObject, SOAPEnvelopeBase, \
24    SOAPHeaderBase, SOAPBodyBase
25
26class ETreeSOAPExtensions(object): 
27    """Utility to enable addition of core ElementTree specific attributes and
28    methods for ElementTree SOAP implementation
29    """
30    def __init__(self):
31        self.__qname = None
32        self.__elem = None
33
34    def _getQname(self):
35        return self.__qname
36
37    def _setQname(self, value):
38        if not isinstance(value, QName):
39            raise TypeError('Expecting %r for "qname" attribute; got %r' %
40                            (QName, type(value)))
41        self.__qname = value
42
43    def _getElem(self):
44        return self.__elem
45
46    def _setElem(self, value):
47        if not ElementTree.iselement(value):
48            raise TypeError('Expecting %r for "elem" attribute; got %r' %
49                            (ElementTree.Element, type(value)))
50        self.__elem = value
51       
52    qname = property(_getQname, _setQname, None, "Qualified name object")
53    elem = property(_getElem, _setElem, None, "Root element")
54   
55    @staticmethod
56    def _serialize(elem):
57        """Serialise element tree into string"""
58       
59        # Make a basic check for the SOAP name space declaration, if the
60        # element is constructed from a call to ElementTree.parse it may not
61        # be present
62        namespaceDeclarationFound = False
63        soapElemNsDeclaration = (
64            'xmlns:%s' % SOAPObject.ELEMENT_PREFIX, 
65            SOAPObject.DEFAULT_NS
66        )
67        if soapElemNsDeclaration[0] not in elem.attrib:
68            log.warning("No SOAP namespace declaration found - adding one in")
69            elem.set(*soapElemNsDeclaration)
70       
71        return canonicalize(elem)
72   
73    @classmethod
74    def _prettyPrint(cls, elem):
75        """Basic pretty printing separating each element on to a new line"""
76        xml = cls._serialize(elem)
77        xml = ">\n".join(xml.split(">"))
78        xml = "\n<".join(xml.split("<"))
79        xml = '\n'.join(xml.split('\n\n'))
80        return xml
81
82    def _parse(self, source):
83        """Read in the XML from source
84        @type source: basestring/file
85        @param source: file path to XML file or file object
86        """
87        tree = ElementTree.parse(source)
88        elem = tree.getroot()
89       
90        return elem       
91
92
93class SOAPHeader(SOAPHeaderBase, ETreeSOAPExtensions):
94    """ElementTree implementation of SOAP Header object"""
95   
96    DEFAULT_ELEMENT_NAME = QName(SOAPHeaderBase.DEFAULT_ELEMENT_NS,
97                               tag=SOAPHeaderBase.DEFAULT_ELEMENT_LOCAL_NAME,
98                               prefix=SOAPHeaderBase.DEFAULT_ELEMENT_NS_PREFIX)
99   
100    def __init__(self):
101        SOAPHeaderBase.__init__(self)
102        ETreeSOAPExtensions.__init__(self)
103       
104        self.qname = QName(SOAPHeaderBase.DEFAULT_ELEMENT_NS, 
105                           tag=SOAPHeaderBase.DEFAULT_ELEMENT_LOCAL_NAME, 
106                           prefix=SOAPHeaderBase.DEFAULT_ELEMENT_NS_PREFIX)
107
108    def create(self, makeNsDeclaration=True):
109        """Create header ElementTree element"""
110       
111        self.elem = ElementTree.Element(str(self.qname))
112        if makeNsDeclaration:
113            self.elem.set(
114                    "xmlns:%s" % SOAPHeaderBase.DEFAULT_ELEMENT_NS_PREFIX,
115                    SOAPHeaderBase.DEFAULT_ELEMENT_NS)
116   
117    def serialize(self):
118        """Serialise element tree into string"""
119        return ETreeSOAPExtensions._serialize(self.elem)
120   
121    def prettyPrint(self):
122        """Basic pretty printing separating each element on to a new line"""
123        return ETreeSOAPExtensions._prettyPrint(self.elem)
124
125
126class SOAPBody(SOAPBodyBase, ETreeSOAPExtensions):
127    """ElementTree based implementation for SOAP Body object"""
128   
129    DEFAULT_ELEMENT_NAME = QName(SOAPBodyBase.DEFAULT_ELEMENT_NS,
130                                 tag=SOAPBodyBase.DEFAULT_ELEMENT_LOCAL_NAME,
131                                 prefix=SOAPBodyBase.DEFAULT_ELEMENT_NS_PREFIX)
132   
133    def __init__(self):
134        SOAPBodyBase.__init__(self)
135        ETreeSOAPExtensions.__init__(self)
136       
137        self.qname = QName(SOAPBodyBase.DEFAULT_ELEMENT_NS, 
138                           tag=SOAPBodyBase.DEFAULT_ELEMENT_LOCAL_NAME, 
139                           prefix=SOAPBodyBase.DEFAULT_ELEMENT_NS_PREFIX)
140       
141    def create(self, makeNsDeclaration=True):
142        """Create header ElementTree element"""
143       
144        self.elem = ElementTree.Element(str(self.qname))
145        if makeNsDeclaration:
146            self.elem.set("xmlns:%s" % SOAPBodyBase.DEFAULT_ELEMENT_NS_PREFIX,
147                          SOAPBodyBase.DEFAULT_ELEMENT_NS)
148   
149    def serialize(self):
150        """Serialise element tree into string"""
151        return ETreeSOAPExtensions._serialize(self.elem)
152   
153    def prettyPrint(self):
154        """Basic pretty printing separating each element on to a new line"""
155        return ETreeSOAPExtensions._prettyPrint(self.elem)
156   
157
158class SOAPEnvelope(SOAPEnvelopeBase, ETreeSOAPExtensions):
159    """ElementTree based SOAP implementation"""
160    DEFAULT_ELEMENT_NAME = QName(SOAPEnvelopeBase.DEFAULT_ELEMENT_NS,
161                             tag=SOAPEnvelopeBase.DEFAULT_ELEMENT_LOCAL_NAME,
162                             prefix=SOAPEnvelopeBase.DEFAULT_ELEMENT_NS_PREFIX)
163
164    def __init__(self):
165        SOAPEnvelopeBase.__init__(self)
166        ETreeSOAPExtensions.__init__(self)
167       
168        self.qname = QName(SOAPEnvelopeBase.DEFAULT_ELEMENT_NS, 
169                             tag=SOAPEnvelopeBase.DEFAULT_ELEMENT_LOCAL_NAME, 
170                             prefix=SOAPEnvelopeBase.DEFAULT_ELEMENT_NS_PREFIX)
171        self.__header = SOAPHeader()
172        self.__body = SOAPBody()
173
174    def _getHeader(self):
175        return self.__header
176
177    def _setHeader(self, value):
178        if not isinstance(value, SOAPHeader):
179            raise TypeError('Expecting %r for "header" attribute; got %r' %
180                            (SOAPHeader, type(value)))
181        self.__header = value
182
183    def _getBody(self):
184        return self.__body
185
186    def _setBody(self, value):
187        if not isinstance(value, SOAPBody):
188            raise TypeError('Expecting %r for "header" attribute; got %r' %
189                            (SOAPBody, type(value)))
190        self.__body = value
191
192    header = property(_getHeader, _setHeader, None, "SOAP header object")
193    body = property(_getBody, _setBody, None, "SOAP body object")
194
195    def create(self, makeNsDeclaration=True):
196        """Create SOAP Envelope with header and body"""
197       
198        self.elem = ElementTree.Element(str(self.qname))
199        if makeNsDeclaration:
200            self.elem.set("xmlns:%s" % SOAPBodyBase.DEFAULT_ELEMENT_NS_PREFIX,
201                          SOAPBodyBase.DEFAULT_ELEMENT_NS)
202           
203        self.header.create(makeNsDeclaration=False)
204        self.elem.append(self.header.elem)
205       
206        self.body.create(makeNsDeclaration=False)
207        self.elem.append(self.body.elem)
208   
209    def serialize(self):
210        """Serialise element tree into string"""
211        return ETreeSOAPExtensions._serialize(self.elem)
212   
213    def prettyPrint(self):
214        """Basic pretty printing separating each element onto a new line"""
215        return ETreeSOAPExtensions._prettyPrint(self.elem)
216   
217    def parse(self, source):
218        self.elem = ETreeSOAPExtensions._parse(self, source) 
219       
220        for elem in self.elem:
221            localName = getLocalName(elem)
222            if localName == SOAPHeader.DEFAULT_ELEMENT_LOCAL_NAME:
223                self.header.elem = elem
224               
225            elif localName == SOAPBody.DEFAULT_ELEMENT_LOCAL_NAME:
226                self.body.elem = elem
227               
228            else:
229                raise SOAPFault('Invalid child element in SOAP Envelope "%s" '
230                                'for source %r' % (localName, source))
Note: See TracBrowser for help on using the repository browser.