[CalendarServer-changes] [6823] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Fri Jan 28 14:44:05 PST 2011


Revision: 6823
          http://trac.macosforge.org/projects/calendarserver/changeset/6823
Author:   sagen at apple.com
Date:     2011-01-28 14:44:03 -0800 (Fri, 28 Jan 2011)
Log Message:
-----------
Adds home nodeName( ) method for retrieving pubsub node name (while also waiting for their creation)

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/tap/util.py
    CalendarServer/trunk/twistedcaldav/cache.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_livedirectory.py
    CalendarServer/trunk/twistedcaldav/notify.py
    CalendarServer/trunk/twistedcaldav/resource.py
    CalendarServer/trunk/txdav/caldav/datastore/test/common.py
    CalendarServer/trunk/txdav/common/datastore/file.py
    CalendarServer/trunk/txdav/common/datastore/sql.py
    CalendarServer/trunk/txdav/common/datastore/test/util.py
    CalendarServer/trunk/txdav/idav.py

Modified: CalendarServer/trunk/calendarserver/tap/util.py
===================================================================
--- CalendarServer/trunk/calendarserver/tap/util.py	2011-01-28 22:28:21 UTC (rev 6822)
+++ CalendarServer/trunk/calendarserver/tap/util.py	2011-01-28 22:44:03 UTC (rev 6823)
@@ -53,7 +53,7 @@
 from twistedcaldav.directory.principal import DirectoryPrincipalProvisioningResource
 from twistedcaldav.directory.sudo import SudoDirectoryService
 from twistedcaldav.directory.wiki import WikiDirectoryService
-from twistedcaldav.notify import NotifierFactory
+from twistedcaldav.notify import NotifierFactory, getPubSubConfiguration
 from twistedcaldav.directorybackedaddressbook import DirectoryBackedAddressBookResource
 from twistedcaldav.resource import CalDAVResource, AuthenticationWrapper
 from twistedcaldav.schedule import IScheduleInboxResource
@@ -172,6 +172,7 @@
         notifierFactory = NotifierFactory(
             config.Notifications.InternalNotificationHost,
             config.Notifications.InternalNotificationPort,
+            pubSubConfig=getPubSubConfiguration(config)
         )
     else:
         notifierFactory = None

Modified: CalendarServer/trunk/twistedcaldav/cache.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/cache.py	2011-01-28 22:28:21 UTC (rev 6822)
+++ CalendarServer/trunk/twistedcaldav/cache.py	2011-01-28 22:44:03 UTC (rev 6823)
@@ -436,3 +436,6 @@
 
     def getID(self, label="default"):
         return None
+
+    def nodeName(self, label="default"):
+        return succeed(None)

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_livedirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_livedirectory.py	2011-01-28 22:28:21 UTC (rev 6822)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_livedirectory.py	2011-01-28 22:44:03 UTC (rev 6823)
@@ -182,6 +182,8 @@
     if runODTests:
 
         from twistedcaldav.directory.appleopendirectory import OpenDirectoryService
+        print "Running live OD tests"
+
         class LiveODDirectoryServiceCase(LiveDirectoryTests, TestCase):
 
             def setUp(self):

Modified: CalendarServer/trunk/twistedcaldav/notify.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/notify.py	2011-01-28 22:28:21 UTC (rev 6822)
+++ CalendarServer/trunk/twistedcaldav/notify.py	2011-01-28 22:44:03 UTC (rev 6823)
@@ -39,7 +39,7 @@
 
 from twisted.internet.protocol import ReconnectingClientFactory, ServerFactory
 from twisted.internet.ssl import ClientContextFactory
-from twisted.internet.defer import inlineCallbacks, Deferred
+from twisted.internet.defer import inlineCallbacks, Deferred, returnValue
 from twisted.protocols.basic import LineReceiver
 from twisted.plugin import IPlugin
 from twisted.application import internet, service
@@ -142,6 +142,21 @@
         else:
             return "%s|%s" % (self._prefix, id)
 
