croaker-aws-s3 0.5.2.20090127001
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.
- data/COPYING +19 -0
 - data/INSTALL +55 -0
 - data/README +545 -0
 - data/Rakefile +334 -0
 - data/bin/s3sh +6 -0
 - data/bin/setup.rb +10 -0
 - data/lib/aws/s3/acl.rb +636 -0
 - data/lib/aws/s3/authentication.rb +222 -0
 - data/lib/aws/s3/base.rb +257 -0
 - data/lib/aws/s3/bittorrent.rb +58 -0
 - data/lib/aws/s3/bucket.rb +329 -0
 - data/lib/aws/s3/connection.rb +349 -0
 - data/lib/aws/s3/error.rb +69 -0
 - data/lib/aws/s3/exceptions.rb +133 -0
 - data/lib/aws/s3/extensions.rb +324 -0
 - data/lib/aws/s3/logging.rb +311 -0
 - data/lib/aws/s3/object.rb +613 -0
 - data/lib/aws/s3/owner.rb +44 -0
 - data/lib/aws/s3/parsing.rb +99 -0
 - data/lib/aws/s3/response.rb +180 -0
 - data/lib/aws/s3/service.rb +51 -0
 - data/lib/aws/s3/version.rb +12 -0
 - data/lib/aws/s3.rb +61 -0
 - data/support/faster-xml-simple/lib/faster_xml_simple.rb +187 -0
 - data/support/faster-xml-simple/test/regression_test.rb +47 -0
 - data/support/faster-xml-simple/test/test_helper.rb +17 -0
 - data/support/faster-xml-simple/test/xml_simple_comparison_test.rb +46 -0
 - data/support/rdoc/code_info.rb +211 -0
 - data/test/acl_test.rb +254 -0
 - data/test/authentication_test.rb +114 -0
 - data/test/base_test.rb +136 -0
 - data/test/bucket_test.rb +74 -0
 - data/test/connection_test.rb +217 -0
 - data/test/error_test.rb +70 -0
 - data/test/extensions_test.rb +331 -0
 - data/test/fixtures/buckets.yml +133 -0
 - data/test/fixtures/errors.yml +34 -0
 - data/test/fixtures/headers.yml +3 -0
 - data/test/fixtures/logging.yml +15 -0
 - data/test/fixtures/loglines.yml +5 -0
 - data/test/fixtures/logs.yml +7 -0
 - data/test/fixtures/policies.yml +16 -0
 - data/test/fixtures.rb +89 -0
 - data/test/logging_test.rb +89 -0
 - data/test/mocks/fake_response.rb +26 -0
 - data/test/object_test.rb +205 -0
 - data/test/parsing_test.rb +66 -0
 - data/test/remote/acl_test.rb +117 -0
 - data/test/remote/bittorrent_test.rb +45 -0
 - data/test/remote/bucket_test.rb +146 -0
 - data/test/remote/logging_test.rb +82 -0
 - data/test/remote/object_test.rb +371 -0
 - data/test/remote/test_helper.rb +30 -0
 - data/test/response_test.rb +68 -0
 - data/test/service_test.rb +23 -0
 - data/test/test_helper.rb +111 -0
 - metadata +143 -0
 
| 
         @@ -0,0 +1,99 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #:stopdoc:
         
     | 
| 
      
 2 
     | 
    
         
            +
            module AWS
         
     | 
| 
      
 3 
     | 
    
         
            +
              module S3
         
     | 
| 
      
 4 
     | 
    
         
            +
                module Parsing
         
     | 
| 
      
 5 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 6 
     | 
    
         
            +
                    def parser=(parsing_library)
         
     | 
| 
      
 7 
     | 
    
         
            +
                      XmlParser.parsing_library = parsing_library
         
     | 
| 
      
 8 
     | 
    
         
            +
                    end
         
     | 
| 
      
 9 
     | 
    
         
            +
                    
         
     | 
| 
      
 10 
     | 
    
         
            +
                    def parser
         
     | 
| 
      
 11 
     | 
    
         
            +
                      XmlParser.parsing_library
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
                  
         
     | 
| 
      
 15 
     | 
    
         
            +
                  module Typecasting
         
     | 
| 
      
 16 
     | 
    
         
            +
                    def typecast(object)
         
     | 
| 
      
 17 
     | 
    
         
            +
                      case object
         
     | 
| 
      
 18 
     | 
    
         
            +
                      when Hash
         
     | 
| 
      
 19 
     | 
    
         
            +
                        typecast_hash(object)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      when Array
         
     | 
| 
      
 21 
     | 
    
         
            +
                        object.map {|element| typecast(element)}
         
     | 
| 
      
 22 
     | 
    
         
            +
                      when String
         
     | 
| 
      
 23 
     | 
    
         
            +
                        CoercibleString.coerce(object)
         
     | 
| 
      
 24 
     | 
    
         
            +
                      else
         
     | 
| 
      
 25 
     | 
    
         
            +
                        object
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                    
         
     | 
| 
      
 29 
     | 
    
         
            +
                    def typecast_hash(hash)
         
     | 
| 
      
 30 
     | 
    
         
            +
                      if content = hash['__content__']  
         
     | 
| 
      
 31 
     | 
    
         
            +
                        typecast(content)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      else
         
     | 
| 
      
 33 
     | 
    
         
            +
                        keys   = hash.keys.map {|key| key.underscore}
         
     | 
| 
      
 34 
     | 
    
         
            +
                        values = hash.values.map {|value| typecast(value)}
         
     | 
| 
      
 35 
     | 
    
         
            +
                        keys.inject({}) do |new_hash, key|
         
     | 
| 
      
 36 
     | 
    
         
            +
                          new_hash[key] = values.slice!(0)
         
     | 
| 
      
 37 
     | 
    
         
            +
                          new_hash
         
     | 
| 
      
 38 
     | 
    
         
            +
                        end
         
     | 
| 
      
 39 
     | 
    
         
            +
                      end
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                  
         
     | 
| 
      
 43 
     | 
    
         
            +
                  class XmlParser < Hash
         
     | 
| 
      
 44 
     | 
    
         
            +
                    include Typecasting
         
     | 
| 
      
 45 
     | 
    
         
            +
                    
         
     | 
| 
      
 46 
     | 
    
         
            +
                    class << self
         
     | 
| 
      
 47 
     | 
    
         
            +
                      attr_accessor :parsing_library
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
                    
         
     | 
| 
      
 50 
     | 
    
         
            +
                    attr_reader :body, :xml_in, :root
         
     | 
| 
      
 51 
     | 
    
         
            +
                    
         
     | 
| 
      
 52 
     | 
    
         
            +
                    def initialize(body)
         
     | 
| 
      
 53 
     | 
    
         
            +
                      @body = body
         
     | 
