configurationengine/source/cone/storage/stringstorage.py
changeset 0 2e8eeb919028
child 3 e7e0ae78773e
equal deleted inserted replaced
-1:000000000000 0:2e8eeb919028
       
     1 #
       
     2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description: 
       
    15 #
       
    16 
       
    17 import StringIO
       
    18 import os
       
    19 import pickle
       
    20 import copy
       
    21 import logging
       
    22 
       
    23 from cone.public import *
       
    24 from cone.storage import persistentdictionary
       
    25 
       
    26 
       
    27 class _StringStorageObject(container.ObjectContainer):
       
    28     def __init__(self, name):
       
    29         container.ObjectContainer.__init__(self, utils.resourceref.to_dottedref(name))
       
    30         self.path = name
       
    31         self.data = ""
       
    32 
       
    33     def get_path(self):
       
    34         """
       
    35         Return the path of the configuration resource
       
    36         """
       
    37         return self.path
       
    38 
       
    39     def set_path(self,path):
       
    40         """
       
    41         Set the path of the configuration resource
       
    42         """
       
    43         self.path = path
       
    44 
       
    45     def path_to_elem(self, toparent=None):
       
    46         parent_path = ""
       
    47         # check if the parent is found at all from this hierarchy
       
    48         if toparent and not self._find_parent_or_default(match=toparent):
       
    49             toparent = self._find_parent_or_default(container=True)
       
    50         if self._find_parent():
       
    51             parent_path = self._find_parent()._path(toparent).replace(".","/") 
       
    52         return utils.resourceref.join_refs([parent_path,self.get_path()])
       
    53     
       
    54     def __getstate__(self):
       
    55         return self.__dict__.copy()
       
    56         
       
    57     def __setstate__(self,dict):
       
    58         self.__dict__ =  dict.copy()
       
    59         
       
    60 class StringStorage(api.Storage, container.ObjectContainer):
       
    61     """
       
    62     A general base class for all storage type classes
       
    63     @param path : the reference to the root of the storage.
       
    64     """
       
    65     def __init__(self, path):
       
    66         container.ObjectContainer.__init__(self,"")
       
    67         api.Storage.__init__(self,path)
       
    68 
       
    69     def __getstate__(self):
       
    70         dict = self.__dict__.copy()
       
    71         del dict['__opened_res__']
       
    72         return dict
       
    73 
       
    74     def __setstate__(self,dict):
       
    75         self.__dict__ =  dict.copy()
       
    76         self.__dict__['__opened_res__'] = {}
       
    77 
       
    78     def __dump__(self):
       
    79         """
       
    80         Dump the storage to the reference file
       
    81         """
       
    82         file = open(self.get_path(),"w")
       
    83         pickle.dump(self,file)
       
    84         file.close()
       
    85 
       
    86     @classmethod
       
    87     def __open__(cls,path, mode="r"):
       
    88         if mode.find("a")!=-1 or mode.find("r")!=-1:
       
    89             if os.path.exists(path) and os.path.isfile(path):
       
    90                 file = open(path,"r")
       
    91                 obj = pickle.load(file)
       
    92                 file.close()
       
    93             else:
       
    94                 raise exceptions.StorageException("The given data file for storage does not exist! %s" % path)
       
    95         elif mode.find("w")!=-1:
       
    96             # check if the given storage path exists and delete it if it does
       
    97             if os.path.dirname(path) != '' and not os.path.exists(os.path.dirname(path)):
       
    98                  os.makedirs(os.path.dirname(path))
       
    99             obj = StringStorage(path)
       
   100             """ key value pairs of data. Key path = datastring """ 
       
   101         else:
       
   102             raise exceptions.StorageException("Unsupported creation mode given! %s" % mode)
       
   103         return obj
       
   104 
       
   105     @classmethod
       
   106     def supported_storage(cls,path):
       
   107         """
       
   108         Class method for determing if the given clas supports a storage by given path. 
       
   109         E.g. foo.zip, foo.cpd, foo/bar, http://foo.com/
       
   110         @param path:
       
   111         @return: Boolean value. True if the storage of the path is supported. False if not.  
       
   112         """
       
   113         if utils.resourceref.get_ext(path) == "pk":
       
   114             return True
       
   115         else:
       
   116             return False
       
   117 
       
   118     def close(self):
       
   119         """
       
   120         Close the repository, which will save and close all open resources.  
       
   121         """
       
   122         super(StringStorage,self).close()
       
   123         self.__dump__()
       
   124 
       
   125     def save(self):
       
   126         """
       
   127         Save changes from all resources to the repository.  
       
   128         """        
       
   129         super(StringStorage,self).save()
       
   130         self.__dump__()
       
   131 
       
   132     def open_resource(self,path,mode="r"):
       
   133         """
       
   134         Open the given resource and return a File object.
       
   135         @param path : reference to the resource 
       
   136         @param mode : the mode in which to open. Can be one of r = read, w = write, a = append.
       
   137         raises a NotResource exception if the path item is not a resource.
       
   138         """
       
   139         res = None
       
   140         # Add the current path in front of the given path
       
   141         path = utils.resourceref.join_refs([self.get_current_path(), path])
       
   142         dottedref = utils.resourceref.to_dref(path)
       
   143         (pathto,name)= utils.resourceref.psplit_ref(path)
       
   144         (dpath, dref) = utils.dottedref.psplit_ref(dottedref)
       
   145         
       
   146         # check for existence
       
   147         if self.get_mode(mode) == self.MODE_READ:
       
   148             try:
       
   149                 # Try to create a new StringResource in any case
       
   150                 
       
   151                 res = StringResource(self, path, self._get(dottedref).data,mode) 
       
   152             except exceptions.NotFound,e:
       
   153                 raise exceptions.NotResource("Not found %s" % path)
       
   154         elif self.get_mode(mode) == self.MODE_WRITE:
       
   155             # Create a new StringResource in any case
       
   156             self._add_to_path(dpath,_StringStorageObject(name))
       
   157             res = StringResource(self, path, self._get(dottedref).data,mode) 
       
   158         elif self.get_mode(mode) == self.MODE_APPEND:
       
   159             # Append case, create the data reference if it is not existing
       
   160             if not self._has(dottedref):
       
   161                 self._add_to_path(dpath,_StringStorageObject(name))
       
   162                         # Create a new StringResource in any case
       
   163             res = StringResource(self, path, self._get(dottedref).data,mode)
       
   164             res.seek(0, os.SEEK_END)
       
   165         self.__opened__(res)
       
   166         return res
       
   167 
       
   168     def delete_resource(self,path):
       
   169         """
       
   170         Delete the given resource from storage
       
   171         @param res : Resource objcet to the resource 
       
   172         raises a NotSupportedException exception if delete operation is not supported by the storage
       
   173         """
       
   174         # First close all open resources
       
   175         # Add the current path in front of the given path
       
   176         path = utils.resourceref.join_refs([self.curpath, path])
       
   177         for res in self.__get_open__(path):
       
   178             self.__closed__(res)
       
   179         self._remove(utils.resourceref.to_dref(path))
       
   180 
       
   181     def close_resource(self, res):
       
   182         """
       
   183         Close the given resource instance. Normally this is called by the Resource object 
       
   184         in its own close.
       
   185         @param res: the resource object to close. 
       
   186         """
       
   187         try:
       
   188             self.__closed__(res)
       
   189             if not res.get_mode() == api.Storage.MODE_READ:
       
   190                 self._get(utils.resourceref.to_dref(res.path)).data = res.getvalue()
       
   191         except KeyError,e:
       
   192             raise StorageException("No such %s open resource! %s" % (res.path,e))
       
   193             
       
   194 
       
   195     def save_resource(self, res):
       
   196         """
       
   197         Flush the changes of a given resource instance. Normally this is called by the Resource object 
       
   198         in its own save.
       
   199         @param res: the resource to the resource to save. 
       
   200         """
       
   201         if not self.__has_resource__(res):
       
   202             raise exceptions.NotResource("No such %s open resource!" % res.path)
       
   203         else:
       
   204             if not res.get_mode() == api.Storage.MODE_READ:
       
   205                 self._get(utils.resourceref.to_dref(res.path)).data = res.getvalue()
       
   206 
       
   207     def is_resource(self,path):
       
   208         """
       
   209         Return true if the path is a resource
       
   210         @param path : reference to path where resources are searched
       
   211         """
       
   212         # Add the current path in front of the given path
       
   213         path = utils.resourceref.join_refs([self.get_current_path(), path])
       
   214         return self._has(utils.resourceref.to_dref(path))
       
   215 
       
   216     def list_resources(self,path,recurse=False,empty_folders=False):
       
   217         """
       
   218         find the resources under certain path/path 
       
   219         @param path : reference to path where resources are searched
       
   220         @param recurse : defines whether to return resources directly under the path or does the listing recurse to subfolders. 
       
   221         Default value is False. Set to True to enable recursion.
       
   222         """
       
   223         """ Get the given curpath element """
       
   224         try:
       
   225             curelem = self._get(utils.resourceref.to_dref(self.get_current_path()))
       
   226             dref = utils.resourceref.to_dref(path)
       
   227             if recurse:
       
   228                 return sorted([child.path_to_elem(curelem) for child in curelem._get(dref)._traverse(type=_StringStorageObject)])
       
   229             else:
       
   230                 return sorted([child.path_to_elem(curelem) for child in curelem._get(dref)._objects(type=_StringStorageObject)])
       
   231         except exceptions.NotFound:
       
   232             return []
       
   233         
       
   234     def import_resources(self,paths,storage,empty_folders=False):
       
   235         for path in paths:
       
   236             if not storage.is_resource(path):
       
   237                 logging.getLogger('cone').warning("The given path is not a Resource in the storage %s! Ignoring from export!" % path)
       
   238                 continue
       
   239             wres = self.open_resource(path,'wb')
       
   240             res  = storage.open_resource(path,"rb")
       
   241             wres.write(res.read())
       
   242             wres.close()
       
   243             res.close()
       
   244             
       
   245 
       
   246     def create_folder(self,path):
       
   247         """
       
   248         Create a folder entry to a path
       
   249         @param path : path to the folder
       
   250         """
       
   251         if not self._has(utils.resourceref.to_dref(path)):
       
   252             (dpath,name) = utils.dottedref.psplit_ref(utils.resourceref.to_dref(path))
       
   253             self._add_to_path(dpath, self._default_object(name))
       
   254 
       
   255     def delete_folder(self,path):
       
   256         """
       
   257         Delete a folder entry from a path. The path must be empty.
       
   258         @param path : path to the folder
       
   259         """
       
   260         self._remove(utils.resourceref.to_dref(path))
       
   261 
       
   262     def is_folder(self,path):
       
   263         """
       
   264         Check if the given path is an existing folder in the storage
       
   265         @param path : path to the folder
       
   266         """
       
   267         return self._has(utils.resourceref.to_dref(path))
       
   268 
       
   269     def export_resources(self,refs,storage,empty_folders=False):
       
   270         """
       
   271         export resources from this storage based on a list of reference to this storage
       
   272         @param refs : a list of resource names in this storage (references).
       
   273         @param storage : the external storage where to export.
       
   274         """  
       
   275         storage.import_resources(refs, self, empty_folders=empty_folders)
       
   276 
       
   277     def unload(self, path, object):
       
   278         """
       
   279         Dump a given object to the storage (reference is fetched from the object)
       
   280         @param object: The object to dump to the storage, which is expected to be an instance 
       
   281         of Base class.
       
   282         """
       
   283         # Add the current path in front of the given path
       
   284         path = utils.resourceref.join_refs([self.get_current_path(), path])
       
   285         if not isinstance(object, api.Configuration):
       
   286             raise exceptions.StorageException("Cannot dump object type %s" % object.__class__)
       
   287         res = self.open_resource(path,"w")
       
   288         data = persistentdictionary.dumps(object)
       
   289         res.write(data)
       
   290         res.close()
       
   291         return
       
   292 
       
   293     def load(self, path):
       
   294         """
       
   295         Load an from a reference.
       
   296         """
       
   297         # Add the current path in front of the given path
       
   298         path = utils.resourceref.join_refs([self.get_current_path(), path])
       
   299         if not utils.resourceref.get_ext(path) == "confml":
       
   300             raise exceptions.StorageException("Cannot load object from given path = %s!" % path)
       
   301         if self.is_resource(path):
       
   302             res = self.open_resource(path,"r")
       
   303             # read the dictionary from the resource with eval
       
   304             obj = persistentdictionary.loads(res.read())
       
   305             res.close()
       
   306             return obj
       
   307         else:
       
   308             raise exceptions.NotResource("No such %s resource!" % path)
       
   309 
       
   310 class StringResource(api.Resource):
       
   311     """
       
   312     A StringResource class that works on top of StringIO buffer. This class in 
       
   313     intended mainly for testing purposes.
       
   314     """    
       
   315     def __init__(self,storage,path,stringdata, mode=api.Storage.MODE_READ):
       
   316         strio = StringIO.StringIO(stringdata)    
       
   317         api.Resource.__init__(self,storage,path, mode)
       
   318         self.handle = strio
       
   319         self.read = self.handle.read
       
   320         self.tell = self.handle.tell
       
   321         self.seek = self.handle.seek
       
   322         self.readline = self.handle.readline
       
   323         self.getvalue = self.handle.getvalue
       
   324     
       
   325     def write(self, string):
       
   326         if self.get_mode() == api.Storage.MODE_READ:
       
   327             raise exceptions.StorageException("Writing attempted to %s in read-only mode." % self.path)
       
   328         else:
       
   329             self.handle.write(string)
       
   330 
       
   331     def read(self, bytes=0):
       
   332         if self.get_mode() == api.Storage.MODE_WRITE:
       
   333             raise exceptions.StorageException("Reading attempted to %s in write-only mode." % self.path)
       
   334         else:
       
   335             self.handle.read(string)
       
   336 
       
   337     def save(self):
       
   338         self.storage.save_resource(self)
       
   339 
       
   340     def close(self):
       
   341         self.storage.close_resource(self)
       
   342         self.handle.close()
       
   343     
       
   344     def get_size(self):
       
   345         if self.get_mode() == api.Storage.MODE_WRITE:
       
   346             raise exceptions.StorageException("Reading resource size attempted to %s in write-only mode." % self.path)
       
   347         return len(self.handle.getvalue())
       
   348 
       
   349     def get_content_info(self):
       
   350         if self.content_info == None:
       
   351             self.content_info = utils.make_content_info(self, self.handle.getvalue())
       
   352         
       
   353         return self.content_info