File: parsers.rb

package info (click to toggle)
ruby-aws 2.10.2-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, buster, forky, sid, trixie
  • size: 748 kB
  • sloc: ruby: 7,748; makefile: 16
file content (227 lines) | stat: -rw-r--r-- 6,076 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
module Aws

#-----------------------------------------------------------------

  class RightSaxParserCallback #:nodoc:
    def self.include_callback
      include XML::SaxParser::Callbacks
    end

    def initialize(right_aws_parser)
      @right_aws_parser = right_aws_parser
    end

    def on_start_element(name, attr_hash)
      @right_aws_parser.tag_start(name, attr_hash)
    end

    def on_characters(chars)
      @right_aws_parser.text(chars)
    end

    def on_end_element(name)
      @right_aws_parser.tag_end(name)
    end

    def on_start_document;
    end

    def on_comment(msg)
      ;
    end

    def on_processing_instruction(target, data)
      ;
    end

    def on_cdata_block(cdata)
      ;
    end

    def on_end_document;
    end
  end

  class AwsParser #:nodoc:
    # default parsing library
    DEFAULT_XML_LIBRARY  = 'rexml'
    # a list of supported parsers
    @@supported_xml_libs = [DEFAULT_XML_LIBRARY, 'libxml']

    @@xml_lib            = DEFAULT_XML_LIBRARY # xml library name: 'rexml' | 'libxml'
    def self.xml_lib
      @@xml_lib
    end

    def self.xml_lib=(new_lib_name)
      @@xml_lib = new_lib_name
    end

    attr_accessor :result
    attr_reader :xmlpath
    attr_accessor :xml_lib

    def initialize(params={})
      @xmlpath = ''
      @result  = false
      @text    = ''
      @xml_lib = params[:xml_lib] || @@xml_lib
      @logger  = params[:logger]
      reset
    end

    def tag_start(name, attributes)
      @text = ''
      tagstart(name, attributes)
      @xmlpath += @xmlpath.empty? ? name : "/#{name}"
    end

    def tag_end(name)
      if @xmlpath =~ /^(.*?)\/?#{name}$/
        @xmlpath = $1
      end
      tagend(name)
    end

    def text(text)
      @text += text
      tagtext(text)
    end

    # Parser method.
    # Params:
    #   xml_text         - xml message text(String) or Net:HTTPxxx instance (response)
    #   params[:xml_lib] - library name: 'rexml' | 'libxml'
    def parse(xml_text, params={})
      # Get response body
      unless xml_text.is_a?(String)
        xml_text = xml_text.body.respond_to?(:force_encoding) ? xml_text.body.force_encoding("UTF-8") : xml_text.body
      end

      @xml_lib = params[:xml_lib] || @xml_lib
      # check that we had no problems with this library otherwise use default
      @xml_lib = DEFAULT_XML_LIBRARY unless @@supported_xml_libs.include?(@xml_lib)
      # load xml library
      if @xml_lib=='libxml' && !defined?(XML::SaxParser)
        begin
          require 'xml/libxml'
          # is it new ? - Setup SaxParserCallback
          if XML::Parser::VERSION >= '0.5.1.0'
            RightSaxParserCallback.include_callback
          end
        rescue LoadError => e
          @@supported_xml_libs.delete(@xml_lib)
          @xml_lib = DEFAULT_XML_LIBRARY
          if @logger
            @logger.error e.inspect
            @logger.error e.backtrace
            @logger.info "Can not load 'libxml' library. '#{DEFAULT_XML_LIBRARY}' is used for parsing."
          end
        end
      end
      # Parse the xml text
      case @xml_lib
        when 'libxml'
          xml = XML::SaxParser.string(xml_text)
          # check libxml-ruby version
          if XML::Parser::VERSION >= '0.5.1.0'
            xml.callbacks = RightSaxParserCallback.new(self)
          else
            xml.on_start_element { |name, attr_hash| self.tag_start(name, attr_hash) }
            xml.on_characters { |text| self.text(text) }
            xml.on_end_element { |name| self.tag_end(name) }
          end
          xml.parse
        else
          REXML::Document.parse_stream(xml_text, self)
      end
    end

    # Parser must have a lots of methods
    # (see /usr/lib/ruby/1.8/rexml/parsers/streamparser.rb)
    # We dont need most of them in AwsParser and method_missing helps us
    # to skip their definition
    def method_missing(method, *params)
      # if the method is one of known - just skip it ...
      return if [:comment, :attlistdecl, :notationdecl, :elementdecl,
                 :entitydecl, :cdata, :xmldecl, :attlistdecl, :instruction,
                 :doctype].include?(method)
      # ... else - call super to raise an exception
      super(method, params)
    end

    # the functions to be overriden by children (if nessesery)
    def reset;
    end

    def tagstart(name, attributes)
      ;
    end

    def tagend(name)
      ;
    end

    def tagtext(text)
      ;
    end
  end

#-----------------------------------------------------------------
#      PARSERS: Errors
#-----------------------------------------------------------------

#<Error>
#  <Code>TemporaryRedirect</Code>
#  <Message>Please re-send this request to the specified temporary endpoint. Continue to use the original request endpoint for future requests.</Message>
#  <RequestId>FD8D5026D1C5ABA3</RequestId>
#  <Endpoint>bucket-for-k.s3-external-3.amazonaws.com</Endpoint>
#  <HostId>ItJy8xPFPli1fq/JR3DzQd3iDvFCRqi1LTRmunEdM1Uf6ZtW2r2kfGPWhRE1vtaU</HostId>
#  <Bucket>bucket-for-k</Bucket>
#</Error>

  class RightErrorResponseParser < AwsParser #:nodoc:
    attr_accessor :errors # array of hashes: error/message
    attr_accessor :requestID
#    attr_accessor :endpoint, :host_id, :bucket
    def parse(response)
      super
    end

    def tagend(name)
      case name
        when 'RequestID';
          @requestID = @text
        when 'Code';
          @code = @text
        when 'Message';
          @message = @text
        when 'Endpoint'  ; @endpoint  = @text
        when 'HostId'    ; @host_id   = @text
        when 'Bucket'    ; @bucket    = @text
        when 'Error';
          @errors << [@code, @message]
      end
    end

    def reset
      @errors = []
    end
  end

# Dummy parser - does nothing
# Returns the original params back
  class RightDummyParser # :nodoc:
    attr_accessor :result

    def parse(response, params={})
      @result = [response, params]
    end
  end

  class RightHttp2xxParser < AwsParser # :nodoc:
    def parse(response)
      @result = response.is_a?(Net::HTTPSuccess)
    end
  end
end