aws-sdk 1.4.1 → 1.5.0

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 (193) hide show
  1. data/.yardopts +0 -1
  2. data/lib/aws/api_config/AutoScaling-2011-01-01.yml +772 -544
  3. data/lib/aws/api_config/CloudFormation-2010-05-15.yml +284 -185
  4. data/lib/aws/api_config/DynamoDB-2011-12-05.yml +458 -738
  5. data/lib/aws/api_config/EC2-2011-12-15.yml +3502 -2653
  6. data/lib/aws/api_config/ELB-2011-08-15.yml +484 -352
  7. data/lib/aws/api_config/IAM-2010-05-08.yml +899 -711
  8. data/lib/aws/api_config/SNS-2010-03-31.yml +235 -167
  9. data/lib/aws/api_config/SQS-2011-10-01.yml +290 -251
  10. data/lib/aws/api_config/STS-2011-06-15.yml +35 -41
  11. data/lib/aws/api_config/SimpleDB-2009-04-15.yml +290 -263
  12. data/lib/aws/api_config/SimpleEmailService-2010-12-01.yml +144 -130
  13. data/lib/aws/api_config/SimpleWorkflow-2012-01-25.yml +697 -1139
  14. data/lib/aws/auto_scaling/activity_collection.rb +1 -1
  15. data/lib/aws/auto_scaling/client.rb +724 -9
  16. data/lib/aws/auto_scaling/errors.rb +1 -5
  17. data/lib/aws/auto_scaling/group.rb +1 -1
  18. data/lib/aws/auto_scaling/group_collection.rb +1 -1
  19. data/lib/aws/auto_scaling/instance_collection.rb +1 -1
  20. data/lib/aws/auto_scaling/launch_configuration.rb +1 -1
  21. data/lib/aws/auto_scaling/launch_configuration_collection.rb +1 -1
  22. data/lib/aws/auto_scaling/notification_configuration_collection.rb +1 -1
  23. data/lib/aws/auto_scaling/request.rb +1 -2
  24. data/lib/aws/auto_scaling/scaling_policy_collection.rb +1 -1
  25. data/lib/aws/auto_scaling/scheduled_action_collection.rb +3 -3
  26. data/lib/aws/auto_scaling/tag_collection.rb +1 -1
  27. data/lib/aws/cloud_formation.rb +1 -18
  28. data/lib/aws/cloud_formation/client.rb +314 -8
  29. data/lib/aws/cloud_formation/errors.rb +1 -5
  30. data/lib/aws/cloud_formation/request.rb +1 -2
  31. data/lib/aws/cloud_formation/stack.rb +4 -3
  32. data/lib/aws/cloud_formation/stack_collection.rb +2 -2
  33. data/lib/aws/cloud_formation/stack_resource_collection.rb +1 -1
  34. data/lib/aws/cloud_formation/stack_resource_summary_collection.rb +2 -2
  35. data/lib/aws/cloud_formation/stack_summary_collection.rb +1 -1
  36. data/lib/aws/core.rb +29 -14
  37. data/lib/aws/core/async_handle.rb +11 -12
  38. data/lib/aws/core/client.rb +112 -102
  39. data/lib/aws/core/client/query_json.rb +110 -0
  40. data/lib/aws/core/client/query_xml.rb +122 -0
  41. data/lib/aws/core/data.rb +242 -0
  42. data/lib/aws/core/http/request.rb +7 -4
  43. data/lib/aws/core/lazy_error_classes.rb +60 -38
  44. data/lib/aws/core/option_grammar.rb +1 -0
  45. data/lib/aws/core/policy.rb +2 -1
  46. data/lib/aws/core/resource.rb +38 -33
  47. data/lib/aws/core/response.rb +109 -44
  48. data/lib/aws/core/signature/version_2.rb +42 -0
  49. data/lib/aws/core/signature/version_3.rb +73 -0
  50. data/lib/aws/core/signature/version_3_http.rb +72 -0
  51. data/lib/aws/core/signature/version_4.rb +138 -0
  52. data/lib/aws/core/uri_escape.rb +6 -9
  53. data/lib/aws/core/xml/frame.rb +242 -0
  54. data/lib/aws/core/xml/frame_stack.rb +85 -0
  55. data/lib/aws/core/xml/grammar.rb +299 -0
  56. data/lib/aws/core/xml/parser.rb +70 -0
  57. data/lib/aws/core/xml/root_frame.rb +65 -0
  58. data/lib/aws/core/{configured_xml_grammars.rb → xml/sax_handlers/libxml.rb} +22 -20
  59. data/lib/aws/core/xml/sax_handlers/nokogiri.rb +55 -0
  60. data/lib/aws/core/{authorize_with_session_token.rb → xml/sax_handlers/ox.rb} +19 -7
  61. data/lib/aws/core/{configured_option_grammars.rb → xml/sax_handlers/rexml.rb} +22 -23
  62. data/lib/aws/core/xml/stub.rb +123 -0
  63. data/lib/aws/dynamo_db/batch_get.rb +1 -1
  64. data/lib/aws/dynamo_db/client.rb +796 -14
  65. data/lib/aws/dynamo_db/errors.rb +1 -38
  66. data/lib/aws/dynamo_db/item_collection.rb +29 -28
  67. data/lib/aws/dynamo_db/request.rb +3 -53
  68. data/lib/aws/dynamo_db/table.rb +6 -2
  69. data/lib/aws/ec2/attachment.rb +1 -1
  70. data/lib/aws/ec2/client.rb +3954 -9
  71. data/lib/aws/ec2/dhcp_options.rb +3 -3
  72. data/lib/aws/ec2/errors.rb +10 -4
  73. data/lib/aws/ec2/instance.rb +7 -6
  74. data/lib/aws/ec2/instance_collection.rb +2 -2
  75. data/lib/aws/ec2/key_pair_collection.rb +3 -3
  76. data/lib/aws/ec2/network_acl.rb +4 -2
  77. data/lib/aws/ec2/network_acl/entry.rb +10 -10
  78. data/lib/aws/ec2/network_interface.rb +2 -3
  79. data/lib/aws/ec2/network_interface/attachment.rb +8 -8
  80. data/lib/aws/ec2/permission_collection.rb +3 -3
  81. data/lib/aws/ec2/request.rb +1 -3
  82. data/lib/aws/ec2/resource_tag_collection.rb +4 -8
  83. data/lib/aws/ec2/route_table.rb +3 -2
  84. data/lib/aws/ec2/route_table/route.rb +7 -7
  85. data/lib/aws/ec2/security_group.rb +2 -2
  86. data/lib/aws/ec2/security_group/egress_ip_permission_collection.rb +16 -5
  87. data/lib/aws/ec2/security_group/ingress_ip_permission_collection.rb +4 -3
  88. data/lib/aws/ec2/security_group/ip_permission.rb +1 -2
  89. data/lib/aws/ec2/snapshot_collection.rb +6 -3
  90. data/lib/aws/ec2/subnet.rb +1 -1
  91. data/lib/aws/ec2/volume.rb +1 -3
  92. data/lib/aws/ec2/volume_collection.rb +2 -0
  93. data/lib/aws/elb/availability_zone_collection.rb +2 -2
  94. data/lib/aws/elb/backend_server_policy_collection.rb +1 -1
  95. data/lib/aws/elb/client.rb +513 -9
  96. data/lib/aws/elb/errors.rb +2 -6
  97. data/lib/aws/elb/instance_collection.rb +2 -2
  98. data/lib/aws/elb/request.rb +1 -1
  99. data/lib/aws/errors.rb +61 -74
  100. data/lib/aws/iam.rb +2 -3
  101. data/lib/aws/iam/client.rb +1178 -10
  102. data/lib/aws/iam/collection.rb +2 -1
  103. data/lib/aws/iam/errors.rb +1 -6
  104. data/lib/aws/iam/group.rb +8 -9
  105. data/lib/aws/iam/request.rb +1 -1
  106. data/lib/aws/iam/server_certificate_collection.rb +8 -5
  107. data/lib/aws/iam/signing_certificate.rb +1 -1
  108. data/lib/aws/iam/user.rb +2 -2
  109. data/lib/aws/iam/user_policy.rb +3 -2
  110. data/lib/aws/rails.rb +1 -2
  111. data/lib/aws/record.rb +3 -3
  112. data/lib/aws/record/abstract_base.rb +0 -3
  113. data/lib/aws/record/attributes.rb +7 -7
  114. data/lib/aws/record/model.rb +19 -19
  115. data/lib/aws/record/model/finder_methods.rb +7 -7
  116. data/lib/aws/s3/bucket.rb +7 -2
  117. data/lib/aws/s3/client.rb +391 -398
  118. data/lib/aws/s3/client/xml.rb +44 -71
  119. data/lib/aws/s3/data_options.rb +3 -2
  120. data/lib/aws/s3/errors.rb +8 -11
  121. data/lib/aws/s3/multipart_upload_collection.rb +1 -3
  122. data/lib/aws/s3/object_collection.rb +2 -1
  123. data/lib/aws/s3/object_metadata.rb +2 -2
  124. data/lib/aws/s3/paginated_collection.rb +2 -2
  125. data/lib/aws/s3/prefix_and_delimiter_collection.rb +1 -1
  126. data/lib/aws/s3/presigned_post.rb +18 -17
  127. data/lib/aws/s3/request.rb +4 -3
  128. data/lib/aws/s3/s3_object.rb +8 -10
  129. data/lib/aws/simple_db/attribute.rb +2 -2
  130. data/lib/aws/simple_db/attribute_collection.rb +14 -4
  131. data/lib/aws/simple_db/client.rb +313 -14
  132. data/lib/aws/simple_db/domain.rb +1 -1
  133. data/lib/aws/simple_db/domain_collection.rb +4 -4
  134. data/lib/aws/simple_db/domain_metadata.rb +1 -1
  135. data/lib/aws/simple_db/errors.rb +14 -2
  136. data/lib/aws/simple_db/expect_condition_option.rb +1 -1
  137. data/lib/aws/simple_db/item.rb +1 -1
  138. data/lib/aws/simple_db/item_collection.rb +9 -9
  139. data/lib/aws/simple_db/item_data.rb +9 -6
  140. data/lib/aws/simple_db/request.rb +1 -1
  141. data/lib/aws/simple_email_service.rb +8 -7
  142. data/lib/aws/simple_email_service/client.rb +174 -9
  143. data/lib/aws/simple_email_service/email_address_collection.rb +0 -1
  144. data/lib/aws/simple_email_service/errors.rb +1 -5
  145. data/lib/aws/simple_email_service/quotas.rb +8 -6
  146. data/lib/aws/simple_email_service/request.rb +7 -1
  147. data/lib/aws/simple_workflow/client.rb +1383 -6
  148. data/lib/aws/simple_workflow/decision_task.rb +1 -3
  149. data/lib/aws/simple_workflow/errors.rb +1 -38
  150. data/lib/aws/simple_workflow/history_event_collection.rb +2 -2
  151. data/lib/aws/simple_workflow/request.rb +5 -49
  152. data/lib/aws/simple_workflow/type.rb +1 -1
  153. data/lib/aws/simple_workflow/type_collection.rb +4 -3
  154. data/lib/aws/simple_workflow/workflow_execution_collection.rb +2 -2
  155. data/lib/aws/sns/client.rb +345 -9
  156. data/lib/aws/sns/errors.rb +1 -5
  157. data/lib/aws/sns/request.rb +1 -2
  158. data/lib/aws/sns/subscription_collection.rb +2 -2
  159. data/lib/aws/sns/topic.rb +15 -14
  160. data/lib/aws/sns/topic_collection.rb +1 -1
  161. data/lib/aws/sqs/client.rb +334 -9
  162. data/lib/aws/sqs/errors.rb +1 -6
  163. data/lib/aws/sqs/queue.rb +20 -21
  164. data/lib/aws/sqs/queue_collection.rb +3 -3
  165. data/lib/aws/sqs/request.rb +2 -2
  166. data/lib/aws/sts.rb +8 -10
  167. data/lib/aws/sts/client.rb +67 -10
  168. data/lib/aws/sts/errors.rb +1 -5
  169. data/lib/aws/sts/request.rb +1 -1
  170. data/lib/user.rb +49 -0
  171. metadata +21 -28
  172. data/lib/aws/auto_scaling/client/xml.rb +0 -32
  173. data/lib/aws/cloud_formation/client/xml.rb +0 -32
  174. data/lib/aws/core/api_config.rb +0 -44
  175. data/lib/aws/core/authorize_v2.rb +0 -39
  176. data/lib/aws/core/authorize_v3.rb +0 -38
  177. data/lib/aws/core/authorize_v4.rb +0 -149
  178. data/lib/aws/core/configured_client_methods.rb +0 -76
  179. data/lib/aws/core/configured_grammars.rb +0 -63
  180. data/lib/aws/core/configured_json_client_methods.rb +0 -74
  181. data/lib/aws/core/ignore_result_element.rb +0 -34
  182. data/lib/aws/core/json_client.rb +0 -41
  183. data/lib/aws/core/xml_grammar.rb +0 -957
  184. data/lib/aws/ec2/client/xml.rb +0 -175
  185. data/lib/aws/elb/client/xml.rb +0 -33
  186. data/lib/aws/elb/listener_spec.rb +0 -14
  187. data/lib/aws/iam/client/xml.rb +0 -34
  188. data/lib/aws/simple_db/client/options.rb +0 -32
  189. data/lib/aws/simple_db/client/xml.rb +0 -63
  190. data/lib/aws/simple_email_service/client/xml.rb +0 -34
  191. data/lib/aws/sns/client/xml.rb +0 -34
  192. data/lib/aws/sqs/client/xml.rb +0 -33
  193. data/lib/aws/sts/client/xml.rb +0 -34
