aws-sdk 1.5.4 → 1.5.5

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.
@@ -58,6 +58,7 @@ module AWS
58
58
  # bucket.exists? #=> true
59
59
  #
60
60
  # @param [String] bucket_name
61
+ #
61
62
  # @param [Hash] options
62
63
  #
63
64
  # @option options [String] :location_constraint (nil) The
@@ -71,13 +72,29 @@ module AWS
71
72
  # bucket = s3.buckets.create("my-us-west-bucket")
72
73
  # bucket.location_constraint # => "us-west-1"
73
74
  #
74
- # @option options [String] :acl (:private) Sets the ACL of the bucket
75
- # you are creating. Valid Values include :private, :public_read,
76
- # :public_read_write, :authenticated_read, :bucket_owner_read and
77
- # :bucket_owner_full_control
75
+ # @option options [Symbol,String] :acl (:private) Sets the ACL of the
76
+ # bucket you are creating. Valid Values include:
77
+ # * +:private+
78
+ # * +:public_read+
79
+ # * +:public_read_write+
80
+ # * +:authenticated_read+
81
+ # * +:log_delivery_write+
82
+ #
83
+ # @option options [String] :grant_read
84
+ # @option options [String] :grant_write
85
+ # @option options [String] :grant_read_acp
86
+ # @option options [String] :grant_write_acp
87
+ # @option options [String] :grant_full_control
88
+ #
78
89
  # @return [Bucket]
90
+ #
79
91
  def create bucket_name, options = {}
80
92
 
93
+ # convert the symbolized-canned acl into the string version
94
+ if acl = options[:acl]
95
+ options[:acl] = acl.to_s.tr('_', '-')
96
+ end
97
+
81
98
  # auto set the location constraint for the user if it is not
82
99
  # passed in and the endpoint is not the us-standard region. don't
83
100
  # override the location constraint though, even it is wrong,
data/lib/aws/s3/client.rb CHANGED
@@ -56,15 +56,22 @@ module AWS
56
56
  add_client_request_method(method_name) do
57
57
 
58
58
  configure_request do |req, options|
59
- require_bucket_name!(options[:bucket_name])
59
+
60
+ require_bucket_name!(options[:bucket_name])
61
+
60
62
  req.http_method = verb
61
63
  req.bucket = options[:bucket_name]
62
64
  req.add_param(subresource) if subresource
63
65
 
64
66
  if header_options = method_options[:header_options]
65
- header_options.each do |(option_name, header)|
66
- req.headers[header] = options[option_name] if
67
- options[option_name]
67
+ header_options.each do |(opt, header)|
68
+ if value = options[opt]
69
+ # for backwards compatability we translate canned acls
70
+ # header values from symbols to strings (e.g.
71
+ # :public_read translates to 'public-read')
72
+ value = (opt == :acl ? value.to_s.tr('_', '-') : value)
73
+ req.headers[header] = value
74
+ end
68
75
  end
69
76
  end
70
77
 
@@ -109,11 +116,26 @@ module AWS
109
116
  # @overload create_bucket(options = {})
110
117
  # @param [Hash] options
111
118
  # @option options [required,String] :bucket_name
119
+ # @option options [String] :acl A canned ACL (e.g. 'private',
120
+ # 'public-read', etc). See the S3 API documentation for
121
+ # a complete list of valid values.
122
+ # @option options [String] :grant_read
123
+ # @option options [String] :grant_write
124
+ # @option options [String] :grant_read_acp
125
+ # @option options [String] :grant_write_acp
126
+ # @option options [String] :grant_full_control
112
127
  # @return [Core::Response]
113
- bucket_method(:create_bucket, :put) do
128
+ bucket_method(:create_bucket, :put, :header_options => {
129
+ :acl => 'x-amz-acl',
130
+ :grant_read => 'x-amz-grant-read',
131
+ :grant_write => 'x-amz-grant-write',
132
+ :grant_read_acp => 'x-amz-grant-read-acp',
133
+ :grant_write_acp => 'x-amz-grant-write-acp',
134
+ :grant_full_control => 'x-amz-grant-full-control',
135
+ }) do
136
+
114
137
  configure_request do |req, options|
115
138
  validate_bucket_name!(options[:bucket_name])
