diff options
Diffstat (limited to 'actionwebservice/lib/action_web_service/vendor/ws/marshaling/xmlrpc_marshaling.rb')
-rw-r--r-- | actionwebservice/lib/action_web_service/vendor/ws/marshaling/xmlrpc_marshaling.rb | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/actionwebservice/lib/action_web_service/vendor/ws/marshaling/xmlrpc_marshaling.rb b/actionwebservice/lib/action_web_service/vendor/ws/marshaling/xmlrpc_marshaling.rb new file mode 100644 index 0000000000..87154f87e1 --- /dev/null +++ b/actionwebservice/lib/action_web_service/vendor/ws/marshaling/xmlrpc_marshaling.rb @@ -0,0 +1,116 @@ +module WS + module Marshaling + class XmlRpcError < WSError + end + + class XmlRpcMarshaler < AbstractMarshaler + def initialize + @caster = BaseTypeCaster.new + @spec2binding = {} + end + + def marshal(param) + transform_outbound(param) + end + + def unmarshal(obj) + obj.param.value = transform_inbound(obj.param) + obj.param + end + + def typed_unmarshal(obj, spec) + param = obj.param + param.info.data = register_type(spec) + param.value = transform_inbound(param) + 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 + + def transform_outbound(param) + binding = param.info.data + case binding + when XmlRpcArrayBinding + param.value.map{|x| cast_outbound(x, binding.element_klass)} + when XmlRpcBinding + cast_outbound(param.value, param.info.type) + end + end + + def transform_inbound(param) + return param.value if param.info.data.nil? + binding = param.info.data + param.info.type = binding.klass + case binding + when XmlRpcArrayBinding + param.value.map{|x| cast_inbound(x, binding.element_klass)} + when XmlRpcBinding + cast_inbound(param.value, param.info.type) + end + end + + def cast_outbound(value, klass) + if BaseTypes.base_type?(klass) + @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 + else + struct = {} + value.instance_variables.each do |name| + key = name.sub(/^@/, '') + struct[key] = value.instance_variable_get(name) + end + struct + end + end + + def cast_inbound(value, klass) + if BaseTypes.base_type?(klass) + value = value.to_time if value.is_a?(XMLRPC::DateTime) + @caster.cast(value, klass) + elsif value.is_a?(XMLRPC::FaultException) + value + else + obj = klass.new + value.each do |name, val| + obj.send('%s=' % name.to_s, val) + end + obj + 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 |