+    @inlineCallbacks
+    def nodeName(self, label="default"):
+        id = self.getID(label=label)
+        pubSubConfig = self._notifierFactory.pubSubConfig
+        name = getPubSubPath(id, pubSubConfig)
+        try:
+            if self._notifierFactory.nodeCacher:
+                nodeCacher = self._notifierFactory.nodeCacher
+            else:
+                nodeCacher = getNodeCacher()
+            (yield nodeCacher.waitForNode(self, name))
+        except NodeCreationException, e:
+            self.log_warn(e)
+            returnValue(None)
+        returnValue(name)
 
 class NotificationClientLineProtocol(LineReceiver, LoggingMixIn):
     """
@@ -205,10 +220,16 @@
     gateway.
     """
 
-    def __init__(self, host, port, reactor=None):
+    def __init__(self, gatewayHost, gatewayPort, pubSubConfig=None,
+        nodeCacher=None, reactor=None):
+
         self.factory = None
-        self.host = host
-        self.port = port
+
+        self.gatewayHost = gatewayHost
+        self.gatewayPort = gatewayPort
+        self.pubSubConfig = pubSubConfig
+        self.nodeCacher = nodeCacher
+
         self.observers = set()
         self.queued = set()
 
@@ -219,7 +240,8 @@
     def send(self, op, id):
         if self.factory is None:
             self.factory = NotificationClientFactory(self)
-            self.reactor.connectTCP(self.host, self.port, self.factory)
+            self.reactor.connectTCP(self.gatewayHost, self.gatewayPort,
+                self.factory)
             self.log_debug("Creating factory")
 
         msg = "%s %s" % (op, str(id))

Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py	2011-01-28 22:28:21 UTC (rev 6822)
+++ CalendarServer/trunk/twistedcaldav/resource.py	2011-01-28 22:44:03 UTC (rev 6823)
@@ -536,10 +536,8 @@
                     dataObject = getattr(self, "_newStoreObject")
                 if dataObject:
                     label = "collection" if isvirt else "default"
-                    notifierID = dataObject.notifierID(label=label)
-                    if notifierID is not None and config.Notifications.Services.XMPPNotifier.Enabled:
-                        pubSubConfiguration = getPubSubConfiguration(config)
-                        nodeName = getPubSubPath(notifierID, pubSubConfiguration)
+                    nodeName = (yield dataObject.nodeName(label=label))
+                    if nodeName:
                         propVal = customxml.PubSubXMPPPushKeyProperty(nodeName)
                         returnValue(propVal)
 
@@ -2220,87 +2218,71 @@
             returnValue(customxml.MaxCollections.fromString(config.MaxCollectionsPerHome))
             
         elif qname == (customxml.calendarserver_namespace, "push-transports"):
-            notifierID = self._newStoreHome.notifierID()
-            if notifierID is not None and config.Notifications.Services.XMPPNotifier.Enabled:
-                children = []
+            if config.Notifications.Services.XMPPNotifier.Enabled:
+                nodeName = (yield self._newStoreHome.nodeName())
+                if nodeName:
+                    notifierID = self._newStoreHome.notifierID()
+                    if notifierID:
+                        children = []
 
-                apsConfiguration = getPubSubAPSConfiguration(notifierID, config)
-                if apsConfiguration:
-                    children.append(
-                        customxml.PubSubTransportProperty(
-                            customxml.PubSubSubscriptionProperty(
-                                davxml.HRef(
-                                    apsConfiguration["SubscriptionURL"]
-                                ),
-                            ),
-                            customxml.PubSubAPSBundleIDProperty(
-                                apsConfiguration["APSBundleID"]
-                            ),
-                            type="APSD",
-                        )
-                    )
+                        apsConfiguration = getPubSubAPSConfiguration(notifierID, config)
+                        if apsConfiguration:
+                            children.append(
+                                customxml.PubSubTransportProperty(
+                                    customxml.PubSubSubscriptionProperty(
+                                        davxml.HRef(
+                                            apsConfiguration["SubscriptionURL"]
+                                        ),
+                                    ),
+                                    customxml.PubSubAPSBundleIDProperty(
+                                        apsConfiguration["APSBundleID"]
+                                    ),
+                                    type="APSD",
+                                )
+                            )
 
