/**
  * Send a message to queue. Works out which interface to send it to, and dispatches it.
  * @param String $queue Name of queue to send message to
  * @param Any $message			The message to send.
  * @param Map $header			A map of header items.
  * @param Boolean $buffered		If the queue specifies a buffer and this is true, the messages will be
  * 								sent to the buffer instead. If the queue specifies a buffer and this is false,
  * 								the buffer is bypassed, and the messages are sent directly to destination.
  * 								If the queue does not specify a buffer, this has no effect.
  */
 static function send($queue, $message, $header = array(), $buffered = true)
 {
     $conf = self::get_queue_config($queue);
     $sendOptions = isset($conf["send"]) ? $conf["send"] : array();
     $sendQueue = $queue;
     // If we are buffering and the queue is configured with a buffer, we'll use the buffer queue's config
     // instead, because we're queueing to that.
     $buffer = "";
     if ($buffered && isset($conf["send"]) && is_array($conf["send"]) && isset($conf["send"]["buffer"])) {
         $buffer = $conf["send"]["buffer"];
     }
     if ($buffer) {
         $sendQueue = $buffer;
         $conf = self::get_queue_config($buffer);
     }
     $inst = singleton($conf["implementation"]);
     if (is_object($message) && $message instanceof MessageFrame) {
         $msgframe = $message;
         if (!$header == null) {
             $header = array();
         }
         if (!$msgframe->header) {
             $msgframe->header = array();
         }
         $msgframe->header = array_merge($msgframe->header, $header);
     } else {
         $msgframe = new MessageFrame($message, $header);
     }
     if (self::$force_immediate_delivery) {
         // Cut the loop short
         self::deliver_message($msgframe, $conf);
     } else {
         self::encode_message($msgframe, $conf);
         $inst->send($sendQueue, $msgframe, $conf);
         // If we are asked to process this queue on shutdown, ensure the php shutdown function
         // is registered, and that this queue has been added to the list of queues to process.
         // We sort out what actions are needed later.
         $isRunningTest = class_exists('SapphireTest', false) && SapphireTest::is_running_test();
         if (isset($sendOptions["onShutdown"]) && (!$isRunningTest || self::$force_onshutdown_when_testing)) {
             if (!self::$queues_to_flush_on_shutdown) {
                 // only register the shutdown function once, and only if asked for or defaulted
                 if (!isset($sendOptions["registerShutdown"]) || $sendOptions["registerShutdown"]) {
                     register_shutdown_function(array(__CLASS__, "consume_on_shutdown"));
                 }
                 self::$queues_to_flush_on_shutdown = array();
             }
             self::$queues_to_flush_on_shutdown[$queue] = true;
         }
     }
 }