# HG changeset patch # User Ralph Meijer # Date 1097164625 0 # Node ID 88426868722929345ced1d9a9c4d9fca99453ee9 # Parent 9b610962d0459789f451fd33f88a051af982b438 Simplify call chain by mapping incoming requests directly to method calls in pubsub.py, and providing a exception handler for all backend calls. diff -r 9b610962d045 -r 884268687229 idavoll/backend.py --- a/idavoll/backend.py Wed Oct 06 21:07:37 2004 +0000 +++ b/idavoll/backend.py Thu Oct 07 15:57:05 2004 +0000 @@ -72,82 +72,75 @@ def do_publish(self, node_id, publisher, items): try: - try: - node = self.nodes[node_id] - persist_items = node.configuration.persist_items - deliver_payloads = node.configuration.deliver_payloads - except KeyError: - raise NodeNotFound + node = self.nodes[node_id] + persist_items = node.configuration.persist_items + deliver_payloads = node.configuration.deliver_payloads + except KeyError: + raise NodeNotFound - try: - if node.affiliations[publisher] not in ['owner', 'publisher']: - raise NotAuthorized - except KeyError: - raise NotAuthorized() + try: + if node.affiliations[publisher] not in ['owner', 'publisher']: + raise NotAuthorized + except KeyError: + raise NotAuthorized() - if items and not persist_items and not deliver_payloads: - raise NoPayloadAllowed - elif not items and (persist_items or deliver_payloads): - raise PayloadExpected - - print "publish by %s to %s" % (publisher, node_id) + if items and not persist_items and not deliver_payloads: + raise NoPayloadAllowed + elif not items and (persist_items or deliver_payloads): + raise PayloadExpected - if persist_items or deliver_payloads: - for item in items: - if item["id"] is None: - item["id"] = 'random' # FIXME + print "publish by %s to %s" % (publisher, node_id) - if persist_items: - self.storeItems(node_id, publisher, items) + if persist_items or deliver_payloads: + for item in items: + if item["id"] is None: + item["id"] = 'random' # FIXME + + if persist_items: + self.storeItems(node_id, publisher, items) - if items and not deliver_payloads: - for item in items: - item.children = [] + if items and not deliver_payloads: + for item in items: + item.children = [] - recipients = self.get_subscribers(node_id) - recipients.addCallback(self.magic_filter, node_id, items) - recipients.addCallback(self.pubsub_service.do_notification, node_id) + recipients = self.get_subscribers(node_id) + recipients.addCallback(self.magic_filter, node_id, items) + recipients.addCallback(self.pubsub_service.do_notification, node_id) - return defer.succeed(None) - except: - return defer.fail(failure.Failure()) + return defer.succeed(None) def do_subscribe(self, node_id, subscriber, requestor): # expect subscriber and requestor to be a jid.JID try: - try: - node = self.nodes[node_id] - except KeyError: - raise NodeNotFound + node = self.nodes[node_id] + except KeyError: + raise NodeNotFound - affiliation = node.affiliations.get(requestor.full(), 'none') + affiliation = node.affiliations.get(requestor.full(), 'none') - if affiliation == 'banned': - raise NotAuthorized + if affiliation == 'banned': + raise NotAuthorized - print subscriber.full() - print subscriber.userhostJID().full() - print requestor.full() - - if subscriber.userhostJID() != requestor: - raise NotAuthorized + print subscriber.full() + print subscriber.userhostJID().full() + print requestor.full() - try: - subscription = node.subscriptions[subscriber.full()] - except KeyError: - subscription = Subscription('subscribed') - node.subscriptions[subscriber.full()] = subscription - - print node.subscriptions + if subscriber.userhostJID() != requestor: + raise NotAuthorized - return defer.succeed({ - 'affiliation': affiliation, - 'node': node_id, - 'jid': subscriber, - 'subscription': subscription.state}) - except: - return defer.fail(failure.Failure) + try: + subscription = node.subscriptions[subscriber.full()] + except KeyError: + subscription = Subscription('subscribed') + node.subscriptions[subscriber.full()] = subscription + print node.subscriptions + + return defer.succeed({ + 'affiliation': affiliation, + 'node': node_id, + 'jid': subscriber, + 'subscription': subscription.state}) def magic_filter(self, subscribers, node_id, items): list = {} @@ -159,14 +152,9 @@ def get_subscribers(self, node_id): d = defer.Deferred() try: - result = self.nodes[node_id].subscriptions.keys() + return defer.succeed(self.nodes[node_id].subscriptions.keys()) except: - f = failure.Failure() - reactor.callLater(0, d.errback, f) - else: - reactor.callLater(0, d.callback, result) - - return d + return defer.fail() def storeItems(self, node_id, publisher, items): for item in items: @@ -174,19 +162,17 @@ print self.nodes[node_id].items - def create_node(node_id, owner): + def create_node(self, node_id, owner): result = {} - try: - if not node_id: - raise NoInstantNodes + if not node_id: + raise NoInstantNodes - if node_id in self.nodes: - raise NodeExists - - self.nodes[node_id] = Node(node_id) - node.affiliations[owner.full()] = 'owner' - return defer.succeed({'node_id': node.id}) - except: - return defer.fail(failure.Failure) + if node_id in self.nodes: + raise NodeExists + + node = Node(node_id) + node.affiliations[owner.full()] = 'owner' + self.nodes[node_id] = node + return defer.succeed({'node_id': node.id}) diff -r 9b610962d045 -r 884268687229 idavoll/pubsub.py --- a/idavoll/pubsub.py Wed Oct 06 21:07:37 2004 +0000 +++ b/idavoll/pubsub.py Thu Oct 07 15:57:05 2004 +0000 @@ -1,6 +1,8 @@ from twisted.protocols.jabber import component,jid from twisted.xish import utility, domish from twisted.python import components +from twisted.internet import defer + import backend import xmpp_error @@ -22,6 +24,25 @@ PUBSUB_CONFIGURE_GET = PUBSUB_GET + '/configure' PUBSUB_CONFIGURE_SET = PUBSUB_SET + '/configure' +class PubSubError(Exception): + pubsub_error = None + msg = '' + +class NotImplemented(PubSubError): + pass + +class OptionsUnavailable(PubSubError): + pubsub_error = 'subscription-options-unavailable' + +class SubscriptionOptionsUnavailable(PubSubError): + pubsub_error = 'subscription-options-unavailable' + +class NodeNotConfigurable(PubSubError): + pubsub_error = 'node-not-configurable' + +class CreateNodeNotConfigurable(PubSubError): + pubsub_error = 'node-not-configurable' + error_map = { backend.NotAuthorized: 'not-authorized', backend.NodeNotFound: 'item-not-found', @@ -29,28 +50,19 @@ 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', } -class ComponentServiceFromBackend(component.Service, utility.EventDispatcher): +class ComponentServiceFromBackend(component.Service): def __init__(self, backend): - utility.EventDispatcher.__init__(self) self.backend = backend self.backend.pubsub_service = self - self.addObserver(PUBSUB_PUBLISH, self.onPublish) - - # make sure subscribe and create are handled before resp. options and - # configure - self.addObserver(PUBSUB_SUBSCRIBE, self.onSubscribe, 0) - self.addObserver(PUBSUB_OPTIONS_SET, self.onOptionsSet, 1) - self.addObserver(PUBSUB_CREATE, self.onSubscribe, 0) - self.addObserver(PUBSUB_CONFIGURE_SET, self.onConfigureSet, 1) - - self.addObserver(PUBSUB_OPTIONS_GET, self.onOptionsGet) - self.addObserver(PUBSUB_CONFIGURE_GET, self.onConfigureGet) - self.addObserver(PUBSUB_GET, self.notImplemented, -1) - self.addObserver(PUBSUB_SET, self.notImplemented, -1) - + def componentConnected(self, xmlstream): xmlstream.addObserver(PUBSUB_SET, self.onPubSub) xmlstream.addObserver(PUBSUB_GET, self.onPubSub) @@ -76,6 +88,11 @@ 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') @@ -88,14 +105,34 @@ iq.children = result or [] return iq - def notImplemented(self, iq): - self.send(xmpp_error.error_from_iq(iq, 'feature-not-implemented')) + def onPubSub(self, iq): + for elem in iq.pubsub.elements(): + if not elem.hasAttribute('xmlns'): + action = elem.name + break + + if not action: + return - def onPubSub(self, iq): - self.dispatch(iq) + 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 onPublish(self, iq): + # action handlers + + def onPublishSet(self, iq): node = iq.pubsub.publish["node"] items = [] @@ -105,45 +142,25 @@ print items - d = self.backend.do_publish(node, jid.JID(iq["from"]).userhost(), items) - d.addCallback(self.success, iq) - d.addErrback(self.error, iq) - d.addCallback(self.send) + return self.backend.do_publish(node, + jid.JID(iq["from"]).userhost(), + items) def onOptionsGet(self, iq): - xmpp_error.error_from_iq(iq, 'feature-not-implemented') - iq.error.addElement((NS_PUBSUB_ERRORS, 'subscription-options-unavailable'), NS_PUBSUB_ERRORS) - self.send(iq) + raise OptionsUnavailable def onOptionsSet(self, iq): - if iq.pubsub.subscribe: - # this should be handled by the subscribe handler - return - - xmpp_error.error_from_iq(iq, 'feature-not-implemented') - iq.error.addElement((NS_PUBSUB_ERRORS, 'subscription-options-unavailable'), NS_PUBSUB_ERRORS) - self.send(iq) + raise OptionsUnavailable def onConfigureGet(self, iq): - xmpp_error.error_from_iq(iq, 'feature-not-implemented') - iq.error.addElement((NS_PUBSUB_ERRORS, 'node-not-configurable'), NS_PUBSUB_ERRORS) - self.send(iq) + raise NodeNotConfigurable def onConfigureSet(self, iq): - if iq.pubsub.create: - # this should be handled by the create handler - return + raise NodeNotConfigurable - xmpp_error.error_from_iq(iq, 'feature-not-implemented') - iq.error.addElement((NS_PUBSUB_ERRORS, 'node-not-configurable'), NS_PUBSUB_ERRORS) - self.send(iq) - - def onSubscribe(self, iq): + def onSubscribeSet(self, iq): if iq.pubsub.options: - xmpp_error.error_from_iq(iq, 'not-acceptable') - iq.error.addElement((NS_PUBSUB_ERRORS, 'subscription-options-unavailable'), NS_PUBSUB_ERRORS) - self.send(iq) - return + raise SubscribeOptionsUnavailable node_id = iq.pubsub.subscribe["node"] subscriber = jid.JID(iq.pubsub.subscribe["jid"]) @@ -163,8 +180,27 @@ entity["subscription"] = result["subscription"] return reply + def onCreateSet(self, iq): + if iq.pubsub.options: + raise CreateNodeNotConfigurable + + node = iq.pubsub.create["node"] + owner = jid.JID(iq["from"]).userhostJID() + + d = self.backend.create_node(node, owner) + d.addCallback(self.return_create_response, iq) + return d + + 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 + + # other methods + def do_notification(self, list, node): - for recipient, items in list.items(): self.notify(node, items, recipient) @@ -178,31 +214,5 @@ items.children.extend(itemlist) self.send(message) - def onCreate(self, iq): - if iq.pubsub.options: - xmpp_error.error_from_iq(iq, 'not-acceptable') - iq.error.addElement((NS_PUBSUB_ERRORS, 'node-not-configurable'), NS_PUBSUB_ERRORS) - self.send(iq) - return - - node = iq.pubsub.create["node"] - owner = jid.JID(iq["from"]).userhostJID() - - try: - d = self.backend.create_node(node, owner) - d.addCallback(self.return_create_response, iq) - d.addCallback(self.succeed, iq) - d.addErrback(self.error, iq) - d.addCallback(self.send) - except: - pass - - 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(ComponentServiceFromBackend, backend.IBackendService, component.IService)