Esempio n. 1
0
    def help(self, method=None):
        "Generate sample request and response messages"
        (function, returns, args, doc) = self.methods[method]
        xml = """
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body><%(method)s xmlns="%(namespace)s"/></soap:Body>
</soap:Envelope>"""  % {'method':method, 'namespace':self.namespace}
        request = SimpleXMLElement(xml, namespace=self.namespace, prefix=self.prefix)
        if args:
            items = args.items()
        elif args is None:
            items = [('value', None)]
        else:
            items = []
        for k,v in items:
            request(method).marshall(k, v, add_comments=True, ns=False)

        xml = """
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body><%(method)sResponse xmlns="%(namespace)s"/></soap:Body>
</soap:Envelope>"""  % {'method':method, 'namespace':self.namespace}
        response = SimpleXMLElement(xml, namespace=self.namespace, prefix=self.prefix)
        if returns:
            items = returns.items()
        elif args is None:
            items = [('value', None)]
        else:
            items = []
        for k,v in items:
            response('%sResponse'%method).marshall(k, v, add_comments=True, ns=False)

        return request.as_xml(pretty=True), response.as_xml(pretty=True), doc
Esempio n. 2
0
    def help(self, method=None):
        "Generate sample request and response messages"
        (function, returns, args, doc) = self.methods[method]
        xml = """
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body><%(method)s xmlns="%(namespace)s"/></soap:Body>
</soap:Envelope>"""  % {'method':method, 'namespace':self.namespace}
        request = SimpleXMLElement(xml, namespace=self.namespace, prefix=self.prefix)
        if args:
            items = args.items()
        elif args is None:
            items = [('value', None)]
        else:
            items = []
        for k,v in items:
            request(method).marshall(k, v, add_comments=True, ns=False)

        xml = """
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body><%(method)sResponse xmlns="%(namespace)s"/></soap:Body>
</soap:Envelope>"""  % {'method':method, 'namespace':self.namespace}
        response = SimpleXMLElement(xml, namespace=self.namespace, prefix=self.prefix)
        if returns:
            items = returns.items()
        elif args is None:
            items = [('value', None)]
        else:
            items = []
        for k,v in items:
            response('%sResponse'%method).marshall(k, v, add_comments=True, ns=False)

        return request.as_xml(pretty=True), response.as_xml(pretty=True), doc
Esempio n. 3
0
 def call(self, method, *args, **kwargs):
     "Prepare xml request and make SOAP call, returning a SimpleXMLElement"
     #TODO: method != input_message
     # Basic SOAP request:
     xml = self.__xml % dict(method=method,
                             namespace=self.namespace,
                             ns=self.__ns,
                             soap_ns=self.__soap_ns,
                             soap_uri=soap_namespaces[self.__soap_ns])
     request = SimpleXMLElement(xml,
                                namespace=self.__ns and self.namespace,
                                prefix=self.__ns)
     # serialize parameters
     if kwargs:
         parameters = kwargs.items()
     else:
         parameters = args
     if parameters and isinstance(parameters[0], SimpleXMLElement):
         # merge xmlelement parameter ("raw" - already marshalled)
         for param in parameters[0].children():
             getattr(request, method).import_node(param)
     else:
         # marshall parameters:
         for k, v in parameters:  # dict: tag=valor
             getattr(request, method).marshall(k, v)
     self.xml_request = request.as_xml()
     self.xml_response = self.send(method, self.xml_request)
     response = SimpleXMLElement(self.xml_response,
                                 namespace=self.namespace)
     if self.exceptions and response(
             "Fault", ns=soap_namespaces.values(), error=False):
         raise SoapFault(unicode(response.faultcode),
                         unicode(response.faultstring))
     return response
Esempio n. 4
0
 def call(self, method, *args, **kwargs):
     "Prepare xml request and make SOAP call, returning a SimpleXMLElement"
     # TODO: method != input_message
     # Basic SOAP request:
     xml = self.__xml % dict(
         method=method,
         namespace=self.namespace,
         ns=self.__ns,
         soap_ns=self.__soap_ns,
         soap_uri=soap_namespaces[self.__soap_ns],
     )
     request = SimpleXMLElement(xml, namespace=self.__ns and self.namespace, prefix=self.__ns)
     # serialize parameters
     if kwargs:
         parameters = kwargs.items()
     else:
         parameters = args
     if parameters and isinstance(parameters[0], SimpleXMLElement):
         # merge xmlelement parameter ("raw" - already marshalled)
         for param in parameters[0].children():
             getattr(request, method).import_node(param)
     else:
         # marshall parameters:
         for k, v in parameters:  # dict: tag=valor
             getattr(request, method).marshall(k, v)
     self.xml_request = request.as_xml()
     self.xml_response = self.send(method, self.xml_request)
     response = SimpleXMLElement(self.xml_response, namespace=self.namespace)
     if self.exceptions and response("Fault", ns=soap_namespaces.values(), error=False):
         raise SoapFault(unicode(response.faultcode), unicode(response.faultstring))
     return response
