reidiculous-actionwebservice-client 3.0.4

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 (179) hide show
  1. data/CHANGELOG +320 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +381 -0
  4. data/Rakefile +180 -0
  5. data/TODO +32 -0
  6. data/lib/action_web_service.rb +71 -0
  7. data/lib/action_web_service/api.rb +297 -0
  8. data/lib/action_web_service/base.rb +38 -0
  9. data/lib/action_web_service/casting.rb +149 -0
  10. data/lib/action_web_service/client.rb +3 -0
  11. data/lib/action_web_service/client/base.rb +28 -0
  12. data/lib/action_web_service/client/soap_client.rb +113 -0
  13. data/lib/action_web_service/client/xmlrpc_client.rb +58 -0
  14. data/lib/action_web_service/container.rb +3 -0
  15. data/lib/action_web_service/container/action_controller_container.rb +93 -0
  16. data/lib/action_web_service/container/delegated_container.rb +86 -0
  17. data/lib/action_web_service/container/direct_container.rb +69 -0
  18. data/lib/action_web_service/dispatcher.rb +2 -0
  19. data/lib/action_web_service/dispatcher/abstract.rb +207 -0
  20. data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +379 -0
  21. data/lib/action_web_service/invocation.rb +202 -0
  22. data/lib/action_web_service/protocol.rb +4 -0
  23. data/lib/action_web_service/protocol/abstract.rb +115 -0
  24. data/lib/action_web_service/protocol/discovery.rb +37 -0
  25. data/lib/action_web_service/protocol/soap_protocol.rb +176 -0
  26. data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +242 -0
  27. data/lib/action_web_service/protocol/xmlrpc_protocol.rb +122 -0
  28. data/lib/action_web_service/scaffolding.rb +281 -0
  29. data/lib/action_web_service/soap/attachment.rb +107 -0
  30. data/lib/action_web_service/soap/baseData.rb +942 -0
  31. data/lib/action_web_service/soap/element.rb +258 -0
  32. data/lib/action_web_service/soap/encodingstyle/aspDotNetHandler.rb +213 -0
  33. data/lib/action_web_service/soap/encodingstyle/handler.rb +100 -0
  34. data/lib/action_web_service/soap/encodingstyle/literalHandler.rb +226 -0
  35. data/lib/action_web_service/soap/encodingstyle/soapHandler.rb +582 -0
  36. data/lib/action_web_service/soap/generator.rb +268 -0
  37. data/lib/action_web_service/soap/header/handler.rb +57 -0
  38. data/lib/action_web_service/soap/header/handlerset.rb +70 -0
  39. data/lib/action_web_service/soap/header/simplehandler.rb +44 -0
  40. data/lib/action_web_service/soap/httpconfigloader.rb +119 -0
  41. data/lib/action_web_service/soap/mapping.rb +10 -0
  42. data/lib/action_web_service/soap/mapping/factory.rb +355 -0
  43. data/lib/action_web_service/soap/mapping/mapping.rb +381 -0
  44. data/lib/action_web_service/soap/mapping/registry.rb +541 -0
  45. data/lib/action_web_service/soap/mapping/rubytypeFactory.rb +475 -0
  46. data/lib/action_web_service/soap/mapping/typeMap.rb +50 -0
  47. data/lib/action_web_service/soap/mapping/wsdlencodedregistry.rb +280 -0
  48. data/lib/action_web_service/soap/mapping/wsdlliteralregistry.rb +418 -0
  49. data/lib/action_web_service/soap/marshal.rb +59 -0
  50. data/lib/action_web_service/soap/mimemessage.rb +240 -0
  51. data/lib/action_web_service/soap/netHttpClient.rb +190 -0
  52. data/lib/action_web_service/soap/parser.rb +251 -0
  53. data/lib/action_web_service/soap/processor.rb +66 -0
  54. data/lib/action_web_service/soap/property.rb +333 -0
  55. data/lib/action_web_service/soap/rpc/cgistub.rb +206 -0
  56. data/lib/action_web_service/soap/rpc/driver.rb +254 -0
  57. data/lib/action_web_service/soap/rpc/element.rb +325 -0
  58. data/lib/action_web_service/soap/rpc/httpserver.rb +129 -0
  59. data/lib/action_web_service/soap/rpc/proxy.rb +497 -0
  60. data/lib/action_web_service/soap/rpc/router.rb +594 -0
  61. data/lib/action_web_service/soap/rpc/rpc.rb +25 -0
  62. data/lib/action_web_service/soap/rpc/soaplet.rb +162 -0
  63. data/lib/action_web_service/soap/rpc/standaloneServer.rb +43 -0
  64. data/lib/action_web_service/soap/soap.rb +140 -0
  65. data/lib/action_web_service/soap/streamHandler.rb +229 -0
  66. data/lib/action_web_service/soap/wsdlDriver.rb +575 -0
  67. data/lib/action_web_service/struct.rb +64 -0
  68. data/lib/action_web_service/support/class_inheritable_options.rb +28 -0
  69. data/lib/action_web_service/support/signature_types.rb +227 -0
  70. data/lib/action_web_service/test_invoke.rb +110 -0
  71. data/lib/action_web_service/version.rb +9 -0
  72. data/lib/action_web_service/wsdl/binding.rb +65 -0
  73. data/lib/action_web_service/wsdl/data.rb +64 -0
  74. data/lib/action_web_service/wsdl/definitions.rb +250 -0
  75. data/lib/action_web_service/wsdl/documentation.rb +32 -0
  76. data/lib/action_web_service/wsdl/import.rb +80 -0
  77. data/lib/action_web_service/wsdl/importer.rb +38 -0
  78. data/lib/action_web_service/wsdl/info.rb +39 -0
  79. data/lib/action_web_service/wsdl/message.rb +54 -0
  80. data/lib/action_web_service/wsdl/operation.rb +130 -0
  81. data/lib/action_web_service/wsdl/operationBinding.rb +108 -0
  82. data/lib/action_web_service/wsdl/param.rb +85 -0
  83. data/lib/action_web_service/wsdl/parser.rb +163 -0
  84. data/lib/action_web_service/wsdl/part.rb +52 -0
  85. data/lib/action_web_service/wsdl/port.rb +84 -0
  86. data/lib/action_web_service/wsdl/portType.rb +73 -0
  87. data/lib/action_web_service/wsdl/service.rb +61 -0
  88. data/lib/action_web_service/wsdl/soap/address.rb +40 -0
  89. data/lib/action_web_service/wsdl/soap/binding.rb +49 -0
  90. data/lib/action_web_service/wsdl/soap/body.rb +56 -0
  91. data/lib/action_web_service/wsdl/soap/cgiStubCreator.rb +76 -0
  92. data/lib/action_web_service/wsdl/soap/classDefCreator.rb +314 -0
  93. data/lib/action_web_service/wsdl/soap/classDefCreatorSupport.rb +126 -0
  94. data/lib/action_web_service/wsdl/soap/clientSkeltonCreator.rb +78 -0
  95. data/lib/action_web_service/wsdl/soap/complexType.rb +161 -0
  96. data/lib/action_web_service/wsdl/soap/data.rb +42 -0
  97. data/lib/action_web_service/wsdl/soap/definitions.rb +149 -0
  98. data/lib/action_web_service/wsdl/soap/driverCreator.rb +95 -0
  99. data/lib/action_web_service/wsdl/soap/element.rb +28 -0
  100. data/lib/action_web_service/wsdl/soap/fault.rb +56 -0
  101. data/lib/action_web_service/wsdl/soap/header.rb +86 -0
  102. data/lib/action_web_service/wsdl/soap/headerfault.rb +56 -0
  103. data/lib/action_web_service/wsdl/soap/mappingRegistryCreator.rb +92 -0
  104. data/lib/action_web_service/wsdl/soap/methodDefCreator.rb +228 -0
  105. data/lib/action_web_service/wsdl/soap/operation.rb +122 -0
  106. data/lib/action_web_service/wsdl/soap/servantSkeltonCreator.rb +67 -0
  107. data/lib/action_web_service/wsdl/soap/standaloneServerStubCreator.rb +85 -0
  108. data/lib/action_web_service/wsdl/soap/wsdl2ruby.rb +176 -0
  109. data/lib/action_web_service/wsdl/types.rb +43 -0
  110. data/lib/action_web_service/wsdl/wsdl.rb +23 -0
  111. data/lib/action_web_service/wsdl/xmlSchema/all.rb +69 -0
  112. data/lib/action_web_service/wsdl/xmlSchema/annotation.rb +34 -0
  113. data/lib/action_web_service/wsdl/xmlSchema/any.rb +56 -0
  114. data/lib/action_web_service/wsdl/xmlSchema/attribute.rb +127 -0
  115. data/lib/action_web_service/wsdl/xmlSchema/choice.rb +69 -0
  116. data/lib/action_web_service/wsdl/xmlSchema/complexContent.rb +92 -0
  117. data/lib/action_web_service/wsdl/xmlSchema/complexType.rb +139 -0
  118. data/lib/action_web_service/wsdl/xmlSchema/content.rb +96 -0
  119. data/lib/action_web_service/wsdl/xmlSchema/data.rb +80 -0
  120. data/lib/action_web_service/wsdl/xmlSchema/element.rb +154 -0
  121. data/lib/action_web_service/wsdl/xmlSchema/enumeration.rb +36 -0
  122. data/lib/action_web_service/wsdl/xmlSchema/import.rb +65 -0
  123. data/lib/action_web_service/wsdl/xmlSchema/importer.rb +87 -0
  124. data/lib/action_web_service/wsdl/xmlSchema/include.rb +54 -0
  125. data/lib/action_web_service/wsdl/xmlSchema/length.rb +35 -0
  126. data/lib/action_web_service/wsdl/xmlSchema/parser.rb +166 -0
  127. data/lib/action_web_service/wsdl/xmlSchema/pattern.rb +36 -0
  128. data/lib/action_web_service/wsdl/xmlSchema/schema.rb +143 -0
  129. data/lib/action_web_service/wsdl/xmlSchema/sequence.rb +69 -0
  130. data/lib/action_web_service/wsdl/xmlSchema/simpleContent.rb +65 -0
  131. data/lib/action_web_service/wsdl/xmlSchema/simpleExtension.rb +54 -0
  132. data/lib/action_web_service/wsdl/xmlSchema/simpleRestriction.rb +73 -0
  133. data/lib/action_web_service/wsdl/xmlSchema/simpleType.rb +73 -0
  134. data/lib/action_web_service/wsdl/xmlSchema/unique.rb +34 -0
  135. data/lib/action_web_service/wsdl/xmlSchema/xsd2ruby.rb +107 -0
  136. data/lib/action_web_service/xsd/charset.rb +187 -0
  137. data/lib/action_web_service/xsd/codegen.rb +12 -0
  138. data/lib/action_web_service/xsd/codegen/classdef.rb +203 -0
  139. data/lib/action_web_service/xsd/codegen/commentdef.rb +34 -0
  140. data/lib/action_web_service/xsd/codegen/gensupport.rb +166 -0
  141. data/lib/action_web_service/xsd/codegen/methoddef.rb +63 -0
  142. data/lib/action_web_service/xsd/codegen/moduledef.rb +191 -0
  143. data/lib/action_web_service/xsd/datatypes.rb +1269 -0
  144. data/lib/action_web_service/xsd/datatypes1999.rb +20 -0
  145. data/lib/action_web_service/xsd/iconvcharset.rb +33 -0
  146. data/lib/action_web_service/xsd/mapping.rb +42 -0
  147. data/lib/action_web_service/xsd/namedelements.rb +95 -0
  148. data/lib/action_web_service/xsd/ns.rb +140 -0
  149. data/lib/action_web_service/xsd/qname.rb +78 -0
  150. data/lib/action_web_service/xsd/xmlparser.rb +61 -0
  151. data/lib/action_web_service/xsd/xmlparser/parser.rb +96 -0
  152. data/lib/action_web_service/xsd/xmlparser/rexmlparser.rb +54 -0
  153. data/lib/action_web_service/xsd/xmlparser/xmlparser.rb +50 -0
  154. data/lib/action_web_service/xsd/xmlparser/xmlscanner.rb +147 -0
  155. data/lib/actionwebservice.rb +1 -0
  156. data/setup.rb +1379 -0
  157. data/test/abstract_client.rb +183 -0
  158. data/test/abstract_dispatcher.rb +548 -0
  159. data/test/abstract_unit.rb +45 -0
  160. data/test/api_test.rb +103 -0
  161. data/test/apis/auto_load_api.rb +3 -0
  162. data/test/apis/broken_auto_load_api.rb +2 -0
  163. data/test/base_test.rb +42 -0
  164. data/test/casting_test.rb +95 -0
  165. data/test/client_soap_test.rb +156 -0
  166. data/test/client_xmlrpc_test.rb +153 -0
  167. data/test/container_test.rb +73 -0
  168. data/test/dispatcher_action_controller_soap_test.rb +139 -0
  169. data/test/dispatcher_action_controller_xmlrpc_test.rb +59 -0
  170. data/test/fixtures/db_definitions/mysql.sql +8 -0
  171. data/test/fixtures/db_definitions/sqlite3.sql +8 -0
  172. data/test/fixtures/users.yml +12 -0
  173. data/test/gencov +3 -0
  174. data/test/invocation_test.rb +185 -0
  175. data/test/run +6 -0
  176. data/test/scaffolded_controller_test.rb +146 -0
  177. data/test/struct_test.rb +52 -0
  178. data/test/test_invoke_test.rb +112 -0
  179. metadata +265 -0