| 
      
 54 
     | 
    
         
            +
                      unless body.strip.empty?
         
     | 
| 
      
 55 
     | 
    
         
            +
                        parse
         
     | 
| 
      
 56 
     | 
    
         
            +
                        set_root
         
     | 
| 
      
 57 
     | 
    
         
            +
                        typecast_xml_in
         
     | 
| 
      
 58 
     | 
    
         
            +
                      end
         
     | 
| 
      
 59 
     | 
    
         
            +
                    end
         
     | 
| 
      
 60 
     | 
    
         
            +
                  
         
     | 
| 
      
 61 
     | 
    
         
            +
                    private
         
     | 
| 
      
 62 
     | 
    
         
            +
                  
         
     | 
| 
      
 63 
     | 
    
         
            +
                      def parse
         
     | 
| 
      
 64 
     | 
    
         
            +
                        @xml_in = self.class.parsing_library.xml_in(body, parsing_options)
         
     | 
| 
      
 65 
     | 
    
         
            +
                      end
         
     | 
| 
      
 66 
     | 
    
         
            +
                      
         
     | 
| 
      
 67 
     | 
    
         
            +
                      def parsing_options
         
     | 
| 
      
 68 
     | 
    
         
            +
                        {
         
     | 
| 
      
 69 
     | 
    
         
            +
                          # Includes the enclosing tag as the top level key
         
     | 
| 
      
 70 
     | 
    
         
            +
                          'keeproot'      => true, 
         
     | 
| 
      
 71 
     | 
    
         
            +
                          # Makes tag value available via the '__content__' key
         
     | 
| 
      
 72 
     | 
    
         
            +
                          'contentkey'    => '__content__', 
         
     | 
| 
      
 73 
     | 
    
         
            +
                          # Always parse tags into a hash, even when there are no attributes 
         
     | 
| 
      
 74 
     | 
    
         
            +
                          # (unless there is also no value, in which case it is nil)
         
     | 
| 
      
 75 
     | 
    
         
            +
                          'forcecontent'  => true, 
         
     | 
| 
      
 76 
     | 
    
         
            +
                          # If a tag is empty, makes its content nil
         
     | 
| 
      
 77 
     | 
    
         
            +
                          'suppressempty' => nil,
         
     | 
| 
      
 78 
     | 
    
         
            +
                          # Force nested elements to be put into an array, even if there is only one of them
         
     | 
| 
      
 79 
     | 
    
         
            +
                          'forcearray'    => ['Contents', 'Bucket', 'Grant']
         
     | 
| 
      
 80 
     | 
    
         
            +
                        }
         
     | 
| 
      
 81 
     | 
    
         
            +
                      end
         
     | 
| 
      
 82 
     | 
    
         
            +
                      
         
     | 
| 
      
 83 
     | 
    
         
            +
                      def set_root
         
     | 
| 
      
 84 
     | 
    
         
            +
                        @root = @xml_in.keys.first.underscore
         
     | 
| 
      
 85 
     | 
    
         
            +
                      end
         
     | 
| 
      
 86 
     | 
    
         
            +
                      
         
     | 
| 
      
 87 
     | 
    
         
            +
                      def typecast_xml_in
         
     | 
| 
      
 88 
     | 
    
         
            +
                        typecast_xml = {}
         
     | 
| 
      
 89 
     | 
    
         
            +
                        @xml_in.dup.each do |key, value| # Some typecasting is destructive so we dup
         
     | 
| 
      
 90 
     | 
    
         
            +
                          typecast_xml[key.underscore] = typecast(value)
         
     | 
| 
      
 91 
     | 
    
         
            +
                        end
         
     | 
| 
      
 92 
     | 
    
         
            +
                        # An empty body will try to update with a string so only update if the result is a hash
         
     | 
| 
      
 93 
     | 
    
         
            +
                        update(typecast_xml[root]) if typecast_xml[root].is_a?(Hash)
         
     | 
| 
      
 94 
     | 
    
         
            +
                      end
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
              end
         
     | 
| 
      
 98 
     | 
    
         
            +
            end
         
     | 
| 
      
 99 
     | 
    
         
            +
            #:startdoc:
         
     | 
| 
         @@ -0,0 +1,180 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #:stopdoc:
         
     | 
| 
      
 2 
     | 
    
         
            +
            module AWS
         
     | 
| 
      
 3 
     | 
    
         
            +
              module S3
         
     | 
| 
      
 4 
     | 
    
         
            +
                class Base
         
     | 
| 
      
 5 
     | 
    
         
            +
                  class Response < String  
         
     | 
| 
      
 6 
     | 
    
         
            +
                    attr_reader :response, :body, :parsed
         
     | 
| 
      
 7 
     | 
    
         
            +
                    def initialize(response)
         
     | 
| 
      
 8 
     | 
    
         
            +
                      @response = response
         
     | 
| 
      
 9 
     | 
    
         
            +
                      @body     = response.body.to_s
         
     | 
| 
      
 10 
     | 
    
         
            +
                      super(body)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
                
         
     | 
| 
      
 13 
     | 
    
         
            +
                    def headers
         
     | 
| 
      
 14 
     | 
    
         
            +
                      headers = {}
         
     | 
| 
      
 15 
     | 
    
         
            +
                      response.each do |header, value|
         
     | 
| 
      
 16 
     | 
    
         
            +
                        headers[header] = value
         
     | 
| 
      
 17 
     | 
    
         
            +
                      end
         
     | 
| 
      
 18 
     | 
    
         
            +
                      headers
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                    memoized :headers
         
     | 
| 
      
 21 
     | 
    
         
            +
                
         
     | 
| 
      
 22 
     | 
    
         
            +
                    def [](header)
         
     | 
| 
      
 23 
     | 
    
         
            +
                      headers[header]
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
                
         
     | 
| 
      
 26 
     | 
    
         
            +
                    def each(&block)
         
     | 
| 
      
 27 
     | 
    
         
            +
                      headers.each(&block)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
                
         
     | 
| 
      
 30 
     | 
    
         
            +
                    def code
         
     | 
| 
      
 31 
     | 
    
         
            +
                      response.code.to_i
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
                
         
     | 
| 
      
 34 
     | 
    
         
            +
                    {:success      => 200..299, :redirect     => 300..399,
         
     | 
| 
      
 35 
     | 
    
         
            +
                     :client_error => 400..499, :server_error => 500..599}.each do |result, code_range|
         
     | 
| 
      
 36 
     | 
    
         
            +
                      class_eval(<<-EVAL, __FILE__, __LINE__)
         
     | 
| 
      
 37 
     | 
    
         
            +
                        def #{result}? 
         
     | 
| 
      
 38 
     | 
    
         
            +
                          return false unless response
         
     | 
