| 
									
										
										
										
											2009-02-20 18:57:20 +00:00
										 |  |  | <?php | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright 2005-2006 The Apache Software Foundation | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * http://www.apache.org/licenses/LICENSE-2.0 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* vim: set expandtab tabstop=3 shiftwidth=3: */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | require_once 'Stomp/Frame.php'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * A Stomp Connection | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @package Stomp | 
					
						
							|  |  |  |  * @author Hiram Chirino <hiram@hiramchirino.com> | 
					
						
							|  |  |  |  * @author Dejan Bosanac <dejan@nighttale.net>  | 
					
						
							|  |  |  |  * @author Michael Caplan <mcaplan@labnet.net> | 
					
						
							|  |  |  |  * @version $Revision: 43 $ | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class Stomp | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Perform request synchronously | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public $sync = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Default prefetch size | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var int | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 	public $prefetchSize = 1; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  |      * Client id used for durable subscriptions | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var string | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 	public $clientId = null; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     protected $_brokerUri = null; | 
					
						
							|  |  |  |     protected $_socket = null; | 
					
						
							|  |  |  |     protected $_hosts = array(); | 
					
						
							|  |  |  |     protected $_params = array(); | 
					
						
							|  |  |  |     protected $_subscriptions = array(); | 
					
						
							|  |  |  |     protected $_defaultPort = 61613; | 
					
						
							|  |  |  |     protected $_currentHost = - 1; | 
					
						
							|  |  |  |     protected $_attempts = 10; | 
					
						
							|  |  |  |     protected $_username = ''; | 
					
						
							|  |  |  |     protected $_password = ''; | 
					
						
							|  |  |  |     protected $_sessionId; | 
					
						
							|  |  |  |     protected $_read_timeout_seconds = 60; | 
					
						
							|  |  |  |     protected $_read_timeout_milliseconds = 0; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Constructor | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $brokerUri Broker URL | 
					
						
							|  |  |  |      * @throws Stomp_Exception | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function __construct ($brokerUri) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->_brokerUri = $brokerUri; | 
					
						
							|  |  |  |         $this->_init(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Initialize connection | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @throws Stomp_Exception | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function _init () | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $pattern = "|^(([a-zA-Z]+)://)+\(*([a-zA-Z0-9\.:/i,-]+)\)*\??([a-zA-Z0-9=]*)$|i"; | 
					
						
							|  |  |  |         if (preg_match($pattern, $this->_brokerUri, $regs)) { | 
					
						
							|  |  |  |             $scheme = $regs[2]; | 
					
						
							|  |  |  |             $hosts = $regs[3]; | 
					
						
							|  |  |  |             $params = $regs[4]; | 
					
						
							|  |  |  |             if ($scheme != "failover") { | 
					
						
							|  |  |  |                 $this->_processUrl($this->_brokerUri); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 $urls = explode(",", $hosts); | 
					
						
							|  |  |  |                 foreach ($urls as $url) { | 
					
						
							|  |  |  |                     $this->_processUrl($url); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if ($params != null) { | 
					
						
							|  |  |  |                 parse_str($params, $this->_params); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             require_once 'Stomp/Exception.php'; | 
					
						
							|  |  |  |             throw new Stomp_Exception("Bad Broker URL {$this->_brokerUri}"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Process broker URL | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $url Broker URL | 
					
						
							|  |  |  |      * @throws Stomp_Exception | 
					
						
							|  |  |  |      * @return boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function _processUrl ($url) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $parsed = parse_url($url); | 
					
						
							|  |  |  |         if ($parsed) { | 
					
						
							|  |  |  |             array_push($this->_hosts, array($parsed['host'] , $parsed['port'] , $parsed['scheme'])); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             require_once 'Stomp/Exception.php'; | 
					
						
							|  |  |  |             throw new Stomp_Exception("Bad Broker URL $url"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Make socket connection to the server | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @throws Stomp_Exception | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function _makeConnection () | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (count($this->_hosts) == 0) { | 
					
						
							|  |  |  |             require_once 'Stomp/Exception.php'; | 
					
						
							|  |  |  |             throw new Stomp_Exception("No broker defined"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // force disconnect, if previous established connection exists
 | 
					
						
							|  |  |  |         $this->disconnect(); | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         $i = $this->_currentHost; | 
					
						
							|  |  |  |         $att = 0; | 
					
						
							|  |  |  |         $connected = false; | 
					
						
							|  |  |  |         while (! $connected && $att ++ < $this->_attempts) { | 
					
						
							|  |  |  |             if (isset($this->_params['randomize']) && $this->_params['randomize'] == 'true') { | 
					
						
							|  |  |  |                 $i = rand(0, count($this->_hosts) - 1); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 $i = ($i + 1) % count($this->_hosts); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $broker = $this->_hosts[$i]; | 
					
						
							|  |  |  |             $host = $broker[0]; | 
					
						
							|  |  |  |             $port = $broker[1]; | 
					
						
							|  |  |  |             $scheme = $broker[2]; | 
					
						
							|  |  |  |             if ($port == null) { | 
					
						
							|  |  |  |                 $port = $this->_defaultPort; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if ($this->_socket != null) { | 
					
						
							|  |  |  |                 fclose($this->_socket); | 
					
						
							|  |  |  |                 $this->_socket = null; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $this->_socket = @fsockopen($scheme . '://' . $host, $port); | 
					
						
							|  |  |  |             if (!is_resource($this->_socket) && $att >= $this->_attempts && !array_key_exists($i + 1, $this->_hosts)) { | 
					
						
							|  |  |  |                 require_once 'Stomp/Exception.php'; | 
					
						
							|  |  |  |                 throw new Stomp_Exception("Could not connect to $host:$port ($att/{$this->_attempts})"); | 
					
						
							|  |  |  |             } else if (is_resource($this->_socket)) { | 
					
						
							|  |  |  |                 $connected = true; | 
					
						
							|  |  |  |                 $this->_currentHost = $i; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (! $connected) { | 
					
						
							|  |  |  |             require_once 'Stomp/Exception.php'; | 
					
						
							|  |  |  |             throw new Stomp_Exception("Could not connect to a broker"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Connect to server | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $username | 
					
						
							|  |  |  |      * @param string $password | 
					
						
							|  |  |  |      * @return boolean | 
					
						
							|  |  |  |      * @throws Stomp_Exception | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function connect ($username = '', $password = '') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->_makeConnection(); | 
					
						
							|  |  |  |         if ($username != '') { | 
					
						
							|  |  |  |             $this->_username = $username; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if ($password != '') { | 
					
						
							|  |  |  |             $this->_password = $password; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 		$headers = array('login' => $this->_username , 'passcode' => $this->_password); | 
					
						
							|  |  |  | 		if ($this->clientId != null) { | 
					
						
							|  |  |  | 			$headers["client-id"] = $this->clientId; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		$frame = new Stomp_Frame("CONNECT", $headers); | 
					
						
							|  |  |  |         $this->_writeFrame($frame); | 
					
						
							|  |  |  |         $frame = $this->readFrame(); | 
					
						
							|  |  |  |         if ($frame instanceof Stomp_Frame && $frame->command == 'CONNECTED') { | 
					
						
							|  |  |  |             $this->_sessionId = $frame->headers["session"]; | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             require_once 'Stomp/Exception.php'; | 
					
						
							|  |  |  |             if ($frame instanceof Stomp_Frame) { | 
					
						
							|  |  |  |                 throw new Stomp_Exception("Unexpected command: {$frame->command}", 0, $frame->body); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 throw new Stomp_Exception("Connection not acknowledged"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Check if client session has ben established | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function isConnected () | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return !empty($this->_sessionId) && is_resource($this->_socket); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Current stomp session ID | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return string | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function getSessionId() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return $this->_sessionId; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Send a message to a destination in the messaging system  | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $destination Destination queue | 
					
						
							|  |  |  |      * @param string|Stomp_Frame $msg Message | 
					
						
							|  |  |  |      * @param array $properties | 
					
						
							|  |  |  |      * @param boolean $sync Perform request synchronously | 
					
						
							|  |  |  |      * @return boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function send ($destination, $msg, $properties = null, $sync = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if ($msg instanceof Stomp_Frame) { | 
					
						
							|  |  |  |             $msg->headers['destination'] = $destination; | 
					
						
							|  |  |  |             $msg->headers = array_merge($msg->headers, $properties); | 
					
						
							|  |  |  |             $frame = $msg; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $headers = $properties; | 
					
						
							|  |  |  |             $headers['destination'] = $destination; | 
					
						
							|  |  |  |             $frame = new Stomp_Frame('SEND', $headers, $msg); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $this->_prepareReceipt($frame, $sync); | 
					
						
							|  |  |  |         $this->_writeFrame($frame); | 
					
						
							|  |  |  |         return $this->_waitForReceipt($frame, $sync); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Prepair frame receipt | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Stomp_Frame $frame | 
					
						
							|  |  |  |      * @param boolean $sync | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function _prepareReceipt (Stomp_Frame $frame, $sync) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $receive = $this->sync; | 
					
						
							|  |  |  |         if ($sync !== null) { | 
					
						
							|  |  |  |             $receive = $sync; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if ($receive == true) { | 
					
						
							|  |  |  |             $frame->headers['receipt'] = md5(microtime()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Wait for receipt | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Stomp_Frame $frame | 
					
						
							|  |  |  |      * @param boolean $sync | 
					
						
							|  |  |  |      * @return boolean | 
					
						
							|  |  |  |      * @throws Stomp_Exception | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function _waitForReceipt (Stomp_Frame $frame, $sync) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $receive = $this->sync; | 
					
						
							|  |  |  |         if ($sync !== null) { | 
					
						
							|  |  |  |             $receive = $sync; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if ($receive == true) { | 
					
						
							|  |  |  |             $id = (isset($frame->headers['receipt'])) ? $frame->headers['receipt'] : null; | 
					
						
							|  |  |  |             if ($id == null) { | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $frame = $this->readFrame(); | 
					
						
							|  |  |  |             if ($frame instanceof Stomp_Frame && $frame->command == 'RECEIPT') { | 
					
						
							|  |  |  |                 if ($frame->headers['receipt-id'] == $id) { | 
					
						
							|  |  |  |                     return true; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     require_once 'Stomp/Exception.php'; | 
					
						
							|  |  |  |                     throw new Stomp_Exception("Unexpected receipt id {$frame->headers['receipt-id']}", 0, $frame->body); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 require_once 'Stomp/Exception.php'; | 
					
						
							|  |  |  |                 if ($frame instanceof Stomp_Frame) { | 
					
						
							|  |  |  |                     throw new Stomp_Exception("Unexpected command {$frame->command}", 0, $frame->body); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     throw new Stomp_Exception("Receipt not received"); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Register to listen to a given destination | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $destination Destination queue | 
					
						
							|  |  |  |      * @param array $properties | 
					
						
							|  |  |  |      * @param boolean $sync Perform request synchronously | 
					
						
							|  |  |  |      * @return boolean | 
					
						
							|  |  |  |      * @throws Stomp_Exception | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function subscribe ($destination, $properties = null, $sync = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $headers = array('ack' => 'client'); | 
					
						
							|  |  |  | 		$headers['activemq.prefetchSize'] = $this->prefetchSize; | 
					
						
							|  |  |  | 		if ($this->clientId != null) { | 
					
						
							|  |  |  | 			$headers["activemq.subcriptionName"] = $this->clientId; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  |         if (isset($properties)) { | 
					
						
							|  |  |  |             foreach ($properties as $name => $value) { | 
					
						
							|  |  |  |                 $headers[$name] = $value; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $headers['destination'] = $destination; | 
					
						
							|  |  |  |         $frame = new Stomp_Frame('SUBSCRIBE', $headers); | 
					
						
							|  |  |  |         $this->_prepareReceipt($frame, $sync); | 
					
						
							|  |  |  |         $this->_writeFrame($frame); | 
					
						
							|  |  |  |         if ($this->_waitForReceipt($frame, $sync) == true) { | 
					
						
							|  |  |  |             $this->_subscriptions[$destination] = $properties; | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Remove an existing subscription | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $destination | 
					
						
							|  |  |  |      * @param array $properties | 
					
						
							|  |  |  |      * @param boolean $sync Perform request synchronously | 
					
						
							|  |  |  |      * @return boolean | 
					
						
							|  |  |  |      * @throws Stomp_Exception | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function unsubscribe ($destination, $properties = null, $sync = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $headers = array(); | 
					
						
							|  |  |  |         if (isset($properties)) { | 
					
						
							|  |  |  |             foreach ($properties as $name => $value) { | 
					
						
							|  |  |  |                 $headers[$name] = $value; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $headers['destination'] = $destination; | 
					
						
							|  |  |  |         $frame = new Stomp_Frame('UNSUBSCRIBE', $headers); | 
					
						
							|  |  |  |         $this->_prepareReceipt($frame, $sync); | 
					
						
							|  |  |  |         $this->_writeFrame($frame); | 
					
						
							|  |  |  |         if ($this->_waitForReceipt($frame, $sync) == true) { | 
					
						
							|  |  |  |             unset($this->_subscriptions[$destination]); | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Start a transaction | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $transactionId | 
					
						
							|  |  |  |      * @param boolean $sync Perform request synchronously | 
					
						
							|  |  |  |      * @return boolean | 
					
						
							|  |  |  |      * @throws Stomp_Exception | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function begin ($transactionId = null, $sync = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $headers = array(); | 
					
						
							|  |  |  |         if (isset($transactionId)) { | 
					
						
							|  |  |  |             $headers['transaction'] = $transactionId; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $frame = new Stomp_Frame('BEGIN', $headers); | 
					
						
							|  |  |  |         $this->_prepareReceipt($frame, $sync); | 
					
						
							|  |  |  |         $this->_writeFrame($frame); | 
					
						
							|  |  |  |         return $this->_waitForReceipt($frame, $sync); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Commit a transaction in progress | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $transactionId | 
					
						
							|  |  |  |      * @param boolean $sync Perform request synchronously | 
					
						
							|  |  |  |      * @return boolean | 
					
						
							|  |  |  |      * @throws Stomp_Exception | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function commit ($transactionId = null, $sync = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $headers = array(); | 
					
						
							|  |  |  |         if (isset($transactionId)) { | 
					
						
							|  |  |  |             $headers['transaction'] = $transactionId; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $frame = new Stomp_Frame('COMMIT', $headers); | 
					
						
							|  |  |  |         $this->_prepareReceipt($frame, $sync); | 
					
						
							|  |  |  |         $this->_writeFrame($frame); | 
					
						
							|  |  |  |         return $this->_waitForReceipt($frame, $sync); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Roll back a transaction in progress | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $transactionId | 
					
						
							|  |  |  |      * @param boolean $sync Perform request synchronously | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function abort ($transactionId = null, $sync = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $headers = array(); | 
					
						
							|  |  |  |         if (isset($transactionId)) { | 
					
						
							|  |  |  |             $headers['transaction'] = $transactionId; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $frame = new Stomp_Frame('ABORT', $headers); | 
					
						
							|  |  |  |         $this->_prepareReceipt($frame, $sync); | 
					
						
							|  |  |  |         $this->_writeFrame($frame); | 
					
						
							|  |  |  |         return $this->_waitForReceipt($frame, $sync); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Acknowledge consumption of a message from a subscription | 
					
						
							|  |  |  | 	 * Note: This operation is always asynchronous | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string|Stomp_Frame $messageMessage ID | 
					
						
							|  |  |  |      * @param string $transactionId | 
					
						
							|  |  |  |      * @return boolean | 
					
						
							|  |  |  |      * @throws Stomp_Exception | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function ack ($message, $transactionId = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if ($message instanceof Stomp_Frame) { | 
					
						
							|  |  |  |             $frame = new Stomp_Frame('ACK', $message->headers); | 
					
						
							|  |  |  |             $this->_writeFrame($frame); | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $headers = array(); | 
					
						
							|  |  |  |             if (isset($transactionId)) { | 
					
						
							|  |  |  |                 $headers['transaction'] = $transactionId; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $headers['message-id'] = $message; | 
					
						
							|  |  |  |             $frame = new Stomp_Frame('ACK', $headers); | 
					
						
							|  |  |  |             $this->_writeFrame($frame); | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Graceful disconnect from the server | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function disconnect () | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-08-31 15:49:11 -04:00
										 |  |  | 		$headers = array(); | 
					
						
							| 
									
										
										
										
											2009-02-20 18:57:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if ($this->clientId != null) { | 
					
						
							|  |  |  | 			$headers["client-id"] = $this->clientId; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_resource($this->_socket)) { | 
					
						
							|  |  |  |             $this->_writeFrame(new Stomp_Frame('DISCONNECT', $headers)); | 
					
						
							|  |  |  |             fclose($this->_socket); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $this->_socket = null; | 
					
						
							|  |  |  |         $this->_sessionId = null; | 
					
						
							|  |  |  |         $this->_currentHost = -1; | 
					
						
							|  |  |  |         $this->_subscriptions = array(); | 
					
						
							|  |  |  |         $this->_username = ''; | 
					
						
							|  |  |  |         $this->_password = ''; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Write frame to server | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Stomp_Frame $stompFrame | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function _writeFrame (Stomp_Frame $stompFrame) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!is_resource($this->_socket)) { | 
					
						
							|  |  |  |             require_once 'Stomp/Exception.php'; | 
					
						
							|  |  |  |             throw new Stomp_Exception('Socket connection hasn\'t been established'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $data = $stompFrame->__toString(); | 
					
						
							|  |  |  |         $r = fwrite($this->_socket, $data, strlen($data)); | 
					
						
							|  |  |  |         if ($r === false || $r == 0) { | 
					
						
							|  |  |  |             $this->_reconnect(); | 
					
						
							|  |  |  |             $this->_writeFrame($stompFrame); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set timeout to wait for content to read | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param int $seconds_to_wait  Seconds to wait for a frame | 
					
						
							|  |  |  |      * @param int $milliseconds Milliseconds to wait for a frame | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function setReadTimeout($seconds, $milliseconds = 0)  | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->_read_timeout_seconds = $seconds; | 
					
						
							|  |  |  |         $this->_read_timeout_milliseconds = $milliseconds; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Read responce frame from server | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Stomp_Frame|Stomp_Message_Map|boolean False when no frame to read | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function readFrame () | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!$this->hasFrameToRead()) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         $rb = 1024; | 
					
						
							|  |  |  |         $data = ''; | 
					
						
							|  |  |  |         do { | 
					
						
							|  |  |  |             $read = fgets($this->_socket, $rb); | 
					
						
							|  |  |  |             if ($read === false) { | 
					
						
							|  |  |  |                 $this->_reconnect(); | 
					
						
							|  |  |  |                 return $this->readFrame(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $data .= $read; | 
					
						
							|  |  |  |             $len = strlen($data); | 
					
						
							|  |  |  |         } while (($len < 2 || ! ($data[$len - 2] == "\x00" && $data[$len - 1] == "\n"))); | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         list ($header, $body) = explode("\n\n", $data, 2); | 
					
						
							|  |  |  |         $header = explode("\n", $header); | 
					
						
							|  |  |  |         $headers = array(); | 
					
						
							|  |  |  |         $command = null; | 
					
						
							|  |  |  |         foreach ($header as $v) { | 
					
						
							|  |  |  |             if (isset($command)) { | 
					
						
							|  |  |  |                 list ($name, $value) = explode(':', $v, 2); | 
					
						
							|  |  |  |                 $headers[$name] = $value; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 $command = $v; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $frame = new Stomp_Frame($command, $headers, trim($body)); | 
					
						
							|  |  |  |         if (isset($frame->headers['amq-msg-type']) && $frame->headers['amq-msg-type'] == 'MapMessage') { | 
					
						
							|  |  |  |             require_once 'Stomp/Message/Map.php'; | 
					
						
							|  |  |  |             return new Stomp_Message_Map($frame); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             return $frame; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Check if there is a frame to read | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return boolean | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function hasFrameToRead() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $read = array($this->_socket); | 
					
						
							|  |  |  |         $write = null; | 
					
						
							|  |  |  |         $except = null; | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         $has_frame_to_read = stream_select($read, $write, $except, $this->_read_timeout_seconds, $this->_read_timeout_milliseconds); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($has_frame_to_read === false) { | 
					
						
							|  |  |  |             throw new Stomp_Exception('Check failed to determin if the socket is readable'); | 
					
						
							|  |  |  |         } else if ($has_frame_to_read > 0) { | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             return false;  | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Reconnects and renews subscriptions (if there were any) | 
					
						
							|  |  |  |      * Call this method when you detect connection problems      | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function _reconnect () | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $subscriptions = $this->_subscriptions; | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         $this->connect($this->_username, $this->_password); | 
					
						
							|  |  |  |         foreach ($subscriptions as $dest => $properties) { | 
					
						
							|  |  |  |             $this->subscribe($dest, $properties); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Graceful object desruction | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function __destruct() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->disconnect(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ?>
 |