PageRenderTime 39ms CodeModel.GetById 20ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/branches/v2.1.0/library/Microsoft/WindowsAzure/Storage/Queue.php

#
PHP | 582 lines | 312 code | 58 blank | 212 comment | 86 complexity | 7afdb4d1c3942ed2ba52e165ca27f839 MD5 | raw file
  1<?php
  2/**
  3 * Copyright (c) 2009 - 2010, RealDolmen
  4 * All rights reserved.
  5 *
  6 * Redistribution and use in source and binary forms, with or without
  7 * modification, are permitted provided that the following conditions are met:
  8 *     * Redistributions of source code must retain the above copyright
  9 *       notice, this list of conditions and the following disclaimer.
 10 *     * Redistributions in binary form must reproduce the above copyright
 11 *       notice, this list of conditions and the following disclaimer in the
 12 *       documentation and/or other materials provided with the distribution.
 13 *     * Neither the name of RealDolmen nor the
 14 *       names of its contributors may be used to endorse or promote products
 15 *       derived from this software without specific prior written permission.
 16 *
 17 * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 20 * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 27 *
 28 * @category   Microsoft
 29 * @package    Microsoft_WindowsAzure
 30 * @subpackage Storage
 31 * @copyright  Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
 32 * @license    http://todo     name_todo
 33 * @version    $Id: Blob.php 24241 2009-07-22 09:43:13Z unknown $
 34 */
 35
 36/**
 37 * @see Microsoft_WindowsAzure_Credentials_SharedKey
 38 */
 39require_once 'Microsoft/WindowsAzure/Credentials/SharedKey.php';
 40
 41/**
 42 * @see Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
 43 */
 44require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
 45
 46/**
 47 * @see Microsoft_Http_Client
 48 */
 49require_once 'Microsoft/Http/Client.php';
 50
 51/**
 52 * @see Microsoft_Http_Response
 53 */
 54require_once 'Microsoft/Http/Response.php';
 55
 56/**
 57 * @see Microsoft_WindowsAzure_Storage
 58 */
 59require_once 'Microsoft/WindowsAzure/Storage.php';
 60
 61/**
 62 * Microsoft_WindowsAzure_Storage_QueueInstance
 63 */
 64require_once 'Microsoft/WindowsAzure/Storage/QueueInstance.php';
 65
 66/**
 67 * Microsoft_WindowsAzure_Storage_QueueMessage
 68 */
 69require_once 'Microsoft/WindowsAzure/Storage/QueueMessage.php';
 70
 71/**
 72 * @see Microsoft_WindowsAzure_Exception
 73 */
 74require_once 'Microsoft/WindowsAzure/Exception.php';
 75
 76
 77/**
 78 * @category   Microsoft
 79 * @package    Microsoft_WindowsAzure
 80 * @subpackage Storage
 81 * @copyright  Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
 82 * @license    http://phpazure.codeplex.com/license
 83 */
 84class Microsoft_WindowsAzure_Storage_Queue extends Microsoft_WindowsAzure_Storage
 85{
 86	/**
 87	 * Maximal message size (in bytes)
 88	 */
 89	const MAX_MESSAGE_SIZE = 8388608;
 90	
 91	/**
 92	 * Maximal message ttl (in seconds)
 93	 */
 94	const MAX_MESSAGE_TTL = 604800;
 95	
 96	/**
 97	 * Creates a new Microsoft_WindowsAzure_Storage_Queue instance
 98	 *
 99	 * @param string $host Storage host name
100	 * @param string $accountName Account name for Windows Azure
101	 * @param string $accountKey Account key for Windows Azure
102	 * @param boolean $usePathStyleUri Use path-style URI's
103	 * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
104	 */
105	public function __construct($host = Microsoft_WindowsAzure_Storage::URL_DEV_QUEUE, $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT, $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY, $usePathStyleUri = false, Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
106	{
107		parent::__construct($host, $accountName, $accountKey, $usePathStyleUri, $retryPolicy);
108		
109		// API version
110		$this->_apiVersion = '2009-09-19';
111	}
112	
113	/**
114	 * Check if a queue exists
115	 * 
116	 * @param string $queueName Queue name
117	 * @return boolean
118	 */
119	public function queueExists($queueName = '')
120	{
121		if ($queueName === '') {
122			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
123		}
124		if (!self::isValidQueueName($queueName)) {
125		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
126		}
127			
128		// List queues
129        $queues = $this->listQueues($queueName, 1);
130        foreach ($queues as $queue) {
131            if ($queue->Name == $queueName) {
132                return true;
133            }
134        }
135        
136        return false;
137	}
138	
139	/**
140	 * Create queue
141	 *
142	 * @param string $queueName Queue name
143	 * @param array  $metadata  Key/value pairs of meta data
144	 * @return object Queue properties
145	 * @throws Microsoft_WindowsAzure_Exception
146	 */
147	public function createQueue($queueName = '', $metadata = array())
148	{
149		if ($queueName === '') {
150			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
151		}
152		if (!self::isValidQueueName($queueName)) {
153		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
154		}
155			
156		// Create metadata headers
157		$headers = array();
158		$headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); 
159		
160		// Perform request
161		$response = $this->_performRequest($queueName, '', Microsoft_Http_Client::PUT, $headers);	
162		if ($response->isSuccessful()) {
163		    return new Microsoft_WindowsAzure_Storage_QueueInstance(
164		        $queueName,
165		        $metadata
166		    );
167		} else {
168			throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
169		}
170	}
171	
172	/**
173	 * Create queue if it does not exist
174	 *
175	 * @param string $queueName Queue name
176	 * @param array  $metadata  Key/value pairs of meta data
177	 * @throws Microsoft_WindowsAzure_Exception
178	 */
179	public function createQueueIfNotExists($queueName = '', $metadata = array())
180	{
181		if (!$this->queueExists($queueName)) {
182			$this->createQueue($queueName, $metadata);
183		}
184	}
185	
186	/**
187	 * Get queue
188	 * 
189	 * @param string $queueName  Queue name
190	 * @return Microsoft_WindowsAzure_Storage_QueueInstance
191	 * @throws Microsoft_WindowsAzure_Exception
192	 */
193	public function getQueue($queueName = '')
194	{
195		if ($queueName === '') {
196			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
197		}
198		if (!self::isValidQueueName($queueName)) {
199		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
200		}
201		    
202		// Perform request
203		$response = $this->_performRequest($queueName, '?comp=metadata', Microsoft_Http_Client::GET);	
204		if ($response->isSuccessful()) {
205		    // Parse metadata
206		    $metadata = $this->_parseMetadataHeaders($response->getHeaders());
207
208		    // Return queue
209		    $queue = new Microsoft_WindowsAzure_Storage_QueueInstance(
210		        $queueName,
211		        $metadata
212		    );
213		    $queue->ApproximateMessageCount = intval($response->getHeader('x-ms-approximate-message-count'));
214		    return $queue;
215		} else {
216		    throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
217		}
218	}
219	
220	/**
221	 * Get queue metadata
222	 * 
223	 * @param string $queueName  Queue name
224	 * @return array Key/value pairs of meta data
225	 * @throws Microsoft_WindowsAzure_Exception
226	 */
227	public function getQueueMetadata($queueName = '')
228	{
229		if ($queueName === '') {
230			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
231		}
232		if (!self::isValidQueueName($queueName)) {
233		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
234		}
235			
236	    return $this->getQueue($queueName)->Metadata;
237	}
238	
239	/**
240	 * Set queue metadata
241	 * 
242	 * Calling the Set Queue Metadata operation overwrites all existing metadata that is associated with the queue. It's not possible to modify an individual name/value pair.
243	 *
244	 * @param string $queueName  Queue name
245	 * @param array  $metadata       Key/value pairs of meta data
246	 * @throws Microsoft_WindowsAzure_Exception
247	 */
248	public function setQueueMetadata($queueName = '', $metadata = array())
249	{
250		if ($queueName === '') {
251			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
252		}
253		if (!self::isValidQueueName($queueName)) {
254		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
255		}
256		if (count($metadata) == 0) {
257		    return;
258		}
259		    
260		// Create metadata headers
261		$headers = array();
262		$headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); 
263		
264		// Perform request
265		$response = $this->_performRequest($queueName, '?comp=metadata', Microsoft_Http_Client::PUT, $headers);
266
267		if (!$response->isSuccessful()) {
268			throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
269		}
270	}
271	
272	/**
273	 * Delete queue
274	 *
275	 * @param string $queueName Queue name
276	 * @throws Microsoft_WindowsAzure_Exception
277	 */
278	public function deleteQueue($queueName = '')
279	{
280		if ($queueName === '') {
281			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
282		}
283		if (!self::isValidQueueName($queueName)) {
284		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
285		}
286			
287		// Perform request
288		$response = $this->_performRequest($queueName, '', Microsoft_Http_Client::DELETE);
289		if (!$response->isSuccessful()) {
290			throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
291		}
292	}
293	
294	/**
295	 * List queues
296	 *
297	 * @param string $prefix     Optional. Filters the results to return only queues whose name begins with the specified prefix.
298	 * @param int    $maxResults Optional. Specifies the maximum number of queues to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000)
299	 * @param string $marker     Optional string value that identifies the portion of the list to be returned with the next list operation.
300	 * @param string $include    Optional. Include this parameter to specify that the queue's metadata be returned as part of the response body. (allowed values: '', 'metadata')
301	 * @param int    $currentResultCount Current result count (internal use)
302	 * @return array
303	 * @throws Microsoft_WindowsAzure_Exception
304	 */
305	public function listQueues($prefix = null, $maxResults = null, $marker = null, $include = null, $currentResultCount = 0)
306	{
307	    // Build query string
308		$queryString = array('comp=list');
309        if (!is_null($prefix)) {
310	        $queryString[] = 'prefix=' . $prefix;
311        }
312	    if (!is_null($maxResults)) {
313	        $queryString[] = 'maxresults=' . $maxResults;
314	    }
315	    if (!is_null($marker)) {
316	        $queryString[] = 'marker=' . $marker;
317	    }
318		if (!is_null($include)) {
319	        $queryString[] = 'include=' . $include;
320	    }
321	    $queryString = self::createQueryStringFromArray($queryString);
322	        
323		// Perform request
324		$response = $this->_performRequest('', $queryString, Microsoft_Http_Client::GET);	
325		if ($response->isSuccessful()) {
326			$xmlQueues = $this->_parseResponse($response)->Queues->Queue;
327			$xmlMarker = (string)$this->_parseResponse($response)->NextMarker;
328
329			$queues = array();
330			if (!is_null($xmlQueues)) {
331				for ($i = 0; $i < count($xmlQueues); $i++) {
332					$queues[] = new Microsoft_WindowsAzure_Storage_QueueInstance(
333						(string)$xmlQueues[$i]->Name,
334						$this->_parseMetadataElement($xmlQueues[$i])
335					);
336				}
337			}
338			$currentResultCount = $currentResultCount + count($queues);
339			if (!is_null($maxResults) && $currentResultCount < $maxResults) {
340    			if (!is_null($xmlMarker) && $xmlMarker != '') {
341    			    $queues = array_merge($queues, $this->listQueues($prefix, $maxResults, $xmlMarker, $include, $currentResultCount));
342    			}
343			}
344			if (!is_null($maxResults) && count($queues) > $maxResults) {
345			    $queues = array_slice($queues, 0, $maxResults);
346			}
347			    
348			return $queues;
349		} else {
350			throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
351		}
352	}
353	
354	/**
355	 * Put message into queue
356	 *
357	 * @param string $queueName  Queue name
358	 * @param string $message    Message
359	 * @param int    $ttl        Message Time-To-Live (in seconds). Defaults to 7 days if the parameter is omitted.
360	 * @throws Microsoft_WindowsAzure_Exception
361	 */
362	public function putMessage($queueName = '', $message = '', $ttl = null)
363	{
364		if ($queueName === '') {
365			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
366		}
367		if (!self::isValidQueueName($queueName)) {
368		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
369		}
370		if (strlen($message) > self::MAX_MESSAGE_SIZE) {
371		    throw new Microsoft_WindowsAzure_Exception('Message is too big. Message content should be < 8KB.');
372		}
373		if ($message == '') {
374		    throw new Microsoft_WindowsAzure_Exception('Message is not specified.');
375		}
376		if (!is_null($ttl) && ($ttl <= 0 || $ttl > self::MAX_MESSAGE_SIZE)) {
377		    throw new Microsoft_WindowsAzure_Exception('Message TTL is invalid. Maximal TTL is 7 days (' . self::MAX_MESSAGE_SIZE . ' seconds) and should be greater than zero.');
378		}
379		    
380	    // Build query string
381		$queryString = array();
382        if (!is_null($ttl)) {
383	        $queryString[] = 'messagettl=' . $ttl;
384        }
385	    $queryString = self::createQueryStringFromArray($queryString);
386	        
387	    // Build body
388	    $rawData = '';
389	    $rawData .= '<QueueMessage>';
390	    $rawData .= '    <MessageText>' . base64_encode($message) . '</MessageText>';
391	    $rawData .= '</QueueMessage>';
392	        
393		// Perform request
394		$response = $this->_performRequest($queueName . '/messages', $queryString, Microsoft_Http_Client::POST, array(), false, $rawData);
395
396		if (!$response->isSuccessful()) {
397			throw new Microsoft_WindowsAzure_Exception('Error putting message into queue.');
398		}
399	}
400	
401	/**
402	 * Get queue messages
403	 *
404	 * @param string $queueName         Queue name
405	 * @param string $numOfMessages     Optional. A nonzero integer value that specifies the number of messages to retrieve from the queue, up to a maximum of 32. By default, a single message is retrieved from the queue with this operation.
406	 * @param int    $visibilityTimeout Optional. An integer value that specifies the message's visibility timeout in seconds. The maximum value is 2 hours. The default message visibility timeout is 30 seconds.
407	 * @param string $peek              Peek only?
408	 * @return array
409	 * @throws Microsoft_WindowsAzure_Exception
410	 */
411	public function getMessages($queueName = '', $numOfMessages = 1, $visibilityTimeout = null, $peek = false)
412	{
413		if ($queueName === '') {
414			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
415		}
416		if (!self::isValidQueueName($queueName)) {
417		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
418		}
419		if ($numOfMessages < 1 || $numOfMessages > 32 || intval($numOfMessages) != $numOfMessages) {
420		    throw new Microsoft_WindowsAzure_Exception('Invalid number of messages to retrieve.');
421		}
422		if (!is_null($visibilityTimeout) && ($visibilityTimeout <= 0 || $visibilityTimeout > 7200)) {
423		    throw new Microsoft_WindowsAzure_Exception('Visibility timeout is invalid. Maximum value is 2 hours (7200 seconds) and should be greater than zero.');
424		}
425		    
426	    // Build query string
427		$queryString = array();
428    	if ($peek) {
429    	    $queryString[] = 'peekonly=true';
430    	}
431    	if ($numOfMessages > 1) {
432	        $queryString[] = 'numofmessages=' . $numOfMessages;
433    	}
434    	if (!$peek && !is_null($visibilityTimeout)) {
435	        $queryString[] = 'visibilitytimeout=' . $visibilityTimeout;
436    	}   
437	    $queryString = self::createQueryStringFromArray($queryString);
438	        
439		// Perform request
440		$response = $this->_performRequest($queueName . '/messages', $queryString, Microsoft_Http_Client::GET);	
441		if ($response->isSuccessful()) {
442		    // Parse results
443			$result = $this->_parseResponse($response);
444		    if (!$result) {
445		        return array();
446		    }
447
448		    $xmlMessages = null;
449		    if (count($result->QueueMessage) > 1) {
450    		    $xmlMessages = $result->QueueMessage;
451    		} else {
452    		    $xmlMessages = array($result->QueueMessage);
453    		}
454
455			$messages = array();
456			for ($i = 0; $i < count($xmlMessages); $i++) {
457				$messages[] = new Microsoft_WindowsAzure_Storage_QueueMessage(
458					(string)$xmlMessages[$i]->MessageId,
459					(string)$xmlMessages[$i]->InsertionTime,
460					(string)$xmlMessages[$i]->ExpirationTime,
461					($peek ? '' : (string)$xmlMessages[$i]->PopReceipt),
462					($peek ? '' : (string)$xmlMessages[$i]->TimeNextVisible),
463					(string)$xmlMessages[$i]->DequeueCount,
464					base64_decode((string)$xmlMessages[$i]->MessageText)
465			    );
466			}
467			    
468			return $messages;
469		} else {
470			throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
471		}
472	}
473	
474	/**
475	 * Peek queue messages
476	 *
477	 * @param string $queueName         Queue name
478	 * @param string $numOfMessages     Optional. A nonzero integer value that specifies the number of messages to retrieve from the queue, up to a maximum of 32. By default, a single message is retrieved from the queue with this operation.
479	 * @return array
480	 * @throws Microsoft_WindowsAzure_Exception
481	 */
482	public function peekMessages($queueName = '', $numOfMessages = 1)
483	{
484	    return $this->getMessages($queueName, $numOfMessages, null, true);
485	}
486	
487	/**
488	 * Clear queue messages
489	 *
490	 * @param string $queueName         Queue name
491	 * @throws Microsoft_WindowsAzure_Exception
492	 */
493	public function clearMessages($queueName = '')
494	{
495		if ($queueName === '') {
496			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
497		}
498		if (!self::isValidQueueName($queueName)) {
499		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
500		}
501
502		// Perform request
503		$response = $this->_performRequest($queueName . '/messages', '', Microsoft_Http_Client::DELETE);	
504		if (!$response->isSuccessful()) {
505			throw new Microsoft_WindowsAzure_Exception('Error clearing messages from queue.');
506		}
507	}
508	
509	/**
510	 * Delete queue message
511	 *
512	 * @param string $queueName         					Queue name
513	 * @param Microsoft_WindowsAzure_Storage_QueueMessage $message Message to delete from queue. A message retrieved using "peekMessages" can NOT be deleted!
514	 * @throws Microsoft_WindowsAzure_Exception
515	 */
516	public function deleteMessage($queueName = '', Microsoft_WindowsAzure_Storage_QueueMessage $message)
517	{
518		if ($queueName === '') {
519			throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
520		}
521		if (!self::isValidQueueName($queueName)) {
522		    throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
523		}
524		if ($message->PopReceipt == '') {
525		    throw new Microsoft_WindowsAzure_Exception('A message retrieved using "peekMessages" can NOT be deleted! Use "getMessages" instead.');
526		}
527
528		// Perform request
529		$response = $this->_performRequest($queueName . '/messages/' . $message->MessageId, '?popreceipt=' . $message->PopReceipt, Microsoft_Http_Client::DELETE);	
530		if (!$response->isSuccessful()) {
531			throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
532		}
533	}
534	
535	/**
536	 * Is valid queue name?
537	 *
538	 * @param string $queueName Queue name
539	 * @return boolean
540	 */
541    public static function isValidQueueName($queueName = '')
542    {
543        if (preg_match("/^[a-z0-9][a-z0-9-]*$/", $queueName) === 0) {
544            return false;
545        }
546    
547        if (strpos($queueName, '--') !== false) {
548            return false;
549        }
550    
551        if (strtolower($queueName) != $queueName) {
552            return false;
553        }
554    
555        if (strlen($queueName) < 3 || strlen($queueName) > 63) {
556            return false;
557        }
558            
559        if (substr($queueName, -1) == '-') {
560            return false;
561        }
562    
563        return true;
564    }
565    
566	/**
567	 * Get error message from Microsoft_Http_Response
568	 * 
569	 * @param Microsoft_Http_Response $response Repsonse
570	 * @param string $alternativeError Alternative error message
571	 * @return string
572	 */
573	protected function _getErrorMessage(Microsoft_Http_Response $response, $alternativeError = 'Unknown error.')
574	{
575		$response = $this->_parseResponse($response);
576		if ($response && $response->Message) {
577		    return (string)$response->Message;
578		} else {
579		    return $alternativeError;
580		}
581	}
582}