[CalendarServer-changes] [5970] CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Tue Aug 3 13:44:19 PDT 2010


Revision: 5970
          http://trac.macosforge.org/projects/calendarserver/changeset/5970
Author:   cdaboo at apple.com
Date:     2010-08-03 13:44:19 -0700 (Tue, 03 Aug 2010)
Log Message:
-----------
Re-factor the home resource classes to have a more logic inheritance hierarchy and move common stuff
into a base class. Also get rid of auto provisioning mixin and do on-demand resource creation rather than
putChild in __init__.

Modified Paths:
--------------
    CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/addressbook.py
    CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/calendar.py
    CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/resource.py
    CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/extensions.py
    CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/method/report_sync_collection.py
    CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/resource.py
    CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/schedule.py
    CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/sharing.py
    CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/storebridge.py
    CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_multiget.py
    CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_wrapping.py
    CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/util.py

Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/addressbook.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/addressbook.py	2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/addressbook.py	2010-08-03 20:44:19 UTC (rev 5970)
@@ -20,7 +20,6 @@
 
 __all__ = [
     "uidsResourceName",
-   #"DirectoryAddressBookProvisioningResource",
     "DirectoryAddressBookHomeProvisioningResource",
     "DirectoryAddressBookHomeTypeProvisioningResource",
     "DirectoryAddressBookHomeUIDProvisioningResource",
@@ -29,21 +28,17 @@
 
 from twext.python.log import Logger
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.resource import TwistedACLInheritable
 from twext.web2.dav.util import joinURL
 from twext.web2.http import HTTPError
 from twext.web2.http_headers import ETag, MimeType
 
-from twisted.internet.defer import succeed
-
 from twistedcaldav.config import config
 from twistedcaldav.directory.idirectory import IDirectoryService
+from twistedcaldav.directory.resource import DirectoryReverseProxyResource
 from twistedcaldav.directory.util import transactionFromRequest
-from twistedcaldav.directory.resource import AutoProvisioningResourceMixIn,\
-    DirectoryReverseProxyResource
 from twistedcaldav.extensions import ReadOnlyResourceMixIn, DAVResource,\
     DAVResourceWithChildrenMixin
+from twistedcaldav.resource import AddressBookHomeResource
 
 from uuid import uuid4
 
@@ -61,7 +56,6 @@
         )
 
 class DirectoryAddressBookProvisioningResource (
-    AutoProvisioningResourceMixIn,
     ReadOnlyResourceMixIn,
     CalDAVComplianceMixIn,
     DAVResourceWithChildrenMixin,
@@ -101,20 +95,11 @@
         #
         # Create children
         #
-        def provisionChild(name):
-            self.putChild(name, self.provisionChild(name))
-
         for recordType in self.directory.recordTypes():
-            provisionChild(recordType)
+            self.putChild(recordType, DirectoryAddressBookHomeTypeProvisioningResource(self, recordType))
 
-        provisionChild(uidsResourceName)
+        self.putChild(uidsResourceName, DirectoryAddressBookHomeUIDProvisioningResource(self))
 
-    def provisionChild(self, name):
-        if name == uidsResourceName:
-            return DirectoryAddressBookHomeUIDProvisioningResource(self)
-
-        return DirectoryAddressBookHomeTypeProvisioningResource(self, name)
-
     def url(self):
         return self._url
 
@@ -172,7 +157,6 @@
         return joinURL(self._parent.url(), self.recordType)
 
     def locateChild(self, request, segments):
-        self.provision()
         name = segments[0]
         if name == "":
             return (self, segments[1:])
@@ -234,10 +218,6 @@
 
         self.directory = parent.directory
         self.parent = parent
-        
-        # TODO: better way to get this class - perhaps request from the store
-        from twistedcaldav.resource import AddressBookHomeResource
-        self.homeResourceClass = AddressBookHomeResource
 
     def url(self):
         return joinURL(self.parent.url(), uidsResourceName)
@@ -263,7 +243,6 @@
 
     def homeResourceForRecord(self, record, request):
 
-        self.provision()
         transaction = transactionFromRequest(request, self.parent._newStore)
 
         name = record.uid
@@ -279,7 +258,7 @@
         assert len(name) > 4, "Directory record has an invalid GUID: %r" % (name,)
         
         if record.locallyHosted():
-            child = self.homeResourceClass(self, record, transaction)
+            child = DirectoryAddressBookHomeResource(self, record, transaction)
         else:
             child = DirectoryReverseProxyResource(self, record)
 
@@ -306,135 +285,20 @@
         return self.parent.principalForRecord(record)
 
 
-class DirectoryAddressBookHomeResource (AutoProvisioningResourceMixIn, DAVResource):
+class DirectoryAddressBookHomeResource (AddressBookHomeResource):
     """
     Address book home collection resource.
     """
-    def __init__(self, parent, record):
+    def __init__(self, parent, record, transaction):
         """
         @param path: the path to the file which will back the resource.
         """
         assert parent is not None
         assert record is not None
+        assert transaction is not None
 
-        super(DirectoryAddressBookHomeResource, self).__init__()
-
         self.record = record
-        self.parent = parent
+        super(DirectoryAddressBookHomeResource, self).__init__(parent, record.uid, transaction)
 
-        childlist = ()
-        if config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and not config.Sharing.Calendars.Enabled:
-            from twistedcaldav.notifications import NotificationCollectionResource
-            childlist += (
-                ("notification", NotificationCollectionResource),
-            )
-        for name, cls in childlist:
-            child = self.provisionChild(name)
-            assert isinstance(child, cls), "Child %r is not a %s: %r" % (name, cls.__name__, child)
-            self.putChild(name, child)
-
-    def provisionDefaultAddressBooks(self):
-
-        # Disable notifications during provisioning
-        if hasattr(self, "clientNotifier"):
-            self.clientNotifier.disableNotify()
-
-        try:
-            self.provision()
-    
-            childName = "addressbook"
-            child = self.provisionChild(childName)
-
-            d = child.createAddressBookCollection()
-        except:
-            # We want to make sure to re-enable notifications, so do so
-            # if there is an immediate exception above, or via errback, below
-            if hasattr(self, "clientNotifier"):
-                self.clientNotifier.enableNotify(None)
-            raise
-
-        # Re-enable notifications
-        if hasattr(self, "clientNotifier"):
-            d.addCallback(self.clientNotifier.enableNotify)
-            d.addErrback(self.clientNotifier.enableNotify)
-
-        return d
-
-    def provisionChild(self, name):
-        raise NotImplementedError("Subclass must implement provisionChild()")
-
-    def url(self):
-        return joinURL(self.parent.url(), self.record.uid, "/")
-
-    def canonicalURL(self, request):
-        return succeed(self.url())
-    ##
-    # DAV
-    ##
-    
-    def isCollection(self):
-        return True
-
-    def http_COPY(self, request):
-        return responsecode.FORBIDDEN
-
-    ##
-    # ACL
-    ##
-
-    def owner(self, request):
-        return succeed(davxml.HRef(self.principalForRecord().principalURL()))
-
-    def ownerPrincipal(self, request):
-        return succeed(self.principalForRecord())
-
-    def resourceOwnerPrincipal(self, request):
-        return succeed(self.principalForRecord())
-
-    def defaultAccessControlList(self):
-        myPrincipal = self.principalForRecord()
-
-        aces = (
-            # Inheritable DAV:all access for the resource's associated principal.
-            davxml.ACE(
-                davxml.Principal(davxml.HRef(myPrincipal.principalURL())),
-                davxml.Grant(davxml.Privilege(davxml.All())),
-                davxml.Protected(),
-                TwistedACLInheritable(),
-            ),
-        )
-
-        # Give read access to config.ReadPrincipals
-        aces += config.ReadACEs
-
-        # Give all access to config.AdminPrincipals
-        aces += config.AdminACEs
-        
-        return davxml.ACL(*aces)
-
-    def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None):
-        # Permissions here are fixed, and are not subject to inheritance rules, etc.
-        return succeed(self.defaultAccessControlList())
-
-    def principalCollections(self):
-        return self.parent.principalCollections()
-
     def principalForRecord(self):
         return self.parent.principalForRecord(self.record)
