axtro-actionwebservice 2.3.5.1.20101118142125

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 +184 -0
  5. data/TODO +32 -0
  6. data/examples/googlesearch/README +143 -0
  7. data/examples/googlesearch/autoloading/google_search_api.rb +51 -0
  8. data/examples/googlesearch/autoloading/google_search_controller.rb +58 -0
  9. data/examples/googlesearch/delegated/google_search_service.rb +109 -0
  10. data/examples/googlesearch/delegated/search_controller.rb +8 -0
  11. data/examples/googlesearch/direct/google_search_api.rb +51 -0
  12. data/examples/googlesearch/direct/search_controller.rb +59 -0
  13. data/examples/metaWeblog/README +17 -0
  14. data/examples/metaWeblog/apis/blogger_api.rb +61 -0
  15. data/examples/metaWeblog/apis/blogger_service.rb +35 -0
  16. data/examples/metaWeblog/apis/meta_weblog_api.rb +68 -0
  17. data/examples/metaWeblog/apis/meta_weblog_service.rb +49 -0
  18. data/examples/metaWeblog/controllers/xmlrpc_controller.rb +17 -0
  19. data/generators/web_service/USAGE +28 -0
  20. data/generators/web_service/templates/api_definition.rb +6 -0
  21. data/generators/web_service/templates/controller.rb +9 -0
  22. data/generators/web_service/templates/functional_test.rb +20 -0
  23. data/generators/web_service/web_service_generator.rb +30 -0
  24. data/lib/action_web_service.rb +61 -0
  25. data/lib/action_web_service/acts_as_web_service.rb +26 -0
  26. data/lib/action_web_service/api.rb +298 -0
  27. data/lib/action_web_service/base.rb +39 -0
  28. data/lib/action_web_service/casting.rb +160 -0
  29. data/lib/action_web_service/client.rb +4 -0
  30. data/lib/action_web_service/client/base.rb +29 -0
  31. data/lib/action_web_service/client/soap_client.rb +114 -0
  32. data/lib/action_web_service/client/xmlrpc_client.rb +59 -0
  33. data/lib/action_web_service/container.rb +4 -0
  34. data/lib/action_web_service/container/action_controller_container.rb +94 -0
  35. data/lib/action_web_service/container/delegated_container.rb +87 -0
  36. data/lib/action_web_service/container/direct_container.rb +70 -0
  37. data/lib/action_web_service/dispatcher.rb +3 -0
  38. data/lib/action_web_service/dispatcher/abstract.rb +209 -0
  39. data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +397 -0
  40. data/lib/action_web_service/invocation.rb +203 -0
  41. data/lib/action_web_service/protocol.rb +5 -0
  42. data/lib/action_web_service/protocol/abstract.rb +113 -0
  43. data/lib/action_web_service/protocol/discovery.rb +38 -0
  44. data/lib/action_web_service/protocol/soap_protocol.rb +177 -0
  45. data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +243 -0
  46. data/lib/action_web_service/protocol/soap_protocol/marshaler.rb~ +243 -0
  47. data/lib/action_web_service/protocol/xmlrpc_protocol.rb +124 -0
  48. data/lib/action_web_service/scaffolding.rb +282 -0
  49. data/lib/action_web_service/simple.rb +54 -0
  50. data/lib/action_web_service/string_to_datetime_for_soap.rb +17 -0
  51. data/lib/action_web_service/struct.rb +69 -0
  52. data/lib/action_web_service/support/class_inheritable_options.rb +27 -0
  53. data/lib/action_web_service/support/signature_types.rb +262 -0
  54. data/lib/action_web_service/templates/scaffolds/layout.html.erb +65 -0
  55. data/lib/action_web_service/templates/scaffolds/methods.html.erb +6 -0
  56. data/lib/action_web_service/templates/scaffolds/parameters.html.erb +29 -0
  57. data/lib/action_web_service/templates/scaffolds/result.html.erb +30 -0
  58. data/lib/action_web_service/test_invoke.rb +111 -0
  59. data/lib/action_web_service/version.rb +11 -0
  60. data/lib/action_web_service/version.rb~ +10 -0
  61. data/lib/actionwebservice.rb +2 -0
  62. data/setup.rb +1380 -0
  63. data/test/abstract_client.rb +185 -0
  64. data/test/abstract_dispatcher.rb +550 -0
  65. data/test/abstract_unit.rb +44 -0
  66. data/test/api_test.rb +103 -0
  67. data/test/apis/auto_load_api.rb +4 -0
  68. data/test/apis/broken_auto_load_api.rb +3 -0
  69. data/test/base_test.rb +43 -0
  70. data/test/casting_test.rb +96 -0
  71. data/test/client_soap_test.rb +157 -0
  72. data/test/client_xmlrpc_test.rb +155 -0
  73. data/test/container_test.rb +76 -0
  74. data/test/dispatcher_action_controller_soap_test.rb +147 -0
  75. data/test/dispatcher_action_controller_xmlrpc_test.rb +60 -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 +187 -0
  81. data/test/run +6 -0
  82. data/test/scaffolded_controller_test.rb +148 -0
  83. data/test/struct_test.rb +85 -0
  84. data/test/test_invoke_test.rb +114 -0
  85. metadata +167 -0