-                pubSubConfiguration = getPubSubConfiguration(config)
-                if pubSubConfiguration['xmpp-server']:
-                    children.append(
-                        customxml.PubSubTransportProperty(
-                            customxml.PubSubXMPPServerProperty(
-                                pubSubConfiguration['xmpp-server']
-                            ),
-                            customxml.PubSubXMPPURIProperty(
-                                getPubSubXMPPURI(notifierID, pubSubConfiguration)
-                            ),
-                            type="XMPP",
-                        )
-                    )
+                        pubSubConfiguration = getPubSubConfiguration(config)
+                        if pubSubConfiguration['xmpp-server']:
+                            children.append(
+                                customxml.PubSubTransportProperty(
+                                    customxml.PubSubXMPPServerProperty(
+                                        pubSubConfiguration['xmpp-server']
+                                    ),
+                                    customxml.PubSubXMPPURIProperty(
+                                        getPubSubXMPPURI(notifierID, pubSubConfiguration)
+                                    ),
+                                    type="XMPP",
+                                )
+                            )
 
-                returnValue(customxml.PubSubPushTransportsProperty(*children))
+                        returnValue(customxml.PubSubPushTransportsProperty(*children))
 
 
-            else:
-                returnValue(customxml.PubSubPushTransportsProperty())
+            returnValue(customxml.PubSubPushTransportsProperty())
 
         elif qname == (customxml.calendarserver_namespace, "pushkey"):
-            notifierID = self._newStoreHome.notifierID()
-            if notifierID is not None and config.Notifications.Services.XMPPNotifier.Enabled:
-                pubSubConfiguration = getPubSubConfiguration(config)
-                nodeName = getPubSubPath(notifierID, pubSubConfiguration)
+            if config.Notifications.Services.XMPPNotifier.Enabled:
+                nodeName = (yield self._newStoreHome.nodeName())
+                if nodeName:
+                    returnValue(customxml.PubSubXMPPPushKeyProperty(nodeName))
+            returnValue(customxml.PubSubXMPPPushKeyProperty())
 
-                # Create the pubsub node so client has something to subscribe
-                # to
-                try:
-                    (yield getNodeCacher().waitForNode(
-                        self._newStoreHome._notifier, nodeName))
-                except NodeCreationException, e:
-                    self.log_warn(e)
 
-                returnValue(customxml.PubSubXMPPPushKeyProperty(nodeName))
-            else:
-                returnValue(customxml.PubSubXMPPPushKeyProperty())
-
-
         elif qname == (customxml.calendarserver_namespace, "xmpp-uri"):
-            notifierID = self._newStoreHome.notifierID()
-            if notifierID is not None and config.Notifications.Services.XMPPNotifier.Enabled:
-                pubSubConfiguration = getPubSubConfiguration(config)
+            if config.Notifications.Services.XMPPNotifier.Enabled:
+                nodeName = (yield self._newStoreHome.nodeName())
+                if nodeName:
+                    notifierID = self._newStoreHome.notifierID()
+                    if notifierID:
+                        pubSubConfiguration = getPubSubConfiguration(config)
+                        returnValue(customxml.PubSubXMPPURIProperty(
+                            getPubSubXMPPURI(notifierID, pubSubConfiguration)))
 
-                # Create the pubsub node so client has something to subscribe
-                # to
-                nodeName = getPubSubPath(notifierID, pubSubConfiguration)
-                try:
-                    (yield getNodeCacher().waitForNode(
-                        self._newStoreHome._notifier, nodeName))
-                except NodeCreationException, e:
-                    self.log_warn(e)
+            returnValue(customxml.PubSubXMPPURIProperty())
 
-                returnValue(customxml.PubSubXMPPURIProperty(
-                    getPubSubXMPPURI(notifierID, pubSubConfiguration)))
-            else:
-                returnValue(customxml.PubSubXMPPURIProperty())
-
         elif qname == (customxml.calendarserver_namespace, "xmpp-heartbeat-uri"):