-
-    ##
-    # Quota
-    ##
-
-    def hasQuotaRoot(self, request):
-        """
-        @return: a C{True} if this resource has quota root, C{False} otherwise.
-        """
-        return config.UserQuota != 0
-    
-    def quotaRoot(self, request):
-        """
-        @return: a C{int} containing the maximum allowed bytes if this collection
-            is quota-controlled, or C{None} if not quota controlled.
-        """
-        return config.UserQuota if config.UserQuota != 0 else None

Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/calendar.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/calendar.py	2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/calendar.py	2010-08-03 20:44:19 UTC (rev 5970)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.directory.test.test_calendar -*-
 ##
-# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2010 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
-from twistedcaldav.directory.util import transactionFromRequest
 
 """
 Implements a directory-backed calendar hierarchy.
@@ -22,7 +21,6 @@
 
 __all__ = [
     "uidsResourceName",
-   #"DirectoryCalendarProvisioningResource",
     "DirectoryCalendarHomeProvisioningResource",
     "DirectoryCalendarHomeTypeProvisioningResource",
     "DirectoryCalendarHomeUIDProvisioningResource",
@@ -31,23 +29,20 @@
 
 from twext.python.log import Logger
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.resource import TwistedACLInheritable
 from twext.web2.dav.util import joinURL
 from twext.web2.http import HTTPError
 from twext.web2.http_headers import ETag, MimeType
 
 from twisted.internet.defer import succeed
 
-from twistedcaldav import caldavxml
 from twistedcaldav.config import config
-from twistedcaldav.dropbox import DropBoxHomeResource
-from twistedcaldav.extensions import ReadOnlyResourceMixIn, DAVResource,\
-    DAVResourceWithChildrenMixin
 from twistedcaldav.directory.idirectory import IDirectoryService
+from twistedcaldav.directory.resource import DirectoryReverseProxyResource
+from twistedcaldav.directory.util import transactionFromRequest
 from twistedcaldav.directory.wiki import getWikiACL
-from twistedcaldav.directory.resource import AutoProvisioningResourceMixIn,\
-    DirectoryReverseProxyResource
+from twistedcaldav.extensions import ReadOnlyResourceMixIn, DAVResource,\
+    DAVResourceWithChildrenMixin
+from twistedcaldav.resource import CalendarHomeResource
 
 from uuid import uuid4
 
@@ -65,7 +60,6 @@
         )
 
 class DirectoryCalendarProvisioningResource (
-    AutoProvisioningResourceMixIn,
     ReadOnlyResourceMixIn,
     CalDAVComplianceMixIn,
     DAVResourceWithChildrenMixin,
@@ -104,20 +98,11 @@
         #
         # Create children
         #
-        def provisionChild(name):
-            self.putChild(name, self.provisionChild(name))
-
         for recordType in self.directory.recordTypes():
-            provisionChild(recordType)
+            self.putChild(recordType, DirectoryCalendarHomeTypeProvisioningResource(self, recordType))
 
-        provisionChild(uidsResourceName)
+        self.putChild(uidsResourceName, DirectoryCalendarHomeUIDProvisioningResource(self))
 
-    def provisionChild(self, name):
-        if name == uidsResourceName:
-            return DirectoryCalendarHomeUIDProvisioningResource(self)
-
-        return DirectoryCalendarHomeTypeProvisioningResource(self, name)
-
     def url(self):
         return self._url
 
@@ -174,7 +159,6 @@
         return joinURL(self._parent.url(), self.recordType)
 
     def locateChild(self, request, segments):
-        self.provision()
         name = segments[0]
         if name == "":
             return (self, segments[1:])
@@ -235,10 +219,6 @@
 
         self.directory = parent.directory
         self.parent = parent
-        
-        # TODO: better way to get this class - perhaps request from the store
-        from twistedcaldav.resource import CalendarHomeResource
-        self.homeResourceClass = CalendarHomeResource
 
     def url(self):
         return joinURL(self.parent.url(), uidsResourceName)
@@ -264,7 +244,6 @@
 
     def homeResourceForRecord(self, record, request):
 
-        self.provision()
         transaction = transactionFromRequest(request, self.parent._newStore)
         name = record.uid
 
@@ -279,7 +258,7 @@
         assert len(name) > 4, "Directory record has an invalid GUID: %r" % (name,)
         
         if record.locallyHosted():
-            child = self.homeResourceClass(self, record, transaction)
+            child = DirectoryCalendarHomeResource(self, record, transaction)
         else:
             child = DirectoryReverseProxyResource(self, record)
 
@@ -306,132 +285,22 @@
         return self.parent.principalForRecord(record)
 
 
-class DirectoryCalendarHomeResource (AutoProvisioningResourceMixIn, DAVResource):
+class DirectoryCalendarHomeResource (CalendarHomeResource):
     """
     Calendar home collection resource.
     """
-    def __init__(self, parent, record):
+    def __init__(self, parent, record, transaction):
         """
         @param path: the path to the file which will back the resource.
         """
         assert parent is not None
         assert record is not None
+        assert transaction is not None
 
-        super(DirectoryCalendarHomeResource, self).__init__()
-
         self.record = record
-        self.parent = parent
+        super(DirectoryCalendarHomeResource, self).__init__(parent, record.uid, transaction)
 
-        # Cache children which must be of a specific type
-        from twistedcaldav.schedule import ScheduleInboxResource, ScheduleOutboxResource
-        childlist = (
-            ("inbox" , ScheduleInboxResource ),
-            ("outbox", ScheduleOutboxResource),
-        )
-        if config.EnableDropBox:
-            childlist += (
-                ("dropbox", DropBoxHomeResource),
-            )
-        if config.FreeBusyURL.Enabled:
-            from twistedcaldav.freebusyurl import FreeBusyURLResource
-            childlist += (
-                ("freebusy", FreeBusyURLResource),
-            )
-        if config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
-            from twistedcaldav.notifications import NotificationCollectionResource
-            childlist += (
-                ("notification", NotificationCollectionResource),
-            )
-        for name, cls in childlist:
-            child = self.provisionChild(name)
-            # assert isinstance(child, cls), "Child %r is not a %s: %r" % (name, cls.__name__, child)
-            self.putChild(name, child)
-
-
-    def provisionChild(self, name):
-        raise NotImplementedError("Subclass must implement provisionChild()")
-
-    def url(self):
-        return joinURL(self.parent.url(), self.record.uid, "/")
-
-    def canonicalURL(self, request):
-        return succeed(self.url())
-
-    ##
-    # DAV
-    ##
-    
-    def isCollection(self):
-        return True
-
-    def http_COPY(self, request):
-        return responsecode.FORBIDDEN
-
-    ##
-    # ACL
-    ##
-
-    def owner(self, request):
-        return succeed(davxml.HRef(self.principalForRecord().principalURL()))
-
-    def ownerPrincipal(self, request):
-        return succeed(self.principalForRecord())
-
-    def resourceOwnerPrincipal(self, request):
-        return succeed(self.principalForRecord())
-
-    def defaultAccessControlList(self):
-        myPrincipal = self.principalForRecord()
-
-        aces = (
-            # Inheritable DAV:all access for the resource's associated principal.
-            davxml.ACE(
-                davxml.Principal(davxml.HRef(myPrincipal.principalURL())),
-                davxml.Grant(davxml.Privilege(davxml.All())),
-                davxml.Protected(),
-                TwistedACLInheritable(),
-            ),
-            # Inheritable CALDAV:read-free-busy access for authenticated users.
-            davxml.ACE(
-                davxml.Principal(davxml.Authenticated()),
-                davxml.Grant(davxml.Privilege(caldavxml.ReadFreeBusy())),
-                TwistedACLInheritable(),
-            ),
-        )
-
-        # Give read access to config.ReadPrincipals
-        aces += config.ReadACEs
-
-        # Give all access to config.AdminPrincipals
-        aces += config.AdminACEs
-        
-        if config.EnableProxyPrincipals:
-            aces += (
-                # DAV:read/DAV:read-current-user-privilege-set access for this principal's calendar-proxy-read users.
-                davxml.ACE(
-                    davxml.Principal(davxml.HRef(joinURL(myPrincipal.principalURL(), "calendar-proxy-read/"))),
-                    davxml.Grant(
-                        davxml.Privilege(davxml.Read()),
-                        davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
-                    ),
-                    davxml.Protected(),
-                    TwistedACLInheritable(),
-                ),
-                # DAV:read/DAV:read-current-user-privilege-set/DAV:write access for this principal's calendar-proxy-write users.
-                davxml.ACE(
-                    davxml.Principal(davxml.HRef(joinURL(myPrincipal.principalURL(), "calendar-proxy-write/"))),
-                    davxml.Grant(
-                        davxml.Privilege(davxml.Read()),
-                        davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
-                        davxml.Privilege(davxml.Write()),
-                    ),
-                    davxml.Protected(),
-                    TwistedACLInheritable(),
-                ),
-            )
-
-        return davxml.ACL(*aces)
-
+    # Special ACLs for Wiki service
     def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None):
         def gotACL(wikiACL):
             if wikiACL is not None:
@@ -447,29 +316,5 @@
         d.addCallback(gotACL)
         return d
 
-    def principalCollections(self):
-        return self.parent.principalCollections()
-
     def principalForRecord(self):
         return self.parent.principalForRecord(self.record)
-
-    ##
-    # Quota
-    ##
-
-    def hasQuotaRoot(self, request):
-        """
-        Always get quota root value from config.
-
-        @return: a C{True} if this resource has quota root, C{False} otherwise.
-        """
-        return config.UserQuota != 0
-    
-    def quotaRoot(self, request):
-        """
-        Always get quota root value from config.
-
-        @return: a C{int} containing the maximum allowed bytes if this collection
-            is quota-controlled, or C{None} if not quota controlled.
-        """
-        return config.UserQuota if config.UserQuota != 0 else None

Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/resource.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/resource.py	2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/resource.py	2010-08-03 20:44:19 UTC (rev 5970)
@@ -13,65 +13,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
-from twistedcaldav.client.reverseproxy import ReverseProxyResource
-from twext.web2.dav.util import joinURL
 
 """
 Implements a directory-backed principal hierarchy.
 """
 
-__all__ = ["AutoProvisioningResourceMixIn"]
+from twext.web2.dav.util import joinURL
 
-from twisted.internet.defer import maybeDeferred, inlineCallbacks, returnValue
+from twistedcaldav.client.reverseproxy import ReverseProxyResource
 
-class AutoProvisioningResourceMixIn (object):
-    """
-    Adds auto-provisioning to a Resource implementation.
-    """
-    def provision(self):
-        """
-        Provision this resource by creating any required backing store, etc. that
-        must be set up before the resource can be accessed normally.  Specifically,
-        this must have been called before anything that involves I/O happens.
-        This method may be called multiple times; provisioning code should ensure that
-        it handles this properly, typically by returning immediately if the resource is
-        already provisioned (eg. the backing store exists).
-        @return: a deferred or None.
-        """
-        return None
+__all__ = ["DirectoryReverseProxyResource"]
 
-    def provisionChild(self, name):
-        """
-        Creates the child object with the given name.
-        This is basically akin to L{File.createSimilarFile}, but here we know we're
-        creating a child of this resource, and can take certain actions to ensure that
-        it's prepared appropriately and is of the correct class.
-        @param name: the name of the child resource.
-        @return: the newly created (optionally deferred) child, or None of no resource
-            is bound as a child of this resource with the given C{name}.
-        """
-        return None
-
-    @inlineCallbacks
-    def locateChild(self, request, segments):
-        """
-        This implementation calls L{provision}, then super's L{locateChild}, thereby
-        ensuring that looked-up resources are provisioned.
-        """
-        yield maybeDeferred(self.provision)
-
-        name = segments[0]
-        if name != "":
-            # If getChild() finds a child resource, return it
-            child = self.getChild(name)
-            if child is None:
-                child = self.provisionChild(name)
-            if child:
-                returnValue((child, segments[1:],))
-        
-        result = (yield super(AutoProvisioningResourceMixIn, self).locateChild(request, segments))
-        returnValue(result)
-
 class DirectoryReverseProxyResource(ReverseProxyResource):
     
     def __init__(self, parent, record):

Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/extensions.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/extensions.py	2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/extensions.py	2010-08-03 20:44:19 UTC (rev 5970)
@@ -635,7 +635,7 @@
                 return value
             
         url = urllib.quote(name, '/')
-        if isinstance(child, SuperDAVFile) and child.isCollection():
+        if isinstance(child, DAVResource) and child.isCollection():
             url += "/"
             name += "/"
 
@@ -710,8 +710,10 @@
         # Allow live property to be overridden by dead property
         if self.deadProperties().contains((dav_namespace, "resourcetype")):
             return self.deadProperties().get((dav_namespace, "resourcetype"))
-        return davxml.ResourceType()
+        return davxml.ResourceType(davxml.Collection()) if self.isCollection() else davxml.ResourceType()
 
+    def contentType(self):
+        return MimeType("httpd", "unix-directory") if self.isCollection() else None
 
 class DAVResourceWithChildrenMixin (object):
     """

Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/method/report_sync_collection.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/method/report_sync_collection.py	2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/method/report_sync_collection.py	2010-08-03 20:44:19 UTC (rev 5970)
@@ -60,7 +60,7 @@
         Return the specified properties on the specified resource.
         @param request: the L{IRequest} for the current request.
         @param props: a list of property elements or qname tuples for the properties of interest.