116
- req.canned_acl = options[:acl]
117
139
  if location = options[:location_constraint]
118
140
  xmlns = "http://s3.amazonaws.com/doc/#{API_VERSION}/"
119
141
  req.body = <<-XML
@@ -124,7 +146,9 @@ module AWS
124
146
  end
125
147
  super(req, options)
126
148
  end
149
+
127
150
  end
151
+ alias_method :put_bucket, :create_bucket
128
152
 
129
153
  # Deletes an empty bucket.
130
154
  # @overload delete_bucket(options = {})
@@ -308,32 +332,87 @@ module AWS
308
332
 
309
333
  end
310
334
 
311
- # Sets the access control list for a bucket.
312
- # @overload set_bucket_acl(options = {})
335
+ # Sets the access control list for a bucket. You must specify an ACL
336
+ # via one of the following methods:
337
+ #
338
+ # * as a canned ACL (via +:acl+)
339
+ # * as a list of grants (via the +:grant_*+ options)
340
+ # * as an access control policy document (via +:access_control_policy+)
341
+ #
342
+ # @example Using a canned acl
343
+ # s3_client.put_bucket_acl(
344
+ # :bucket_name => 'bucket-name',
345
+ # :acl => 'public-read')
346
+ #
347
+ # @example Using grants
348
+ # s3_client.put_bucket_acl(
349
+ # :bucket_name => 'bucket-name',
350
+ # :grant_read => 'uri="http://acs.amazonaws.com/groups/global/AllUsers"',
351
+ # :grant_full_control => 'emailAddress="xyz@amazon.com", id="8a9...fa7"')
352
+ #
353
+ # @example Using an access control policy document
354
+ # policy_xml = <<-XML
355
+ # <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
356
+ # <Owner>
357
+ # <ID>852b113e7a2f25102679df27bb0ae12b3f85be6BucketOwnerCanonicalUserID</ID>
358
+ # <DisplayName>OwnerDisplayName</DisplayName>
359
+ # </Owner>
360
+ # <AccessControlList>
361
+ # <Grant>
362
+ # <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
363
+ # <ID>BucketOwnerCanonicalUserID</ID>
364
+ # <DisplayName>OwnerDisplayName</DisplayName>
365
+ # </Grantee>
366
+ # <Permission>FULL_CONTROL</Permission>
367
+ # </Grant>
368
+ # <Grant>
369
+ # <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
370
+ # <URI xmlns="">http://acs.amazonaws.com/groups/global/AllUsers</URI>
371
+ # </Grantee>
372
+ # <Permission xmlns="">READ</Permission>
373
+ # </Grant>
374
+ # </AccessControlList>
375
+ # </AccessControlPolicy>
376
+ #
377
+ # XML
378
+ # s3_client.put_bucket_acl(
379
+ # :bucket_name => 'bucket-name',
380
+ # :access_control_policy => policy_xml)
381
+ #
382
+ # @overload put_bucket_acl(options = {})
313
383
  # @param [Hash] options
314
384
  # @option options [required,String] :bucket_name
315
- # @option options [required,String,AccessControlList,Hash] :acl
316
- # This may be any of the following:
317
- # * An XML policy as a string (which is passed to S3 uninterpreted)
318
- # * An {AccessControlList} object
319
- # * Any object that responds to +#to_xml+
320
- # * A hash that is compatible with {AccessControlList} #new.
385
+ # @option options [String] :access_control_policy An access control
386
+ # policy description as a string of XML. See the S3 API
387
+ # documentation for a description.
388
+ # @option options [String] :acl A canned ACL (e.g. 'private',
389
+ # 'public-read', etc). See the S3 API documentation for
390
+ # a complete list of valid values.
391
+ # @option options [String] :grant_read
392
+ # @option options [String] :grant_write
393
+ # @option options [String] :grant_read_acp
394
+ # @option options [String] :grant_write_acp
395
+ # @option options [String] :grant_full_control
321
396
  # @return [Core::Response]
322
- bucket_method(:set_bucket_acl, :put, 'acl') do
397
+ bucket_method(:put_bucket_acl, :put, 'acl', :header_options => {
398
+ :acl => 'x-amz-acl',
399
+ :grant_read => 'x-amz-grant-read',
400
+ :grant_write => 'x-amz-grant-write',
401
+ :grant_read_acp => 'x-amz-grant-read-acp',
402
+ :grant_write_acp => 'x-amz-grant-write-acp',
403
+ :grant_full_control => 'x-amz-grant-full-control',
404
+ }) do
323
405
 
