aboutsummaryrefslogtreecommitdiffstats
path: root/actionservice/lib/action_service/protocol
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2005-02-18 23:43:09 +0000
committerDavid Heinemeier Hansson <david@loudthinking.com>2005-02-18 23:43:09 +0000
commit7a67d0f617db7d2962b6c3b80466e21570b244bf (patch)
tree56fa640e31f4f7f22d34a246bc1b197706a07e3a /actionservice/lib/action_service/protocol
parentfdecb6843ba8c5b0f718225f343017e11fa7f711 (diff)
downloadrails-7a67d0f617db7d2962b6c3b80466e21570b244bf.tar.gz
rails-7a67d0f617db7d2962b6c3b80466e21570b244bf.tar.bz2
rails-7a67d0f617db7d2962b6c3b80466e21570b244bf.zip
Renamed Action Service to Action Web Service
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@669 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionservice/lib/action_service/protocol')
-rw-r--r--actionservice/lib/action_service/protocol/abstract.rb128
-rw-r--r--actionservice/lib/action_service/protocol/registry.rb55
-rw-r--r--actionservice/lib/action_service/protocol/soap.rb484
-rw-r--r--actionservice/lib/action_service/protocol/xmlrpc.rb183
4 files changed, 0 insertions, 850 deletions
diff --git a/actionservice/lib/action_service/protocol/abstract.rb b/actionservice/lib/action_service/protocol/abstract.rb
deleted file mode 100644
index bd02b6e829..0000000000
--- a/actionservice/lib/action_service/protocol/abstract.rb
+++ /dev/null
@@ -1,128 +0,0 @@
-module ActionService # :nodoc:
- module Protocol # :nodoc:
- CheckedMessage = :checked
- UncheckedMessage = :unchecked
-
- class ProtocolError < ActionService::ActionServiceError # :nodoc:
- end
-
- class AbstractProtocol # :nodoc:
- attr :container_class
-
- def initialize(container_class)
- @container_class = container_class
- end
-
- def unmarshal_request(protocol_request)
- raise NotImplementedError
- end
-
- def marshal_response(protocol_request, return_value)
- raise NotImplementedError
- end
-
- def marshal_exception(exception)
- raise NotImplementedError
- end
-
- def self.create_protocol_request(container_class, action_pack_request)
- nil
- end
-
- def self.create_protocol_client(api, protocol_name, endpoint_uri, options)
- nil
- end
- end
-
- class AbstractProtocolMessage # :nodoc:
- attr_accessor :signature
- attr_accessor :return_signature
- attr_accessor :type
- attr :options
-
- def initialize(options={})
- @signature = @return_signature = nil
- @options = options
- @type = @options[:type] || CheckedMessage
- end
-
- def signature=(value)
- return if value.nil?
- @signature = []
- value.each do |klass|
- if klass.is_a?(Hash)
- @signature << klass.values.shift
- else
- @signature << klass
- end
- end
- @signature
- end
-
- def checked?
- @type == CheckedMessage
- end
-
- def check_parameter_types(values, signature)
- return unless checked? && signature
- unless signature.length == values.length
- raise(ProtocolError, "Signature and parameter lengths mismatch")
- end
- (1..signature.length).each do |i|
- check_compatibility(signature[i-1], values[i-1].class)
- end
- end
-
- def check_compatibility(expected_class, received_class)
- return if \
- (expected_class == TrueClass or expected_class == FalseClass) and \
- (received_class == TrueClass or received_class == FalseClass)
- unless received_class.ancestors.include?(expected_class) or \
- expected_class.ancestors.include?(received_class)
- raise(ProtocolError, "value of type #{received_class.name} is not " +
- "compatible with expected type #{expected_class.name}")
- end
- end
- end
-
- class ProtocolRequest < AbstractProtocolMessage # :nodoc:
- attr :protocol
- attr :raw_body
-
- attr_accessor :web_service_name
- attr_accessor :public_method_name
- attr_accessor :content_type
-
- def initialize(protocol, raw_body, web_service_name, public_method_name, content_type, options={})
- super(options)
- @protocol = protocol
- @raw_body = raw_body
- @web_service_name = web_service_name
- @public_method_name = public_method_name
- @content_type = content_type
- end
-
- def unmarshal
- @protocol.unmarshal_request(self)
- end
-
- def marshal(return_value)
- @protocol.marshal_response(self, return_value)
- end
- end
-
- class ProtocolResponse < AbstractProtocolMessage # :nodoc:
- attr :protocol
- attr :raw_body
-
- attr_accessor :content_type
-
- def initialize(protocol, raw_body, content_type, options={})
- super(options)
- @protocol = protocol
- @raw_body = raw_body
- @content_type = content_type
- end
- end
- end
-end
diff --git a/actionservice/lib/action_service/protocol/registry.rb b/actionservice/lib/action_service/protocol/registry.rb
deleted file mode 100644
index e06361f916..0000000000
--- a/actionservice/lib/action_service/protocol/registry.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-module ActionService # :nodoc:
- module Protocol # :nodoc:
- HeaderAndBody = :header_and_body
- BodyOnly = :body_only
-
- module Registry # :nodoc:
- def self.append_features(base) # :nodoc:
- super
- base.extend(ClassMethods)
- base.send(:include, ActionService::Protocol::Registry::InstanceMethods)
- end
-
- module ClassMethods # :nodoc:
- def register_protocol(type, klass) # :nodoc:
- case type
- when HeaderAndBody
- write_inheritable_array("header_and_body_protocols", [klass])
- when BodyOnly
- write_inheritable_array("body_only_protocols", [klass])
- else
- raise(ProtocolError, "unknown protocol type #{type}")
- end
- end
- end
-
- module InstanceMethods # :nodoc:
- private
- def probe_request_protocol(action_pack_request)
- (header_and_body_protocols + body_only_protocols).each do |protocol|
- protocol_request = protocol.create_protocol_request(self.class, action_pack_request)
- return protocol_request if protocol_request
- end
- raise(ProtocolError, "unsupported request message format")
- end
-
- def probe_protocol_client(api, protocol_name, endpoint_uri, options)
- (header_and_body_protocols + body_only_protocols).each do |protocol|
- protocol_client = protocol.create_protocol_client(api, protocol_name, endpoint_uri, options)
- return protocol_client if protocol_client
- end
- raise(ProtocolError, "unsupported client protocol :#{protocol_name}")
- end
-
- def header_and_body_protocols
- self.class.read_inheritable_attribute("header_and_body_protocols") || []
- end
-
- def body_only_protocols
- self.class.read_inheritable_attribute("body_only_protocols") || []
- end
- end
-
- end
- end
-end
diff --git a/actionservice/lib/action_service/protocol/soap.rb b/actionservice/lib/action_service/protocol/soap.rb
deleted file mode 100644
index 993e174e52..0000000000
--- a/actionservice/lib/action_service/protocol/soap.rb
+++ /dev/null
@@ -1,484 +0,0 @@
-require 'soap/processor'
-require 'soap/mapping'
-require 'soap/rpc/element'
-require 'xsd/datatypes'
-require 'xsd/ns'
-require 'singleton'
-
-module ActionService # :nodoc:
- module Protocol # :nodoc:
- module Soap # :nodoc:
- class ProtocolError < ActionService::ActionServiceError # :nodoc:
- end
-
- def self.append_features(base) # :nodoc:
- super
- base.register_protocol(HeaderAndBody, SoapProtocol)
- base.extend(ClassMethods)
- base.wsdl_service_name('ActionService')
- end
-
- module ClassMethods
- # Specifies the WSDL service name to use when generating WSDL. Highly
- # recommended that you set this value, or code generators may generate
- # classes with very generic names.
- #
- # === Example
- # class MyController < ActionController::Base
- # wsdl_service_name 'MyService'
- # end
- def wsdl_service_name(name)
- write_inheritable_attribute("soap_mapper", SoapMapper.new("urn:#{name}"))
- end
-
- def soap_mapper # :nodoc:
- read_inheritable_attribute("soap_mapper")
- end
- end
-
- class SoapProtocol < AbstractProtocol # :nodoc:
- attr :mapper
-
- def initialize(mapper)
- @mapper = mapper
- end
-
- def self.create_protocol_request(container_class, action_pack_request)
- soap_action = extract_soap_action(action_pack_request)
- return nil unless soap_action
- service_name = action_pack_request.parameters['action']
- public_method_name = soap_action.gsub(/^[\/]+/, '').split(/[\/]+/)[-1]
- content_type = action_pack_request.env['HTTP_CONTENT_TYPE']
- content_type ||= 'text/xml'
- protocol = SoapProtocol.new(container_class.soap_mapper)
- ProtocolRequest.new(protocol,
- action_pack_request.raw_post,
- service_name.to_sym,
- public_method_name,
- content_type)
- end
-
- def self.create_protocol_client(api, protocol_name, endpoint_uri, options)
- return nil unless protocol_name.to_s.downcase.to_sym == :soap
- ActionService::Client::Soap.new(api, endpoint_uri, options)
- end
-
- def unmarshal_request(protocol_request)
- unmarshal = lambda do
- envelope = SOAP::Processor.unmarshal(protocol_request.raw_body)
- request = envelope.body.request
- values = request.collect{|k, v| request[k]}
- soap_to_ruby_array(values)
- end
- signature = protocol_request.signature
- if signature
- map_signature_types(signature)
- values = unmarshal.call
- signature = signature.map{|x|mapper.lookup(x).ruby_klass}
- protocol_request.check_parameter_types(values, signature)
- values
- else
- if protocol_request.checked?
- []
- else
- unmarshal.call
- end
- end
- end
-
- def marshal_response(protocol_request, return_value)
- marshal = lambda do |signature|
- mapping = mapper.lookup(signature[0])
- return_value = fixup_array_types(mapping, return_value)
- signature = signature.map{|x|mapper.lookup(x).ruby_klass}
- protocol_request.check_parameter_types([return_value], signature)
- param_def = [['retval', 'return', mapping.registry_mapping]]
- [param_def, ruby_to_soap(return_value)]
- end
- signature = protocol_request.return_signature
- param_def = nil
- if signature
- param_def, return_value = marshal.call(signature)
- else
- if protocol_request.checked?
- param_def, return_value = nil, nil
- else
- param_def, return_value = marshal.call([return_value.class])
- end
- end
- qname = XSD::QName.new(mapper.custom_namespace,
- protocol_request.public_method_name)
- response = SOAP::RPC::SOAPMethodResponse.new(qname, param_def)
- response.retval = return_value unless return_value.nil?
- ProtocolResponse.new(self, create_response(response), 'text/xml')
- end
-
- def marshal_exception(exc)
- ProtocolResponse.new(self, create_exception_response(exc), 'text/xml')
- end
-
- private
- def self.extract_soap_action(request)
- return nil unless request.method == :post
- content_type = request.env['HTTP_CONTENT_TYPE'] || 'text/xml'
- return nil unless content_type
- soap_action = request.env['HTTP_SOAPACTION']
- return nil unless soap_action
- soap_action.gsub!(/^"/, '')
- soap_action.gsub!(/"$/, '')
- soap_action.strip!
- return nil if soap_action.empty?
- soap_action
- end
-
- def fixup_array_types(mapping, obj)
- mapping.each_attribute do |name, type, attr_mapping|
- if attr_mapping.custom_type?
- attr_obj = obj.send(name)
- new_obj = fixup_array_types(attr_mapping, attr_obj)
- obj.send("#{name}=", new_obj) unless new_obj.equal?(attr_obj)
- end
- end
- if mapping.is_a?(SoapArrayMapping)
- obj = mapping.ruby_klass.new(obj)
- # man, this is going to be slow for big arrays :(
- (1..obj.size).each do |i|
- i -= 1
- obj[i] = fixup_array_types(mapping.element_mapping, obj[i])
- end
- else
- if !mapping.generated_klass.nil? && mapping.generated_klass.respond_to?(:members)
- # have to map the publically visible structure of the class
- new_obj = mapping.generated_klass.new
- mapping.generated_klass.members.each do |name, klass|
- new_obj.send("#{name}=", obj.send(name))
- end
- obj = new_obj
- end
- end
- obj
- end
-
- def map_signature_types(types)
- types.collect{|type| mapper.map(type)}
- end
-
- def create_response(body)
- header = SOAP::SOAPHeader.new
- body = SOAP::SOAPBody.new(body)
- envelope = SOAP::SOAPEnvelope.new(header, body)
- SOAP::Processor.marshal(envelope)
- end
-
- def create_exception_response(exc)
- detail = SOAP::Mapping::SOAPException.new(exc)
- body = SOAP::SOAPFault.new(
- SOAP::SOAPString.new('Server'),
- SOAP::SOAPString.new(exc.to_s),
- SOAP::SOAPString.new(self.class.name),
- SOAP::Mapping.obj2soap(detail))
- create_response(body)
- end
-
- def ruby_to_soap(obj)
- SOAP::Mapping.obj2soap(obj, mapper.registry)
- end
-
- def soap_to_ruby(obj)
- SOAP::Mapping.soap2obj(obj, mapper.registry)
- end
-
- def soap_to_ruby_array(array)
- array.map{|x| soap_to_ruby(x)}
- end
- end
-
- class SoapMapper # :nodoc:
- attr :registry
- attr :custom_namespace
- attr :custom_types
-
- def initialize(custom_namespace)
- @custom_namespace = custom_namespace
- @registry = SOAP::Mapping::Registry.new
- @klass2map = {}
- @custom_types = {}
- @ar2klass = {}
- end
-
- def lookup(klass)
- lookup_klass = klass.is_a?(Array) ? klass[0] : klass
- generated_klass = nil
- unless lookup_klass.respond_to?(:ancestors)
- raise(ProtocolError, "expected parameter type definition to be a Class")
- end
- if lookup_klass.ancestors.include?(ActiveRecord::Base)
- generated_klass = @ar2klass.has_key?(klass) ? @ar2klass[klass] : nil
- klass = generated_klass if generated_klass
- end
- return @klass2map[klass] if @klass2map.has_key?(klass)
-
- custom_type = false
-
- ruby_klass = select_class(lookup_klass)
- generated_klass = @ar2klass[lookup_klass] if @ar2klass.has_key?(lookup_klass)
- type_name = ruby_klass.name
-
- # Array signatures generate a double-mapping and require generation
- # of an Array subclass to represent the mapping in the SOAP
- # registry
- array_klass = nil
- if klass.is_a?(Array)
- array_klass = Class.new(Array) do
- module_eval <<-END
- def self.name
- "#{type_name}Array"
- end
- END
- end
- end
-
- mapping = @registry.find_mapped_soap_class(ruby_klass) rescue nil
- unless mapping
- # Custom structured type, generate a mapping
- info = { :type => XSD::QName.new(@custom_namespace, type_name) }
- @registry.add(ruby_klass,
- SOAP::SOAPStruct,
- SOAP::Mapping::Registry::TypedStructFactory,
- info)
- mapping = ensure_mapped(ruby_klass)
- custom_type = true
- end
-
- array_mapping = nil
- if array_klass
- # Typed array always requires a custom type. The info of the array
- # is the info of its element type (in mapping[2]), falling back
- # to SOAP base types.
- info = mapping[2]
- info ||= {}
- info[:type] ||= soap_base_type_qname(mapping[0])
- @registry.add(array_klass,
- SOAP::SOAPArray,
- SOAP::Mapping::Registry::TypedArrayFactory,
- info)
- array_mapping = ensure_mapped(array_klass)
- end
-
- if array_mapping
- @klass2map[ruby_klass] = SoapMapping.new(self,
- type_name,
- ruby_klass,
- generated_klass,
- mapping[0],
- mapping,
- custom_type)
- @klass2map[klass] = SoapArrayMapping.new(self,
- type_name,
- array_klass,
- array_mapping[0],
- array_mapping,
- @klass2map[ruby_klass])
- @custom_types[klass] = @klass2map[klass]
- @custom_types[ruby_klass] = @klass2map[ruby_klass] if custom_type
- else
- @klass2map[klass] = SoapMapping.new(self,
- type_name,
- ruby_klass,
- generated_klass,
- mapping[0],
- mapping,
- custom_type)
- @custom_types[klass] = @klass2map[klass] if custom_type
- end
-
- @klass2map[klass]
- end
- alias :map :lookup
-
- def map_container_services(container, &block)
- dispatching_mode = container.web_service_dispatching_mode
- web_services = nil
- case dispatching_mode
- when :direct
- api = container.class.web_service_api
- if container.respond_to?(:controller_class_name)
- web_service_name = container.controller_class_name.sub(/Controller$/, '').underscore
- else
- web_service_name = container.class.name.demodulize.underscore
- end
- web_services = { web_service_name => api }
- when :delegated
- web_services = {}
- container.class.web_services.each do |web_service_name, web_service_info|
- begin
- object = container.web_service_object(web_service_name)
- rescue Exception => e
- raise(ProtocolError, "failed to retrieve web service object for web service '#{web_service_name}': #{e.message}")
- end
- web_services[web_service_name] = object.class.web_service_api
- end
- end
- web_services.each do |web_service_name, api|
- if api.nil?
- raise(ProtocolError, "no web service API set while in :#{dispatching_mode} mode")
- end
- map_api(api) do |api_methods|
- yield web_service_name, api, api_methods if block_given?
- end
- end
- end
-
- def map_api(api, &block)
- lookup_proc = lambda do |klass|
- mapping = lookup(klass)
- custom_mapping = nil
- if mapping.respond_to?(:element_mapping)
- custom_mapping = mapping.element_mapping
- else
- custom_mapping = mapping
- end
- if custom_mapping && custom_mapping.custom_type?
- # What gives? This is required so that structure types
- # referenced only by structures (and not signatures) still
- # have a custom type mapping in the registry (needed for WSDL
- # generation).
- custom_mapping.each_attribute{}
- end
- mapping
- end
- api_methods = block.nil?? nil : {}
- api.api_methods.each do |method_name, method_info|
- expects = method_info[:expects]
- expects_signature = nil
- if expects
- expects_signature = block ? [] : nil
- expects.each do |klass|
- lookup_klass = nil
- if klass.is_a?(Hash)
- lookup_klass = lookup_proc.call(klass.values[0])
- expects_signature << {klass.keys[0]=>lookup_klass} if block
- else
- lookup_klass = lookup_proc.call(klass)
- expects_signature << lookup_klass if block
- end
- end
- end
- returns = method_info[:returns]
- returns_signature = returns ? returns.map{|klass| lookup_proc.call(klass)} : nil
- if block
- api_methods[method_name] = {
- :expects => expects_signature,
- :returns => returns_signature
- }
- end
- end
- yield api_methods if block
- end
-
- private
- def select_class(klass)
- return Integer if klass == Fixnum
- if klass.ancestors.include?(ActiveRecord::Base)
- new_klass = Class.new(ActionService::Struct)
- new_klass.class_eval <<-EOS
- def self.name
- "#{klass.name}"
- end
- EOS
- klass.columns.each do |column|
- next if column.klass.nil?
- new_klass.send(:member, column.name.to_sym, column.klass)
- end
- @ar2klass[klass] = new_klass
- return new_klass
- end
- klass
- end
-
- def ensure_mapped(klass)
- mapping = @registry.find_mapped_soap_class(klass) rescue nil
- raise(ProtocolError, "failed to register #{klass.name}") unless mapping
- mapping
- end
-
- def soap_base_type_qname(base_type)
- xsd_type = base_type.ancestors.find{|c| c.const_defined? 'Type'}
- xsd_type ? xsd_type.const_get('Type') : XSD::XSDAnySimpleType::Type
- end
- end
-
- class SoapMapping # :nodoc:
- attr :ruby_klass
- attr :generated_klass
- attr :soap_klass
- attr :registry_mapping
-
- def initialize(mapper, type_name, ruby_klass, generated_klass, soap_klass, registry_mapping,
- custom_type=false)
- @mapper = mapper
- @type_name = type_name
- @ruby_klass = ruby_klass
- @generated_klass = generated_klass
- @soap_klass = soap_klass
- @registry_mapping = registry_mapping
- @custom_type = custom_type
- end
-
- def type_name
- @type_name
- end
-
- def custom_type?
- @custom_type
- end
-
- def qualified_type_name
- name = type_name
- if custom_type?
- "typens:#{name}"
- else
- xsd_type_for(@soap_klass)
- end
- end
-
- def each_attribute(&block)
- if @ruby_klass.respond_to?(:members)
- @ruby_klass.members.each do |name, klass|
- name = name.to_s
- mapping = @mapper.lookup(klass)
- yield name, mapping.qualified_type_name, mapping
- end
- end
- end
-
- def is_xsd_type?(klass)
- klass.ancestors.include?(XSD::NSDBase)
- end
-
- def xsd_type_for(klass)
- ns = XSD::NS.new
- ns.assign(XSD::Namespace, SOAP::XSDNamespaceTag)
- xsd_klass = klass.ancestors.find{|c| c.const_defined?('Type')}
- return ns.name(XSD::AnyTypeName) unless xsd_klass
- ns.name(xsd_klass.const_get('Type'))
- end
- end
-
- class SoapArrayMapping < SoapMapping # :nodoc:
- attr :element_mapping
-
- def initialize(mapper, type_name, ruby_klass, soap_klass, registry_mapping, element_mapping)
- super(mapper, type_name, ruby_klass, nil, soap_klass, registry_mapping, true)
- @element_mapping = element_mapping
- end
-
- def type_name
- super + "Array"
- end
-
- def each_attribute(&block); end
- end
- end
- end
-end
diff --git a/actionservice/lib/action_service/protocol/xmlrpc.rb b/actionservice/lib/action_service/protocol/xmlrpc.rb
deleted file mode 100644
index 32b8e00327..0000000000
--- a/actionservice/lib/action_service/protocol/xmlrpc.rb
+++ /dev/null
@@ -1,183 +0,0 @@
-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 ActionService # :nodoc:
- module Protocol # :nodoc:
- module XmlRpc # :nodoc:
- def self.append_features(base) # :nodoc:
- super
- base.register_protocol(BodyOnly, XmlRpcProtocol)
- end
-
- 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
- ActionService::Client::XmlRpc.new(api, endpoint_uri, options)
- end
-
- def initialize(container_class)
- super(container_class)
- container_class.write_inheritable_hash('default_system_methods', XmlRpcProtocol => method(:xmlrpc_default_system_handler))
- 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)
- 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
- end
- ProtocolResponse.new(self, raw_response, '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?(ActionService::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?(ActionService::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 transform_array_types(signature)
- signature.map{|x| x.is_a?(Array) ? XmlRpcArray.new(x[0]) : x}
- end
- end
-
- private
- def xmlrpc_default_system_handler(name, service_class, *args)
- case name
- when 'system.listMethods'
- methods = []
- api = service_class.web_service_api
- api.api_methods.each do |name, info|
- methods << api.public_api_method_name(name)
- end
- methods.sort
- else
- throw :try_default
- end
- end
-
- 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
-end