diff options
author | Leon Breedt <bitserf@gmail.com> | 2005-02-27 21:21:40 +0000 |
---|---|---|
committer | Leon Breedt <bitserf@gmail.com> | 2005-02-27 21:21:40 +0000 |
commit | 100015cd806e31578a03ba23ffbc12c093118a26 (patch) | |
tree | 20cd8b5f8fd8cbfb60f2b8d2f309c0c259889d50 /actionwebservice/lib/action_web_service/dispatcher | |
parent | 19dddf24a63bd8a715ca47955963ba77d174d830 (diff) | |
download | rails-100015cd806e31578a03ba23ffbc12c093118a26.tar.gz rails-100015cd806e31578a03ba23ffbc12c093118a26.tar.bz2 rails-100015cd806e31578a03ba23ffbc12c093118a26.zip |
Make all custom types and method calls are declared in the 'urn:ActionWebService'
namespace as a default, fixes SOAP marshaling for .NET, a regression since the merge.
Make array annotation be recursive in WS::Marshaling::SoapMarshaling, this makes
typed arrays buried in nested structures still be annotated correctly.
Support :layered dispatching mode for XML-RPC namespaced method names.
Change WS::ParamInfo.create signature to require type_binding, and update all
uses of this.
Restore #default_api_method functionality, fixes a regression since the merge.
Fix marshalling of ActiveRecord::Base derivatives, fixes a regression since the merge.
This changeset closes #676, #677, and #678.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@811 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionwebservice/lib/action_web_service/dispatcher')
-rw-r--r-- | actionwebservice/lib/action_web_service/dispatcher/abstract.rb | 51 | ||||
-rw-r--r-- | actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb | 67 |
2 files changed, 79 insertions, 39 deletions
diff --git a/actionwebservice/lib/action_web_service/dispatcher/abstract.rb b/actionwebservice/lib/action_web_service/dispatcher/abstract.rb index b7560afc87..641f291533 100644 --- a/actionwebservice/lib/action_web_service/dispatcher/abstract.rb +++ b/actionwebservice/lib/action_web_service/dispatcher/abstract.rb @@ -19,7 +19,7 @@ module ActionWebService # :nodoc: case web_service_dispatching_mode when :direct web_service_direct_invoke(invocation) - when :delegated + when :delegated, :layered web_service_delegated_invoke(invocation) end end @@ -27,7 +27,11 @@ module ActionWebService # :nodoc: def web_service_direct_invoke(invocation) @method_params = invocation.method_ordered_params return_value = self.__send__(invocation.api_method_name) - returns = invocation.returns ? invocation.returns[0] : nil + if invocation.api.has_api_method?(invocation.api_method_name) + returns = invocation.returns ? invocation.returns[0] : nil + else + returns = return_value.class + end invocation.protocol.marshal_response(invocation.public_method_name, return_value, returns) end @@ -44,29 +48,43 @@ module ActionWebService # :nodoc: end def web_service_invocation(request) + public_method_name = request.method_name invocation = Invocation.new invocation.protocol = request.protocol invocation.service_name = request.service_name + if web_service_dispatching_mode == :layered + if request.method_name =~ /^([^\.]+)\.(.*)$/ + public_method_name = $2 + invocation.service_name = $1 + end + end + invocation.public_method_name = public_method_name case web_service_dispatching_mode when :direct invocation.api = self.class.web_service_api invocation.service = self - when :delegated - invocation.service = web_service_object(request.service_name) rescue nil + when :delegated, :layered + invocation.service = web_service_object(invocation.service_name) rescue nil unless invocation.service - raise(DispatcherError, "failed to instantiate service #{invocation.service_name}") + raise(DispatcherError, "service #{invocation.service_name} not available") end invocation.api = invocation.service.class.web_service_api end - public_method_name = request.method_name - unless invocation.api.has_public_api_method?(public_method_name) - raise(DispatcherError, "no such method '#{public_method_name}' on API #{invocation.api}") + if invocation.api.has_public_api_method?(public_method_name) + invocation.api_method_name = invocation.api.api_method_name(public_method_name) + else + if invocation.api.default_api_method.nil? + raise(DispatcherError, "no such method '#{public_method_name}' on API #{invocation.api}") + else + invocation.api_method_name = invocation.api.default_api_method.to_s.to_sym + end + end + unless invocation.service.respond_to?(invocation.api_method_name) + raise(DispatcherError, "no such method '#{public_method_name}' on API #{invocation.api} (#{invocation.api_method_name})") end - invocation.public_method_name = public_method_name - invocation.api_method_name = invocation.api.api_method_name(public_method_name) info = invocation.api.api_methods[invocation.api_method_name] - invocation.expects = info[:expects] - invocation.returns = info[:returns] + invocation.expects = info ? info[:expects] : nil + invocation.returns = info ? info[:returns] : nil if invocation.expects i = 0 invocation.method_ordered_params = request.method_params.map do |param| @@ -83,7 +101,7 @@ module ActionWebService # :nodoc: params = [] invocation.expects.each do |spec| type_binding = invocation.protocol.register_signature_type(spec) - info = WS::ParamInfo.create(spec, i, type_binding) + info = WS::ParamInfo.create(spec, type_binding, i) params << WS::Param.new(invocation.method_ordered_params[i], info) i += 1 end @@ -96,10 +114,15 @@ module ActionWebService # :nodoc: invocation.method_ordered_params = [] invocation.method_named_params = {} end + if invocation.returns + invocation.returns.each do |spec| + invocation.protocol.register_signature_type(spec) + end + end invocation end - class Invocation + class Invocation # :nodoc: attr_accessor :protocol attr_accessor :service_name attr_accessor :api diff --git a/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb b/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb index a35029b40d..7080f813d4 100644 --- a/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +++ b/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb @@ -20,20 +20,22 @@ module ActionWebService # :nodoc: base.add_web_service_definition_callback do |klass, name, info| if klass.web_service_dispatching_mode == :delegated klass.class_eval "def #{name}; dispatch_web_service_request; end" + elsif klass.web_service_dispatching_mode == :layered + klass.class_eval 'def api; dispatch_web_service_request; end' end end base.extend(ClassMethods) base.send(:include, ActionWebService::Dispatcher::ActionController::InstanceMethods) end - module ClassMethods + module ClassMethods # :nodoc: def inherited(child) inherited_without_action_controller(child) child.send(:include, ActionWebService::Dispatcher::ActionController::WsdlAction) end end - module InstanceMethods + module InstanceMethods # :nodoc: private def dispatch_web_service_request request = discover_web_service_request(@request) @@ -105,16 +107,16 @@ module ActionWebService # :nodoc: def log_request(request, body) unless logger.nil? name = request.method_name - params = request.method_params.map{|x| x.value.inspect} + params = request.method_params.map{|x| "#{x.info.name}=>#{x.value.inspect}"} service = request.service_name - logger.debug("\nWeb Service Request: #{name}(#{params}) #{service}") + logger.debug("\nWeb Service Request: #{name}(#{params.join(", ")}) Entrypoint: #{service}") logger.debug(indent(body)) end end def log_response(response, elapsed=nil) unless logger.nil? - logger.debug("\nWeb Service Response (%f):" + (elapsed ? " (%f):" % elapsed : ":")) + logger.debug("\nWeb Service Response" + (elapsed ? " (%f):" % elapsed : ":")) logger.debug(indent(response.body)) end end @@ -124,7 +126,7 @@ module ActionWebService # :nodoc: end end - module WsdlAction + module WsdlAction # :nodoc: XsdNs = 'http://www.w3.org/2001/XMLSchema' WsdlNs = 'http://schemas.xmlsoap.org/wsdl/' SoapNs = 'http://schemas.xmlsoap.org/wsdl/soap/' @@ -155,7 +157,7 @@ module ActionWebService # :nodoc: xml = '' dispatching_mode = web_service_dispatching_mode global_service_name = wsdl_service_name - namespace = "urn:#{global_service_name}" + namespace = 'urn:ActionWebService' soap_action_base = "/#{controller_name}" marshaler = WS::Marshaling::SoapMarshaler.new(namespace) @@ -164,18 +166,18 @@ module ActionWebService # :nodoc: when :direct api = self.class.web_service_api web_service_name = controller_class_name.sub(/Controller$/, '').underscore - apis[web_service_name] = [api, register_api(marshaler, api)] + apis[web_service_name] = [api, register_api(api, marshaler)] when :delegated self.class.web_services.each do |web_service_name, info| service = web_service_object(web_service_name) api = service.class.web_service_api - apis[web_service_name] = [api, register_api(marshaler, api)] + apis[web_service_name] = [api, register_api(api, marshaler)] end end custom_types = [] apis.values.each do |api, bindings| bindings.each do |b| - custom_types << b if b.is_custom_type? + custom_types << b end end @@ -200,15 +202,16 @@ module ActionWebService # :nodoc: xm.xsd(:complexContent) do xm.xsd(:restriction, 'base' => 'soapenc:Array') do xm.xsd(:attribute, 'ref' => 'soapenc:arrayType', - 'wsdl:arrayType' => binding.element_binding.qualified_type_name + '[]') + 'wsdl:arrayType' => binding.element_binding.qualified_type_name('typens') + '[]') end end end when binding.is_typed_struct? xm.xsd(:complexType, 'name' => binding.type_name) do xm.xsd(:all) do - binding.each_member do |name, type_name| - xm.xsd(:element, 'name' => name, 'type' => type_name) + binding.each_member do |name, spec| + b = marshaler.register_type(spec) + xm.xsd(:element, 'name' => name, 'type' => b.qualified_type_name('typens')) end end end @@ -229,7 +232,7 @@ module ActionWebService # :nodoc: returns = info[:returns] if returns binding = marshaler.register_type(returns[0]) - xm.part('name' => 'return', 'type' => binding.qualified_type_name) + xm.part('name' => 'return', 'type' => binding.qualified_type_name('typens')) end else expects = info[:expects] @@ -242,7 +245,7 @@ module ActionWebService # :nodoc: param_name = "param#{i}" end binding = marshaler.register_type(type) - xm.part('name' => param_name, 'type' => binding.qualified_type_name) + xm.part('name' => param_name, 'type' => binding.qualified_type_name('typens')) i += 1 end if expects end @@ -273,7 +276,7 @@ module ActionWebService # :nodoc: public_name = api.public_api_method_name(name) xm.operation('name' => public_name) do case web_service_dispatching_mode - when :direct + when :direct, :layered soap_action = soap_action_base + "/api/" + public_name when :delegated soap_action = soap_action_base \ @@ -325,20 +328,34 @@ module ActionWebService # :nodoc: "#{global_service}#{service.to_s.camelize}Binding" end - def register_api(marshaler, api) - type_bindings = [] + def register_api(api, marshaler) + bindings = {} + traverse_custom_types(api, marshaler) do |binding| + bindings[binding] = nil unless bindings.has_key?(binding.type_class) + end + bindings.keys + end + + def traverse_custom_types(api, marshaler, &block) api.api_methods.each do |name, info| expects, returns = info[:expects], info[:returns] - if expects - expects.each{|type| type_bindings << marshaler.register_type(type)} - end - if returns - returns.each{|type| type_bindings << marshaler.register_type(type)} + expects.each{|x| traverse_custom_type_spec(marshaler, x, &block)} if expects + returns.each{|x| traverse_custom_type_spec(marshaler, x, &block)} if returns + end + end + + def traverse_custom_type_spec(marshaler, spec, &block) + binding = marshaler.register_type(spec) + if binding.is_typed_struct? + binding.each_member do |name, member_spec| + traverse_custom_type_spec(marshaler, member_spec, &block) end + elsif binding.is_typed_array? + traverse_custom_type_spec(marshaler, binding.element_binding.type_class, &block) end - type_bindings + yield binding end - end + end end end end |