[CalendarServer-changes] [3139] CalendarServer/trunk/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Fri Oct 10 12:04:19 PDT 2008


Revision: 3139
          http://trac.macosforge.org/projects/calendarserver/changeset/3139
Author:   sagen at apple.com
Date:     2008-10-10 12:04:18 -0700 (Fri, 10 Oct 2008)
Log Message:
-----------
Mix DirectoryPrincipalPropertySearchMixIn in with DAVResource and DAVPrincipalResource so that such reports can be run against more resources

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/directory/principal.py
    CalendarServer/trunk/twistedcaldav/extensions.py
    CalendarServer/trunk/twistedcaldav/static.py

Modified: CalendarServer/trunk/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/principal.py	2008-10-10 17:34:50 UTC (rev 3138)
+++ CalendarServer/trunk/twistedcaldav/directory/principal.py	2008-10-10 19:04:18 UTC (rev 3139)
@@ -76,7 +76,6 @@
 
 
 class DirectoryProvisioningResource (
-    DirectoryPrincipalPropertySearchMixIn,
     PermissionsMixIn,
     CalendarPrincipalCollectionResource,
     DAVFile,
@@ -415,7 +414,7 @@
     def principalCollections(self):
         return self.parent.principalCollections()
 
-class DirectoryPrincipalResource (DirectoryPrincipalPropertySearchMixIn, PropfindCacheMixin, PermissionsMixIn, DAVPrincipalResource, DAVFile):
+class DirectoryPrincipalResource (PropfindCacheMixin, PermissionsMixIn, DAVPrincipalResource, DAVFile):
     """
     Directory principal resource.
     """

Modified: CalendarServer/trunk/twistedcaldav/extensions.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/extensions.py	2008-10-10 17:34:50 UTC (rev 3138)
+++ CalendarServer/trunk/twistedcaldav/extensions.py	2008-10-10 19:04:18 UTC (rev 3139)
@@ -204,7 +204,158 @@
     return fun
 
 
-class DAVResource (SudoSACLMixin, SuperDAVResource, LoggingMixIn):
+class DirectoryPrincipalPropertySearchMixIn(object):
+
+    @deferredGenerator
+    def report_DAV__principal_property_search(self, request,
+        principal_property_search):
+        """
+        Generate a principal-property-search REPORT. (RFC 3744, section 9.4)
+        Overrides twisted implementation, targetting only directory-enabled
+        searching.
+        """
+        # Verify root element
+        if not isinstance(principal_property_search,
+            davxml.PrincipalPropertySearch):
+            raise ValueError("%s expected as root element, not %s." %
+                (davxml.PrincipalPropertySearch.sname(),
+                principal_property_search.sname()))
+
+        # Should we AND (the default) or OR (if test="anyof")?
+        testMode = principal_property_search.attributes.get("test", "allof")
+        if testMode not in ("allof", "anyof"):
+            raise ValueError("Unknown value for test attribute: %s" %
+                (testMode,))
+        operand = "and" if testMode == "allof" else "or"
+
+        # Are we narrowing results down to a single CUTYPE?
+        cuType = principal_property_search.attributes.get("type", None)
+        if cuType not in ("INDIVIDUAL", "GROUP", "RESOURCE", "ROOM", None):
+            raise ValueError("Unknown value for type attribute: %s" % (cuType,))
+
+        # Only handle Depth: 0
+        depth = request.headers.getHeader("depth", "0")
+        if depth != "0":
+            log.err("Error in prinicpal-property-search REPORT, Depth set to %s" % (depth,))
+            raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Depth %s not allowed" % (depth,)))
+
+        # Get a single DAV:prop element from the REPORT request body
+        propertiesForResource = None
+        propElement = None
+        propertySearches = []
+        applyTo = False
+        for child in principal_property_search.children:
+            if child.qname() == (dav_namespace, "prop"):
+                propertiesForResource = prop_common.propertyListForResource
+                propElement = child
+            elif child.qname() == (dav_namespace,
+                "apply-to-principal-collection-set"):
+                applyTo = True
+            elif child.qname() == (dav_namespace, "property-search"):
+                props = child.childOfType(davxml.PropertyContainer)
+                props.removeWhitespaceNodes()
+
+                match = child.childOfType(davxml.Match)
+                caseless = match.attributes.get("caseless", "yes")
+                if caseless not in ("yes", "no"):
+                    raise ValueError("Unknown value for caseless attribute: %s"
+                        % (caseless,))
+                caseless = True if caseless == "yes" else False
+                matchType = match.attributes.get("match-type", "contains")
+                if matchType not in ("starts-with", "contains"):
+                    raise ValueError("Unknown value for match-type attribute: %s" %
+                        (matchType,))
+
+                propertySearches.append((props.children, str(match),
+                    caseless, matchType))
+
+        # Run report
+        try:
+
+            resources = []
+            if applyTo or not hasattr(self, "directory"):
+                for principalCollection in self.principalCollections():
+                    uri = principalCollection.principalCollectionURL()
+                    resource = waitForDeferred(request.locateResource(uri))
+                    yield resource
+                    resource = resource.getResult()
+                    if resource:
+                        resources.append((resource, uri))
+            else:
+                resources.append((self, request.uri))
+
+            # We need to access a directory service
+            principalCollection = resources[0][0]
+            if not hasattr(principalCollection, "directory"):
+                # Use Twisted's implementation instead in this case
+                d = waitForDeferred(super(DirectoryPrincipalPropertySearchMixIn, self).report_DAV__principal_property_search(request, principal_property_search))
+                yield d
+                yield d.getResult()
+                return
+
+            dir = principalCollection.directory
+
+            # See if we can take advantage of the directory
+            fields = []
+            nonDirectorySearches = []
+            for props, match, caseless, matchType in propertySearches:
+                nonDirectoryProps = []
+                for prop in props:
+                    fieldName, match = principalCollection.propertyToField(
+                        prop, match)
+                    if fieldName:
+                        fields.append((fieldName, match, caseless, matchType))
+                    else:
+                        nonDirectoryProps.append(prop)
+                if nonDirectoryProps:
+                    nonDirectorySearches.append((nonDirectoryProps, match,
+                        caseless, matchType))
+
+            matchingResources = []
+            matchcount = 0
+
+            # nonDirectorySearches are ignored
+
+            if fields:
+
+                for record in dir.recordsMatchingFieldsWithCUType(fields,
+                    operand=operand, cuType=cuType):
+
+                    resource = principalCollection.principalForRecord(record)
+
+                    # We've determined this is a matching resource
+                    matchcount += 1
+                    if matchcount > max_number_of_matches:
+                        raise NumberOfMatchesWithinLimits
+                    matchingResources.append(resource)
+
+            # Generate the response
+            responses = []
+            for resource in matchingResources:
+                url = resource.url()
+                d = waitForDeferred(prop_common.responseForHref(
+                    request,
+                    responses,
+                    davxml.HRef.fromString(url),
+                    resource,
+                    propertiesForResource,
+                    propElement
+                ))
+                yield d
+                d.getResult()
+
+
+        except NumberOfMatchesWithinLimits:
+            log.err("Too many matching components in prinicpal-property-search report")
+            raise HTTPError(ErrorResponse(
+                responsecode.FORBIDDEN,
+                (dav_namespace, "number-of-matches-within-limits")
+            ))
+
+        yield MultiStatusResponse(responses)
+
+
+class DAVResource (DirectoryPrincipalPropertySearchMixIn, SudoSACLMixin, SuperDAVResource, LoggingMixIn):
     """
     Extended L{twisted.web2.dav.resource.DAVResource} implementation.
     """
@@ -405,7 +556,7 @@
         returnValue(match)
 
 
-class DAVPrincipalResource (SuperDAVPrincipalResource, LoggingMixIn):
+class DAVPrincipalResource (DirectoryPrincipalPropertySearchMixIn, SuperDAVPrincipalResource, LoggingMixIn):
     """
     Extended L{twisted.web2.dav.static.DAVFile} implementation.
     """
@@ -839,147 +990,3 @@
             )
         return self._data
 
