summaryrefslogtreecommitdiff
path: root/lib/error.rb
blob: 23e738d70d844ab47972451233f93a240a98369c (plain)
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
require 'open4'

# add additional fields to Exception class to format errors according to OT-API
module OpenToxError
  attr_accessor :http_code, :uri, :error_cause
  def initialize(message, uri=nil, cause=nil)
    message.gsub!(/\A"|"\Z/, '') # remove quotes
    @error_cause = cause ? OpenToxError::cut_backtrace(cause) : short_backtrace
    
    super message
    #unless self.is_a? Errno::EAGAIN # avoid "Resource temporarily unavailable" errors
      @uri = uri.to_s.sub(%r{//.*:.*@},'//') # remove credentials from uri
      @http_code ||= 500
      @rdf = RDF::Graph.new
      subject = RDF::Node.new
      @rdf << [subject, RDF.type, RDF::OT.ErrorReport]
      @rdf << [subject, RDF::OT.actor, @uri]
      @rdf << [subject, RDF::OT.message, message]
      @rdf << [subject, RDF::OT.statusCode, @http_code]
      @rdf << [subject, RDF::OT.errorCode, self.class.to_s]
      @rdf << [subject, RDF::OT.errorCause, @error_cause]
      $logger.error("\n"+self.to_turtle)
    #end
  end
  
  def self.cut_backtrace(trace)
    if trace.is_a?(Array)
      cut_index = trace.find_index{|line| line.match(/sinatra|minitest/)}
      cut_index ||= trace.size
      cut_index -= 1
      cut_index = trace.size-1 if cut_index < 0
      trace[0..cut_index].join("\n")
    else
      trace
    end
  end
  
  def short_backtrace
    backtrace = caller.collect{|line| line unless line =~ /#{File.dirname(__FILE__)}/}.compact
    OpenToxError::cut_backtrace(backtrace)
  end

  RDF_FORMATS.each do |format|
    # rdf serialization methods for all formats e.g. to_rdfxml
    send :define_method, "to_#{format}".to_sym do
      RDF::Writer.for(format).buffer do |writer|
        @rdf.each{|statement| writer << statement} if @rdf
      end
    end
  end

  def to_turtle # redefine to use prefixes (not supported by RDF::Writer)
    prefixes = {:rdf => "http://www.w3.org/1999/02/22-rdf-syntax-ns#"}
    ['OT', 'DC', 'XSD', 'OLO'].each{|p| prefixes[p.downcase.to_sym] = eval("RDF::#{p}.to_s") }
    RDF::Turtle::Writer.for(:turtle).buffer(:prefixes => prefixes)  do |writer|
      @rdf.each{|statement| writer << statement} if @rdf
    end
  end

end

class RuntimeError
#class StandardError
  include OpenToxError
end

# clutters log file with library errors
#class NoMethodError
  #include OpenToxError
#end

module OpenTox

  class Error < RuntimeError
    include OpenToxError
    
    def initialize(code, message, uri=nil, cause=nil)
      @http_code = code
      super message, uri, cause
    end
  end

  # OpenTox errors
  RestClientWrapper.known_errors.each do |error|
    # create error classes 
    c = Class.new Error do
      define_method :initialize do |message, uri=nil, cause=nil|
        super error[:code], message, uri, cause
      end
    end
    OpenTox.const_set error[:class],c
    
    # define global methods for raising errors, eg. bad_request_error
    Object.send(:define_method, error[:method]) do |message,uri=nil,cause=nil|
      raise c.new(message.inspect, uri, cause)
    end
  end
  
end