Welcome to the "trac"-ing site of soap4r!
[soap4r] [httpclient] [openpgp4u] [pkcs1] [logger] [csv] [vtr]

root/branches/1_5/lib/wsdl/soap/definitions.rb

Revision 1983, 6.9 kB (checked in by nahi, 1 year ago)
  • illegal marshaling a request for rpc/literal + parameter is a built-in basetype of XML Schema + message is defined as "type" (not "element"). fixed. closes #434.
  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision
Line 
1 # WSDL4R - WSDL additional definitions for SOAP.
2 # Copyright (C) 2000-2007  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
3
4 # This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
5 # redistribute it and/or modify it under the same terms of Ruby's license;
6 # either the dual license version in 2003, or any later version.
7
8
9 require 'wsdl/info'
10 require 'xsd/namedelements'
11 require 'soap/mapping'
12
13
14 module WSDL
15
16
17 class Definitions < Info
18   def self.soap_rpc_complextypes
19     types = XSD::NamedElements.new
20     types << array_complextype
21     types << fault_complextype
22     types << exception_complextype
23     types
24   end
25
26   def self.array_complextype
27     type = XMLSchema::ComplexType.new(::SOAP::ValueArrayName)
28     type.complexcontent = XMLSchema::ComplexContent.new
29     type.complexcontent.restriction = XMLSchema::ComplexRestriction.new
30     type.complexcontent.restriction.base = ::SOAP::ValueArrayName
31     attr = XMLSchema::Attribute.new
32     attr.ref = ::SOAP::AttrArrayTypeName
33     anyarray = XSD::QName.new(
34       XSD::AnyTypeName.namespace,
35       XSD::AnyTypeName.name + '[]')
36     attr.arytype = anyarray
37     type.complexcontent.restriction.attributes << attr
38     type
39   end
40
41 =begin
42 <xs:complexType name="Fault" final="extension">
43   <xs:sequence>
44     <xs:element name="faultcode" type="xs:QName" />
45     <xs:element name="faultstring" type="xs:string" />
46     <xs:element name="faultactor" type="xs:anyURI" minOccurs="0" />
47     <xs:element name="detail" type="tns:detail" minOccurs="0" />
48   </xs:sequence>
49 </xs:complexType>
50 =end
51   def self.fault_complextype
52     type = XMLSchema::ComplexType.new(::SOAP::EleFaultName)
53     faultcode = XMLSchema::Element.new(::SOAP::EleFaultCodeName, XSD::XSDQName::Type)
54     faultstring = XMLSchema::Element.new(::SOAP::EleFaultStringName, XSD::XSDString::Type)
55     faultactor = XMLSchema::Element.new(::SOAP::EleFaultActorName, XSD::XSDAnyURI::Type)
56     faultactor.minoccurs = 0
57     detail = XMLSchema::Element.new(::SOAP::EleFaultDetailName, XSD::AnyTypeName)
58     detail.minoccurs = 0
59     type.all_elements = [faultcode, faultstring, faultactor, detail]
60     type.final = 'extension'
61     type
62   end
63
64   def self.exception_complextype
65     type = XMLSchema::ComplexType.new(XSD::QName.new(
66         ::SOAP::Mapping::RubyCustomTypeNamespace, 'SOAPException'))
67     excn_name = XMLSchema::Element.new(XSD::QName.new(nil, 'excn_type_name'), XSD::XSDString::Type)
68     cause = XMLSchema::Element.new(XSD::QName.new(nil, 'cause'), XSD::AnyTypeName)
69     backtrace = XMLSchema::Element.new(XSD::QName.new(nil, 'backtrace'), ::SOAP::ValueArrayName)
70     message = XMLSchema::Element.new(XSD::QName.new(nil, 'message'), XSD::XSDString::Type)
71     type.all_elements = [excn_name, cause, backtrace, message]
72     type
73   end
74
75   def soap_rpc_complextypes(binding)
76     types = rpc_operation_complextypes(binding)
77     types + self.class.soap_rpc_complextypes
78   end
79
80   def collect_faulttypes
81     result = []
82     collect_fault_messages.each do |name|
83       faultparts = message(name).parts
84       if faultparts.size != 1
85         raise RuntimeError.new("Expecting fault message \"#{name}\" to have ONE part")
86       end
87       fault_part = faultparts[0]
88       # WS-I Basic Profile Version 1.1 (R2205) requires fault message parts
89       # to refer to elements rather than types
90       faulttype = fault_part.element
91       if not faulttype
92         warn("Fault message \"#{name}\" part \"#{fault_part.name}\" must specify an \"element\" attribute")
93         faulttype = fault_part.type
94       end
95       if faulttype and result.index(faulttype).nil?
96         result << faulttype
97       end
98     end
99     result
100   end
101
102 private
103
104   def get_fault_binding(op_binding, fault_name)
105     op_binding.fault.each do |fault|
106       return fault if fault.name == fault_name
107     end
108     return nil
109   end
110
111   def op_binding_declares_fault(op_binding, fault_name)
112     return get_fault_binding(op_binding, fault_name) != nil
113   end
114
115   def collect_fault_messages
116     result = []
117     porttypes.each do |porttype|
118       port_binding = porttype.find_binding()
119       next unless port_binding
120       porttype.operations.each do |operation|
121         op_binding = port_binding.operations.find { |ele| ele.name == operation.name }
122         next unless op_binding
123         operation.fault.each do |fault|
124           # Make sure the operation fault has a name
125           if not fault.name
126             warn("Operation \"#{operation.name}\": fault must specify a \"name\" attribute")
127             next
128           end
129           # Make sure that portType fault has a corresponding soap:fault
130           # definition in binding section.
131           if not op_binding_declares_fault(op_binding, fault.name)
132             warn("Operation \"#{operation.name}\", fault \"#{fault.name}\": no corresponding wsdl:fault binding found with a matching \"name\" attribute")         
133             next
134           end
135           fault_binding = get_fault_binding(op_binding, fault.name)
136           if fault_binding.soapfault.nil?
137             warn("WARNING: no soap:fault found for wsdl:fault \"#{fault_binding.name}\" in operation \"#{operation.name}\" \n\n")
138             next
139           end
140           if fault_binding.soapfault.name != fault_binding.name
141             warn("WARNING: name of soap:fault \"#{fault_binding.soapfault.name}\" doesn't match the name of wsdl:fault \"#{fault_binding.name}\" in operation \"#{operation.name}\" \n\n")
142             next
143           end
144           # According to WS-I (R2723): if in a wsdl:binding the use attribute
145           # on a contained soapbind:fault element is present, its value MUST
146           # be "literal".         
147           if fault_binding.soapfault.use and fault_binding.soapfault.use != "literal"
148             warn("Operation \"#{operation.name}\", fault \"#{fault.name}\": soap:fault \"use\" attribute must be \"literal\"")         
149           end
150           if result.index(fault.message).nil?
151             result << fault.message
152           end
153         end
154       end
155     end
156     result
157   end
158
159   def rpc_operation_complextypes(binding)
160     types = XSD::NamedElements.new
161     binding.operations.each do |op_bind|
162       if op_bind_rpc?(op_bind)
163         operation = op_bind.find_operation
164         if op_bind.input
165           type = XMLSchema::ComplexType.new(op_bind.soapoperation_name)
166           message = messages[operation.input.message]
167           type.sequence_elements = elements_from_message(message)
168           types << type
169         end
170         if op_bind.output
171           type = XMLSchema::ComplexType.new(operation.outputname)
172           message = messages[operation.output.message]
173           type.sequence_elements = elements_from_message(message)
174           types << type
175         end
176       end
177     end
178     types
179   end
180
181   def op_bind_rpc?(op_bind)
182     op_bind.soapoperation_style == :rpc
183   end
184
185   def elements_from_message(message)
186     message.parts.collect { |part|
187       if part.element
188         collect_elements[part.element]
189       elsif part.name.nil? or part.type.nil?
190         raise RuntimeError.new("part of a message must be an element or typed")
191       else
192         qname = XSD::QName.new(nil, part.name)
193         XMLSchema::Element.new(qname, part.type)
194       end
195     }
196   end
197 end
198
199
200 end
Note: See TracBrowser for help on using the browser.