from zope.app.interfaces.services.session import ISessionDataManager from zope.app.interfaces.container import IZopeContainer, IAddNotifiable from zope.interface import implements from zodb.btrees.OOBTree import OOBTree from zope.context.wrapper import ContextMethod from persistence import Persistent from zope.component import getService from zope.proxy import removeAllProxies from zope.app.traversing import getName from weakref import ref from UserDict import UserDict # this is just a little, fast hacked implemention of a SessionDataManager. # It stores all data inside a BTree. # There is no way to automatic cleanup this SessionDataManager from old, unused # data objects at this moment. class SessionData(object): """An data-Object, loosly modeled after settings.Settings. Data are kept in a registry-like fassion, using paths to the information like: '/this/category/issue/extra'. All paths start at root.""" def __init__(self, data={}): self._data = data def has(self, key): """Checks for the existence of a key.""" data = self._data for step in key.split('/'): if data.has_key(step): data = data[step] else: return False return True __contains__ = has def set(self, key, value): """Writes a key for the session, adds it, if it doesn't exist allready!""" data = self._data for step in key.split('/')[:-1]: if data.has_key(step): data = data[step] else: data[step] = {} data = data[step] data[key.split('/')[-1]] = value __setitem__ = set def get(self, key=None): """Returns the value of the given key, or None, if it doesn't exist.""" data = self._data if key is not None: for step in key.split('/'): if data.has_key(step): data = data[step] else: return None return data __getitem__ = get def __repr__(self): tree = self._buildTree() return tree def _buildTree(self, data=None, level=0): if data is None: data = self._data tree = '' for item in data: if level > 0: for i in range(1, level): tree += '...' if type(data[item]) == type({}): tree += "'%s'\n%s" % (item, self._buildTree(data=data[item], level=level+1)) else: tree += "'%s': \t%s\n" % (item, data[item]) return tree class SimpleSessionDataManager(Persistent): implements(ISessionDataManager, IAddNotifiable) def __init__(self): self._data = OOBTree() def getDataObject(self, sessionId): """Returns data attached to session. Should create new object if this is a new session. """ if sessionId not in self._data: self._data[sessionId] = SessionData() return ref(self._data[sessionId]) def deleteData(self, sessionId): """Delete data attached to session.""" if sessionId in self._data: del self._data[sessionId] def afterAddHook(self, object, container): # register myself to SessionService name = getName(object) sessions = getService(object, 'Sessions') sessions.registerDataManager(name, removeAllProxies(self)) afterAddHook = ContextMethod(afterAddHook) def beforeDeleteHook(self, object, container): name = getName(object) sessions = getService(object, 'Sessions') sessions.unregisterDataManager(name) beforeDeleteHook = ContextMethod(beforeDeleteHook)