aws-sdk 1.5.4 → 1.5.5

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