def build_schema(self, types=None): schema_nodes = Application.build_schema(self, types) if types is None: pref_tns = soaplib.get_namespace_prefix(self.get_tns()) logger.debug("generating schema for targetNamespace=%r, prefix: %r" % (self.get_tns(), pref_tns)) tmp_dir_name = tempfile.mkdtemp() # serialize nodes to files for k,v in schema_nodes.items(): file_name = '%s/%s.xsd' % (tmp_dir_name, k) f = open(file_name, 'w') etree.ElementTree(v).write(f, pretty_print=True) f.close() logger.debug("writing %r for ns %s" % (file_name, soaplib.nsmap[k])) f = open('%s/%s.xsd' % (tmp_dir_name, pref_tns), 'r') logger.debug("building schema...") self.schema = etree.XMLSchema(etree.parse(f)) logger.debug("schema %r built, cleaning up..." % self.schema) f.close() shutil.rmtree(tmp_dir_name) logger.debug("removed %r" % tmp_dir_name) return self.schema
def build_schema(self, types=None): """ Build application schema specifically for xml validation purposes. """ schema_nodes = Application.build_schema(self, types) if types is None: pref_tns = soaplib.get_namespace_prefix(self.get_tns()) logger.debug("generating schema for targetNamespace=%r, prefix: %r" % (self.get_tns(), pref_tns)) tmp_dir_name = tempfile.mkdtemp() # serialize nodes to files for k,v in schema_nodes.items(): file_name = '%s/%s.xsd' % (tmp_dir_name, k) f = open(file_name, 'w') etree.ElementTree(v).write(f, pretty_print=True) f.close() logger.debug("writing %r for ns %s" % (file_name, soaplib.nsmap[k])) f = open('%s/%s.xsd' % (tmp_dir_name, pref_tns), 'r') logger.debug("building schema...") self.schema = etree.XMLSchema(etree.parse(f)) logger.debug("schema %r built, cleaning up..." % self.schema) f.close() shutil.rmtree(tmp_dir_name) logger.debug("removed %r" % tmp_dir_name) return self.schema
def __build_schema_nodes(self, schema_entries, types=None): """ Fill individual <schema> nodes for every service that are part of this app. """ schema_nodes = {} for pref in schema_entries.namespaces: schema = get_schema_node(pref, schema_nodes, types) # append import tags for namespace in schema_entries.imports[pref]: import_ = etree.SubElement(schema, "{%s}import"% soaplib.ns_xsd) import_.set("namespace", namespace) if types is None: import_.set('schemaLocation', "%s.xsd" % soaplib.get_namespace_prefix(namespace)) # append element tags for node in schema_entries.namespaces[pref].elements.values(): schema.append(node) # append simpleType and complexType tags for node in schema_entries.namespaces[pref].types.values(): schema.append(node) return schema_nodes
def __add_callbacks(self, root, types, service_name, url): ns_xsd = soaplib.ns_xsd ns_wsa = soaplib.ns_wsa ns_wsdl = soaplib.ns_wsdl ns_soap = soaplib.ns_soap ns_tns = self.get_tns() pref_tns = soaplib.get_namespace_prefix(ns_tns) cb_port_type = None # add necessary async headers # WS-Addressing -> RelatesTo ReplyTo MessageID # callback porttype if self._has_callbacks(): wsa_schema = etree.SubElement(types, "{%s}schema" % ns_xsd) wsa_schema.set("targetNamespace", '%sCallback' % ns_tns) wsa_schema.set("elementFormDefault", "qualified") import_ = etree.SubElement(wsa_schema, "{%s}import" % ns_xsd) import_.set("namespace", ns_wsa) import_.set("schemaLocation", ns_wsa) relt_message = etree.SubElement(root, '{%s}message' % ns_wsdl) relt_message.set('name', 'RelatesToHeader') relt_part = etree.SubElement(relt_message, '{%s}part' % ns_wsdl) relt_part.set('name', 'RelatesTo') relt_part.set('element', '%s:RelatesTo' % _pref_wsa) reply_message = etree.SubElement(root, '{%s}message' % ns_wsdl) reply_message.set('name', 'ReplyToHeader') reply_part = etree.SubElement(reply_message, '{%s}part' % ns_wsdl) reply_part.set('name', 'ReplyTo') reply_part.set('element', '%s:ReplyTo' % _pref_wsa) id_header = etree.SubElement(root, '{%s}message' % ns_wsdl) id_header.set('name', 'MessageIDHeader') id_part = etree.SubElement(id_header, '{%s}part' % ns_wsdl) id_part.set('name', 'MessageID') id_part.set('element', '%s:MessageID' % _pref_wsa) # make portTypes cb_port_type = etree.SubElement(root, '{%s}portType' % ns_wsdl) cb_port_type.set('name', '%sCallback' % service_name) cb_service_name = '%sCallback' % service_name cb_service = etree.SubElement(root, '{%s}service' % ns_wsdl) cb_service.set('name', cb_service_name) cb_wsdl_port = etree.SubElement(cb_service, '{%s}port' % ns_wsdl) cb_wsdl_port.set('name', cb_service_name) cb_wsdl_port.set('binding', '%s:%s' % (pref_tns, cb_service_name)) cb_address = etree.SubElement(cb_wsdl_port, '{%s}address' % ns_soap) cb_address.set('location', url) return cb_port_type
def add_service(self, root, service_name, types, url, service): ns_wsdl = soaplib.ns_wsdl ns_soap = soaplib.ns_soap ns_tns = self.get_tns() pref_tns = soaplib.get_namespace_prefix(ns_tns) wsdl_port = etree.SubElement(service, '{%s}port' % ns_wsdl) wsdl_port.set('name', service_name) wsdl_port.set('binding', '%s:%s' % (pref_tns, service_name)) addr = etree.SubElement(wsdl_port, '{%s}address' % ns_soap) addr.set('location', url)
def add_service(self, root, service_name, types, url, service): """ Add service node to the wsdl. """ pref_tns = soaplib.get_namespace_prefix(self.get_tns()) wsdl_port = etree.SubElement(service, '{%s}port' % soaplib.ns_wsdl) wsdl_port.set('name', service_name) wsdl_port.set('binding', '%s:%s' % (pref_tns, service_name)) addr = etree.SubElement(wsdl_port, '{%s}address' % soaplib.ns_soap) addr.set('location', url)
def add_partner_link(self, root, service_name, types, url, plink): """ Add the partnerLinkType node to the wsdl. """ ns_plink = soaplib.ns_plink pref_tns = soaplib.get_namespace_prefix(self.get_tns()) role = etree.SubElement(plink, '{%s}role' % ns_plink) role.set('name', service_name) plink_port_type = etree.SubElement(role, '{%s}portType' % ns_plink) plink_port_type.set('name', '%s:%s' % (pref_tns, service_name))
def add_to_schema(cls, schema_entries): if not schema_entries.has_class(cls): simple_type = etree.Element('{%s}simpleType' % _ns_xs) simple_type.set('name', cls.get_type_name()) restriction = etree.SubElement(simple_type, '{%s}restriction' % _ns_xs) restriction.set('base', '%s:string' % soaplib.get_namespace_prefix(soaplib.ns_xsd)) for v in values: enumeration = etree.SubElement(restriction, '{%s}enumeration' % _ns_xs) enumeration.set('value', v) schema_entries.add_simple_type(cls, simple_type)
def add_partner_link(self, root, service_name, types, url, plink): ns_plink = soaplib.ns_plink ns_tns = self.get_tns() pref_tns = soaplib.get_namespace_prefix(ns_tns) role = etree.SubElement(plink, '{%s}role' % ns_plink) role.set('name', service_name) plink_port_type = etree.SubElement(role, '{%s}portType' % ns_plink) plink_port_type.set('name', '%s:%s' % (pref_tns, service_name)) if self._has_callbacks(): role = etree.SubElement(plink, '{%s}role' % ns_plink) role.set('name', '%sCallback' % service_name) plink_port_type = etree.SubElement(role, '{%s}portType' % ns_plink) plink_port_type.set('name', '%s:%sCallback' % (pref_tns, service_name))
def get_namespace_prefix(cls): ns = cls.get_namespace() retval = soaplib.get_namespace_prefix(ns) return retval
def __build_wsdl(self, url): ns_wsdl = soaplib.ns_wsdl ns_soap = soaplib.ns_soap ns_plink = soaplib.ns_plink ns_tns = self.get_tns() pref_tns = soaplib.get_namespace_prefix(ns_tns) #'tns' # FIXME: this can be enabled when soaplib.nsmap is no longer global #soaplib.set_namespace_prefix(ns_tns, pref_tns) # FIXME: doesn't look so robust url = url.replace('.wsdl', '') service_name = self.get_name() # create wsdl root node root = etree.Element("{%s}definitions" % ns_wsdl, nsmap=soaplib.nsmap) root.set('targetNamespace', ns_tns) root.set('name', service_name) # create types node types = etree.SubElement(root, "{%s}types" % ns_wsdl) self.build_schema(types) messages = set() for s in self.services: s=self.get_service(s,None) s.add_messages_for_methods(root, messages) if self._with_plink: # create plink node plink = etree.SubElement(root, '{%s}partnerLinkType' % ns_plink) plink.set('name', service_name) self.add_partner_link(root, service_name, types, url, plink) # create service node service = etree.SubElement(root, '{%s}service' % ns_wsdl) service.set('name', service_name) self.add_service(root, service_name, types, url, service) # create portType node port_type = etree.SubElement(root, '{%s}portType' % ns_wsdl) port_type.set('name', service_name) # create binding nodes binding = etree.SubElement(root, '{%s}binding' % ns_wsdl) binding.set('name', service_name) binding.set('type', '%s:%s'% (pref_tns, service_name)) soap_binding = etree.SubElement(binding, '{%s}binding' % ns_soap) soap_binding.set('style', 'document') soap_binding.set('transport', 'http://schemas.xmlsoap.org/soap/http') cb_binding = None for s in self.services: s=self.get_service(s) s.add_port_type(root, service_name, types, url, port_type) cb_binding = s.add_bindings_for_methods(root, service_name, types, url, binding, cb_binding) self.__wsdl = etree.tostring(root, xml_declaration=True, encoding="UTF-8") return self.__wsdl
def add_bindings_for_methods(self, root, service_name, types, url, binding, cb_binding=None): ''' A private method for adding bindings to the wsdl @param the root element of the wsdl @param the name of this service ''' ns_wsdl = soaplib.ns_wsdl ns_soap = soaplib.ns_soap pref_tns = soaplib.get_namespace_prefix(self.get_tns()) if self._has_callbacks(): if cb_binding is None: cb_binding = etree.SubElement(root, '{%s}binding' % ns_wsdl) cb_binding.set('name', '%sCallback' % service_name) cb_binding.set('type', 'typens:%sCallback' % service_name) soap_binding = etree.SubElement(cb_binding, '{%s}binding' % ns_soap) soap_binding.set('transport', 'http://schemas.xmlsoap.org/soap/http') for method in self.public_methods: operation = etree.Element('{%s}operation' % ns_wsdl) operation.set('name', method.name) soap_operation = etree.SubElement(operation, '{%s}operation' % ns_soap) soap_operation.set('soapAction', method.public_name) soap_operation.set('style', 'document') # get input input = etree.SubElement(operation, '{%s}input' % ns_wsdl) input.set('name', method.in_message.get_type_name()) soap_body = etree.SubElement(input, '{%s}body' % ns_soap) soap_body.set('use', 'literal') # get input soap header in_header = method.in_header if in_header is None: in_header = self.__in_header__ if not (in_header is None): soap_header = etree.SubElement(input, '{%s}header' % ns_soap) soap_header.set('use', 'literal') soap_header.set('message', in_header.get_type_name_ns()) soap_header.set('part', in_header.get_type_name()) if not (method.is_async or method.is_callback): output = etree.SubElement(operation, '{%s}output' % ns_wsdl) output.set('name', method.out_message.get_type_name()) soap_body = etree.SubElement(output, '{%s}body' % ns_soap) soap_body.set('use', 'literal') # get input soap header out_header = method.in_header if out_header is None: out_header = self.__in_header__ if not (out_header is None): soap_header = etree.SubElement(output, '{%s}header' % ns_soap) soap_header.set('use', 'literal') soap_header.set('message', out_header.get_type_name_ns()) soap_header.set('part', out_header.get_type_name()) if method.is_callback: relates_to = etree.SubElement(input, '{%s}header' % ns_soap) relates_to.set('message', '%s:RelatesToHeader' % pref_tns) relates_to.set('part', 'RelatesTo') relates_to.set('use', 'literal') cb_binding.append(operation) else: if method.is_async: rt_header = etree.SubElement(input,'{%s}header' % ns_soap) rt_header.set('message', '%s:ReplyToHeader' % pref_tns) rt_header.set('part', 'ReplyTo') rt_header.set('use', 'literal') mid_header = etree.SubElement(input, '{%s}header'% ns_soap) mid_header.set('message', '%s:MessageIDHeader' % pref_tns) mid_header.set('part', 'MessageID') mid_header.set('use', 'literal') binding.append(operation) return cb_binding
def __build_wsdl(self, url): """ Build the wsdl for the application. """ ns_wsdl = soaplib.ns_wsdl ns_soap = soaplib.ns_soap ns_plink = soaplib.ns_plink ns_tns = self.get_tns() pref_tns = soaplib.get_namespace_prefix(ns_tns) #'tns' # FIXME: this can be enabled when soaplib.nsmap is no longer global #soaplib.set_namespace_prefix(ns_tns, pref_tns) # FIXME: doesn't look so robust url = url.replace('.wsdl', '') service_name = self.get_name() # create wsdl root node root = etree.Element("{%s}definitions" % ns_wsdl, nsmap=soaplib.nsmap) root.set('targetNamespace', ns_tns) root.set('name', service_name) # create types node types = etree.SubElement(root, "{%s}types" % ns_wsdl) self.build_schema(types) messages = set() for s in self.services: s=self.get_service(s,None) s.add_messages_for_methods(root, messages) if self._with_plink: # create plink node plink = etree.SubElement(root, '{%s}partnerLinkType' % ns_plink) plink.set('name', service_name) self.add_partner_link(root, service_name, types, url, plink) # create service node service = etree.SubElement(root, '{%s}service' % ns_wsdl) service.set('name', service_name) self.add_service(root, service_name, types, url, service) # create portType node port_type = etree.SubElement(root, '{%s}portType' % ns_wsdl) port_type.set('name', service_name) # create binding nodes binding = etree.SubElement(root, '{%s}binding' % ns_wsdl) binding.set('name', service_name) binding.set('type', '%s:%s'% (pref_tns, service_name)) soap_binding = etree.SubElement(binding, '{%s}binding' % ns_soap) soap_binding.set('style', 'document') soap_binding.set('transport', 'http://schemas.xmlsoap.org/soap/http') for s in self.services: s = self.get_service(s) s.add_port_type(root, service_name, types, url, port_type) s.add_bindings_for_methods(root, service_name, types, url, binding) self.__wsdl = etree.tostring(root, xml_declaration=True, encoding="UTF-8") return self.__wsdl