aws-sdk 1.4.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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