[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