Esempio n. 5
0
    def call(self, method, *args, **kwargs):
        "Prepare xml request and make SOAP call, returning a SimpleXMLElement"                
        #TODO: method != input_message
        # Basic SOAP request:
        if kwargs:
            parameters = kwargs.items()
            username, password = args
        else:
            (username, password), parameters = args
        
        created = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')

        expires = (datetime.utcnow() + timedelta(0, 300)).strftime('%Y-%m-%dT%H:%M:%SZ')
        
        header = self.header
        try:
            header = header % dict(Username = username, Password = password, Created=created, Expires=expires)
        except KeyError:
            pass
        
        xml = self.__xml % dict(method=method, namespace=self.namespace, ns=self.__ns, header = header,
                                soap_ns=self.__soap_ns, soap_uri=soap_namespaces[self.__soap_ns], body_xmlns = self.body_xmlns)
        
        request = SimpleXMLElement(xml,namespace=self.__ns and self.namespace, prefix=self.__ns)
        # serialize parameters

        if parameters and isinstance(parameters[0], SimpleXMLElement):
            # merge xmlelement parameter ("raw" - already marshalled)
            for param in parameters[0].children():
                getattr(request,method).import_node(param)
        else:
            # marshall parameters:
            for k,v in parameters: # dict: tag=valor
                getattr(request,method).marshall(k,v)
        
        self.xml_request = request.as_xml()
        
        try:
            self.xml_response = self.send(method, self.xml_request)
            response = SimpleXMLElement(self.xml_response, namespace=self.namespace)
            if self.exceptions and response("Fault", ns=soap_namespaces.values(), error=False):
                raise SoapFault(unicode(response.faultcode), unicode(response.faultstring))
            return response
        except urllib2.HTTPError, error:
            self.xml_response = error.read()
            try:
                response = SimpleXMLElement(self.xml_response, namespace=self.namespace)
            except:
                raise error
            if self.exceptions and response("Fault", ns=soap_namespaces.values(), error=False):
                try:
                    detail = str(response.detail.Message)
                except:
                    detail = ""
                if "ID3242" in detail:
                    raise NotAuthorizedError()
                else:
                    raise SoapFault(unicode(response.faultcode), unicode(response.faultstring))
            else:
                raise error
Esempio n. 6
0
 def call(self, method, *args, **kwargs):
     "Prepare xml request and make SOAP call, returning a SimpleXMLElement"                
     #TODO: method != input_message
     # Basic SOAP request:
     xml = self.__xml % dict(method=method, namespace=self.namespace, ns=self.__ns,
                             soap_ns=self.__soap_ns, soap_uri=soap_namespaces[self.__soap_ns])
     request = SimpleXMLElement(xml,namespace=self.__ns and self.namespace, prefix=self.__ns)
     # serialize parameters
     if kwargs:
         parameters = kwargs.items()
     else:
         parameters = args
     if parameters and isinstance(parameters[0], SimpleXMLElement):
         # merge xmlelement parameter ("raw" - already marshalled)
         for param in parameters[0].children():
             getattr(request,method).import_node(param)
     elif parameters:
         # marshall parameters:
         for k,v in parameters: # dict: tag=valor
             getattr(request,method).marshall(k,v)
     elif not self.__soap_server in ('oracle', ) or self.__soap_server in ('jbossas6',):
         # JBossAS-6 requires no empty method parameters!
         delattr(request("Body", ns=soap_namespaces.values(),), method)
     # construct header and parameters (if not wsdl given) except wsse
     if self.__headers and not self.services:
         self.__call_headers = dict([(k, v) for k, v in self.__headers.items()
                                     if not k.startswith("wsse:")])
     # always extract WS Security header and send it
     if 'wsse:Security' in self.__headers:
         #TODO: namespaces too hardwired, clean-up...
         header = request('Header' , ns=soap_namespaces.values(),)
         k = 'wsse:Security'
         v = self.__headers[k]
         header.marshall(k, v, ns=False, add_children_ns=False)
         header(k)['xmlns:wsse'] = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
         #<wsse:UsernameToken xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'> 
     if self.__call_headers:
         header = request('Header' , ns=soap_namespaces.values(),)
         for k, v in self.__call_headers.items():
             ##if not self.__ns:
             ##    header['xmlns']
             header.marshall(k, v, ns=self.__ns, add_children_ns=False)
     self.xml_request = request.as_xml()
     self.xml_response = self.send(method, self.xml_request)
     response = SimpleXMLElement(self.xml_response, namespace=self.namespace)
     if self.exceptions and response("Fault", ns=soap_namespaces.values(), error=False):
         raise SoapFault(unicode(response.faultcode), unicode(response.faultstring))
     return response
