Author: mjakl
Date: Sun Jul 5 20:39:05 2009
New Revision: 791315
URL: http://svn.apache.org/viewvc?rev=791315&view=rev
Log:
Implemented the "delete node" use-case. Fixes VYSPER-57.
Modified:
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/AbstractPublishSubscribeIQHandler.java
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/AbstractPubSubGeneralHandler.java
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/owner/PubSubOwnerDeleteNodeHandler.java
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/model/CollectionNode.java
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/model/LeafNode.java
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionNodeStorageProvider.java
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionnodeInMemoryStorageProvider.java
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeInMemoryStorageProvider.java
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeStorageProvider.java
mina/sandbox/vysper/trunk/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/owner/PubSubDeleteNodeTestCase.java
Modified:
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/AbstractPublishSubscribeIQHandler.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/AbstractPublishSubscribeIQHandler.java?rev=791315&r1=791314&r2=791315&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/AbstractPublishSubscribeIQHandler.java
(original)
+++
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/AbstractPublishSubscribeIQHandler.java
Sun Jul 5 20:39:05 2009
@@ -22,6 +22,7 @@
import org.apache.vysper.compliance.SpecCompliant;
import org.apache.vysper.xmpp.addressing.Entity;
import org.apache.vysper.xmpp.modules.core.base.handler.DefaultIQHandler;
+import
org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.handler.ErrorStanzaGenerator;
import
org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.model.CollectionNode;
import org.apache.vysper.xmpp.server.SessionContext;
import org.apache.vysper.xmpp.stanza.IQStanza;
@@ -39,6 +40,8 @@
@SpecCompliant(spec="xep-0060", status=
SpecCompliant.ComplianceStatus.IN_PROGRESS, coverage =
SpecCompliant.ComplianceCoverage.UNSUPPORTED)
public abstract class AbstractPublishSubscribeIQHandler extends
DefaultIQHandler {
+ // one ErrorStanzaGenerator available for all subclasses
+ protected ErrorStanzaGenerator errorStanzaGenerator = null;
// the pubsub service itself is a collection node
protected CollectionNode root;
// we need to generate some IDs
@@ -52,6 +55,7 @@
public AbstractPublishSubscribeIQHandler(CollectionNode root) {
this.root = root;
this.idGenerator = new JVMBuiltinUUIDGenerator();
+ errorStanzaGenerator = new ErrorStanzaGenerator();
}
/**
@@ -116,4 +120,20 @@
}
return sender;
}
+
+ /**
+ * Extracts the node name from a given IQ stanza. The node attribute
+ * takes precedence over the JID resource. The standard requires only
+ * one of these addressing methods.
+ *
+ * @param stanza the received IQStanza
+ * @return the node
+ */
+ protected String extractNodeName(IQStanza stanza) {
+ String node =
stanza.getFirstInnerElement().getFirstInnerElement().getAttributeValue("node");
+ if(node == null) {
+ //throw Exception();
+ }
+ return node;
+ }
}
Modified:
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/AbstractPubSubGeneralHandler.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/AbstractPubSubGeneralHandler.java?rev=791315&r1=791314&r2=791315&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/AbstractPubSubGeneralHandler.java
(original)
+++
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/AbstractPubSubGeneralHandler.java
Sun Jul 5 20:39:05 2009
@@ -23,7 +23,6 @@
import
org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.AbstractPublishSubscribeIQHandler;
import
org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.model.CollectionNode;
import org.apache.vysper.xmpp.protocol.NamespaceURIs;
-import org.apache.vysper.xmpp.stanza.IQStanza;
/**
* This class is the superclass for all stanzas within the pubsub namespace.
@@ -33,15 +32,11 @@
@SpecCompliant(spec="xep-0060", status=
SpecCompliant.ComplianceStatus.IN_PROGRESS, coverage =
SpecCompliant.ComplianceCoverage.UNSUPPORTED)
public abstract class AbstractPubSubGeneralHandler extends
AbstractPublishSubscribeIQHandler {
- // one ErrorStanzaGenerator available for all subclasses
- protected ErrorStanzaGenerator errorStanzaGenerator = null;
-
/**
* @param root
*/
public AbstractPubSubGeneralHandler(CollectionNode root) {
super(root);
- errorStanzaGenerator = new ErrorStanzaGenerator();
}
/**
@@ -51,21 +46,4 @@
protected String getNamespace() {
return NamespaceURIs.XEP0060_PUBSUB;
}
-
- /**
- * Extracts the node name from a given IQ stanza. The node attribute
- * takes precedence over the JID resource. The standard requires only
- * one of these addressing methods.
- *
- * @param stanza the received IQStanza
- * @return the node
- */
- protected String extractNodeName(IQStanza stanza) {
- String node =
stanza.getFirstInnerElement().getFirstInnerElement().getAttributeValue("node");
- if(node == null) {
- //throw Exception();
- }
- return node;
- }
-
}
Modified:
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/owner/PubSubOwnerDeleteNodeHandler.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/owner/PubSubOwnerDeleteNodeHandler.java?rev=791315&r1=791314&r2=791315&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/owner/PubSubOwnerDeleteNodeHandler.java
(original)
+++
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/owner/PubSubOwnerDeleteNodeHandler.java
Sun Jul 5 20:39:05 2009
@@ -20,7 +20,19 @@
package org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.handler.owner;
import org.apache.vysper.compliance.SpecCompliant;
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.delivery.StanzaRelay;
import
org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.model.CollectionNode;
+import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.model.LeafNode;
+import org.apache.vysper.xmpp.server.ServerRuntimeContext;
+import org.apache.vysper.xmpp.server.SessionContext;
+import org.apache.vysper.xmpp.stanza.IQStanza;
+import org.apache.vysper.xmpp.stanza.IQStanzaType;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import org.apache.vysper.xmpp.xmlfragment.Attribute;
+import org.apache.vysper.xmpp.xmlfragment.XMLElement;
+import org.apache.vysper.xmpp.xmlfragment.XMLFragment;
/**
@@ -45,5 +57,61 @@
protected String getWorkerElement() {
return "delete";
}
+
+ /**
+ * This method takes care of handling the "delete" use-case including all
(relevant) error conditions.
+ *
+ * @return the appropriate response stanza (either success or some error
condition).
+ */
+ @Override
+ @SpecCompliant(spec="xep-0060", section="8.4", status=
SpecCompliant.ComplianceStatus.IN_PROGRESS, coverage =
SpecCompliant.ComplianceCoverage.UNSUPPORTED)
+ protected Stanza handleSet(IQStanza stanza,
+ ServerRuntimeContext serverRuntimeContext,
+ SessionContext sessionContext) {
+ Entity sender = getFromAddress(stanza, sessionContext);
+ Entity receiver = sessionContext.getServerJID();
+ String iqStanzaID = stanza.getAttributeValue("id");
+ StanzaBuilder sb = StanzaBuilder.createIQStanza(receiver, sender,
IQStanzaType.RESULT, iqStanzaID);
+ String nodeName = extractNodeName(stanza);
+ LeafNode node = root.find(nodeName);
+
+ if(node == null) {
+ return errorStanzaGenerator.generateNoNodeErrorStanza(sender,
receiver, stanza);
+ }
+
+ if(!node.isSubscribed(sender)) {
+ return
errorStanzaGenerator.generateInsufficientPrivilegesErrorStanza(sender,
receiver, stanza);
+ }
+
+ sendDeleteNotifications(serverRuntimeContext, sender, nodeName, node);
+ root.deleteNode(nodeName);
+
+ return new IQStanza(sb.getFinalStanza());
+ }
+
+ /**
+ * Creates and sends a notification for all subscribers that the node is
going to be deleted.
+ *
+ * @param serverRuntimeContext
+ * @param sender
+ * @param nodeName
+ * @param node
+ */
+ private void sendDeleteNotifications(ServerRuntimeContext
serverRuntimeContext, Entity sender, String nodeName,
+ LeafNode node) {
+ StanzaRelay relay = serverRuntimeContext.getStanzaRelay();
+ String strID = idGenerator.create();
+ XMLElement delete = createDeleteElement(nodeName);
+ node.publish(sender, relay, strID, delete);
+ }
+
+ /**
+ * Creates a XMLElement like this <delete node="nodeName"/>
+ * @param nodeName the value for the node attribute
+ * @return the XMLElement for inclusion in the delete notification.
+ */
+ private XMLElement createDeleteElement(String nodeName) {
+ return new XMLElement("delete", null, new Attribute[] {new
Attribute("node", nodeName)}, (XMLFragment[])null);
+ }
}
Modified:
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/model/CollectionNode.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/model/CollectionNode.java?rev=791315&r1=791314&r2=791315&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/model/CollectionNode.java
(original)
+++
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/model/CollectionNode.java
Sun Jul 5 20:39:05 2009
@@ -130,4 +130,12 @@
this.collectionNodeStorage.initialize();
this.leafNodeStorage.initialize();
}
+
+ /**
+ * Deletes a node.
+ * @param nodeName the node to delete
+ */
+ public void deleteNode(String nodeName) {
+ this.collectionNodeStorage.deleteNode(nodeName);
+ }
}
Modified:
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/model/LeafNode.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/model/LeafNode.java?rev=791315&r1=791314&r2=791315&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/model/LeafNode.java
(original)
+++
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/model/LeafNode.java
Sun Jul 5 20:39:05 2009
@@ -228,4 +228,8 @@
public void initialize() {
storage.initialize(this);
}
+
+ public void delete() {
+ this.storage.delete(this.name);
+ }
}
Modified:
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionNodeStorageProvider.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionNodeStorageProvider.java?rev=791315&r1=791314&r2=791315&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionNodeStorageProvider.java
(original)
+++
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionNodeStorageProvider.java
Sun Jul 5 20:39:05 2009
@@ -65,4 +65,10 @@
* Call to do some preliminary tasks after the module has been configured.
*/
public void initialize();
+
+ /**
+ * Delete the node with name nodeName.
+ * @param nodeName the name of the node to delete.
+ */
+ public void deleteNode(String nodeName);
}
Modified:
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionnodeInMemoryStorageProvider.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionnodeInMemoryStorageProvider.java?rev=791315&r1=791314&r2=791315&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionnodeInMemoryStorageProvider.java
(original)
+++
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionnodeInMemoryStorageProvider.java
Sun Jul 5 20:39:05 2009
@@ -80,4 +80,13 @@
public void initialize() {
// empty
}
+
+ /**
+ * Delete the node specified by nodeName.
+ */
+ public void deleteNode(String nodeName) {
+ LeafNode n = findNode(nodeName);
+ n.delete();
+ this.nodes.remove(nodeName);
+ }
}
Modified:
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeInMemoryStorageProvider.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeInMemoryStorageProvider.java?rev=791315&r1=791314&r2=791315&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeInMemoryStorageProvider.java
(original)
+++
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeInMemoryStorageProvider.java
Sun Jul 5 20:39:05 2009
@@ -145,6 +145,9 @@
// empty
}
+ /**
+ * Go through each message and call visit of the visitor.
+ */
public void acceptForEachItem(String nodeName, ItemVisitor iv) {
Map<String, PayloadItem> messages = nodeMessages.get(nodeName);
for(String itemID : messages.keySet()) {
@@ -152,8 +155,19 @@
}
}
+ /**
+ * Initialize the node with the storage.
+ */
public void initialize(LeafNode leafNode) {
nodeMessages.put(leafNode.getName(), new TreeMap<String,
PayloadItem>());
nodeSubscribers.put(leafNode.getName(), new TreeMap<String, Entity>());
}
+
+ /**
+ * Remove the specified node from the storage.
+ */
+ public void delete(String name) {
+ nodeMessages.remove(name);
+ nodeSubscribers.remove(name);
+ }
}
Modified:
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeStorageProvider.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeStorageProvider.java?rev=791315&r1=791314&r2=791315&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeStorageProvider.java
(original)
+++
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeStorageProvider.java
Sun Jul 5 20:39:05 2009
@@ -133,4 +133,9 @@
*/
public void initialize(LeafNode leafNode);
+ /**
+ * Remove the specified node from the storage.
+ */
+ public void delete(String name);
+
}
Modified:
mina/sandbox/vysper/trunk/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/owner/PubSubDeleteNodeTestCase.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/owner/PubSubDeleteNodeTestCase.java?rev=791315&r1=791314&r2=791315&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/owner/PubSubDeleteNodeTestCase.java
(original)
+++
mina/sandbox/vysper/trunk/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/handler/owner/PubSubDeleteNodeTestCase.java
Sun Jul 5 20:39:05 2009
@@ -19,13 +19,21 @@
*/
package org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.handler.owner;
+import java.util.List;
+
import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.addressing.EntityImpl;
import org.apache.vysper.xmpp.modules.core.base.handler.IQHandler;
import
org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.AbstractPublishSubscribeTestCase;
import
org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.handler.AbstractStanzaGenerator;
+import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.model.LeafNode;
import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.protocol.ResponseStanzaContainer;
+import org.apache.vysper.xmpp.stanza.IQStanza;
import org.apache.vysper.xmpp.stanza.IQStanzaType;
+import org.apache.vysper.xmpp.stanza.Stanza;
import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import org.apache.vysper.xmpp.xmlfragment.XMLElement;
/**
* @author The Apache MINA Project (http://mina.apache.org)
@@ -62,4 +70,82 @@
return new PubSubOwnerDeleteNodeHandler(root);
}
+ public void testDelete() throws Exception {
+ String testNode = "test";
+ LeafNode node = root.createNode(pubsubService, testNode);
+ node.subscribe("someid", client); // make the client subscriber
(=owner)
+ node.subscribe("otherid1", new EntityImpl("yoda", "starwars.com",
"spaceship"));
+ node.subscribe("otherid2", new EntityImpl("r2d2", "starwars.com",
"desert"));
+ node.subscribe("otherid3", new EntityImpl("anakin", "starwars.com",
"deathstar"));
+
+ assertNotNull(root.find(testNode));
+ // make sure we have 4 subscribers
+ assertEquals(4, node.countSubscriptions());
+
+ AbstractStanzaGenerator sg = getDefaultStanzaGenerator();
+ Stanza stanza = sg.getStanza(client, pubsubService, "id123", testNode);
+ ResponseStanzaContainer result = sendStanza(stanza, true);
+ assertTrue(result.hasResponse());
+ IQStanza response = new IQStanza(result.getResponseStanza());
+ assertEquals(IQStanzaType.RESULT.value(),response.getType());
+
+ assertEquals("id123", response.getAttributeValue("id")); // IDs must
match
+
+ LeafNode n = root.find(testNode);
+ assertNull(n);
+
+ // check that the subscribers got a notification
+ assertEquals(4, relay.getCountRelayed());
+ }
+
+ public void testDeleteNotAuth() throws Exception {
+ String testNode = "test";
+ root.createNode(pubsubService, testNode);
+
+ assertNotNull(root.find(testNode));
+
+ AbstractStanzaGenerator sg = getDefaultStanzaGenerator();
+ Stanza stanza = sg.getStanza(client, pubsubService, "id123", testNode);
+ ResponseStanzaContainer result = sendStanza(stanza, true);
+ assertTrue(result.hasResponse());
+ IQStanza response = new IQStanza(result.getResponseStanza());
+ assertEquals(IQStanzaType.ERROR.value(),response.getType());
+
+ assertEquals("id123", response.getAttributeValue("id")); // IDs must
match
+
+ XMLElement error = response.getInnerElementsNamed("error").get(0);
//jump directly to the error part
+ assertEquals("error", error.getName());
+ assertEquals("auth", error.getAttributeValue("type"));
+
+ List<XMLElement> errorContent = error.getInnerElements();
+ assertEquals(1, errorContent.size());
+ assertEquals("forbidden", errorContent.get(0).getName());
+ assertEquals(NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STANZAS,
errorContent.get(0).getNamespace());
+
+ LeafNode n = root.find(testNode);
+ assertNotNull(n); // still there
+ }
+
+ public void testDeleteNoSuchNode() throws Exception {
+ String testNode = "test";
+ assertNull(root.find(testNode));
+
+ AbstractStanzaGenerator sg = getDefaultStanzaGenerator();
+ Stanza stanza = sg.getStanza(client, pubsubService, "id123", testNode);
+ ResponseStanzaContainer result = sendStanza(stanza, true);
+ assertTrue(result.hasResponse());
+ IQStanza response = new IQStanza(result.getResponseStanza());
+ assertEquals(IQStanzaType.ERROR.value(),response.getType());
+
+ assertEquals("id123", response.getAttributeValue("id")); // IDs must
match
+
+ XMLElement error = response.getInnerElementsNamed("error").get(0);
//jump directly to the error part
+ assertEquals("error", error.getName());
+ assertEquals("cancel", error.getAttributeValue("type"));
+
+ List<XMLElement> errorContent = error.getInnerElements();
+ assertEquals(1, errorContent.size());
+ assertEquals("item-not-found", errorContent.get(0).getName());
+ assertEquals(NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STANZAS,
errorContent.get(0).getNamespace());
+ }
}