-            pubSubConfiguration = getPubSubConfiguration(config)
-            if pubSubConfiguration['enabled']:
+            if config.Notifications.Services.XMPPNotifier.Enabled:
+                pubSubConfiguration = getPubSubConfiguration(config)
                 returnValue(
                     customxml.PubSubHeartbeatProperty(
                         customxml.PubSubHeartbeatURIProperty(
@@ -2311,16 +2293,14 @@
                         )
                     )
                 )
-            else:
-                returnValue(customxml.PubSubHeartbeatURIProperty())
+            returnValue(customxml.PubSubHeartbeatURIProperty())
 
         elif qname == (customxml.calendarserver_namespace, "xmpp-server"):
-            pubSubConfiguration = getPubSubConfiguration(config)
-            if pubSubConfiguration['enabled']:
+            if config.Notifications.Services.XMPPNotifier.Enabled:
+                pubSubConfiguration = getPubSubConfiguration(config)
                 returnValue(customxml.PubSubXMPPServerProperty(
                     pubSubConfiguration['xmpp-server']))
-            else:
-                returnValue(customxml.PubSubXMPPServerProperty())
+            returnValue(customxml.PubSubXMPPServerProperty())
 
         returnValue((yield super(CommonHomeResource, self).readProperty(property, request)))
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2011-01-28 22:28:21 UTC (rev 6822)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2011-01-28 22:44:03 UTC (rev 6823)
@@ -405,8 +405,22 @@
         self.assertEquals(calendar.notifierID(), "CalDAV|home1")
         self.assertEquals(calendar.notifierID(label="collection"), "CalDAV|home1/calendar_1")
 
+    @inlineCallbacks
+    def test_nodeNameSuccess(self):
+        home = yield self.homeUnderTest()
+        name = yield home.nodeName()
+        self.assertEquals(name, "/CalDAV/example.com/home1/")
 
     @inlineCallbacks
+    def test_nodeNameFailure(self):
+        # The StubNodeCacher is set up to fail when the node name has the
+        # word "fail" in it, for testing the failure mode:
+        home = yield self.transactionUnderTest().calendarHomeWithUID("fail",
+            create=True)
+        name = yield home.nodeName()
+        self.assertEquals(name, None)
+
+    @inlineCallbacks
     def test_calendarHomeWithUID_exists(self):
         """
         Finding an existing calendar home by UID results in an object that

Modified: CalendarServer/trunk/txdav/common/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/file.py	2011-01-28 22:28:21 UTC (rev 6822)
+++ CalendarServer/trunk/txdav/common/datastore/file.py	2011-01-28 22:44:03 UTC (rev 6823)
@@ -526,6 +526,16 @@
         else:
             return None
 
+    @inlineCallbacks
+    def nodeName(self, label="default"):
+        if self._notifiers:
+            for notifier in self._notifiers:
+                name = (yield notifier.nodeName(label=label))
+                if name is not None:
+                    returnValue(name)
+        else:
+            returnValue(None)
+
     def notifyChanged(self):
         """
         Trigger a notification of a change
@@ -838,6 +848,16 @@
         else:
             return None
 
+    @inlineCallbacks
+    def nodeName(self, label="default"):
+        if self._notifiers:
+            for notifier in self._notifiers:
+                name = (yield notifier.nodeName(label=label))
+                if name is not None:
+                    returnValue(name)
+        else:
+            returnValue(None)
+
     def notifyChanged(self):
         """
         Trigger a notification of a change

Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py	2011-01-28 22:28:21 UTC (rev 6822)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py	2011-01-28 22:44:03 UTC (rev 6823)
@@ -770,6 +770,16 @@
         else:
             return None
 
+    @inlineCallbacks
+    def nodeName(self, label="default"):
+        if self._notifiers:
+            for notifier in self._notifiers:
+                name = (yield notifier.nodeName(label=label))
+                if name is not None:
+                    returnValue(name)
+        else:
+            returnValue(None)
+
     def notifyChanged(self):
         """
         Trigger a notification of a change
