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
|
module WS
module Marshaling
class XmlRpcError < WSError
end
class XmlRpcMarshaler < AbstractMarshaler
def initialize
super()
@spec2binding = {}
end
def marshal(param)
value = param.value
cast_outbound_recursive(param.value, spec_for(param)) rescue value
end
def unmarshal(obj)
obj.param
end
def typed_unmarshal(obj, spec)
obj.param.info.data = lookup_type(spec)
value = obj.param.value
obj.param.value = cast_inbound_recursive(value, spec) rescue value
obj.param
end
def register_type(spec)
if @spec2binding.has_key?(spec)
return @spec2binding[spec]
end
klass = BaseTypes.canonical_param_type_class(spec)
type_binding = nil
if klass.is_a?(Array)
type_binding = XmlRpcArrayBinding.new(klass[0])
else
type_binding = XmlRpcBinding.new(klass)
end
@spec2binding[spec] = type_binding
end
alias :lookup_type :register_type
def cast_inbound_recursive(value, spec)
binding = lookup_type(spec)
case binding
when XmlRpcArrayBinding
value.map{ |x| cast_inbound(x, binding.element_klass) }
when XmlRpcBinding
cast_inbound(value, binding.klass)
end
end
def cast_outbound_recursive(value, spec)
binding = lookup_type(spec)
case binding
when XmlRpcArrayBinding
value.map{ |x| cast_outbound(x, binding.element_klass) }
when XmlRpcBinding
cast_outbound(value, binding.klass)
end
end
private
def spec_for(param)
binding = param.info.data
binding.is_a?(XmlRpcArrayBinding) ? [binding.element_klass] : binding.klass
end
def cast_inbound(value, klass)
if BaseTypes.base_type?(klass)
value = value.to_time if value.is_a?(XMLRPC::DateTime)
base_type_caster.cast(value, klass)
elsif value.is_a?(XMLRPC::FaultException)
value
elsif klass.ancestors.include?(ActionWebService::Struct)
obj = klass.new
klass.members.each do |name, klass|
name = name.to_s
obj.send('%s=' % name, cast_inbound_recursive(value[name], klass))
end
obj
else
obj = klass.new
if obj.respond_to?(:update)
obj.update(value)
else
value.each do |name, val|
obj.send('%s=' % name.to_s, val)
end
end
obj
end
end
def cast_outbound(value, klass)
if BaseTypes.base_type?(klass)
base_type_caster.cast(value, klass)
elsif value.is_a?(Exception)
XMLRPC::FaultException.new(2, value.message)
elsif Object.const_defined?('ActiveRecord') && value.is_a?(ActiveRecord::Base)
value.attributes
elsif value.is_a?(ActionWebService::Struct)
struct = {}
value.class.members.each do |name, klass|
name = name.to_s
struct[name] = cast_outbound_recursive(value[name], klass)
end
struct
else
struct = {}
if value.respond_to?(:each_pair)
value.each_pair{ |key, value| struct[key] = value }
else
value.instance_variables.each do |name|
key = name.sub(/^@/, '')
struct[key] = value.instance_variable_get(name)
end
end
struct
end
end
end
class XmlRpcBinding
attr :klass
def initialize(klass)
@klass = klass
end
end
class XmlRpcArrayBinding < XmlRpcBinding
attr :element_klass
def initialize(element_klass)
super(Array)
@element_klass = element_klass
end
end
end
end
|