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
@@ -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