Esempio n. 7
0
    def wsdl(self):
        "Generate Web Service Description v1.1"
        xml = """<?xml version="1.0"?>
<wsdl:definitions name="%(name)s" 
          targetNamespace="%(namespace)s"
          xmlns:tns="%(namespace)s"
          xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
          xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">%(documentation)s</wsdl:documentation>

    <wsdl:types>
       <xsd:schema targetNamespace="%(namespace)s"
              elementFormDefault="qualified"
              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
       </xsd:schema>
    </wsdl:types>

</wsdl:definitions>
""" % {
            'namespace': self.namespace,
            'name': self.name,
            'documentation': self.documentation
        }
        wsdl = SimpleXMLElement(xml)

        for method, (function, returns, args, doc) in self.methods.items():
            # create elements:

            def parse_element(name, values, array=False, complex=False):
                if not complex:
                    element = wsdl('wsdl:types')('xsd:schema').add_child(
                        'xsd:element')
                    complex = element.add_child("xsd:complexType")
                else:
                    complex = wsdl('wsdl:types')('xsd:schema').add_child(
                        'xsd:complexType')
                    element = complex
                element['name'] = name
                if values:
                    items = values
                elif values is None:
                    items = [('value', None)]
                else:
                    items = []
                if not array and items:
                    all = complex.add_child("xsd:all")
                elif items:
                    all = complex.add_child("xsd:sequence")
                for k, v in items:
                    e = all.add_child("xsd:element")
                    e['name'] = k
                    if array:
                        e[:] = {'minOccurs': "0", 'maxOccurs': "unbounded"}
                    if v in TYPE_MAP.keys():
                        t = 'xsd:%s' % TYPE_MAP[v]
                    elif v is None:
                        t = 'xsd:anyType'
                    elif isinstance(v, list):
                        n = "ArrayOf%s%s" % (name, k)
                        l = []
                        for d in v:
                            l.extend(d.items())
                        parse_element(n, l, array=True, complex=True)
                        t = "tns:%s" % n
                    elif isinstance(v, dict):
                        n = "%s%s" % (name, k)
                        parse_element(n, v.items(), complex=True)
                        t = "tns:%s" % n
                    e.add_attribute('type', t)

            parse_element("%s" % method, args and args.items())
            parse_element("%sResponse" % method, returns and returns.items())

            # create messages:
            for m, e in ('Input', ''), ('Output', 'Response'):
                message = wsdl.add_child('wsdl:message')
                message['name'] = "%s%s" % (method, m)
                part = message.add_child("wsdl:part")
                part[:] = {
                    'name': 'parameters',
                    'element': 'tns:%s%s' % (method, e)
                }

        # create ports
        portType = wsdl.add_child('wsdl:portType')
        portType['name'] = "%sPortType" % self.name
        for method, (function, returns, args, doc) in self.methods.items():
            op = portType.add_child('wsdl:operation')
            op['name'] = method
            if doc:
                op.add_child("wsdl:documentation", doc)
            input = op.add_child("wsdl:input")
            input['message'] = "tns:%sInput" % method
            output = op.add_child("wsdl:output")
            output['message'] = "tns:%sOutput" % method

        # create bindings
        binding = wsdl.add_child('wsdl:binding')
        binding['name'] = "%sBinding" % self.name
        binding['type'] = "tns:%sPortType" % self.name
        soapbinding = binding.add_child('soap:binding')
        soapbinding['style'] = "document"
        soapbinding['transport'] = "http://schemas.xmlsoap.org/soap/http"
        for method in self.methods.keys():
            op = binding.add_child('wsdl:operation')
            op['name'] = method
            soapop = op.add_child('soap:operation')
            soapop['soapAction'] = self.action + method
            soapop['style'] = 'document'
            input = op.add_child("wsdl:input")
            ##input.add_attribute('name', "%sInput" % method)
            soapbody = input.add_child("soap:body")
            soapbody["use"] = "literal"
            output = op.add_child("wsdl:output")
            ##output.add_attribute('name', "%sOutput" % method)
            soapbody = output.add_child("soap:body")
            soapbody["use"] = "literal"

        service = wsdl.add_child('wsdl:service')
        service["name"] = "%sService" % self.name
        service.add_child('wsdl:documentation', text=self.documentation)
        port = service.add_child('wsdl:port')
        port["name"] = "%s" % self.name
        port["binding"] = "tns:%sBinding" % self.name
        soapaddress = port.add_child('soap:address')
        soapaddress["location"] = self.location
        return wsdl.as_xml(pretty=True)