324
406
  configure_request do |req, options|
325
- require_acl!(options[:acl])
407
+ move_access_control_policy(options)
408
+ require_acl!(options)
326
409
  super(req, options)
327
- if options[:acl].kind_of?(Hash)
328
- req.body = AccessControlList.new(options[:acl]).to_xml
329
- elsif options[:acl].respond_to?(:to_str)
330
- req.body = options[:acl]
331
- else
332
- req.body = options[:acl].to_xml
333
- end
410
+ req.body = options[:access_control_policy] if
411
+ options[:access_control_policy]
334
412
  end
335
413
 
336
414
  end
415
+ alias_method :set_bucket_acl, :put_bucket_acl
337
416
 
338
417
  # Gets the access control list for a bucket.
339
418
  # @overload get_bucket_acl(options = {})
@@ -342,33 +421,91 @@ module AWS
342
421
  # @return [Core::Response]
343
422
  bucket_method(:get_bucket_acl, :get, 'acl', XML::GetBucketAcl)
344
423
 
345
- # Sets the access control list for an object.
346
- # @overload set_object_acl(options = {})
424
+ # Sets the access control list for an object. You must specify an ACL
425
+ # via one of the following methods:
426
+ #
427
+ # * as a canned ACL (via +:acl+)
428
+ # * as a list of grants (via the +:grant_*+ options)
429
+ # * as an access control policy document (via +:access_control_policy+)
430
+ #
431
+ # @example Using a canned acl
432
+ # s3_client.put_object_acl(
433
+ # :bucket_name => 'bucket-name',
434
+ # :key => 'object-key',
435
+ # :acl => 'public-read')
436
+ #
437
+ # @example Using grants
438
+ # s3_client.put_bucket_acl(
439
+ # :bucket_name => 'bucket-name',
440
+ # :key => 'object-key',
441
+ # :grant_read => 'uri="http://acs.amazonaws.com/groups/global/AllUsers"',
442
+ # :grant_full_control => 'emailAddress="xyz@amazon.com", id="8a9...fa7"')
443
+ #
444
+ # @example Using an access control policy document
445
+ # policy_xml = <<-XML
446
+ # <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
447
+ # <Owner>
448
+ # <ID>852b113e7a2f25102679df27bb0ae12b3f85be6BucketOwnerCanonicalUserID</ID>
449
+ # <DisplayName>OwnerDisplayName</DisplayName>
450
+ # </Owner>
451
+ # <AccessControlList>
452
+ # <Grant>
453
+ # <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
454
+ # <ID>BucketOwnerCanonicalUserID</ID>
455
+ # <DisplayName>OwnerDisplayName</DisplayName>
456
+ # </Grantee>
457
+ # <Permission>FULL_CONTROL</Permission>
458
+ # </Grant>
459
+ # <Grant>
460
+ # <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
461
+ # <URI xmlns="">http://acs.amazonaws.com/groups/global/AllUsers</URI>
462
+ # </Grantee>
463
+ # <Permission xmlns="">READ</Permission>
464
+ # </Grant>
465
+ # </AccessControlList>
466
+ # </AccessControlPolicy>
467
+ #
468
+ # XML
469
+ # s3_client.put_bucket_acl(
470
+ # :bucket_name => 'bucket-name',
471
+ # :key => 'object-key',
472
+ # :access_control_policy => policy_xml)
473
+ #
474
+ # @overload put_object_acl(options = {})
347
475
  # @param [Hash] options
348
476
  # @option options [required,String] :bucket_name
349
477
  # @option options [required,String] :key
