summaryrefslogtreecommitdiff
path: root/lib/soap/wsdlDriver.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/soap/wsdlDriver.rb')
-rw-r--r--lib/soap/wsdlDriver.rb361
1 files changed, 121 insertions, 240 deletions
diff --git a/lib/soap/wsdlDriver.rb b/lib/soap/wsdlDriver.rb
index af868ea886..aa822df4e4 100644
--- a/lib/soap/wsdlDriver.rb
+++ b/lib/soap/wsdlDriver.rb
@@ -14,12 +14,14 @@ require 'soap/baseData'
require 'soap/streamHandler'
require 'soap/mimemessage'
require 'soap/mapping'
-require 'soap/mapping/wsdlRegistry'
+require 'soap/mapping/wsdlencodedregistry'
+require 'soap/mapping/wsdlliteralregistry'
require 'soap/rpc/rpc'
require 'soap/rpc/element'
+require 'soap/rpc/proxy'
require 'soap/processor'
require 'soap/header/handlerset'
-require 'logger'
+require 'xsd/codegen/gensupport'
module SOAP
@@ -94,13 +96,14 @@ class WSDLDriver
__attr_proxy :options
__attr_proxy :headerhandler
+ __attr_proxy :streamhandler
__attr_proxy :test_loopback_response
__attr_proxy :endpoint_url, true
__attr_proxy :mapping_registry, true # for RPC unmarshal
__attr_proxy :wsdl_mapping_registry, true # for RPC marshal
__attr_proxy :default_encodingstyle, true
- __attr_proxy :allow_unqualified_element, true
__attr_proxy :generate_explicit_type, true
+ __attr_proxy :allow_unqualified_element, true
def httpproxy
@servant.options["protocol.http.proxy"]
@@ -143,105 +146,105 @@ class WSDLDriver
end
def reset_stream
- @servant.streamhandler.reset
+ @servant.reset_stream
end
# Backward compatibility.
alias generateEncodeType= generate_explicit_type=
class Servant__
- include Logger::Severity
include SOAP
attr_reader :options
- attr_reader :streamhandler
- attr_reader :headerhandler
attr_reader :port
- attr_accessor :mapping_registry
- attr_accessor :wsdl_mapping_registry
+ attr_accessor :soapaction
attr_accessor :default_encodingstyle
attr_accessor :allow_unqualified_element
attr_accessor :generate_explicit_type
+ attr_accessor :mapping_registry
+ attr_accessor :wsdl_mapping_registry
def initialize(host, wsdl, port, logdev)
@host = host
@wsdl = wsdl
@port = port
@logdev = logdev
-
+ @soapaction = nil
@options = setup_options
+ @default_encodingstyle = nil
+ @allow_unqualified_element = nil
+ @generate_explicit_type = false
@mapping_registry = nil # for rpc unmarshal
@wsdl_mapping_registry = nil # for rpc marshal
- @default_encodingstyle = EncodingNamespace
- @allow_unqualified_element = true
- @generate_explicit_type = false
@wiredump_file_base = nil
@mandatorycharset = nil
-
@wsdl_elements = @wsdl.collect_elements
@wsdl_types = @wsdl.collect_complextypes + @wsdl.collect_simpletypes
@rpc_decode_typemap = @wsdl_types +
@wsdl.soap_rpc_complextypes(port.find_binding)
- @wsdl_mapping_registry = Mapping::WSDLRegistry.new(@rpc_decode_typemap)
- @doc_mapper = Mapper.new(@wsdl_elements, @wsdl_types)
+ @wsdl_mapping_registry = Mapping::WSDLEncodedRegistry.new(@rpc_decode_typemap)
+ @doc_mapper = Mapping::WSDLLiteralRegistry.new(@wsdl_elements, @wsdl_types)
endpoint_url = @port.soap_address.location
- @streamhandler = HTTPPostStreamHandler.new(endpoint_url,
- @options["protocol.http"] ||= Property.new)
- @headerhandler = Header::HandlerSet.new
# Convert a map which key is QName, to a Hash which key is String.
- @operations = {}
+ @operation = {}
@port.inputoperation_map.each do |op_name, op_info|
- @operations[op_name.name] = op_info
+ @operation[op_name.name] = op_info
add_method_interface(op_info)
end
+ @proxy = ::SOAP::RPC::Proxy.new(endpoint_url, @soapaction, @options)
+ end
+
+ def inspect
+ "#<#{self.class}:#{@proxy.inspect}>"
end
def endpoint_url
- @streamhandler.endpoint_url
+ @proxy.endpoint_url
end
def endpoint_url=(endpoint_url)
- @streamhandler.endpoint_url = endpoint_url
- @streamhandler.reset
+ @proxy.endpoint_url = endpoint_url
end
- def test_loopback_response
- @streamhandler.test_loopback_response
+ def headerhandler
+ @proxy.headerhandler
end
- def rpc_send(method_name, *params)
- log(INFO) { "call: calling method '#{ method_name }'." }
- log(DEBUG) { "call: parameters '#{ params.inspect }'." }
+ def streamhandler
+ @proxy.streamhandler
+ end
- op_info = @operations[method_name]
- method = create_method_struct(op_info, params)
- req_header = call_headers
- req_body = SOAPBody.new(method)
- req_env = SOAPEnvelope.new(req_header, req_body)
+ def test_loopback_response
+ @proxy.test_loopback_response
+ end
- if @wiredump_file_base
- @streamhandler.wiredump_file_base =
- @wiredump_file_base + '_' << method_name
- end
+ def reset_stream
+ @proxy.reset_stream
+ end
+ def rpc_call(name, *values)
+ set_wiredump_file_base(name)
+ unless op_info = @operation[name]
+ raise MethodDefinitionError, "Method: #{name} not defined."
+ end
+ req_header = create_request_header
+ req_body = create_request_body(op_info, *values)
+ opt = create_options({
+ :soapaction => op_info.soapaction || @soapaction,
+ :decode_typemap => @rpc_decode_typemap})
+ env = @proxy.invoke(req_header, req_body, opt)
+ raise EmptyResponseError.new("Empty response.") unless env
+ receive_headers(env.header)
begin
- opt = create_options
- opt[:decode_typemap] = @rpc_decode_typemap
- res_env = invoke(req_env, op_info, opt)
- receive_headers(res_env.header)
- if res_env.body.fault
- raise ::SOAP::FaultError.new(res_env.body.fault)
- end
+ @proxy.check_fault(env.body)
rescue ::SOAP::FaultError => e
Mapping.fault2exception(e)
end
-
- ret = res_env.body.response ?
- Mapping.soap2obj(res_env.body.response, @mapping_registry) : nil
-
- if res_env.body.outparams
- outparams = res_env.body.outparams.collect { |outparam|
+ ret = env.body.response ?
+ Mapping.soap2obj(env.body.response, @mapping_registry) : nil
+ if env.body.outparams
+ outparams = env.body.outparams.collect { |outparam|
Mapping.soap2obj(outparam)
}
return [ret].concat(outparams)
@@ -250,32 +253,64 @@ class WSDLDriver
end
end
+ def document_call(name, param)
+ set_wiredump_file_base(name)
+ op_info = @operation[name]
+ req_header = header_from_obj(header_obj, op_info)
+ req_body = body_from_obj(body_obj, op_info)
+ env = @proxy.invoke(req_header, req_body, op_info.soapaction || @soapaction, @wsdl_types)
+ raise EmptyResponseError.new("Empty response.") unless env
+ if env.body.fault
+ raise ::SOAP::FaultError.new(env.body.fault)
+ end
+ res_body_obj = env.body.response ?
+ Mapping.soap2obj(env.body.response, @mapping_registry) : nil
+ return env.header, res_body_obj
+ end
+
# req_header: [[element, mustunderstand, encodingstyle(QName/String)], ...]
# req_body: SOAPBasetype/SOAPCompoundtype
def document_send(name, header_obj, body_obj)
- log(INFO) { "document_send: sending document '#{ name }'." }
- op_info = @operations[name]
+ set_wiredump_file_base(name)
+ op_info = @operation[name]
req_header = header_from_obj(header_obj, op_info)
req_body = body_from_obj(body_obj, op_info)
- req_env = SOAPEnvelope.new(req_header, req_body)
- opt = create_options
- res_env = invoke(req_env, op_info, opt)
- if res_env.body.fault
- raise ::SOAP::FaultError.new(res_env.body.fault)
- end
- res_body_obj = res_env.body.response ?
- Mapping.soap2obj(res_env.body.response, @mapping_registry) : nil
- return res_env.header, res_body_obj
+ opt = create_options({
+ :soapaction => op_info.soapaction || @soapaction,
+ :decode_typemap => @wsdl_types})
+ env = @proxy.invoke(req_header, req_body, opt)
+ raise EmptyResponseError.new("Empty response.") unless env
+ if env.body.fault
+ raise ::SOAP::FaultError.new(env.body.fault)
+ end
+ res_body_obj = env.body.response ?
+ Mapping.soap2obj(env.body.response, @mapping_registry) : nil
+ return env.header, res_body_obj
end
private
- def call_headers
- headers = @headerhandler.on_outbound
+ def create_options(hash = nil)
+ opt = {}
+ opt[:default_encodingstyle] = @default_encodingstyle
+ opt[:allow_unqualified_element] = @allow_unqualified_element
+ opt[:generate_explicit_type] = @generate_explicit_type
+ opt.update(hash) if hash
+ opt
+ end
+
+ def set_wiredump_file_base(name)
+ if @wiredump_file_base
+ @proxy.set_wiredump_file_base(@wiredump_file_base + "_#{ name }")
+ end
+ end
+
+ def create_request_header
+ headers = @proxy.headerhandler.on_outbound
if headers.empty?
nil
else
- h = ::SOAP::SOAPHeader.new
+ h = SOAPHeader.new
headers.each do |header|
h.add(header.elename.name, header)
end
@@ -284,10 +319,15 @@ class WSDLDriver
end
def receive_headers(headers)
- @headerhandler.on_inbound(headers) if headers
+ @proxy.headerhandler.on_inbound(headers) if headers
+ end
+
+ def create_request_body(op_info, *values)
+ method = create_method_struct(op_info, *values)
+ SOAPBody.new(method)
end
- def create_method_struct(op_info, params)
+ def create_method_struct(op_info, *params)
parts_names = op_info.bodyparts.collect { |part| part.name }
obj = create_method_obj(parts_names, params)
method = Mapping.obj2soap(obj, @wsdl_mapping_registry, op_info.optype_name)
@@ -313,52 +353,6 @@ class WSDLDriver
o
end
- def invoke(req_env, op_info, opt)
- opt[:external_content] = nil
- send_string = Processor.marshal(req_env, opt)
- log(DEBUG) { "invoke: sending string #{ send_string }" }
- conn_data = StreamHandler::ConnectionData.new(send_string)
- if ext = opt[:external_content]
- mime = MIMEMessage.new
- ext.each do |k, v|
- mime.add_attachment(v.data)
- end
- mime.add_part(conn_data.send_string + "\r\n")
- mime.close
- conn_data.send_string = mime.content_str
- conn_data.send_contenttype = mime.headers['content-type'].str
- end
- conn_data = @streamhandler.send(conn_data, op_info.soapaction)
- log(DEBUG) { "invoke: received string #{ conn_data.receive_string }" }
- if conn_data.receive_string.empty?
- return nil, nil
- end
- unmarshal(conn_data, opt)
- end
-
- def unmarshal(conn_data, opt)
- contenttype = conn_data.receive_contenttype
- if /#{MIMEMessage::MultipartContentType}/i =~ contenttype
- opt[:external_content] = {}
- mime = MIMEMessage.parse("Content-Type: " + contenttype,
- conn_data.receive_string)
- mime.parts.each do |part|
- value = Attachment.new(part.content)
- value.contentid = part.contentid
- obj = SOAPAttachment.new(value)
- opt[:external_content][value.contentid] = obj if value.contentid
- end
- opt[:charset] = @mandatorycharset ||
- StreamHandler.parse_media_type(mime.root.headers['content-type'].str)
- env = Processor.unmarshal(mime.root.content, opt)
- else
- opt[:charset] = @mandatorycharset ||
- ::SOAP::StreamHandler.parse_media_type(contenttype)
- env = Processor.unmarshal(conn_data.receive_string, opt)
- end
- env
- end
-
def header_from_obj(obj, op_info)
if obj.is_a?(SOAPHeader)
obj
@@ -376,7 +370,7 @@ class WSDLDriver
else
header = SOAPHeader.new()
op_info.headerparts.each do |part|
- child = Mapper.find_attribute(obj, part.name)
+ child = Mapping.find_attribute(obj, part.name)
ele = headeritem_from_obj(child, part.element || part.eletype)
header.add(part.name, ele)
end
@@ -390,7 +384,7 @@ class WSDLDriver
elsif obj.is_a?(SOAPHeaderItem)
obj
else
- @doc_mapper.obj2ele(obj, name)
+ @doc_mapper.obj2soap(obj, name)
end
end
@@ -410,7 +404,7 @@ class WSDLDriver
else
body = SOAPBody.new
op_info.bodyparts.each do |part|
- child = Mapper.find_attribute(obj, part.name)
+ child = Mapping.find_attribute(obj, part.name)
ele = bodyitem_from_obj(child, part.element || part.type)
body.add(ele.elename.name, ele)
end
@@ -424,51 +418,40 @@ class WSDLDriver
elsif obj.is_a?(SOAPElement)
obj
else
- @doc_mapper.obj2ele(obj, name)
+ @doc_mapper.obj2soap(obj, name)
end
end
def add_method_interface(op_info)
+ name = ::XSD::CodeGen::GenSupport.safemethodname(op_info.op_name.name)
case op_info.style
when :document
- add_document_method_interface(op_info.op_name.name)
+ add_document_method_interface(name)
when :rpc
parts_names = op_info.bodyparts.collect { |part| part.name }
- add_rpc_method_interface(op_info.op_name.name, parts_names)
+ add_rpc_method_interface(name, parts_names)
else
raise RuntimeError.new("Unknown style: #{op_info.style}")
end
end
- def add_document_method_interface(name)
- @host.instance_eval <<-EOS
- def #{ name }(headers, body)
- @servant.document_send(#{ name.dump }, headers, body)
- end
- EOS
- end
-
def add_rpc_method_interface(name, parts_names)
i = 0
param_names = parts_names.collect { |orgname| i += 1; "arg#{ i }" }
callparam = (param_names.collect { |pname| ", " + pname }).join
@host.instance_eval <<-EOS
def #{ name }(#{ param_names.join(", ") })
- @servant.rpc_send(#{ name.dump }#{ callparam })
+ @servant.rpc_call(#{ name.dump }#{ callparam })
end
EOS
end
- def create_options
- opt = {}
- opt[:default_encodingstyle] = @default_encodingstyle
- opt[:allow_unqualified_element] = @allow_unqualified_element
- opt[:generate_explicit_type] = @generate_explicit_type
- opt
- end
-
- def log(sev)
- @logdev.add(sev, nil, self.class) { yield } if @logdev
+ def add_document_method_interface(name)
+ @host.instance_eval <<-EOS
+ def #{ name }(h, b)
+ @servant.document_send(#{ name.dump }, h, b)
+ end
+ EOS
end
def setup_options
@@ -487,108 +470,6 @@ class WSDLDriver
opt["protocol.http.no_proxy"] ||= Env::NO_PROXY
opt
end
-
- class MappingError < StandardError; end
- class Mapper
- def initialize(elements, types)
- @elements = elements
- @types = types
- end
-
- def obj2ele(obj, name)
- if ele = @elements[name]
- _obj2ele(obj, ele)
- elsif type = @types[name]
- obj2type(obj, type)
- else
- raise MappingError.new("Cannot find name #{name} in schema.")
- end
- end
-
- def ele2obj(ele, *arg)
- raise NotImplementedError.new
- end
-
- def Mapper.find_attribute(obj, attr_name)
- if obj.respond_to?(attr_name)
- obj.__send__(attr_name)
- elsif obj.is_a?(Hash)
- obj[attr_name] || obj[attr_name.intern]
- else
- obj.instance_eval("@#{ attr_name }")
- end
- end
-
- private
-
- def _obj2ele(obj, ele)
- o = nil
- if ele.type
- if type = @types[ele.type]
- o = obj2type(obj, type)
- elsif type = TypeMap[ele.type]
- o = base2soap(obj, type)
- else
- raise MappingError.new("Cannot find type #{ele.type}.")
- end
- o.elename = ele.name
- elsif ele.local_complextype
- o = SOAPElement.new(ele.name)
- ele.local_complextype.each_element do |child_ele|
- o.add(_obj2ele(Mapper.find_attribute(obj, child_ele.name.name),
- child_ele))
- end
- else
- raise MappingError.new("Illegal schema?")
- end
- o
- end
-
- def obj2type(obj, type)
- if type.is_a?(::WSDL::XMLSchema::SimpleType)
- simple2soap(obj, type)
- else
- complex2soap(obj, type)
- end
- end
-
- def simple2soap(obj, type)
- o = base2soap(obj, TypeMap[type.base])
- if type.restriction.enumeration.empty?
- STDERR.puts("#{type.name}: simpleType which is not enum type not supported.")
- return o
- end
- if type.restriction.enumeration.include?(o)
- raise MappingError.new("#{o} is not allowed for #{type.name}")
- end
- o
- end
-
- def complex2soap(obj, type)
- o = SOAPElement.new(type.name)
- type.each_element do |child_ele|
- o.add(_obj2ele(Mapper.find_attribute(obj, child_ele.name.name),
- child_ele))
- end
- o
- end
-
- def _ele2obj(ele)
- raise NotImplementedError.new
- end
-
- def base2soap(obj, type)
- soap_obj = nil
- if type <= XSD::XSDString
- soap_obj = type.new(XSD::Charset.is_ces(obj, $KCODE) ?
- XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding) :
- obj)
- else
- soap_obj = type.new(obj)
- end
- soap_obj
- end
- end
end
end