@@ -0,0 +1,243 @@
1
+ # encoding: UTF-8
2
+ require 'soap/mapping'
3
+
4
+ # hack to improve the .Net interoperability
5
+ class SOAP::Mapping::Object
6
+ def each_pair
7
+ self.__xmlele.each { |n, v| yield n.name, v }
8
+ end
9
+ end
10
+
11
+ module ActionWebService
12
+ module Protocol
13
+ module Soap
14
+ # Workaround for SOAP4R return values changing
15
+ class Registry < SOAP::Mapping::Registry
16
+ if SOAP::Version >= "1.5.4"
17
+ def find_mapped_soap_class(obj_class)
18
+ return @map.instance_eval { @obj2soap[obj_class][0] }
19
+ end
20
+
21
+ def find_mapped_obj_class(soap_class)
22
+ return @map.instance_eval { @soap2obj[soap_class][0] }
23
+ end
24
+ end
25
+ end
26
+
27
+ class SoapMarshaler
28
+ attr :namespace
29
+ attr :registry
30
+
31
+ def initialize(namespace=nil)
32
+ @namespace = namespace || 'urn:ActionWebService'
33
+ @registry = Registry.new
34
+ @type2binding = {}
35
+ register_static_factories
36
+ end
37
+
38
+ def soap_to_ruby(obj)
39
+ SOAP::Mapping.soap2obj(obj, @registry)
40
+ end
41
+
42
+ def ruby_to_soap(obj)
43
+ soap = SOAP::Mapping.obj2soap(obj, @registry)
44
+ soap.elename = XSD::QName.new if SOAP::Version >= "1.5.5" && soap.elename == XSD::QName::EMPTY
45
+ soap
46
+ end
47
+
48
+ def register_type(type)
49
+ return @type2binding[type] if @type2binding.has_key?(type)
50
+
51
+ if type.array?
52
+ array_mapping = @registry.find_mapped_soap_class(Array)
53
+ qname = XSD::QName.new(@namespace, soap_type_name(type.element_type.type_class.name) + 'Array')
54
+ element_type_binding = register_type(type.element_type)
55
+ @type2binding[type] = SoapBinding.new(self, qname, type, array_mapping, element_type_binding)
56
+ elsif (mapping = @registry.find_mapped_soap_class(type.type_class) rescue nil)
57
+ qname = mapping[2] ? mapping[2][:type] : nil
58
+ qname ||= soap_base_type_name(mapping[0])
59
+ @type2binding[type] = SoapBinding.new(self, qname, type, mapping)
60
+ else
61
+ qname = XSD::QName.new(@namespace, soap_type_name(type.type_class.name))
62
+ @registry.add(type.type_class,
63
+ SOAP::SOAPStruct,
64
+ typed_struct_factory(type.type_class),
65
+ { :type => qname })
66
+ mapping = @registry.find_mapped_soap_class(type.type_class)
67
+ @type2binding[type] = SoapBinding.new(self, qname, type, mapping)
68
+ end
69
+
70
+ if type.structured?
71
+ type.each_member do |m_name, m_type|
72
+ register_type(m_type)
73
+ end
74
+ end
75
+
76
+ @type2binding[type]
77
+ end
78
+ alias :lookup_type :register_type
79
+
80
+ def annotate_arrays(binding, value)
81
+ if value.nil?
82
+ return
83
+ elsif binding.type.array?
84
+ mark_typed_array(value, binding.element_binding.qname)
85
+ if binding.element_binding.type.custom?
86
+ value.each do |element|
87
+ annotate_arrays(binding.element_binding, element)
88
+ end
89
+ end
90
+ elsif binding.type.structured?
91
+ binding.type.each_member do |name, type|
92
+ member_binding = register_type(type)
93
+ member_value = value.respond_to?('[]') ? value[name] : value.send(name)
94
+ annotate_arrays(member_binding, member_value) if type.custom?
95
+ end
96
+ end
97
+ end
98
+
99
+ private
100
+ def typed_struct_factory(type_class)
101
+ if Object.const_defined?('ActiveRecord')
102
+ if type_class.ancestors.include?(ActiveRecord::Base)
103
+ qname = XSD::QName.new(@namespace, soap_type_name(type_class.name))
104
+ type_class.instance_variable_set('@qname', qname)
105
+ return SoapActiveRecordStructFactory.new
106
+ end
107
+ end
108
+ SOAP::Mapping::Registry::TypedStructFactory
109
+ end
110
+
111
+ def mark_typed_array(array, qname)
112
+ (class << array; self; end).class_eval do
113
+ define_method(:arytype) do
114
+ qname
115
+ end
116
+ end
117
+ end
118
+
119
+ def soap_base_type_name(type)
120
+ xsd_type = type.ancestors.find{ |c| c.const_defined? 'Type' }
121
+ xsd_type ? xsd_type.const_get('Type') : XSD::XSDAnySimpleType::Type
122
+ end
123
+
124
+ def soap_type_name(type_name)
125
+ type_name.gsub(/::/, '..')
126
+ end
127
+
128
+ def register_static_factories
129
+ @registry.add(ActionWebService::Base64, SOAP::SOAPBase64, SoapBase64Factory.new, nil)
130
+ mapping = @registry.find_mapped_soap_class(ActionWebService::Base64)
131
+ @type2binding[ActionWebService::Base64] =
132
+ SoapBinding.new(self, SOAP::SOAPBase64::Type, ActionWebService::Base64, mapping)
133
+ @registry.add(Array, SOAP::SOAPArray, SoapTypedArrayFactory.new, nil)
134
+ @registry.add(::BigDecimal, SOAP::SOAPDouble, SOAP::Mapping::Registry::BasetypeFactory, {:derived_class => true})
135
+ end
136
+ end
137
+
138
+ class SoapBinding
139
+ attr :qname
140
+ attr :type
141
+ attr :mapping
142
+ attr :element_binding
143
+
144
+ def initialize(marshaler, qname, type, mapping, element_binding=nil)
145
+ @marshaler = marshaler
146
+ @qname = qname
147
+ @type = type
148
+ @mapping = mapping
149
+ @element_binding = element_binding
150
+ end
151
+
152
+ def type_name
153
+ @type.custom? ? @qname.name : nil
154
+ end
155
+
156
+ def qualified_type_name(ns=nil)
157
+ if @type.custom?
158
+ "#{ns ? ns : @qname.namespace}:#{@qname.name}"
159
+ else
160
+ ns = XSD::NS.new
161
+ ns.assign(XSD::Namespace, SOAP::XSDNamespaceTag)
162
+ ns.assign(SOAP::EncodingNamespace, "soapenc")
163
+ xsd_klass = mapping[0].ancestors.find{|c| c.const_defined?('Type')}
164
+ return ns.name(XSD::AnyTypeName) unless xsd_klass
165
+ ns.name(xsd_klass.const_get('Type'))
166
+ end
167
+ end
168
+
169
+ def eql?(other)
170
+ @qname == other.qname
171
+ end
172
+ alias :== :eql?
173
+
174
+ def hash
175
+ @qname.hash
176
+ end
177
+ end
178
+
179
+ class SoapActiveRecordStructFactory < SOAP::Mapping::Factory
180
+ def obj2soap(soap_class, obj, info, map)
181
+ unless obj.is_a?(ActiveRecord::Base)
182
+ return nil
183
+ end
184
+ soap_obj = soap_class.new(obj.class.instance_variable_get('@qname'))
185
+ obj.class.columns.each do |column|
186
+ key = column.name.to_s
187
+ value = obj.send(key)
188
+ soap_obj[key] = SOAP::Mapping._obj2soap(value, map)
189
+ end
190
+ soap_obj
191
+ end
192
+
193
+ def soap2obj(obj_class, node, info, map)
194
+ unless node.type == obj_class.instance_variable_get('@qname')
195
+ return false
196
+ end
197
+ obj = obj_class.new
198
+ node.each do |key, value|
199
+ obj[key] = value.data
200
+ end
201
+ obj.instance_variable_set('@new_record', false)
202
+ return true, obj
203
+ end
204
+ end
205
+
206
+ class SoapTypedArrayFactory < SOAP::Mapping::Factory
207
+ def obj2soap(soap_class, obj, info, map)
208
+ unless obj.respond_to?(:arytype)
209
+ return nil
210
+ end
211
+ soap_obj = soap_class.new(SOAP::ValueArrayName, 1, obj.arytype)
212
+ mark_marshalled_obj(obj, soap_obj)
213
+ obj.each do |item|
214
+ child = SOAP::Mapping._obj2soap(item, map)
215
+ soap_obj.add(child)
216
+ end
217
+ soap_obj
218
+ end
219
+
220
+ def soap2obj(obj_class, node, info, map)
221
+ return false
222
+ end
223
+ end
224
+
225
+ class SoapBase64Factory < SOAP::Mapping::Factory
226
+ def obj2soap(soap_class, obj, info, map)
227
+ unless obj.is_a?(ActionWebService::Base64)
228
+ return nil
229
+ end
230
+ return soap_class.new(obj)
231
+ end
232
+
233
+ def soap2obj(obj_class, node, info, map)
234
+ unless node.type == SOAP::SOAPBase64::Type
235
+ return false
236
+ end
237
+ return true, obj_class.new(node.string)
238
+ end
239
+ end
240
+
241
+ end
242
+ end
243
+ end
@@ -0,0 +1,243 @@
1
+ # encoding: UTF-8
2
+ require 'soap/mapping'
3
+
4
+ # hack to improve the .Net interoperability
5
+ class SOAP::Mapping::Object
6
+ def each_pair
7
+ self.__xmlele.each { |n, v| yield n.name, v }
8
+ end
9
+ end
10
+
11
+ module ActionWebService
12
+ module Protocol
13
+ module Soap
14
+ # Workaround for SOAP4R return values changing
15
+ class Registry < SOAP::Mapping::Registry
16
+ if SOAP::Version >= "1.5.4"
17
+ def find_mapped_soap_class(obj_class)
18
+ return @map.instance_eval { @obj2soap[obj_class][0] }
19
+ end
20
+
21
+ def find_mapped_obj_class(soap_class)
22
+ return @map.instance_eval { @soap2obj[soap_class][0] }
23
+ end
24
+ end
25
+ end
26
+
27
+ class SoapMarshaler
28
+ attr :namespace
29
+ attr :registry
30
+
31
+ def initialize(namespace=nil)
32
+ @namespace = namespace || 'urn:ActionWebService'
33
+ @registry = Registry.new
34
+ @type2binding = {}
35
+ register_static_factories
36
+ end
37
+
38
+ def soap_to_ruby(obj)
39
+ SOAP::Mapping.soap2obj(obj, @registry)
40
+ end
41
+
42
+ def ruby_to_soap(obj)
43
+ soap = SOAP::Mapping.obj2soap(obj, @registry)
44
+ soap.elename = XSD::QName.new if SOAP::Version >= "1.5.5" && soap.elename == XSD::QName::EMPTY
45
+ soap
46
+ end
47
+
48
+ def register_type(type)
49
+ return @type2binding[type] if @type2binding.has_key?(type)
50
+
51
+ if type.array?
52
+ array_mapping = @registry.find_mapped_soap_class(Array)
53
+ qname = XSD::QName.new(@namespace, soap_type_name(type.element_type.type_class.name) + 'Array')
54
+ element_type_binding = register_type(type.element_type)
55
+ @type2binding[type] = SoapBinding.new(self, qname, type, array_mapping, element_type_binding)
56
+ elsif (mapping = @registry.find_mapped_soap_class(type.type_class) rescue nil)
57
+ qname = mapping[2] ? mapping[2][:type] : nil
58
+ qname ||= soap_base_type_name(mapping[0])
59
+ @type2binding[type] = SoapBinding.new(self, qname, type, mapping)
60
+ else
61
+ qname = XSD::QName.new(@namespace, soap_type_name(type.type_class.name))
62
+ @registry.add(type.type_class,
63
+ SOAP::SOAPStruct,
64
+ typed_struct_factory(type.type_class),
65
+ { :type => qname })
66
+ mapping = @registry.find_mapped_soap_class(type.type_class)
67
+ @type2binding[type] = SoapBinding.new(self, qname, type, mapping)
68
+ end
69
+
70
+ if type.structured?
71
+ type.each_member do |m_name, m_type|
72
+ register_type(m_type)
73
+ end
74
+ end
75
+
76
+ @type2binding[type]
77
+ end
78
+ alias :lookup_type :register_type
79
+
80
+ def annotate_arrays(binding, value)
81
+ if value.nil?
82
+ return
83
+ elsif binding.type.array?
84
+ mark_typed_array(value, binding.element_binding.qname)
85
+ if binding.element_binding.type.custom?
86
+ value.each do |element|
87
+ annotate_arrays(binding.element_binding, element)
88
+ end
89
+ end
90
+ elsif binding.type.structured?
91
+ binding.type.each_member do |name, type|
92
+ member_binding = register_type(type)
93
+ member_value = value.respond_to?('[]') ? value[name] : value.send(name)
94
+ annotate_arrays(member_binding, member_value) if type.custom?
95
+ end
96
+ end
97
+ end
98
+
99
+ private
100
+ def typed_struct_factory(type_class)
101
+ if Object.const_defined?('ActiveRecord')
102
+ if type_class.ancestors.include?(ActiveRecord::Base)
103
+ qname = XSD::QName.new(@namespace, soap_type_name(type_class.name))
104
+ type_class.instance_variable_set('@qname', qname)
105
+ return SoapActiveRecordStructFactory.new
106
+ end
107
+ end
108
+ SOAP::Mapping::Registry::TypedStructFactory
109
+ end
110
+
111
+ def mark_typed_array(array, qname)
112
+ (class << array; self; end).class_eval do
113
+ define_method(:arytype) do
114
+ qname
115
+ end
116
+ end
117
+ end
118
+
119
+ def soap_base_type_name(type)
120
+ xsd_type = type.ancestors.find{ |c| c.const_defined? 'Type' }
121
+ xsd_type ? xsd_type.const_get('Type') : XSD::XSDAnySimpleType::Type
122
+ end
123
+
124
+ def soap_type_name(type_name)
125
+ type_name.gsub(/::/, '..')
126
+ end
127
+
128
+ def register_static_factories
129
+ @registry.add(ActionWebService::Base64, SOAP::SOAPBase64, SoapBase64Factory.new, nil)
130
+ mapping = @registry.find_mapped_soap_class(ActionWebService::Base64)
131
+ @type2binding[ActionWebService::Base64] =
132
+ SoapBinding.new(self, SOAP::SOAPBase64::Type, ActionWebService::Base64, mapping)
133
+ @registry.add(Array, SOAP::SOAPArray, SoapTypedArrayFactory.new, nil)
134
+ @registry.add(::BigDecimal, SOAP::SOAPDouble, SOAP::Mapping::Registry::BasetypeFactory, {:derived_class => true})
135
+ end
136
+ end
137
+
138
+ class SoapBinding
139
+ attr :qname
140
+ attr :type
141
+ attr :mapping
142
+ attr :element_binding
143
+
144
+ def initialize(marshaler, qname, type, mapping, element_binding=nil)
145
+ @marshaler = marshaler
146
+ @qname = qname
147
+ @type = type
148
+ @mapping = mapping
149
+ @element_binding = element_binding
150
+ end
151
+
152
+ def type_name
153
+ @type.custom? ? @qname.name : nil
154
+ end
155
+
156
+ def qualified_type_name(ns=nil)
157
+ if @type.custom?
158
+ "#{ns ? ns : @qname.namespace}:#{@qname.name}"
159
+ else
160
+ ns = XSD::NS.new
161
+ ns.assign(XSD::Namespace, SOAP::XSDNamespaceTag)
162
+ ns.assign(SOAP::EncodingNamespace, "soapenc")
163
+ xsd_klass = mapping[0].ancestors.find{|c| c.const_defined?('Type')}
164
+ return ns.name(XSD::AnyTypeName) unless xsd_klass
165
+ ns.name(xsd_klass.const_get('Type'))
166
+ end
167
+ end
168
+
169
+ def eql?(other)
170
+ @qname == other.qname
171
+ end
172
+ alias :== :eql?
173
+
174
+ def hash
175
+ @qname.hash
176
+ end
177
+ end
178
+
179
+ class SoapActiveRecordStructFactory < SOAP::Mapping::Factory
180
+ def obj2soap(soap_class, obj, info, map)
181
+ unless obj.is_a?(ActiveRecord::Base)
182
+ return nil
183
+ end
184
+ soap_obj = soap_class.new(obj.class.instance_variable_get('@qname'))
185
+ obj.class.columns.each do |column|
186
+ key = column.name.to_s
187
+ value = obj.send(key)
188
+ soap_obj[key] = SOAP::Mapping._obj2soap(value, map)
189
+ end
190
+ soap_obj
191
+ end
192
+
193
+ def soap2obj(obj_class, node, info, map)
194
+ unless node.type == obj_class.instance_variable_get('@qname')
195
+ return false
196
+ end
197
+ obj = obj_class.new
198
+ node.each do |key, value|
199
+ obj[key] = value.data
200
+ end
201
+ obj.instance_variable_set('@new_record', false)
202
+ return true, obj
203
+ end
204
+ end
205
+
206
+ class SoapTypedArrayFactory < SOAP::Mapping::Factory
207
+ def obj2soap(soap_class, obj, info, map)
208
+ unless obj.respond_to?(:arytype)
209
+ return nil
210
+ end
211
+ soap_obj = soap_class.new(SOAP::ValueArrayName, 1, obj.arytype)
212
+ mark_marshalled_obj(obj, soap_obj)
213
+ obj.each do |item|
214
+ child = SOAP::Mapping._obj2soap(item, map)
215
+ soap_obj.add(child)
216
+ end
217
+ soap_obj
218
+ end
219
+
220
+ def soap2obj(obj_class, node, info, map)
221
+ return false
222
+ end
223
+ end
224
+
225
+ class SoapBase64Factory < SOAP::Mapping::Factory
226
+ def obj2soap(soap_class, obj, info, map)
227
+ unless obj.is_a?(ActionWebService::Base64)
228
+ return nil
229
+ end
230
+ return soap_class.new(obj)
231
+ end
232
+
233
+ def soap2obj(obj_class, node, info, map)
234
+ unless node.type == SOAP::SOAPBase64::Type
235
+ return false
236
+ end
237
+ return true, obj_class.new(node.string)
238
+ end
239
+ end
240
+
241
+ end
242
+ end
243
+ end