-        @param resource: the L{DAVFile} for the targeted resource.
+        @param resource: the L{DAVResource} for the targeted resource.
         @return: a map of OK and NOT FOUND property values.
         """
         properties_by_status = {

Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/resource.py	2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/resource.py	2010-08-03 20:44:19 UTC (rev 5970)
@@ -70,9 +70,8 @@
 from twistedcaldav.customxml import calendarserver_namespace
 from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
 from twistedcaldav.datafilters.privateevents import PrivateEventFilter
-from twistedcaldav.directory.addressbook import DirectoryAddressBookHomeResource
-from twistedcaldav.directory.calendar import DirectoryCalendarHomeResource
 from twistedcaldav.directory.internal import InternalDirectoryRecord
+from twistedcaldav.dropbox import DropBoxHomeResource
 from twistedcaldav.extensions import DAVResource, DAVPrincipalResource,\
     PropertyNotFoundError, DAVResourceWithChildrenMixin
 from twistedcaldav.ical import Component
@@ -2113,47 +2112,46 @@
         """
         return None
 
-class CalendarHomeResource(SharedHomeMixin, DirectoryCalendarHomeResource, CalDAVResource):
+class CommonHomeResource(SharedHomeMixin, CalDAVResource):
     """
     Calendar home collection resource.
     """