@@ -0,0 +1,183 @@
1
+ require 'abstract_unit'
2
+ require 'webrick'
3
+ require 'webrick/log'
4
+ require 'singleton'
5
+
6
+ module ClientTest
7
+ class Person < ActionWebService::Struct
8
+ member :firstnames, [:string]
9
+ member :lastname, :string
10
+
11
+ def ==(other)
12
+ firstnames == other.firstnames && lastname == other.lastname
13
+ end
14
+ end
15
+
16
+ class Inner < ActionWebService::Struct
17
+ member :name, :string
18
+ end
19
+
20
+ class Outer < ActionWebService::Struct
21
+ member :name, :string
22
+ member :inner, Inner
23
+ end
24
+
25
+ class User < ActiveRecord::Base
26
+ end
27
+
28
+ module Accounting
29
+ class User < ActiveRecord::Base
30
+ end
31
+ end
32
+
33
+ class WithModel < ActionWebService::Struct
34
+ member :user, User
35
+ member :users, [User]
36
+ end
37
+
38
+ class WithMultiDimArray < ActionWebService::Struct
39
+ member :pref, [[:string]]
40
+ end
41
+
42
+ class API < ActionWebService::API::Base
43
+ api_method :void
44
+ api_method :normal, :expects => [:int, :int], :returns => [:int]
45
+ api_method :array_return, :returns => [[Person]]
46
+ api_method :struct_pass, :expects => [[Person]], :returns => [:bool]
47
+ api_method :nil_struct_return, :returns => [Person]
48
+ api_method :inner_nil, :returns => [Outer]
49
+ api_method :client_container, :returns => [:int]
50
+ api_method :named_parameters, :expects => [{:key=>:string}, {:id=>:int}]
51
+ api_method :thrower
52
+ api_method :user_return, :returns => [User]
53
+ api_method :with_model_return, :returns => [WithModel]
54
+ api_method :scoped_model_return, :returns => [Accounting::User]
55
+ api_method :multi_dim_return, :returns => [WithMultiDimArray]
56
+ end
57
+
58
+ class NullLogOut
59
+ def <<(*args); end
60
+ end
61
+
62
+ class Container < ActionController::Base
63
+ web_service_api API
64
+
65
+ attr_accessor :value_void
66
+ attr_accessor :value_normal
67
+ attr_accessor :value_array_return
68
+ attr_accessor :value_struct_pass
69
+ attr_accessor :value_named_parameters
70
+
71
+ def initialize
72
+ @value_void = nil
73
+ @value_normal = nil
74
+ @value_array_return = nil
75
+ @value_struct_pass = nil
76
+ @value_named_parameters = nil
77
+ end
78
+
79
+ def void
80
+ @value_void = @method_params
81
+ end
82
+
83
+ def normal
84
+ @value_normal = @method_params
85
+ 5
86
+ end
87
+
88
+ def array_return
89
+ person = Person.new
90
+ person.firstnames = ["one", "two"]
91
+ person.lastname = "last"
92
+ @value_array_return = [person]
93
+ end
94
+
95
+ def struct_pass
96
+ @value_struct_pass = @method_params
97
+ true
98
+ end
99
+
100
+ def nil_struct_return
101
+ nil
102
+ end
103
+
104
+ def inner_nil
105
+ Outer.new :name => 'outer', :inner => nil
106
+ end
107
+
108
+ def client_container
109
+ 50
110
+ end
111
+
112
+ def named_parameters
113
+ @value_named_parameters = @method_params
114
+ end
115
+
116
+ def thrower
117
+ raise "Hi"
118
+ end
119
+
120
+ def user_return
121
+ User.find(1)
122
+ end
123
+
124
+ def with_model_return
125
+ WithModel.new :user => User.find(1), :users => User.find(:all)
126
+ end
127
+
128
+ def scoped_model_return
129
+ Accounting::User.find(1)
130
+ end
131
+
132
+ def multi_dim_return
133
+ WithMultiDimArray.new :pref => [%w{pref1 value1}, %w{pref2 value2}]
134
+ end
135
+ end
136
+
137
+ class AbstractClientLet < WEBrick::HTTPServlet::AbstractServlet
138
+ def initialize(controller)
139
+ @controller = controller
140
+ end
141
+
142
+ def get_instance(*args)
143
+ self
144
+ end
145
+
146
+ def require_path_info?
147
+ false
148
+ end
149
+
150
+ def do_GET(req, res)
151
+ raise WEBrick::HTTPStatus::MethodNotAllowed, "GET request not allowed."
152
+ end
153
+
154
+ def do_POST(req, res)
155
+ raise NotImplementedError
156
+ end
157
+ end
158
+
159
+ class AbstractServer
160
+ include ClientTest
161
+ include Singleton
162
+ attr :container
163
+ def initialize
164
+ @container = Container.new
165
+ @clientlet = create_clientlet(@container)
166
+ log = WEBrick::BasicLog.new(NullLogOut.new)
167
+ @server = WEBrick::HTTPServer.new(:Port => server_port, :Logger => log, :AccessLog => [])
168
+ @server.mount('/', @clientlet)
169
+ @thr = Thread.new { @server.start }
170
+ until @server.status == :Running; end
171
+ at_exit { @server.stop; @thr.join }
172
+ end
173
+
174
+ protected
175
+ def create_clientlet
176
+ raise NotImplementedError
177
+ end
178
+
179
+ def server_port
180
+ raise NotImplementedError
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,548 @@
1
+ require 'abstract_unit'
2
+ require 'stringio'
3
+
4
+ class ActionController::Base; def rescue_action(e) raise e end; end
5
+
6
+ module DispatcherTest
7
+ Utf8String = "One World Caf\303\251"
8
+ WsdlNamespace = 'http://rubyonrails.com/some/namespace'
9
+
10
+ class Node < ActiveRecord::Base
11
+ def initialize(*args)
12
+ super(*args)
13
+ @new_record = false
14
+ end
15
+
16
+ class << self
17
+ def name
18
+ "DispatcherTest::Node"
19
+ end
20
+
21
+ def columns(*args)
22
+ [
23
+ ActiveRecord::ConnectionAdapters::Column.new('id', 0, 'int'),
24
+ ActiveRecord::ConnectionAdapters::Column.new('name', nil, 'string'),
25
+ ActiveRecord::ConnectionAdapters::Column.new('description', nil, 'string'),
26
+ ]
27
+ end
28
+
29
+ def connection
30
+ self
31
+ end
32
+ end
33
+ end
34
+
35
+ class Person < ActionWebService::Struct
36
+ member :id, :int
37
+ member :name, :string
38
+
39
+ def ==(other)
40
+ self.id == other.id && self.name == other.name
41
+ end
42
+ end
43
+
44
+ class API < ActionWebService::API::Base
45
+ api_method :add, :expects => [:int, :int], :returns => [:int]
46
+ api_method :interceptee
47
+ api_method :struct_return, :returns => [[Node]]
48
+ api_method :void
49
+ end
50
+
51
+ class DirectAPI < ActionWebService::API::Base
52
+ api_method :add, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int]
53
+ api_method :add2, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int]
54
+ api_method :before_filtered
55
+ api_method :after_filtered, :returns => [[:int]]
56
+ api_method :struct_return, :returns => [[Node]]
57
+ api_method :struct_pass, :expects => [{:person => Person}]
58
+ api_method :base_struct_return, :returns => [[Person]]
59
+ api_method :hash_struct_return, :returns => [[Person]]
60
+ api_method :thrower
61
+ api_method :void
62
+ api_method :test_utf8, :returns => [:string]
63
+ api_method :hex, :expects => [:base64], :returns => [:string]
64
+ api_method :unhex, :expects => [:string], :returns => [:base64]
65
+ api_method :time, :expects => [:time], :returns => [:time]
66
+ end
67
+
68
+ class VirtualAPI < ActionWebService::API::Base
69
+ default_api_method :fallback
70
+ end
71
+
72
+ class Service < ActionWebService::Base
73
+ web_service_api API
74
+
75
+ before_invocation :do_intercept, :only => [:interceptee]
76
+
77
+ attr :added
78
+ attr :intercepted
79
+ attr :void_called
80
+
81
+ def initialize
82
+ @void_called = false
83
+ end
84
+
85
+ def add(a, b)
86
+ @added = a + b
87
+ end
88
+
89
+ def interceptee
90
+ @intercepted = false
91
+ end
92
+
93
+ def struct_return
94
+ n1 = Node.new('id' => 1, 'name' => 'node1', 'description' => 'Node 1')
95
+ n2 = Node.new('id' => 2, 'name' => 'node2', 'description' => 'Node 2')
96
+ [n1, n2]
97
+ end
98
+
99
+ def void(*args)
100
+ @void_called = args
101
+ end
102
+
103
+ def do_intercept(name, args)
104
+ [false, "permission denied"]
105
+ end
106
+ end
107
+
108
+ class MTAPI < ActionWebService::API::Base
109
+ inflect_names false
110
+ api_method :getCategories, :returns => [[:string]]
111
+ api_method :bool, :returns => [:bool]
112
+ api_method :alwaysFail
113
+ api_method :person, :returns => [Person]
114
+ end
115
+
116
+ class BloggerAPI < ActionWebService::API::Base
117
+ inflect_names false
118
+ api_method :getCategories, :returns => [[:string]]
119
+ api_method :str, :expects => [:int], :returns => [:string]
120
+ api_method :alwaysFail
121
+ end
122
+
123
+ class MTService < ActionWebService::Base
124
+ web_service_api MTAPI
125
+
126
+ def getCategories
127
+ ["mtCat1", "mtCat2"]
128
+ end
129
+
130
+ def bool
131
+ 'y'
132
+ end
133
+
134
+ def alwaysFail
135
+ raise "MT AlwaysFail"
136
+ end
137
+
138
+ def person
139
+ Person.new('id' => 1, 'name' => 'person1')
140
+ end
141
+ end
142
+
143
+ class BloggerService < ActionWebService::Base
144
+ web_service_api BloggerAPI
145
+
146
+ def getCategories
147
+ ["bloggerCat1", "bloggerCat2"]
148
+ end
149
+
150
+ def str(int)
151
+ unless int.is_a?(Integer)
152
+ raise "Not an integer!"
153
+ end
154
+ 500 + int
155
+ end
156
+
157
+ def alwaysFail
158
+ raise "Blogger AlwaysFail"
159
+ end
160
+ end
161
+
162
+ class AbstractController < ActionController::Base
163
+ def generate_wsdl
164
+ self.request ||= ::ActionController::TestRequest.new
165
+ to_wsdl
166
+ end
167
+ end
168
+
169
+ class DelegatedController < AbstractController
170
+ web_service_dispatching_mode :delegated
171
+ wsdl_namespace WsdlNamespace
172
+
173
+ web_service(:test_service) { @service ||= Service.new; @service }
174
+ end
175
+
176
+ class LayeredController < AbstractController
177
+ web_service_dispatching_mode :layered
178
+ wsdl_namespace WsdlNamespace
179
+
180
+ web_service(:mt) { @mt_service ||= MTService.new; @mt_service }
181
+ web_service(:blogger) { @blogger_service ||= BloggerService.new; @blogger_service }
182
+ end
183
+
184
+ class DirectController < AbstractController
185
+ web_service_api DirectAPI
186
+ web_service_dispatching_mode :direct
187
+ wsdl_namespace WsdlNamespace
188
+
189
+ before_invocation :alwaysfail, :only => [:before_filtered]
190
+ after_invocation :alwaysok, :only => [:after_filtered]
191
+
192
+ attr :added
193
+ attr :added2
194
+ attr :before_filter_called
195
+ attr :before_filter_target_called
196
+ attr :after_filter_called
197
+ attr :after_filter_target_called
198
+ attr :void_called
199
+ attr :struct_pass_value
200
+
201
+ def initialize
202
+ @before_filter_called = false
203
+ @before_filter_target_called = false
204
+ @after_filter_called = false
205
+ @after_filter_target_called = false
206
+ @void_called = false
207
+ @struct_pass_value = false
208
+ end
209
+
210
+ def add
211
+ @added = params['a'] + params['b']
212
+ end
213
+
214
+ def add2(a, b)
215
+ @added2 = a + b
216
+ end
217
+
218
+ def before_filtered
219
+ @before_filter_target_called = true
220
+ end
221
+
222
+ def after_filtered
223
+ @after_filter_target_called = true
224
+ [5, 6, 7]
225
+ end
226
+
227
+ def thrower
228
+ raise "Hi, I'm an exception"
229
+ end
230
+
231
+ def struct_return
232
+ n1 = Node.new('id' => 1, 'name' => 'node1', 'description' => 'Node 1')
233
+ n2 = Node.new('id' => 2, 'name' => 'node2', 'description' => 'Node 2')
234
+ [n1, n2]
235
+ end
236
+
237
+ def struct_pass(person)
238
+ @struct_pass_value = person
239
+ end
240
+
241
+ def base_struct_return
242
+ p1 = Person.new('id' => 1, 'name' => 'person1')
243
+ p2 = Person.new('id' => 2, 'name' => 'person2')
244
+ [p1, p2]
245
+ end
246
+
247
+ def hash_struct_return
248
+ p1 = { :id => '1', 'name' => 'test' }
249
+ p2 = { 'id' => '2', :name => 'person2' }
250
+ [p1, p2]
251
+ end
252
+
253
+ def void
254
+ @void_called = @method_params
255
+ end
256
+
257
+ def test_utf8
258
+ Utf8String
259
+ end
260
+
261
+ def hex(s)
262
+ return s.unpack("H*")[0]
263
+ end
264
+
265
+ def unhex(s)
266
+ return [s].pack("H*")
267
+ end
268
+
269
+ def time(t)
270
+ t
271
+ end
272
+
273
+ protected
274
+ def alwaysfail(method_name, params)
275
+ @before_filter_called = true
276
+ false
277
+ end
278
+
279
+ def alwaysok(method_name, params, return_value)
280
+ @after_filter_called = true
281
+ end
282
+ end
283
+
284
+ class VirtualController < AbstractController
285
+ web_service_api VirtualAPI
286
+ wsdl_namespace WsdlNamespace
287
+
288
+ def fallback
289
+ "fallback!"
290
+ end
291
+ end
292
+ end
293
+
294
+ module DispatcherCommonTests
295
+ def test_direct_dispatching
296
+ assert_equal(70, do_method_call(@direct_controller, 'Add', 20, 50))
297
+ assert_equal(70, @direct_controller.added)
298
+ assert_equal(50, do_method_call(@direct_controller, 'Add2', 25, 25))
299
+ assert_equal(50, @direct_controller.added2)
300
+ assert(@direct_controller.void_called == false)
301
+ assert(do_method_call(@direct_controller, 'Void', 3, 4, 5).nil?)
302
+ assert(@direct_controller.void_called == [])
303
+ result = do_method_call(@direct_controller, 'BaseStructReturn')
304
+ assert(result[0].is_a?(DispatcherTest::Person))
305
+ assert(result[1].is_a?(DispatcherTest::Person))
306
+ assert_equal("cafe", do_method_call(@direct_controller, 'Hex', "\xca\xfe"))
307
+ assert_equal("\xca\xfe", do_method_call(@direct_controller, 'Unhex', "cafe"))
308
+ time = Time.gm(1998, "Feb", 02, 15, 12, 01)
309
+ assert_equal(time, do_method_call(@direct_controller, 'Time', time))
310
+ end
311
+
312
+ def test_direct_entrypoint
313
+ assert(@direct_controller.respond_to?(:api))
314
+ end
315
+
316
+ def test_virtual_dispatching
317
+ assert_equal("fallback!", do_method_call(@virtual_controller, 'VirtualOne'))
318
+ assert_equal("fallback!", do_method_call(@virtual_controller, 'VirtualTwo'))
319
+ end
320
+
321
+ def test_direct_filtering
322
+ assert_equal(false, @direct_controller.before_filter_called)
323
+ assert_equal(false, @direct_controller.before_filter_target_called)
324
+ do_method_call(@direct_controller, 'BeforeFiltered')
325
+ assert_equal(true, @direct_controller.before_filter_called)
326
+ assert_equal(false, @direct_controller.before_filter_target_called)
327
+ assert_equal(false, @direct_controller.after_filter_called)
328
+ assert_equal(false, @direct_controller.after_filter_target_called)
329
+ assert_equal([5, 6, 7], do_method_call(@direct_controller, 'AfterFiltered'))
330
+ assert_equal(true, @direct_controller.after_filter_called)
331
+ assert_equal(true, @direct_controller.after_filter_target_called)
332
+ end
333
+
334
+ def test_delegated_dispatching
335
+ assert_equal(130, do_method_call(@delegated_controller, 'Add', 50, 80))
336
+ service = @delegated_controller.web_service_object(:test_service)
337
+ assert_equal(130, service.added)
338
+ @delegated_controller.web_service_exception_reporting = true
339
+ assert(service.intercepted.nil?)
340
+ result = do_method_call(@delegated_controller, 'Interceptee')
341
+ assert(service.intercepted.nil?)
342
+ assert(is_exception?(result))
343
+ assert_match(/permission denied/, exception_message(result))
344
+ result = do_method_call(@delegated_controller, 'NonExistentMethod')
345
+ assert(is_exception?(result))
346
+ assert_match(/NonExistentMethod/, exception_message(result))
347
+ assert(service.void_called == false)
348
+ assert(do_method_call(@delegated_controller, 'Void', 3, 4, 5).nil?)
349
+ assert(service.void_called == [])
350
+ end
351
+
352
+ def test_garbage_request
353
+ [@direct_controller, @delegated_controller].each do |controller|
354
+ controller.class.web_service_exception_reporting = true
355
+ send_garbage_request = lambda do
356
+ service_name = service_name(controller)
357
+ request = protocol.encode_action_pack_request(service_name, 'broken, method, name!', 'broken request body', :request_class => ActionController::TestRequest)
358
+ response = ActionController::TestResponse.new
359
+ controller.process(request, response)
360
+ # puts response.body
361
+ assert(response.status =~ /^500/)
362
+ end
363
+ send_garbage_request.call
364
+ controller.class.web_service_exception_reporting = false
365
+ send_garbage_request.call
366
+ end
367
+ end
368
+
369
+ def test_exception_marshaling
370
+ @direct_controller.web_service_exception_reporting = true
371
+ result = do_method_call(@direct_controller, 'Thrower')
372
+ assert(is_exception?(result))
373
+ assert_equal("Hi, I'm an exception", exception_message(result))
374
+ @direct_controller.web_service_exception_reporting = false
375
+ result = do_method_call(@direct_controller, 'Thrower')
376
+ assert(exception_message(result) != "Hi, I'm an exception")
377
+ end
378
+
379
+ def test_ar_struct_return
380
+ [@direct_controller, @delegated_controller].each do |controller|
381
+ result = do_method_call(controller, 'StructReturn')
382
+ assert(result[0].is_a?(DispatcherTest::Node))
383
+ assert(result[1].is_a?(DispatcherTest::Node))
384
+ assert_equal('node1', result[0].name)
385
+ assert_equal('node2', result[1].name)
386
+ end
387
+ end
388
+
389
+ def test_casting
390
+ assert_equal 70, do_method_call(@direct_controller, 'Add', "50", "20")
391
+ assert_equal false, @direct_controller.struct_pass_value
392
+ person = DispatcherTest::Person.new(:id => 1, :name => 'test')
393
+ result = do_method_call(@direct_controller, 'StructPass', person)
394
+ assert(nil == result || true == result)
395
+ assert_equal person, @direct_controller.struct_pass_value
396
+ assert !person.equal?(@direct_controller.struct_pass_value)
397
+ result = do_method_call(@direct_controller, 'StructPass', {'id' => '1', 'name' => 'test'})
398
+ case
399
+ when soap?
400
+ assert_equal(person, @direct_controller.struct_pass_value)
401
+ assert !person.equal?(@direct_controller.struct_pass_value)
402
+ when xmlrpc?
403
+ assert_equal(person, @direct_controller.struct_pass_value)
404
+ assert !person.equal?(@direct_controller.struct_pass_value)
405
+ end
406
+ assert_equal person, do_method_call(@direct_controller, 'HashStructReturn')[0]
407
+ result = do_method_call(@direct_controller, 'StructPass', {'id' => '1', 'name' => 'test', 'nonexistent_attribute' => 'value'})
408
+ case
409
+ when soap?
410
+ assert_equal(person, @direct_controller.struct_pass_value)
411
+ assert !person.equal?(@direct_controller.struct_pass_value)
412
+ when xmlrpc?
413
+ assert_equal(person, @direct_controller.struct_pass_value)
414
+ assert !person.equal?(@direct_controller.struct_pass_value)
415
+ end
416
+ end
417
+
418
+ def test_logging
419
+ buf = ""
420
+ ActionController::Base.logger = Logger.new(StringIO.new(buf))
421
+ test_casting
422
+ test_garbage_request
423
+ test_exception_marshaling
424
+ ActionController::Base.logger = nil
425
+ assert_match /Web Service Response/, buf
426
+ assert_match /Web Service Request/, buf
427
+ end
428
+
429
+ def test_allowed_http_methods
430
+ webservice_api = @direct_controller.class.web_service_api
431
+ original_allowed_http_methods = webservice_api.allowed_http_methods
432
+
433
+ # check defaults
434
+ assert_equal false, http_method_allowed?(:get)
435
+ assert_equal false, http_method_allowed?(:head)
436
+ assert_equal false, http_method_allowed?(:put)
437
+ assert_equal false, http_method_allowed?(:delete)
438
+ assert_equal true, http_method_allowed?(:post)
439
+
440
+ # allow get and post
441
+ webservice_api.allowed_http_methods = [ :get, :post ]
442
+ assert_equal true, http_method_allowed?(:get)
443
+ assert_equal true, http_method_allowed?(:post)
444
+
445
+ # allow get only
446
+ webservice_api.allowed_http_methods = [ :get ]
447
+ assert_equal true, http_method_allowed?(:get)
448
+ assert_equal false, http_method_allowed?(:post)
449
+
450
+ # allow delete only
451
+ webservice_api.allowed_http_methods = [ 'DELETE' ]
452
+ assert_equal false, http_method_allowed?(:get)
453
+ assert_equal false, http_method_allowed?(:head)
454
+ assert_equal false, http_method_allowed?(:post)
455
+ assert_equal false, http_method_allowed?(:put)
456
+ assert_equal true, http_method_allowed?(:delete)
457
+
458
+ ensure
459
+ webservice_api.allowed_http_methods = original_allowed_http_methods
460
+ end
461
+
462
+ protected
463
+ def service_name(container)
464
+ raise NotImplementedError
465
+ end
466
+
467
+ def exception_message(obj)
468
+ raise NotImplementedError
469
+ end
470
+
471
+ def is_exception?(obj)
472
+ raise NotImplementedError
473
+ end
474
+
475
+ def protocol
476
+ @protocol
477
+ end
478
+
479
+ def soap?
480
+ protocol.is_a? ActionWebService::Protocol::Soap::SoapProtocol
481
+ end
482
+
483
+ def xmlrpc?
484
+ protocol.is_a? ActionWebService::Protocol::XmlRpc::XmlRpcProtocol
485
+ end
486
+
487
+ def do_method_call(container, public_method_name, *params)
488
+ request_env = {}
489
+ mode = container.web_service_dispatching_mode
490
+ case mode
491
+ when :direct
492
+ service_name = service_name(container)
493
+ api = container.class.web_service_api
494
+ method = api.public_api_method_instance(public_method_name)
495
+ when :delegated
496
+ service_name = service_name(container)
497
+ api = container.web_service_object(service_name).class.web_service_api
498
+ method = api.public_api_method_instance(public_method_name)
499
+ when :layered
500
+ service_name = nil
501
+ real_method_name = nil
502
+ if public_method_name =~ /^([^\.]+)\.(.*)$/
503
+ service_name = $1
504
+ real_method_name = $2
505
+ end
506
+ if soap?
507
+ public_method_name = real_method_name
508
+ request_env['HTTP_SOAPACTION'] = "/soap/#{service_name}/#{real_method_name}"
509
+ end
510
+ api = container.web_service_object(service_name.to_sym).class.web_service_api rescue nil
511
+ method = api.public_api_method_instance(real_method_name) rescue nil
512
+ service_name = self.service_name(container)
513
+ end
514
+ protocol.register_api(api)
515
+ virtual = false
516
+ unless method
517
+ virtual = true
518
+ method ||= ActionWebService::API::Method.new(public_method_name.underscore.to_sym, public_method_name, nil, nil)
519
+ end
520
+ body = protocol.encode_request(public_method_name, params.dup, method.expects)
521
+ # puts body
522
+ ap_request = protocol.encode_action_pack_request(service_name, public_method_name, body, :request_class => ActionController::TestRequest)
523
+ ap_request.env.update(request_env)
524
+ ap_response = ActionController::TestResponse.new
525
+ container.process(ap_request, ap_response)
526
+ # puts ap_response.body
527
+ @response_body = ap_response.body
528
+ public_method_name, return_value = protocol.decode_response(ap_response.body)
529
+ unless is_exception?(return_value) || virtual
530
+ return_value = method.cast_returns(return_value)
531
+ end
532
+ if soap?
533
+ # http://dev.rubyonrails.com/changeset/920
534
+ assert_match(/Response$/, public_method_name) unless public_method_name == "fault"
535
+ end
536
+ return_value
537
+ end
538
+
539
+ def http_method_allowed?(method)
540
+ method = method.to_s.upcase
541
+ test_request = ActionController::TestRequest.new
542
+ test_request.action = 'api'
543
+ test_response = ActionController::TestResponse.new
544
+ test_request.env['REQUEST_METHOD'] = method
545
+ result = @direct_controller.process(test_request, test_response)
546
+ result.body =~ /(GET|POST|PUT|DELETE|TRACE|CONNECT) not supported/ ? false : true
547
+ end
548
+ end