actionwebservice 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +47 -0
- data/MIT-LICENSE +21 -0
- data/README +238 -0
- data/Rakefile +144 -0
- data/TODO +13 -0
- data/examples/googlesearch/README +143 -0
- data/examples/googlesearch/autoloading/google_search_api.rb +50 -0
- data/examples/googlesearch/autoloading/google_search_controller.rb +57 -0
- data/examples/googlesearch/delegated/google_search_service.rb +108 -0
- data/examples/googlesearch/delegated/search_controller.rb +7 -0
- data/examples/googlesearch/direct/google_search_api.rb +50 -0
- data/examples/googlesearch/direct/search_controller.rb +58 -0
- data/examples/metaWeblog/README +16 -0
- data/examples/metaWeblog/blog_controller.rb +127 -0
- data/lib/action_web_service.rb +60 -0
- data/lib/action_web_service/api.rb +2 -0
- data/lib/action_web_service/api/abstract.rb +192 -0
- data/lib/action_web_service/api/action_controller.rb +92 -0
- data/lib/action_web_service/base.rb +41 -0
- data/lib/action_web_service/client.rb +3 -0
- data/lib/action_web_service/client/base.rb +39 -0
- data/lib/action_web_service/client/soap_client.rb +88 -0
- data/lib/action_web_service/client/xmlrpc_client.rb +77 -0
- data/lib/action_web_service/container.rb +85 -0
- data/lib/action_web_service/dispatcher.rb +2 -0
- data/lib/action_web_service/dispatcher/abstract.rb +150 -0
- data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +299 -0
- data/lib/action_web_service/invocation.rb +205 -0
- data/lib/action_web_service/protocol.rb +4 -0
- data/lib/action_web_service/protocol/abstract.rb +128 -0
- data/lib/action_web_service/protocol/registry.rb +55 -0
- data/lib/action_web_service/protocol/soap_protocol.rb +484 -0
- data/lib/action_web_service/protocol/xmlrpc_protocol.rb +168 -0
- data/lib/action_web_service/struct.rb +55 -0
- data/lib/action_web_service/support/class_inheritable_options.rb +26 -0
- data/lib/action_web_service/support/signature.rb +100 -0
- data/setup.rb +1360 -0
- data/test/abstract_client.rb +131 -0
- data/test/abstract_soap.rb +58 -0
- data/test/abstract_unit.rb +9 -0
- data/test/api_test.rb +52 -0
- data/test/base_test.rb +42 -0
- data/test/client_soap_test.rb +93 -0
- data/test/client_xmlrpc_test.rb +92 -0
- data/test/container_test.rb +53 -0
- data/test/dispatcher_action_controller_test.rb +186 -0
- data/test/gencov +3 -0
- data/test/invocation_test.rb +149 -0
- data/test/protocol_registry_test.rb +53 -0
- data/test/protocol_soap_test.rb +252 -0
- data/test/protocol_xmlrpc_test.rb +147 -0
- data/test/run +5 -0
- data/test/struct_test.rb +40 -0
- metadata +131 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'action_web_service/support/class_inheritable_options'
|
2
|
+
require 'action_web_service/support/signature'
|
3
|
+
|
4
|
+
module ActionWebService # :nodoc:
|
5
|
+
class ActionWebServiceError < StandardError # :nodoc:
|
6
|
+
end
|
7
|
+
|
8
|
+
# An Action Web Service object implements a specified API.
|
9
|
+
#
|
10
|
+
# Used by controllers operating in _Delegated_ dispatching mode.
|
11
|
+
#
|
12
|
+
# ==== Example
|
13
|
+
#
|
14
|
+
# class PersonService < ActionWebService::Base
|
15
|
+
# web_service_api PersonAPI
|
16
|
+
#
|
17
|
+
# def find_person(criteria)
|
18
|
+
# Person.find_all [...]
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# def delete_person(id)
|
22
|
+
# Person.find_by_id(id).destroy
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# class PersonAPI < ActionWebService::API::Base
|
27
|
+
# api_method :find_person, :expects => [SearchCriteria], :returns => [[Person]]
|
28
|
+
# api_method :delete_person, :expects => [:int]
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# class SearchCriteria < ActionStruct::Base
|
32
|
+
# member :firstname, :string
|
33
|
+
# member :lastname, :string
|
34
|
+
# member :email, :string
|
35
|
+
# end
|
36
|
+
class Base
|
37
|
+
# Whether to report exceptions back to the caller in the protocol's exception
|
38
|
+
# format
|
39
|
+
class_inheritable_option :web_service_exception_reporting, true
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ActionWebService # :nodoc:
|
2
|
+
module Client # :nodoc:
|
3
|
+
class ClientError < StandardError # :nodoc:
|
4
|
+
end
|
5
|
+
|
6
|
+
class Base # :nodoc:
|
7
|
+
def initialize(api, endpoint_uri)
|
8
|
+
@api = api
|
9
|
+
@endpoint_uri = endpoint_uri
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_missing(name, *args) # :nodoc:
|
13
|
+
call_name = method_name(name)
|
14
|
+
return super(name, *args) if call_name.nil?
|
15
|
+
perform_invocation(call_name, args)
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
def perform_invocation(method_name, args) # :nodoc:
|
20
|
+
raise NotImplementedError, "use a protocol-specific client"
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def method_name(name)
|
25
|
+
if @api.has_api_method?(name.to_sym)
|
26
|
+
name.to_s
|
27
|
+
elsif @api.has_public_api_method?(name.to_s)
|
28
|
+
@api.api_method_name(name.to_s).to_s
|
29
|
+
else
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def lookup_class(klass)
|
35
|
+
klass.is_a?(Hash) ? klass.values[0] : klass
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'soap/rpc/driver'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module ActionWebService # :nodoc:
|
5
|
+
module Client # :nodoc:
|
6
|
+
|
7
|
+
# Implements SOAP client support (using RPC encoding for the messages).
|
8
|
+
#
|
9
|
+
# ==== Example Usage
|
10
|
+
#
|
11
|
+
# class PersonAPI < ActionWebService::API::Base
|
12
|
+
# api_method :find_all, :returns => [[Person]]
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# soap_client = ActionWebService::Client::Soap.new(PersonAPI, "http://...")
|
16
|
+
# persons = soap_client.find_all
|
17
|
+
#
|
18
|
+
class Soap < Base
|
19
|
+
|
20
|
+
# Creates a new web service client using the SOAP RPC protocol.
|
21
|
+
#
|
22
|
+
# +api+ must be an ActionWebService::API::Base derivative, and
|
23
|
+
# +endpoint_uri+ must point at the relevant URL to which protocol requests
|
24
|
+
# will be sent with HTTP POST.
|
25
|
+
#
|
26
|
+
# Valid options:
|
27
|
+
# [<tt>:service_name</tt>] If the remote server has used a custom +wsdl_service_name+
|
28
|
+
# option, you must specify it here
|
29
|
+
def initialize(api, endpoint_uri, options={})
|
30
|
+
super(api, endpoint_uri)
|
31
|
+
@service_name = options[:service_name] || 'ActionWebService'
|
32
|
+
@namespace = "urn:#{@service_name}"
|
33
|
+
@mapper = ActionWebService::Protocol::Soap::SoapMapper.new(@namespace)
|
34
|
+
@protocol = ActionWebService::Protocol::Soap::SoapProtocol.new(@mapper)
|
35
|
+
@soap_action_base = options[:soap_action_base]
|
36
|
+
@soap_action_base ||= URI.parse(endpoint_uri).path
|
37
|
+
@driver = create_soap_rpc_driver(api, endpoint_uri)
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
def perform_invocation(method_name, args)
|
42
|
+
@driver.send(method_name, *args)
|
43
|
+
end
|
44
|
+
|
45
|
+
def soap_action(method_name)
|
46
|
+
"#{@soap_action_base}/#{method_name}"
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def create_soap_rpc_driver(api, endpoint_uri)
|
51
|
+
@mapper.map_api(api)
|
52
|
+
driver = SoapDriver.new(endpoint_uri, nil)
|
53
|
+
driver.mapping_registry = @mapper.registry
|
54
|
+
api.api_methods.each do |name, info|
|
55
|
+
public_name = api.public_api_method_name(name)
|
56
|
+
qname = XSD::QName.new(@namespace, public_name)
|
57
|
+
action = soap_action(public_name)
|
58
|
+
expects = info[:expects]
|
59
|
+
returns = info[:returns]
|
60
|
+
param_def = []
|
61
|
+
i = 1
|
62
|
+
if expects
|
63
|
+
expects.each do |klass|
|
64
|
+
param_name = klass.is_a?(Hash) ? klass.keys[0] : "param#{i}"
|
65
|
+
param_klass = lookup_class(klass)
|
66
|
+
mapping = @mapper.lookup(param_klass)
|
67
|
+
param_def << ['in', param_name, mapping.registry_mapping]
|
68
|
+
i += 1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
if returns
|
72
|
+
mapping = @mapper.lookup(lookup_class(returns[0]))
|
73
|
+
param_def << ['retval', 'return', mapping.registry_mapping]
|
74
|
+
end
|
75
|
+
driver.add_method(qname, action, name.to_s, param_def)
|
76
|
+
end
|
77
|
+
driver
|
78
|
+
end
|
79
|
+
|
80
|
+
class SoapDriver < SOAP::RPC::Driver # :nodoc:
|
81
|
+
def add_method(qname, soapaction, name, param_def)
|
82
|
+
@proxy.add_rpc_method(qname, soapaction, name, param_def)
|
83
|
+
add_rpc_method_interface(name, param_def)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'xmlrpc/client'
|
3
|
+
|
4
|
+
module ActionWebService # :nodoc:
|
5
|
+
module Client # :nodoc:
|
6
|
+
|
7
|
+
# Implements XML-RPC client support
|
8
|
+
#
|
9
|
+
# ==== Example Usage
|
10
|
+
#
|
11
|
+
# class BloggerAPI < ActionWebService::API::Base
|
12
|
+
# inflect_names false
|
13
|
+
# api_method :getRecentPosts, :returns => [[Blog::Post]]
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# blog = ActionWebService::Client::XmlRpc.new(BloggerAPI, "http://.../RPC", :handler_name => "blogger")
|
17
|
+
# posts = blog.getRecentPosts
|
18
|
+
class XmlRpc < Base
|
19
|
+
|
20
|
+
# Creates a new web service client using the XML-RPC protocol.
|
21
|
+
#
|
22
|
+
# +api+ must be an ActionWebService::API::Base derivative, and
|
23
|
+
# +endpoint_uri+ must point at the relevant URL to which protocol requests
|
24
|
+
# will be sent with HTTP POST.
|
25
|
+
#
|
26
|
+
# Valid options:
|
27
|
+
# [<tt>:handler_name</tt>] If the remote server defines its services inside special
|
28
|
+
# handler (the Blogger API uses a <tt>"blogger"</tt> handler name for example),
|
29
|
+
# provide it here, or your method calls will fail
|
30
|
+
def initialize(api, endpoint_uri, options={})
|
31
|
+
@api = api
|
32
|
+
@handler_name = options[:handler_name]
|
33
|
+
@client = XMLRPC::Client.new2(endpoint_uri, options[:proxy], options[:timeout])
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
def perform_invocation(method_name, args)
|
38
|
+
args = transform_outgoing_method_params(method_name, args)
|
39
|
+
ok, return_value = @client.call2(public_name(method_name), *args)
|
40
|
+
return transform_return_value(method_name, return_value) if ok
|
41
|
+
raise(ClientError, "#{return_value.faultCode}: #{return_value.faultString}")
|
42
|
+
end
|
43
|
+
|
44
|
+
def transform_outgoing_method_params(method_name, params)
|
45
|
+
info = @api.api_methods[method_name.to_sym]
|
46
|
+
signature = info[:expects]
|
47
|
+
signature_length = signature.nil?? 0 : signature.length
|
48
|
+
if signature_length != params.length
|
49
|
+
raise(ProtocolError, "API declares #{public_name(method_name)} to accept " +
|
50
|
+
"#{signature_length} parameters, but #{params.length} parameters " +
|
51
|
+
"were supplied")
|
52
|
+
end
|
53
|
+
if signature_length > 0
|
54
|
+
signature = Protocol::XmlRpc::XmlRpcProtocol.transform_array_types(signature)
|
55
|
+
(1..signature.size).each do |i|
|
56
|
+
i -= 1
|
57
|
+
params[i] = Protocol::XmlRpc::XmlRpcProtocol.ruby_to_xmlrpc(params[i], lookup_class(signature[i]))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
params
|
61
|
+
end
|
62
|
+
|
63
|
+
def transform_return_value(method_name, return_value)
|
64
|
+
info = @api.api_methods[method_name.to_sym]
|
65
|
+
return true unless signature = info[:returns]
|
66
|
+
param_klass = lookup_class(signature[0])
|
67
|
+
signature = Protocol::XmlRpc::XmlRpcProtocol.transform_array_types([param_klass])
|
68
|
+
Protocol::XmlRpc::XmlRpcProtocol.xmlrpc_to_ruby(return_value, signature[0])
|
69
|
+
end
|
70
|
+
|
71
|
+
def public_name(method_name)
|
72
|
+
public_name = @api.public_api_method_name(method_name)
|
73
|
+
@handler_name ? "#{@handler_name}.#{public_name}" : public_name
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module ActionWebService # :nodoc:
|
2
|
+
module Container # :nodoc:
|
3
|
+
class ContainerError < ActionWebService::ActionWebServiceError # :nodoc:
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.append_features(base) # :nodoc:
|
7
|
+
super
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
base.send(:include, ActionWebService::Container::InstanceMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
# Declares a web service that will provides access to the API of the given
|
14
|
+
# +object+. +object+ must be an ActionWebService::Base derivative.
|
15
|
+
#
|
16
|
+
# Web service object creation can either be _immediate_, where the object
|
17
|
+
# instance is given at class definition time, or _deferred_, where
|
18
|
+
# object instantiation is delayed until request time.
|
19
|
+
#
|
20
|
+
# ==== Immediate web service object example
|
21
|
+
#
|
22
|
+
# class ApiController < ApplicationController
|
23
|
+
# web_service_dispatching_mode :delegated
|
24
|
+
#
|
25
|
+
# web_service :person, PersonService.new
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# For deferred instantiation, a block should be given instead of an
|
29
|
+
# object instance. This block will be executed in controller instance
|
30
|
+
# context, so it can rely on controller instance variables being present.
|
31
|
+
#
|
32
|
+
# ==== Deferred web service object example
|
33
|
+
#
|
34
|
+
# class ApiController < ApplicationController
|
35
|
+
# web_service_dispatching_mode :delegated
|
36
|
+
#
|
37
|
+
# web_service(:person) { PersonService.new(@request.env) }
|
38
|
+
# end
|
39
|
+
def web_service(name, object=nil, &block)
|
40
|
+
if (object && block_given?) || (object.nil? && block.nil?)
|
41
|
+
raise(ContainerError, "either service, or a block must be given")
|
42
|
+
end
|
43
|
+
name = name.to_sym
|
44
|
+
if block_given?
|
45
|
+
info = { name => { :block => block } }
|
46
|
+
else
|
47
|
+
info = { name => { :object => object } }
|
48
|
+
end
|
49
|
+
write_inheritable_hash("web_services", info)
|
50
|
+
call_web_service_definition_callbacks(self, name, info)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Whether this service contains a service with the given +name+
|
54
|
+
def has_web_service?(name)
|
55
|
+
web_services.has_key?(name.to_sym)
|
56
|
+
end
|
57
|
+
|
58
|
+
def web_services # :nodoc:
|
59
|
+
read_inheritable_attribute("web_services") || {}
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_web_service_definition_callback(&block) # :nodoc:
|
63
|
+
write_inheritable_array("web_service_definition_callbacks", [block])
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
def call_web_service_definition_callbacks(container_class, web_service_name, service_info)
|
68
|
+
(read_inheritable_attribute("web_service_definition_callbacks") || []).each do |block|
|
69
|
+
block.call(container_class, web_service_name, service_info)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
module InstanceMethods # :nodoc:
|
75
|
+
def web_service_object(web_service_name)
|
76
|
+
info = self.class.web_services[web_service_name.to_sym]
|
77
|
+
unless info
|
78
|
+
raise(ContainerError, "no such web service '#{web_service_name}'")
|
79
|
+
end
|
80
|
+
service = info[:block]
|
81
|
+
service ? instance_eval(&service) : info[:object]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
|
3
|
+
module ActionWebService # :nodoc:
|
4
|
+
module Dispatcher # :nodoc:
|
5
|
+
class DispatcherError < ActionWebService::ActionWebServiceError # :nodoc:
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.append_features(base) # :nodoc:
|
9
|
+
super
|
10
|
+
base.class_inheritable_option(:web_service_dispatching_mode, :direct)
|
11
|
+
base.class_inheritable_option(:web_service_exception_reporting, true)
|
12
|
+
base.send(:include, ActionWebService::Dispatcher::InstanceMethods)
|
13
|
+
end
|
14
|
+
|
15
|
+
module InstanceMethods # :nodoc:
|
16
|
+
private
|
17
|
+
def dispatch_web_service_request(action_pack_request)
|
18
|
+
protocol_request = protocol_response = nil
|
19
|
+
bm = Benchmark.measure do
|
20
|
+
protocol_request = probe_request_protocol(action_pack_request)
|
21
|
+
protocol_response = dispatch_protocol_request(protocol_request)
|
22
|
+
end
|
23
|
+
[protocol_request, protocol_response, bm.real, nil]
|
24
|
+
rescue Exception => e
|
25
|
+
protocol_response = prepare_exception_response(protocol_request, e)
|
26
|
+
[protocol_request, prepare_exception_response(protocol_request, e), nil, e]
|
27
|
+
end
|
28
|
+
|
29
|
+
def dispatch_protocol_request(protocol_request)
|
30
|
+
case web_service_dispatching_mode
|
31
|
+
when :direct
|
32
|
+
dispatch_direct_request(protocol_request)
|
33
|
+
when :delegated
|
34
|
+
dispatch_delegated_request(protocol_request)
|
35
|
+
else
|
36
|
+
raise(ContainerError, "unsupported dispatching mode :#{web_service_dispatching_mode}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def dispatch_direct_request(protocol_request)
|
41
|
+
request = prepare_dispatch_request(protocol_request)
|
42
|
+
return_value = direct_invoke(request)
|
43
|
+
protocol_request.marshal(return_value)
|
44
|
+
end
|
45
|
+
|
46
|
+
def dispatch_delegated_request(protocol_request)
|
47
|
+
request = prepare_dispatch_request(protocol_request)
|
48
|
+
return_value = delegated_invoke(request)
|
49
|
+
protocol_request.marshal(return_value)
|
50
|
+
end
|
51
|
+
|
52
|
+
def direct_invoke(request)
|
53
|
+
return nil unless before_direct_invoke(request)
|
54
|
+
return_value = send(request.method_name)
|
55
|
+
after_direct_invoke(request)
|
56
|
+
return_value
|
57
|
+
end
|
58
|
+
|
59
|
+
def before_direct_invoke(request)
|
60
|
+
@method_params = request.params
|
61
|
+
end
|
62
|
+
|
63
|
+
def after_direct_invoke(request)
|
64
|
+
end
|
65
|
+
|
66
|
+
def delegated_invoke(request)
|
67
|
+
cancellation_reason = nil
|
68
|
+
web_service = request.web_service
|
69
|
+
return_value = web_service.perform_invocation(request.method_name, request.params) do |x|
|
70
|
+
cancellation_reason = x
|
71
|
+
end
|
72
|
+
if cancellation_reason
|
73
|
+
raise(DispatcherError, "request canceled: #{cancellation_reason}")
|
74
|
+
end
|
75
|
+
return_value
|
76
|
+
end
|
77
|
+
|
78
|
+
def prepare_dispatch_request(protocol_request)
|
79
|
+
api = method_name = web_service_name = web_service = params = nil
|
80
|
+
public_method_name = protocol_request.public_method_name
|
81
|
+
case web_service_dispatching_mode
|
82
|
+
when :direct
|
83
|
+
api = self.class.web_service_api
|
84
|
+
when :delegated
|
85
|
+
web_service_name = protocol_request.web_service_name
|
86
|
+
web_service = web_service_object(web_service_name)
|
87
|
+
api = web_service.class.web_service_api
|
88
|
+
end
|
89
|
+
method_name = api.api_method_name(public_method_name)
|
90
|
+
signature = nil
|
91
|
+
if method_name
|
92
|
+
signature = api.api_methods[method_name]
|
93
|
+
protocol_request.type = Protocol::CheckedMessage
|
94
|
+
protocol_request.signature = signature[:expects]
|
95
|
+
protocol_request.return_signature = signature[:returns]
|
96
|
+
else
|
97
|
+
method_name = api.default_api_method
|
98
|
+
if method_name
|
99
|
+
protocol_request.type = Protocol::UncheckedMessage
|
100
|
+
else
|
101
|
+
raise(DispatcherError, "no such method #{web_service_name}##{public_method_name}")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
params = protocol_request.unmarshal
|
105
|
+
DispatchRequest.new(
|
106
|
+
:api => api,
|
107
|
+
:public_method_name => public_method_name,
|
108
|
+
:method_name => method_name,
|
109
|
+
:signature => signature,
|
110
|
+
:web_service_name => web_service_name,
|
111
|
+
:web_service => web_service,
|
112
|
+
:params => params)
|
113
|
+
end
|
114
|
+
|
115
|
+
def prepare_exception_response(protocol_request, exception)
|
116
|
+
if protocol_request && exception
|
117
|
+
case web_service_dispatching_mode
|
118
|
+
when :direct
|
119
|
+
if web_service_exception_reporting
|
120
|
+
return protocol_request.protocol.marshal_exception(exception)
|
121
|
+
end
|
122
|
+
when :delegated
|
123
|
+
web_service = web_service_object(protocol_request.web_service_name)
|
124
|
+
if web_service && web_service.class.web_service_exception_reporting
|
125
|
+
return protocol_request.protocol.marshal_exception(exception)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
else
|
129
|
+
protocol_request.protocol.marshal_exception(RuntimeError.new("missing protocol request or exception"))
|
130
|
+
end
|
131
|
+
rescue Exception
|
132
|
+
nil
|
133
|
+
end
|
134
|
+
|
135
|
+
class DispatchRequest
|
136
|
+
attr :api
|
137
|
+
attr :public_method_name
|
138
|
+
attr :method_name
|
139
|
+
attr :signature
|
140
|
+
attr :web_service_name
|
141
|
+
attr :web_service
|
142
|
+
attr :params
|
143
|
+
|
144
|
+
def initialize(values={})
|
145
|
+
values.each{|k,v| instance_variable_set("@#{k.to_s}", v)}
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|