| 
      
 39 
     | 
    
         
            +
                          (#{code_range}).include? code
         
     | 
| 
      
 40 
     | 
    
         
            +
                        end
         
     | 
| 
      
 41 
     | 
    
         
            +
                      EVAL
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
                
         
     | 
| 
      
 44 
     | 
    
         
            +
                    def error?
         
     | 
| 
      
 45 
     | 
    
         
            +
                      !success? && response['content-type'] == 'application/xml' && parsed.root == 'error'
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end
         
     | 
| 
      
 47 
     | 
    
         
            +
                
         
     | 
| 
      
 48 
     | 
    
         
            +
                    def error
         
     | 
| 
      
 49 
     | 
    
         
            +
                      Error.new(parsed, self)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                    memoized :error
         
     | 
| 
      
 52 
     | 
    
         
            +
                
         
     | 
| 
      
 53 
     | 
    
         
            +
                    def parsed
         
     | 
| 
      
 54 
     | 
    
         
            +
                      # XmlSimple is picky about what kind of object it parses, so we pass in body rather than self
         
     | 
| 
      
 55 
     | 
    
         
            +
                      Parsing::XmlParser.new(body)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
                    memoized :parsed
         
     | 
| 
      
 58 
     | 
    
         
            +
                
         
     | 
| 
      
 59 
     | 
    
         
            +
                    def inspect
         
     | 
| 
      
 60 
     | 
    
         
            +
                      "#<%s:0x%s %s %s>" % [self.class, object_id, response.code, response.message]
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
                
         
     | 
| 
      
 65 
     | 
    
         
            +
                class Bucket  
         
     | 
| 
      
 66 
     | 
    
         
            +
                  class Response < Base::Response
         
     | 
| 
      
 67 
     | 
    
         
            +
                    def bucket
         
     | 
| 
      
 68 
     | 
    
         
            +
                      parsed
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
              
         
     | 
| 
      
 73 
     | 
    
         
            +
                class S3Object
         
     | 
| 
      
 74 
     | 
    
         
            +
                  class Response < Base::Response
         
     | 
| 
      
 75 
     | 
    
         
            +
                    def etag
         
     | 
| 
      
 76 
     | 
    
         
            +
                      headers['etag'][1...-1]
         
     | 
| 
      
 77 
     | 
    
         
            +
                    end
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                class Service
         
     | 
| 
      
 82 
     | 
    
         
            +
                  class Response < Base::Response
         
     | 
| 
      
 83 
     | 
    
         
            +
                    def empty?
         
     | 
| 
      
 84 
     | 
    
         
            +
                      parsed['buckets'].nil?
         
     | 
| 
      
 85 
     | 
    
         
            +
                    end
         
     | 
| 
      
 86 
     | 
    
         
            +
              
         
     | 
| 
      
 87 
     | 
    
         
            +
                    def buckets
         
     | 
| 
      
 88 
     | 
    
         
            +
                      parsed['buckets']['bucket'] || []
         
     | 
| 
      
 89 
     | 
    
         
            +
                    end
         
     | 
| 
      
 90 
     | 
    
         
            +
                  end
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
                
         
     | 
| 
      
 93 
     | 
    
         
            +
                module ACL
         
     | 
| 
      
 94 
     | 
    
         
            +
                  class Policy
         
     | 
| 
      
 95 
     | 
    
         
            +
                    class Response < Base::Response
         
     | 
| 
      
 96 
     | 
    
         
            +
                      alias_method :policy, :parsed
         
     | 
| 
      
 97 
     | 
    
         
            +
                    end
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
                
         
     | 
| 
      
 101 
     | 
    
         
            +
                # Requests whose response code is between 300 and 599 and contain an <Error></Error> in their body
         
     | 
| 
      
 102 
     | 
    
         
            +
                # are wrapped in an Error::Response. This Error::Response contains an Error object which raises an exception
         
     | 
| 
      
 103 
     | 
    
         
            +
                # that corresponds to the error in the response body. The exception object contains the ErrorResponse, so
         
     | 
| 
      
 104 
     | 
    
         
            +
                # in all cases where a request happens, you can rescue ResponseError and have access to the ErrorResponse and
         
     | 
| 
      
 105 
     | 
    
         
            +
                # its Error object which contains information about the ResponseError.
         
     | 
| 
      
 106 
     | 
    
         
            +
                #
         
     | 
| 
      
 107 
     | 
    
         
            +
                #   begin
         
     | 
| 
      
 108 
     | 
    
         
            +
                #     Bucket.create(..)
         
     | 
| 
      
 109 
     | 
    
         
            +
                #   rescue ResponseError => exception
         
     | 
| 
      
 110 
     | 
    
         
            +
                #    exception.response
         
     | 
| 
      
 111 
     | 
    
         
            +
                #    # => <Error::Response>
         
     | 
| 
      
 112 
     | 
    
         
            +
                #    exception.response.error
         
     | 
| 
      
 113 
     | 
    
         
            +
                #    # => <Error>
         
     | 
| 
      
 114 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 115 
     | 
    
         
            +
                class Error
         
     | 
| 
      
 116 
     | 
    
         
            +
                  class Response < Base::Response
         
     | 
| 
      
 117 
     | 
    
         
            +
                    def error? 
         
     | 
| 
      
 118 
     | 
    
         
            +
                      true
         
     | 
| 
      
 119 
     | 
    
         
            +
                    end
         
     | 
| 
      
 120 
     | 
    
         
            +
                  
         
     | 
| 
      
 121 
     | 
    
         
            +
                    def inspect
         
     | 
| 
      
 122 
     | 
    
         
            +
                      "#<%s:0x%s %s %s: '%s'>" % [self.class.name, object_id, response.code, error.code, error.message]
         
     | 
| 
      
 123 
     | 
    
         
            +
                    end
         
     | 
| 
      
 124 
     | 
    
         
            +
                  end
         
     | 
| 
      
 125 
     | 
    
         
            +
                end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                # Guess response class name from current class name. If the guessed response class doesn't exist
         
     | 
| 
      
 128 
     | 
    
         
            +
                # do the same thing to the current class's parent class, up the inheritance heirarchy until either
         
     | 
| 
      
 129 
     | 
    
         
            +
                # a response class is found or until we get to the top of the heirarchy in which case we just use 
         
     | 
| 
      
 130 
     | 
    
         
            +
                # the the Base response class.
         
     | 
| 
      
 131 
     | 
    
         
            +
                #
         
     | 
| 
      
 132 
     | 
    
         
            +
                # Important: This implemantation assumes that the Base class has a corresponding Base::Response.
         
     | 
| 
      
 133 
     | 
    
         
            +
                class FindResponseClass #:nodoc:
         
     | 
| 
      
 134 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 135 
     | 
    
         
            +
                    def for(start)
         
     | 
| 
      
 136 
     | 
    
         
            +
                      new(start).find
         
     | 
| 
      
 137 
     | 
    
         
            +
                    end
         
     | 
| 
      
 138 
     | 
    
         
            +
                  end
         
     | 
| 
      
 139 
     | 
    
         
            +
              
         
     | 
| 
      
 140 
     | 
    
         
            +
                  def initialize(start)
         
     | 
| 
      
 141 
     | 
    
         
            +
                    @container     = AWS::S3
         
     | 
| 
      
 142 
     | 
    
         
            +
                    @current_class = start
         
     | 
| 
      
 143 
     | 
    
         
            +
                  end
         
     | 
| 
      
 144 
     | 
    
         
            +
              
         
     | 
| 
      
 145 
     | 
    
         
            +
                  def find
         
     | 
| 
      
 146 
     | 
    
         
            +
                    self.current_class = current_class.superclass until response_class_found?            
         
     | 
| 
      
 147 
     | 
    
         
            +
                    target.const_get(class_to_find)
         
     | 
| 
      
 148 
     | 
    
         
            +
                  end
         
     | 
| 
      
 149 
     | 
    
         
            +
              
         
     | 
| 
      
 150 
     | 
    
         
            +
                  private
         
     | 
| 
      
 151 
     | 
    
         
            +
                    attr_reader :container
         
     | 
| 
      
 152 
     | 
    
         
            +
                    attr_accessor :current_class
         
     | 
| 
      
 153 
     | 
    
         
            +
                    
         
     | 
| 
      
 154 
     | 
    
         
            +
                    def target
         
     | 
| 
      
 155 
     | 
    
         
            +
                      container.const_get(current_name)
         
     | 
| 
      
 156 
     | 
    
         
            +
                    end
         
     | 
| 
      
 157 
     | 
    
         
            +
                    
         
     | 
| 
      
 158 
     | 
    
         
            +
                    def target?
         
     | 
| 
      
 159 
     | 
    
         
            +
                      container.const_defined?(current_name)
         
     | 
| 
      
 160 
     | 
    
         
            +
                    end
         
     | 
| 
      
 161 
     | 
    
         
            +
                    
         
     | 
| 
      
 162 
     | 
    
         
            +
                    def response_class_found?
         
     | 
| 
      
 163 
     | 
    
         
            +
                      target? && target.const_defined?(class_to_find)
         
     | 
| 
      
 164 
     | 
    
         
            +
                    end
         
     | 
| 
      
 165 
     | 
    
         
            +
                    
         
     | 
| 
      
 166 
     | 
    
         
            +
                    def class_to_find
         
     | 
| 
      
 167 
     | 
    
         
            +
                      :Response
         
     | 
| 
      
 168 
     | 
    
         
            +
                    end
         
     | 
| 
      
 169 
     | 
    
         
            +
                    
         
     | 
| 
      
 170 
     | 
    
         
            +
                    def current_name
         
     | 
| 
      
 171 
     | 
    
         
            +
                      truncate(current_class)
         
     | 
| 
      
 172 
     | 
    
         
            +
                    end
         
     | 
| 
      
 173 
     | 
    
         
            +
                    
         
     | 
| 
      
 174 
     | 
    
         
            +
                    def truncate(klass)
         
     | 
| 
      
 175 
     | 
    
         
            +
                      klass.name[/[^:]+$/]
         
     | 
| 
      
 176 
     | 
    
         
            +
                    end
         
     | 
| 
      
 177 
     | 
    
         
            +
                  end
         
     | 
| 
      
 178 
     | 
    
         
            +
              end
         
     | 
| 
      
 179 
     | 
    
         
            +
            end
         
     | 
| 
      
 180 
     | 
    
         
            +
            #:startdoc:
         
     | 
| 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module AWS
         
     | 
| 
      
 2 
     | 
    
         
            +
              module S3
         
     | 
| 
      
 3 
     | 
    
         
            +
                # The service lets you find out general information about your account, like what buckets you have. 
         
     | 
| 
      
 4 
     | 
    
         
            +
                # 
         
     | 
| 
      
 5 
     | 
    
         
            +
                #   Service.buckets
         
     | 
| 
      
 6 
     | 
    
         
            +
                #   # => []
         
     | 
| 
      
 7 
     | 
    
         
            +
                class Service < Base
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @@response = nil #:nodoc:
         
     | 
| 
      
 9 
     | 
    
         
            +
                  
         
     | 
| 
      
 10 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 11 
     | 
    
         
            +
                    # List all your buckets.
         
     | 
| 
      
 12 
     | 
    
         
            +
                    #
         
     | 
| 
      
 13 
     | 
    
         
            +
                    #   Service.buckets
         
     | 
| 
      
 14 
     | 
    
         
            +
                    #   # => []
         
     | 
| 
      
 15 
     | 
    
         
            +
                    #
         
     | 
| 
      
 16 
     | 
    
         
            +
                    # For performance reasons, the bucket list will be cached. If you want avoid all caching, pass the <tt>:reload</tt> 
         
     | 
| 
      
 17 
     | 
    
         
            +
                    # as an argument:
         
     | 
| 
      
 18 
     | 
    
         
            +
                    #
         
     | 
| 
      
 19 
     | 
    
         
            +
                    #   Service.buckets(:reload)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    def buckets
         
     | 
| 
      
 21 
     | 
    
         
            +
                      response = get('/')
         
     | 
| 
      
 22 
     | 
    
         
            +
                      if response.empty?
         
     | 
| 
      
 23 
     | 
    
         
            +
                        []
         
     | 
| 
      
 24 
     | 
    
         
            +
                      else
         
     | 
| 
      
 25 
     | 
    
         
            +
                        response.buckets.map {|attributes| Bucket.new(attributes)}
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                    memoized :buckets
         
     | 
| 
      
 29 
     | 
    
         
            +
                    
         
     | 
| 
      
 30 
     | 
    
         
            +
                    # Sometimes methods that make requests to the S3 servers return some object, like a Bucket or an S3Object. 
         
     | 
| 
      
 31 
     | 
    
         
            +
                    # Othertimes they return just <tt>true</tt>. Other times they raise an exception that you may want to rescue. Despite all these 
         
     | 
| 
      
 32 
     | 
    
         
            +
                    # possible outcomes, every method that makes a request stores its response object for you in Service.response. You can always 
         
     | 
| 
      
 33 
     | 
    
         
            +
                    # get to the last request's response via Service.response.
         
     | 
| 
      
 34 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 35 
     | 
    
         
            +
                    #   objects = Bucket.objects('jukebox')
         
     | 
| 
      
 36 
     | 
    
         
            +
                    #   Service.response.success?
         
     | 
| 
      
 37 
     | 
    
         
            +
                    #   # => true
         
     | 
| 
      
 38 
     | 
    
         
            +
                    #
         
     | 
| 
      
 39 
     | 
    
         
            +
                    # This is also useful when an error exception is raised in the console which you weren't expecting. You can 
         
     | 
| 
      
 40 
     | 
    
         
            +
                    # root around in the response to get more details of what might have gone wrong.
         
     | 
| 
      
 41 
     | 
    
         
            +
                    def response
         
     | 
| 
      
 42 
     | 
    
         
            +
                      @@response
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    
         
     | 
| 
      
 45 
     | 
    
         
            +
                    def response=(response) #:nodoc:
         
     | 
| 
      
 46 
     | 
    
         
            +
                      @@response = response
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/aws/s3.rb
    ADDED
    
    | 
         @@ -0,0 +1,61 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'base64'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'cgi'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'uri'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'openssl'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'digest/sha1'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'net/https'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'time'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'date'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'open-uri'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            $:.unshift(File.dirname(__FILE__))
         
     | 
| 
      
 12 
     | 
    
         
            +
            require 's3/extensions'
         
     | 
| 
      
 13 
     | 
    
         
            +
            require_library_or_gem 'builder' unless defined? Builder
         
     | 
| 
      
 14 
     | 
    
         
            +
            require_library_or_gem 'mime/types' unless defined? MIME::Types
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            require 's3/base'
         
     | 
| 
      
 17 
     | 
    
         
            +
            require 's3/version'
         
     | 
| 
      
 18 
     | 
    
         
            +
            require 's3/parsing'
         
     | 
| 
      
 19 
     | 
    
         
            +
            require 's3/acl'
         
     | 
| 
      
 20 
     | 
    
         
            +
            require 's3/logging'
         
     | 
| 
      
 21 
     | 
    
         
            +
            require 's3/bittorrent'
         
     | 
| 
      
 22 
     | 
    
         
            +
            require 's3/service'
         
     | 
| 
      
 23 
     | 
    
         
            +
            require 's3/owner'
         
     | 
| 
      
 24 
     | 
    
         
            +
            require 's3/bucket'
         
     | 
| 
      
 25 
     | 
    
         
            +
            require 's3/object'
         
     | 
| 
      
 26 
     | 
    
         
            +
            require 's3/error'
         
     | 
| 
      
 27 
     | 
    
         
            +
            require 's3/exceptions'
         
     | 
| 
      
 28 
     | 
    
         
            +
            require 's3/connection'
         
     | 
| 
      
 29 
     | 
    
         
            +
            require 's3/authentication'
         
     | 
| 
      
 30 
     | 
    
         
            +
            require 's3/response'
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            AWS::S3::Base.class_eval do
         
     | 
| 
      
 33 
     | 
    
         
            +
              include AWS::S3::Connection::Management
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            AWS::S3::Bucket.class_eval do
         
     | 
| 
      
 37 
     | 
    
         
            +
              include AWS::S3::Logging::Management
         
     | 
| 
      
 38 
     | 
    
         
            +
              include AWS::S3::ACL::Bucket
         
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            AWS::S3::S3Object.class_eval do
         
     | 
| 
      
 42 
     | 
    
         
            +
              include AWS::S3::ACL::S3Object
         
     | 
| 
      
 43 
     | 
    
         
            +
              include AWS::S3::BitTorrent
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            require_library_or_gem 'xmlsimple' unless defined? XmlSimple
         
     | 
| 
      
 47 
     | 
    
         
            +
            # If libxml is installed, we use the FasterXmlSimple library, that provides most of the functionality of XmlSimple
         
     | 
| 
      
 48 
     | 
    
         
            +
            # except it uses the xml/libxml library for xml parsing (rather than REXML). If libxml isn't installed, we just fall back on
         
     | 
| 
      
 49 
     | 
    
         
            +
            # XmlSimple.
         
     | 
| 
      
 50 
     | 
    
         
            +
            AWS::S3::Parsing.parser =
         
     | 
| 
      
 51 
     | 
    
         
            +
              begin
         
     | 
| 
      
 52 
     | 
    
         
            +
                require_library_or_gem 'xml/libxml'
         
     | 
| 
      
 53 
     | 
    
         
            +
                # Older version of libxml aren't stable (bus error when requesting attributes that don't exist) so we
         
     | 
| 
      
 54 
     | 
    
         
            +
                # have to use a version greater than '0.3.8.2'.
         
     | 
| 
      
 55 
     | 
    
         
            +
                raise LoadError unless XML::Parser::VERSION > '0.3.8.2'
         
     | 
| 
      
 56 
     | 
    
         
            +
                $:.push(File.join(File.dirname(__FILE__), '..', '..', 'support', 'faster-xml-simple', 'lib'))
         
     | 
| 
      
 57 
     | 
    
         
            +
                require_library_or_gem 'faster_xml_simple' 
         
     | 
| 
      
 58 
     | 
    
         
            +
                FasterXmlSimple
         
     | 
| 
      
 59 
     | 
    
         
            +
              rescue LoadError
         
     | 
| 
      
 60 
     | 
    
         
            +
                XmlSimple
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
         @@ -0,0 +1,187 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # 
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Copyright (c) 2006 Michael Koziarski
         
     | 
| 
      
 3 
     | 
    
         
            +
            # 
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Permission is hereby granted, free of charge, to any person obtaining a copy of
         
     | 
| 
      
 5 
     | 
    
         
            +
            # this software and associated documentation files (the "Software"), to deal in the
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Software without restriction, including without limitation the rights to use,
         
     | 
| 
      
 7 
     | 
    
         
            +
            # copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
         
     | 
| 
      
 8 
     | 
    
         
            +
            # Software, and to permit persons to whom the Software is furnished to do so,
         
     | 
| 
      
 9 
     | 
    
         
            +
            # subject to the following conditions:
         
     | 
| 
      
 10 
     | 
    
         
            +
            # 
         
     | 
| 
      
 11 
     | 
    
         
            +
            # The above copyright notice and this permission notice shall be included in all
         
     | 
| 
      
 12 
     | 
    
         
            +
            # copies or substantial portions of the Software.
         
     | 
| 
      
 13 
     | 
    
         
            +
            # 
         
     | 
| 
      
 14 
     | 
    
         
            +
            # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 15 
     | 
    
         
            +
            # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
         
     | 
| 
      
 16 
     | 
    
         
            +
            # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
         
     | 
| 
      
 17 
     | 
    
         
            +
            # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
         
     | 
| 
      
 18 
     | 
    
         
            +
            # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         
     | 
| 
      
 19 
     | 
    
         
            +
            # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 22 
     | 
    
         
            +
            require 'xml/libxml'
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            class FasterXmlSimple
         
     | 
| 
      
 25 
     | 
    
         
            +
              Version = '0.5.0'
         
     | 
| 
      
 26 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 27 
     | 
    
         
            +
                # Take an string containing XML, and returns a hash representing that 
         
     | 
| 
      
 28 
     | 
    
         
            +
                # XML document.  For example:
         
     | 
| 
      
 29 
     | 
    
         
            +
                # 
         
     | 
| 
      
 30 
     | 
    
         
            +
                #   FasterXmlSimple.xml_in("<root><something>1</something></root>")
         
     | 
| 
      
 31 
     | 
    
         
            +
                #   {"root"=>{"something"=>{"__content__"=>"1"}}}
         
     | 
| 
      
 32 
     | 
    
         
            +
                #
         
     | 
| 
      
 33 
     | 
    
         
            +
                # Faster XML Simple is designed to be a drop in replacement for the xml_in
         
     | 
| 
      
 34 
     | 
    
         
            +
                # functionality of http://xml-simple.rubyforge.org
         
     | 
| 
      
 35 
     | 
    
         
            +
                #
         
     | 
| 
      
 36 
     | 
    
         
            +
                # The following options are supported:
         
     | 
| 
      
 37 
     | 
    
         
            +
                # 
         
     | 
| 
      
 38 
     | 
    
         
            +
                # * <tt>contentkey</tt>: The key to use for the content of text elements,
         
     | 
| 
      
 39 
     | 
    
         
            +
                #   defaults to '\_\_content__'
         
     | 
| 
      
 40 
     | 
    
         
            +
                # * <tt>forcearray</tt>: The list of elements which should always be returned
         
     | 
| 
      
 41 
     | 
    
         
            +
                #   as arrays.  Under normal circumstances single element arrays are inlined.
         
     | 
| 
      
 42 
     | 
    
         
            +
                # * <tt>suppressempty</tt>: The value to return for empty elements, pass +true+
         
     | 
| 
      
 43 
     | 
    
         
            +
                #   to remove empty elements entirely.
         
     | 
| 
      
 44 
     | 
    
         
            +
                # * <tt>keeproot</tt>:  By default the hash returned has a single key with the
         
     | 
| 
      
 45 
     | 
    
         
            +
                #   name of the root element.  If the name of the root element isn't 
         
     | 
| 
      
 46 
     | 
    
         
            +
                #   interesting to you, pass +false+. 
         
     | 
| 
      
 47 
     | 
    
         
            +
                # * <tt>forcecontent</tt>:  By default a text element with no attributes, will 
         
     | 
| 
      
 48 
     | 
    
         
            +
                #   be collapsed to just a string instead of a hash with a single key.  
         
     | 
| 
      
 49 
     | 
    
         
            +
                #   Pass +true+ to prevent this.
         
     | 
| 
      
 50 
     | 
    
         
            +
                #
         
     | 
| 
      
 51 
     | 
    
         
            +
                #
         
     | 
| 
      
 52 
     | 
    
         
            +
                def xml_in(string, options={})
         
     | 
| 
      
 53 
     | 
    
         
            +
                  new(string, options).out
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
              
         
     | 
| 
      
 57 
     | 
    
         
            +
              def initialize(string, options) #:nodoc:
         
     | 
| 
      
 58 
     | 
    
         
            +
                @doc     = parse(string)
         
     | 
| 
      
 59 
     | 
    
         
            +
                @options = default_options.merge options
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
              
         
     | 
| 
      
 62 
     | 
    
         
            +
              def out #:nodoc:
         
     | 
| 
      
 63 
     | 
    
         
            +
                if @options['keeproot']
         
     | 
| 
      
 64 
     | 
    
         
            +
                  {@doc.root.name => collapse(@doc.root)}
         
     | 
| 
      
 65 
     | 
    
         
            +
                else
         
     | 
| 
      
 66 
     | 
    
         
            +
                  collapse(@doc.root)
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
      
 69 
     | 
    
         
            +
              
         
     | 
| 
      
 70 
     | 
    
         
            +
              private
         
     | 
| 
      
 71 
     | 
    
         
            +
                def default_options
         
     | 
| 
      
 72 
     | 
    
         
            +
                  {'contentkey' => '__content__', 'forcearray' => [], 'keeproot'=>true}
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
              
         
     | 
| 
      
 75 
     | 
    
         
            +
                def collapse(element)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  result = hash_of_attributes(element) 
         
     | 
| 
      
 77 
     | 
    
         
            +
                  if text_node? element
         
     | 
| 
      
 78 
     | 
    
         
            +
                    text = collapse_text(element)
         
     | 
| 
      
 79 
     | 
    
         
            +
                    result[content_key] = text if text =~ /\S/
         
     | 
| 
      
 80 
     | 
    
         
            +
                  elsif element.children?
         
     | 
| 
      
 81 
     | 
    
         
            +
                    element.inject(result) do |hash, child|
         
     | 
| 
      
 82 
     | 
    
         
            +
                      unless child.text?
         
     | 
| 
      
 83 
     | 
    
         
            +
                        child_result = collapse(child) 
         
     | 
| 
      
 84 
     | 
    
         
            +
                        (hash[child.name] ||= []) << child_result
         
     | 
| 
      
 85 
     | 
    
         
            +
                      end
         
     | 
| 
      
 86 
     | 
    
         
            +
                      hash
         
     | 
| 
      
 87 
     | 
    
         
            +
                    end
         
     | 
| 
      
 88 
     | 
    
         
            +
                  end
         
     | 
| 
      
 89 
     | 
    
         
            +
                  if result.empty?
         
     | 
| 
      
 90 
     | 
    
         
            +
                    return empty_element
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
                  # Compact them to ensure it complies with the user's requests
         
     | 
| 
      
 93 
     | 
    
         
            +
                  inline_single_element_arrays(result) 
         
     | 
| 
      
 94 
     | 
    
         
            +
                  remove_empty_elements(result) if suppress_empty?
         
     | 
| 
      
 95 
     | 
    
         
            +
                  if content_only?(result) && !force_content?
         
     | 
| 
      
 96 
     | 
    
         
            +
                    result[content_key]
         
     | 
| 
      
 97 
     | 
    
         
            +
                  else
         
     | 
| 
      
 98 
     | 
    
         
            +
                    result
         
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
                
         
     | 
| 
      
 102 
     | 
    
         
            +
                def content_only?(result)
         
     | 
| 
      
 103 
     | 
    
         
            +
                  result.keys == [content_key]
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
              
         
     | 
| 
      
 106 
     | 
    
         
            +
                def content_key
         
     | 
| 
      
 107 
     | 
    
         
            +
                  @options['contentkey']
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
              
         
     | 
| 
      
 110 
     | 
    
         
            +
                def force_array?(key_name)
         
     | 
| 
      
 111 
     | 
    
         
            +
                  Array(@options['forcearray']).include?(key_name)
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
              
         
     | 
| 
      
 114 
     | 
    
         
            +
                def inline_single_element_arrays(result)
         
     | 
| 
      
 115 
     | 
    
         
            +
                  result.each do |key, value|
         
     | 
| 
      
 116 
     | 
    
         
            +
                    if value.size == 1 && value.is_a?(Array) && !force_array?(key)
         
     | 
| 
      
 117 
     | 
    
         
            +
                      result[key] = value.first
         
     | 
| 
      
 118 
     | 
    
         
            +
                    end
         
     | 
| 
      
 119 
     | 
    
         
            +
                  end    
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
              
         
     | 
| 
      
 122 
     | 
    
         
            +
                def remove_empty_elements(result)
         
     | 
| 
      
 123 
     | 
    
         
            +
                  result.each do |key, value|
         
     | 
| 
      
 124 
     | 
    
         
            +
                    if value == empty_element
         
     | 
| 
      
 125 
     | 
    
         
            +
                      result.delete key
         
     | 
| 
      
 126 
     | 
    
         
            +
                    end
         
     | 
| 
      
 127 
     | 
    
         
            +
                  end
         
     | 
| 
      
 128 
     | 
    
         
            +
                end
         
     | 
| 
      
 129 
     | 
    
         
            +
                
         
     | 
| 
      
 130 
     | 
    
         
            +
                def suppress_empty?
         
     | 
| 
      
 131 
     | 
    
         
            +
                  @options['suppressempty'] == true
         
     | 
| 
      
 132 
     | 
    
         
            +
                end
         
     | 
| 
      
 133 
     | 
    
         
            +
                 
         
     | 
| 
      
 134 
     | 
    
         
            +
                def empty_element
         
     | 
| 
      
 135 
     | 
    
         
            +
                  if !@options.has_key? 'suppressempty'
         
     | 
| 
      
 136 
     | 
    
         
            +
                    {}
         
     | 
| 
      
 137 
     | 
    
         
            +
                  else
         
     | 
| 
      
 138 
     | 
    
         
            +
                    @options['suppressempty']
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                # removes the content if it's nothing but blanks,  prevents
         
     | 
| 
      
 143 
     | 
    
         
            +
                # the hash being polluted with lots of content like "\n\t\t\t" 
         
     | 
| 
      
 144 
     | 
    
         
            +
                def suppress_empty_content(result)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  result.delete content_key if result[content_key] !~ /\S/ 
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
              
         
     | 
| 
      
 148 
     | 
    
         
            +
                def force_content?
         
     | 
| 
      
 149 
     | 
    
         
            +
                  @options['forcecontent']
         
     | 
| 
      
 150 
     | 
    
         
            +
                end
         
     | 
| 
      
 151 
     | 
    
         
            +
              
         
     | 
| 
      
 152 
     | 
    
         
            +
                # a text node is one with 1 or more child nodes which are
         
     | 
| 
      
 153 
     | 
    
         
            +
                # text nodes, and no non-text children, there's no sensible
         
     | 
| 
      
 154 
     | 
    
         
            +
                # way to support nodes which are text and markup like:
         
     | 
| 
      
 155 
     | 
    
         
            +
                # <p>Something <b>Bold</b> </p>
         
     | 
| 
      
 156 
     | 
    
         
            +
                def text_node?(element)
         
     | 
| 
      
 157 
     | 
    
         
            +
                  !element.text? && element.all? {|c| c.text?}
         
     | 
| 
      
 158 
     | 
    
         
            +
                end
         
     | 
| 
      
 159 
     | 
    
         
            +
              
         
     | 
| 
      
 160 
     | 
    
         
            +
                # takes a text node, and collapses it into a string
         
     | 
| 
      
 161 
     | 
    
         
            +
                def collapse_text(element)
         
     | 
| 
      
 162 
     | 
    
         
            +
                  element.map {|c| c.content } * ''
         
     | 
| 
      
 163 
     | 
    
         
            +
                end
         
     | 
| 
      
 164 
     | 
    
         
            +
              
         
     | 
| 
      
 165 
     | 
    
         
            +
                def hash_of_attributes(element)
         
     | 
| 
      
 166 
     | 
    
         
            +
                  result = {}
         
     | 
| 
      
 167 
     | 
    
         
            +
                  element.each_attr do |attribute| 
         
     | 
| 
      
 168 
     | 
    
         
            +
                    name = attribute.name
         
     | 
| 
      
 169 
     | 
    
         
            +
                    name = [attribute.ns, attribute.name].join(':') if attribute.ns?
         
     | 
| 
      
 170 
     | 
    
         
            +
                    result[name] = attribute.value 
         
     | 
| 
      
 171 
     | 
    
         
            +
                  end
         
     | 
| 
      
 172 
     | 
    
         
            +
                  result
         
     | 
| 
      
 173 
     | 
    
         
            +
                end
         
     | 
| 
      
 174 
     | 
    
         
            +
              
         
     | 
| 
      
 175 
     | 
    
         
            +
                def parse(string)
         
     | 
| 
      
 176 
     | 
    
         
            +
                  if string == ''
         
     | 
| 
      
 177 
     | 
    
         
            +
                    string = ' '
         
     | 
| 
      
 178 
     | 
    
         
            +
                  end
         
     | 
| 
      
 179 
     | 
    
         
            +
                  XML::Parser.string(string).parse
         
     | 
| 
      
 180 
     | 
    
         
            +
                end
         
     | 
| 
      
 181 
     | 
    
         
            +
            end
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
            class XmlSimple # :nodoc:
         
     | 
| 
      
 184 
     | 
    
         
            +
              def self.xml_in(*args)
         
     | 
| 
      
 185 
     | 
    
         
            +
                FasterXmlSimple.xml_in *args
         
     | 
| 
      
 186 
     | 
    
         
            +
              end
         
     | 
| 
      
 187 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/test_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class RegressionTest < FasterXSTest
         
     | 
| 
      
 4 
     | 
    
         
            +
              def test_content_nil_regressions
         
     | 
| 
      
 5 
     | 
    
         
            +
                expected = {"asdf"=>{"jklsemicolon"=>{}}}
         
     | 
| 
      
 6 
     | 
    
         
            +
                assert_equal expected, FasterXmlSimple.xml_in("<asdf><jklsemicolon /></asdf>")
         
     | 
| 
      
 7 
     | 
    
         
            +
                assert_equal expected, FasterXmlSimple.xml_in("<asdf><jklsemicolon /></asdf>", 'forcearray'=>['asdf'])
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
              
         
     | 
| 
      
 10 
     | 
    
         
            +
              def test_s3_regression
         
     | 
| 
      
 11 
     | 
    
         
            +
                str = File.read("test/fixtures/test-7.xml")
         
     | 
| 
      
 12 
     | 
    
         
            +
                assert_nil FasterXmlSimple.xml_in(str)["AccessControlPolicy"]["AccessControlList"]["__content__"]
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
              
         
     | 
| 
      
 15 
     | 
    
         
            +
              def test_xml_simple_transparency
         
     | 
| 
      
 16 
     | 
    
         
            +
                assert_equal XmlSimple.xml_in("<asdf />"), FasterXmlSimple.xml_in("<asdf />")
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
              
         
     | 
| 
      
 19 
     | 
    
         
            +
              def test_suppress_empty_variations
         
     | 
| 
      
 20 
     | 
    
         
            +
                str = "<asdf><fdsa /></asdf>"
         
     | 
| 
      
 21 
     | 
    
         
            +
                
         
     | 
| 
      
 22 
     | 
    
         
            +
                assert_equal Hash.new, FasterXmlSimple.xml_in(str)["asdf"]["fdsa"]
         
     | 
| 
      
 23 
     | 
    
         
            +
                assert_nil FasterXmlSimple.xml_in(str, 'suppressempty'=>nil)["asdf"]["fdsa"]
         
     | 
| 
      
 24 
     | 
    
         
            +
                assert_equal '', FasterXmlSimple.xml_in(str, 'suppressempty'=>'')["asdf"]["fdsa"]
         
     | 
| 
      
 25 
     | 
    
         
            +
                assert !FasterXmlSimple.xml_in(str, 'suppressempty'=>true)["asdf"].has_key?("fdsa")
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              def test_empty_string_doesnt_crash
         
     | 
| 
      
 29 
     | 
    
         
            +
                assert_raise(XML::Parser::ParseError) do
         
     | 
| 
      
 30 
     | 
    
         
            +
                  silence_stderr do 
         
     | 
| 
      
 31 
     | 
    
         
            +
                    FasterXmlSimple.xml_in('')
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
              
         
     | 
| 
      
 36 
     | 
    
         
            +
              def test_keeproot_false
         
     | 
| 
      
 37 
     | 
    
         
            +
                str = "<asdf><fdsa>1</fdsa></asdf>"
         
     | 
| 
      
 38 
     | 
    
         
            +
                expected = {"fdsa"=>"1"}
         
     | 
| 
      
 39 
     | 
    
         
            +
                assert_equal expected, FasterXmlSimple.xml_in(str, 'keeproot'=>false)
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
              
         
     | 
| 
      
 42 
     | 
    
         
            +
              def test_keeproot_false_with_force_content
         
     | 
| 
      
 43 
     | 
    
         
            +
                str = "<asdf><fdsa>1</fdsa></asdf>"
         
     | 
| 
      
 44 
     | 
    
         
            +
                expected = {"fdsa"=>{"__content__"=>"1"}}
         
     | 
| 
      
 45 
     | 
    
         
            +
                assert_equal expected, FasterXmlSimple.xml_in(str, 'keeproot'=>false, 'forcecontent'=>true)
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            require 'test/unit'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'faster_xml_simple'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            class FasterXSTest < Test::Unit::TestCase
         
     | 
| 
      
 6 
     | 
    
         
            +
              def default_test
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
              
         
     | 
| 
      
 9 
     | 
    
         
            +
              def silence_stderr
         
     | 
| 
      
 10 
     | 
    
         
            +
                str = STDERR.dup
         
     | 
| 
      
 11 
     | 
    
         
            +
                STDERR.reopen("/dev/null")
         
     | 
| 
      
 12 
     | 
    
         
            +
                STDERR.sync=true
         
     | 
| 
      
 13 
     | 
    
         
            +
                yield
         
     | 
| 
      
 14 
     | 
    
         
            +
              ensure
         
     | 
| 
      
 15 
     | 
    
         
            +
                STDERR.reopen(str)
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/test_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'yaml'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            class XmlSimpleComparisonTest < FasterXSTest
         
     | 
| 
      
 5 
     | 
    
         
            +
              
         
     | 
| 
      
 6 
     | 
    
         
            +
              # Define test methods
         
     | 
| 
      
 7 
     | 
    
         
            +
              
         
     | 
| 
      
 8 
     | 
    
         
            +
              Dir["test/fixtures/test-*.xml"].each do |file_name|
         
     | 
| 
      
 9 
     | 
    
         
            +
                xml_file_name = file_name
         
     | 
| 
      
 10 
     | 
    
         
            +
                method_name = File.basename(file_name, ".xml").gsub('-', '_')
         
     | 
| 
      
 11 
     | 
    
         
            +
                yml_file_name = file_name.gsub('xml', 'yml')
         
     | 
| 
      
 12 
     | 
    
         
            +
                rails_yml_file_name = file_name.gsub('xml', 'rails.yml')
         
     | 
| 
      
 13 
     | 
    
         
            +
                class_eval <<-EOV, __FILE__, __LINE__
         
     | 
| 
      
 14 
     | 
    
         
            +
                  def #{method_name}
         
     | 
| 
      
 15 
     | 
    
         
            +
                    assert_equal YAML.load(File.read('#{yml_file_name}')), 
         
     | 
| 
      
 16 
     | 
    
         
            +
                          FasterXmlSimple.xml_in(File.read('#{xml_file_name}'), default_options )
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  
         
     | 
| 
      
 19 
     | 
    
         
            +
                  def #{method_name}_rails
         
     | 
| 
      
 20 
     | 
    
         
            +
                    assert_equal YAML.load(File.read('#{rails_yml_file_name}')), 
         
     | 
| 
      
 21 
     | 
    
         
            +
                          FasterXmlSimple.xml_in(File.read('#{xml_file_name}'), rails_options)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                EOV
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
              
         
     | 
| 
      
 26 
     | 
    
         
            +
              def default_options
         
     | 
| 
      
 27 
     | 
    
         
            +
                {
         
     | 
| 
      
 28 
     | 
    
         
            +
                   'keeproot'      => true, 
         
     | 
| 
      
 29 
     | 
    
         
            +
                   'contentkey'    => '__content__', 
         
     | 
| 
      
 30 
     | 
    
         
            +
                   'forcecontent'  => true, 
         
     | 
| 
      
 31 
     | 
    
         
            +
                   'suppressempty' => nil,
         
     | 
| 
      
 32 
     | 
    
         
            +
                   'forcearray'    => ['something-else']
         
     | 
| 
      
 33 
     | 
    
         
            +
                }
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
              
         
     | 
| 
      
 36 
     | 
    
         
            +
              def rails_options
         
     | 
| 
      
 37 
     | 
    
         
            +
                {
         
     | 
| 
      
 38 
     | 
    
         
            +
                  'forcearray'   => false,
         
     | 
| 
      
 39 
     | 
    
         
            +
                  'forcecontent' => true,
         
     | 
| 
      
 40 
     | 
    
         
            +
                  'keeproot'     => true,
         
     | 
| 
      
 41 
     | 
    
         
            +
                  'contentkey'   => '__content__'
         
     | 
| 
      
 42 
     | 
    
         
            +
                }
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
              
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     |