-
-class DirectoryPrincipalPropertySearchMixIn(object):
-
-    def report_DAV__principal_property_search(self, request,
-        principal_property_search):
-        """
-        Generate a principal-property-search REPORT. (RFC 3744, section 9.4)
-        Overrides twisted implementation, targetting only directory-enabled
-        searching.
-        """
-        # Verify root element
-        if not isinstance(principal_property_search,
-            davxml.PrincipalPropertySearch):
-            raise ValueError("%s expected as root element, not %s." %
-                (davxml.PrincipalPropertySearch.sname(),
-                principal_property_search.sname()))
-
-        # Should we AND (the default) or OR (if test="anyof")?
-        testMode = principal_property_search.attributes.get("test", "allof")
-        if testMode not in ("allof", "anyof"):
-            raise ValueError("Unknown value for test attribute: %s" %
-                (testMode,))
-        operand = "and" if testMode == "allof" else "or"
-
-        # Are we narrowing results down to a single CUTYPE?
-        cuType = principal_property_search.attributes.get("type", None)
-        if cuType not in ("INDIVIDUAL", "GROUP", "RESOURCE", "ROOM", None):
-            raise ValueError("Unknown value for type attribute: %s" % (cuType,))
-
-        # Only handle Depth: 0
-        depth = request.headers.getHeader("depth", "0")
-        if depth != "0":
-            log.err("Error in prinicpal-property-search REPORT, Depth set to %s" % (depth,))
-            raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Depth %s not allowed" % (depth,)))
-
-        # Get a single DAV:prop element from the REPORT request body
-        propertiesForResource = None
-        propElement = None
-        propertySearches = []
-        applyTo = False
-        for child in principal_property_search.children:
-            if child.qname() == (dav_namespace, "prop"):
-                propertiesForResource = prop_common.propertyListForResource
-                propElement = child
-            elif child.qname() == (dav_namespace,
-                "apply-to-principal-collection-set"):
-                applyTo = True
-            elif child.qname() == (dav_namespace, "property-search"):
-                props = child.childOfType(davxml.PropertyContainer)
-                props.removeWhitespaceNodes()
-
-                match = child.childOfType(davxml.Match)
-                caseless = match.attributes.get("caseless", "yes")
-                if caseless not in ("yes", "no"):
-                    raise ValueError("Unknown value for caseless attribute: %s"
-                        % (caseless,))
-                caseless = True if caseless == "yes" else False
-                matchType = match.attributes.get("match-type", "contains")
-                if matchType not in ("starts-with", "contains"):
-                    raise ValueError("Unknown value for match-type attribute: %s" %
-                        (matchType,))
-
-                propertySearches.append((props.children, str(match),
-                    caseless, matchType))
-
-        # Run report
-        try:
-
-            resources = []
-            if applyTo or not hasattr(self, "directory"):
-                for principalCollection in self.principalCollections():
-                    uri = principalCollection.principalCollectionURL()
-                    resource = waitForDeferred(request.locateResource(uri))
-                    yield resource
-                    resource = resource.getResult()
-                    if resource:
-                        resources.append((resource, uri))
-            else:
-                resources.append((self, request.uri))
-
-            # We need to access a directory service
-            principalCollection = resources[0][0]
-            dir = principalCollection.directory
-
-            # See if we can take advantage of the directory
-            fields = []
-            nonDirectorySearches = []
-            for props, match, caseless, matchType in propertySearches:
-                nonDirectoryProps = []
-                for prop in props:
-                    fieldName, match = principalCollection.propertyToField(
-                        prop, match)
-                    if fieldName:
-                        fields.append((fieldName, match, caseless, matchType))
-                    else:
-                        nonDirectoryProps.append(prop)
-                if nonDirectoryProps:
-                    nonDirectorySearches.append((nonDirectoryProps, match,
-                        caseless, matchType))
-
-            matchingResources = []
-            matchcount = 0
-
-            # nonDirectorySearches are ignored
-
-            if fields:
-
-                for record in dir.recordsMatchingFieldsWithCUType(fields,
-                    operand=operand, cuType=cuType):
-
-                    resource = principalCollection.principalForRecord(record)
-
-                    # We've determined this is a matching resource
-                    matchcount += 1
-                    if matchcount > max_number_of_matches:
-                        raise NumberOfMatchesWithinLimits
-                    matchingResources.append(resource)
-
-            # Generate the response
-            responses = []
-            for resource in matchingResources:
-                url = resource.url()
-                d = waitForDeferred(prop_common.responseForHref(
-                    request,
-                    responses,
-                    davxml.HRef.fromString(url),
-                    resource,
-                    propertiesForResource,
-                    propElement
-                ))
-                yield d
-                d.getResult()
-
-
-        except NumberOfMatchesWithinLimits:
-            log.err("Too many matching components in prinicpal-property-search report")
-            raise HTTPError(ErrorResponse(
-                responsecode.FORBIDDEN,
-                (dav_namespace, "number-of-matches-within-limits")
-            ))
-
-        yield MultiStatusResponse(responses)
-
-    report_DAV__principal_property_search = deferredGenerator(report_DAV__principal_property_search)