-    def __init__(self, parent, record, transaction):
+    def __init__(self, parent, name, transaction):
         """
         """
 
+        self.parent = parent
+        self.name = name
         self.associateWithTransaction(transaction)
+        self._provisionedChildren = {}
+        self._provisionedLinks = {}
+        self._setupProvisions()
 
         # TODO: when calendar home gets a resourceID( ) method, remove
-        # the "id=record.uid" keyword from this call:
-        self.clientNotifier = ClientNotifier(self, id=record.uid)
-        storeHome = transaction.calendarHomeWithUID(record.uid)
-        if storeHome is not None:
-            created = False
-        else:
-            storeHome = transaction.calendarHomeWithUID(
-                record.uid, create=True
-            )
-            created = True
-        self._newStoreCalendarHome = storeHome
+        # the "id=name" keyword from this call:
+        self.clientNotifier = ClientNotifier(self, id=name)
+        self._newStoreHome, created = self.makeNewStore()
         CalDAVResource.__init__(self)
-        DirectoryCalendarHomeResource.__init__(self, parent, record)
 
         from twistedcaldav.storebridge import _NewStorePropertiesWrapper
         self._dead_properties = _NewStorePropertiesWrapper(
-            self._newStoreCalendarHome.properties()
+            self._newStoreHome.properties()
         )
         if created:
-            # This is a bit of a hack.  Really we ought to be always generating
-            # this URL live from a back-end method that tells us what the
-            # default calendar is.
-            inbox = self.getChild("inbox")
-            childURL = joinURL(self.url(), "calendar")
-            inbox.processFreeBusyCalendar(childURL, True)
+            self.postCreateHome()
 
+    def _setupProvisions(self):
+        pass
 
+    def makeNewStore(self):
+        raise NotImplementedError
+
+    def postCreateHome(self):
+        pass
+
     def liveProperties(self):
         
