    # File lib/amqp/exchange.rb, line 299
        def initialize(channel, type, name, opts = {}, &block)
          @channel             = channel
          @type                = type
          @opts                = self.class.add_default_options(type, name, opts, block)
          @default_routing_key = opts[:routing_key] || opts[:key] || AMQ::Protocol::EMPTY_STRING
          @name                = name unless name.empty?

          @status                  = :unknown
          @default_publish_options = (opts.delete(:default_publish_options) || {
                                        :routing_key  => @default_routing_key,
                                        :mandatory    => false,
                                        :immediate    => false
                                      }).freeze

          @default_headers = (opts.delete(:default_headers) || {
                                :content_type => DEFAULT_CONTENT_TYPE,
                                :persistent   => false,
                                :priority     => 0
                              }).freeze

          super(channel.connection, channel, name, type)

          # The AMQP 0.8 specification (as well as 0.9.1) in 1.1.4.2 mentiones
          # that Exchange.Declare-Ok confirms the name of the exchange (because
          # of automaticallynamed), which is logical to interpret that this
          # functionality should be the same as for Queue (though it isn't
          # explicitely told in the specification). In fact, RabbitMQ (and
          # probably other implementations as well) doesn't support it and
          # there is a default exchange with an empty name (so-called default
          # or nameless exchange), so if we'd send Exchange.Declare(exchange=""),
          # then RabbitMQ interpret it as if we'd try to redefine this default
          # exchange so it'd produce an error.
          unless name == "amq.#{type}" or name.empty? or opts[:no_declare]
            @status = :opening

            unless @opts[:no_declare]
              @channel.once_open do
                if block
                  shim = Proc.new do |exchange, declare_ok|
                    case block.arity
                    when 1 then block.call(exchange)
                    else
                      block.call(exchange, declare_ok)
                    end
                  end

                  self.declare(passive = @opts[:passive], durable = @opts[:durable], auto_delete = @opts[:auto_delete], nowait = @opts[:nowait], @opts[:arguments], &shim)
                else
                  self.declare(passive = @opts[:passive], durable = @opts[:durable], auto_delete = @opts[:auto_delete], nowait = @opts[:nowait], @opts[:arguments])
                end
              end
            end
          else
            # Call the callback immediately, as given exchange is already
            # declared.
            @status = :opened
            block.call(self) if block
          end

          @on_declare = block
        end