diff idavoll/pubsub.py @ 23:884268687229

Simplify call chain by mapping incoming requests directly to method calls in pubsub.py, and providing a exception handler for all backend calls.
author Ralph Meijer <ralphm@ik.nu>
date Thu, 07 Oct 2004 15:57:05 +0000
parents e01bbbfa8a46
children 256dcda26752
line wrap: on
line diff
--- 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)