Author: ngn
Date: Fri Aug 21 15:13:50 2009
New Revision: 806592
URL: http://svn.apache.org/viewvc?rev=806592&view=rev
Log:
Implment changing nickname (VYSPER-111)
Added:
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCUserItem.java
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerChangeNickTestCase.java
Modified:
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandler.java
Modified:
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandler.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandler.java?rev=806592&r1=806591&r2=806592&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandler.java
(original)
+++
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandler.java
Fri Aug 21 15:13:50 2009
@@ -99,68 +99,91 @@
String type = stanza.getType();
if(type == null) {
- return enterRoom(stanza, roomJid, occupantJid, nick,
sessionContext);
+ return available(stanza, roomJid, occupantJid, nick,
sessionContext);
} else if(type.equals("unavailable")) {
- return exitRoom(stanza, roomJid, occupantJid, nick,
sessionContext);
+ return unavailable(stanza, roomJid, occupantJid, nick,
sessionContext);
} else {
throw new RuntimeException("Presence type not handled by MUC
module: " + type);
}
}
- private Stanza enterRoom(PresenceStanza stanza, Entity roomJid,
+ private Stanza available(PresenceStanza stanza, Entity roomJid,
Entity newOccupantJid, String nick, SessionContext sessionContext)
{
- logger.debug("{} has requested to enter room {}", newOccupantJid,
roomJid);
// TODO what to use for the room name?
Room room = conference.findOrCreateRoom(roomJid, roomJid.getNode());
if(room.isInRoom(nick)) {
- // user is already in room
+ // user with this nick is already in room
return createPresenceErrorStanza(roomJid, newOccupantJid,
stanza.getID(), "cancel", "conflict");
}
- // check password if password protected
- if(room.isRoomType(RoomType.PasswordProtected)) {
- // TODO room constructor for password
-
- String password = null;
- try {
- XMLElement xElement = stanza.getSingleInnerElementsNamed("x");
- if(xElement != null) {
- XMLElement passwordElement =
xElement.getSingleInnerElementsNamed("password");
- if(passwordElement != null) {
- password = passwordElement.getInnerText().getText();
+ if(room.isInRoom(newOccupantJid)) {
+ // user is already in room, change nick
+ logger.debug("{} has requested to change nick in room {}",
newOccupantJid, roomJid);
+
+ // occupant is already in room
+ Occupant occupant = room.findOccupantByJID(newOccupantJid);
+ if(nick.equals(occupant.getName())) {
+ // TODO nick unchanged, should we do anything here?
+ } else {
+ String oldNick = occupant.getName();
+ // update the nick
+ occupant.setName(nick);
+
+ // send out unavailable presences to all existing occupants
+ for(Occupant receiver : room.getOccupants()) {
+ sendChangeNickUnavailable(occupant, oldNick, receiver,
room, sessionContext);
+ }
+
+ // send out available presences to all existing occupants
+ for(Occupant receiver : room.getOccupants()) {
+ sendChangeNickAvailable(occupant, receiver, room,
sessionContext);
+ }
+
+ }
+ } else {
+ logger.debug("{} has requested to enter room {}", newOccupantJid,
roomJid);
+ // check password if password protected
+ if(room.isRoomType(RoomType.PasswordProtected)) {
+ String password = null;
+ try {
+ XMLElement xElement =
stanza.getSingleInnerElementsNamed("x");
+ if(xElement != null) {
+ XMLElement passwordElement =
xElement.getSingleInnerElementsNamed("password");
+ if(passwordElement != null) {
+ password =
passwordElement.getInnerText().getText();
+ }
}
+ } catch (XMLSemanticError e) {
+ password = null;
+ }
+
+ if(password == null || !password.equals(room.getPassword())) {
+ // password missing or not matching
+ return createPresenceErrorStanza(roomJid, newOccupantJid,
stanza.getID(), "auth", "not-authorized");
}
- } catch (XMLSemanticError e) {
- password = null;
}
- if(password == null || !password.equals(room.getPassword())) {
- // password missing or not matching
- return createPresenceErrorStanza(roomJid, newOccupantJid,
stanza.getID(), "auth", "not-authorized");
+ Occupant newOccupant = room.addOccupant(newOccupantJid, nick);
+
+ // relay presence of all existing room occupants to the now joined
occupant
+ for(Occupant occupant : room.getOccupants()) {
+ sendExistingOccupantToNewOccupant(newOccupant, occupant, room,
sessionContext);
}
+
+ // relay presence of the newly added occupant to all existing
occupants
+ for(Occupant occupant : room.getOccupants()) {
+ sendNewOccupantPresenceToExisting(newOccupant, occupant, room,
sessionContext);
+ }
+
+ logger.debug("{} successfully entered room {}", newOccupantJid,
roomJid);
}
-
- Occupant newOccupant = room.addOccupant(newOccupantJid, nick);
-
- // relay presence of all existing room occupants to the now joined
occupant
- for(Occupant occupant : room.getOccupants()) {
- sendExistingOccupantToNewOccupant(newOccupant, occupant, room,
sessionContext);
- }
-
- // relay presence of the newly added occupant to all existing occupants
- for(Occupant occupant : room.getOccupants()) {
- sendNewOccupantPresenceToExisting(newOccupant, occupant, room,
sessionContext);
- }
-
- logger.debug("{} successfully entered room {}", newOccupantJid,
roomJid);
-
return null;
- }
+ }
- private Stanza exitRoom(PresenceStanza stanza, Entity roomJid,
+ private Stanza unavailable(PresenceStanza stanza, Entity roomJid,
Entity occupantJid, String nick, SessionContext sessionContext) {
Room room = conference.findRoom(roomJid);
@@ -230,19 +253,11 @@
StanzaBuilder builder =
StanzaBuilder.createPresenceStanza(roomAndNewUserNick,
existingOccupant.getJid(), null, null, null, null);
builder.startInnerElement("x", NamespaceURIs.XEP0045_MUC_USER);
- builder.startInnerElement("item")
- .addAttribute("affiliation",
newOccupant.getAffiliation().toString())
- .addAttribute("role", newOccupant.getRole().toString());
- // section 7.1.5
- if(room.getRoomTypes().contains(RoomType.NonAnonymous) ||
- (room.getRoomTypes().contains(RoomType.SemiAnonymous) &&
existingOccupant.getRole() == Role.Moderator)) {
- // room is non-anonymous or semi-anonmoys and the occupant a
moderator, send full user JID
- builder.addAttribute("jid",
newOccupant.getJid().getFullQualifiedName());
- // TODO unit test for semi + moderator
- }
-
- builder.endInnerElement();
+ // room is non-anonymous or semi-anonmoys and the occupant a
moderator, send full user JID
+ boolean includeJid =
room.getRoomTypes().contains(RoomType.NonAnonymous) ||
+ (room.getRoomTypes().contains(RoomType.SemiAnonymous) &&
existingOccupant.getRole() == Role.Moderator);
+ new MUCUserItem(newOccupant).insertElement(builder, includeJid, false);
if(existingOccupant.getJid().equals(newOccupant.getJid())) {
@@ -259,6 +274,53 @@
logger.debug("Room presence from {} sent to {}", roomAndNewUserNick,
existingOccupant);
relayStanza(existingOccupant.getJid(), builder.getFinalStanza(),
sessionContext);
}
+
+ private void sendChangeNickUnavailable(Occupant changer, String oldNick,
Occupant receiver, Room room, SessionContext sessionContext) {
+ Entity roomAndOldNick = new EntityImpl(room.getJID(), oldNick);
+
+ StanzaBuilder builder =
StanzaBuilder.createPresenceStanza(roomAndOldNick, receiver.getJid(), null,
+ PresenceStanzaType.UNAVAILABLE, null, null);
+ builder.startInnerElement("x", NamespaceURIs.XEP0045_MUC_USER);
+
+
+ boolean includeJid = includeJidInItem(room, receiver);
+ new MUCUserItem(changer).insertElement(builder, includeJid, true);
+
+ builder.startInnerElement("status").addAttribute("code",
"330").endInnerElement();
+ if(receiver.getJid().equals(changer.getJid())) {
+ // send status to indicate that this is the users own presence
+ builder.startInnerElement("status").addAttribute("code",
"110").endInnerElement();
+ }
+ builder.endInnerElement();
+
+ logger.debug("Room presence from {} sent to {}", roomAndOldNick,
receiver);
+ relayStanza(receiver.getJid(), builder.getFinalStanza(),
sessionContext);
+ }
+
+
+ private boolean includeJidInItem(Room room, Occupant receiver) {
+ // room is non-anonymous or semi-anonmoys and the occupant a moderator,
send full user JID
+ return room.getRoomTypes().contains(RoomType.NonAnonymous) ||
+ (room.getRoomTypes().contains(RoomType.SemiAnonymous) &&
receiver.getRole() == Role.Moderator);
+ }
+ private void sendChangeNickAvailable(Occupant changer, Occupant receiver,
Room room, SessionContext sessionContext) {
+ Entity roomAndOldNick = new EntityImpl(room.getJID(),
changer.getName());
+
+ StanzaBuilder builder =
StanzaBuilder.createPresenceStanza(roomAndOldNick, receiver.getJid(), null,
null, null, null);
+ builder.startInnerElement("x", NamespaceURIs.XEP0045_MUC_USER);
+
+ boolean includeJid = includeJidInItem(room, receiver);
+ new MUCUserItem(changer).insertElement(builder, includeJid, false);
+
+ if(receiver.getJid().equals(changer.getJid())) {
+ // send status to indicate that this is the users own presence
+ builder.startInnerElement("status").addAttribute("code",
"110").endInnerElement();
+ }
+ builder.endInnerElement();
+
+ relayStanza(receiver.getJid(), builder.getFinalStanza(),
sessionContext);
+ }
+
private void sendExitRoomPresenceToExisting(Occupant exitingOccupant,
Occupant existingOccupant, Room room,
String statusMessage, SessionContext sessionContext) {
Added:
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCUserItem.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCUserItem.java?rev=806592&view=auto
==============================================================================
---
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCUserItem.java
(added)
+++
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCUserItem.java
Fri Aug 21 15:13:50 2009
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.vysper.xmpp.modules.extension.xep0045_muc.handler;
+
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Affiliation;
+import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Occupant;
+import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Role;
+import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+
+/**
+ *
+ * @author The Apache MINA Project ([email protected])
+ */
+public class MUCUserItem {
+
+ protected Entity jid; // optional
+ protected String nick; // optional
+ protected Affiliation affiliation; // optional
+ protected Role role; // optional
+
+ public MUCUserItem(Occupant occupant) {
+ this.jid = occupant.getJid();
+ this.nick = occupant.getName();
+ this.affiliation = occupant.getAffiliation();
+ this.role = occupant.getRole();
+ }
+
+
+ public MUCUserItem(Entity jid, String nick, Affiliation affiliation, Role
role) {
+ this.jid = jid;
+ this.nick = nick;
+ this.affiliation = affiliation;
+ this.role = role;
+ }
+
+ public Entity getJid() {
+ return jid;
+ }
+
+ public String getNick() {
+ return nick;
+ }
+
+ public Affiliation getAffiliation() {
+ return affiliation;
+ }
+
+ public Role getRole() {
+ return role;
+ }
+
+ public void insertElement(StanzaBuilder stanzaBuilder, boolean includeJid,
boolean includeNick) {
+ stanzaBuilder.startInnerElement("item");
+ if (includeJid && jid != null) stanzaBuilder.addAttribute("jid",
jid.getFullQualifiedName());
+ if (includeNick && nick != null)
stanzaBuilder.addAttribute("nick", nick);
+ if (affiliation != null) stanzaBuilder.addAttribute("affiliation",
affiliation.toString());
+ if (role != null) stanzaBuilder.addAttribute("role",
role.toString());
+ stanzaBuilder.endInnerElement();
+ }
+
+}
Added:
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerChangeNickTestCase.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerChangeNickTestCase.java?rev=806592&view=auto
==============================================================================
---
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerChangeNickTestCase.java
(added)
+++
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerChangeNickTestCase.java
Fri Aug 21 15:13:50 2009
@@ -0,0 +1,100 @@
+package org.apache.vysper.xmpp.modules.extension.xep0045_muc.handler;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.addressing.EntityImpl;
+import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Affiliation;
+import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Occupant;
+import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Role;
+import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Room;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.protocol.ProtocolException;
+import org.apache.vysper.xmpp.protocol.ResponseStanzaContainer;
+import org.apache.vysper.xmpp.protocol.StanzaHandler;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import org.apache.vysper.xmpp.xmlfragment.XMLElement;
+
+/**
+ */
+public class MUCPresenceHandlerChangeNickTestCase extends
AbstractMUCHandlerTestCase {
+
+ private Stanza changeNick(Entity occupantJid, Entity roomWithNickJid)
throws ProtocolException {
+ StanzaBuilder stanzaBuilder =
StanzaBuilder.createPresenceStanza(occupantJid, roomWithNickJid, null, null,
null, null);
+
stanzaBuilder.startInnerElement("x").addNamespaceAttribute(NamespaceURIs.XEP0045_MUC);
+
+ stanzaBuilder.endInnerElement();
+ Stanza presenceStanza = stanzaBuilder.getFinalStanza();
+ ResponseStanzaContainer container = handler.execute(presenceStanza,
sessionContext.getServerRuntimeContext(), true, sessionContext, null);
+ if(container != null) {
+ return container.getResponseStanza();
+ } else {
+ return null;
+ }
+ }
+
+
+ @Override
+ protected StanzaHandler createHandler() {
+ return new MUCPresenceHandler(conference);
+ }
+
+ public void testChangeNick() throws Exception {
+ Room room = conference.findRoom(ROOM1_JID);
+ room.addOccupant(OCCUPANT1_JID, "nick");
+ room.addOccupant(OCCUPANT2_JID, "nick 2");
+
+ changeNick(OCCUPANT1_JID, new EntityImpl(ROOM1_JID, "new nick"));
+
+ Occupant occupant = room.findOccupantByJID(OCCUPANT1_JID);
+ assertEquals("new nick", occupant.getName());
+
+ MUCUserItem unavailbleItem = new MUCUserItem(OCCUPANT1_JID, "new
nick", Affiliation.None, Role.Participant);
+ assertPresenceStanza(occupant1Queue.getNext(), new
EntityImpl(ROOM1_JID, "nick"), OCCUPANT1_JID, "unavailable",
+ Arrays.asList(unavailbleItem), Arrays.asList(330, 110));
+ assertPresenceStanza(occupant2Queue.getNext(), new
EntityImpl(ROOM1_JID, "nick"), OCCUPANT2_JID, "unavailable",
+ Arrays.asList(unavailbleItem), Arrays.asList(330));
+
+ MUCUserItem availbleItem = new MUCUserItem(OCCUPANT1_JID, null,
Affiliation.None, Role.Participant);
+ assertPresenceStanza(occupant1Queue.getNext(), new
EntityImpl(ROOM1_JID, "new nick"), OCCUPANT1_JID, null,
+ Arrays.asList(availbleItem), Arrays.asList(110));
+ assertPresenceStanza(occupant2Queue.getNext(), new
EntityImpl(ROOM1_JID, "new nick"), OCCUPANT2_JID, null,
+ Arrays.asList(availbleItem), null);
+ }
+
+ public void testChangeNickWithDuplicateNick() throws Exception {
+ Room room = conference.findRoom(ROOM1_JID);
+ room.addOccupant(OCCUPANT1_JID, "nick");
+ room.addOccupant(OCCUPANT2_JID, "nick 2");
+
+ Stanza error = changeNick(OCCUPANT1_JID, new
EntityImpl(ROOM1_JID,"nick 2"));
+
+ assertNotNull(error);
+ }
+
+ private void assertPresenceStanza(Stanza stanza, Entity expectedFrom,
Entity expectedTo, String expectedType,
+ List<MUCUserItem> expectedItems, List<Integer> expectedStatuses) {
+
+ assertNotNull(stanza);
+ assertEquals(expectedFrom, stanza.getFrom());
+ assertEquals(expectedTo, stanza.getTo());
+ assertEquals(expectedType, stanza.getAttributeValue("type"));
+
+ XMLElement xElm = stanza.getFirstInnerElement();
+ assertEquals(NamespaceURIs.XEP0045_MUC_USER, xElm.getNamespaceURI());
+
+ Iterator<XMLElement> itemElements = xElm.getInnerElements().iterator();
+ for(MUCUserItem item : expectedItems) {
+ XMLElement itemElm = itemElements.next();
+
+ assertEquals(item.getJid().getFullQualifiedName(),
itemElm.getAttributeValue("jid"));
+ assertEquals(item.getNick(), itemElm.getAttributeValue("nick"));
+ assertEquals(item.getAffiliation().toString(),
itemElm.getAttributeValue("affiliation"));
+ assertEquals(item.getRole().toString(),
itemElm.getAttributeValue("role"));
+ }
+ }
+
+}