summaryrefslogtreecommitdiff
path: root/lib/error.rb
blob: 58b98167030b1c51ae3aa3b99873cd4984f70b73 (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
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
require 'open4'

# add additional fields to Exception class to format errors according to OT-API
class RuntimeError
  attr_accessor :http_code, :uri
  def initialize message, uri=nil
    super message
    @uri = uri
    @http_code ||= 500
    $logger.error "\n"+self.to_turtle
  end

  # define to_ and self.from_ methods for various rdf formats
  RDF_FORMATS.each do |format|

    send :define_method, "to_#{format}".to_sym do
      rdf = RDF::Writer.for(format).buffer do |writer|
        # TODO: not used for turtle
        # http://rdf.rubyforge.org/RDF/Writer.html#
        writer.prefix :ot, RDF::URI('http://www.opentox.org/api/1.2#')
        writer.prefix :ot1_1, RDF::URI('http://www.opentox.org/api/1.1#')
        subject = RDF::Node.new
        writer << [subject, RDF.type, RDF::OT.ErrorReport]
        writer << [subject, RDF::OT.actor, @uri.to_s]
        writer << [subject, RDF::OT.message, @message.to_s]
        writer << [subject, RDF::OT.statusCode, @http_code]
        writer << [subject, RDF::OT.errorCode, self.class.to_s]

        # cut backtrace
        backtrace = caller.collect{|line| line unless line =~ /#{File.dirname(__FILE__)}/}.compact
        cut_index = backtrace.find_index{|line| line.match /sinatra|minitest/}
        cut_index ||= backtrace.size
        cut_index -= 1
        cut_index = backtrace.size-1 if cut_index < 0
        details = backtrace[0..cut_index].join("\n")
        details += "REST paramenters:\n#{@request.args.inspect}" if @request
        writer << [subject, RDF::OT.errorCause, details]
      end
      rdf
    end

  end
end

module OpenTox

  class Error < RuntimeError
    def initialize code, message, uri=nil
      @http_code = code
      super message, uri
    end
  end

  # OpenTox errors
  {
    "BadRequestError" => 400,
    "NotAuthorizedError" => 401,
    "NotFoundError" => 404,
    "LockedError" => 423,
    "InternalServerError" => 500,
    "NotImplementedError" => 501,
    "ServiceUnavailableError" => 503,
    "TimeOutError" => 504,
  }.each do |klass,code|
    # create error classes 
    c = Class.new Error do
      define_method :initialize do |message, uri=nil|
        super code, message, uri
      end
    end
    OpenTox.const_set klass,c
    
    # define global methods for raising errors, eg. bad_request_error
    Object.send(:define_method, klass.underscore.to_sym) do |message,uri=nil|
      raise c, message, uri
    end
  end
  
  # Errors received from RestClientWrapper calls
  class RestCallError < Error
    attr_accessor :request#, :response
    def initialize message, request, uri
    #def initialize request, response, message
      @request = request
      #@response = response
      super 502, message, uri
    end
  end

=begin
  # TODO: create reports directly from errors, requires modified task service
  class ErrorReport
    def initialize http_code, error
      @http_code = http_code
      @report = {}
      @report[RDF::OT.actor] = error.uri.to_s
      @report[RDF::OT.message] = error.message.to_s
      @report[RDF::OT.statusCode] = @http_code 
      @report[RDF::OT.errorCode] = error.class.to_s

      # cut backtrace
      backtrace = caller.collect{|line| line unless line =~ /#{File.dirname(__FILE__)}/}.compact
      cut_index = backtrace.find_index{|line| line.match /sinatra|minitest/}
      cut_index ||= backtrace.size
      cut_index -= 1
      cut_index = backtrace.size-1 if cut_index < 0
      @report[RDF::OT.errorDetails] = backtrace[0..cut_index].join("\n")
      @report[RDF::OT.errorDetails] += "REST paramenters:\n#{error.request.args.inspect}" if defined? error.request
      #@report[RDF::OT.message] += "\n" + error.response.body.to_s if defined? error.response
      # TODO fix Error cause
      # should point to another errorReport, but errorReports do not have URIs
      # create a separate service?
      #report[RDF::OT.errorCause] = @report if defined?(@report) 
    end

    # define to_ and self.from_ methods for various rdf formats
    RDF_FORMATS.each do |format|

      send :define_method, "to_#{format}".to_sym do
        rdf = RDF::Writer.for(format).buffer do |writer|
          # TODO: not used for turtle
          # http://rdf.rubyforge.org/RDF/Writer.html#
          writer.prefix :ot, RDF::URI('http://www.opentox.org/api/1.2#')
          writer.prefix :ot1_1, RDF::URI('http://www.opentox.org/api/1.1#')
          subject = RDF::Node.new
          @report.each do |predicate,object|
            writer << [subject, predicate, object] if object
          end
        end
        rdf
      end

      define_singleton_method "from_#{format}".to_sym do |rdf|
        report = ErrorReport.new
        RDF::Reader.for(format).new(rdf) do |reader|
          reader.each_statement{ |statement| report.rdf << statement }
        end
        report
      end
    end
  end
=end
end