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
|
require 'test/unit'
module Test
module Unit
class TestCase # :nodoc:
private
# invoke the specified API method
def invoke_direct(method_name, *args)
prepare_request('api', 'api', method_name, *args)
@controller.process(@request, @response)
decode_rpc_response
end
alias_method :invoke, :invoke_direct
# invoke the specified API method on the specified service
def invoke_delegated(service_name, method_name, *args)
prepare_request(service_name.to_s, service_name, method_name, *args)
@controller.process(@request, @response)
decode_rpc_response
end
# invoke the specified layered API method on the correct service
def invoke_layered(service_name, method_name, *args)
if protocol == :soap
raise "SOAP protocol support for :layered dispatching mode is not available"
end
prepare_request('api', service_name, method_name, *args)
@controller.process(@request, @response)
decode_rpc_response
end
# ---------------------- internal ---------------------------
def prepare_request(action, service_name, api_method_name, *args)
@request.request_parameters['action'] = action
@request.env['REQUEST_METHOD'] = 'POST'
@request.env['HTTP_CONTENT_TYPE'] = 'text/xml'
@request.env['RAW_POST_DATA'] = encode_rpc_call(service_name, api_method_name, *args)
case protocol
when :soap
soap_action = "/#{@controller.controller_name}/#{service_name}/#{public_method_name(service_name, api_method_name)}"
@request.env['HTTP_SOAPACTION'] = soap_action
when :xmlrpc
@request.env.delete('HTTP_SOAPACTION')
end
end
def encode_rpc_call(service_name, api_method_name, *args)
case @controller.web_service_dispatching_mode
when :direct
api = @controller.class.web_service_api
when :delegated, :layered
api = @controller.web_service_object(service_name.to_sym).class.web_service_api
end
info = api.api_methods[api_method_name.to_sym]
((info[:expects] || []) + (info[:returns] || [])).each do |spec|
marshaler.register_type spec
end
expects = info[:expects]
args = args.dup
(0..(args.length-1)).each do |i|
type_binding = marshaler.register_type(expects ? expects[i] : args[i].class)
info = WS::ParamInfo.create(expects ? expects[i] : args[i].class, type_binding, i)
args[i] = marshaler.marshal(WS::Param.new(args[i], info))
end
encoder.encode_rpc_call(public_method_name(service_name, api_method_name), args)
end
def decode_rpc_response
public_method_name, return_value = encoder.decode_rpc_response(@response.body)
result = marshaler.unmarshal(return_value).value
unless @return_exceptions
exception = is_exception?(result)
raise exception if exception
end
result
end
def public_method_name(service_name, api_method_name)
public_name = service_api(service_name).public_api_method_name(api_method_name)
if @controller.web_service_dispatching_mode == :layered
'%s.%s' % [service_name.to_s, public_name]
else
public_name
end
end
def service_api(service_name)
case @controller.web_service_dispatching_mode
when :direct
@controller.class.web_service_api
when :delegated, :layered
@controller.web_service_object(service_name.to_sym).class.web_service_api
end
end
def protocol
@protocol ||= :soap
end
def marshaler
case protocol
when :soap
@soap_marshaler ||= WS::Marshaling::SoapMarshaler.new 'urn:ActionWebService'
when :xmlrpc
@xmlrpc_marshaler ||= WS::Marshaling::XmlRpcMarshaler.new
end
end
def encoder
case protocol
when :soap
@soap_encoder ||= WS::Encoding::SoapRpcEncoding.new 'urn:ActionWebService'
when :xmlrpc
@xmlrpc_encoder ||= WS::Encoding::XmlRpcEncoding.new
end
end
def is_exception?(obj)
case protocol
when :soap
(obj.respond_to?(:detail) && obj.detail.respond_to?(:cause) && \
obj.detail.cause.is_a?(Exception)) ? obj.detail.cause : nil
when :xmlrpc
obj.is_a?(XMLRPC::FaultException) ? obj : nil
end
end
end
end
end
|