Exemple #1
0
    def wsdl(self, url):
        '''
        This method generates and caches the wsdl for this object based
        on the soap methods designated by the soapmethod or soapdocument
        descriptors
        @param url the url that this service can be found at.  This must be
        passed in by the caller because this object has no notion of the
        server environment in which it runs.
        @returns the string of the wsdl
        '''
        if not self.__wsdl__ == None:
            # return the cached __wsdl__
            return self.__wsdl__
        url = url.replace('.wsdl', '')
        # otherwise build it
        serviceName = self.__class__.__name__.split('.')[-1]

        tns = self.__tns__
        methods = self.methods()
        hasCallbacks = self._hasCallbacks()

        nsmap = NamespaceLookup(tns, True)
        if hasCallbacks:
            nsmap.set('wsa',
                'http://schemas.xmlsoap.org/ws/2003/03/addressing')

        root = create_xml_element(
            "definitions", nsmap, 'http://schemas.xmlsoap.org/wsdl/')
        root.set('targetNamespace', tns)
        root.set('name', serviceName)

        types = create_xml_subelement(root, "types")

        self._add_schema(types, methods, nsmap)
        self._add_messages_for_methods(root, methods, nsmap)

        # add necessary async headers
        # WS-Addressing -> RelatesTo ReplyTo MessageID
        # callback porttype
        if hasCallbacks:
            wsaSchemaNode = create_xml_subelement(types, "schema")
            wsaSchemaNode.set("targetNamespace", tns+'Callback')
            wsaSchemaNode.set("xmlns", "http://www.w3.org/2001/XMLSchema")
            wsaSchemaNode.set("elementFormDefault", "qualified")

            importNode = create_xml_subelement(wsaSchemaNode, "import")
            importNode.set("namespace",
                "http://schemas.xmlsoap.org/ws/2003/03/addressing")
            importNode.set("schemaLocation",
                "http://schemas.xmlsoap.org/ws/2003/03/addressing/")


            reltMessage = create_xml_subelement(root, 'message')
            reltMessage.set('name', 'RelatesToHeader')
            reltPart = create_xml_subelement(reltMessage, 'part')
            reltPart.set('name', 'RelatesTo')
            reltPart.set('element', 'wsa:RelatesTo')

            replyMessage = create_xml_subelement(root, 'message')
            replyMessage.set('name', 'ReplyToHeader')
            replyPart = create_xml_subelement(replyMessage, 'part')
            replyPart.set('name', 'ReplyTo')
            replyPart.set('element', 'wsa:ReplyTo')

            idHeader = create_xml_subelement(root, 'message')
            idHeader.set('name', 'MessageIDHeader')
            idPart = create_xml_subelement(idHeader, 'part')
            idPart.set('name', 'MessageID')
            idPart.set('element', 'wsa:MessageID')

            # make portTypes
            callbackPortType = create_xml_subelement(root, 'portType')
            callbackPortType.set('name', '%sCallback' % serviceName)

            cbServiceName = '%sCallback' % serviceName
            cbService = create_xml_subelement(root, 'service')
            cbService.set('name', cbServiceName)
            cbWsdlPort = create_xml_subelement(cbService, 'port')
            cbWsdlPort.set('name', cbServiceName)
            cbWsdlPort.set('binding', 'tns:%s' % cbServiceName)
            cbAddr = create_xml_subelement(cbWsdlPort,
                nsmap.get('soap') + 'address')
            cbAddr.set('location', url)


        serviceName = self.__class__.__name__.split('.')[-1]
        portType = create_xml_subelement(root, 'portType')
        portType.set('name', serviceName)
        for method in methods:
            if method.isCallback:
                operation = create_xml_subelement(callbackPortType,
                    'operation')
            else:
                operation = create_xml_subelement(portType, 'operation')

            operation.set('name', method.name)
            params = []
            for name, param in method.inMessage.params:
                params.append(name)

            documentation = create_xml_subelement(operation, 'documentation')
            documentation.text = method.doc
            operation.set('parameterOrder', method.inMessage.typ)
            opInput = create_xml_subelement(operation, 'input')
            opInput.set('name', method.inMessage.typ)
            opInput.set('message', 'tns:%s' % method.inMessage.typ)

            if (len(method.outMessage.params) > 0 and
                not method.isCallback and not method.isAsync):
                opOutput = create_xml_subelement(operation, 'output')
                opOutput.set('name', method.outMessage.typ)
                opOutput.set('message', 'tns:%s' % method.outMessage.typ)

        # make partner link
        plink = create_xml_subelement(root,
            nsmap.get('plnk') + 'partnerLinkType')
        plink.set('name', serviceName)
        role = create_xml_subelement(plink,
            nsmap.get('plnk') + 'role')
        role.set('name', serviceName)
        plinkPortType = create_xml_subelement(role,
            nsmap.get('plnk') + 'portType')
        plinkPortType.set('name', 'tns:%s' % serviceName)

        if hasCallbacks:
            role = create_xml_subelement(plink, nsmap.get('plnk') + 'role')
            role.set('name', '%sCallback' % serviceName)
            plinkPortType = create_xml_subelement(role,
                nsmap.get('plnk') + 'portType')
            plinkPortType.set('name', 'tns:%sCallback' % serviceName)

        self._add_bindings_for_methods(root, serviceName, methods, nsmap)

        service = create_xml_subelement(root, 'service')
        service.set('name', serviceName)
        wsdlPort = create_xml_subelement(service, 'port')
        wsdlPort.set('name', serviceName)
        wsdlPort.set('binding', 'tns:%s' % serviceName)
        addr = create_xml_subelement(wsdlPort, nsmap.get('soap') + 'address')
        addr.set('location', url)

        wsdl = ElementTree.tostring(root)
        wsdl = "<?xml version='1.0' encoding='utf-8' ?>%s" % (wsdl)

        #cache the wsdl for next time
        self.__wsdl__ = wsdl
        return self.__wsdl__