fdv-actionwebservice 2.3.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) 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/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.rb +66 -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 +149 -0
  28. data/lib/action_web_service/client.rb +3 -0
  29. data/lib/action_web_service/client/base.rb +28 -0
  30. data/lib/action_web_service/client/soap_client.rb +113 -0
  31. data/lib/action_web_service/client/xmlrpc_client.rb +58 -0
  32. data/lib/action_web_service/container.rb +3 -0
  33. data/lib/action_web_service/container/action_controller_container.rb +93 -0
  34. data/lib/action_web_service/container/delegated_container.rb +86 -0
  35. data/lib/action_web_service/container/direct_container.rb +69 -0
  36. data/lib/action_web_service/dispatcher.rb +2 -0
  37. data/lib/action_web_service/dispatcher/abstract.rb +207 -0
  38. data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +379 -0
  39. data/lib/action_web_service/invocation.rb +202 -0
  40. data/lib/action_web_service/protocol.rb +4 -0
  41. data/lib/action_web_service/protocol/abstract.rb +112 -0
  42. data/lib/action_web_service/protocol/discovery.rb +37 -0
  43. data/lib/action_web_service/protocol/soap_protocol.rb +176 -0
  44. data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +242 -0
  45. data/lib/action_web_service/protocol/xmlrpc_protocol.rb +122 -0
  46. data/lib/action_web_service/scaffolding.rb +281 -0
  47. data/lib/action_web_service/struct.rb +64 -0
  48. data/lib/action_web_service/support/class_inheritable_options.rb +26 -0
  49. data/lib/action_web_service/support/signature_types.rb +226 -0
  50. data/lib/action_web_service/templates/scaffolds/layout.html.erb +65 -0
  51. data/lib/action_web_service/templates/scaffolds/methods.html.erb +6 -0
  52. data/lib/action_web_service/templates/scaffolds/parameters.html.erb +29 -0
  53. data/lib/action_web_service/templates/scaffolds/result.html.erb +30 -0
  54. data/lib/action_web_service/test_invoke.rb +110 -0
  55. data/lib/action_web_service/version.rb +9 -0
  56. data/lib/actionwebservice.rb +1 -0
  57. data/setup.rb +1379 -0
  58. data/test/abstract_client.rb +183 -0
  59. data/test/abstract_dispatcher.rb +548 -0
  60. data/test/abstract_unit.rb +43 -0
  61. data/test/api_test.rb +102 -0
  62. data/test/apis/auto_load_api.rb +3 -0
  63. data/test/apis/broken_auto_load_api.rb +2 -0
  64. data/test/base_test.rb +42 -0
  65. data/test/casting_test.rb +95 -0
  66. data/test/client_soap_test.rb +155 -0
  67. data/test/client_xmlrpc_test.rb +153 -0
  68. data/test/container_test.rb +73 -0
  69. data/test/dispatcher_action_controller_soap_test.rb +139 -0
  70. data/test/dispatcher_action_controller_xmlrpc_test.rb +59 -0
  71. data/test/fixtures/db_definitions/mysql.sql +8 -0
  72. data/test/fixtures/users.yml +12 -0
  73. data/test/gencov +3 -0
  74. data/test/invocation_test.rb +185 -0
  75. data/test/run +6 -0
  76. data/test/scaffolded_controller_test.rb +146 -0
  77. data/test/struct_test.rb +52 -0
  78. data/test/test_invoke_test.rb +112 -0
  79. metadata +166 -0
