diff options
Diffstat (limited to 'actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb')
-rw-r--r-- | actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb | 184 |
1 files changed, 32 insertions, 152 deletions
diff --git a/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb b/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb index 1addccba56..1533a2bdb9 100644 --- a/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb +++ b/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb @@ -1,167 +1,47 @@ -require 'xmlrpc/parser' -require 'xmlrpc/create' -require 'xmlrpc/config' -require 'xmlrpc/utils' -require 'singleton' - -module XMLRPC # :nodoc: - class XmlRpcHelper # :nodoc: - include Singleton - include ParserWriterChooseMixin - - def parse_method_call(message) - parser().parseMethodCall(message) - end - - def create_method_response(successful, return_value) - create().methodResponse(successful, return_value) - end - end -end - -module ActionWebService # :nodoc: - module Protocol # :nodoc: - module XmlRpc # :nodoc: - def self.append_features(base) # :nodoc: - super - base.register_protocol(BodyOnly, XmlRpcProtocol) +module ActionWebService + module Protocol + module XmlRpc + def self.included(base) + base.register_protocol(XmlRpcProtocol) end + + class XmlRpcProtocol + attr :marshaler - class XmlRpcProtocol < AbstractProtocol # :nodoc: - def self.create_protocol_request(container_class, action_pack_request) - helper = XMLRPC::XmlRpcHelper.instance - service_name = action_pack_request.parameters['action'] - methodname, params = helper.parse_method_call(action_pack_request.raw_post) - methodname.gsub!(/^[^\.]+\./, '') unless methodname =~ /^system\./ # XXX - protocol = XmlRpcProtocol.new(container_class) - content_type = action_pack_request.env['HTTP_CONTENT_TYPE'] - content_type ||= 'text/xml' - request = ProtocolRequest.new(protocol, - action_pack_request.raw_post, - service_name.to_sym, - methodname, - content_type, - :xmlrpc_values => params) - request - rescue - nil - end - - def self.create_protocol_client(api, protocol_name, endpoint_uri, options) - return nil unless protocol_name.to_s.downcase.to_sym == :xmlrpc - ActionWebService::Client::XmlRpc.new(api, endpoint_uri, options) + def initialize + @encoder = WS::Encoding::XmlRpcEncoding.new + @marshaler = WS::Marshaling::XmlRpcMarshaler.new end - def initialize(container_class) - super(container_class) + def unmarshal_request(ap_request) + method_name, params = @encoder.decode_rpc_call(ap_request.raw_post) + params = params.map{|x| @marshaler.unmarshal(x)} + service_name = ap_request.parameters['action'] + Request.new(self, method_name, params, service_name) + rescue + nil end - def unmarshal_request(protocol_request) - values = protocol_request.options[:xmlrpc_values] - signature = protocol_request.signature - if signature - values = self.class.transform_incoming_method_params(self.class.transform_array_types(signature), values) - protocol_request.check_parameter_types(values, check_array_types(signature)) - values - else - protocol_request.checked? ? [] : values - end - end - - def marshal_response(protocol_request, return_value) - helper = XMLRPC::XmlRpcHelper.instance - signature = protocol_request.return_signature - if signature - protocol_request.check_parameter_types([return_value], check_array_types(signature)) - return_value = self.class.transform_return_value(self.class.transform_array_types(signature), return_value) - raw_response = helper.create_method_response(true, return_value) + def marshal_response(method_name, return_value, signature_type) + if !return_value.nil? && signature_type + type_binding = @marshaler.register_type(signature_type) + info = WS::ParamInfo.create(signature_type, 0, type_binding) + return_value = @marshaler.marshal(WS::Param.new(return_value, info)) else - # XML-RPC doesn't have the concept of a void method, nor does it - # support a nil return value, so return true if we would have returned - # nil - if protocol_request.checked? - raw_response = helper.create_method_response(true, true) - else - return_value = true if return_value.nil? - raw_response = helper.create_method_response(true, return_value) - end + return_value = nil end - ProtocolResponse.new(self, raw_response, 'text/xml') + body = @encoder.encode_rpc_response(method_name, return_value) + Response.new(body, 'text/xml') end - - def marshal_exception(exception) - helper = XMLRPC::XmlRpcHelper.instance - exception = XMLRPC::FaultException.new(1, exception.message) - raw_response = helper.create_method_response(false, exception) - ProtocolResponse.new(self, raw_response, 'text/xml') - end - - class << self - def transform_incoming_method_params(signature, params) - (1..signature.size).each do |i| - i -= 1 - params[i] = xmlrpc_to_ruby(params[i], signature[i]) - end - params - end - - def transform_return_value(signature, return_value) - ruby_to_xmlrpc(return_value, signature[0]) - end - - def ruby_to_xmlrpc(param, param_class) - if param_class.is_a?(XmlRpcArray) - param.map{|p| ruby_to_xmlrpc(p, param_class.klass)} - elsif param_class.ancestors.include?(ActiveRecord::Base) - param.instance_variable_get('@attributes') - elsif param_class.ancestors.include?(ActionWebService::Struct) - struct = {} - param_class.members.each do |name, klass| - value = param.send(name) - next if value.nil? - struct[name.to_s] = value - end - struct - else - param - end - end - def xmlrpc_to_ruby(param, param_class) - if param_class.is_a?(XmlRpcArray) - param.map{|p| xmlrpc_to_ruby(p, param_class.klass)} - elsif param_class.ancestors.include?(ActiveRecord::Base) - raise(ProtocolError, "incoming ActiveRecord::Base types are not allowed") - elsif param_class.ancestors.include?(ActionWebService::Struct) - unless param.is_a?(Hash) - raise(ProtocolError, "expected parameter to be a Hash") - end - new_param = param_class.new - param_class.members.each do |name, klass| - new_param.send('%s=' % name.to_s, param[name.to_s]) - end - new_param - else - param - end - end + def register_signature_type(spec) + nil + end - def transform_array_types(signature) - signature.map{|x| x.is_a?(Array) ? XmlRpcArray.new(x[0]) : x} - end + def protocol_client(api, protocol_name, endpoint_uri, options) + return nil unless protocol_name == :xmlrpc + ActionWebService::Client::XmlRpc.new(api, endpoint_uri, options) end - - private - def check_array_types(signature) - signature.map{|x| x.is_a?(Array) ? Array : x} - end - - class XmlRpcArray - attr :klass - def initialize(klass) - @klass = klass - end - end end end end |