# $SnapHashLicense:
#
# SnapLogic - Open source data services
#
# Copyright (C) 2008, SnapLogic, Inc. All rights reserved.
#
# See http://www.snaplogic.org for more information about
# the SnapLogic project.
#
# This program is free software, distributed under the terms of
# the GNU General Public License Version 2. See the LEGAL file
# at the top of the source tree.
#
# "SnapLogic" is a trademark of SnapLogic, Inc.
#
#
# $
# $Id: snap_store.py 8600 2009-08-17 21:28:46Z pamor $
"""
Abstract snap store module.
This module contains a base class for supported store objects, MySQL and SQLite.
"""
__docformat__ = "epytext en"
import threading
import StringIO
from snaplogic.common.snap_exceptions import *
from snaplogic.common import uri_prefix,version_info
from snaplogic.common.thread_utils import RWLock
from snaplogic.snapi_base import keys
from snaplogic import rp
class SnapStore(object):
"""
Base class for stores of different types providing interfaces for performing all repository actions.
This class provides a static factory method for instantiating a store object of specified type.
"""
_RP = rp.get_rp('application/json')
def __init__(self):
"""
Initialization.
"""
self._lock = threading.RLock()
if self._RP is None:
raise SnapRepInitError('JSON RP is not available.')
def _assert_current_ids(self, uri, guid, gen_id):
"""
Asserts that the IDs given are the same as those stored for the resource at uri.
The GUID and generation ID for the resource bound at uri are retrieved and compared to those given
in guid and gen_id. If they do not match, an exception is thrown.
If gen_id or guid are None, they are considered to match any value and will not result in a mismatch error.
If guid is None, gen_id is not checked either since the gen_id depends on guid for context.
@param uri: URI of resource to check.
@type uri: string
@param guid: GUID expected for stored resource or None to match any.
@type guid: string
@param gen_id: Generation ID expected for stored resource or None to match any.
@type gen_id: integer
@raise SnapObjNotFoundError: No resource is lcoated at uri within the store.
@raise SnapResDefGUIDError: Resource in store at uri has a different GUID than provided in guid.
@raise SnapResDefGenIDError: Resource in store at uri has different generation ID than provided in gen_id.
"""
resource = self.list_resources([uri])[uri]
if resource is not None:
if guid is not None:
if resource[keys.GUID] != guid:
raise SnapResDefGUIDError("Resource '%s' GUID did not match." % uri,
('Expected', guid),
('Found', resource[keys.GUID]))
elif gen_id is not None and resource[keys.GEN_ID] != gen_id:
raise SnapResDefGenIDError("Resource '%s' generation ID did not match." % uri,
('Expected', gen_id),
('Found', resource[keys.GEN_ID]))
else:
raise SnapObjNotFoundError("Resource '%s' was not found in the Repository." % uri)
def _generate_uri(self, guid, resdef):
"""
Generate a unique URI for a new resource.
@param guid: GUID created for new resource.
@type guid: string
@param resdef: ResDef dictionary defining the resource.
@type resdef: dict
@return: A unique autogenerated URI.
@rtype: string
"""
return "%s/%s" % (uri_prefix.AUTOGEN, guid)
def _make_summary_dict(self, guid, gen_id, summary=None):
"""
Create a dictionary appropriate for embeddeding into the result of summarize_resources().
@param guid: GUID of resource.
@type guid: string
@param gen_id: Generation ID of resource.
@type gen_id: int
@param summary: Dictionary containing summary of details requested. If None, no details
are returned.
@type summary: dict
@return: A dictionary appropriate for embedding in summarize_resources() result.
@rtype: dict
"""
d = {keys.GUID: guid, keys.GEN_ID: gen_id}
if summary is not None:
d[keys.SUMMARY] = summary
return d
def _make_listing_dict(self, guid, gen_id, resdef):
"""
Create a dictionary appropriate for embeddeding into the result of list_resources().
@param guid: GUID of resource.
@type guid: string
@param gen_id: Generation ID of resource.
@type gen_id: int
@param resdef: Resource ResDef.
@type resdef: dict
@return: A dictionary appropriate for embedding in list_resource() result.
@rtype: dict
"""
return {keys.GUID: guid, keys.GEN_ID: gen_id, keys.DESCRIPTION: resdef.get(keys.DESCRIPTION, '')}
def _encode_value(self, value):
"""
Encodes a python value into a string representation.
@param value: A python value.
@type value: any
@return: String representation of the value.
"""
try:
buf = StringIO.StringIO()
writer = self._RP.Writer(buf)
writer.initialize()
writer.write(value)
writer.end()
return buf.getvalue()
except TypeError, e:
raise SnapException.chain(e, SnapObjTypeError("Cannot encode value '%s'" % str(value)))
def _decode_value(self, encoded_value):
"""
Decodes a value previous encoded with _encode_value().
@param encoded_value: An encoded string containing a Python value.
@type encoded_value: string
@return: The decoded Python value.
@rtype: any
"""
buf = StringIO.StringIO(encoded_value)
buf.seek(0)
reader = self._RP.Reader(buf)
return reader.next()
|