rubyjedi-actionwebservice 2.3.5.20100615120735

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. data/CHANGELOG +335 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +381 -0
  4. data/Rakefile +180 -0
  5. data/TODO +32 -0
  6. data/examples/googlesearch/README +143 -0
  7. data/examples/googlesearch/autoloading/google_search_api.rb +50 -0
  8. data/examples/googlesearch/autoloading/google_search_controller.rb +57 -0
  9. data/examples/googlesearch/delegated/google_search_service.rb +108 -0
  10. data/examples/googlesearch/delegated/search_controller.rb +7 -0
  11. data/examples/googlesearch/direct/google_search_api.rb +50 -0
  12. data/examples/googlesearch/direct/search_controller.rb +58 -0
  13. data/examples/metaWeblog/README +17 -0
  14. data/examples/metaWeblog/apis/blogger_api.rb +60 -0
  15. data/examples/metaWeblog/apis/blogger_service.rb +34 -0
  16. data/examples/metaWeblog/apis/meta_weblog_api.rb +67 -0
  17. data/examples/metaWeblog/apis/meta_weblog_service.rb +48 -0
  18. data/examples/metaWeblog/controllers/xmlrpc_controller.rb +16 -0
  19. data/generators/web_service/USAGE +28 -0
  20. data/generators/web_service/templates/api_definition.rb +5 -0
  21. data/generators/web_service/templates/controller.rb +8 -0
  22. data/generators/web_service/templates/functional_test.rb +19 -0
  23. data/generators/web_service/web_service_generator.rb +29 -0
  24. data/lib/action_web_service/acts_as_web_service.rb +24 -0
  25. data/lib/action_web_service/api.rb +297 -0
  26. data/lib/action_web_service/base.rb +38 -0
  27. data/lib/action_web_service/casting.rb +151 -0
  28. data/lib/action_web_service/client/base.rb +28 -0
  29. data/lib/action_web_service/client/soap_client.rb +113 -0
  30. data/lib/action_web_service/client/xmlrpc_client.rb +58 -0
  31. data/lib/action_web_service/client.rb +3 -0
  32. data/lib/action_web_service/container/action_controller_container.rb +93 -0
  33. data/lib/action_web_service/container/delegated_container.rb +86 -0
  34. data/lib/action_web_service/container/direct_container.rb +69 -0
  35. data/lib/action_web_service/container.rb +3 -0
  36. data/lib/action_web_service/dispatcher/abstract.rb +208 -0
  37. data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +396 -0
  38. data/lib/action_web_service/dispatcher.rb +2 -0
  39. data/lib/action_web_service/invocation.rb +202 -0
  40. data/lib/action_web_service/protocol/abstract.rb +112 -0
  41. data/lib/action_web_service/protocol/discovery.rb +37 -0
  42. data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +242 -0
  43. data/lib/action_web_service/protocol/soap_protocol.rb +176 -0
  44. data/lib/action_web_service/protocol/xmlrpc_protocol.rb +123 -0
  45. data/lib/action_web_service/protocol.rb +4 -0
  46. data/lib/action_web_service/scaffolding.rb +281 -0
  47. data/lib/action_web_service/simple.rb +53 -0
  48. data/lib/action_web_service/string_to_datetime_for_soap.rb +16 -0
  49. data/lib/action_web_service/struct.rb +68 -0
  50. data/lib/action_web_service/support/class_inheritable_options.rb +26 -0
  51. data/lib/action_web_service/support/signature_types.rb +261 -0
  52. data/lib/action_web_service/templates/scaffolds/layout.html.erb +65 -0
  53. data/lib/action_web_service/templates/scaffolds/methods.html.erb +6 -0
  54. data/lib/action_web_service/templates/scaffolds/parameters.html.erb +29 -0
  55. data/lib/action_web_service/templates/scaffolds/result.html.erb +30 -0
  56. data/lib/action_web_service/test_invoke.rb +110 -0
  57. data/lib/action_web_service/version.rb +9 -0
  58. data/lib/action_web_service.rb +60 -0
  59. data/lib/actionwebservice.rb +1 -0
  60. data/setup.rb +1379 -0
  61. data/test/abstract_client.rb +184 -0
  62. data/test/abstract_dispatcher.rb +549 -0
  63. data/test/abstract_unit.rb +43 -0
  64. data/test/actionwebservice_unittest.db +0 -0
  65. data/test/api_test.rb +102 -0
  66. data/test/apis/auto_load_api.rb +3 -0
  67. data/test/apis/broken_auto_load_api.rb +2 -0
  68. data/test/base_test.rb +42 -0
  69. data/test/casting_test.rb +95 -0
  70. data/test/client_soap_test.rb +156 -0
  71. data/test/client_xmlrpc_test.rb +154 -0
  72. data/test/container_test.rb +75 -0
  73. data/test/debug.log +12305 -0
  74. data/test/dispatcher_action_controller_soap_test.rb +139 -0
  75. data/test/dispatcher_action_controller_xmlrpc_test.rb +59 -0
  76. data/test/fixtures/db_definitions/mysql.sql +8 -0
  77. data/test/fixtures/db_definitions/sqlite3.sql +8 -0
  78. data/test/fixtures/users.yml +12 -0
  79. data/test/gencov +3 -0
  80. data/test/invocation_test.rb +186 -0
  81. data/test/run +6 -0
  82. data/test/scaffolded_controller_test.rb +147 -0
  83. data/test/struct_test.rb +84 -0
  84. data/test/test_invoke_test.rb +113 -0
  85. metadata +182 -0
