require 'thread' module Aws # Each Service module has its own Errors module, e.g. {S3::Errors}. module Errors # The base class for all errors returned by an Amazon Web Service. # All ~400 level client errors and ~500 level server errors are raised # as service errors. This indicates it was an error returned from the # service and not one generated by the client. class ServiceError < RuntimeError # @param [Seahorse::Client::RequestContext] context # @param [String] message def initialize(context, message) @context = context super(message) end # @return [Seahorse::Client::RequestContext] The context of the request # that triggered the remote service to return this error. attr_reader :context class << self # @return [String] attr_accessor :code end end # Various plugins perform client-side checksums of responses. # This error indicates a checksum failed. class ChecksumError < RuntimeError; end # Raised when a {Service} is constructed an no suitable API # version is found based on configuration. class NoSuchApiVersionError < RuntimeError; end # Raised when a {Service} is constructed and the specified shared # credentials profile does not exist. class NoSuchProfileError < RuntimeError; end # Raised when a {Service} is constructed and credentials are not # set, or the set credentials are empty. class MissingCredentialsError < RuntimeError; end # Raised when a {Service} is constructed and region is not specified. class MissingRegionError < RuntimeError; end # This module is mixed into another module, providing dynamic # error classes. Error classes all inherit from {ServiceError}. # # # creates and returns the class # Aws::S3::Errors::MyNewErrorClass # # Since the complete list of possible AWS errors returned by services # is not known, this allows us to create them as needed. This also # allows users to rescue errors by class without them being concrete # classes beforehand. # # @api private module DynamicErrors def self.extended(submodule) submodule.instance_variable_set("@const_set_mutex", Mutex.new) submodule.const_set(:ServiceError, Class.new(ServiceError)) end def const_missing(constant) set_error_constant(constant) end # Given the name of a service and an error code, this method # returns an error class (that extends {ServiceError}. # # Aws::S3::Errors.error_class('NoSuchBucket').new # #=> #<Aws::S3::Errors::NoSuchBucket> # # @api private def error_class(error_code) constant = error_code.to_s constant = constant.gsub(/http:\/\/.*$/, '') # remove http namespaces constant = constant.gsub(/[^a-zA-Z0-9]/, '').to_sym if error_const_set?(constant) const_get(constant) else set_error_constant(constant) end end private def set_error_constant(constant) @const_set_mutex.synchronize do # Ensure the const was not defined while blocked by the mutex if error_const_set?(constant) const_get(constant) else error_class = Class.new(const_get(:ServiceError)) error_class.code = constant.to_s const_set(constant, error_class) end end end def error_const_set?(constant) # Purposefully not using #const_defined? as that method returns true # for constants not defined directly in the current module. constants.include?(constant.to_sym) end end end end