Modified: CalendarServer/trunk/twistedcaldav/static.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/static.py	2008-10-10 17:34:50 UTC (rev 3138)
+++ CalendarServer/trunk/twistedcaldav/static.py	2008-10-10 19:04:18 UTC (rev 3139)
@@ -490,7 +490,7 @@
 
         return True
 
-class CalendarHomeProvisioningFile (DirectoryPrincipalPropertySearchMixIn, AutoProvisioningFileMixIn, DirectoryCalendarHomeProvisioningResource, DAVFile):
+class CalendarHomeProvisioningFile (AutoProvisioningFileMixIn, DirectoryCalendarHomeProvisioningResource, DAVFile):
     """
     Resource which provisions calendar home collections as needed.
     """
@@ -512,7 +512,7 @@
     def createSimilarFile(self, path):
         raise HTTPError(responsecode.NOT_FOUND)
 
-class CalendarHomeTypeProvisioningFile (DirectoryPrincipalPropertySearchMixIn, AutoProvisioningFileMixIn, DirectoryCalendarHomeTypeProvisioningResource, DAVFile):
+class CalendarHomeTypeProvisioningFile (AutoProvisioningFileMixIn, DirectoryCalendarHomeTypeProvisioningResource, DAVFile):
     def __init__(self, path, parent, recordType):
         """
         @param path: the path to the file which will back the resource.
@@ -601,7 +601,7 @@
     def createSimilarFile(self, path):
         raise HTTPError(responsecode.NOT_FOUND)
 
-class CalendarHomeFile (DirectoryPrincipalPropertySearchMixIn, PropfindCacheMixin, AutoProvisioningFileMixIn, DirectoryCalendarHomeResource, CalDAVFile):
+class CalendarHomeFile (PropfindCacheMixin, AutoProvisioningFileMixIn, DirectoryCalendarHomeResource, CalDAVFile):
     """
     Calendar home collection resource.
     """
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20081010/d901e283/attachment-0001.html 


More information about the calendarserver-changes mailing list