[Checkins]
SVN: z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/
Implement shared locking a bit better. We do this by
pretending that we can
Michael Kerrin
michael.kerrin at openapp.ie
Thu Jun 7 17:03:20 EDT 2007
Log message for revision 76479:
Implement shared locking a bit better. We do this by pretending that we can
create multiple shared lock tokens on a resource by storing all the extra
information for the second shared lock token in the locks annotation.
Changed:
U z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/configure.zcml
U z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/ftests.py
U z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/manager.py
U z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/properties.py
-=-
Modified: z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/configure.zcml
===================================================================
--- z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/configure.zcml 2007-06-07 20:35:17 UTC (rev 76478)
+++ z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/configure.zcml 2007-06-07 21:03:19 UTC (rev 76479)
@@ -16,7 +16,7 @@
<class class=".manager.DAVLockmanager">
<require
permission="zope.View"
- attributes="getActivelock islocked islockable"
+ attributes="islocked islockable"
/>
<require
@@ -25,20 +25,6 @@
/>
</class>
- <adapter
- factory=".properties.DAVActiveLock"
- for="zope.interface.Interface
- zope.publisher.interfaces.http.IHTTPRequest"
- provides="z3c.dav.coreproperties.IActiveLock"
- />
-
- <class class=".properties.DAVActiveLockAdapter">
- <require
- permission="zope.View"
- interface="z3c.dav.coreproperties.IActiveLock"
- />
- </class>
-
<class class=".indirecttokens.IndirectToken">
<require
permission="zope.View"
Modified: z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/ftests.py
===================================================================
--- z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/ftests.py 2007-06-07 20:35:17 UTC (rev 76478)
+++ z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/ftests.py 2007-06-07 21:03:19 UTC (rev 76479)
@@ -306,28 +306,34 @@
locktoken = locktoken[1:-1] # remove the <> characters
token = self.utility.get(self.getRootFolder())
- self.assertEqual(
- token.annotations["z3c.dav.lockingutils.info"]["token"],
- locktoken)
+ tokendata = token.annotations["z3c.dav.lockingutils.info"]
+ self.assert_(locktoken in tokendata)
+ assertXMLEqual(
+ tokendata[locktoken]["owner"],
+ """<owner xmlns="DAV:">
+<href>http://example.org/~ejw/contact.html</href>
+</owner>""")
token = self.utility.get(self.getRootFolder()["a"])
- self.assertEqual(
- token.annotations["z3c.dav.lockingutils.info"]["token"],
- locktoken)
+ self.assert_(
+ locktoken in token.annotations["z3c.dav.lockingutils.info"])
root = self.getRootFolder()
self.assertEqual(
- IDAVLockmanager(root).getActivelock().locktoken[0], locktoken)
+ IDAVLockmanager(root).getActivelock(locktoken).locktoken[0],
+ locktoken)
self.assertEqual(
- IDAVLockmanager(root["a"]["r2"]).getActivelock().locktoken[0],
+ IDAVLockmanager(root["a"]["r2"]).getActivelock(
+ locktoken).locktoken[0],
locktoken)
request = z3c.dav.publisher.WebDAVRequest(
StringIO(""), {"HTTP_HOST": "localhost"})
- lockroot = IDAVLockmanager(root).getActivelock(request).lockroot
+ lockroot = IDAVLockmanager(root).getActivelock(
+ locktoken, request).lockroot
self.assertEqual(lockroot, "http://localhost")
lockroot = IDAVLockmanager(root["a"]["r3"]).getActivelock(
- request).lockroot
+ locktoken, request).lockroot
self.assertEqual(lockroot, "http://localhost")
def test_lock_collection_depth_inf_withlockedsubitem(self):
@@ -418,7 +424,8 @@
self.assertEqual(response.getStatus(), 200)
self.assertEqual(response.getHeader("content-type"), "application/xml")
locktoken = response.getHeader("lock-token")
- self.assert_(locktoken and locktoken[0] == "<" and locktoken[-1] == ">")
+ self.assert_(
+ locktoken and locktoken[0] == "<" and locktoken[-1] == ">")
httpresponse = self.checkPropfind(
"/a/r2", env = {"DEPTH": "0", "CONTENT_TYPE": "text/xml"},
@@ -485,16 +492,17 @@
StringIO(""), {"HTTP_HOST": "localhost"})
lockmanager = IDAVLockmanager(rootfolder)
- self.assertEqual(lockmanager.getActivelock(request).lockroot,
- "http://localhost/a")
+ self.assertEqual(lockmanager.getActivelock(
+ locktoken, request).lockroot, "http://localhost/a")
self.assertEqual(
- lockmanager.getActivelock().locktoken[0], locktoken[1:-1])
+ lockmanager.getActivelock(locktoken).locktoken[0], locktoken)
lockmanager = IDAVLockmanager(subresource)
- self.assertEqual(lockmanager.getActivelock(request).lockroot,
- "http://localhost/a")
self.assertEqual(
- lockmanager.getActivelock().locktoken[0], locktoken[1:-1])
+ lockmanager.getActivelock(locktoken, request).lockroot,
+ "http://localhost/a")
+ self.assertEqual(
+ lockmanager.getActivelock(locktoken).locktoken[0], locktoken)
def test_lock_invalid_depth(self):
file = self.addResource("/testresource", "some file content",
@@ -528,10 +536,13 @@
owner = """<D:owner xmlns:D="DAV:">
<D:href>mailto:michael</D:href>
</D:owner>"""
- lockmanager.lock(u"exclusive", u"write", owner,
- datetime.timedelta(seconds = 1000), "infinity")
- locktoken = lockmanager.getActivelock().locktoken[0]
- self.assertEqual(lockmanager.getActivelock().timeout, u"Second-1000")
+ locktoken = lockmanager.lock(u"exclusive", u"write", owner,
+ datetime.timedelta(seconds = 1000),
+ "infinity")
+ ltoken = lockmanager.getActivelock(locktoken).locktoken[0]
+ self.assert_(ltoken == locktoken)
+ self.assertEqual(
+ lockmanager.getActivelock(locktoken).timeout, u"Second-1000")
transaction.commit()
self.logout()
@@ -629,17 +640,17 @@
lockmanager = IDAVLockmanager(file)
self.assertEqual(lockmanager.islocked(), False)
- lockmanager.lock(scope = "exclusive", type = "write",
- owner = """<D:owner xmlns:D="DAV:">
+ locktoken = lockmanager.lock(
+ scope = "exclusive", type = "write",
+ owner = """<D:owner xmlns:D="DAV:">
<D:href>mailto:michael at linux</D:href>
</D:owner>""",
- duration = datetime.timedelta(100),
- depth = "0")
+ duration = datetime.timedelta(100),
+ depth = "0")
transaction.commit()
lockmanager = IDAVLockmanager(file)
self.assertEqual(lockmanager.islocked(), True)
- locktoken = lockmanager.getActivelock().locktoken[0]
# end the current interaction
self.logout()
Modified: z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/manager.py
===================================================================
--- z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/manager.py 2007-06-07 20:35:17 UTC (rev 76478)
+++ z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/manager.py 2007-06-07 21:03:19 UTC (rev 76479)
@@ -16,15 +16,13 @@
the zope.locking utiltity to integrate it into z3c.dav.
"""
-import time
-import random
from BTrees.OOBTree import OOBTree
import zope.component
import zope.interface
-from zope.security.proxy import removeSecurityProxy
-from zope.traversing.browser.absoluteurl import absoluteURL
+import zope.security.management
from zope.app.container.interfaces import IReadContainer
import z3c.dav.interfaces
+import z3c.dav.locking
import interfaces
import indirecttokens
@@ -32,14 +30,13 @@
WEBDAV_LOCK_KEY = "z3c.dav.lockingutils.info"
-_randGen = random.Random(time.time())
-
class DAVLockmanager(object):
"""
>>> from zope.interface.verify import verifyObject
>>> from zope.locking import utility, utils
>>> from zope.locking.adapters import TokenBroker
+ >>> from zope.traversing.browser.absoluteurl import absoluteURL
>>> file = Demo()
@@ -79,17 +76,13 @@
Lock with an exclusive lock token.
- >>> roottoken = adapter.lock(u'exclusive', u'write',
+ >>> locktoken = adapter.lock(u'exclusive', u'write',
... u'Michael', datetime.timedelta(seconds = 3600), '0')
- >>> util.get(file) == roottoken
- True
- >>> zope.locking.interfaces.IExclusiveLock.providedBy(roottoken)
- True
>>> adapter.islocked()
True
- >>> activelock = adapter.getActivelock()
+ >>> activelock = adapter.getActivelock(locktoken)
>>> activelock.lockscope
[u'exclusive']
>>> activelock.locktype
@@ -102,53 +95,76 @@
'/dummy'
>>> activelock.owner
u'Michael'
+ >>> len(activelock.locktoken)
+ 1
+ >>> activelock.locktoken #doctest:+ELLIPSIS
+ ['opaquelocktoken:...
+ >>> util.get(file) == activelock.token
+ True
+ >>> zope.locking.interfaces.IExclusiveLock.providedBy(activelock.token)
+ True
+
+ Now refresh the timeout on the locktoken.
+
>>> adapter.refreshlock(datetime.timedelta(seconds = 7200))
- >>> adapter.getActivelock().timeout
+ >>> adapter.getActivelock(locktoken).timeout
u'Second-7200'
- >>> adapter.unlock()
+ Unlock the resource.
+
+ >>> adapter.unlock(locktoken)
>>> util.get(file) is None
True
>>> adapter.islocked()
False
- >>> adapter.getActivelock() is None
+ >>> adapter.getActivelock(locktoken) is None
True
+ We can't unlock the resource twice.
+
+ >>> adapter.unlock(locktoken)
+ Traceback (most recent call last):
+ ...
+ ConflictError: The context is not locked, so we can't unlock it.
+
Shared locking support.
- >>> roottoken = adapter.lock(u'shared', u'write', u'Michael',
+ >>> locktoken = adapter.lock(u'shared', u'write', u'Michael',
... datetime.timedelta(seconds = 3600), '0')
- >>> util.get(file) == roottoken
- True
- >>> zope.locking.interfaces.ISharedLock.providedBy(roottoken)
- True
- >>> activelock = adapter.getActivelock()
+ >>> activelock = adapter.getActivelock(locktoken)
>>> activelock.lockscope
[u'shared']
+ >>> len(activelock.locktoken)
+ 1
>>> activelock.locktoken #doctest:+ELLIPSIS
['opaquelocktoken:...
- >>> adapter.unlock()
+ >>> util.get(file) == activelock.token
+ True
+ >>> zope.locking.interfaces.ISharedLock.providedBy(activelock.token)
+ True
+ >>> adapter.unlock(locktoken)
+
Recursive lock suport.
>>> demofolder = DemoFolder()
>>> demofolder['demo'] = file
>>> adapter = DAVLockmanager(demofolder)
- >>> roottoken = adapter.lock(u'exclusive', u'write', u'MichaelK',
- ... datetime.timedelta(seconds = 3600), 'infinity')
+ >>> locktoken = adapter.lock(u'exclusive', u'write',
+ ... u'MichaelK', datetime.timedelta(seconds = 3600), 'infinity')
>>> demotoken = util.get(file)
>>> interfaces.IIndirectToken.providedBy(demotoken)
True
- >>> activelock = adapter.getActivelock()
+ >>> activelock = adapter.getActivelock(locktoken)
>>> activelock.lockroot
'/dummy/'
- >>> DAVLockmanager(file).getActivelock().lockroot
+ >>> DAVLockmanager(file).getActivelock(locktoken).lockroot
'/dummy/'
>>> absoluteURL(file, None)
'/dummy/dummy'
@@ -164,8 +180,11 @@
AlreadyLocked...
>>> adapter.islocked()
True
+ >>> activelock = adapter.getActivelock(locktoken)
+ >>> len(activelock.locktoken)
+ 1
- >>> adapter.unlock()
+ >>> adapter.unlock(locktoken[0])
Some error conditions.
@@ -193,71 +212,129 @@
def __init__(self, context):
self.context = self.__parent__ = context
- def generateLocktoken(self):
- return "opaquelocktoken:%s-%s-00105A989226:%.03f" % \
- (_randGen.random(), _randGen.random(), time.time())
-
def islockable(self):
utility = zope.component.queryUtility(
zope.locking.interfaces.ITokenUtility,
context = self.context, default = None)
return utility is not None
- def lock(self, scope, type, owner, duration, depth,
- roottoken = None, context = None):
- if context is None:
- context = self.context
+ def maybeRecursivelyLockIndirectly(self, utility,
+ context, roottoken, depth):
+ if depth == "infinity" and IReadContainer.providedBy(context):
+ for subob in context.values():
+ token = utility.get(subob)
+ if token:
+ raise z3c.dav.interfaces.AlreadyLocked(
+ subob, message = u"Sub-object is already locked")
+ indirecttoken = indirecttokens.IndirectToken(subob, roottoken)
+ utility.register(indirecttoken)
+ self.maybeRecursivelyLockIndirectly(
+ utility, subob, roottoken, depth)
- tokenBroker = zope.locking.interfaces.ITokenBroker(context)
- if tokenBroker.get():
+ def register(self, utility, token):
+ try:
+ return utility.register(token)
+ except zope.locking.interfaces.RegistrationError:
raise z3c.dav.interfaces.AlreadyLocked(
- context, message = u"Context or subitem is already locked.")
+ token.context, message = u"Context is locked")
- if roottoken is None:
- if scope == u"exclusive":
- roottoken = tokenBroker.lock(duration = duration)
- elif scope == u"shared":
- roottoken = tokenBroker.lockShared(duration = duration)
- else:
- raise z3c.dav.interfaces.UnprocessableError(
- self.context,
- message = u"Invalid lockscope supplied to the lock manager")
+ def lock(self, scope, type, owner, duration, depth):
+ principal_id = getPrincipalId()
+ utility = zope.component.getUtility(
+ zope.locking.interfaces.ITokenUtility, context = self.context)
- annots = roottoken.annotations.get(WEBDAV_LOCK_KEY, None)
- if annots is None:
+ locktoken = z3c.dav.locking.generateLocktoken()
+
+ if scope == u"exclusive":
+ roottoken = self.register(
+ utility, zope.locking.tokens.ExclusiveLock(
+ self.context, principal_id, duration = duration))
+ annots = roottoken.annotations[WEBDAV_LOCK_KEY] = OOBTree()
+ elif scope == u"shared":
+ # A successful request for a new shared lock MUST result in the
+ # generation of a unique lock associated with the requesting
+ # principal. Thus if five principals have taken out shared write
+ # locks on the same resource there will be five locks and five
+ # lock tokens, one for each principal.
+ roottoken = utility.get(self.context)
+ if roottoken is None:
+ roottoken = self.register(
+ utility, zope.locking.tokens.SharedLock(
+ self.context, (principal_id,), duration = duration))
annots = roottoken.annotations[WEBDAV_LOCK_KEY] = OOBTree()
- annots["owner"] = owner
- annots["token"] = self.generateLocktoken()
- annots["depth"] = depth
+ annots["principal_ids"] = [principal_id]
+ else:
+ roottoken.add((principal_id,))
+ if WEBDAV_LOCK_KEY not in roottoken.annotations:
+ # Locked by an alternative application
+ annots = roottoken.annotations[WEBDAV_LOCK_KEY] = OOBTree()
+ # Use OOBTree here
+ annots["principal_ids"] = [principal_id]
+ else:
+ annots = roottoken.annotations[WEBDAV_LOCK_KEY]
+ annots["principal_ids"].append(principal_id)
else:
- indirecttoken = indirecttokens.IndirectToken(context, roottoken)
- ## XXX - using removeSecurityProxy - is this right, has
- ## it seems wrong
- removeSecurityProxy(roottoken).utility.register(indirecttoken)
+ raise z3c.dav.interfaces.UnprocessableError(
+ self.context,
+ message = u"Invalid lockscope supplied to the lock manager")
- if depth == "infinity" and IReadContainer.providedBy(context):
- for subob in context.values():
- self.lock(scope, type, owner, duration, depth,
- roottoken, subob)
+ annots[locktoken] = OOBTree()
+ annots[locktoken].update({"owner": owner, "depth": depth})
- return roottoken
+ self.maybeRecursivelyLockIndirectly(
+ utility, self.context, roottoken, depth)
- def getActivelock(self, request = None):
+ return locktoken
+
+ def getActivelock(self, locktoken, request = None):
if self.islocked():
token = zope.locking.interfaces.ITokenBroker(self.context).get()
- return properties.DAVActiveLockAdapter(
- token, self.context, request)
+ return properties.DAVActiveLock(
+ locktoken, token, self.context, request)
return None
def refreshlock(self, timeout):
token = zope.locking.interfaces.ITokenBroker(self.context).get()
token.duration = timeout
- def unlock(self):
- tokenBroker = zope.locking.interfaces.ITokenBroker(self.context)
- token = tokenBroker.get()
- token.end()
+ def unlock(self, locktoken):
+ utility = zope.component.getUtility(
+ zope.locking.interfaces.ITokenUtility, context = self.context)
+ token = utility.get(self.context)
+ if token is None:
+ raise z3c.dav.interfaces.ConflictError(
+ self.context,
+ message = "The context is not locked, so we can't unlock it.")
+ if interfaces.IIndirectToken.providedBy(token):
+ token = token.roottoken
+
+ if zope.locking.interfaces.IExclusiveLock.providedBy(token):
+ token.end()
+ elif zope.locking.interfaces.ISharedLock.providedBy(token):
+ principal_id = getPrincipalId()
+ annots = token.annotations[WEBDAV_LOCK_KEY]
+ del annots[locktoken]
+ annots["principal_ids"].remove(principal_id)
+ if principal_id not in annots["principal_ids"]:
+ # will end token if no principals left
+ token.remove((principal_id,))
+ else:
+ raise ValueError("Unknown lock token")
+
def islocked(self):
tokenBroker = zope.locking.interfaces.ITokenBroker(self.context)
return tokenBroker.get() is not None
+
+
+def getPrincipalId():
+ principal_ids = [
+ participation.principal.id
+ for participation in
+ zope.security.management.getInteraction().participations]
+
+ if len(principal_ids) != 1:
+ raise ValueError("There must be only one participant principal")
+ principal_id = principal_ids[0]
+
+ return principal_id
Modified: z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/properties.py
===================================================================
--- z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/properties.py 2007-06-07 20:35:17 UTC (rev 76478)
+++ z3c.davapp.zopelocking/trunk/src/z3c/davapp/zopelocking/properties.py 2007-06-07 21:03:19 UTC (rev 76479)
@@ -117,10 +117,7 @@
return [ExclusiveLockEntry(), SharedLockEntry()]
- at component.adapter(interface.Interface,
- zope.publisher.interfaces.http.IHTTPRequest)
- at interface.implementer(IActiveLock)
-def DAVActiveLock(context, request):
+class DAVActiveLock(object):
"""
This adapter is responsible for the data for the `{DAV:}activelock`
XML element. This XML element occurs within the `{DAV:}lockdiscovery`
@@ -134,7 +131,6 @@
>>> import zope.locking.utils
>>> from zope.locking import tokens
>>> from zope.locking.utility import TokenUtility
- >>> from zope.locking.adapters import TokenBroker
>>> from z3c.dav.publisher import WebDAVRequest
>>> import indirecttokens
@@ -143,13 +139,8 @@
>>> oldNow = zope.locking.utils.now
>>> zope.locking.utils.now = hackNow
- The activelock property only exists whenever the zope.locking package
- is configured properly.
-
>>> resource = DemoFolder()
>>> request = WebDAVRequest(StringIO(''), {})
- >>> DAVActiveLock(resource, request) is None
- True
Now register a ITokenUtility utility and lock the resource with it.
@@ -165,14 +156,7 @@
content object to zope.locking.interfaces.ITokenBroker. This is part
of the zope.locking installation that hasn't been completed yet.
- >>> DAVActiveLock(resource, request) is None
- True
-
- >>> component.getGlobalSiteManager().registerAdapter(
- ... TokenBroker, (interface.Interface,),
- ... zope.locking.interfaces.ITokenBroker)
-
- >>> activelock = DAVActiveLock(resource, request)
+ >>> activelock = DAVActiveLock(None, locktoken, resource, request)
>>> IActiveLock.providedBy(activelock)
True
>>> verifyObject(IActiveLock, activelock)
@@ -215,15 +199,6 @@
... z3c.dav.coreproperties.lockdiscovery,
... lockdiscovery, request)
>>> print etree.tostring(davwidget.render()) #doctest:+XMLDATA
- <lockdiscovery xmlns="DAV:" />
-
- >>> component.getGlobalSiteManager().registerAdapter(DAVActiveLock)
-
- >>> lockdiscovery = DAVLockdiscovery(resource, request)
- >>> davwidget = z3c.dav.properties.getWidget(
- ... z3c.dav.coreproperties.lockdiscovery,
- ... lockdiscovery, request)
- >>> print etree.tostring(davwidget.render()) #doctest:+XMLDATA
<lockdiscovery xmlns="DAV:">
<activelock>
<lockscope><exclusive /></lockscope>
@@ -237,16 +212,17 @@
We use the lock tokens annotation to store the data for the owner, depth
and locktoken attributes.
- >>> locktoken.annotations[WEBDAV_LOCK_KEY] = OOBTree()
- >>> locktoken.annotations[WEBDAV_LOCK_KEY]['depth'] = 'testdepth'
- >>> locktoken.annotations[WEBDAV_LOCK_KEY]['owner'] = '<owner xmlns="DAV:">Me</owner>'
- >>> locktoken.annotations[WEBDAV_LOCK_KEY]['token'] = 'simpletoken'
+ >>> locktokendata= locktoken.annotations[WEBDAV_LOCK_KEY] = OOBTree()
+ >>> locktokendata['simpletoken'] = OOBTree()
+ >>> locktokendata['simpletoken']['depth'] = 'testdepth'
+ >>> locktokendata['simpletoken']['owner'] = '<owner xmlns="DAV:">Me</owner>'
After updating the lock token's annotations we need to regenerate the
activelock adapter so that the tokendata internal attribute is setup
correctly.
- >>> activelock = DAVActiveLock(resource, request)
+ >>> activelock = DAVActiveLock(
+ ... 'simpletoken', locktoken, resource, request)
The owner attribute is not required by the WebDAV specification, but
we can see it anyways, and similarly for the locktoken attribute.
@@ -288,7 +264,8 @@
... resource['demo'], locktoken)
>>> sublocktoken = util.register(sublocktoken)
- >>> activelock = DAVActiveLock(resource['demo'], request)
+ >>> activelock = DAVActiveLock(
+ ... 'simpletoken', sublocktoken, resource['demo'], request)
>>> verifyObject(IActiveLock, activelock)
True
@@ -341,7 +318,7 @@
... resource, datetime.timedelta(hours = 1))
>>> locktoken = util.register(locktoken)
- >>> activelock = DAVActiveLock(resource, request)
+ >>> activelock = DAVActiveLock(None, locktoken, resource, request)
>>> IActiveLock.providedBy(activelock)
True
@@ -396,7 +373,7 @@
>>> locktoken = tokens.ExclusiveLock(resource, 'michael')
>>> locktoken = util.register(locktoken)
- >>> activelock = DAVActiveLock(resource, request)
+ >>> activelock = DAVActiveLock(None, locktoken, resource, request)
>>> verifyObject(IActiveLock, activelock)
True
>>> activelock.timeout is None
@@ -423,32 +400,16 @@
>>> component.getGlobalSiteManager().unregisterUtility(
... util, zope.locking.interfaces.ITokenUtility)
True
- >>> component.getGlobalSiteManager().unregisterAdapter(
- ... TokenBroker, (interface.Interface,),
- ... zope.locking.interfaces.ITokenBroker)
- True
- >>> component.getGlobalSiteManager().unregisterAdapter(DAVActiveLock)
- True
"""
- try:
- token = zope.locking.interfaces.ITokenBroker(context).get()
- except TypeError:
- token = None
- if token is None:
- return None
- return DAVActiveLockAdapter(token, context, request)
-
-
-class DAVActiveLockAdapter(object):
- component.adapts(interface.Interface,
- z3c.dav.interfaces.IWebDAVRequest)
interface.implements(IActiveLock)
- def __init__(self, token, context, request):
+ def __init__(self, locktoken, token, context, request):
self.context = self.__parent__ = context
+ self._locktoken = locktoken
self.token = token
- self.tokendata = token.annotations.get(WEBDAV_LOCK_KEY, {})
+ self.tokendata = token.annotations.get(
+ WEBDAV_LOCK_KEY, {}).get(locktoken, {})
self.request = request
@property
@@ -486,10 +447,7 @@
@property
def locktoken(self):
- token = self.tokendata.get("token", None)
- if token is None:
- return None
- return [token]
+ return self._locktoken and [self._locktoken]
@property
def lockroot(self):
@@ -501,7 +459,8 @@
return absoluteURL(root, self.request)
- at component.adapter(interface.Interface, z3c.dav.interfaces.IWebDAVRequest)
+ at component.adapter(
+ interface.Interface, zope.publisher.interfaces.http.IHTTPRequest)
@interface.implementer(z3c.dav.coreproperties.IDAVLockdiscovery)
def DAVLockdiscovery(context, request):
"""
@@ -553,7 +512,7 @@
1
>>> IActiveLock.providedBy(lockdiscovery[0])
True
- >>> isinstance(lockdiscovery[0], DAVActiveLockAdapter)
+ >>> isinstance(lockdiscovery[0], DAVActiveLock)
True
Cleanup
@@ -574,7 +533,7 @@
utility = component.queryUtility(zope.locking.interfaces.ITokenUtility)
if utility is None:
return None
- return DAVLockdiscoveryAdapter(context, request)
+ return DAVLockdiscoveryAdapter(context, request, utility)
class DAVLockdiscoveryAdapter(object):
@@ -582,14 +541,26 @@
component.adapts(interface.Interface,
z3c.dav.interfaces.IWebDAVRequest)
- def __init__(self, context, request):
+ def __init__(self, context, request, utility):
self.context = context
self.request = request
+ self.utility = utility
@property
def lockdiscovery(self):
- adapter = component.queryMultiAdapter((self.context, self.request),
- IActiveLock, default = None)
- if adapter is None:
+ token = self.utility.get(self.context)
+ if token is None:
return None
- return [adapter]
+
+ activelocks = []
+ for locktoken in token.annotations.get(WEBDAV_LOCK_KEY, {}).keys():
+ if locktoken != "principal_ids":
+ activelocks.append(DAVActiveLock(locktoken, token,
+ self.context, self.request))
+ if activelocks:
+ return activelocks
+
+ # Probable a non-webdav client / application created this lock.
+ # We probable need an other active lock implementation to handle
+ # this case.
+ return [DAVActiveLock(None, token, self.context, self.request)]
More information about the Checkins
mailing list