Esempio n. 8
0
    def wsdl(self):
        "Generate Web Service Description v1.1"
        xml = """<?xml version="1.0"?>
<wsdl:definitions name="%(name)s" 
          targetNamespace="%(namespace)s"
          xmlns:tns="%(namespace)s"
          xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
          xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">%(documentation)s</wsdl:documentation>

    <wsdl:types>
       <xsd:schema targetNamespace="%(namespace)s"
              elementFormDefault="qualified"
              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
       </xsd:schema>
    </wsdl:types>

</wsdl:definitions>
""" % {'namespace': self.namespace, 'name': self.name, 'documentation': self.documentation}
        wsdl = SimpleXMLElement(xml)

        for method, (function, returns, args, doc) in self.methods.items():
            # create elements:
                
            def parse_element(name, values, array=False, complex=False):
                if not complex:
                    element = wsdl('wsdl:types')('xsd:schema').add_child('xsd:element')
                    complex = element.add_child("xsd:complexType")
                else:
                    complex = wsdl('wsdl:types')('xsd:schema').add_child('xsd:complexType')
                    element = complex
                element['name'] = name
                if values:
                    items = values
                elif values is None:
                    items = [('value', None)]
                else:
                    items = []
                if not array and items:
                    all = complex.add_child("xsd:all")
                elif items:
                    all = complex.add_child("xsd:sequence")
                for k,v in items:
                    e = all.add_child("xsd:element")
                    e['name'] = k
                    if array:
                        e[:]={'minOccurs': "0", 'maxOccurs': "unbounded"}
                    if v in TYPE_MAP.keys():
                        t='xsd:%s' % TYPE_MAP[v]
                    elif v is None:
                        t='xsd:anyType'
                    elif isinstance(v, list):
                        n="ArrayOf%s%s" % (name, k)
                        l = []
                        for d in v:
                            l.extend(d.items())
                        parse_element(n, l, array=True, complex=True)
                        t = "tns:%s" % n
                    elif isinstance(v, dict): 
                        n="%s%s" % (name, k)
                        parse_element(n, v.items(), complex=True)
                        t = "tns:%s" % n
                    e.add_attribute('type', t)
            
            parse_element("%s" % method, args and args.items())
            parse_element("%sResponse" % method, returns and returns.items())

            # create messages:
            for m,e in ('Input',''), ('Output','Response'):
                message = wsdl.add_child('wsdl:message')
                message['name'] = "%s%s" % (method, m)
                part = message.add_child("wsdl:part")
                part[:] = {'name': 'parameters', 
                           'element': 'tns:%s%s' % (method,e)}

        # create ports
        portType = wsdl.add_child('wsdl:portType')
        portType['name'] = "%sPortType" % self.name
        for method, (function, returns, args, doc) in self.methods.items():
            op = portType.add_child('wsdl:operation')
            op['name'] = method
            if doc:
                op.add_child("wsdl:documentation", doc)
            input = op.add_child("wsdl:input")
            input['message'] = "tns:%sInput" % method
            output = op.add_child("wsdl:output")
            output['message'] = "tns:%sOutput" % method

        # create bindings
        binding = wsdl.add_child('wsdl:binding')
        binding['name'] = "%sBinding" % self.name
        binding['type'] = "tns:%sPortType" % self.name
        soapbinding = binding.add_child('soap:binding')
        soapbinding['style'] = "document"
        soapbinding['transport'] = "http://schemas.xmlsoap.org/soap/http"
        for method in self.methods.keys():
            op = binding.add_child('wsdl:operation')
            op['name'] = method
            soapop = op.add_child('soap:operation')
            soapop['soapAction'] = self.action
            soapop['style'] = 'document'
            input = op.add_child("wsdl:input")
            ##input.add_attribute('name', "%sInput" % method)
            soapbody = input.add_child("soap:body")
            soapbody["use"] = "literal"
            output = op.add_child("wsdl:output")
            ##output.add_attribute('name', "%sOutput" % method)
            soapbody = output.add_child("soap:body")
            soapbody["use"] = "literal"

        service = wsdl.add_child('wsdl:service')
        service["name"] = "%sService" % self.name
        service.add_child('wsdl:documentation', text=self.documentation)
        port=service.add_child('wsdl:port')
        port["name"] = "%s" % self.name
        port["binding"] = "tns:%sBinding" % self.name
        soapaddress = port.add_child('soap:address')
        soapaddress["location"] = self.location
        return wsdl.as_xml(pretty=True)
