diff options
author | nahi <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-12-20 13:50:15 +0000 |
---|---|---|
committer | nahi <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-12-20 13:50:15 +0000 |
commit | e5a3aba50e2bd7e0327aacd8fe1ab7963fc4a007 (patch) | |
tree | b56a6e784df74331c28e4a94901b96837f214e35 /lib/soap/rpc/proxy.rb | |
parent | 643dc132113489749c333a6bda14730d9b175ed1 (diff) |
* added files:
* lib/soap/mapping/wsdl*.rb
* lib/wsdl/soap/element.rb
* lib/wsdl/xmlSchema/simpleContent.rb
* modified files:
* lib/soap/*
* lib/wsdl/*
* lib/xsd/*
* test/soap/*
* test/wsdl/*
* test/xsd/*
* summary
* imported from the soap4r repository. Version: 1.5.3-ruby1.8.2
* added several XSD basetype support: nonPositiveInteger,
negativeInteger, nonNegativeInteger, unsignedLong, unsignedInt,
unsignedShort, unsignedByte, positiveInteger
* HTTP client connection/send/receive timeout support.
* HTTP client/server gzipped content encoding support.
* improved WSDL schema definition support; still is far from
complete, but is making step by step improovement.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7612 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/soap/rpc/proxy.rb')
-rw-r--r-- | lib/soap/rpc/proxy.rb | 264 |
1 files changed, 205 insertions, 59 deletions
diff --git a/lib/soap/rpc/proxy.rb b/lib/soap/rpc/proxy.rb index 355bf2e81a..ca110664f9 100644 --- a/lib/soap/rpc/proxy.rb +++ b/lib/soap/rpc/proxy.rb @@ -28,73 +28,79 @@ public attr_accessor :mandatorycharset attr_accessor :allow_unqualified_element attr_accessor :default_encodingstyle - attr_reader :method + attr_accessor :generate_explicit_type + attr_reader :headerhandler + attr_reader :streamhandler - def initialize(streamhandler, soapaction = nil) - @streamhandler = streamhandler + attr_accessor :mapping_registry + attr_accessor :literal_mapping_registry + + attr_reader :operation + + def initialize(endpoint_url, soapaction, options) + @endpoint_url = endpoint_url @soapaction = soapaction - @method = {} + @options = options + @streamhandler = HTTPStreamHandler.new( + @options["protocol.http"] ||= ::SOAP::Property.new) + @operation = {} @mandatorycharset = nil - @allow_unqualified_element = false + @allow_unqualified_element = true @default_encodingstyle = nil + @generate_explicit_type = true + @headerhandler = Header::HandlerSet.new + @mapping_registry = nil + @literal_mapping_registry = ::SOAP::Mapping::WSDLLiteralRegistry.new end - class Request - include RPC + def inspect + "#<#{self.class}:#{@endpoint_url}>" + end - public + def endpoint_url + @endpoint_url + end - attr_reader :method - attr_reader :namespace - attr_reader :name + def endpoint_url=(endpoint_url) + @endpoint_url = endpoint_url + reset_stream + end - def initialize(model, values) - @method = model.dup - @namespace = @method.elename.namespace - @name = @method.elename.name + def reset_stream + @streamhandler.reset(@endpoint_url) + end - params = {} - - if ((values.size == 1) and (values[0].is_a?(Hash))) - params = values[0] - else - i = 0 - @method.each_param_name(SOAPMethod::IN, SOAPMethod::INOUT) do |name| - params[name] = values[i] || SOAPNil.new - i += 1 - end - end - @method.set_param(params) - end + def set_wiredump_file_base(wiredump_file_base) + @streamhandler.wiredump_file_base = wiredump_file_base end - def add_method(qname, soapaction, name, param_def) - @method[name] = SOAPMethodRequest.new(qname, param_def, soapaction) + def test_loopback_response + @streamhandler.test_loopback_response end - def create_request(name, *values) - if (@method.key?(name)) - method = @method[name] - method.encodingstyle = @default_encodingstyle if @default_encodingstyle - else - raise SOAP::RPC::MethodDefinitionError.new( - "Method: #{ name } not defined.") - end - Request.new(method, values) + def add_rpc_method(qname, soapaction, name, param_def, opt = {}) + opt[:request_style] ||= :rpc + opt[:response_style] ||= :rpc + opt[:request_use] ||= :encoded + opt[:response_use] ||= :encoded + @operation[name] = Operation.new(qname, soapaction, name, param_def, opt) end - def invoke(req_header, req_body, soapaction = nil) - if req_header and !req_header.is_a?(SOAPHeader) - req_header = create_header(req_header) - end - if !req_body.is_a?(SOAPBody) - req_body = SOAPBody.new(req_body) - end - opt = create_options - opt[:external_content] = nil + def add_document_method(qname, soapaction, name, param_def, opt = {}) + opt[:request_style] ||= :document + opt[:response_style] ||= :document + opt[:request_use] ||= :literal + opt[:response_use] ||= :literal + @operation[name] = Operation.new(qname, soapaction, name, param_def, opt) + end + + # add_method is for shortcut of typical rpc/encoded method definition. + alias add_method add_rpc_method + + def invoke(req_header, req_body, opt = create_options) req_env = SOAPEnvelope.new(req_header, req_body) - send_string = Processor.marshal(req_env, opt) - conn_data = StreamHandler::ConnectionData.new(send_string) + opt[:external_content] = nil + conn_data = marshal(req_env, opt) if ext = opt[:external_content] mime = MIMEMessage.new ext.each do |k, v| @@ -105,16 +111,33 @@ public conn_data.send_string = mime.content_str conn_data.send_contenttype = mime.headers['content-type'].str end - conn_data = @streamhandler.send(conn_data, soapaction) + conn_data = @streamhandler.send(@endpoint_url, conn_data, opt[:soapaction]) if conn_data.receive_string.empty? - return nil, nil + return nil end unmarshal(conn_data, opt) end - def call(req_header, name, *values) - req = create_request(name, *values) - invoke(req_header, req.method, req.method.soapaction || @soapaction) + def call(name, *params) + unless op_info = @operation[name] + raise MethodDefinitionError, "Method: #{name} not defined." + end + req_header = create_request_header + req_body = op_info.create_request_body(params, @mapping_registry, + @literal_mapping_registry) + opt = create_options({ + :soapaction => op_info.soapaction || @soapaction, + :default_encodingstyle => op_info.response_default_encodingstyle}) + env = invoke(req_header, req_body, opt) + receive_headers(env.header) + raise EmptyResponseError.new("Empty response.") unless env + begin + check_fault(env.body) + rescue ::SOAP::FaultError => e + Mapping.fault2exception(e) + end + op_info.create_response_obj(env, @mapping_registry, + @literal_mapping_registry) end def check_fault(body) @@ -125,6 +148,28 @@ public private + def create_request_header + headers = @headerhandler.on_outbound + if headers.empty? + nil + else + h = ::SOAP::SOAPHeader.new + headers.each do |header| + h.add(header.elename.name, header) + end + h + end + end + + def receive_headers(headers) + @headerhandler.on_inbound(headers) if headers + end + + def marshal(env, opt) + send_string = Processor.marshal(env, opt) + StreamHandler::ConnectionData.new(send_string) + end + def unmarshal(conn_data, opt) contenttype = conn_data.receive_contenttype if /#{MIMEMessage::MultipartContentType}/i =~ contenttype @@ -156,14 +201,115 @@ private header end - def create_options + def create_options(hash = nil) opt = {} opt[:default_encodingstyle] = @default_encodingstyle - if @allow_unqualified_element - opt[:allow_unqualified_element] = true - end + opt[:allow_unqualified_element] = @allow_unqualified_element + opt[:generate_explicit_type] = @generate_explicit_type + opt.update(hash) if hash opt end + + class Operation + attr_reader :soapaction + attr_reader :request_style + attr_reader :response_style + attr_reader :request_use + attr_reader :response_use + + def initialize(qname, soapaction, name, param_def, opt) + @soapaction = soapaction + @request_style = opt[:request_style] + @response_style = opt[:response_style] + @request_use = opt[:request_use] + @response_use = opt[:response_use] + @rpc_method_factory = @document_method_name = nil + check_style(@request_style) + check_style(@response_style) + if @request_style == :rpc + @rpc_method_factory = SOAPMethodRequest.new(qname, param_def, + @soapaction) + else + @document_method_name = {} + param_def.each do |inout, paramname, typeinfo| + klass, namespace, name = typeinfo + case inout.to_s + when "input" + @document_method_name[:input] = ::XSD::QName.new(namespace, name) + when "output" + @document_method_name[:output] = ::XSD::QName.new(namespace, name) + else + raise MethodDefinitionError, "unknown type: " + inout + end + end + end + end + + def request_default_encodingstyle + (@request_style == :rpc) ? EncodingNamespace : LiteralNamespace + end + + def response_default_encodingstyle + (@response_style == :rpc) ? EncodingNamespace : LiteralNamespace + end + + # for rpc + def each_param_name(*target) + if @request_style == :rpc + @rpc_method_factory.each_param_name(*target) do |name| + yield(name) + end + else + yield(@document_method_name[:input].name) + end + end + + def create_request_body(values, mapping_registry, literal_mapping_registry) + if @request_style == :rpc + values = Mapping.obj2soap(values, mapping_registry).to_a + method = @rpc_method_factory.dup + params = {} + idx = 0 + method.each_param_name(::SOAP::RPC::SOAPMethod::IN, + ::SOAP::RPC::SOAPMethod::INOUT) do |name| + params[name] = values[idx] || SOAPNil.new + idx += 1 + end + method.set_param(params) + SOAPBody.new(method) + else + name = @document_method_name[:input] + document = literal_mapping_registry.obj2soap(values[0], name) + SOAPBody.new(document) + end + end + + def create_response_obj(env, mapping_registry, literal_mapping_registry) + if @response_style == :rpc + 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) + } + [ret].concat(outparams) + else + ret + end + else + Mapping.soap2obj(env.body.root_node, literal_mapping_registry) + end + end + + private + + ALLOWED_STYLE = [:rpc, :document] + def check_style(style) + unless ALLOWED_STYLE.include?(style) + raise MethodDefinitionError, "unknown style: " + style + end + end + end end |