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__