Esempio n. 9
0
    def dispatch(self, xml, action=None):
        "Receive and proccess SOAP call"
        # default values:
        prefix = self.prefix
        ret = fault = None
        soap_ns, soap_uri = self.soap_ns, self.soap_uri
        soap_fault_code = 'VersionMismatch'
        name = None
        
        # namespaces = [('model', 'http://model.common.mt.moboperator'), ('external', 'http://external.mt.moboperator')]
        _ns_reversed = dict(((v,k) for k,v in self.namespaces.iteritems())) # Switch keys-values
        # _ns_reversed = {'http://external.mt.moboperator': 'external', 'http://model.common.mt.moboperator': 'model'}
        
        try:
            request = SimpleXMLElement(xml, namespace=self.namespace)
            
            # detect soap prefix and uri (xmlns attributes of Envelope)
            for k, v in request[:]:
                if v in ("http://schemas.xmlsoap.org/soap/envelope/",
                                  "http://www.w3.org/2003/05/soap-env",):
                    soap_ns = request.attributes()[k].localName
                    soap_uri = request.attributes()[k].value
                
                # If the value from attributes on Envelope is in additional namespaces
                elif v in self.namespaces.values():
                    _ns = request.attributes()[k].localName
                    _uri = request.attributes()[k].value
                    _ns_reversed[_uri] = _ns # update with received alias
                    # Now we change 'external' and 'model' to the received forms i.e. 'ext' and 'mod'
                # After that we know how the client has prefixed additional namespaces
            
            ns = NS_RX.findall(xml)
            for k, v in ns:
                if v in self.namespaces.values():
                    _ns_reversed[v] = k
            
            soap_fault_code = 'Client'
            
            # parse request message and get local method
            method = request('Body', ns=soap_uri).children()(0)
            if action:
                # method name = action 
                name = action[len(self.action)+1:-1]
                prefix = self.prefix
            if not action or not name:
                # method name = input message name
                name = method.get_local_name()
                prefix = method.get_prefix()

            log.debug('dispatch method: %s', name)
            function, returns_types, args_types, doc = self.methods[name]
            log.debug('returns_types %s', returns_types)
            
            # de-serialize parameters (if type definitions given)
            if args_types:
                args = method.children().unmarshall(args_types)
            elif args_types is None:
                args = {'request': method} # send raw request
            else:
                args = {} # no parameters
            
            soap_fault_code = 'Server'
            # execute function
            ret = function(**args)
            log.debug('dispathed method returns: %s', ret)

        except Exception: # This shouldn't be one huge try/except
            import sys
            etype, evalue, etb = sys.exc_info()
            log.error(traceback.format_exc())
            if self.debug:
                detail = ''.join(traceback.format_exception(etype, evalue, etb))
                detail += '\n\nXML REQUEST\n\n' + xml
            else:
                detail = None
            fault = {'faultcode': "%s.%s" % (soap_fault_code, etype.__name__), 
                     'faultstring': unicode(evalue), 
                     'detail': detail}

        # build response message
        if not prefix:
            xml = """<%(soap_ns)s:Envelope xmlns:%(soap_ns)s="%(soap_uri)s"/>"""  
        else:
            xml = """<%(soap_ns)s:Envelope xmlns:%(soap_ns)s="%(soap_uri)s"
                       xmlns:%(prefix)s="%(namespace)s"/>"""  
            
        xml %= {    # a %= {} is a shortcut for a = a % {}
            'namespace': self.namespace, 
            'prefix': prefix,
            'soap_ns': soap_ns, 
            'soap_uri': soap_uri
        }
        
        # Now we add extra namespaces
        xml = SoapDispatcher._extra_namespaces(xml, _ns_reversed)
        
        # Change our namespace alias to that given by the client.
        # We put [('model', 'http://model.common.mt.moboperator'), ('external', 'http://external.mt.moboperator')]
        # mix it with {'http://external.mt.moboperator': 'ext', 'http://model.common.mt.moboperator': 'mod'}
        mapping = dict(((k, _ns_reversed[v]) for k,v in self.namespaces.iteritems())) # Switch keys-values and change value
        # and get {'model': u'mod', 'external': u'ext'}
        
        response = SimpleXMLElement(xml, 
                                    namespace=self.namespace,
                                    namespaces_map = mapping,
                                    prefix=prefix)
        
        response['xmlns:xsi'] = "http://www.w3.org/2001/XMLSchema-instance"
        response['xmlns:xsd'] = "http://www.w3.org/2001/XMLSchema"
        
        body = response.add_child("%s:Body" % soap_ns, ns=False)
        
        if fault:
            # generate a Soap Fault (with the python exception)
            body.marshall("%s:Fault" % soap_ns, fault, ns=False)
        else:
            # return normal value
            res = body.add_child("%sResponse" % name, ns=prefix)
            if not prefix:
                res['xmlns'] = self.namespace # add target namespace

            # serialize returned values (response) if type definition available
            if returns_types:
                if not isinstance(ret, dict):
                    res.marshall(returns_types.keys()[0], ret, )
                else:
                    for k,v in ret.items():
                        res.marshall(k, v)
            elif returns_types is None:
                # merge xmlelement returned
                res.import_node(ret)
            elif returns_types == {}:
                log.warning('Given returns_types is an empty dict.')

        return response.as_xml(pretty=self.pretty)
