1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
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
def self.layered_service_name(public_method_name) # :nodoc:
if public_method_name =~ /^([^\.]+)\.(.*)$/
$1
else
nil
end
end
module InstanceMethods # :nodoc:
private
def invoke_web_service_request(protocol_request)
invocation = web_service_invocation(protocol_request)
case web_service_dispatching_mode
when :direct
web_service_direct_invoke(invocation)
when :delegated, :layered
web_service_delegated_invoke(invocation)
end
end
def web_service_direct_invoke(invocation)
@method_params = invocation.method_ordered_params
return_value = self.__send__(invocation.api_method_name)
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
def web_service_delegated_invoke(invocation)
cancellation_reason = nil
return_value = invocation.service.perform_invocation(invocation.api_method_name, invocation.method_ordered_params) do |x|
cancellation_reason = x
end
if cancellation_reason
raise(DispatcherError, "request canceled: #{cancellation_reason}")
end
returns = invocation.returns ? invocation.returns[0] : nil
invocation.protocol.marshal_response(invocation.public_method_name, return_value, returns)
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, :layered
invocation.service = web_service_object(invocation.service_name) rescue nil
unless invocation.service
raise(DispatcherError, "service #{invocation.service_name} not available")
end
invocation.api = invocation.service.class.web_service_api
end
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
info = invocation.api.api_methods[invocation.api_method_name]
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|
if invocation.protocol.is_a?(Protocol::XmlRpc::XmlRpcProtocol)
marshaler = invocation.protocol.marshaler
decoded_param = WS::Encoding::XmlRpcDecodedParam.new(param.info.name, param.value)
marshaled_param = marshaler.typed_unmarshal(decoded_param, invocation.expects[i]) rescue nil
param = marshaled_param ? marshaled_param : param
end
i += 1
param.value
end
i = 0
params = []
invocation.expects.each do |spec|
type_binding = invocation.protocol.register_signature_type(spec)
info = WS::ParamInfo.create(spec, type_binding, i)
params << WS::Param.new(invocation.method_ordered_params[i], info)
i += 1
end
invocation.method_ws_params = params
invocation.method_named_params = {}
invocation.method_ws_params.each do |param|
invocation.method_named_params[param.info.name] = param.value
end
else
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 # :nodoc:
attr_accessor :protocol
attr_accessor :service_name
attr_accessor :api
attr_accessor :public_method_name
attr_accessor :api_method_name
attr_accessor :method_ordered_params
attr_accessor :method_named_params
attr_accessor :method_ws_params
attr_accessor :expects
attr_accessor :returns
attr_accessor :service
end
end
end
end
|