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
@@ -0,0 +1,42 @@
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
+ module Signature
17
+ module Version2
18
+
19
+ def add_authorization! signer
20
+ self.access_key_id = signer.access_key_id
21
+ add_param('AWSAccessKeyId', access_key_id)
22
+ if signer.respond_to?(:session_token) and token = signer.session_token
23
+ add_param("SecurityToken", token)
24
+ end
25
+ add_param('SignatureVersion', '2')
26
+ add_param('SignatureMethod', 'HmacSHA256')
27
+ add_param('Signature', signer.sign(string_to_sign))
28
+ end
29
+
30
+ def string_to_sign
31
+ [
32
+ http_method,
33
+ host,
34
+ path,
35
+ params.sort.collect { |p| p.encoded }.join('&'),
36
+ ].join("\n")
37
+ end
38
+
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,73 @@
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 'openssl'
15
+ require 'time'
16
+
17
+ module AWS
18
+ module Core
19
+ module Signature
20
+ module Version3
21
+
22
+ def add_authorization!(signer)
23
+
24
+ self.access_key_id = signer.access_key_id
25
+
26
+ headers["x-amz-date"] ||= (headers["date"] ||= Time.now.rfc822)
27
+ headers["host"] ||= host
28
+
29
+ headers["x-amz-security-token"] = signer.session_token if
30
+ signer.respond_to?(:session_token) and signer.session_token
31
+
32
+ # compute the authorization
33
+ request_hash = OpenSSL::Digest::SHA256.digest(string_to_sign)
34
+ signature = signer.sign(request_hash)
35
+ headers["x-amzn-authorization"] =
36
+ "AWS3 "+
37
+ "AWSAccessKeyId=#{signer.access_key_id},"+
38
+ "Algorithm=HmacSHA256,"+
39
+ "SignedHeaders=#{headers_to_sign.join(';')},"+
40
+ "Signature=#{signature}"
41
+ end
42
+
43
+ protected
44
+
45
+ def string_to_sign
46
+ [
47
+ http_method,
48
+ "/",
49
+ "",
50
+ canonical_headers,
51
+ body
52
+ ].join("\n")
53
+ end
54
+
55
+ def canonical_headers
56
+ headers_to_sign.map do |name|
57
+ value = headers[name]
58
+ "#{name.downcase.strip}:#{value.strip}\n"
59
+ end.sort.join
60
+ end
61
+
62
+ def headers_to_sign
63
+ headers.keys.select do |header|
64
+ header == "host" ||
65
+ header == "content-encoding" ||
66
+ header =~ /^x-amz/
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,72 @@
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 'openssl'
15
+ require 'time'
16
+
17
+ module AWS
18
+ module Core
19
+ module Signature
20
+ module Version3
21
+
22
+ def add_authorization!(signer)
23
+
24
+ self.access_key_id = signer.access_key_id
25
+
26
+ headers["x-amz-date"] ||= (headers["date"] ||= Time.now.rfc822)
27
+ headers["host"] ||= host
28
+
29
+ headers["x-amz-security-token"] = signer.session_token if
30
+ signer.respond_to?(:session_token) and signer.session_token
31
+
32
+ # compute the authorization
33
+ request_hash = OpenSSL::Digest::SHA256.digest(string_to_sign)
34
+ signature = signer.sign(request_hash)
35
+ headers["x-amzn-authorization"] =
36
+ "AWS3 "+
37
+ "AWSAccessKeyId=#{signer.access_key_id},"+
38
+ "Algorithm=HmacSHA256,"+
39
+ "SignedHeaders=#{headers_to_sign.join(';')},"+
40
+ "Signature=#{signature}"
41
+ end
42
+
43
+ protected
44
+
45
+ def string_to_sign
46
+ [
47
+ http_method,
48
+ "/",
49
+ "",
50
+ canonical_headers,
51
+ body
52
+ ].join("\n")
53
+ end
54
+
55
+ def canonical_headers
56
+ headers_to_sign.map do |name|
57
+ value = headers[name]
58
+ "#{name.downcase.strip}:#{value.strip}\n"
59
+ end.sort.join
60
+ end
61
+
62
+ def headers_to_sign
63
+ headers.keys.select do |header|
64
+ header == "host" ||
65
+ header =~ /^x-amz/
66
+ end
67
+ end
68
+
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,138 @@
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 'time'
15
+ require 'openssl'
16
+ require 'digest'
17
+
18
+ module AWS
19
+ module Core
20
+ module Signature
21
+ module Version4
22
+
23
+ def add_authorization! signer
24
+ self.access_key_id = signer.access_key_id
25
+ datetime = Time.now.utc.strftime("%Y%m%dT%H%M%SZ")
26
+ headers['content-type'] ||= 'application/x-www-form-urlencoded'
27
+ headers['host'] = host
28
+ headers['x-amz-date'] = datetime
29
+ headers['x-amz-security-token'] = signer.session_token if signer.session_token
30
+ headers['authorization'] = authorization(signer, datetime)
31
+ end
32
+
33
+ protected
34
+
35
+ def authorization signer, datetime
36
+ parts = []
37
+ parts << "AWS4-HMAC-SHA256 Credential=#{access_key_id}/#{credential_string(datetime)}"
38
+ parts << "SignedHeaders=#{signed_headers}"
39
+ parts << "Signature=#{hex16(signature(signer, datetime))}"
40
+ parts.join(', ')
41
+ end
42
+
43
+ def signature signer, datetime
44
+ k_secret = signer.secret_access_key
45
+ k_date = hmac("AWS4" + k_secret, datetime[0,8])
46
+ k_region = hmac(k_date, region)
47
+ k_service = hmac(k_region, service)
48
+ k_credentials = hmac(k_service, 'aws4_request')
49
+ hmac(k_credentials, string_to_sign(datetime))
50
+ end
51
+
52
+ def string_to_sign datetime
53
+ parts = []
54
+ parts << 'AWS4-HMAC-SHA256'
55
+ parts << datetime
56
+ parts << credential_string(datetime)
57
+ parts << hex16(hash(canonical_request))
58
+ parts.join("\n")
59
+ end
60
+
61
+ def credential_string datetime
62
+ parts = []
63
+ parts << datetime[0,8]
64
+ parts << region
65
+ parts << service
66
+ parts << 'aws4_request'
67
+ parts.join("/")
68
+ end
69
+
70
+ def canonical_request
71
+ parts = []
72
+ parts << action_name
73
+ parts << canonical_uri
74
+ parts << canonical_querystring
75
+ parts << canonical_headers + "\n"
76
+ parts << signed_headers
77
+ parts << hex16(hash(payload))
78
+ parts.join("\n")
79
+ end
80
+
81
+ def service
82
+ # this method is implemented in the request class for each service
83
+ raise NotImplementedError
84
+ end
85
+
86
+ def action_name
87
+ http_method.to_s.upcase
88
+ end
89
+
90
+ def canonical_uri
91
+ path
92
+ end
93
+
94
+ def payload
95
+ body || ''
96
+ end
97
+
98
+ def canonical_querystring
99
+ http_method.to_s.upcase == 'GET' ? url_encoded_params : ''
100
+ end
101
+
102
+ def signed_headers
103
+ to_sign = headers.keys.map{|k| k.to_s.downcase }
104
+ to_sign.delete('authorization')
105
+ to_sign.sort.join(";")
106
+ end
107
+
108
+ def canonical_headers
109
+ headers = []
110
+ self.headers.each_pair do |k,v|
111
+ header = [k.to_s.downcase, v]
112
+ headers << header unless header.first == 'authorization'
113
+ end
114
+ headers = headers.sort_by(&:first)
115
+ headers.map{|k,v| "#{k}:#{canonical_header_values(v)}" }.join("\n")
116
+ end
117
+
118
+ def canonical_header_values values
119
+ values = [values] unless values.is_a?(Array)
120
+ values.map(&:to_s).map(&:strip).join(',')
121
+ end
122
+
123
+ def hex16 string
124
+ string.unpack('H*').first
125
+ end
126
+
127
+ def hmac key, string
128
+ OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha256'), key, string)
129
+ end
130
+
131
+ def hash string
132
+ Digest::SHA256.digest(string)
133
+ end
134
+
135
+ end
136
+ end
137
+ end
138
+ end
@@ -16,22 +16,19 @@ require 'cgi'
16
16
  module AWS