@@ -0,0 +1,112 @@
1
+ module ActionWebService # :nodoc:
2
+ module Protocol # :nodoc:
3
+ class ProtocolError < ActionWebServiceError # :nodoc:
4
+ end
5
+
6
+ class AbstractProtocol # :nodoc:
7
+ def setup(controller)
8
+ end
9
+
10
+ def decode_action_pack_request(action_pack_request)
11
+ end
12
+
13
+ def encode_action_pack_request(service_name, public_method_name, raw_body, options={})
14
+ klass = options[:request_class] || SimpleActionPackRequest
15
+ request = klass.new({})
16
+ request.request_parameters['action'] = service_name.to_s
17
+ request.env['RAW_POST_DATA'] = raw_body
18
+ request.env['REQUEST_METHOD'] = 'POST'
19
+ request.env['HTTP_CONTENT_TYPE'] = 'text/xml'
20
+ request
21
+ end
22
+
23
+ def decode_request(raw_request, service_name, protocol_options={})
24
+ end
25
+
26
+ def encode_request(method_name, params, param_types)
27
+ end
28
+
29
+ def decode_response(raw_response)
30
+ end
31
+
32
+ def encode_response(method_name, return_value, return_type, protocol_options={})
33
+ end
34
+
35
+ def protocol_client(api, protocol_name, endpoint_uri, options)
36
+ end
37
+
38
+ def register_api(api)
39
+ end
40
+ end
41
+
42
+ class Request # :nodoc:
43
+ attr :protocol
44
+ attr_accessor :method_name
45
+ attr_accessor :method_params
46
+ attr :service_name
47
+ attr_accessor :api
48
+ attr_accessor :api_method
49
+ attr :protocol_options
50
+
51
+ def initialize(protocol, method_name, method_params, service_name, api=nil, api_method=nil, protocol_options=nil)
52
+ @protocol = protocol
53
+ @method_name = method_name
54
+ @method_params = method_params
55
+ @service_name = service_name
56
+ @api = api
57
+ @api_method = api_method
58
+ @protocol_options = protocol_options || {}
59
+ end
60
+ end
61
+
62
+ class Response # :nodoc:
63
+ attr :body
64
+ attr :content_type
65
+ attr :return_value
66
+
67
+ def initialize(body, content_type, return_value)
68
+ @body = body
69
+ @content_type = content_type
70
+ @return_value = return_value
71
+ end
72
+ end
73
+
74
+ class SimpleActionPackRequest < ActionController::Request # :nodoc:
75
+ def initialize(env = {})
76
+ @env = env
77
+ @qparams = {}
78
+ @rparams = {}
79
+ @cookies = {}
80
+ reset_session
81
+ end
82
+
83
+ def query_parameters
84
+ @qparams
85
+ end
86
+
87
+ def request_parameters
88
+ @rparams
89
+ end
90
+
91
+ def env
92
+ @env
93
+ end
94
+
95
+ def host
96
+ ''
97
+ end
98
+
99
+ def cookies
100
+ @cookies
101
+ end
102
+
103
+ def session
104
+ @session
105
+ end
106
+
107
+ def reset_session
108
+ @session = {}
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,37 @@
1
+ module ActionWebService # :nodoc:
2
+ module Protocol # :nodoc:
3
+ module Discovery # :nodoc:
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ base.send(:include, ActionWebService::Protocol::Discovery::InstanceMethods)
7
+ end
8
+
9
+ module ClassMethods # :nodoc:
10
+ def register_protocol(klass)
11
+ write_inheritable_array("web_service_protocols", [klass])
12
+ end
13
+ end
14
+
15
+ module InstanceMethods # :nodoc:
16
+ private
17
+ def discover_web_service_request(action_pack_request)
18
+ (self.class.read_inheritable_attribute("web_service_protocols") || []).each do |protocol|
19
+ protocol = protocol.create(self)
20
+ request = protocol.decode_action_pack_request(action_pack_request)
21
+ return request unless request.nil?
22
+ end
23
+ nil
24
+ end
25
+
26
+ def create_web_service_client(api, protocol_name, endpoint_uri, options)
27
+ (self.class.read_inheritable_attribute("web_service_protocols") || []).each do |protocol|
28
+ protocol = protocol.create(self)
29
+ client = protocol.protocol_client(api, protocol_name, endpoint_uri, options)
30
+ return client unless client.nil?
31
+ end
32
+ nil
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,242 @@
1
+ require 'soap/mapping'
2
+
3
+ # hack to improve the .Net interoperability
4
+ class SOAP::Mapping::Object
5
+ def each_pair
6
+ self.__xmlele.each { |n, v| yield n.name, v.to_s }
7
+ end
8
+ end
9
+
10
+ module ActionWebService
11
+ module Protocol
12
+ module Soap
13
+ # Workaround for SOAP4R return values changing
14
+ class Registry < SOAP::Mapping::Registry
15
+ if SOAP::Version >= "1.5.4"
16
+ def find_mapped_soap_class(obj_class)
17
+ return @map.instance_eval { @obj2soap[obj_class][0] }
18
+ end
19
+
20
+ def find_mapped_obj_class(soap_class)
21
+ return @map.instance_eval { @soap2obj[soap_class][0] }
22
+ end
23
+ end
24
+ end
25
+
26
+ class SoapMarshaler
27
+ attr :namespace
28
+ attr :registry
29
+
30
+ def initialize(namespace=nil)
31
+ @namespace = namespace || 'urn:ActionWebService'
32
+ @registry = Registry.new
33
+ @type2binding = {}
34
+ register_static_factories
35
+ end
36
+
37
+ def soap_to_ruby(obj)
38
+ SOAP::Mapping.soap2obj(obj, @registry)
39
+ end
40
+
41
+ def ruby_to_soap(obj)
42
+ soap = SOAP::Mapping.obj2soap(obj, @registry)
43
+ soap.elename = XSD::QName.new if SOAP::Version >= "1.5.5" && soap.elename == XSD::QName::EMPTY
44
+ soap
45
+ end
46
+
47
+ def register_type(type)
48
+ return @type2binding[type] if @type2binding.has_key?(type)
49
+
50
+ if type.array?
51
+ array_mapping = @registry.find_mapped_soap_class(Array)
52
+ qname = XSD::QName.new(@namespace, soap_type_name(type.element_type.type_class.name) + 'Array')
53
+ element_type_binding = register_type(type.element_type)
54
+ @type2binding[type] = SoapBinding.new(self, qname, type, array_mapping, element_type_binding)
55
+ elsif (mapping = @registry.find_mapped_soap_class(type.type_class) rescue nil)
56
+ qname = mapping[2] ? mapping[2][:type] : nil
57
+ qname ||= soap_base_type_name(mapping[0])
58
+ @type2binding[type] = SoapBinding.new(self, qname, type, mapping)
59
+ else
60
+ qname = XSD::QName.new(@namespace, soap_type_name(type.type_class.name))
61
+ @registry.add(type.type_class,
62
+ SOAP::SOAPStruct,
63
+ typed_struct_factory(type.type_class),
64
+ { :type => qname })
65
+ mapping = @registry.find_mapped_soap_class(type.type_class)
66
+ @type2binding[type] = SoapBinding.new(self, qname, type, mapping)
67
+ end
68
+
69
+ if type.structured?
70
+ type.each_member do |m_name, m_type|
71
+ register_type(m_type)
72
+ end
73
+ end
74
+
75
+ @type2binding[type]
76
+ end
77
+ alias :lookup_type :register_type
78
+
79
+ def annotate_arrays(binding, value)
80
+ if value.nil?
81
+ return
82
+ elsif binding.type.array?
83
+ mark_typed_array(value, binding.element_binding.qname)
84
+ if binding.element_binding.type.custom?
85
+ value.each do |element|
86
+ annotate_arrays(binding.element_binding, element)
87
+ end
88
+ end
89
+ elsif binding.type.structured?
90
+ binding.type.each_member do |name, type|
91
+ member_binding = register_type(type)
92
+ member_value = value.respond_to?('[]') ? value[name] : value.send(name)
93
+ annotate_arrays(member_binding, member_value) if type.custom?
94
+ end
95
+ end
96
+ end
97
+
98
+ private
99
+ def typed_struct_factory(type_class)
100
+ if Object.const_defined?('ActiveRecord')
101
+ if type_class.ancestors.include?(ActiveRecord::Base)
102
+ qname = XSD::QName.new(@namespace, soap_type_name(type_class.name))
103
+ type_class.instance_variable_set('@qname', qname)
104
+ return SoapActiveRecordStructFactory.new
105
+ end
106
+ end
107
+ SOAP::Mapping::Registry::TypedStructFactory
108
+ end
109
+
110
+ def mark_typed_array(array, qname)
111
+ (class << array; self; end).class_eval do
112
+ define_method(:arytype) do
113
+ qname
114
+ end
115
+ end
116
+ end
117
+
118
+ def soap_base_type_name(type)
119
+ xsd_type = type.ancestors.find{ |c| c.const_defined? 'Type' }
120
+ xsd_type ? xsd_type.const_get('Type') : XSD::XSDAnySimpleType::Type
121
+ end
122
+
123
+ def soap_type_name(type_name)
124
+ type_name.gsub(/::/, '..')
125
+ end
126
+
127
+ def register_static_factories
128
+ @registry.add(ActionWebService::Base64, SOAP::SOAPBase64, SoapBase64Factory.new, nil)
129
+ mapping = @registry.find_mapped_soap_class(ActionWebService::Base64)
130
+ @type2binding[ActionWebService::Base64] =
131
+ SoapBinding.new(self, SOAP::SOAPBase64::Type, ActionWebService::Base64, mapping)
132
+ @registry.add(Array, SOAP::SOAPArray, SoapTypedArrayFactory.new, nil)
133
+ @registry.add(::BigDecimal, SOAP::SOAPDouble, SOAP::Mapping::Registry::BasetypeFactory, {:derived_class => true})
134
+ end
135
+ end
136
+
137
+ class SoapBinding
138
+ attr :qname
139
+ attr :type
140
+ attr :mapping
141
+ attr :element_binding
142
+
143
+ def initialize(marshaler, qname, type, mapping, element_binding=nil)
144
+ @marshaler = marshaler
145
+ @qname = qname
146
+ @type = type
147
+ @mapping = mapping
148
+ @element_binding = element_binding
149
+ end
150
+
151
+ def type_name
152
+ @type.custom? ? @qname.name : nil
153
+ end
154
+
155
+ def qualified_type_name(ns=nil)
156
+ if @type.custom?
157
+ "#{ns ? ns : @qname.namespace}:#{@qname.name}"
158
+ else
159
+ ns = XSD::NS.new
160
+ ns.assign(XSD::Namespace, SOAP::XSDNamespaceTag)
161
+ ns.assign(SOAP::EncodingNamespace, "soapenc")
162
+ xsd_klass = mapping[0].ancestors.find{|c| c.const_defined?('Type')}
163
+ return ns.name(XSD::AnyTypeName) unless xsd_klass
164
+ ns.name(xsd_klass.const_get('Type'))
165
+ end
166
+ end
167
+
168
+ def eql?(other)
169
+ @qname == other.qname
170
+ end
171
+ alias :== :eql?
172
+
173
+ def hash
174
+ @qname.hash
175
+ end
176
+ end
177
+
178
+ class SoapActiveRecordStructFactory < SOAP::Mapping::Factory
179
+ def obj2soap(soap_class, obj, info, map)
180
+ unless obj.is_a?(ActiveRecord::Base)
181
+ return nil
182
+ end
183
+ soap_obj = soap_class.new(obj.class.instance_variable_get('@qname'))
184
+ obj.class.columns.each do |column|
185
+ key = column.name.to_s
186
+ value = obj.send(key)
187
+ soap_obj[key] = SOAP::Mapping._obj2soap(value, map)
188
+ end
189
+ soap_obj
190
+ end
191
+
192
+ def soap2obj(obj_class, node, info, map)
193
+ unless node.type == obj_class.instance_variable_get('@qname')
194
+ return false
195
+ end
196
+ obj = obj_class.new
197
+ node.each do |key, value|
198
+ obj[key] = value.data
199
+ end
200
+ obj.instance_variable_set('@new_record', false)
201
+ return true, obj
202
+ end
203
+ end
204
+
205
+ class SoapTypedArrayFactory < SOAP::Mapping::Factory
206
+ def obj2soap(soap_class, obj, info, map)
207
+ unless obj.respond_to?(:arytype)
208
+ return nil
209
+ end
210
+ soap_obj = soap_class.new(SOAP::ValueArrayName, 1, obj.arytype)
211
+ mark_marshalled_obj(obj, soap_obj)
212
+ obj.each do |item|
213
+ child = SOAP::Mapping._obj2soap(item, map)
214
+ soap_obj.add(child)
215
+ end
216
+ soap_obj
217
+ end
218
+
219
+ def soap2obj(obj_class, node, info, map)
220
+ return false
221
+ end
222
+ end
223
+
224
+ class SoapBase64Factory < SOAP::Mapping::Factory
225
+ def obj2soap(soap_class, obj, info, map)
226
+ unless obj.is_a?(ActionWebService::Base64)
227
+ return nil
228
+ end
229
+ return soap_class.new(obj)
230
+ end
231
+
232
+ def soap2obj(obj_class, node, info, map)
233
+ unless node.type == SOAP::SOAPBase64::Type
234
+ return false
235
+ end
236
+ return true, obj_class.new(node.string)
237
+ end
238
+ end
239
+
240
+ end
241
+ end
242
+ end
@@ -0,0 +1,176 @@
1
+ require 'action_web_service/protocol/soap_protocol/marshaler'
2
+ require 'soap/streamHandler'
3
+ require 'action_web_service/client/soap_client'
4
+
5
+ module ActionWebService # :nodoc:
6
+ module API # :nodoc:
7
+ class Base # :nodoc:
8
+ def self.soap_client(endpoint_uri, options={})
9
+ ActionWebService::Client::Soap.new self, endpoint_uri, options
10
+ end
11
+ end
12
+ end
13
+
14
+ module Protocol # :nodoc:
15
+ module Soap # :nodoc:
16
+ def self.included(base)
17
+ base.register_protocol(SoapProtocol)
18
+ base.class_inheritable_option(:wsdl_service_name)
19
+ base.class_inheritable_option(:wsdl_namespace)
20
+ end
21
+
22
+ class SoapProtocol < AbstractProtocol # :nodoc:
23
+ AWSEncoding = 'UTF-8'
24
+ XSDEncoding = 'UTF8'
25
+
26
+ attr :marshaler
27
+
28
+ def initialize(namespace=nil)
29
+ namespace ||= 'urn:ActionWebService'
30
+ @marshaler = SoapMarshaler.new namespace
31
+ end
32
+
33
+ def self.create(controller)
34
+ SoapProtocol.new(controller.wsdl_namespace)
35
+ end
36
+
37
+ def decode_action_pack_request(action_pack_request)
38
+ return nil unless soap_action = has_valid_soap_action?(action_pack_request)
39
+ service_name = action_pack_request.parameters['action']
40
+ input_encoding = parse_charset(action_pack_request.env['HTTP_CONTENT_TYPE'])
41
+ protocol_options = {
42
+ :soap_action => soap_action,
43
+ :charset => input_encoding
44
+ }
45
+ decode_request(action_pack_request.raw_post, service_name, protocol_options)
46
+ end
47
+
48
+ def encode_action_pack_request(service_name, public_method_name, raw_body, options={})
49
+ request = super
50
+ request.env['HTTP_SOAPACTION'] = '/soap/%s/%s' % [service_name, public_method_name]
51
+ request
52
+ end
53
+
54
+ def decode_request(raw_request, service_name, protocol_options={})
55
+ envelope = SOAP::Processor.unmarshal(raw_request, :charset => protocol_options[:charset])
56
+ unless envelope
57
+ raise ProtocolError, "Failed to parse SOAP request message"
58
+ end
59
+ request = envelope.body.request
60
+ method_name = request.elename.name
61
+ params = request.collect{ |k, v| marshaler.soap_to_ruby(request[k]) }
62
+ Request.new(self, method_name, params, service_name, nil, nil, protocol_options)
63
+ end
64
+
65
+ def encode_request(method_name, params, param_types)
66
+ param_types.each{ |type| marshaler.register_type(type) } if param_types
67
+ qname = XSD::QName.new(marshaler.namespace, method_name)
68
+ param_def = []
69
+ if param_types
70
+ params = param_types.zip(params).map do |type, param|
71
+ param_def << ['in', type.name, marshaler.lookup_type(type).mapping]
72
+ [type.name, marshaler.ruby_to_soap(param)]
73
+ end
74
+ else
75
+ params = []
76
+ end
77
+ request = SOAP::RPC::SOAPMethodRequest.new(qname, param_def)
78
+ request.set_param(params)
79
+ envelope = create_soap_envelope(request)
80
+ SOAP::Processor.marshal(envelope)
81
+ end
82
+
83
+ def decode_response(raw_response)
84
+ envelope = SOAP::Processor.unmarshal(raw_response)
85
+ unless envelope
86
+ raise ProtocolError, "Failed to parse SOAP request message"
87
+ end
88
+ method_name = envelope.body.request.elename.name
89
+ return_value = envelope.body.response
90
+ return_value = marshaler.soap_to_ruby(return_value) unless return_value.nil?
91
+ [method_name, return_value]
92
+ end
93
+
94
+ def encode_response(method_name, return_value, return_type, protocol_options={})
95
+ if return_type
96
+ return_binding = marshaler.register_type(return_type)
97
+ marshaler.annotate_arrays(return_binding, return_value)
98
+ end
99
+ qname = XSD::QName.new(marshaler.namespace, method_name)
100
+ if return_value.nil?
101
+ response = SOAP::RPC::SOAPMethodResponse.new(qname, nil)
102
+ else
103
+ if return_value.is_a?(Exception)
104
+ detail = SOAP::Mapping::SOAPException.new(return_value)
105
+ response = SOAP::SOAPFault.new(
106
+ SOAP::SOAPQName.new('%s:%s' % [SOAP::SOAPNamespaceTag, 'Server']),
107
+ SOAP::SOAPString.new(return_value.to_s),
108
+ SOAP::SOAPString.new(self.class.name),
109
+ marshaler.ruby_to_soap(detail))
110
+ else
111
+ if return_type
112
+ param_def = [['retval', 'return', marshaler.lookup_type(return_type).mapping]]
113
+ response = SOAP::RPC::SOAPMethodResponse.new(qname, param_def)
114
+ response.retval = marshaler.ruby_to_soap(return_value)
115
+ else
116
+ response = SOAP::RPC::SOAPMethodResponse.new(qname, nil)
117
+ end
118
+ end
119
+ end
120
+ envelope = create_soap_envelope(response)
121
+
122
+ # FIXME: This is not thread-safe, but StringFactory_ in SOAP4R only
123
+ # reads target encoding from the XSD::Charset.encoding variable.
124
+ # This is required to ensure $KCODE strings are converted
125
+ # correctly to UTF-8 for any values of $KCODE.
126
+ previous_encoding = XSD::Charset.encoding
127
+ XSD::Charset.encoding = XSDEncoding
128
+ response_body = SOAP::Processor.marshal(envelope, :charset => AWSEncoding)
129
+ XSD::Charset.encoding = previous_encoding
130
+
131
+ Response.new(response_body, "text/xml; charset=#{AWSEncoding}", return_value)
132
+ end
133
+
134
+ def protocol_client(api, protocol_name, endpoint_uri, options={})
135
+ return nil unless protocol_name == :soap
136
+ ActionWebService::Client::Soap.new(api, endpoint_uri, options)
137
+ end
138
+
139
+ def register_api(api)
140
+ api.api_methods.each do |name, method|
141
+ method.expects.each{ |type| marshaler.register_type(type) } if method.expects
142
+ method.returns.each{ |type| marshaler.register_type(type) } if method.returns
143
+ end
144
+ end
145
+
146
+ private
147
+ def has_valid_soap_action?(request)
148
+ return nil unless request.method == :post
149
+ soap_action = request.env['HTTP_SOAPACTION']
150
+ return nil unless soap_action
151
+ soap_action = soap_action.dup
152
+ soap_action.gsub!(/^"/, '')
153
+ soap_action.gsub!(/"$/, '')
154
+ soap_action.strip!
155
+ return nil if soap_action.empty?
156
+ soap_action
157
+ end
158
+
159
+ def create_soap_envelope(body)
160
+ header = SOAP::SOAPHeader.new
161
+ body = SOAP::SOAPBody.new(body)
162
+ SOAP::SOAPEnvelope.new(header, body)
163
+ end
164
+
165
+ def parse_charset(content_type)
166
+ return AWSEncoding if content_type.nil?
167
+ if /^text\/xml(?:\s*;\s*charset=([^"]+|"[^"]+"))$/i =~ content_type
168
+ $1
169
+ else
170
+ AWSEncoding
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,123 @@
1
+ require 'xmlrpc/marshal'
2
+ require 'action_web_service/client/xmlrpc_client'
3
+
4
+ module XMLRPC # :nodoc:
5
+ class FaultException # :nodoc:
6
+ alias :message :faultString
7
+ end
8
+
9
+ class Create
10
+ def wrong_type(value)
11
+ if BigDecimal === value
12
+ [true, value.to_f]
13
+ else
14
+ false
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ module ActionWebService # :nodoc:
21
+ module API # :nodoc:
22
+ class Base # :nodoc:
23
+ def self.xmlrpc_client(endpoint_uri, options={})
24
+ ActionWebService::Client::XmlRpc.new self, endpoint_uri, options
25
+ end
26
+ end
27
+ end
28
+
29
+ module Protocol # :nodoc:
30
+ module XmlRpc # :nodoc:
31
+ def self.included(base)
32
+ base.register_protocol(XmlRpcProtocol)
33
+ end
34
+
35
+ class XmlRpcProtocol < AbstractProtocol # :nodoc:
36
+ def self.create(controller)
37
+ XmlRpcProtocol.new
38
+ end
39
+
40
+ def decode_action_pack_request(action_pack_request)
41
+ service_name = action_pack_request.parameters['action']
42
+ decode_request(action_pack_request.raw_post, service_name)
43
+ end
44
+
45
+ def decode_request(raw_request, service_name)
46
+ method_name, params = XMLRPC::Marshal.load_call(raw_request)
47
+ Request.new(self, method_name, params, service_name)
48
+ rescue
49
+ return nil
50
+ end
51
+
52
+ def encode_request(method_name, params, param_types)
53
+ if param_types
54
+ params = params.dup
55
+ param_types.each_with_index{ |type, i| params[i] = value_to_xmlrpc_wire_format(params[i], type) }
56
+ end
57
+ XMLRPC::Marshal.dump_call(method_name, *params)
58
+ end
59
+
60
+ def decode_response(raw_response)
61
+ [nil, XMLRPC::Marshal.load_response(raw_response)]
62
+ end
63
+
64
+ def encode_response(method_name, return_value, return_type, protocol_options={})
65
+ if return_value && return_type
66
+ return_value = value_to_xmlrpc_wire_format(return_value, return_type)
67
+ end
68
+ return_value = false if return_value.nil?
69
+ raw_response = XMLRPC::Marshal.dump_response(return_value)
70
+ Response.new(raw_response, 'text/xml', return_value)
71
+ end
72
+
73
+ def encode_multicall_response(responses, protocol_options={})
74
+ result = responses.map do |return_value, return_type|
75
+ if return_value && return_type
76
+ return_value = value_to_xmlrpc_wire_format(return_value, return_type)
77
+ return_value = [return_value] unless return_value.nil?
78
+ end
79
+ return_value = false if return_value.nil?
80
+ return_value
81
+ end
82
+ raw_response = XMLRPC::Marshal.dump_response(result)
83
+ Response.new(raw_response, 'text/xml', result)
84
+ end
85
+
86
+ def protocol_client(api, protocol_name, endpoint_uri, options={})
87
+ return nil unless protocol_name == :xmlrpc
88
+ ActionWebService::Client::XmlRpc.new(api, endpoint_uri, options)
89
+ end
90
+
91
+ def value_to_xmlrpc_wire_format(value, value_type)
92
+ if value_type.array?
93
+ value.map{ |val| value_to_xmlrpc_wire_format(val, value_type.element_type) }
94
+ else
95
+ if value.is_a?(ActionWebService::Struct)
96
+ struct = {}
97
+ value.class.members.each do |name, type_options|
98
+ type, options = type_options
99
+ member_value = value[name]
100
+ next if member_value.nil?
101
+ struct[name.to_s] = value_to_xmlrpc_wire_format(member_value, type)
102
+ end
103
+ struct
104
+ elsif value.is_a?(ActiveRecord::Base)
105
+ struct = {}
106
+ value.attributes.each do |key, member_value|
107
+ next if member_value.nil?
108
+ struct[key.to_s] = member_value
109
+ end
110
+ struct
111
+ elsif value.is_a?(ActionWebService::Base64)
112
+ XMLRPC::Base64.new(value)
113
+ elsif value.is_a?(Exception) && !value.is_a?(XMLRPC::FaultException)
114
+ XMLRPC::FaultException.new(2, value.message)
115
+ else
116
+ value
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,4 @@
1
+ require 'action_web_service/protocol/abstract'
2
+ require 'action_web_service/protocol/discovery'
3
+ require 'action_web_service/protocol/soap_protocol'
4
+ require 'action_web_service/protocol/xmlrpc_protocol'