350
- # @option options [required,String,AccessControlList,Hash] :acl
351
- # This may be any of the following:
352
- # * An XML policy as a string (which is passed to S3 uninterpreted)
353
- # * An {AccessControlList} object
354
- # * Any object that responds to +#to_xml+
355
- # * A hash that is compatible with {AccessControlList} #new.
478
+ # @option options [String] :access_control_policy An access control
479
+ # policy description as a string of XML. See the S3 API
480
+ # documentation for a description.
481
+ # @option options [String] :acl A canned ACL (e.g. 'private',
482
+ # 'public-read', etc). See the S3 API documentation for
483
+ # a complete list of valid values.
484
+ # @option options [String] :grant_read
485
+ # @option options [String] :grant_write
486
+ # @option options [String] :grant_read_acp
487
+ # @option options [String] :grant_write_acp
488
+ # @option options [String] :grant_full_control
356
489
  # @return [Core::Response]
357
- object_method(:set_object_acl, :put, 'acl') do
490
+ object_method(:put_object_acl, :put, 'acl', :header_options => {
491
+ :acl => 'x-amz-acl',
492
+ :grant_read => 'x-amz-grant-read',
493
+ :grant_write => 'x-amz-grant-write',
494
+ :grant_read_acp => 'x-amz-grant-read-acp',
495
+ :grant_write_acp => 'x-amz-grant-write-acp',
496
+ :grant_full_control => 'x-amz-grant-full-control',
497
+ }) do
498
+
358
499
  configure_request do |req, options|
359
- require_acl!(options[:acl]) unless options[:acl].kind_of?(Symbol)
500
+ move_access_control_policy(options)
501
+ require_acl!(options)
360
502
  super(req, options)
361
- if options[:acl].kind_of?(Hash)
362
- req.body = AccessControlList.new(options[:acl]).to_xml
363
- elsif options[:acl].kind_of?(Symbol)
364
- req.headers["x-amz-acl"] = options[:acl].to_s.tr("_","-")
365
- elsif options[:acl].respond_to?(:to_str)
366
- req.body = options[:acl]
367
- else
368
- req.body = options[:acl].to_xml
369
- end
503
+ req.body = options[:access_control_policy] if
504
+ options[:access_control_policy]
370
505
  end
506
+
371
507
  end
508
+ alias_method :set_object_acl, :put_object_acl
372
509
 
373
510
  # Gets the access control list for an object.
374
511
  # @overload get_object_acl(options = {})
@@ -442,7 +579,7 @@ module AWS
442
579
  # +:reduced_redundancy+.
443
580
  # @option options [String] :cache_control
444
581
  # Can be used to specify caching behavior.
445
- # @option opitons [String] :content_disposition
582
+ # @option options [String] :content_disposition
446
583
  # Specifies presentational information.
447
584
  # @option options [String] :content_encoding
448
585
  # Specifies the content encoding.
@@ -451,19 +588,33 @@ module AWS
451
588
  # @option options [String] :content_type
452
589
  # Specifies the content type.
453
590
  # @option options [String] :expires
591
+ # @option options [String] :acl A canned ACL (e.g. 'private',
592
+ # 'public-read', etc). See the S3 API documentation for
593
+ # a complete list of valid values.
594
+ # @option options [String] :grant_read
595
+ # @option options [String] :grant_write
596
+ # @option options [String] :grant_read_acp
597
+ # @option options [String] :grant_write_acp
598
+ # @option options [String] :grant_full_control
454
599
  # @return [Core::Response]
455
600
  #
456
- object_method(:put_object, :put,
457
- :header_options => {
458
- :content_md5 => 'Content-MD5',
459
- :cache_control => 'Cache-Control',
460
- :content_disposition => 'Content-Disposition',
461
- :content_encoding => 'Content-Encoding',
462
- :content_type => 'Content-Type',
463
- :storage_class => 'x-amz-storage-class',
464
- :server_side_encryption => 'x-amz-server-side-encryption',
465
- :expires => 'Expires'
466
- }) do
601
+ object_method(:put_object, :put, :header_options => {
602
+ :acl => 'x-amz-acl',
603
+ :grant_read => 'x-amz-grant-read',
604
+ :grant_write => 'x-amz-grant-write',
605
+ :grant_read_acp => 'x-amz-grant-read-acp',
606
+ :grant_write_acp => 'x-amz-grant-write-acp',
607
+ :grant_full_control => 'x-amz-grant-full-control',
608
+ :content_md5 => 'Content-MD5',
609
+ :cache_control => 'Cache-Control',
610
+ :content_disposition => 'Content-Disposition',
611
+ :content_encoding => 'Content-Encoding',
612
+ :content_type => 'Content-Type',
613
+ :storage_class => 'x-amz-storage-class',
614
+ :server_side_encryption => 'x-amz-server-side-encryption',
615
+ :expires => 'Expires'
616
+ }) do
617
+
467
618
  configure_request do |request, options, block|