17
17
  module Core
18
18
 
19
- # @private
19
+ # Provides helper methods for URI escaping values and paths.
20
20
  module UriEscape
21
21
 
22
- # Does URI escaping the way AWS expects it to be done.
23
- #
24
- # @private
25
- protected
22
+ # @param [String] value
23
+ # @return [String] Returns a URI escaped string.
26
24
  def escape value
27
25
  value = value.encode("UTF-8") if value.respond_to?(:encode)
28
26
  CGI::escape(value.to_s).gsub('+', '%20').gsub('%7E', '~')
29
27
  end
30
28
 
31
- # URI-escapes a path without escaping the separators
32
- #
33
- # @private
34
- protected
29
+ # @param [String] value
30
+ # @return [String] Returns a URI-escaped path without escaping the
31
+ # separators.
35
32
  def escape_path value
36
33
  escaped = ""
37
34
  value.scan(%r{(/*)([^/]*)(/*)}) do |(leading, part, trailing)|
@@ -0,0 +1,242 @@
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 'base64'
15
+
16
+ module AWS
17
+ module Core
18
+ module XML
19
+ class Frame
20
+
21
+ TRANSLATE_DIGITS = ['0123456789'.freeze, ('X'*10).freeze]
22
+
23
+ EASY_FORMAT = "XXXX-XX-XXTXX:XX:XX.XXXZ".freeze
24
+
25
+ DATE_PUNCTUATION = ['-:.TZ'.freeze, (' '*5).freeze]
26
+
27
+ def initialize root_frame, parent_frame, element_name, rules
28
+
29
+ @root_frame = root_frame
30
+ @parent_frame = parent_frame
31
+ @element_name = element_name
32
+ @rules = rules
33
+ @rules[:children] ||= {}
34
+
35
+ @data = {}.merge(rules[:defaults] || {})
36
+ @text = nil
37
+
38
+ # initialize values for child frames of special types (e.g.
39
+ # lists, maps, and forced elements)
40
+ known_child_frames.each do |child_frame|
41
+ context = data_context_for(child_frame)
42
+ if child_frame.list?
43
+ context[child_frame.ruby_name] = []
44
+ elsif child_frame.map?
45
+ context[child_frame.ruby_name] = {}
46
+ elsif child_frame.forced?
47
+ context[child_frame.ruby_name] = child_frame.value
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ attr_reader :root_frame
54
+ attr_reader :parent_frame
55
+ attr_reader :element_name
56
+ attr_reader :rules
57
+
58
+ def data
59
+ ignored? ? parent_frame.data : @data
60
+ end
61
+
62
+ def ruby_name
63
+ rules[:rename] || root_frame.inflect(element_name)
64
+ end
65
+
66
+ def rules_for child_element_name
67
+ rules[:children][child_element_name] || {}
68
+ end
69
+
70
+ # The list of child frames that have customizations (rules), all
71
+ # other children will be parsed using standard rules
72
+ def known_child_frames
73
+ rules[:children].keys.map {|name| build_child_frame(name) }
74
+ end
75
+
76
+ def build_child_frame element_name
77
+ # if element_name should be wrapped
78
+ # build a frame for the wrapper
79
+ # build a child frame from the wrapper
80
+ # else
81
+ Frame.new(root_frame, self, element_name, rules_for(element_name))
82
+ end
83
+
84
+ def consume_child_frame child_frame
85
+
86
+ child_frame.close
87
+
88
+ return if child_frame.ignored?
89
+
90
+ ruby_name = child_frame.ruby_name
91
+ value = child_frame.value
92
+ context = data_context_for(child_frame)
93
+
94
+ if child_frame.list?
95
+ context[ruby_name] << value
96
+ elsif map = child_frame.map?
97
+ context[ruby_name][child_frame.map_key] = child_frame.map_value
98
+ else
99
+ context[ruby_name] = value
100
+ end
101
+ end
102
+
103
+ def close
104
+ # some xml elements should be indexed at the root level
105
+ # The :index rule determines the name of this index
106
+ # and what keys the data should be indexed as (one element
107
+ # can be indexed under multiple keys). The index value
108
+ # is always the element itself.
109
+ if index = @rules[:index]
110
+ index_keys_for(index) do |key|
111
+ root_frame.add_to_index(index[:name], key, data)
112
+ end
113
+ end
114
+ end
115
+
116
+ def index_keys_for index_opts, &block
117
+
118
+ # simple (single) key
119
+ if key = index_opts[:key]
120
+ yield(data[key])
121
+ return
122
+ end
123
+
124
+ # composite key, joined by ":"
125
+ if parts = index_opts[:keys]
126
+ composite_key = parts.map{|part| data[part] }.join(":")
127
+ yield(composite_key)
128
+ return
129
+ end
130
+
131
+ # multiple keys, collected from the given path
132
+ if path = index_opts[:key_path]
133
+ keys_from_path(data, path.dup, &block)
134
+ return
135
+ end
136
+
137
+ raise "missing require index rule option, :key, :keys or :key_path"
138
+
139
+ end
140
+
141
+ def keys_from_path data, path, &block
142
+
143
+ step = path.shift
144
+ value = data[step]
145
+
146
+ if path.empty?
147
+ yield(value)
148
+ return
149
+ end
150
+
151
+ if value.is_a?(Array)
152
+ value.each do |v|
153
+ keys_from_path(v, path.dup, &block)
154
+ end
155
+ else
156
+ keys_from_path(value, path.dup, &block)
157
+ end
158
+
159
+ end
160
+
161
+ def add_text chars
162
+ @text ||= ''
163
+ @text << chars
164
+ end
165
+
166
+ def value
167
+ if !data.empty?
168
+ data[:encoding] == 'base64' ? Base64.decode64(@text.strip) : data
169
+ elsif @text.nil?
170
+ rules[:type] == :boolean ? false : nil
171
+ else
172
+ case rules[:type]
173
+ when nil then @text
174
+ when :datetime then datetime_like_value(DateTime, :civil)
175
+ when :time then datetime_like_value(Time, :utc)
176
+ when :integer then @text.to_i
177
+ when :float then @text.to_f
178
+ when :boolean then @text == 'true'
179
+ when :blob then Base64.decode64(@text)
180
+ when :symbol then Core::Inflection.ruby_name(@text).to_sym
181
+ else raise "unhandled type"
182
+ end
183
+ end
184
+ end
185
+
186
+ def ignored?
187
+ @rules[:ignore]
188
+ end
189
+
190
+ def forced?
191
+ @rules[:force]
192
+ end
193
+
194
+ def list?
195
+ @rules[:list]
196
+ end
197
+
198
+ def map?
199
+ @rules[:map]
200
+ end
201
+
202
+ def wrapped?
203
+ @rules[:wrap]
204
+ end
205
+ alias_method :wrapper, :wrapped?
206
+
207
+ protected
208
+
209
+ def map_key
210
+ data[root_frame.inflect(@rules[:map].first)]
211
+ end
212
+
213
+ def map_value
214
+ data[root_frame.inflect(@rules[:map].last)]
215
+ end
216
+
217
+ def data_context_for child_frame
218
+ if child_frame.wrapped?
219
+ data[child_frame.wrapper] ||= {}
220
+ data[child_frame.wrapper]
221
+ else
222
+ data
223
+ end
224
+ end
225
+
226
+ def datetime_like_value klass, parts_constructor
227
+ # it's way faster to parse this specific format manually
228
+ # vs. DateTime#parse, and this happens to be the format
229
+ # that AWS uses almost (??) everywhere.
230
+ if @text.tr(*TRANSLATE_DIGITS) == EASY_FORMAT
231
+ parts = @text.tr(*DATE_PUNCTUATION).chop.split.map {|p| p.to_i }
232
+ klass.send(parts_constructor, *parts)
233
+ else
234
+ # fallback in case we have to handle another date format
235
+ klass.parse(@text)
236
+ end
237
+ end
238
+
239
+ end
240
+ end
241
+ end
242
+ end