diff --git a/source/org/jivesoftware/smackx/muc/DefaultParticipantStatusListener.java b/source/org/jivesoftware/smackx/muc/DefaultParticipantStatusListener.java index e5f3e9194..625655fbb 100644 --- a/source/org/jivesoftware/smackx/muc/DefaultParticipantStatusListener.java +++ b/source/org/jivesoftware/smackx/muc/DefaultParticipantStatusListener.java @@ -31,6 +31,12 @@ package org.jivesoftware.smackx.muc; */ public class DefaultParticipantStatusListener implements ParticipantStatusListener { + public void joined(String participant) { + } + + public void left(String participant) { + } + public void kicked(String participant) { } diff --git a/source/org/jivesoftware/smackx/muc/MultiUserChat.java b/source/org/jivesoftware/smackx/muc/MultiUserChat.java index 736a40dca..5dc01db3c 100644 --- a/source/org/jivesoftware/smackx/muc/MultiUserChat.java +++ b/source/org/jivesoftware/smackx/muc/MultiUserChat.java @@ -2014,6 +2014,12 @@ public class MultiUserChat { isUserStatusModification, from); } + else { + // A new occupant has joined the room + if (!isUserStatusModification) { + fireParticipantStatusListeners("joined", from); + } + } } else if (presence.getType() == Presence.Type.UNAVAILABLE) { synchronized (occupantsMap) { @@ -2027,6 +2033,11 @@ public class MultiUserChat { presence.getFrom().equals(myRoomJID), mucUser, from); + } else { + // An occupant has left the room + if (!isUserStatusModification) { + fireParticipantStatusListeners("left", from); + } } } } diff --git a/source/org/jivesoftware/smackx/muc/ParticipantStatusListener.java b/source/org/jivesoftware/smackx/muc/ParticipantStatusListener.java index a3b5449fb..210230843 100644 --- a/source/org/jivesoftware/smackx/muc/ParticipantStatusListener.java +++ b/source/org/jivesoftware/smackx/muc/ParticipantStatusListener.java @@ -28,6 +28,23 @@ package org.jivesoftware.smackx.muc; */ public interface ParticipantStatusListener { + /** + * Called when a new room occupant has joined the room. + * + * @param participant the participant that has just joined the room + * (e.g. room@conference.jabber.org/nick). + */ + public abstract void joined(String participant); + + /** + * Called when a room occupant has left the room on its own. This means that the occupant was + * neither kicked nor banned from the room. + * + * @param participant the participant that has left the room on its own. + * (e.g. room@conference.jabber.org/nick). + */ + public abstract void left(String participant); + /** * Called when a room participant has been kicked from the room. This means that the kicked * participant is no longer participating in the room. diff --git a/test/org/jivesoftware/smackx/muc/MultiUserChatTest.java b/test/org/jivesoftware/smackx/muc/MultiUserChatTest.java index b2edfc3b0..b76609cb6 100644 --- a/test/org/jivesoftware/smackx/muc/MultiUserChatTest.java +++ b/test/org/jivesoftware/smackx/muc/MultiUserChatTest.java @@ -1503,6 +1503,107 @@ public class MultiUserChatTest extends SmackTestCase { } } + /** + * Check that ParticipantStatusListener is receiving joining and leaving events correctly. + */ + public void testJoinLeftEvents() { + final String[] answer = new String[8]; + try { + // User1 will listen for occupants joining and leaving the room + muc.addParticipantStatusListener(new DefaultParticipantStatusListener() { + public void joined(String participant) { + super.joined(participant); + if ((room + "/testbot2").equals(participant)) { + answer[0] = participant; + } + else { + answer[1] = participant; + } + } + public void left(String participant) { + super.left(participant); + if ((room + "/testbot2").equals(participant)) { + answer[2] = participant; + } + else { + answer[3] = participant; + } + } + }); + + // User2 joins the new room + MultiUserChat muc2 = new MultiUserChat(getConnection(1), room); + // User2 will listen for User3 joining and leaving the room + muc2.addParticipantStatusListener(new DefaultParticipantStatusListener() { + public void joined(String participant) { + super.joined(participant); + if ((room + "/testbot").equals(participant)) { + answer[4] = participant; + } + else { + answer[5] = participant; + } + } + public void left(String participant) { + super.left(participant); + if ((room + "/testbot").equals(participant)) { + answer[6] = participant; + } + else { + answer[7] = participant; + } + } + }); + muc2.join("testbot2"); + + // User3 joins the new room + MultiUserChat muc3 = new MultiUserChat(getConnection(2), room); + muc3.join("testbot3"); + + // User3 leaves the room + muc3.leave(); + // User2 leaves the room + muc2.leave(); + + // Check that ParticipantStatusListener is working OK + assertEquals( + "User1 didn't receive the event of User2 joining the room", + room + "/testbot2", + answer[0]); + assertEquals( + "User1 didn't receive the event of User3 joining the room", + room + "/testbot3", + answer[1]); + assertEquals( + "User1 didn't receive the event of User2 leaving the room", + room + "/testbot2", + answer[2]); + assertEquals( + "User1 didn't receive the event of User3 leaving the room", + room + "/testbot3", + answer[3]); + assertEquals( + "User2 didn't receive the event of User1 joining the room", + room + "/testbot", + answer[4]); + assertEquals( + "User2 didn't receive the event of User3 joining the room", + room + "/testbot3", + answer[5]); + assertNull( + "User2 received the event of User1 leaving the room", + answer[6]); + assertEquals( + "User2 didn't receive the event of User3 leaving the room", + room + "/testbot3", + answer[7]); + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + private void makeRoomModerated() throws XMPPException { // User1 (which is the room owner) converts the instant room into a moderated room Form form = muc.getConfigurationForm();