aboutsummaryrefslogtreecommitdiffstats
path: root/actionwebservice/lib/action_web_service/dispatcher/abstract.rb
diff options
context:
space:
mode:
authorLeon Breedt <bitserf@gmail.com>2005-02-19 08:29:42 +0000
committerLeon Breedt <bitserf@gmail.com>2005-02-19 08:29:42 +0000
commit418d487020d24e69b528fdbedfecb20a87f99fcb (patch)
tree1956d6982123df1638bdef8274dff50ae71b25c2 /actionwebservice/lib/action_web_service/dispatcher/abstract.rb
parente7499638d06023ae493d14ec1dc4f58bad8ac168 (diff)
downloadrails-418d487020d24e69b528fdbedfecb20a87f99fcb.tar.gz
rails-418d487020d24e69b528fdbedfecb20a87f99fcb.tar.bz2
rails-418d487020d24e69b528fdbedfecb20a87f99fcb.zip
refactoring:
* move dispatching out of the Container into Dispatcher, it makes more sense for Container to only contain the list of web services defined in it. * collapse Wsdl and ActionController "routers" into an ActionController-specific module, no advantage to having them seperate as they were quite tightly coupled. rename to Dispatcher, to avoi confusion with Routing. * add a "_thing" suffix to concept-specific filenames. this is so that we don't end up with many soap.rb files, for example. * remove "virtual invocation" support. adds complexity, and it doesn't seem to add any value. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@679 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionwebservice/lib/action_web_service/dispatcher/abstract.rb')
-rw-r--r--actionwebservice/lib/action_web_service/dispatcher/abstract.rb158
1 files changed, 158 insertions, 0 deletions
diff --git a/actionwebservice/lib/action_web_service/dispatcher/abstract.rb b/actionwebservice/lib/action_web_service/dispatcher/abstract.rb
new file mode 100644
index 0000000000..e03446924a
--- /dev/null
+++ b/actionwebservice/lib/action_web_service/dispatcher/abstract.rb
@@ -0,0 +1,158 @@
+require 'benchmark'
+
+module ActionWebService # :nodoc:
+ module Dispatcher # :nodoc:
+ class DispatcherError < ActionWebService::ActionWebServiceError # :nodoc:
+ end
+
+ def self.append_features(base) # :nodoc:
+ super
+ base.class_inheritable_option(:web_service_dispatching_mode, :direct)
+ base.class_inheritable_option(:web_service_exception_reporting, true)
+ base.send(:include, ActionWebService::Dispatcher::InstanceMethods)
+ end
+
+ module InstanceMethods # :nodoc:
+ private
+ def dispatch_web_service_request(action_pack_request)
+ protocol_request = protocol_response = nil
+ bm = Benchmark.measure do
+ protocol_request = probe_request_protocol(action_pack_request)
+ protocol_response = dispatch_protocol_request(protocol_request)
+ end
+ [protocol_request, protocol_response, bm.real, nil]
+ rescue Exception => e
+ protocol_response = prepare_exception_response(protocol_request, e)
+ [protocol_request, prepare_exception_response(protocol_request, e), nil, e]
+ end
+
+ def dispatch_protocol_request(protocol_request)
+ case web_service_dispatching_mode
+ when :direct
+ dispatch_direct_request(protocol_request)
+ when :delegated
+ dispatch_delegated_request(protocol_request)
+ else
+ raise(ContainerError, "unsupported dispatching mode :#{web_service_dispatching_mode}")
+ end
+ end
+
+ def dispatch_direct_request(protocol_request)
+ request = prepare_dispatch_request(protocol_request)
+ return_value = direct_invoke(request)
+ protocol_request.marshal(return_value)
+ end
+
+ def dispatch_delegated_request(protocol_request)
+ request = prepare_dispatch_request(protocol_request)
+ return_value = delegated_invoke(request)
+ protocol_request.marshal(return_value)
+ end
+
+ def direct_invoke(request)
+ return nil unless before_direct_invoke(request)
+ return_value = send(request.method_name)
+ after_direct_invoke(request)
+ return_value
+ end
+
+ def before_direct_invoke(request)
+ @method_params = request.params
+ end
+
+ def after_direct_invoke(request)
+ end
+
+ def delegated_invoke(request)
+ cancellation_reason = nil
+ web_service = request.web_service
+ return_value = web_service.perform_invocation(request.method_name, request.params) do |x|
+ cancellation_reason = x
+ end
+ if cancellation_reason
+ raise(DispatcherError, "request canceled: #{cancellation_reason}")
+ end
+ return_value
+ end
+
+ def fallback_invoke(dispatch_request)
+ raise NotImplementedError
+ end
+
+ def prepare_dispatch_request(protocol_request)
+ api = method_name = web_service_name = web_service = params = nil
+ public_method_name = protocol_request.public_method_name
+ case web_service_dispatching_mode
+ when :direct
+ api = self.class.web_service_api
+ when :delegated
+ web_service_name = protocol_request.web_service_name
+ web_service = web_service_object(web_service_name)
+ api = web_service.class.web_service_api
+ end
+ method_name = api.api_method_name(public_method_name)
+ signature = nil
+ if method_name
+ signature = api.api_methods[method_name]
+ protocol_request.type = Protocol::CheckedMessage
+ protocol_request.signature = signature[:expects]
+ protocol_request.return_signature = signature[:returns]
+ else
+ method_name = api.default_api_method
+ if method_name
+ protocol_request.type = Protocol::UncheckedMessage
+ else
+ raise(DispatcherError, "no such method #{web_service_name}##{public_method_name}")
+ end
+ end
+ params = protocol_request.unmarshal
+ DispatchRequest.new(
+ :api => api,
+ :public_method_name => public_method_name,
+ :method_name => method_name,
+ :signature => signature,
+ :web_service_name => web_service_name,
+ :web_service => web_service,
+ :params => params)
+ end
+
+ def prepare_exception_response(protocol_request, exception)
+ if protocol_request && exception
+ case web_service_dispatching_mode
+ when :direct
+ if web_service_exception_reporting
+ return protocol_request.protocol.marshal_exception(exception)
+ else
+ raise exception
+ end
+ when :delegated
+ web_service = web_service_object(protocol_request.web_service_name)
+ if web_service && web_service.class.web_service_exception_reporting
+ return protocol_request.protocol.marshal_exception(exception)
+ else
+ raise exception
+ end
+ end
+ else
+ protocol_request.protocol.marshal_exception(RuntimeError.new("missing protocol request or exception"))
+ end
+ rescue Exception
+ nil
+ end
+
+ class DispatchRequest
+ attr :api
+ attr :public_method_name
+ attr :method_name
+ attr :signature
+ attr :web_service_name
+ attr :web_service
+ attr :params
+
+ def initialize(values={})
+ values.each{|k,v| instance_variable_set("@#{k.to_s}", v)}
+ end
+ end
+ end
+ end
+end