Esempio n. 10
0
    def dispatch(self, xml, action=None):
        """Receive and process SOAP call"""
        # default values:
        prefix = self.prefix
        ret = fault = None
        soap_ns, soap_uri = self.soap_ns, self.soap_uri
        soap_fault_code = 'VersionMismatch'
        name = None

        # namespaces = [('model', 'http://model.common.mt.moboperator'), ('external', 'http://external.mt.moboperator')]
        _ns_reversed = dict(
            ((v, k)
             for k, v in self.namespaces.iteritems()))  # Switch keys-values
        # _ns_reversed = {'http://external.mt.moboperator': 'external', 'http://model.common.mt.moboperator': 'model'}

        try:
            request = SimpleXMLElement(xml, namespace=self.namespace)

            # detect soap prefix and uri (xmlns attributes of Envelope)
            for k, v in request[:]:
                if v in (
                        "http://schemas.xmlsoap.org/soap/envelope/",
                        "http://www.w3.org/2003/05/soap-env",
                ):
                    soap_ns = request.attributes()[k].localName
                    soap_uri = request.attributes()[k].value

                # If the value from attributes on Envelope is in additional namespaces
                elif v in self.namespaces.values():
                    _ns = request.attributes()[k].localName
                    _uri = request.attributes()[k].value
                    _ns_reversed[_uri] = _ns  # update with received alias
                    # Now we change 'external' and 'model' to the received forms i.e. 'ext' and 'mod'
                # After that we know how the client has prefixed additional namespaces

            ns = NS_RX.findall(xml)
            for k, v in ns:
                if v in self.namespaces.values():
                    _ns_reversed[v] = k

            soap_fault_code = 'Client'

            # parse request message and get local method
            method = request('Body', ns=soap_uri).children()(0)
            if action:
                # method name = action
                name = action[len(self.action) + 1:-1]
                prefix = self.prefix
            if not action or not name:
                # method name = input message name
                name = method.get_local_name()
                prefix = method.get_prefix()

            log.debug('dispatch method: %s', name)
            function, returns_types, args_types, doc = self.methods[name]
            log.debug('returns_types %s', returns_types)

            # de-serialize parameters (if type definitions given)
            if args_types:
                args = method.children().unmarshall(args_types)
            elif args_types is None:
                args = {'request': method}  # send raw request
            else:
                args = {}  # no parameters

            soap_fault_code = 'Server'
            # execute function
            ret = function(**args)
            log.debug('dispathed method returns: %s', ret)

        except Exception:  # This shouldn't be one huge try/except
            import sys
            etype, evalue, etb = sys.exc_info()
            log.error(traceback.format_exc())
            if self.debug:
                detail = ''.join(traceback.format_exception(
                    etype, evalue, etb))
                detail += '\n\nXML REQUEST\n\n' + xml
            else:
                detail = None
            fault = {
                'faultcode': "%s.%s" % (soap_fault_code, etype.__name__),
                'faultstring': unicode(evalue),
                'detail': detail
            }

        # build response message
        if not prefix:
            xml = """<%(soap_ns)s:Envelope xmlns:%(soap_ns)s="%(soap_uri)s"/>"""
        else:
            xml = """<%(soap_ns)s:Envelope xmlns:%(soap_ns)s="%(soap_uri)s"
                       xmlns:%(prefix)s="%(namespace)s"/>"""

        xml %= {  # a %= {} is a shortcut for a = a % {}
            'namespace': self.namespace,
            'prefix': prefix,
            'soap_ns': soap_ns,
            'soap_uri': soap_uri
        }

        # Now we add extra namespaces
        xml = SoapDispatcher._extra_namespaces(xml, _ns_reversed)

        # Change our namespace alias to that given by the client.
        # We put [('model', 'http://model.common.mt.moboperator'), ('external', 'http://external.mt.moboperator')]
        # mix it with {'http://external.mt.moboperator': 'ext', 'http://model.common.mt.moboperator': 'mod'}
        mapping = dict(
            ((k, _ns_reversed[v]) for k, v in self.namespaces.iteritems()
             ))  # Switch keys-values and change value
        # and get {'model': u'mod', 'external': u'ext'}

        response = SimpleXMLElement(xml,
                                    namespace=self.namespace,
                                    namespaces_map=mapping,
                                    prefix=prefix)

        response['xmlns:xsi'] = "http://www.w3.org/2001/XMLSchema-instance"
        response['xmlns:xsd'] = "http://www.w3.org/2001/XMLSchema"

        body = response.add_child("%s:Body" % soap_ns, ns=False)

        if fault:
            # generate a Soap Fault (with the python exception)
            body.marshall("%s:Fault" % soap_ns, fault, ns=False)
        else:
            # return normal value
            res = body.add_child("%sResponse" % name, ns=prefix)
            if not prefix:
                res['xmlns'] = self.namespace  # add target namespace

            # serialize returned values (response) if type definition available
            if returns_types:
                if not isinstance(ret, dict):
                    res.marshall(
                        returns_types.keys()[0],
                        ret,
                    )
                else:
                    for k, v in ret.items():
                        res.marshall(k, v)
            elif returns_types is None:
                # merge xmlelement returned
                res.import_node(ret)
            elif returns_types == {}:
                log.warning('Given returns_types is an empty dict.')

        return response.as_xml(pretty=self.pretty)