@@ -0,0 +1,64 @@
1
+ module ActionWebService
2
+ # To send structured types across the wire, derive from ActionWebService::Struct,
3
+ # and use +member+ to declare structure members.
4
+ #
5
+ # ActionWebService::Struct should be used in method signatures when you want to accept or return
6
+ # structured types that have no Active Record model class representations, or you don't
7
+ # want to expose your entire Active Record model to remote callers.
8
+ #
9
+ # === Example
10
+ #
11
+ # class Person < ActionWebService::Struct
12
+ # member :id, :int
13
+ # member :firstnames, [:string]
14
+ # member :lastname, :string
15
+ # member :email, :string
16
+ # end
17
+ # person = Person.new(:id => 5, :firstname => 'john', :lastname => 'doe')
18
+ #
19
+ # Active Record model classes are already implicitly supported in method
20
+ # signatures.
21
+ class Struct
22
+ # If a Hash is given as argument to an ActionWebService::Struct constructor,
23
+ # it can contain initial values for the structure member.
24
+ def initialize(values={})
25
+ if values.is_a?(Hash)
26
+ values.map{|k,v| __send__('%s=' % k.to_s, v)}
27
+ end
28
+ end
29
+
30
+ # The member with the given name
31
+ def [](name)
32
+ send(name.to_s)
33
+ end
34
+
35
+ # Iterates through each member
36
+ def each_pair(&block)
37
+ self.class.members.each do |name, type|
38
+ yield name, self.__send__(name)
39
+ end
40
+ end
41
+
42
+ class << self
43
+ # Creates a structure member with the specified +name+ and +type+. Generates
44
+ # accessor methods for reading and writing the member value.
45
+ def member(name, type)
46
+ name = name.to_sym
47
+ type = ActionWebService::SignatureTypes.canonical_signature_entry({ name => type }, 0)
48
+ write_inheritable_hash("struct_members", name => type)
49
+ class_eval <<-END
50
+ def #{name}; @#{name}; end
51
+ def #{name}=(value); @#{name} = value; end
52
+ END
53
+ end
54
+
55
+ def members # :nodoc:
56
+ read_inheritable_attribute("struct_members") || {}
57
+ end
58
+
59
+ def member_type(name) # :nodoc:
60
+ members[name.to_sym]
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,26 @@
1
+ class Class # :nodoc:
2
+ def class_inheritable_option(sym, default_value=nil)
3
+ write_inheritable_attribute sym, default_value
4
+ class_eval <<-EOS
5
+ def self.#{sym}(value=nil)
6
+ if !value.nil?
7
+ write_inheritable_attribute(:#{sym}, value)
8
+ else
9
+ read_inheritable_attribute(:#{sym})
10
+ end
11
+ end
12
+
13
+ def self.#{sym}=(value)
14
+ write_inheritable_attribute(:#{sym}, value)
15
+ end
16
+
17
+ def #{sym}
18
+ self.class.#{sym}
19
+ end
20
+
21
+ def #{sym}=(value)
22
+ self.class.#{sym} = value
23
+ end
24
+ EOS
25
+ end
26
+ end
@@ -0,0 +1,226 @@
1
+ module ActionWebService # :nodoc:
2
+ # Action Web Service supports the following base types in a signature:
3
+ #
4
+ # [<tt>:int</tt>] Represents an integer value, will be cast to an integer using <tt>Integer(value)</tt>
5
+ # [<tt>:string</tt>] Represents a string value, will be cast to an string using the <tt>to_s</tt> method on an object
6
+ # [<tt>:base64</tt>] Represents a Base 64 value, will contain the binary bytes of a Base 64 value sent by the caller
7
+ # [<tt>:bool</tt>] Represents a boolean value, whatever is passed will be cast to boolean (<tt>true</tt>, '1', 'true', 'y', 'yes' are taken to represent true; <tt>false</tt>, '0', 'false', 'n', 'no' and <tt>nil</tt> represent false)
8
+ # [<tt>:float</tt>] Represents a floating point value, will be cast to a float using <tt>Float(value)</tt>
9
+ # [<tt>:time</tt>] Represents a timestamp, will be cast to a <tt>Time</tt> object
10
+ # [<tt>:datetime</tt>] Represents a timestamp, will be cast to a <tt>DateTime</tt> object
11
+ # [<tt>:date</tt>] Represents a date, will be cast to a <tt>Date</tt> object
12
+ #
13
+ # For structured types, you'll need to pass in the Class objects of
14
+ # ActionWebService::Struct and ActiveRecord::Base derivatives.
15
+ module SignatureTypes
16
+ def canonical_signature(signature) # :nodoc:
17
+ return nil if signature.nil?
18
+ unless signature.is_a?(Array)
19
+ raise(ActionWebServiceError, "Expected signature to be an Array")
20
+ end
21
+ i = -1
22
+ signature.map{ |spec| canonical_signature_entry(spec, i += 1) }
23
+ end
24
+
25
+ def canonical_signature_entry(spec, i) # :nodoc:
26
+ orig_spec = spec
27
+ name = "param#{i}"
28
+ if spec.is_a?(Hash)
29
+ name, spec = spec.keys.first, spec.values.first
30
+ end
31
+ type = spec
32
+ if spec.is_a?(Array)
33
+ ArrayType.new(orig_spec, canonical_signature_entry(spec[0], 0), name)
34
+ else
35
+ type = canonical_type(type)
36
+ if type.is_a?(Symbol)
37
+ BaseType.new(orig_spec, type, name)
38
+ else
39
+ StructuredType.new(orig_spec, type, name)
40
+ end
41
+ end
42
+ end
43
+
44
+ def canonical_type(type) # :nodoc:
45
+ type_name = symbol_name(type) || class_to_type_name(type)
46
+ type = type_name || type
47
+ return canonical_type_name(type) if type.is_a?(Symbol)
48
+ type
49
+ end
50
+
51
+ def canonical_type_name(name) # :nodoc:
52
+ name = name.to_sym
53
+ case name
54
+ when :int, :integer, :fixnum, :bignum
55
+ :int
56
+ when :string, :text
57
+ :string
58
+ when :base64, :binary
59
+ :base64
60
+ when :bool, :boolean
61
+ :bool
62
+ when :float, :double
63
+ :float
64
+ when :decimal
65
+ :decimal
66
+ when :time, :timestamp
67
+ :time
68
+ when :datetime
69
+ :datetime
70
+ when :date
71
+ :date
72
+ else
73
+ raise(TypeError, "#{name} is not a valid base type")
74
+ end
75
+ end
76
+
77
+ def canonical_type_class(type) # :nodoc:
78
+ type = canonical_type(type)
79
+ type.is_a?(Symbol) ? type_name_to_class(type) : type
80
+ end
81
+
82
+ def symbol_name(name) # :nodoc:
83
+ return name.to_sym if name.is_a?(Symbol) || name.is_a?(String)
84
+ nil
85
+ end
86
+
87
+ def class_to_type_name(klass) # :nodoc:
88
+ klass = klass.class unless klass.is_a?(Class)
89
+ if derived_from?(Integer, klass) || derived_from?(Fixnum, klass) || derived_from?(Bignum, klass)
90
+ :int
91
+ elsif klass == String
92
+ :string
93
+ elsif klass == Base64
94
+ :base64
95
+ elsif klass == TrueClass || klass == FalseClass
96
+ :bool
97
+ elsif derived_from?(Float, klass) || derived_from?(Precision, klass) || derived_from?(Numeric, klass)
98
+ :float
99
+ elsif klass == Time
100
+ :time
101
+ elsif klass == DateTime
102
+ :datetime
103
+ elsif klass == Date
104
+ :date
105
+ else
106
+ nil
107
+ end
108
+ end
109
+
110
+ def type_name_to_class(name) # :nodoc:
111
+ case canonical_type_name(name)
112
+ when :int
113
+ Integer
114
+ when :string
115
+ String
116
+ when :base64
117
+ Base64
118
+ when :bool
119
+ TrueClass
120
+ when :float
121
+ Float
122
+ when :decimal
123
+ BigDecimal
124
+ when :time
125
+ Time
126
+ when :date
127
+ Date
128
+ when :datetime
129
+ DateTime
130
+ else
131
+ nil
132
+ end
133
+ end
134
+
135
+ def derived_from?(ancestor, child) # :nodoc:
136
+ child.ancestors.include?(ancestor)
137
+ end
138
+
139
+ module_function :type_name_to_class
140
+ module_function :class_to_type_name
141
+ module_function :symbol_name
142
+ module_function :canonical_type_class
143
+ module_function :canonical_type_name
144
+ module_function :canonical_type
145
+ module_function :canonical_signature_entry
146
+ module_function :canonical_signature
147
+ module_function :derived_from?
148
+ end
149
+
150
+ class BaseType # :nodoc:
151
+ include SignatureTypes
152
+
153
+ attr :spec
154
+ attr :type
155
+ attr :type_class
156
+ attr :name
157
+
158
+ def initialize(spec, type, name)
159
+ @spec = spec
160
+ @type = canonical_type(type)
161
+ @type_class = canonical_type_class(@type)
162
+ @name = name
163
+ end
164
+
165
+ def custom?
166
+ false
167
+ end
168
+
169
+ def array?
170
+ false
171
+ end
172
+
173
+ def structured?
174
+ false
175
+ end
176
+
177
+ def human_name(show_name=true)
178
+ type_type = array? ? element_type.type.to_s : self.type.to_s
179
+ str = array? ? (type_type + '[]') : type_type
180
+ show_name ? (str + " " + name.to_s) : str
181
+ end
182
+ end
183
+
184
+ class ArrayType < BaseType # :nodoc:
185
+ attr :element_type
186
+
187
+ def initialize(spec, element_type, name)
188
+ super(spec, Array, name)
189
+ @element_type = element_type
190
+ end
191
+
192
+ def custom?
193
+ true
194
+ end
195
+
196
+ def array?
197
+ true
198
+ end
199
+ end
200
+
201
+ class StructuredType < BaseType # :nodoc:
202
+ def each_member
203
+ if @type_class.respond_to?(:members)
204
+ @type_class.members.each do |name, type|
205
+ yield name, type
206
+ end
207
+ elsif @type_class.respond_to?(:columns)
208
+ i = -1
209
+ @type_class.columns.each do |column|
210
+ yield column.name, canonical_signature_entry(column.type, i += 1)
211
+ end
212
+ end
213
+ end
214
+
215
+ def custom?
216
+ true
217
+ end
218
+
219
+ def structured?
220
+ true
221
+ end
222
+ end
223
+
224
+ class Base64 < String # :nodoc:
225
+ end
226
+ end
@@ -0,0 +1,65 @@
1
+ <html>
2
+ <head>
3
+ <title><%= @scaffold_class.wsdl_service_name %> Web Service</title>
4
+ <style>
5
+ body { background-color: #fff; color: #333; }
6
+
7
+ body, p, ol, ul, td {
8
+ font-family: verdana, arial, helvetica, sans-serif;
9
+ font-size: 13px;
10
+ line-height: 18px;
11
+ }
12
+
13
+ pre {
14
+ background-color: #eee;
15
+ padding: 10px;
16
+ font-size: 11px;
17
+ }
18
+
19
+ a { color: #000; }
20
+ a:visited { color: #666; }
21
+ a:hover { color: #fff; background-color:#000; }
22
+
23
+ .fieldWithErrors {
24
+ padding: 2px;
25
+ background-color: red;
26
+ display: table;
27
+ }
28
+
29
+ #errorExplanation {
30
+ width: 400px;
31
+ border: 2px solid red;
32
+ padding: 7px;
33
+ padding-bottom: 12px;
34
+ margin-bottom: 20px;
35
+ background-color: #f0f0f0;
36
+ }
37
+
38
+ #errorExplanation h2 {
39
+ text-align: left;
40
+ font-weight: bold;
41
+ padding: 5px 5px 5px 15px;
42
+ font-size: 12px;
43
+ margin: -7px;
44
+ background-color: #c00;
45
+ color: #fff;
46
+ }
47
+
48
+ #errorExplanation p {
49
+ color: #333;
50
+ margin-bottom: 0;
51
+ padding: 5px;
52
+ }
53
+
54
+ #errorExplanation ul li {
55
+ font-size: 12px;
56
+ list-style: square;
57
+ }
58
+ </style>
59
+ </head>
60
+ <body>
61
+
62
+ <%= @content_for_layout %>
63
+
64
+ </body>
65
+ </html>
@@ -0,0 +1,6 @@
1
+ <% @scaffold_container.services.each do |service| %>
2
+
3
+ <h4>API Methods for <%= service %></h4>
4
+ <%= service_method_list(service) %>
5
+
6
+ <% end %>
@@ -0,0 +1,29 @@
1
+ <h4>Method Invocation Details for <em><%= @scaffold_service %>#<%= @scaffold_method.public_name %></em></h4>
2
+
3
+ <% form_tag(:action => @scaffold_action_name + '_submit') do -%>
4
+ <%= hidden_field_tag "service", @scaffold_service.name %>
5
+ <%= hidden_field_tag "method", @scaffold_method.public_name %>
6
+
7
+ <p>
8
+ <label for="protocol">Protocol:</label><br />
9
+ <%= select_tag 'protocol', options_for_select([['SOAP', 'soap'], ['XML-RPC', 'xmlrpc']], params['protocol']) %>
10
+ </p>
11
+
12
+ <% if @scaffold_method.expects %>
13
+
14
+ <strong>Method Parameters:</strong><br />
15
+ <% @scaffold_method.expects.each_with_index do |type, i| %>
16
+ <p>
17
+ <label for="method_params[<%= i %>]"><%= method_parameter_label(type.name, type) %> </label><br />
18
+ <%= method_parameter_input_fields(@scaffold_method, type, "method_params", i) %>
19
+ </p>
20
+ <% end %>
21
+
22
+ <% end %>
23
+
24
+ <%= submit_tag "Invoke" %>
25
+ <% end -%>
26
+
27
+ <p>
28
+ <%= link_to "Back", :action => @scaffold_action_name %>
29
+ </p>
@@ -0,0 +1,30 @@
1
+ <h4>Method Invocation Result for <em><%= @scaffold_service %>#<%= @scaffold_method.public_name %></em></h4>
2
+
3
+ <p>
4
+ Invocation took <tt><%= '%f' % @method_elapsed %></tt> seconds
5
+ </p>
6
+
7
+ <p>
8
+ <strong>Return Value:</strong><br />
9
+ <pre>
10
+ <%= h @method_return_value.inspect %>
11
+ </pre>
12
+ </p>
13
+
14
+ <p>
15
+ <strong>Request XML:</strong><br />
16
+ <pre>
17
+ <%= h @method_request_xml %>
18
+ </pre>
19
+ </p>
20
+
21
+ <p>
22
+ <strong>Response XML:</strong><br />
23
+ <pre>
24
+ <%= h @method_response_xml %>
25
+ </pre>
26
+ </p>
27
+
28
+ <p>
29
+ <%= link_to "Back", :action => @scaffold_action_name + '_method_params', :method => @scaffold_method.public_name, :service => @scaffold_service.name %>
30
+ </p>