PageRenderTime 145ms CodeModel.GetById 100ms app.highlight 12ms RepoModel.GetById 28ms app.codeStats 1ms

/Zend/Queue/Adapter/Activemq.php

https://bitbucket.org/simukti/zf1
PHP | 366 lines | 187 code | 38 blank | 141 comment | 20 complexity | 317b850217311f2c2dc41b309a7a6ae4 MD5 | raw file
  1<?php
  2/**
  3 * Zend Framework
  4 *
  5 * LICENSE
  6 *
  7 * This source file is subject to the new BSD license that is bundled
  8 * with this package in the file LICENSE.txt.
  9 * It is also available through the world-wide-web at this URL:
 10 * http://framework.zend.com/license/new-bsd
 11 * If you did not receive a copy of the license and are unable to
 12 * obtain it through the world-wide-web, please send an email
 13 * to license@zend.com so we can send you a copy immediately.
 14 *
 15 * @category   Zend
 16 * @package    Zend_Queue
 17 * @subpackage Adapter
 18 * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 19 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 20 * @version    $Id: Activemq.php 24593 2012-01-05 20:35:02Z matthew $
 21 */
 22
 23/**
 24 * @see Zend_Queue_Adapter_AdapterAbstract
 25 */
 26require_once 'Zend/Queue/Adapter/AdapterAbstract.php';
 27
 28/**
 29 * @see Zend_Queue_Adapter_Stomp_Client
 30 */
 31require_once 'Zend/Queue/Stomp/Client.php';
 32
 33/**
 34 * @see Zend_Queue_Adapter_Stomp_Frame
 35 */
 36require_once 'Zend/Queue/Stomp/Frame.php';
 37
 38/**
 39 * Class for using Stomp to talk to an Stomp compliant server
 40 *
 41 * @category   Zend
 42 * @package    Zend_Queue
 43 * @subpackage Adapter
 44 * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 45 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 46 */
 47class Zend_Queue_Adapter_Activemq extends Zend_Queue_Adapter_AdapterAbstract
 48{
 49    const DEFAULT_SCHEME = 'tcp';
 50    const DEFAULT_HOST   = '127.0.0.1';
 51    const DEFAULT_PORT   = 61613;
 52
 53    /**
 54     * @var Zend_Queue_Adapter_Stomp_client
 55     */
 56    private $_client = null;
 57
 58    /**
 59     * @var array
 60     */
 61    private $_subscribed = array();
 62
 63    /**
 64     * Constructor
 65     *
 66     * @param  array|Zend_Config $config An array having configuration data
 67     * @param  Zend_Queue The Zend_Queue object that created this class
 68     * @return void
 69     */
 70    public function __construct($options, Zend_Queue $queue = null)
 71    {
 72        parent::__construct($options);
 73
 74        $options = &$this->_options['driverOptions'];
 75        if (!array_key_exists('scheme', $options)) {
 76            $options['scheme'] = self::DEFAULT_SCHEME;
 77        }
 78        if (!array_key_exists('host', $options)) {
 79            $options['host'] = self::DEFAULT_HOST;
 80        }
 81        if (!array_key_exists('port', $options)) {
 82            $options['port'] = self::DEFAULT_PORT;
 83        }
 84
 85        if (array_key_exists('stompClient', $options)) {
 86            $this->_client = $options['stompClient'];
 87        } else {
 88            $this->_client = new Zend_Queue_Stomp_Client($options['scheme'], $options['host'], $options['port']);
 89        }
 90
 91        $connect = $this->_client->createFrame();
 92
 93        // Username and password are optional on some messaging servers
 94        // such as Apache's ActiveMQ
 95        $connect->setCommand('CONNECT');
 96        if (isset($options['username'])) {
 97            $connect->setHeader('login', $options['username']);
 98            $connect->setHeader('passcode', $options['password']);
 99        }
100
101        $response = $this->_client->send($connect)->receive();
102
103        if ((false !== $response)
104            && ($response->getCommand() != 'CONNECTED')
105        ) {
106            require_once 'Zend/Queue/Exception.php';
107            throw new Zend_Queue_Exception("Unable to authenticate to '".$options['scheme'].'://'.$options['host'].':'.$options['port']."'");
108        }
109    }
110
111    /**
112     * Close the socket explicitly when destructed
113     *
114     * @return void
115     */
116    public function __destruct()
117    {
118        // Gracefully disconnect
119        $frame = $this->_client->createFrame();
120        $frame->setCommand('DISCONNECT');
121        $this->_client->send($frame);
122        unset($this->_client);
123    }
124
125    /**
126     * Create a new queue
127     *
128     * @param  string  $name    queue name
129     * @param  integer $timeout default visibility timeout
130     * @return void
131     * @throws Zend_Queue_Exception
132     */
133    public function create($name, $timeout=null)
134    {
135        require_once 'Zend/Queue/Exception.php';
136        throw new Zend_Queue_Exception('create() is not supported in ' . get_class($this));
137    }
138
139    /**
140     * Delete a queue and all of its messages
141     *
142     * @param  string $name queue name
143     * @return void
144     * @throws Zend_Queue_Exception
145     */
146    public function delete($name)
147    {
148        require_once 'Zend/Queue/Exception.php';
149        throw new Zend_Queue_Exception('delete() is not supported in ' . get_class($this));
150    }
151
152    /**
153     * Delete a message from the queue
154     *
155     * Returns true if the message is deleted, false if the deletion is
156     * unsuccessful.
157     *
158     * @param  Zend_Queue_Message $message
159     * @return boolean
160     */
161    public function deleteMessage(Zend_Queue_Message $message)
162    {
163        $frame = $this->_client->createFrame();
164        $frame->setCommand('ACK');
165        $frame->setHeader('message-id', $message->handle);
166
167        $this->_client->send($frame);
168
169        return true;
170    }
171
172    /**
173     * Get an array of all available queues
174     *
175     * @return void
176     * @throws Zend_Queue_Exception
177     */
178    public function getQueues()
179    {
180        require_once 'Zend/Queue/Exception.php';
181        throw new Zend_Queue_Exception('getQueues() is not supported in this adapter');
182    }
183
184    /**
185     * Checks if the client is subscribed to the queue
186     *
187     * @param  Zend_Queue $queue
188     * @return boolean
189     */
190    protected function _isSubscribed(Zend_Queue $queue)
191    {
192        return isset($this->_subscribed[$queue->getName()]);
193    }
194
195    /**
196      * Subscribes the client to the queue.
197      *
198      * @param  Zend_Queue $queue
199      * @return void
200      */
201    protected function _subscribe(Zend_Queue $queue)
202    {
203        $frame = $this->_client->createFrame();
204        $frame->setCommand('SUBSCRIBE');
205        $frame->setHeader('destination', $queue->getName());
206        $frame->setHeader('ack', 'client');
207        $this->_client->send($frame);
208        $this->_subscribed[$queue->getName()] = true;
209    }
210
211    /**
212     * Return the first element in the queue
213     *
214     * @param  integer    $maxMessages
215     * @param  integer    $timeout
216     * @param  Zend_Queue $queue
217     * @return Zend_Queue_Message_Iterator
218     */
219    public function receive($maxMessages=null, $timeout=null, Zend_Queue $queue=null)
220    {
221        if ($maxMessages === null) {
222            $maxMessages = 1;
223        }
224        if ($timeout === null) {
225            $timeout = self::RECEIVE_TIMEOUT_DEFAULT;
226        }
227        if ($queue === null) {
228            $queue = $this->_queue;
229        }
230
231        // read
232        $data = array();
233
234        // signal that we are reading
235        if (!$this->_isSubscribed($queue)){
236            $this->_subscribe($queue);
237        }
238
239        if ($maxMessages > 0) {
240            if ($this->_client->canRead()) {
241                for ($i = 0; $i < $maxMessages; $i++) {
242                    $response = $this->_client->receive();
243
244                    switch ($response->getCommand()) {
245                        case 'MESSAGE':
246                            $datum = array(
247                                'message_id' => $response->getHeader('message-id'),
248                                'handle'     => $response->getHeader('message-id'),
249                                'body'       => $response->getBody(),
250                                'md5'        => md5($response->getBody())
251                            );
252                            $data[] = $datum;
253                            break;
254                        default:
255                            $block = print_r($response, true);
256                            require_once 'Zend/Queue/Exception.php';
257                            throw new Zend_Queue_Exception('Invalid response received: ' . $block);
258                    }
259                }
260            }
261        }
262
263        $options = array(
264            'queue'        => $queue,
265            'data'         => $data,
266            'messageClass' => $queue->getMessageClass()
267        );
268
269        $classname = $queue->getMessageSetClass();
270
271        if (!class_exists($classname)) {
272            require_once 'Zend/Loader.php';
273            Zend_Loader::loadClass($classname);
274        }
275        return new $classname($options);
276    }
277
278    /**
279     * Push an element onto the end of the queue
280     *
281     * @param  string     $message message to send to the queue
282     * @param  Zend_Queue $queue
283     * @return Zend_Queue_Message
284     */
285    public function send($message, Zend_Queue $queue=null)
286    {
287        if ($queue === null) {
288            $queue = $this->_queue;
289        }
290
291        $frame = $this->_client->createFrame();
292        $frame->setCommand('SEND');
293        $frame->setHeader('destination', $queue->getName());
294        $frame->setHeader('content-length', strlen($message));
295        $frame->setBody((string) $message);
296        $this->_client->send($frame);
297
298        $data = array(
299            'message_id' => null,
300            'body'       => $message,
301            'md5'        => md5($message),
302            'handle'     => null
303        );
304
305        $options = array(
306            'queue' => $queue,
307            'data'  => $data
308        );
309
310        $classname = $queue->getMessageClass();
311        if (!class_exists($classname)) {
312            require_once 'Zend/Loader.php';
313            Zend_Loader::loadClass($classname);
314        }
315        return new $classname($options);
316    }
317
318    /**
319     * Returns the length of the queue
320     *
321     * @param  Zend_Queue $queue
322     * @return integer
323     * @throws Zend_Queue_Exception (not supported)
324     */
325    public function count(Zend_Queue $queue=null)
326    {
327        require_once 'Zend/Queue/Exception.php';
328        throw new Zend_Queue_Exception('count() is not supported in this adapter');
329    }
330
331    /**
332     * Does a queue already exist?
333     *
334     * @param  string $name
335     * @return boolean
336     * @throws Zend_Queue_Exception (not supported)
337     */
338    public function isExists($name)
339    {
340        require_once 'Zend/Queue/Exception.php';
341        throw new Zend_Queue_Exception('isExists() is not supported in this adapter');
342    }
343
344    /**
345     * Return a list of queue capabilities functions
346     *
347     * $array['function name'] = true or false
348     * true is supported, false is not supported.
349     *
350     * @param  string $name
351     * @return array
352     */
353    public function getCapabilities()
354    {
355        return array(
356            'create'        => false,
357            'delete'        => false,
358            'send'          => true,
359            'receive'       => true,
360            'deleteMessage' => true,
361            'getQueues'     => false,
362            'count'         => false,
363            'isExists'      => false,
364        );
365    }
366}