# HG changeset patch # User Ralph Meijer # Date 1098808184 0 # Node ID fa866793075d279178254d4d53f2f08cdd375db2 # Parent ff7c73b253bf427df800b07c65f869930775add3 Split up implementation in several Services that match the division in the backend interfaces. Add appropriate adapter calls. diff -r ff7c73b253bf -r fa866793075d idavoll/pubsub.py --- a/idavoll/pubsub.py Tue Oct 26 16:28:07 2004 +0000 +++ b/idavoll/pubsub.py Tue Oct 26 16:29:44 2004 +0000 @@ -25,194 +25,228 @@ PUBSUB_CONFIGURE_SET = PUBSUB_SET + '/configure' class PubSubError(Exception): - pubsub_error = None - msg = '' + pubsub_error = None + msg = '' class NotImplemented(PubSubError): - pass + pass class OptionsUnavailable(PubSubError): - pubsub_error = 'subscription-options-unavailable' + pubsub_error = 'subscription-options-unavailable' class SubscriptionOptionsUnavailable(PubSubError): - pubsub_error = 'subscription-options-unavailable' + pubsub_error = 'subscription-options-unavailable' class NodeNotConfigurable(PubSubError): - pubsub_error = 'node-not-configurable' + pubsub_error = 'node-not-configurable' class CreateNodeNotConfigurable(PubSubError): - pubsub_error = 'node-not-configurable' + pubsub_error = 'node-not-configurable' error_map = { - backend.NotAuthorized: 'not-authorized', - backend.NodeNotFound: 'item-not-found', - backend.NoPayloadAllowed: 'bad-request', - backend.PayloadExpected: 'bad-request', - backend.NoInstantNodes: 'not-acceptable', - backend.NodeExists: 'conflict', - NotImplemented: 'feature-not-implemented', - OptionsUnavailable: 'feature-not-implemented', - SubscriptionOptionsUnavailable: 'not-acceptable', - NodeNotConfigurable: 'feature-not-implemented', - CreateNodeNotConfigurable: 'not-acceptable', + backend.NotAuthorized: 'not-authorized', + backend.NodeNotFound: 'item-not-found', + backend.NoPayloadAllowed: 'bad-request', + backend.PayloadExpected: 'bad-request', + backend.NoInstantNodes: 'not-acceptable', + backend.NodeExists: 'conflict', + backend.NotImplemented: 'feature-not-implemented', + NotImplemented: 'feature-not-implemented', + OptionsUnavailable: 'feature-not-implemented', + SubscriptionOptionsUnavailable: 'not-acceptable', + NodeNotConfigurable: 'feature-not-implemented', + CreateNodeNotConfigurable: 'not-acceptable', } -class ComponentServiceFromBackend(component.Service): +class Service(component.Service): + + __implements__ = component.IService - def __init__(self, backend): - self.backend = backend - self.backend.pubsub_service = self - - def componentConnected(self, xmlstream): - xmlstream.addObserver(PUBSUB_SET, self.onPubSub) - xmlstream.addObserver(PUBSUB_GET, self.onPubSub) + def __init__(self, backend): + self.backend = backend + + def componentConnected(self, xmlstream): + pass - def getIdentities(self, node): - results = [] - if not node: - results.append({ - 'category': 'pubsub', - 'type': 'generic', - 'name': 'Generic Pubsub Service' - }) - return results + def error(self, failure, iq): + try: + r = failure.trap(*error_map.keys()) + xmpp_error.error_from_iq(iq, error_map[r], failure.value.msg) + if isinstance(failure.value, PubSubError) and \ + failure.value.pubsub_error is not None: + iq.error.addElement((NS_PUBSUB_ERRORS, + failure.value.pubsub_error), + NS_PUBSUB_ERRORS) + return iq + except: + xmpp_error.error_from_iq(iq, 'internal-server-error') + self.send(iq) + raise + + def success(self, result, iq): + iq.swapAttributeValues("to", "from") + iq["type"] = 'result' + iq.children = result or [] + return iq - def getFeatures(self, node): - return [ - "http://jabber.org/protocol/pubsub#outcast-affil", - "http://jabber.org/protocol/pubsub#publisher-affil", - "http://jabber.org/protocol/pubsub#persistent-items", - ] + def handler_wrapper(self, handler, iq): + try: + d = handler(iq) + except: + d = defer.fail() + + d.addCallback(self.success, iq) + d.addErrback(self.error, iq) + d.addCallback(self.send) + iq.handled = True + +class ComponentServiceFromService(Service): - def error(self, failure, iq): - try: - r = failure.trap(*error_map.keys()) - xmpp_error.error_from_iq(iq, error_map[r], failure.value.msg) - if isinstance(failure.value, PubSubError) and \ - failure.value.pubsub_error is not None: - iq.error.addElement((NS_PUBSUB_ERRORS, - failure.value.pubsub_error), - NS_PUBSUB_ERRORS) - return iq - except: - xmpp_error.error_from_iq(iq, 'internal-server-error') - self.send(iq) - raise - - def success(self, result, iq): - iq.swapAttributeValues("to", "from") - iq["type"] = 'result' - iq.children = result or [] - return iq + def getIdentities(self, node): + results = [] + if not node: + results.append({ + 'category': 'pubsub', + 'type': 'generic', + 'name': 'Generic Pubsub Service' + }) + return results + + def getFeatures(self, node): + features = [] + + affiliations = self.backend.get_supported_affiliations() + if 'outcast' in affiliations: + features.append("http://jabber.org/protocol/pubsub#outcast-affil") + + if 'publisher' in affiliations: + features.append("http://jabber.org/protocol/pubsub#publisher-affil") + + # "http://jabber.org/protocol/pubsub#persistent-items" + + return features + +components.registerAdapter(ComponentServiceFromService, backend.IBackendService, component.IService) - def onPubSub(self, iq): - for elem in iq.pubsub.elements(): - if not elem.hasAttribute('xmlns'): - action = elem.name - break +class ComponentServiceFromNotificationService(Service): - if not action: - return + def __init__(self, backend): + Service.__init__(self, backend) + self.backend.register_notifier(self.notify) + + def notify(self, object): + node_id = object["node_id"] + items = object["items"] + d = self.backend.get_notification_list(node_id, items) + d.addCallback(self._notify, node_id) - try: - try: - handler = getattr(self, 'on%s%s' % (action.capitalize(), - iq["type"].capitalize())) - except KeyError: - raise NotImplemented - else: - d = handler(iq) - except: - d = defer.fail() - - d.addCallback(self.success, iq) - d.addErrback(self.error, iq) - d.addCallback(self.send) - iq.handled = True + def _notify(self, list, node_id): + for recipient, items in list.items(): + self._notify_recipient(recipient, node_id, items) - # action handlers - - def onPublishSet(self, iq): - node = iq.pubsub.publish["node"] + def _notify_recipient(self, recipient, node_id, itemlist): + message = domish.Element((NS_COMPONENT, "message")) + message["from"] = self.parent.jabberId + message["to"] = recipient + event = message.addElement((NS_PUBSUB_EVENT, "event"), NS_PUBSUB_EVENT) + items = event.addElement("items") + items["node"] = node_id + items.children.extend(itemlist) + self.send(message) - items = [] - for child in iq.pubsub.publish.children: - if child.__class__ == domish.Element and child.name == 'item': - items.append(child) +components.registerAdapter(ComponentServiceFromNotificationService, backend.INotificationService, component.IService) + +class ComponentServiceFromPublishService(Service): - print items + def componentConnected(self, xmlstream): + xmlstream.addObserver(PUBSUB_PUBLISH, self.onPublish) + + def onPublish(self, iq): + self.handler_wrapper(self._onPublish, iq) - return self.backend.do_publish(node, - jid.JID(iq["from"]).userhost(), - items) + def _onPublish(self, iq): + node = iq.pubsub.publish["node"] - def onOptionsGet(self, iq): - raise OptionsUnavailable + items = [] + for child in iq.pubsub.publish.children: + if child.__class__ == domish.Element and child.name == 'item': + items.append(child) - def onOptionsSet(self, iq): - raise OptionsUnavailable + print items + + return self.backend.publish(node, items, + jid.JID(iq["from"]).userhostJID()) - def onConfigureGet(self, iq): - raise NodeNotConfigurable +components.registerAdapter(ComponentServiceFromPublishService, backend.IPublishService, component.IService) + +class ComponentServiceFromSubscriptionService(Service): - def onConfigureSet(self, iq): - raise NodeNotConfigurable + def componentConnected(self, xmlstream): + xmlstream.addObserver(PUBSUB_SUBSCRIBE, self.onSubscribe) + + def onSubscribe(self, iq): + self.handler_wrapper(self._onSubscribe, iq) - def onSubscribeSet(self, iq): - if iq.pubsub.options: - raise SubscribeOptionsUnavailable + def _onSubscribe(self, iq): + if iq.pubsub.options: + raise SubscribeOptionsUnavailable - node_id = iq.pubsub.subscribe["node"] - subscriber = jid.JID(iq.pubsub.subscribe["jid"]) - requestor = jid.JID(iq["from"]).userhostJID() - d = self.backend.do_subscribe(node_id, subscriber, requestor) - d.addCallback(self.return_subscription) - d.addCallback(self.succeed, iq) - d.addErrback(self.error, iq) - d.addCallback(self.send) + node_id = iq.pubsub.subscribe["node"] + subscriber = jid.JID(iq.pubsub.subscribe["jid"]) + requestor = jid.JID(iq["from"]).userhostJID() + d = self.backend.do_subscribe(node_id, subscriber, requestor) + d.addCallback(self.return_subscription) + d.addCallback(self.succeed, iq) + d.addErrback(self.error, iq) + d.addCallback(self.send) - def return_subscription(self, result): - reply = domish.Element("pubsub", NS_PUBSUB) - entity = reply.addElement("entity") - entity["node"] = result["node"] - entity["jid"] = result["jid"].full() - entity["affiliation"] = result["affiliation"] - entity["subscription"] = result["subscription"] - return reply + def _onConfigureGet(self, iq): + raise NodeNotConfigurable + + def _onConfigureSet(self, iq): + raise NodeNotConfigurable - def onCreateSet(self, iq): - if iq.pubsub.options: - raise CreateNodeNotConfigurable + def return_subscription(self, result): + reply = domish.Element("pubsub", NS_PUBSUB) + entity = reply.addElement("entity") + entity["node"] = result["node"] + entity["jid"] = result["jid"].full() + entity["affiliation"] = result["affiliation"] + entity["subscription"] = result["subscription"] + return reply - node = iq.pubsub.create["node"] - owner = jid.JID(iq["from"]).userhostJID() +components.registerAdapter(ComponentServiceFromSubscriptionService, backend.ISubscriptionService, component.IService) + +class ComponentServiceFromNodeCreationService(Service): - d = self.backend.create_node(node, owner) - d.addCallback(self.return_create_response, iq) - return d + def componentConnected(self, xmlstream): + xmlstream.addObserver(PUBSUB_CREATE, self.onCreate) + + def onCreate(self, iq): + self.handler_wrapper(self._onCreate, iq) - def return_create_response(self, result, iq): - if iq.pubsub.create["node"] is None: - reply = domish.Element('pubsub', NS_PUBSUB) - entity = reply.addElement('create') - entity['node'] = result['node_id'] - return reply + def _onCreate(self, iq): + if iq.pubsub.options: + raise CreateNodeNotConfigurable - # other methods + node = iq.pubsub.create["node"] + owner = jid.JID(iq["from"]).userhostJID() - def do_notification(self, list, node): - for recipient, items in list.items(): - self.notify(node, items, recipient) + d = self.backend.create_node(node, owner) + d.addCallback(self.return_create_response, iq) + return d - def notify(self, node, itemlist, recipient): - message = domish.Element((NS_COMPONENT, "message")) - message["from"] = self.parent.jabberId - message["to"] = recipient - event = message.addElement((NS_PUBSUB_EVENT, "event"), NS_PUBSUB_EVENT) - items = event.addElement("items") - items["node"] = node - items.children.extend(itemlist) - self.send(message) - -components.registerAdapter(ComponentServiceFromBackend, backend.IService, component.IService) + def _onOptionsGet(self, iq): + raise OptionsUnavailable + + def _onOptionsSet(self, iq): + raise OptionsUnavailable + def return_create_response(self, result, iq): + if iq.pubsub.create["node"] is None: + reply = domish.Element('pubsub', NS_PUBSUB) + entity = reply.addElement('create') + entity['node'] = result['node_id'] + return reply + +components.registerAdapter(ComponentServiceFromNodeCreationService, backend.INodeCreationService, component.IService)