web/lib/Zend/Cloud/StorageService/Adapter/WindowsAzure.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * LICENSE
       
     4  *
       
     5  * This source file is subject to the new BSD license that is bundled
       
     6  * with this package in the file LICENSE.txt.
       
     7  * It is also available through the world-wide-web at this URL:
       
     8  * http://framework.zend.com/license/new-bsd
       
     9  * If you did not receive a copy of the license and are unable to
       
    10  * obtain it through the world-wide-web, please send an email
       
    11  * to license@zend.com so we can send you a copy immediately.
       
    12  *
       
    13  * @category   Zend
       
    14  * @package    Zend_Cloud
       
    15  * @subpackage StorageService
       
    16  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    17  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    18  */
       
    19 
       
    20 require_once 'Zend/Cloud/StorageService/Adapter.php';
       
    21 require_once 'Zend/Service/WindowsAzure/Storage/Blob.php';
       
    22 require_once 'Zend/Cloud/StorageService/Exception.php';
       
    23 
       
    24 /**
       
    25  *
       
    26  * Windows Azure Blob Service abstraction
       
    27  * 
       
    28  * @category   Zend
       
    29  * @package    Zend_Cloud
       
    30  * @subpackage StorageService
       
    31  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    32  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    33  */
       
    34 class Zend_Cloud_StorageService_Adapter_WindowsAzure 
       
    35     implements Zend_Cloud_StorageService_Adapter
       
    36 {
       
    37     const ACCOUNT_NAME      = 'storage_accountname';
       
    38     const ACCOUNT_KEY       = 'storage_accountkey';
       
    39     const HOST              = "storage_host";
       
    40     const PROXY_HOST        = "storage_proxy_host";
       
    41     const PROXY_PORT        = "storage_proxy_port";
       
    42     const PROXY_CREDENTIALS = "storage_proxy_credentials";
       
    43     const CONTAINER         = "storage_container";
       
    44     const RETURN_TYPE       = 'return_type';
       
    45     const RETURN_PATHNAME   = 'return_path';
       
    46     const RETURN_OPENMODE   = 'return_openmode';
       
    47     
       
    48     /** return types  for fetch */
       
    49     const RETURN_PATH   = 1;   // return filename
       
    50     const RETURN_STRING = 2; // return data as string
       
    51     const RETURN_STREAM = 3; // return PHP stream
       
    52 
       
    53     /** return types  for list */
       
    54     const RETURN_LIST  = 1;   // return native list
       
    55     const RETURN_NAMES = 2;  // return only names
       
    56     
       
    57     const DEFAULT_HOST = Zend_Service_WindowsAzure_Storage::URL_CLOUD_BLOB;
       
    58 
       
    59     /**
       
    60      * Storage container to operate on
       
    61      * 
       
    62      * @var string
       
    63      */
       
    64     protected $_container;
       
    65     
       
    66     /**
       
    67      * Storage client
       
    68      * 
       
    69      * @var Zend_Service_WindowsAzure_Storage_Blob
       
    70      */
       
    71     protected $_storageClient = null;
       
    72 
       
    73     /**
       
    74      * Creates a new Zend_Cloud_Storage_WindowsAzure instance
       
    75      * 
       
    76      * @param array|Zend_Config  $options   Options for the Zend_Cloud_Storage_WindowsAzure instance
       
    77      */
       
    78     public function __construct($options = array())
       
    79     {
       
    80         if ($options instanceof Zend_Config) {
       
    81             $options = $options->toArray();
       
    82         }
       
    83 
       
    84         if (!is_array($options)) {
       
    85             throw new Zend_Cloud_StorageService_Exception('Invalid options provided');
       
    86         }
       
    87 
       
    88         // Build Zend_Service_WindowsAzure_Storage_Blob instance
       
    89         if (!isset($options[self::HOST])) {
       
    90             $host = self::DEFAULT_HOST;
       
    91         } else {
       
    92             $host = $options[self::HOST];
       
    93         }
       
    94         
       
    95         if (!isset($options[self::ACCOUNT_NAME])) {
       
    96             throw new Zend_Cloud_StorageService_Exception('No Windows Azure account name provided.');
       
    97         }
       
    98         if (!isset($options[self::ACCOUNT_KEY])) {
       
    99             throw new Zend_Cloud_StorageService_Exception('No Windows Azure account key provided.');
       
   100         }
       
   101             
       
   102         $this->_storageClient = new Zend_Service_WindowsAzure_Storage_Blob($host,
       
   103              $options[self::ACCOUNT_NAME], $options[self::ACCOUNT_KEY]);
       
   104         
       
   105         // Parse other options
       
   106         if (!empty($options[self::PROXY_HOST])) {
       
   107             $proxyHost = $options[self::PROXY_HOST];
       
   108             $proxyPort = isset($options[self::PROXY_PORT]) ? $options[self::PROXY_PORT] : 8080;
       
   109             $proxyCredentials = isset($options[self::PROXY_CREDENTIALS]) ? $options[self::PROXY_CREDENTIALS] : '';
       
   110             
       
   111             $this->_storageClient->setProxy(true, $proxyHost, $proxyPort, $proxyCredentials);
       
   112         }
       
   113         
       
   114         if (isset($options[self::HTTP_ADAPTER])) {
       
   115             $this->_storageClient->setHttpClientChannel($options[self::HTTP_ADAPTER]);
       
   116         }
       
   117         
       
   118         // Set container
       
   119         $this->_container = $options[self::CONTAINER];
       
   120 
       
   121         // Make sure the container exists
       
   122         if (!$this->_storageClient->containerExists($this->_container)) {
       
   123             $this->_storageClient->createContainer($this->_container);
       
   124         }
       
   125     }
       
   126     
       
   127     /**
       
   128      * Get an item from the storage service.
       
   129      *
       
   130      * @param  string $path
       
   131      * @param  array $options
       
   132      * @return mixed
       
   133      */
       
   134     public function fetchItem($path, $options = null)
       
   135     {
       
   136         // Options
       
   137         $returnType = self::RETURN_STRING; 
       
   138         $returnPath = tempnam('', 'azr');
       
   139         $openMode   = 'r';
       
   140         
       
   141         // Parse options
       
   142         if (is_array($options)) {
       
   143             if (isset($options[self::RETURN_TYPE])) {
       
   144                 $returnType = $options[self::RETURN_TYPE];
       
   145             }
       
   146                 
       
   147             if (isset($options[self::RETURN_PATHNAME])) {
       
   148                 $returnPath = $options[self::RETURN_PATHNAME];
       
   149             }
       
   150                 
       
   151             if (isset($options[self::RETURN_OPENMODE])) {
       
   152                 $openMode = $options[self::RETURN_OPENMODE];
       
   153             }
       
   154         }
       
   155         
       
   156         // Fetch the blob
       
   157         try {
       
   158             $this->_storageClient->getBlob(
       
   159                 $this->_container,
       
   160                 $path,
       
   161                 $returnPath
       
   162             );
       
   163         } catch (Zend_Service_WindowsAzure_Exception $e) {
       
   164             if (strpos($e->getMessage(), "does not exist") !== false) {
       
   165                 return false;
       
   166             }
       
   167             throw new Zend_Cloud_StorageService_Exception('Error on fetch: '.$e->getMessage(), $e->getCode(), $e);
       
   168         }
       
   169         
       
   170         // Return value
       
   171         if ($returnType == self::RETURN_PATH) {
       
   172             return $returnPath;
       
   173         }
       
   174         if ($returnType == self::RETURN_STRING) {
       
   175             return file_get_contents($returnPath);
       
   176         }
       
   177         if ($returnType == self::RETURN_STREAM) {
       
   178             return fopen($returnPath, $openMode);
       
   179         }
       
   180     }
       
   181     
       
   182     /**
       
   183      * Store an item in the storage service.
       
   184      * WARNING: This operation overwrites any item that is located at 
       
   185      * $destinationPath.
       
   186      * @param string $destinationPath
       
   187      * @param mixed  $data
       
   188      * @param  array $options
       
   189      * @return boolean
       
   190      */
       
   191     public function storeItem($destinationPath, $data, $options = null) 
       
   192     {
       
   193         // Create a temporary file that will be uploaded
       
   194         $temporaryFilePath       = '';
       
   195         $removeTemporaryFilePath = false;
       
   196 
       
   197         if (is_resource($data))    {
       
   198             $temporaryFilePath = tempnam('', 'azr');
       
   199             $fpDestination     = fopen($temporaryFilePath, 'w');
       
   200 
       
   201             $fpSource = $data;
       
   202             rewind($fpSource);
       
   203             while (!feof($fpSource)) {
       
   204                 fwrite($fpDestination, fread($fpSource, 8192));
       
   205             }
       
   206             
       
   207             fclose($fpDestination);
       
   208             
       
   209             $removeTemporaryFilePath = true;
       
   210         } elseif (file_exists($data)) {
       
   211             $temporaryFilePath       = $data;
       
   212             $removeTemporaryFilePath = false;
       
   213         } else {
       
   214             $temporaryFilePath = tempnam('', 'azr');
       
   215             file_put_contents($temporaryFilePath, $data);
       
   216             $removeTemporaryFilePath = true;
       
   217         }
       
   218         
       
   219         try {
       
   220             // Upload data
       
   221             $this->_storageClient->putBlob(
       
   222                 $this->_container,
       
   223                 $destinationPath,
       
   224                 $temporaryFilePath
       
   225             );
       
   226         } catch(Zend_Service_WindowsAzure_Exception $e) {
       
   227             @unlink($temporaryFilePath);
       
   228             throw new Zend_Cloud_StorageService_Exception('Error on store: '.$e->getMessage(), $e->getCode(), $e);        
       
   229         }
       
   230         if ($removeTemporaryFilePath) {
       
   231             @unlink($temporaryFilePath);
       
   232         }
       
   233     }
       
   234     
       
   235     /**
       
   236      * Delete an item in the storage service.
       
   237      *
       
   238      * @param  string $path
       
   239      * @param  array  $options
       
   240      * @return void
       
   241      */
       
   242     public function deleteItem($path, $options = null)
       
   243     {
       
   244         try {
       
   245             $this->_storageClient->deleteBlob(
       
   246                 $this->_container,
       
   247                 $path
       
   248             );
       
   249         } catch (Zend_Service_WindowsAzure_Exception $e) { 
       
   250             throw new Zend_Cloud_StorageService_Exception('Error on delete: '.$e->getMessage(), $e->getCode(), $e);
       
   251         }
       
   252     }
       
   253     
       
   254     /**
       
   255      * Copy an item in the storage service to a given path.
       
   256      *
       
   257      * @param  string $sourcePath
       
   258      * @param  string $destinationPath
       
   259      * @param  array  $options
       
   260      * @return void
       
   261      */
       
   262     public function copyItem($sourcePath, $destinationPath, $options = null)
       
   263     {
       
   264         try {
       
   265             $this->_storageClient->copyBlob(
       
   266                 $this->_container,
       
   267                 $sourcePath,
       
   268                 $this->_container,
       
   269                 $destinationPath
       
   270             );
       
   271         } catch (Zend_Service_WindowsAzure_Exception $e) { 
       
   272             throw new Zend_Cloud_StorageService_Exception('Error on copy: '.$e->getMessage(), $e->getCode(), $e);
       
   273         }
       
   274     }
       
   275     
       
   276     /**
       
   277      * Move an item in the storage service to a given path.
       
   278      *
       
   279      * @param  string $sourcePath
       
   280      * @param  string $destinationPath
       
   281      * @param  array  $options
       
   282      * @return void
       
   283      */
       
   284     public function moveItem($sourcePath, $destinationPath, $options = null)
       
   285     {
       
   286         try {
       
   287             $this->_storageClient->copyBlob(
       
   288                 $this->_container,
       
   289                 $sourcePath,
       
   290                 $this->_container,
       
   291                 $destinationPath
       
   292             );
       
   293             
       
   294             $this->_storageClient->deleteBlob(
       
   295                 $this->_container,
       
   296                 $sourcePath
       
   297             );
       
   298         } catch (Zend_Service_WindowsAzure_Exception $e) { 
       
   299             throw new Zend_Cloud_StorageService_Exception('Error on move: '.$e->getMessage(), $e->getCode(), $e);
       
   300         }
       
   301             
       
   302     }
       
   303     
       
   304     /**
       
   305      * Rename an item in the storage service to a given name.
       
   306      *
       
   307      *
       
   308      * @param  string $path
       
   309      * @param  string $name
       
   310      * @param  array $options
       
   311      * @return void
       
   312      */
       
   313     public function renameItem($path, $name, $options = null)
       
   314     {
       
   315         return $this->moveItem($path, $name, $options);
       
   316     }
       
   317     
       
   318     /**
       
   319      * List items in the given directory in the storage service
       
   320      * 
       
   321      * The $path must be a directory
       
   322      *
       
   323      *
       
   324      * @param  string $path Must be a directory
       
   325      * @param  array $options
       
   326      * @return array A list of item names
       
   327      */
       
   328     public function listItems($path, $options = null)
       
   329     {
       
   330         // Options
       
   331         $returnType = self::RETURN_NAMES; // 1: return list of paths, 2: return raw output from underlying provider
       
   332         
       
   333         // Parse options
       
   334         if (is_array($options)&& isset($options[self::RETURN_TYPE])) {
       
   335                $returnType = $options[self::RETURN_TYPE];
       
   336         }
       
   337         
       
   338         try {
       
   339             // Fetch list
       
   340             $blobList = $this->_storageClient->listBlobs(
       
   341                 $this->_container,
       
   342                 $path
       
   343             );
       
   344         } catch (Zend_Service_WindowsAzure_Exception $e) { 
       
   345             throw new Zend_Cloud_StorageService_Exception('Error on list: '.$e->getMessage(), $e->getCode(), $e);
       
   346         }
       
   347         
       
   348         // Return
       
   349         if ($returnType == self::RETURN_LIST) {
       
   350             return $blobList;
       
   351         }
       
   352         
       
   353         $returnValue = array();
       
   354         foreach ($blobList as $blob) {
       
   355             $returnValue[] = $blob->Name;
       
   356         }
       
   357             
       
   358         return $returnValue;
       
   359     }
       
   360 
       
   361     /**
       
   362      * Get a key/value array of metadata for the given path.
       
   363      *
       
   364      * @param  string $path
       
   365      * @param  array  $options
       
   366      * @return array
       
   367      */
       
   368     public function fetchMetadata($path, $options = null)
       
   369     {
       
   370         try {
       
   371             return $this->_storageClient->getBlobMetaData(
       
   372                 $this->_container,
       
   373                 $path
       
   374             );
       
   375         } catch (Zend_Service_WindowsAzure_Exception $e) {
       
   376             if (strpos($e->getMessage(), "could not be accessed") !== false) {
       
   377                 return false;
       
   378             }
       
   379             throw new Zend_Cloud_StorageService_Exception('Error on fetch: '.$e->getMessage(), $e->getCode(), $e);
       
   380         }
       
   381     }
       
   382     
       
   383     /**
       
   384      * Store a key/value array of metadata at the given path.
       
   385      * WARNING: This operation overwrites any metadata that is located at 
       
   386      * $destinationPath.
       
   387      *
       
   388      * @param  string $destinationPath
       
   389      * @param  array $options
       
   390      * @return void
       
   391      */
       
   392     public function storeMetadata($destinationPath, $metadata, $options = null)
       
   393     {
       
   394         try    {
       
   395             $this->_storageClient->setBlobMetadata($this->_container, $destinationPath, $metadata);
       
   396         } catch (Zend_Service_WindowsAzure_Exception $e) {
       
   397             if (strpos($e->getMessage(), "could not be accessed") === false) {
       
   398                 throw new Zend_Cloud_StorageService_Exception('Error on store metadata: '.$e->getMessage(), $e->getCode(), $e);
       
   399             }
       
   400         }
       
   401     }
       
   402     
       
   403     /**
       
   404      * Delete a key/value array of metadata at the given path.
       
   405      *
       
   406      * @param  string $path
       
   407      * @param  array $options
       
   408      * @return void
       
   409      */
       
   410     public function deleteMetadata($path, $options = null)
       
   411     {
       
   412         try {
       
   413             $this->_storageClient->setBlobMetadata($this->_container, $destinationPath, array());
       
   414         } catch (Zend_Service_WindowsAzure_Exception $e) {
       
   415             if (strpos($e->getMessage(), "could not be accessed") === false) {
       
   416                 throw new Zend_Cloud_StorageService_Exception('Error on delete metadata: '.$e->getMessage(), $e->getCode(), $e);
       
   417             }
       
   418         }
       
   419     }
       
   420     
       
   421     /**
       
   422      * Delete container
       
   423      * 
       
   424      * @return void
       
   425      */
       
   426     public function deleteContainer()
       
   427     {
       
   428         try {
       
   429             $this->_storageClient->deleteContainer($this->_container);
       
   430         } catch (Zend_Service_WindowsAzure_Exception $e) { 
       
   431             throw new Zend_Cloud_StorageService_Exception('Error on delete: '.$e->getMessage(), $e->getCode(), $e);
       
   432         }
       
   433     }
       
   434 
       
   435     /**
       
   436      * Get the concrete adapter.
       
   437      * @return Zend_Service_Azure_Storage_Blob
       
   438      */
       
   439     public function getClient()
       
   440     {
       
   441          return $this->_storageClient;       
       
   442     }
       
   443 }