@@ -1,74 +0,0 @@
1
- # Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License"). You
4
- # may not use this file except in compliance with the License. A copy of
5
- # the License is located at
6
- #
7
- # http://aws.amazon.com/apache2.0/
8
- #
9
- # or in the "license" file accompanying this file. This file is
10
- # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
- # ANY KIND, either express or implied. See the License for the specific
12
- # language governing permissions and limitations under the License.
13
-
14
- require 'json'
15
-
16
- module AWS
17
- module Core
18
-
19
- # @private
20
- module ConfiguredJsonClientMethods
21
-
22
- # @private
23
- module ClassMethods
24
-
25
- include ApiConfig
26
-
27
- def configure_client
28
-
29
- super
30
-
31
- unless self::Options.include?(ConfiguredOptionGrammars)
32
- self::Options.module_eval do
33
- include(ConfiguredOptionGrammars)
34
- define_configured_grammars
35
- end
36
- end
37
-
38
- api_config[:operations].each do |name, customizations|
39
- option_grammar = self::Options.operation_grammar(name)
40
- target_prefix = self::TARGET_PREFIX
41
- add_client_request_method(Inflection.ruby_name(name).to_sym) do
42
-
43
- configure_request do |request, options|
44
- request.headers["x-amz-target"] = target_prefix + name
45
- request.body = option_grammar.to_json(options)
46
- end
47
-
48
- process_response do |response|
49
- response_body = response.http_response.body
50
- response_body = "{}" if response_body == ""
51
- data = JSON.load(response_body)
52
- MetaUtils.extend_method(response, :data) { data }
53
- end
54
-
55
- simulate_response do |response|
56
- data = {}
57
- MetaUtils.extend_method(response, :data) { data }
58
- end
59
-
60
- end
61
- end
62
-
63
- end
64
-
65
- end
66
-
67
- def self.included(mod)
68
- mod.extend(ClassMethods)
69
- end
70
-
71
- end
72
-
73
- end
74
- end
@@ -1,34 +0,0 @@
1
- # Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License"). You
4
- # may not use this file except in compliance with the License. A copy of
5
- # the License is located at
6
- #
7
- # http://aws.amazon.com/apache2.0/
8
- #
9
- # or in the "license" file accompanying this file. This file is
10
- # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
- # ANY KIND, either express or implied. See the License for the specific
12
- # language governing permissions and limitations under the License.
13
-
14
- module AWS
15
- module Core
16
-
17
- # @private
18
- #
19
- # Mixin for XML grammar modules to ignore the outer
20
- # "OperationNameResult" element that wraps the response fields in
21
- # Coral-like service responses.
22
- module IgnoreResultElement
23
-
24
- # @private
25
- #
26
- # Invoked by
27
- # ConfiguredXmlGrammars::ClassMethods#define_configured_grammars
28
- def process_customizations name, customizations
29
- [{ "#{name}Result" => [:ignore, *customizations] }]
30
- end
31
-
32
- end
33
- end
34
- end
@@ -1,41 +0,0 @@
1
- # Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License"). You
4
- # may not use this file except in compliance with the License. A copy of
5
- # the License is located at
6
- #
7
- # http://aws.amazon.com/apache2.0/
8
- #
9
- # or in the "license" file accompanying this file. This file is
10
- # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
- # ANY KIND, either express or implied. See the License for the specific
12
- # language governing permissions and limitations under the License.
13
-
14
- module AWS
15
- module Core
16
-
17
- class JsonClient < Client
18
-
19
- include Core::ConfiguredJsonClientMethods
20
-
21
- protected
22
- def new_request
23
- req = super
24
- req.headers["content-type"] = "application/x-amz-json-1.0"
25
- req
26
- end
27
-
28
- protected
29
- def extract_error_code response
30
- if response.http_response.status >= 300 and
31
- body = response.http_response.body and
32
- json = (JSON.load(body) rescue nil) and
33
- type = json["__type"] and
34
- type =~ /\#(.*)$/
35
- $1
36
- end
37
- end
38
-
39
- end
40
- end
41
- end
@@ -1,957 +0,0 @@
1
- # Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License"). You
4
- # may not use this file except in compliance with the License. A copy of
5
- # the License is located at
6
- #
7
- # http://aws.amazon.com/apache2.0/
8
- #
9
- # or in the "license" file accompanying this file. This file is
10
- # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
- # ANY KIND, either express or implied. See the License for the specific
12
- # language governing permissions and limitations under the License.
13
-
14
- require 'rexml/document'
15
- require 'rexml/streamlistener'
16
- require 'base64'
17
- require 'time'
18
-
19
- begin
20
- require 'nokogiri'
21
- rescue LoadError => e
22
- end
23
-
24
- module AWS
25
- module Core
26
-
27
- # @private
28
- class XmlGrammar
29
-
30
- # @private
31
- class Context
32
-
33
- def initialize
34
- @data = {}
35
- end
36
-
37
- def id
38
- @data[:id]
39
- end
40
-
41
- def method_missing(m, *args)
42
- key = m.to_sym
43
-
44
- return super unless @data.key?(key)
45
- @data[key]
46
- end
47
-
48
- def respond_to?(m)
49
- @data.key?(m.to_sym) or super
50
- end
51
-
52
- def to_hash
53
- @data.inject({}) do |hash,(key,value)|
54
-
55
- # strip question marks from hash keys
56
- if matches = key.to_s.match(/(.+)\?$/)
57
- key = matches[1].to_sym
58
- end
59
-
60
- # recursively convert hashes
61
- if value.is_a?(Array)
62
- value = value.map{|v| v.is_a?(Context) ? v.to_hash : v }
63
- elsif value.is_a?(Context)
64
- value = value.to_hash
65
- end
66
-
67
- hash.merge(key => value)
68
-
69
- end
70
- end
71
-
72
- def inspect
73
- methods = @data.keys
74
- "<Object #{methods.reject{|m| m =~ /=$/ }.join(', ')}>"
75
- end
76
-
77
- # this gets called a LOT during response parsing, and having
78
- # it be a public method is the fastest way to call it.
79
- # Strictly speaking it should be private.
80
- # @private
81
- def __set_data__(getter, value)
82
- @data[getter.to_sym] = value
83
- end
84
-
85
- end
86
-
87
- # @private
88
- class CustomizationContext < Hash
89
-
90
- def initialize(element_name = nil)
91
- original_store(:children, {})
92
-
93
- if element_name
94
- original_store(:name, element_name)
95
- recompute_accessors
96
- end
97
- end
98
-
99
- alias_method :original_store, :[]=
100
-
101
- def []=(name, value)
102
- super
103
- if respond_to?("changed_#{name}")
104
- send("changed_#{name}", value)
105
- end
106
- end
107
-
108
- def changed_boolean(value)
109
- recompute_accessors
110
- end
111
-
112
- def changed_renamed(value)
113
- recompute_accessors
114
- end
115
-
116
- def deep_copy(hash = self)
117
- fields = hash.inject({}) do |copy,(key,value)|
118
- if value.is_a?(CustomizationContext)
119
- value = value.deep_copy
120
- elsif value.is_a?(Hash)
121
- value = deep_copy(value)
122
- end
123
- copy[key] = value
124
- copy
125
- end
126
- hash.merge(fields)
127
- end
128
-
129
- private
130
- def recompute_accessors
131
- ruby_name = Inflection.ruby_name((self[:renamed] ||
132
- self[:name]).to_s)
133
- self[:getter] =
134
- if self[:boolean] && ruby_name != "value"
135
- "#{ruby_name}?"
136
- else
137
- ruby_name
138
- end
139
- self[:setter] = "#{ruby_name}="
140
- end
141
-
142
- end
143
-
144
- # @private
145
- class << self
146
-
147
- def parse xml, options = {}
148
-
149
- context = options[:context] || Context.new
150
-
151
- if defined? Nokogiri
152
- parser = Parser.new(context, customizations)
153
- parser.extend(NokogiriAdapter)
154
- xml = "<foo/>" if xml.empty?
155
- Nokogiri::XML::SAX::Parser.new(parser).parse(xml.strip)
156
- else
157
- parser = Parser.new(context, customizations)
158
- parser.extend(REXMLSaxParserAdapter)
159
- REXML::Parsers::StreamParser.new(REXML::Source.new(xml), parser).parse
160
- end
161
-
162
- context
163
-
164
- end
165
-
166
- def simulate context = nil
167
- StubResponse.new(customizations, context)
168
- end
169
-
170
- def customize config = nil, &block
171
- grammar = Class.new(self)
172
- grammar.customizations = customizations.deep_copy
173
- grammar.config_eval(config) if config
174
- grammar.module_eval(&block) if block_given?
175
- grammar
176
- end
177
-
178
- def element element_name, &block
179
- eval_customization_context(element_name, &block)
180
- end
181
-
182
- def add_method method_name, &block
183
- format_value do |value|
184
- MetaUtils.extend_method(value = super(value), method_name, &block)
185
- value
186
- end
187
- # different strategey, slightly different behavior
188
- # element(method_name.to_s) do
189
- # format_value(&block)
190
- # force
191
- # end
192
- end
193
-
194
- def ignore
195
- @current[:ignored] = true
196
- end
197
-
198
- def rename new_name
199
- @current[:renamed] = new_name.to_s
200
- end
201
-
202
- def force
203
- @current[:forced] = true
204
- end
205
-
206
- def collect_values
207
- @current[:collected] = true
208
- @current[:initial_collection] = lambda { [] }
209
- @current[:add_to_collection] =
210
- lambda { |ary, val| ary << val }
211
- force
212
- end
213
-
214
- def index(name, &block)
215
- (@customizations[:index_names] ||= []) << name
216
- @current[:indexed] = [name, block]
217
- end
218
-
219
- def boolean_value
220
- @current[:boolean] = true
221
- format_value {|value| super(value) == 'true' }
222
- end
223
- # required by the hash configuration method
224
- alias_method :boolean, :boolean_value
225
-
226
- TRANSLATE_DIGITS = ['0123456789'.freeze, ('X'*10).freeze]
227
- EASY_FORMAT = "XXXX-XX-XXTXX:XX:XX.XXXZ".freeze
228
- DATE_PUNCTUATION = ['-:.TZ'.freeze, (' '*5).freeze]
229
-
230
- def datetime_value
231
- datetime_like_value(DateTime, :civil)
232
- end
233
-
234
- def time_value
235
- datetime_like_value(Time, :utc)
236
- end
237
- alias_method :timestamp, :time_value
238
-
239
- def datetime_like_value(klass, parts_constructor)
240
- format_value do |value|
241
- value = super(value)
242
- if value and value.tr(*TRANSLATE_DIGITS) == EASY_FORMAT
243
-
244
- # it's way faster to parse this specific format manually
245
- # vs. DateTime#parse, and this happens to be the format
246
- # that AWS uses almost (??) everywhere.
247
-
248
- parts = value.tr(*DATE_PUNCTUATION).
249
- chop.split.map { |elem| elem.to_i }
250
- klass.send(parts_constructor, *parts)
251
- elsif value
252
- # fallback in case we have to handle another date format
253
- klass.parse(value)
254
- else
255
- nil
256
- end
257
- end
258
- end
259
-
260
- def integer_value
261
- format_value do |value|
262
- value = super(value)
263
- value.nil? ? nil : value.to_i
264
- end
265
- end
266
- # required by the hash configuration method
267
- alias_method :integer, :integer_value
268
- alias_method :long, :integer_value
269
-
270
- def float_value
271
- format_value do |value|
272
- value = super(value)
273
- value.nil? ? nil : value.to_f
274
- end
275
- end
276
-
277
- alias_method :float, :float_value
278
-
279
- def symbol_value
280
- format_value do |value|
281
- value = super(value)
282
- ['', nil].include?(value) ? nil : Inflection.ruby_name(value).to_sym
283
- end
284
- end
285
-
286
- def blob_value
287
- format_value do |value|
288
- value = super(value)
289
- Base64.decode64(value) if value
290
- end
291
- end
292
- alias_method :blob, :blob_value
293
-
294
- def format_value &block
295
- @current[:value_formatter] ||= ValueFormatter.new
296
- @current[:value_formatter].extend_format_value(&block)
297
- end
298
-
299
- def list child_element_name = nil, &block
300
- if child_element_name
301
- ignore
302
- parent_element_name = @current_name
303
- element(child_element_name) do
304
- rename(parent_element_name)
305
- collect_values
306
- yield if block_given?
307
- end
308
- else
309
- collect_values
310
- end
311
- end
312
-
313
- def map_entry(key, value)
314
- collect_values
315
- element(key) { rename :key }
316
- element(value) { rename :value }
317
- @current[:initial_collection] = lambda { {} }
318
- @current[:add_to_collection] = lambda do |hash, entry|
319
- hash[entry.key] = entry.value
320
- end
321
- end
322
-
323
- def map entry_name, key, value
324
- parent_element_name = @current_name
325
- ignore
326
- element(entry_name) do
327
- rename(parent_element_name)
328
- map_entry(key, value)
329
- end
330
- end
331
-
332
- def wrapper method_name, options = {}, &blk
333
- if block_given?
334
- customizations =
335
- eval_customization_context(method_name,
336
- CustomizationContext.new(method_name),
337
- &blk)
338
- raise NotImplementedError.new("can't customize wrapped " +
339
- "elements within the wrapper") unless
340
- customizations[:children].empty?
341
- @current[:wrapper_frames] ||= {}
342
- @current[:wrapper_frames][method_name] = customizations
343
- end
344
-
345
- (options[:for] || []).each do |element_name|
346
- element element_name do
347
- @current[:wrapper] ||= []
348
- @current[:wrapper] << method_name
349
- end
350
- end
351
- end
352
-
353
- def construct_value &block
354
- @current[:construct_value] = block
355
- end
356
-
357
- def eql? other
358
- self.customizations == other.customizations
359
- end
360
-
361
- protected
362
- def initial_customizations(element_name = nil)
363
- CustomizationContext.new(element_name)
364
- end
365
-
366
- protected
367
- def eval_customization_context name, initial = nil, &block
368
- current_name = @current_name
369
- current = @current
370
- parent = @parent
371
- begin
372
- @current_name = name
373
- @parent = @current
374
- initial ||= customizations_for(name)
375
- @current = initial
376
- yield if block_given?
377
- ensure
378
- @current_name = current_name
379
- @current = current
380
- @parent = parent
381
- end
382
-
383
- # will be modified to include the customizations defined in
384
- # the block
385
- initial
386
- end
387
-
388
- protected
389
- def config_eval(config)
390
- config.each do |item|
391
- (type, identifier, args) = parse_config_item(item)
392
- case type
393
- when :method
394
- validate_config_method(identifier)
395
- validate_args(identifier, args)
396
- send(identifier, *args)
397
- when :element
398
- element(identifier) do
399
- config_eval(args)
400
- end
401
- end
402
- end
403
- end
404
-
405
- protected
406
- def validate_args(identifier, args)
407
- arity = method(identifier).arity
408
- if args.length > 0
409
- raise "#{identifier} does not accept an argument" if
410
- arity == 0
411
- else
412
- raise "#{identifier} requires an argument" unless
413
- arity == 0 || arity == -1
414
- end
415
- end
416
-
417
- protected
418
- def parse_config_item(item)
419
- case item
420
- when Symbol
421
- [:method, item, []]
422
- when Hash
423
- (method, arg) = item.to_a.first
424
- if method.kind_of?(Symbol)
425
- [:method, method, [arg].flatten]
426
- else
427
- [:element, method, arg]
428
- end
429
- end
430
- end
431
-
432
- protected
433
- def validate_config_method(method)
434
- allow_methods = %w(
435
- rename attribute_name boolean integer long float list force
436
- ignore collect_values symbol_value timestamp map_entry map
437
- blob
438
- )
439
- unless allow_methods.include?(method.to_s)
440
- raise "#{method} cannot be used in configuration"
441
- end
442
- end
443
-
444
- protected
445
- def customizations
446
- @customizations ||= CustomizationContext.new
447
- end
448
-
449
- protected
450
- def customizations_for element_name
451
- if @parent
452
- @parent[:children][element_name] ||=
453
- CustomizationContext.new(element_name)
454
- else
455
- customizations[:children][element_name] ||=
456
- CustomizationContext.new(element_name)
457
- end
458
- end
459
-
460
- protected
461
- def customizations= customizations
462
- @customizations = customizations
463
- @current = customizations
464
- end
465
-
466
- end
467
-
468
- # @private
469
- class ValueFormatter
470
-
471
- def extend_format_value &block
472
- MetaUtils.extend_method(self, :format_value, &block)
473
- end
474
-
475
- def format_value value
476
- value
477
- end
478
-
479
- end
480
-
481
- # @private
482
- class Parser
483
-
484
- def initialize context, customizations
485
- @context = context
486
- @customizations = customizations
487
- end
488
-
489
- def start_element element_name, attrs
490
-
491
- if @frame
492
- @frame = @frame.build_child_frame(element_name)
493
- else
494
- @frame = RootFrame.new(@context, @customizations)
495
- end
496
-
497
- # consume attributes the same way we consume nested xml elements
498
- attrs.each do |(attr_name, attr_value)|
499
- attr_frame = @frame.build_child_frame(attr_name)
500
- attr_frame.add_text(attr_value)
501
- @frame.consume_child_frame(attr_frame)
502
- end
503
-
504
- end
505
-
506
- def end_element name
507
- @frame.close
508
- if @frame.parent_frame
509
- child_frame = @frame
510
- parent_frame = @frame.parent_frame
511
- parent_frame.consume_child_frame(child_frame)
512
- end
513
- @frame = @frame.parent_frame
514
- end
515
-
516
- def characters chars
517
- @frame.add_text(chars) if @frame
518
- end
519
-
520
- end
521
-
522
- module REXMLSaxParserAdapter
523
-
524
- include REXML::StreamListener
525
-
526
- def tag_start(name, attrs)
527
- start_element(name, attrs)
528
- end
529
-
530
- def tag_end(name)
531
- end_element(name)
532
- end
533
-
534
- def text(chars)
535
- characters(chars)
536
- end
537
-
538
- end
539
-
540
- # @private
541
- module NokogiriAdapter
542
-
543
- def xmldecl(*args); end
544
- def start_document; end
545
- def end_document; end
546
- def start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = [])
547
- start_element(name, attrs.map { |att| [att.localname, att.value] })
548
- end
549
- def end_element_namespace(name, prefix = nil, uri = nil)
550
- end_element(name)
551
- end
552
- def error(*args); end
553
-
554
- end
555
-
556
- # @private
557
- class Frame
558
-
559
- attr_reader :parent_frame
560
-
561
- attr_reader :root_frame
562
-
563
- attr_reader :element_name
564
-
565
- attr_accessor :customizations
566
-
567
- def initialize element_name, options = {}
568
-
569
- @element_name = element_name
570
- @context = options[:context]
571
- @parent_frame = options[:parent_frame]
572
- @root_frame = options[:root_frame]
573
- @wrapper_frames = {}
574
-
575
- if @parent_frame
576
- @customizations = @parent_frame.customizations_for_child(element_name)
577
- else
578
- @customizations = options[:customizations]
579
- @root_frame ||= self
580
- end
581
-
582
- if @root_frame == self and
583
- indexes = @customizations[:index_names]
584
- indexes.each do |name|
585
- if context.kind_of?(Context)
586
- context.__set_data__(name, {})
587
- else
588
- add_mutators(name)
589
- context.send("#{name}=", {})
590
- end
591
- end
592
- end
593
-
594
- # we build and discard child frames here so we can know
595
- # which children should always add a method to this
596
- # frame's context (forced elements, like collected arrays)
597
- @customizations[:children].keys.each do |child_element_name|
598
- consume_initial_frame(build_child_frame(child_element_name))
599
- end
600
-
601
- if @customizations[:wrapper_frames]
602
- @customizations[:wrapper_frames].keys.each do |method_name|
603
- consume_initial_frame(wrapper_frame_for(method_name))
604
- end
605
- end
606
-
607
- end
608
-
609
- def build_child_frame(child_element_name)
610
- Frame.new(child_element_name,
611
- :parent_frame => self,
612
- :root_frame => root_frame)
613
- end
614
-
615
- def consume_child_frame child_frame
616
-
617
- return if child_frame.ignored?
618
-
619
- if child_frame.wrapped?
620
- child_frame.wrapper_methods.each do |method_name|
621
- consume_in_wrapper(method_name, child_frame)
622
- end
623
- else
624
- # forced child frames have already added mutators to this context
625
- add_mutators_for(child_frame) unless child_frame.forced?
626
-
627
- if child_frame.collected?
628
- child_frame.add_to_collection(context.send(child_frame.getter),
629
- child_frame.value)
630
- else
631
- invoke_setter(child_frame, child_frame.value)
632
- end
633
- end
634
-
635
- end
636
-
637
- def close
638
- if indexed = @customizations[:indexed]
639
- (name, block) = indexed
640
- key = block.call(context)
641
- [key].flatten.each do |k|
642
- index(name)[k] = context
643
- end
644
- end
645
- end
646
-
647
- def add_text text
648
- @text ||= ''
649
- @text << text
650
- end
651
-
652
- def value
653
- @customizations[:value_formatter] ?
654
- @customizations[:value_formatter].format_value(default_value) :
655
- default_value
656
- end
657
-
658
- def context
659
- @context ||= (self.ignored? ? parent_frame.context : construct_context)
660
- end
661
-
662
- def setter
663
- @customizations[:setter]
664
- end
665
-
666
- def getter
667
- @customizations[:getter]
668
- end
669
-
670
- def initial_collection
671
- @customizations[:initial_collection].call
672
- end
673
-
674
- def add_to_collection(collection, value)
675
- @customizations[:add_to_collection].call(collection, value)
676
- end
677
-
678
- def index(name)
679
- return root_frame.index(name) unless root_frame == self
680
- context.send(name)
681
- end
682
-
683
- protected
684
- def consume_initial_frame(child_frame)
685
- if child_frame.forced?
686
- add_mutators_for(child_frame)
687
- if child_frame.collected?
688
- invoke_setter(child_frame, child_frame.initial_collection)
689
- else
690
- # this allows nested forced elements to appear
691
- invoke_setter(child_frame, child_frame.value)
692
- end
693
- end
694
- end
695
-
696
- protected
697
- def construct_context
698
- if @customizations[:construct_value]
699
- instance_eval(&@customizations[:construct_value])
700
- else
701
- Context.new
702
- end
703
- end
704
-
705
- protected
706
- def consume_in_wrapper method_name, child_frame
707
- wrapper_frame = wrapper_frame_for(method_name)
708
- add_mutators(method_name)
709
-
710
- # the wrapper consumes the unwrapped child
711
- customizations = child_frame.customizations.merge(:wrapper => nil)
712
- child_frame = child_frame.dup
713
- child_frame.customizations = customizations
714
-
715
- wrapper_frame.consume_child_frame(child_frame)
716
- consume_child_frame(wrapper_frame)
717
- end
718
-
719
- protected
720
- def wrapper_frame_for(method_name)
721
- @wrapper_frames[method_name] ||=
722
- Frame.new(method_name.to_s,
723
- :customizations => wrapper_customizations(method_name))
724
- end
725
-
726
- protected
727
- def wrapper_customizations(method_name)
728
- customizations = CustomizationContext.new(method_name)
729
- customizations[:children] = @customizations[:children]
730
- if wrapper_frames = @customizations[:wrapper_frames] and
731
- additional = wrapper_frames[method_name]
732
- additional[:children] = @customizations[:children].merge(additional[:children]) if
733
- additional[:children]
734
- customizations.merge!(additional)
735
- end
736
- customizations
737
- end
738
-
739
- protected
740
- def invoke_setter(child_frame, value)
741
- if context.kind_of?(Context)
742
- context.__set_data__(child_frame.getter, value)
743
- else
744
- context.send(child_frame.setter, value)
745
- end
746
- end
747
-
748
- protected
749
- def add_mutators_for child_frame
750
- return if context.kind_of?(Context)
751
- add_mutators(child_frame.ruby_name,
752
- child_frame.setter,
753
- child_frame.getter)
754
- end
755
-
756
- protected
757
- def add_mutators(variable_name,
758
- setter = nil,
759
- getter = nil)
760
- return if context.kind_of?(Context)
761
- variable_name = variable_name.to_s.gsub(/\?$/, '')
762
- setter ||= "#{variable_name}="
763
- getter ||= variable_name
764
- return if context.respond_to?(getter) && context.respond_to?(setter)
765
- MetaUtils.extend_method(context, setter) do |val|
766
- instance_variable_set("@#{variable_name}", val)
767
- end
768
- MetaUtils.extend_method(context, getter) do
769
- instance_variable_get("@#{variable_name}")
770
- end
771
- end
772
-
773
- protected
774
- def forced?
775
- @customizations[:forced]
776
- end
777
-
778
- protected
779
- def ignored?
780
- @customizations[:ignored]
781
- end
782
-
783
- protected
784
- def collected?
785
- @customizations[:collected]
786
- end
787
-
788
- protected
789
- def wrapped?
790
- @customizations[:wrapper]
791
- end
792
-
793
- protected
794
- def wrapper_methods
795
- @customizations[:wrapper]
796
- end
797
-
798
- protected
799
- def default_value
800
- if
801
- # TODO : move this out of the default value method
802
- @context and
803
- @context.respond_to?(:encoding) and
804
- @context.encoding == 'base64'
805
- then
806
- Base64.decode64(@text.strip)
807
- else
808
- @context || @text
809
- end
810
- end
811
-
812
- protected
813
- def ruby_name
814
- Inflection.ruby_name(@customizations[:renamed] || element_name)
815
- end
816
-
817
- protected
818
- def customizations_for_child child_element_name
819
- @customizations[:children][child_element_name] ||
820
- CustomizationContext.new(child_element_name)
821
- end
822
-
823
- protected
824
- def initial_customizations(element_name = nil)
825
- end
826
-
827
- end
828
-
829
- # @private
830
- class RootFrame < Frame
831
-
832
- def initialize context, customizations
833
- super('ROOT', :context => context, :customizations => customizations)
834
- end
835
-
836
- end
837
-
838
- # @private
839
- class StubResponse
840
-
841
- def initialize customizations, context = nil
842
- @customizations = customizations
843
- stub_methods(customizations, context || self)
844
- end
845
-
846
- def inspect
847
- methods = public_methods - Object.public_methods
848
- "<Stub #{methods.collect{|m| ":#{m}" }.sort.join(', ')}>"
849
- end
850
-
851
- # @private
852
- private
853
- def stub_methods customizations, context
854
- add_wrappers_to_context(customizations, context)
855
- add_child_elements_to_context(customizations, context)
856
- add_indexes_to_context(customizations, context)
857
- end
858
-
859
- # @private
860
- private
861
- def add_wrappers_to_context customizations, context
862
- wrappers(customizations) do |wrapper_name,wrapper_customizations|
863
- MetaUtils.extend_method(context, wrapper_name) do
864
- StubResponse.new(wrapper_customizations)
865
- end
866
- end
867
- end
868
-
869
- # @private
870
- private
871
- def add_child_elements_to_context customizations, context
872
- without_wrapper(customizations) do |child_name,child_rules|
873
-
874
- ruby_name = Inflection.ruby_name(child_rules[:renamed] || child_name)
875
-
876
- # we stop at any collected elements
877
- if child_rules[:collected]
878
- MetaUtils.extend_method(context, ruby_name) { [] }
879
- next
880
- end
881
-
882
- if child_rules[:construct_value]
883
-
884
- MetaUtils.extend_method(context, ruby_name) do
885
- child_rules[:construct_value].call
886
- end
887
-
888
- elsif child_rules[:children].empty? # has no child elements
889
-
890
- unless child_rules[:ignored]
891
-
892
- method_name = child_rules[:boolean] ? "#{ruby_name}?" : ruby_name
893
-
894
- MetaUtils.extend_method(context, method_name) do
895
- if child_rules[:value_formatter]
896
- child_rules[:value_formatter].format_value('')
897
- else
898
- nil
899
- end
900
- end
901
- end
902
-
903
- else # it has one or more child elements
904
-
905
- if child_rules[:ignored]
906
- stub_methods(child_rules, context)
907
- else
908
- MetaUtils.extend_method(context, ruby_name) do
909
- StubResponse.new(child_rules)
910
- end
911
- end
912
-
913
- end
914
-
915
- end
916
- end
917
-
918
- # @private
919
- def add_indexes_to_context(customizations, context)
920
- if indexes = customizations[:index_names]
921
- indexes.each do |index|
922
- MetaUtils.extend_method(context, index) { {} }
923
- end
924
- end
925
- end
926
-
927
- # @private
928
- def wrappers customizations, &block
929
- wrappers = {}
930
- customizations[:children].each_pair do |child_name,child_rules|
931
- if child_rules[:wrapper]
932
- wrapper_name = child_rules[:wrapper].first
933
- wrappers[wrapper_name] ||= { :children => {} }
934
- wrappers[wrapper_name][:children][child_name] = child_rules.merge(:wrapper => nil)
935
- end
936
- end
937
-
938
- wrappers.each_pair do |wrapper_name, wrapper_customizations|
939
- yield(wrapper_name, wrapper_customizations)
940
- end
941
- end
942
-
943
- # @private
944
- private
945
- def without_wrapper customizations, &block
946
- customizations[:children].each_pair do |child_name,child_rules|
947
- unless child_rules[:wrapper]
948
- yield(child_name, child_rules)
949
- end
950
- end
951
- end
952
-
953
- end
954
-
955
- end
956
- end
957
- end