468
619
  options[:server_side_encryption] =
469
620
  options[:server_side_encryption].to_s.upcase if
@@ -471,7 +622,6 @@ module AWS
471
622
  super(request, options)
472
623
  set_request_data(request, options, block)
473
624
  request.metadata = options[:metadata]
474
- request.canned_acl = options[:acl]
475
625
  request.storage_class = options[:storage_class]
476
626
  end
477
627
 
@@ -679,10 +829,24 @@ module AWS
679
829
  # @option options [String] :storage_class
680
830
  # @option options [String] :server_side_encryption
681
831
  # @option options [String] :expires
832
+ # @option options [String] :acl A canned ACL (e.g. 'private',
833
+ # 'public-read', etc). See the S3 API documentation for
834
+ # a complete list of valid values.
835
+ # @option options [String] :grant_read
836
+ # @option options [String] :grant_write
837
+ # @option options [String] :grant_read_acp
838
+ # @option options [String] :grant_write_acp
839
+ # @option options [String] :grant_full_control
682
840
  # @return [Core::Response]
683
841
  object_method(:initiate_multipart_upload, :post, 'uploads',
684
842
  XML::InitiateMultipartUpload,
685
843
  :header_options => {
844
+ :acl => 'x-amz-acl',
845
+ :grant_read => 'x-amz-grant-read',
846
+ :grant_write => 'x-amz-grant-write',
847
+ :grant_read_acp => 'x-amz-grant-read-acp',
848
+ :grant_write_acp => 'x-amz-grant-write-acp',
849
+ :grant_full_control => 'x-amz-grant-full-control',
686
850
  :cache_control => 'Cache-Control',
687
851
  :content_disposition => 'Content-Disposition',
688
852
  :content_encoding => 'Content-Encoding',
@@ -691,13 +855,13 @@ module AWS
691
855
  :server_side_encryption => 'x-amz-server-side-encryption',
692
856
  :expires => 'Expires'
693
857
  }) do
858
+
694
859
  configure_request do |req, options|
695
860
  options[:server_side_encryption] =
696
861
  options[:server_side_encryption].to_s.upcase if
697
862
  options[:server_side_encryption].kind_of?(Symbol)
698
863
  super(req, options)
699
864
  req.metadata = options[:metadata]
700
- req.canned_acl = options[:acl]
701
865
  req.storage_class = options[:storage_class]
702
866
  end
703
867
 
@@ -884,17 +1048,29 @@ module AWS
884
1048
  # bucket name and key, joined by a forward slash ('/').
885
1049
  # This string must be URL-encoded. Additionally, you must
886
1050
  # have read access to the source object.
887
- # @option options [Symbol] :acl
1051
+ # @option options [String] :acl A canned ACL (e.g. 'private',
1052
+ # 'public-read', etc). See the S3 API documentation for
1053
+ # a complete list of valid values.
1054
+ # @option options [String] :grant_read
1055
+ # @option options [String] :grant_write
1056
+ # @option options [String] :grant_read_acp
1057
+ # @option options [String] :grant_write_acp
1058
+ # @option options [String] :grant_full_control
888
1059
  # @return [Core::Response]
889
- object_method(:copy_object, :put,
890
- :header_options => {
891
- :copy_source => 'x-amz-copy-source',
892
- :cache_control => 'Cache-Control',
893
- :metadata_directive => 'x-amz-metadata-directive',
894
- :storage_class => 'x-amz-storage-class',
895
- :server_side_encryption => 'x-amz-server-side-encryption',
896
- :content_type => 'Content-Type',
897
- }) do
1060
+ object_method(:copy_object, :put, :header_options => {
1061
+ :acl => 'x-amz-acl',
1062
+ :grant_read => 'x-amz-grant-read',
1063
+ :grant_write => 'x-amz-grant-write',
1064
+ :grant_read_acp => 'x-amz-grant-read-acp',
1065
+ :grant_write_acp => 'x-amz-grant-write-acp',
1066
+ :grant_full_control => 'x-amz-grant-full-control',
1067
+ :copy_source => 'x-amz-copy-source',
1068
+ :cache_control => 'Cache-Control',
1069
+ :metadata_directive => 'x-amz-metadata-directive',
1070
+ :storage_class => 'x-amz-storage-class',
1071
+ :server_side_encryption => 'x-amz-server-side-encryption',
1072
+ :content_type => 'Content-Type',
1073
+ }) do
898
1074
 