Esempio n. 11
0
 def call(self, method, *args, **kwargs):
     "Prepare xml request and make SOAP call, returning a SimpleXMLElement"
     #TODO: method != input_message
     # Basic SOAP request:
     xml = self.__xml % dict(method=method,
                             namespace=self.namespace,
                             ns=self.__ns,
                             soap_ns=self.__soap_ns,
                             soap_uri=soap_namespaces[self.__soap_ns])
     request = SimpleXMLElement(xml,
                                namespace=self.__ns and self.namespace,
                                prefix=self.__ns)
     # serialize parameters
     if kwargs:
         parameters = kwargs.items()
     else:
         parameters = args
     if parameters and isinstance(parameters[0], SimpleXMLElement):
         # merge xmlelement parameter ("raw" - already marshalled)
         for param in parameters[0].children():
             getattr(request, method).import_node(param)
     elif parameters:
         # marshall parameters:
         for k, v in parameters:  # dict: tag=valor
             getattr(request, method).marshall(k, v)
     elif not self.__soap_server in ('oracle', ) or self.__soap_server in (
             'jbossas6', ):
         # JBossAS-6 requires no empty method parameters!
         delattr(request(
             "Body",
             ns=soap_namespaces.values(),
         ), method)
     # construct header and parameters (if not wsdl given) except wsse
     if self.__headers and not self.services:
         self.__call_headers = dict([(k, v)
                                     for k, v in self.__headers.items()
                                     if not k.startswith("wsse:")])
     # always extract WS Security header and send it
     if 'wsse:Security' in self.__headers:
         #TODO: namespaces too hardwired, clean-up...
         header = request(
             'Header',
             ns=soap_namespaces.values(),
         )
         k = 'wsse:Security'
         v = self.__headers[k]
         header.marshall(k, v, ns=False, add_children_ns=False)
         header(
             k
         )['xmlns:wsse'] = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
         #<wsse:UsernameToken xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'>
     if self.__call_headers:
         header = request(
             'Header',
             ns=soap_namespaces.values(),
         )
         for k, v in self.__call_headers.items():
             ##if not self.__ns:
             ##    header['xmlns']
             header.marshall(k, v, ns=self.__ns, add_children_ns=False)
     self.xml_request = request.as_xml()
     self.xml_response = self.send(method, self.xml_request)
     response = SimpleXMLElement(self.xml_response,
                                 namespace=self.namespace)
     if self.exceptions and response(
             "Fault", ns=soap_namespaces.values(), error=False):
         raise SoapFault(unicode(response.faultcode),
                         unicode(response.faultstring))
     return response