-        return super(CalendarHomeResource, self).liveProperties() + (
+        return super(CommonHomeResource, self).liveProperties() + (
             (customxml.calendarserver_namespace, "push-transports"),
             (customxml.calendarserver_namespace, "pushkey"),
             (customxml.calendarserver_namespace, "xmpp-uri"),
@@ -2166,67 +2164,85 @@
         Retrieve the new-style shares DB wrapper.
         """
         if not hasattr(self, "_sharesDB"):
-            self._sharesDB = self._newStoreCalendarHome.retrieveOldShares()
+            self._sharesDB = self._newStoreHome.retrieveOldShares()
         return self._sharesDB
 
 
+    def url(self):
+        return joinURL(self.parent.url(), self.name, "/")
+
+    def canonicalURL(self, request):
+        return succeed(self.url())
+
     def exists(self):
         # FIXME: tests
         return True
-    
-    
+
+    def isCollection(self):
+        return True
+
     def quotaSize(self, request):
         # FIXME: tests, workingness
         return succeed(0)
 
+    def hasQuotaRoot(self, request):
+        """
+        Always get quota root value from config.
 
-    def provision(self):
-        if config.Sharing.Enabled and config.Sharing.Calendars.Enabled and self.exists():
-            self.provisionShares()
-        return
+        @return: a C{True} if this resource has quota root, C{False} otherwise.
+        """
+        return config.UserQuota != 0
+    
+    def quotaRoot(self, request):
+        """
+        Always get quota root value from config.
 
-    def provisionChild(self, name):
-        from twistedcaldav.storebridge import StoreScheduleInboxResource
-        from twistedcaldav.storebridge import DropboxCollection
-        if config.EnableDropBox:
-            DropBoxHomeFileClass = DropboxCollection
-        else:
-            DropBoxHomeFileClass = None
+        @return: a C{int} containing the maximum allowed bytes if this collection
+            is quota-controlled, or C{None} if not quota controlled.
+        """
+        return config.UserQuota if config.UserQuota != 0 else None
 
-        if config.FreeBusyURL.Enabled:
-            from twistedcaldav.freebusyurl import FreeBusyURLResource
-            FreeBusyURLResourceClass = FreeBusyURLResource
-        else:
-            FreeBusyURLResourceClass = None
-            
-        # For storebridge stuff we special case this
-        if name == "notification" and config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
-            return self.createNotificationsCollection()
+    def canShare(self):
+        raise NotImplementedError
 
-        from twistedcaldav.schedule import ScheduleOutboxResource
-        cls = {
-            "inbox"        : StoreScheduleInboxResource,
-            "outbox"       : ScheduleOutboxResource,
-            "dropbox"      : DropBoxHomeFileClass,
-            "freebusy"     : FreeBusyURLResourceClass,
-        }.get(name, None)
-
-        if cls is not None:
-            child = cls(self)
+    def makeChild(self, name):
+        
+        # Try built-in children first
+        if name in self._provisionedChildren:
+            cls = self._provisionedChildren[name]
+            from twistedcaldav.notifications import NotificationCollectionResource
+            if cls is NotificationCollectionResource:
+                return self.createNotificationsCollection()
+            child = self._provisionedChildren[name](self)
             child.clientNotifier = self.clientNotifier.clone(child,
                 label="collection")
+            self.putChild(name, child)
             return child
-        return self.makeChild(name)
+        
+        # Try built-in links next
+        if name in self._provisionedLinks:
+            child = LinkResource(self, self._provisionedLinks[name])
+            self.putChild(name, child)
+            return child
+        
+        # Try shares next
+        if self.canShare():
+            child = self.provisionShare(name)
+            if child:
+                return child
 
+        # Do normal child types
+        return self.makeRegularChild(name)
+
     def createNotificationsCollection(self):
         
-        txn = self._newStoreCalendarHome._transaction
-        notifications = txn.notificationsWithUID(self._newStoreCalendarHome.uid())
+        txn = self._newStoreHome._transaction
+        notifications = txn.notificationsWithUID(self._newStoreHome.uid())
 
         from twistedcaldav.storebridge import StoreNotificationCollectionResource
         similar = StoreNotificationCollectionResource(
             notifications,
-            self._newStoreCalendarHome,
+            self._newStoreHome,
             principalCollections = self.principalCollections(),
         )
         self.propagateTransaction(similar)
@@ -2234,42 +2250,17 @@
             label="collection")
         return similar
 
-    def makeChild(self, name):
+    def makeRegularChild(self, name):
+        raise NotImplementedError
 
-        newCalendar = self._newStoreCalendarHome.calendarWithName(name)
-        if newCalendar is None:
-            # Local imports.due to circular dependency between modules.
-            from twistedcaldav.storebridge import (
-                 ProtoCalendarCollectionResource)
-            similar = ProtoCalendarCollectionResource(
-                self._newStoreCalendarHome,
-                name,
-                principalCollections=self.principalCollections()
-            )
-        else:
-            from twistedcaldav.storebridge import CalendarCollectionResource
-            similar = CalendarCollectionResource(
-                newCalendar, self._newStoreCalendarHome,
-                principalCollections=self.principalCollections()
-            )
-        self.propagateTransaction(similar)
-        similar.clientNotifier = self.clientNotifier.clone(similar,
-            label="collection")
-        return similar
-
-    def getChild(self, name):
-        # This avoids finding case variants of put children on case-insensitive filesystems.
-        if name not in self.putChildren and name.lower() in (x.lower() for x in self.putChildren):
-            return None
-
-        return super(CalendarHomeResource, self).getChild(name)
-
     def listChildren(self):
         """
         @return: a sequence of the names of all known children of this resource.
         """
-        children = set(self.putChildren.keys())
-        children.update(self._newStoreCalendarHome.listCalendars())
+        children = set(self._provisionedChildren.keys())
+        children.update(self._provisionedLinks.keys())
+        children.update(self.allShareNames())
+        children.update(self._newStoreHome.listChildren())
         return children
 
     def readProperty(self, property, request):
@@ -2379,105 +2370,205 @@
             else:
                 return succeed(customxml.PubSubXMPPServerProperty())
 
-        return super(CalendarHomeResource, self).readProperty(property, request)
+        return super(CommonHomeResource, self).readProperty(property, request)
 
-    http_ACL = None     # ACL method not supported
+    ##
+    # ACL
+    ##
 
-class AddressBookHomeResource (SharedHomeMixin, DirectoryAddressBookHomeResource, CalDAVResource):
-    """
-    Address book home collection resource.
-    """
-    
-    def __init__(self, parent, record, transaction):
-        """
-        """
+    def owner(self, request):
+        return succeed(davxml.HRef(self.principalForRecord().principalURL()))
 
-        self.associateWithTransaction(transaction)
+    def ownerPrincipal(self, request):
+        return succeed(self.principalForRecord())
 
-        # TODO: when addressbook home gets a resourceID( ) method, remove
-        # the "id=record.uid" keyword from this call:
-        self.clientNotifier = ClientNotifier(self, id=record.uid)
-        self._newStoreAddressBookHome = (
-            transaction.addressbookHomeWithUID(record.uid, create=True)
-        )
-        CalDAVResource.__init__(self)
-        DirectoryAddressBookHomeResource.__init__(self, parent, record)
+    def resourceOwnerPrincipal(self, request):
+        return succeed(self.principalForRecord())
 
-        from twistedcaldav.storebridge import _NewStorePropertiesWrapper
-        self._dead_properties = _NewStorePropertiesWrapper(
-            self._newStoreAddressBookHome.properties()
+    def defaultAccessControlList(self):
+        myPrincipal = self.principalForRecord()
+
+        aces = (
+            # Inheritable DAV:all access for the resource's associated principal.
+            davxml.ACE(
+                davxml.Principal(davxml.HRef(myPrincipal.principalURL())),
+                davxml.Grant(davxml.Privilege(davxml.All())),
+                davxml.Protected(),
+                TwistedACLInheritable(),
+            ),
         )
 
+        # Give read access to config.ReadPrincipals
+        aces += config.ReadACEs
 
-    def liveProperties(self):
-        return super(AddressBookHomeResource, self).liveProperties() + (
-            (customxml.calendarserver_namespace, "push-transports"),
-            (customxml.calendarserver_namespace, "pushkey"),
-            (customxml.calendarserver_namespace, "xmpp-uri"),
-            (customxml.calendarserver_namespace, "xmpp-heartbeat-uri"),
-            (customxml.calendarserver_namespace, "xmpp-server"),
-        )
+        # Give all access to config.AdminPrincipals
+        aces += config.AdminACEs
+        
+        return davxml.ACL(*aces)
 
-    def sharesDB(self):
-        """
-        Retrieve the new-style shares DB wrapper.
-        """
-        if not hasattr(self, "_sharesDB"):
-            self._sharesDB = self._newStoreAddressBookHome.retrieveOldShares()
-        return self._sharesDB
+    def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None):
+        # Permissions here are fixed, and are not subject to inheritance rules, etc.
+        return succeed(self.defaultAccessControlList())
 
+    def principalCollections(self):
+        return self.parent.principalCollections()
 
-    def exists(self):
-        # FIXME: tests
-        return True
-    
-    
-    def quotaSize(self, request):
-        # FIXME: tests, workingness
-        return succeed(0)
+    def principalForRecord(self):
+        raise NotImplementedError("Subclass must implement principalForRecord()")
 
+    # Methods not supported
+    http_ACL = None
+    http_COPY = None
+    http_MOVE = None
 
-    def provision(self):
-        if config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled:
-            self.provisionShares()
-        self.provisionLinks()
 
-    def provisionLinks(self):
-        
-        if not hasattr(self, "_provisionedLinks"):
-            if config.GlobalAddressBook.Enabled:
-                self.putChild(
-                    config.GlobalAddressBook.Name,
-                    LinkResource(self, "/addressbooks/public/global/addressbook/"),
-                )
-            self._provisionedLinks = True
+class CalendarHomeResource(CommonHomeResource):
+    """
+    Calendar home collection resource.
+    """
 
-    def provisionChild(self, name):
- 
-        # For storebridge stuff we special case this
-        if name == "notification" and config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and not config.Sharing.Calendars.Enabled:
-            return self.createNotificationsCollection()
+    def _setupProvisions(self):
 
-        return self.makeChild(name)
+        # Cache children which must be of a specific type
+        from twistedcaldav.storebridge import StoreScheduleInboxResource
+        self._provisionedChildren["inbox"] = StoreScheduleInboxResource
 
-    def createNotificationsCollection(self):
-        
-        txn = self._newStoreAddressBookHome._transaction
-        notifications = txn.notificationsWithUID(self._newStoreAddressBookHome.uid())
+        from twistedcaldav.schedule import ScheduleOutboxResource
+        self._provisionedChildren["outbox"] = ScheduleOutboxResource
 
-        from twistedcaldav.storebridge import StoreNotificationCollectionResource
-        similar = StoreNotificationCollectionResource(
-            notifications,
-            self._newStoreAddressBookHome,
-            principalCollections = self.principalCollections(),
-        )
+        if config.EnableDropBox:
+            from twistedcaldav.storebridge import DropboxCollection
+            self._provisionedChildren["dropbox"] = DropboxCollection
+
+        if config.FreeBusyURL.Enabled:
+            from twistedcaldav.freebusyurl import FreeBusyURLResource
+            self._provisionedChildren["freebusy"] = FreeBusyURLResource
+
+        if config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
+            from twistedcaldav.notifications import NotificationCollectionResource
+            self._provisionedChildren["notification"] = NotificationCollectionResource
+
+    def makeNewStore(self):
+        storeHome = self._associatedTransaction.calendarHomeWithUID(self.name)
+        if storeHome is not None:
+            created = False
+        else:
+            storeHome = self._associatedTransaction.calendarHomeWithUID(
+                self.name, create=True
+            )
+            created = True
+
+        return storeHome, created
+
+    def postCreateHome(self):
+        # This is a bit of a hack.  Really we ought to be always generating
+        # this URL live from a back-end method that tells us what the
+        # default calendar is.
+        inbox = self.getChild("inbox")
+        childURL = joinURL(self.url(), "calendar")
+        inbox.processFreeBusyCalendar(childURL, True)
+
+    def canShare(self):
+        return config.Sharing.Enabled and config.Sharing.Calendars.Enabled and self.exists()
+
+    def makeRegularChild(self, name):
+
+        newCalendar = self._newStoreHome.calendarWithName(name)
+        if newCalendar is None:
+            # Local imports.due to circular dependency between modules.
+            from twistedcaldav.storebridge import (
+                 ProtoCalendarCollectionResource)
+            similar = ProtoCalendarCollectionResource(
+                self._newStoreHome,
+                name,
+                principalCollections=self.principalCollections()
+            )
+        else:
+            from twistedcaldav.storebridge import CalendarCollectionResource
+            similar = CalendarCollectionResource(
+                newCalendar, self._newStoreHome,
+                principalCollections=self.principalCollections()
+            )
         self.propagateTransaction(similar)
         similar.clientNotifier = self.clientNotifier.clone(similar,
             label="collection")
         return similar
 
-    def makeChild(self, name):
+    def defaultAccessControlList(self):
+        myPrincipal = self.principalForRecord()
 
+        aces = (
+            # Inheritable DAV:all access for the resource's associated principal.
+            davxml.ACE(
+                davxml.Principal(davxml.HRef(myPrincipal.principalURL())),
+                davxml.Grant(davxml.Privilege(davxml.All())),
+                davxml.Protected(),
+                TwistedACLInheritable(),
+            ),
+            # Inheritable CALDAV:read-free-busy access for authenticated users.
+            davxml.ACE(
+                davxml.Principal(davxml.Authenticated()),
+                davxml.Grant(davxml.Privilege(caldavxml.ReadFreeBusy())),
+                TwistedACLInheritable(),
+            ),
+        )
+
+        # Give read access to config.ReadPrincipals
+        aces += config.ReadACEs
+
+        # Give all access to config.AdminPrincipals
+        aces += config.AdminACEs
+        
+        if config.EnableProxyPrincipals:
+            aces += (
+                # DAV:read/DAV:read-current-user-privilege-set access for this principal's calendar-proxy-read users.
+                davxml.ACE(
+                    davxml.Principal(davxml.HRef(joinURL(myPrincipal.principalURL(), "calendar-proxy-read/"))),
+                    davxml.Grant(
+                        davxml.Privilege(davxml.Read()),
+                        davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
+                    ),
+                    davxml.Protected(),
+                    TwistedACLInheritable(),
+                ),
+                # DAV:read/DAV:read-current-user-privilege-set/DAV:write access for this principal's calendar-proxy-write users.
+                davxml.ACE(
+                    davxml.Principal(davxml.HRef(joinURL(myPrincipal.principalURL(), "calendar-proxy-write/"))),
+                    davxml.Grant(
+                        davxml.Privilege(davxml.Read()),
+                        davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
+                        davxml.Privilege(davxml.Write()),
+                    ),
+                    davxml.Protected(),
+                    TwistedACLInheritable(),
+                ),
+            )
+
+        return davxml.ACL(*aces)
+
+class AddressBookHomeResource (CommonHomeResource):
+    """
+    Address book home collection resource.
+    """
+    
+    def _setupProvisions(self):
+
+        # Cache children which must be of a specific type
+        if config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and not config.Sharing.Calendars.Enabled:
+            from twistedcaldav.notifications import NotificationCollectionResource
+            self._provisionedChildren["notification"] = NotificationCollectionResource
+
+        if config.GlobalAddressBook.Enabled:
+            self._provisionedLinks[config.GlobalAddressBook.Name] = "/addressbooks/public/global/addressbook/"
+
+    def makeNewStore(self):
+        return self._associatedTransaction.addressbookHomeWithUID(self.name, create=True), False     # Don't care about created
+
+    def canShare(self):
+        return config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and self.exists()
+
+    def makeRegularChild(self, name):
+
         # Check for public/global path
         from twistedcaldav.storebridge import (
             AddressBookCollectionResource,
@@ -2492,17 +2583,17 @@
                 mainCls = GlobalAddressBookCollectionResource
                 protoCls = ProtoGlobalAddressBookCollectionResource
 
-        newAddressBook = self._newStoreAddressBookHome.addressbookWithName(name)
+        newAddressBook = self._newStoreHome.addressbookWithName(name)
         if newAddressBook is None:
             # Local imports.due to circular dependency between modules.
             similar = protoCls(
-                self._newStoreAddressBookHome,
+                self._newStoreHome,
                 name,
                 principalCollections=self.principalCollections()
             )
         else:
             similar = mainCls(
-                newAddressBook, self._newStoreAddressBookHome,
+                newAddressBook, self._newStoreHome,
                 principalCollections=self.principalCollections()
             )
         self.propagateTransaction(similar)
@@ -2510,132 +2601,7 @@
             label="collection")
         return similar
 
-    def getChild(self, name):
-        # This avoids finding case variants of put children on case-insensitive filesystems.
-        if name not in self.putChildren and name.lower() in (x.lower() for x in self.putChildren):
-            return None
 
-        return super(AddressBookHomeResource, self).getChild(name)
-
-    def listChildren(self):
-        """
-        @return: a sequence of the names of all known children of this resource.
-        """
-        children = set(self.putChildren.keys())
-        children.update(self._newStoreAddressBookHome.listAddressbooks())
-        return children
-
-    def readProperty(self, property, request):
-        if type(property) is tuple:
-            qname = property
-        else:
-            qname = property.qname()
-
-        if qname == (customxml.calendarserver_namespace, "push-transports"):
-            pubSubConfiguration = getPubSubConfiguration(config)
-            if (pubSubConfiguration['enabled'] and
-                getattr(self, "clientNotifier", None) is not None):
-                    id = self.clientNotifier.getID()
-                    nodeName = getPubSubPath(id, pubSubConfiguration)
-                    children = []
-                    if pubSubConfiguration['aps-bundle-id']:
-                        children.append(
-                            customxml.PubSubTransportProperty(
-                                customxml.PubSubSubscriptionProperty(
-                                    davxml.HRef(
-                                        pubSubConfiguration['subscription-url']
-                                    ),
-                                ),
-                                customxml.PubSubAPSBundleIDProperty(
-                                    pubSubConfiguration['aps-bundle-id']
-                                ),
-                                type="APSD",
-                            )
-                        )
-                    if pubSubConfiguration['xmpp-server']:
-                        children.append(
-                            customxml.PubSubTransportProperty(
-                                customxml.PubSubXMPPServerProperty(
-                                    pubSubConfiguration['xmpp-server']
-                                ),
-                                customxml.PubSubXMPPURIProperty(
-                                    getPubSubXMPPURI(id, pubSubConfiguration)
-                                ),
-                                type="XMPP",
-                            )
-                        )
-
-                    propVal = customxml.PubSubPushTransportsProperty(*children)
-                    nodeCacher = getNodeCacher()
-                    d = nodeCacher.waitForNode(self.clientNotifier, nodeName)
-                    # In either case we're going to return the value
-                    d.addBoth(lambda ignored: propVal)
-                    return d
-
-
-            else:
-                return succeed(customxml.PubSubPushTransportsProperty())
-
-        if qname == (customxml.calendarserver_namespace, "pushkey"):
-            pubSubConfiguration = getPubSubConfiguration(config)
-            if pubSubConfiguration['enabled']:
-                if getattr(self, "clientNotifier", None) is not None:
-                    id = self.clientNotifier.getID()
-                    nodeName = getPubSubPath(id, pubSubConfiguration)
-                    propVal = customxml.PubSubXMPPPushKeyProperty(nodeName)
-                    nodeCacher = getNodeCacher()
-                    d = nodeCacher.waitForNode(self.clientNotifier, nodeName)
-                    # In either case we're going to return the xmpp-uri value
-                    d.addBoth(lambda ignored: propVal)
-                    return d
-            else:
-                return succeed(customxml.PubSubXMPPPushKeyProperty())
-
-
-        if qname == (customxml.calendarserver_namespace, "xmpp-uri"):
-            pubSubConfiguration = getPubSubConfiguration(config)
-            if pubSubConfiguration['enabled']:
-                if getattr(self, "clientNotifier", None) is not None:
-                    id = self.clientNotifier.getID()
-                    nodeName = getPubSubPath(id, pubSubConfiguration)
-                    propVal = customxml.PubSubXMPPURIProperty(
-                        getPubSubXMPPURI(id, pubSubConfiguration))
-                    nodeCacher = getNodeCacher()
-                    d = nodeCacher.waitForNode(self.clientNotifier, nodeName)
-                    # In either case we're going to return the xmpp-uri value
-                    d.addBoth(lambda ignored: propVal)
-                    return d
-            else:
-                return succeed(customxml.PubSubXMPPURIProperty())
-
-        elif qname == (customxml.calendarserver_namespace, "xmpp-heartbeat-uri"):
-            pubSubConfiguration = getPubSubConfiguration(config)
-            if pubSubConfiguration['enabled']:
-                return succeed(
-                    customxml.PubSubHeartbeatProperty(
-                        customxml.PubSubHeartbeatURIProperty(
-                            getPubSubHeartbeatURI(pubSubConfiguration)
-                        ),
-                        customxml.PubSubHeartbeatMinutesProperty(
-                            str(pubSubConfiguration['heartrate'])
-                        )
-                    )
-                )
-            else:
-                return succeed(customxml.PubSubHeartbeatURIProperty())
-
-        elif qname == (customxml.calendarserver_namespace, "xmpp-server"):
-            pubSubConfiguration = getPubSubConfiguration(config)
-            if pubSubConfiguration['enabled']:
-                return succeed(customxml.PubSubXMPPServerProperty(
-                    pubSubConfiguration['xmpp-server']))
-            else:
-                return succeed(customxml.PubSubXMPPServerProperty())
-
-        return super(AddressBookHomeResource, self).readProperty(property, request)
-
-    http_ACL = None     # ACL method not supported
-
 class GlobalAddressBookResource (ReadOnlyResourceMixIn, CalDAVResource):
     """
     Global address book. All we care about is making sure permissions are setup.

Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/schedule.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/schedule.py	2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/schedule.py	2010-08-03 20:44:19 UTC (rev 5970)
@@ -154,7 +154,7 @@
             if not self.hasDeadProperty(property):
                 top = self.parent.url()
                 values = []
-                for cal in self.parent._newStoreCalendarHome.calendars():
+                for cal in self.parent._newStoreHome.calendars():
                     prop = cal.properties().get(PropertyName.fromString(ScheduleCalendarTransp.sname())) 
                     if prop == ScheduleCalendarTransp(Opaque()):
                         values.append(HRef(joinURL(top, cal.name())))
@@ -261,7 +261,7 @@
         defaultCalendarURL = joinURL(calendarHomeURL, "calendar")
         defaultCalendar = (yield request.locateResource(defaultCalendarURL))
         if defaultCalendar is None or not defaultCalendar.exists():
-            getter = iter(self.parent._newStoreCalendarHome.calendars())
+            getter = iter(self.parent._newStoreHome.calendars())
             # FIXME: the back-end should re-provision a default calendar here.
             # Really, the dead property shouldn't be necessary, and this should
             # be entirely computed by a back-end method like 'defaultCalendar()'

Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/sharing.py	2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/sharing.py	2010-08-03 20:44:19 UTC (rev 5970)
@@ -946,15 +946,25 @@
             self._sharesDB = SharedCollectionsDatabase(self)
         return self._sharesDB
 
-    def provisionShares(self):
+    def provisionShare(self, name):
         
-        if not hasattr(self, "_provisionedShares"):
+        # Try to find a matching share
+        child = None
+        shares = self.allShares()
+        if name in shares:
             from twistedcaldav.sharedcollection import SharedCollectionResource
-            for share in self.sharesDB().allRecords():
-                child = SharedCollectionResource(self, share)
-                self.putChild(share.localname, child)
-            self._provisionedShares = True
+            child = SharedCollectionResource(self, shares[name])
+            self.putChild(name, child)
+        return child
 
+    def allShares(self):
+        if not hasattr(self, "_allShares"):
+            self._allShares = dict([(share.localname, share) for share in self.sharesDB().allRecords()])
+        return self._allShares
+
+    def allShareNames(self):
+        return tuple(self.allShares().keys())
+
     @inlineCallbacks
     def acceptInviteShare(self, request, hostUrl, inviteUID, displayname=None):
         

Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/storebridge.py	2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/storebridge.py	2010-08-03 20:44:19 UTC (rev 5970)
@@ -297,7 +297,7 @@
     def __init__(self, *a, **kw):
         super(StoreScheduleInboxResource, self).__init__(*a, **kw)
         self.parent.propagateTransaction(self)
-        home = self.parent._newStoreCalendarHome
+        home = self.parent._newStoreHome
         storage = home.calendarWithName("inbox")
         if storage is None:
             # raise RuntimeError("backend should be handling this for us")
@@ -308,7 +308,7 @@
             storage = home.calendarWithName("inbox")
         self._initializeWithCalendar(
             storage,
-            self.parent._newStoreCalendarHome
+            self.parent._newStoreHome
         )
 
 
@@ -365,7 +365,7 @@
     def __init__(self, parent, *a, **kw):
         kw.update(principalCollections=parent.principalCollections())
         super(DropboxCollection, self).__init__(*a, **kw)
-        self._newStoreCalendarHome = parent._newStoreCalendarHome
+        self._newStoreHome = parent._newStoreHome
         parent.propagateTransaction(self)
 
 
@@ -377,7 +377,7 @@
 
 
     def getChild(self, name):
-        calendarObject = self._newStoreCalendarHome.calendarObjectWithDropboxID(name)
+        calendarObject = self._newStoreHome.calendarObjectWithDropboxID(name)
         if calendarObject is None:
             return NoDropboxHere()
         objectDropbox = CalendarObjectDropbox(
@@ -393,7 +393,7 @@
 
     def listChildren(self):
         l = []
-        for everyCalendar in self._newStoreCalendarHome.calendars():
+        for everyCalendar in self._newStoreHome.calendars():
             for everyObject in everyCalendar.calendarObjects():
                 l.append(everyObject.dropboxID())
         return l

Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_multiget.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_multiget.py	2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_multiget.py	2010-08-03 20:44:19 UTC (rev 5970)
@@ -29,10 +29,10 @@
 from twistedcaldav import caldavxml
 from twistedcaldav import ical
 from twistedcaldav.index import db_basename
-from twistedcaldav.test.util import HomeTestCase
+from twistedcaldav.test.util import TestCase
 from twistedcaldav.config import config
 
-class CalendarMultiget (HomeTestCase):
+class CalendarMultiget (TestCase):
     """
     calendar-multiget REPORT
     """
@@ -44,12 +44,14 @@
         All events.
         (CalDAV-access-09, section 7.6.8)
         """
+        self.createStockDirectoryService()
+        self.setupCalendars()
         okuids = [r[0] for r in (os.path.splitext(f) for f in os.listdir(self.holidays_dir)) if r[1] == ".ics"]
         okuids[:] = okuids[1:10]
 
         baduids = ["12345 at example.com", "67890 at example.com"]
 
-        return self.simple_event_multiget("/calendar_multiget_events/", okuids, baduids)
+        return self.simple_event_multiget("/calendars/users/wsanchez/calendar_multiget_events/", okuids, baduids)
 
     def test_multiget_all_events(self):
         """

Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_wrapping.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_wrapping.py	2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_wrapping.py	2010-08-03 20:44:19 UTC (rev 5970)
@@ -235,7 +235,7 @@
         """
         calDavFile = yield self.getResource("calendars/users/wsanchez/")
         self.commit()
-        self.assertIsInstance(calDavFile._newStoreCalendarHome, CalendarHome)
+        self.assertIsInstance(calDavFile._newStoreHome, CalendarHome)
 
 
     @inlineCallbacks
@@ -350,7 +350,7 @@
         """
         calDavFile = yield self.getResource("addressbooks/users/wsanchez/")
         self.commit()
-        self.assertIsInstance(calDavFile._newStoreAddressBookHome, AddressBookHome)
+        self.assertIsInstance(calDavFile._newStoreHome, AddressBookHome)
 
 
     @inlineCallbacks

Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/util.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/util.py	2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/util.py	2010-08-03 20:44:19 UTC (rev 5970)
@@ -320,7 +320,7 @@
         def _defer(user):
             # Commit the transaction
             self.site.resource._associatedTransaction.commit()
-            self.docroot = user._newStoreCalendarHome._path.path
+            self.docroot = user._newStoreHome._path.path
 
         return self._refreshRoot().addCallback(_defer)
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100803/8a103bba/attachment-0001.html>


More information about the calendarserver-changes mailing list