899
1075
  configure_request do |req, options|
900
1076
  # TODO : validate metadata directive COPY / REPLACE
@@ -908,7 +1084,6 @@ module AWS
908
1084
  options[:server_side_encryption].to_s.upcase if
909
1085
  options[:server_side_encryption].kind_of?(Symbol)
910
1086
  super(req, options)
911
- req.canned_acl = options[:acl]
912
1087
  req.metadata = options[:metadata]
913
1088
  req.storage_class = options[:storage_class]
914
1089
  if options[:version_id]
@@ -980,6 +1155,30 @@ module AWS
980
1155
  response.data[:server_side_encryption] = sse
981
1156
  end
982
1157
 
1158
+ # Previously the access control policy could be specified via :acl
1159
+ # as a string or an object that responds to #to_xml. The prefered
1160
+ # method now is to pass :access_control_policy an xml document.
1161
+ def move_access_control_policy options
1162
+ if acl = options[:acl]
1163
+ if acl.is_a?(String) and is_xml?(acl)
1164
+ options[:access_control_policy] = options.delete(:acl)
1165
+ elsif acl.respond_to?(:to_xml)
1166
+ options[:access_control_policy] = options.delete(:acl).to_xml
1167
+ end
1168
+ end
1169
+ end
1170
+
1171
+ # @param [String] possible_xml
1172
+ # @reutrn [Boolean] Returns +true+ if the given string is a valid xml
1173
+ # document.
1174
+ def is_xml? possible_xml
1175
+ begin
1176
+ REXML::Document.new(possible_xml).has_elements?
1177
+ rescue
1178
+ false
1179
+ end
1180
+ end
1181
+
983
1182
  module Validators
984
1183
 
985
1184
  # @return [Boolean] Returns true if the given bucket name is valid.
@@ -1102,19 +1301,20 @@ module AWS
1102
1301
  end
1103
1302
  end
1104
1303
 
1105
- def require_acl!(acl)
1106
- validate!('acl', acl) do
1107
- case
1108
- when acl.kind_of?(Hash)
1109
- AccessControlList.new(acl).validate!
1110
- nil
1111
- when !acl.respond_to?(:to_str) && !acl.respond_to?(:to_xml)
1112
- "must support to_xml: #{acl.inspect}"
1113
- when acl.nil? || acl == ''
1114
- 'may not be blank'
1115
- else
1116
- xml_validation_message(acl)
1117
- end
1304
+ def require_acl! options
1305
+ acl_options = [
1306
+ :acl,
1307
+ :grant_read,
1308
+ :grant_write,
1309
+ :grant_read_acp,
1310
+ :grant_write_acp,
1311
+ :grant_full_control,
1312
+ :access_control_policy,
1313
+ ]
1314
+ unless options.keys.any?{|opt| acl_options.include?(opt) }
1315
+ msg = "missing a required ACL option, must provide an ACL " +
1316
+ "via :acl, :grant_* or :access_control_policy"
1317
+ raise ArgumentError, msg
1118
1318
  end
1119
1319
  end
1120
1320
 
@@ -1158,22 +1358,6 @@ module AWS
1158
1358
  "contains invalid JSON: #{error}" if error
1159
1359
  end
1160
1360
 
1161
- def xml_validation_message(obj)
1162
- if obj.respond_to?(:to_str)
1163
- obj = obj.to_str
1164
- elsif obj.respond_to?(:to_xml)
1165
- obj = obj.to_xml
1166
- end
1167
-
1168
- error = nil
1169
- begin
1170
- REXML::Document.new(obj)
1171
- rescue => e
1172
- error = e
1173
- end
1174
- "contains invalid XML: #{error}" if error
1175
- end
1176
-
1177
1361
  end
1178
1362
 
1179
1363
  include Validators