@@ -1566,6 +1576,16 @@
         else:
             return None
 
+    @inlineCallbacks
+    def nodeName(self, label="default"):
+        if self._notifiers:
+            for notifier in self._notifiers:
+                name = (yield notifier.nodeName(label=label))
+                if name is not None:
+                    returnValue(name)
+        else:
+            returnValue(None)
+
     def notifyChanged(self):
         """
         Trigger a notification of a change
@@ -2131,6 +2151,15 @@
         else:
             return None
 
+    @inlineCallbacks
+    def nodeName(self, label="default"):
+        if self._notifiers:
+            for notifier in self._notifiers:
+                name = (yield notifier.nodeName(label=label))
+                if name is not None:
+                    returnValue(name)
+        else:
+            returnValue(None)
 
     def notifyChanged(self):
         """

Modified: CalendarServer/trunk/txdav/common/datastore/test/util.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/test/util.py	2011-01-28 22:28:21 UTC (rev 6822)
+++ CalendarServer/trunk/txdav/common/datastore/test/util.py	2011-01-28 22:44:03 UTC (rev 6823)
@@ -28,7 +28,7 @@
 from twext.python.vcomponent import VComponent
 
 from twisted.internet import reactor
-from twisted.internet.defer import Deferred, inlineCallbacks
+from twisted.internet.defer import Deferred, inlineCallbacks, succeed
 from twisted.internet.task import deferLater
 from twisted.python import log
 from twisted.application.service import Service
@@ -39,7 +39,7 @@
 from txdav.common.icommondatastore import NoSuchHomeChildError
 from twext.enterprise.adbapi2 import ConnectionPool
 from twisted.internet.defer import returnValue
-from twistedcaldav.notify import Notifier
+from twistedcaldav.notify import Notifier, NodeCreationException
 
 
 def allInstancesOf(cls):
@@ -283,7 +283,15 @@
             return self.commit()
 
 
+class StubNodeCacher(object):
 
+    def waitForNode(self, notifier, nodeName):
+        if "fail" in nodeName:
+            raise NodeCreationException("Could not create node")
+        else:
+            return succeed(True)
+
+
 class StubNotifierFactory(object):
     """
     For testing push notifications without an XMPP server.
@@ -291,6 +299,13 @@
 
     def __init__(self):
         self.reset()
+        self.nodeCacher = StubNodeCacher()
+        self.pubSubConfig = {
+            "enabled" : True,
+            "service" : "pubsub.example.com",
+            "host" : "example.com",
+            "port" : "123",
+        }
 
     def newNotifier(self, label="default", id=None, prefix=None):
         return Notifier(self, label=label, id=id, prefix=prefix)

Modified: CalendarServer/trunk/txdav/idav.py
===================================================================
--- CalendarServer/trunk/txdav/idav.py	2011-01-28 22:28:21 UTC (rev 6822)
+++ CalendarServer/trunk/txdav/idav.py	2011-01-28 22:44:03 UTC (rev 6823)
@@ -236,3 +236,25 @@
 
         @return: a string (or None if notifications are disabled)
         """
+
+    def nodeName(label):
+        """
+        Returns a pubsub node path.
+
+        A pubsub node path is comprised of the following values:
+
+        /<protocol>/<hostname>/<notifierID>/
+
+        <protocol> is either CalDAV or CardDAV
+        <hostname> is the name of the calendar server
+        <notifierID> is a unique string representing the resource
+
+        This method builds this string based on pubsub configuration
+        that was passed to the NotifierFactory, and it also attempts
+        to create and configure the node in the pubsub server.  If that
+        fails, a value of None will be returned. This is used when a client
+        requests push-related DAV properties.
+
+        @return: a deferred to a string (or None if notifications are disabled
+        or the node could not be created)
+        """
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110128/ea0db73d/attachment-0001.html>


More information about the calendarserver-changes mailing list