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"));
+        }
+    }
+    
+}


Reply via email to