Esempio n. 12
0
    def call(self, method, *args, **kwargs):
        "Prepare xml request and make SOAP call, returning a SimpleXMLElement"
        #TODO: method != input_message
        # Basic SOAP request:
        if kwargs:
            parameters = kwargs.items()
            username, password = args
        else:
            (username, password), parameters = args

        created = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')

        expires = (datetime.utcnow() +
                   timedelta(0, 300)).strftime('%Y-%m-%dT%H:%M:%SZ')

        header = self.header
        try:
            header = header % dict(Username=username,
                                   Password=password,
                                   Created=created,
                                   Expires=expires)
        except KeyError:
            pass

        xml = self.__xml % dict(method=method,
                                namespace=self.namespace,
                                ns=self.__ns,
                                header=header,
                                soap_ns=self.__soap_ns,
                                soap_uri=soap_namespaces[self.__soap_ns],
                                body_xmlns=self.body_xmlns)

        request = SimpleXMLElement(xml,
                                   namespace=self.__ns and self.namespace,
                                   prefix=self.__ns)
        # serialize parameters

        if parameters and isinstance(parameters[0], SimpleXMLElement):
            # merge xmlelement parameter ("raw" - already marshalled)
            for param in parameters[0].children():
                getattr(request, method).import_node(param)
        else:
            # marshall parameters:
            for k, v in parameters:  # dict: tag=valor
                getattr(request, method).marshall(k, v)

        self.xml_request = request.as_xml()

        try:
            self.xml_response = self.send(method, self.xml_request)
            response = SimpleXMLElement(self.xml_response,
                                        namespace=self.namespace)
            if self.exceptions and response(
                    "Fault", ns=soap_namespaces.values(), error=False):
                raise SoapFault(unicode(response.faultcode),
                                unicode(response.faultstring))
            return response
        except urllib2.HTTPError, error:
            self.xml_response = error.read()
            try:
                response = SimpleXMLElement(self.xml_response,
                                            namespace=self.namespace)
            except:
                raise error
            if self.exceptions and response(
                    "Fault", ns=soap_namespaces.values(), error=False):
                try:
                    detail = str(response.detail.Message)
                except:
                    detail = ""
                if "ID3242" in detail:
                    raise NotAuthorizedError()
                else:
                    raise SoapFault(unicode(response.faultcode),
                                    unicode(response.faultstring))
            else:
                raise error
Esempio n. 13
0
    def call(self, method, *args, **kwargs):
        """Prepare xml request and make SOAP call, returning a SimpleXMLElement.

        If a keyword argument called "headers" is passed with a value of a
        SimpleXMLElement object, then these headers will be inserted into the
        request.
        """
        # TODO: method != input_message
        # Basic SOAP request:
        xml = self.__xml % dict(
            method=method,
            namespace=self.namespace,
            ns=self.__ns,
            soap_ns=self.__soap_ns,
            soap_uri=soap_namespaces[self.__soap_ns],
        )
        request = SimpleXMLElement(xml, namespace=self.__ns and self.namespace, prefix=self.__ns)

        try:
            request_headers = kwargs.pop("headers")
        except KeyError:
            request_headers = None

        # serialize parameters
        if kwargs:
            parameters = kwargs.items()
        else:
            parameters = args
        if parameters and isinstance(parameters[0], SimpleXMLElement):
            # merge xmlelement parameter ("raw" - already marshalled)
            if parameters[0].children() is not None:
                for param in parameters[0].children():
                    getattr(request, method).import_node(param)
        elif parameters:
            # marshall parameters:
            for k, v in parameters:  # dict: tag=valor
                getattr(request, method).marshall(k, v)
        elif not self.__soap_server in ("oracle",) or self.__soap_server in ("jbossas6",):
            # JBossAS-6 requires no empty method parameters!
            delattr(request("Body", ns=soap_namespaces.values()), method)

        # construct header and parameters (if not wsdl given) except wsse
        if self.__headers and not self.services:
            self.__call_headers = dict([(k, v) for k, v in self.__headers.items() if not k.startswith("wsse:")])
        # always extract WS Security header and send it
        if "wsse:Security" in self.__headers:
            # TODO: namespaces too hardwired, clean-up...
            header = request("Header", ns=soap_namespaces.values())
            k = "wsse:Security"
            v = self.__headers[k]
            header.marshall(k, v, ns=False, add_children_ns=False)
            header(k)[
                "xmlns:wsse"
            ] = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
            # <wsse:UsernameToken xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'>
        if self.__call_headers:
            header = request("Header", ns=soap_namespaces.values())
            for k, v in self.__call_headers.items():
                ##if not self.__ns:
                ##    header['xmlns']
                if isinstance(v, SimpleXMLElement):
                    # allows a SimpleXMLElement to be constructed and inserted
                    # rather than a dictionary. marshall doesn't allow ns: prefixes
                    # in dict key names
                    header.import_node(v)
                else:
                    header.marshall(k, v, ns=self.__ns, add_children_ns=False)
        if request_headers:
            header = request("Header", ns=soap_namespaces.values())
            for subheader in request_headers.children():
                header.import_node(subheader)

        self.xml_request = request.as_xml()
        self.xml_response = self.send(method, self.xml_request)
        response = SimpleXMLElement(self.xml_response, namespace=self.namespace, jetty=self.__soap_server in ("jetty",))
        if self.exceptions and response("Fault", ns=soap_namespaces.values(), error=False):
            raise SoapFault(unicode(response.faultcode), unicode(response.faultstring))
        return response