From 94db37b89bab6256d0074314a1d2930ab4d89524 Mon Sep 17 00:00:00 2001 From: Gaston Dombiak Date: Wed, 15 Dec 2004 19:03:37 +0000 Subject: [PATCH] Added support for room management in batch mode. SMACK-4 git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@2430 b35dd754-fafc-0310-a699-88a17e54d16e --- .../smackx/muc/MultiUserChat.java | 950 +++++++++++------- .../smackx/muc/MultiUserChatTest.java | 130 ++- 2 files changed, 707 insertions(+), 373 deletions(-) diff --git a/source/org/jivesoftware/smackx/muc/MultiUserChat.java b/source/org/jivesoftware/smackx/muc/MultiUserChat.java index 164319628..736a40dca 100644 --- a/source/org/jivesoftware/smackx/muc/MultiUserChat.java +++ b/source/org/jivesoftware/smackx/muc/MultiUserChat.java @@ -54,7 +54,7 @@ public class MultiUserChat { private String subject; private String nickname = null; private boolean joined = false; - private Map participantsMap = new HashMap(); + private Map occupantsMap = new HashMap(); private List invitationRejectionListeners = new ArrayList(); private List subjectUpdatedListeners = new ArrayList(); @@ -421,8 +421,8 @@ public class MultiUserChat { Presence leavePresence = new Presence(Presence.Type.UNAVAILABLE); leavePresence.setTo(room + "/" + nickname); connection.sendPacket(leavePresence); - // Reset participant information. - participantsMap = new HashMap(); + // Reset occupant information. + occupantsMap = new HashMap(); nickname = null; joined = false; userHasLeft(); @@ -600,8 +600,8 @@ public class MultiUserChat { else if (answer.getError() != null) { throw new XMPPException(answer.getError()); } - // Reset participant information. - participantsMap = new HashMap(); + // Reset occupant information. + occupantsMap = new HashMap(); nickname = null; joined = false; userHasLeft(); @@ -613,18 +613,18 @@ public class MultiUserChat { * * If the room is password-protected, the invitee will receive a password to use to join * the room. If the room is members-only, the the invitee may be added to the member list. - * - * @param participant the user to invite to the room.(e.g. hecate@shakespeare.lit) + * + * @param user the user to invite to the room.(e.g. hecate@shakespeare.lit) * @param reason the reason why the user is being invited. */ - public void invite(String participant, String reason) { + public void invite(String user, String reason) { // TODO listen for 404 error code when inviter supplies a non-existent JID Message message = new Message(room); // Create the MUCUser packet that will include the invitation MUCUser mucUser = new MUCUser(); MUCUser.Invite invite = new MUCUser.Invite(); - invite.setTo(participant); + invite.setTo(user); invite.setReason(reason); mucUser.setInvite(invite); // Add the MUCUser packet that includes the invitation to the message @@ -816,11 +816,11 @@ public class MultiUserChat { } /** - * Changes the participant's nickname to a new nickname within the room. Each room participant + * Changes the occupant's nickname to a new nickname within the room. Each room occupant * will receive two presence packets. One of type "unavailable" for the old nickname and one * indicating availability for the new nickname. The unavailable presence will contain the new * nickname and an appropriate status code (namely 303) as extended presence information. The - * status code 303 indicates that the participant is changing his/her nickname. + * status code 303 indicates that the occupant is changing his/her nickname. * * @param nickname the new nickname within the room. * @throws XMPPException if the new nickname is already in use by another occupant. @@ -864,7 +864,7 @@ public class MultiUserChat { } /** - * Changes the participant's availability status within the room. The presence type + * Changes the occupant's availability status within the room. The presence type * will remain available but with a new status that describes the presence update and * a new presence mode (e.g. Extended away). * @@ -893,308 +893,231 @@ public class MultiUserChat { } /** - * Kicks a visitor or participant from the room. The kicked participant will receive a presence + * Kicks a visitor or participant from the room. The kicked occupant will receive a presence * of type "unavailable" including a status code 307 and optionally along with the reason - * (if provided) and the bare JID of the user who initiated the kick. After the participant - * was kicked from the room, the rest of the participants will receive a presence of type - * "unavailable". The presence will include a status code 307 which means that the participant + * (if provided) and the bare JID of the user who initiated the kick. After the occupant + * was kicked from the room, the rest of the occupants will receive a presence of type + * "unavailable". The presence will include a status code 307 which means that the occupant * was kicked from the room. * - * @param nickname the nickname of the participant or visitor to kick from the room + * @param nickname the nickname of the participant or visitor to kick from the room * (e.g. "john"). * @param reason the reason why the participant or visitor is being kicked from the room. - * @throws XMPPException if an error occurs kicking the participant. In particular, a + * @throws XMPPException if an error occurs kicking the occupant. In particular, a * 405 error can occur if a moderator or a user with an affiliation of "owner" or "admin" * was intended to be kicked (i.e. Not Allowed error); or a - * 403 error can occur if the participant that intended to kick another participant does + * 403 error can occur if the occupant that intended to kick another occupant does * not have kicking privileges (i.e. Forbidden error); or a * 400 error can occur if the provided nickname is not present in the room. */ public void kickParticipant(String nickname, String reason) throws XMPPException { - MUCAdmin iq = new MUCAdmin(); - iq.setTo(room); - iq.setType(IQ.Type.SET); - // Set the role to "none". This will request the room to kick the participant or visitor - MUCAdmin.Item item = new MUCAdmin.Item(null, "none"); - item.setNick(nickname); - item.setReason(reason); - iq.addItem(item); - - // Wait for a response packet back from the server. - PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); - PacketCollector response = connection.createPacketCollector(responseFilter); - // Send the kick request to the server. - connection.sendPacket(iq); - // Wait up to a certain number of seconds for a reply. - IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); - // Stop queuing results - response.cancel(); - - if (answer == null) { - throw new XMPPException("No response from server."); - } - else if (answer.getError() != null) { - throw new XMPPException(answer.getError()); - } + changeRole(nickname, "none", reason); } /** - * Grants voice to a visitor in the room. In a moderated room, a moderator may want to manage - * who does and does not have "voice" in the room. To have voice means that a room participant + * Grants voice to visitors in the room. In a moderated room, a moderator may want to manage + * who does and does not have "voice" in the room. To have voice means that a room occupant * is able to send messages to the room occupants. * - * @param nickname the nickname of the visitor to grant voice in the room (e.g. "john"). + * @param nicknames the nicknames of the visitors to grant voice in the room (e.g. "john"). * @throws XMPPException if an error occurs granting voice to a visitor. In particular, a - * 403 error can occur if the participant that intended to grant voice is not + * 403 error can occur if the occupant that intended to grant voice is not + * a moderator in this room (i.e. Forbidden error); or a + * 400 error can occur if the provided nickname is not present in the room. + */ + public void grantVoice(Collection nicknames) throws XMPPException { + changeRole(nicknames, "participant"); + } + + /** + * Grants voice to a visitor in the room. In a moderated room, a moderator may want to manage + * who does and does not have "voice" in the room. To have voice means that a room occupant + * is able to send messages to the room occupants. + * + * @param nickname the nickname of the visitor to grant voice in the room (e.g. "john"). + * @throws XMPPException if an error occurs granting voice to a visitor. In particular, a + * 403 error can occur if the occupant that intended to grant voice is not * a moderator in this room (i.e. Forbidden error); or a * 400 error can occur if the provided nickname is not present in the room. */ public void grantVoice(String nickname) throws XMPPException { - MUCAdmin iq = new MUCAdmin(); - iq.setTo(room); - iq.setType(IQ.Type.SET); - // Set the role to "participant". This will grant voice to the visitor - MUCAdmin.Item item = new MUCAdmin.Item(null, "participant"); - item.setNick(nickname); - iq.addItem(item); - - // Wait for a response packet back from the server. - PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); - PacketCollector response = connection.createPacketCollector(responseFilter); - // Send the grant voice request to the server. - connection.sendPacket(iq); - // Wait up to a certain number of seconds for a reply. - IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); - // Stop queuing results - response.cancel(); - - if (answer == null) { - throw new XMPPException("No response from server."); - } - else if (answer.getError() != null) { - throw new XMPPException(answer.getError()); - } + changeRole(nickname, "participant", null); } /** - * Revokes voice from a participant in the room. In a moderated room, a moderator may want to - * revoke a participant's privileges to speak. To have voice means that a room participant + * Revokes voice from participants in the room. In a moderated room, a moderator may want to + * revoke an occupant's privileges to speak. To have voice means that a room occupant * is able to send messages to the room occupants. * + * @param nicknames the nicknames of the participants to revoke voice (e.g. "john"). + * @throws XMPPException if an error occurs revoking voice from a participant. In particular, a + * 405 error can occur if a moderator or a user with an affiliation of "owner" or "admin" + * was tried to revoke his voice (i.e. Not Allowed error); or a + * 400 error can occur if the provided nickname is not present in the room. + */ + public void revokeVoice(Collection nicknames) throws XMPPException { + changeRole(nicknames, "visitor"); + } + + /** + * Revokes voice from a participant in the room. In a moderated room, a moderator may want to + * revoke an occupant's privileges to speak. To have voice means that a room occupant + * is able to send messages to the room occupants. + * * @param nickname the nickname of the participant to revoke voice (e.g. "john"). - * @throws XMPPException if an error occurs revoking voice from a participant. In particular, a + * @throws XMPPException if an error occurs revoking voice from a participant. In particular, a * 405 error can occur if a moderator or a user with an affiliation of "owner" or "admin" * was tried to revoke his voice (i.e. Not Allowed error); or a * 400 error can occur if the provided nickname is not present in the room. */ public void revokeVoice(String nickname) throws XMPPException { - MUCAdmin iq = new MUCAdmin(); - iq.setTo(room); - iq.setType(IQ.Type.SET); - // Set the role to "visitor". This will revoke voice from the participant - MUCAdmin.Item item = new MUCAdmin.Item(null, "visitor"); - item.setNick(nickname); - iq.addItem(item); - - // Wait for a response packet back from the server. - PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); - PacketCollector response = connection.createPacketCollector(responseFilter); - // Send the revoke voice request to the server. - connection.sendPacket(iq); - // Wait up to a certain number of seconds for a reply. - IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); - // Stop queuing results - response.cancel(); - - if (answer == null) { - throw new XMPPException("No response from server."); - } - else if (answer.getError() != null) { - throw new XMPPException(answer.getError()); - } + changeRole(nickname, "visitor", null); } /** - * Bans a user from the room. An admin or owner of the room can ban users from a room. This + * Bans users from the room. An admin or owner of the room can ban users from a room. This * means that the banned user will no longer be able to join the room unless the ban has been * removed. If the banned user was present in the room then he/she will be removed from the * room and notified that he/she was banned along with the reason (if provided) and the bare * XMPP user ID of the user who initiated the ban. * + * @param jids the bare XMPP user IDs of the users to ban. + * @throws XMPPException if an error occurs banning a user. In particular, a + * 405 error can occur if a moderator or a user with an affiliation of "owner" or "admin" + * was tried to be banned (i.e. Not Allowed error). + */ + public void banUsers(Collection jids) throws XMPPException { + changeAffiliationByAdmin(jids, "outcast"); + } + + /** + * Bans a user from the room. An admin or owner of the room can ban users from a room. This + * means that the banned user will no longer be able to join the room unless the ban has been + * removed. If the banned user was present in the room then he/she will be removed from the + * room and notified that he/she was banned along with the reason (if provided) and the bare + * XMPP user ID of the user who initiated the ban. + * * @param jid the bare XMPP user ID of the user to ban (e.g. "user@host.org"). * @param reason the reason why the user was banned. - * @throws XMPPException if an error occurs banning a user. In particular, a + * @throws XMPPException if an error occurs banning a user. In particular, a * 405 error can occur if a moderator or a user with an affiliation of "owner" or "admin" * was tried to be banned (i.e. Not Allowed error). */ public void banUser(String jid, String reason) throws XMPPException { - MUCAdmin iq = new MUCAdmin(); - iq.setTo(room); - iq.setType(IQ.Type.SET); - // Set the affiliation to "outcast". This will ban the user - MUCAdmin.Item item = new MUCAdmin.Item("outcast", null); - item.setJid(jid); - item.setReason(reason); - iq.addItem(item); + changeAffiliationByAdmin(jid, "outcast", reason); + } - // Wait for a response packet back from the server. - PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); - PacketCollector response = connection.createPacketCollector(responseFilter); - // Send the ban user request to the server. - connection.sendPacket(iq); - // Wait up to a certain number of seconds for a reply. - IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); - // Stop queuing results - response.cancel(); - - if (answer == null) { - throw new XMPPException("No response from server."); - } - else if (answer.getError() != null) { - throw new XMPPException(answer.getError()); - } + /** + * Grants membership to other users. Only administrators are able to grant membership. A user + * that becomes a room member will be able to enter a room of type Members-Only (i.e. a room + * that a user cannot enter without being on the member list). + * + * @param jids the XMPP user IDs of the users to grant membership. + * @throws XMPPException if an error occurs granting membership to a user. + */ + public void grantMembership(Collection jids) throws XMPPException { + changeAffiliationByAdmin(jids, "member"); } /** * Grants membership to a user. Only administrators are able to grant membership. A user * that becomes a room member will be able to enter a room of type Members-Only (i.e. a room - * that a user cannot enter without being on the member list). - * + * that a user cannot enter without being on the member list). + * * @param jid the XMPP user ID of the user to grant membership (e.g. "user@host.org"). * @throws XMPPException if an error occurs granting membership to a user. */ public void grantMembership(String jid) throws XMPPException { - MUCAdmin iq = new MUCAdmin(); - iq.setTo(room); - iq.setType(IQ.Type.SET); - // Set the affiliation to "member". This will grant membership to the user - MUCAdmin.Item item = new MUCAdmin.Item("member", null); - item.setJid(jid); - iq.addItem(item); + changeAffiliationByAdmin(jid, "member", null); + } - // Wait for a response packet back from the server. - PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); - PacketCollector response = connection.createPacketCollector(responseFilter); - // Send the grant membership request to the server. - connection.sendPacket(iq); - // Wait up to a certain number of seconds for a reply. - IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); - // Stop queuing results - response.cancel(); - - if (answer == null) { - throw new XMPPException("No response from server."); - } - else if (answer.getError() != null) { - throw new XMPPException(answer.getError()); - } + /** + * Revokes users' membership. Only administrators are able to revoke membership. A user + * that becomes a room member will be able to enter a room of type Members-Only (i.e. a room + * that a user cannot enter without being on the member list). If the user is in the room and + * the room is of type members-only then the user will be removed from the room. + * + * @param jids the bare XMPP user IDs of the users to revoke membership. + * @throws XMPPException if an error occurs revoking membership to a user. + */ + public void revokeMembership(Collection jids) throws XMPPException { + changeAffiliationByAdmin(jids, "none"); } /** * Revokes a user's membership. Only administrators are able to revoke membership. A user * that becomes a room member will be able to enter a room of type Members-Only (i.e. a room - * that a user cannot enter without being on the member list). If the user is in the room and + * that a user cannot enter without being on the member list). If the user is in the room and * the room is of type members-only then the user will be removed from the room. - * - * @param jid the bare XMPP user ID of the user to grant membership (e.g. "user@host.org"). + * + * @param jid the bare XMPP user ID of the user to revoke membership (e.g. "user@host.org"). * @throws XMPPException if an error occurs revoking membership to a user. */ public void revokeMembership(String jid) throws XMPPException { - MUCAdmin iq = new MUCAdmin(); - iq.setTo(room); - iq.setType(IQ.Type.SET); - // Set the affiliation to "none". This will revoke a user's membership - MUCAdmin.Item item = new MUCAdmin.Item("none", null); - item.setJid(jid); - iq.addItem(item); - - // Wait for a response packet back from the server. - PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); - PacketCollector response = connection.createPacketCollector(responseFilter); - // Send the revoke membership request to the server. - connection.sendPacket(iq); - // Wait up to a certain number of seconds for a reply. - IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); - // Stop queuing results - response.cancel(); - - if (answer == null) { - throw new XMPPException("No response from server."); - } - else if (answer.getError() != null) { - throw new XMPPException(answer.getError()); - } + changeAffiliationByAdmin(jid, "none", null); } /** - * Grants moderator privileges to a participant or visitor. Room administrators may grant + * Grants moderator privileges to participants or visitors. Room administrators may grant * moderator privileges. A moderator is allowed to kick users, grant and revoke voice, invite * other users, modify room's subject plus all the partcipants privileges. * + * @param nicknames the nicknames of the occupants to grant moderator privileges. + * @throws XMPPException if an error occurs granting moderator privileges to a user. + */ + public void grantModerator(Collection nicknames) throws XMPPException { + changeRole(nicknames, "moderator"); + } + + /** + * Grants moderator privileges to a participant or visitor. Room administrators may grant + * moderator privileges. A moderator is allowed to kick users, grant and revoke voice, invite + * other users, modify room's subject plus all the partcipants privileges. + * * @param nickname the nickname of the occupant to grant moderator privileges. * @throws XMPPException if an error occurs granting moderator privileges to a user. */ public void grantModerator(String nickname) throws XMPPException { - MUCAdmin iq = new MUCAdmin(); - iq.setTo(room); - iq.setType(IQ.Type.SET); - // Set the role to "moderator". This will grant moderator privileges - MUCAdmin.Item item = new MUCAdmin.Item(null, "moderator"); - item.setNick(nickname); - iq.addItem(item); - - // Wait for a response packet back from the server. - PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); - PacketCollector response = connection.createPacketCollector(responseFilter); - // Send the grant moderator privileges request to the server. - connection.sendPacket(iq); - // Wait up to a certain number of seconds for a reply. - IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); - // Stop queuing results - response.cancel(); - - if (answer == null) { - throw new XMPPException("No response from server."); - } - else if (answer.getError() != null) { - throw new XMPPException(answer.getError()); - } + changeRole(nickname, "moderator", null); } /** - * Revokes moderator privileges from another user. The occupant that loses moderator - * privileges will become a participant. Room administrators may revoke moderator privileges + * Revokes moderator privileges from other users. The occupant that loses moderator + * privileges will become a participant. Room administrators may revoke moderator privileges * only to occupants whose affiliation is member or none. This means that an administrator is * not allowed to revoke moderator privileges from other room administrators or owners. * + * @param nicknames the nicknames of the occupants to revoke moderator privileges. + * @throws XMPPException if an error occurs revoking moderator privileges from a user. + */ + public void revokeModerator(Collection nicknames) throws XMPPException { + changeRole(nicknames, "participant"); + } + + /** + * Revokes moderator privileges from another user. The occupant that loses moderator + * privileges will become a participant. Room administrators may revoke moderator privileges + * only to occupants whose affiliation is member or none. This means that an administrator is + * not allowed to revoke moderator privileges from other room administrators or owners. + * * @param nickname the nickname of the occupant to revoke moderator privileges. * @throws XMPPException if an error occurs revoking moderator privileges from a user. */ public void revokeModerator(String nickname) throws XMPPException { - MUCAdmin iq = new MUCAdmin(); - iq.setTo(room); - iq.setType(IQ.Type.SET); - // Set the role to "participant". This will revoke moderator privileges - MUCAdmin.Item item = new MUCAdmin.Item(null, "participant"); - item.setNick(nickname); - iq.addItem(item); + changeRole(nickname, "participant", null); + } - // Wait for a response packet back from the server. - PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); - PacketCollector response = connection.createPacketCollector(responseFilter); - // Send the revoke moderator privileges request to the server. - connection.sendPacket(iq); - // Wait up to a certain number of seconds for a reply. - IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); - // Stop queuing results - response.cancel(); - - if (answer == null) { - throw new XMPPException("No response from server."); - } - else if (answer.getError() != null) { - throw new XMPPException(answer.getError()); - } + /** + * Grants ownership privileges to other users. Room owners may grant ownership privileges. + * Some room implementations will not allow to grant ownership privileges to other users. + * An owner is allowed to change defining room features as well as perform all administrative + * functions. + * + * @param jids the collection of bare XMPP user IDs of the users to grant ownership. + * @throws XMPPException if an error occurs granting ownership privileges to a user. + */ + public void grantOwnership(Collection jids) throws XMPPException { + changeAffiliationByOwner(jids, "owner"); } /** @@ -1207,30 +1130,19 @@ public class MultiUserChat { * @throws XMPPException if an error occurs granting ownership privileges to a user. */ public void grantOwnership(String jid) throws XMPPException { - MUCOwner iq = new MUCOwner(); - iq.setTo(room); - iq.setType(IQ.Type.SET); - // Set the affiliation to "owner". This will grant a user's ownership - MUCOwner.Item item = new MUCOwner.Item("owner"); - item.setJid(jid); - iq.addItem(item); + changeAffiliationByOwner(jid, "owner"); + } - // Wait for a response packet back from the server. - PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); - PacketCollector response = connection.createPacketCollector(responseFilter); - // Send the grant ownership request to the server. - connection.sendPacket(iq); - // Wait up to a certain number of seconds for a reply. - IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); - // Stop queuing results - response.cancel(); - - if (answer == null) { - throw new XMPPException("No response from server."); - } - else if (answer.getError() != null) { - throw new XMPPException(answer.getError()); - } + /** + * Revokes ownership privileges from other users. The occupant that loses ownership + * privileges will become an administrator. Room owners may revoke ownership privileges. + * Some room implementations will not allow to grant ownership privileges to other users. + * + * @param jids the bare XMPP user IDs of the users to revoke ownership. + * @throws XMPPException if an error occurs revoking ownership privileges from a user. + */ + public void revokeOwnership(Collection jids) throws XMPPException { + changeAffiliationByOwner(jids, "admin"); } /** @@ -1238,34 +1150,23 @@ public class MultiUserChat { * privileges will become an administrator. Room owners may revoke ownership privileges. * Some room implementations will not allow to grant ownership privileges to other users. * - * @param jid the bare XMPP user ID of the user to grant ownership (e.g. "user@host.org"). - * @throws XMPPException if an error occurs granting ownership privileges to a user. + * @param jid the bare XMPP user ID of the user to revoke ownership (e.g. "user@host.org"). + * @throws XMPPException if an error occurs revoking ownership privileges from a user. */ public void revokeOwnership(String jid) throws XMPPException { - MUCOwner iq = new MUCOwner(); - iq.setTo(room); - iq.setType(IQ.Type.SET); - // Set the affiliation to "admin". This will revoke a user's ownership - MUCOwner.Item item = new MUCOwner.Item("admin"); - item.setJid(jid); - iq.addItem(item); + changeAffiliationByOwner(jid, "admin"); + } - // Wait for a response packet back from the server. - PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); - PacketCollector response = connection.createPacketCollector(responseFilter); - // Send the revoke ownership request to the server. - connection.sendPacket(iq); - // Wait up to a certain number of seconds for a reply. - IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); - // Stop queuing results - response.cancel(); - - if (answer == null) { - throw new XMPPException("No response from server."); - } - else if (answer.getError() != null) { - throw new XMPPException(answer.getError()); - } + /** + * Grants administrator privileges to other users. Room owners may grant administrator + * privileges to a member or unaffiliated user. An administrator is allowed to perform + * administrative functions such as banning users and edit moderator list. + * + * @param jids the bare XMPP user IDs of the users to grant administrator privileges. + * @throws XMPPException if an error occurs granting administrator privileges to a user. + */ + public void grantAdmin(Collection jids) throws XMPPException { + changeAffiliationByOwner(jids, "admin"); } /** @@ -1278,54 +1179,193 @@ public class MultiUserChat { * @throws XMPPException if an error occurs granting administrator privileges to a user. */ public void grantAdmin(String jid) throws XMPPException { - MUCOwner iq = new MUCOwner(); - iq.setTo(room); - iq.setType(IQ.Type.SET); - // Set the affiliation to "admin". This will grant administrator privileges - MUCOwner.Item item = new MUCOwner.Item("admin"); - item.setJid(jid); - iq.addItem(item); - - // Wait for a response packet back from the server. - PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); - PacketCollector response = connection.createPacketCollector(responseFilter); - // Send the grant administrator privileges request to the server. - connection.sendPacket(iq); - // Wait up to a certain number of seconds for a reply. - IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); - // Stop queuing results - response.cancel(); - - if (answer == null) { - throw new XMPPException("No response from server."); - } - else if (answer.getError() != null) { - throw new XMPPException(answer.getError()); - } + changeAffiliationByOwner(jid, "admin"); } /** - * Revokes administrator privileges from a user. The occupant that loses administrator + * Revokes administrator privileges from users. The occupant that loses administrator * privileges will become a member. Room owners may revoke administrator privileges from * a member or unaffiliated user. * - * @param jid the bare XMPP user ID of the user to revoke administrator privileges + * @param jids the bare XMPP user IDs of the user to revoke administrator privileges. + * @throws XMPPException if an error occurs revoking administrator privileges from a user. + */ + public void revokeAdmin(Collection jids) throws XMPPException { + changeAffiliationByOwner(jids, "member"); + } + + /** + * Revokes administrator privileges from a user. The occupant that loses administrator + * privileges will become a member. Room owners may revoke administrator privileges from + * a member or unaffiliated user. + * + * @param jid the bare XMPP user ID of the user to revoke administrator privileges * (e.g. "user@host.org"). * @throws XMPPException if an error occurs revoking administrator privileges from a user. */ public void revokeAdmin(String jid) throws XMPPException { + changeAffiliationByOwner(jid, "member"); + } + + private void changeAffiliationByOwner(String jid, String affiliation) throws XMPPException { MUCOwner iq = new MUCOwner(); iq.setTo(room); iq.setType(IQ.Type.SET); - // Set the affiliation to "member". This will revoke a user's ownership - MUCOwner.Item item = new MUCOwner.Item("member"); + // Set the new affiliation. + MUCOwner.Item item = new MUCOwner.Item(affiliation); item.setJid(jid); iq.addItem(item); // Wait for a response packet back from the server. PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); PacketCollector response = connection.createPacketCollector(responseFilter); - // Send the revoke ownership request to the server. + // Send the change request to the server. + connection.sendPacket(iq); + // Wait up to a certain number of seconds for a reply. + IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); + // Stop queuing results + response.cancel(); + + if (answer == null) { + throw new XMPPException("No response from server."); + } + else if (answer.getError() != null) { + throw new XMPPException(answer.getError()); + } + } + + private void changeAffiliationByOwner(Collection jids, String affiliation) + throws XMPPException { + MUCOwner iq = new MUCOwner(); + iq.setTo(room); + iq.setType(IQ.Type.SET); + for (Iterator it=jids.iterator(); it.hasNext();) { + // Set the new affiliation. + MUCOwner.Item item = new MUCOwner.Item(affiliation); + item.setJid((String) it.next()); + iq.addItem(item); + } + + // Wait for a response packet back from the server. + PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); + PacketCollector response = connection.createPacketCollector(responseFilter); + // Send the change request to the server. + connection.sendPacket(iq); + // Wait up to a certain number of seconds for a reply. + IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); + // Stop queuing results + response.cancel(); + + if (answer == null) { + throw new XMPPException("No response from server."); + } + else if (answer.getError() != null) { + throw new XMPPException(answer.getError()); + } + } + + private void changeAffiliationByAdmin(String jid, String affiliation, String reason) + throws XMPPException { + MUCAdmin iq = new MUCAdmin(); + iq.setTo(room); + iq.setType(IQ.Type.SET); + // Set the new affiliation. + MUCAdmin.Item item = new MUCAdmin.Item(affiliation, null); + item.setJid(jid); + item.setReason(reason); + iq.addItem(item); + + // Wait for a response packet back from the server. + PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); + PacketCollector response = connection.createPacketCollector(responseFilter); + // Send the change request to the server. + connection.sendPacket(iq); + // Wait up to a certain number of seconds for a reply. + IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); + // Stop queuing results + response.cancel(); + + if (answer == null) { + throw new XMPPException("No response from server."); + } + else if (answer.getError() != null) { + throw new XMPPException(answer.getError()); + } + } + + private void changeAffiliationByAdmin(Collection jids, String affiliation) + throws XMPPException { + MUCAdmin iq = new MUCAdmin(); + iq.setTo(room); + iq.setType(IQ.Type.SET); + for (Iterator it=jids.iterator(); it.hasNext();) { + // Set the new affiliation. + MUCAdmin.Item item = new MUCAdmin.Item(affiliation, null); + item.setJid((String) it.next()); + iq.addItem(item); + } + + // Wait for a response packet back from the server. + PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); + PacketCollector response = connection.createPacketCollector(responseFilter); + // Send the change request to the server. + connection.sendPacket(iq); + // Wait up to a certain number of seconds for a reply. + IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); + // Stop queuing results + response.cancel(); + + if (answer == null) { + throw new XMPPException("No response from server."); + } + else if (answer.getError() != null) { + throw new XMPPException(answer.getError()); + } + } + + private void changeRole(String nickname, String role, String reason) throws XMPPException { + MUCAdmin iq = new MUCAdmin(); + iq.setTo(room); + iq.setType(IQ.Type.SET); + // Set the new role. + MUCAdmin.Item item = new MUCAdmin.Item(null, role); + item.setNick(nickname); + item.setReason(reason); + iq.addItem(item); + + // Wait for a response packet back from the server. + PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); + PacketCollector response = connection.createPacketCollector(responseFilter); + // Send the change request to the server. + connection.sendPacket(iq); + // Wait up to a certain number of seconds for a reply. + IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); + // Stop queuing results + response.cancel(); + + if (answer == null) { + throw new XMPPException("No response from server."); + } + else if (answer.getError() != null) { + throw new XMPPException(answer.getError()); + } + } + + private void changeRole(Collection nicknames, String role) throws XMPPException { + MUCAdmin iq = new MUCAdmin(); + iq.setTo(room); + iq.setType(IQ.Type.SET); + for (Iterator it=nicknames.iterator(); it.hasNext();) { + // Set the new role. + MUCAdmin.Item item = new MUCAdmin.Item(null, role); + item.setNick((String) it.next()); + iq.addItem(item); + } + + // Wait for a response packet back from the server. + PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); + PacketCollector response = connection.createPacketCollector(responseFilter); + // Send the change request to the server. connection.sendPacket(iq); // Wait up to a certain number of seconds for a reply. IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); @@ -1341,68 +1381,64 @@ public class MultiUserChat { } /** - * Returns the number of participants in the group chat.

+ * Returns the number of occupants in the group chat.

* * Note: this value will only be accurate after joining the group chat, and * may fluctuate over time. If you query this value directly after joining the * group chat it may not be accurate, as it takes a certain amount of time for * the server to send all presence packets to this client. * - * @return the number of participants in the group chat. + * @return the number of occupants in the group chat. */ - public int getParticipantCount() { - synchronized (participantsMap) { - return participantsMap.size(); + public int getOccupantsCount() { + synchronized (occupantsMap) { + return occupantsMap.size(); } } /** - * Returns an Iterator (of Strings) for the list of fully qualified participants + * Returns an Iterator (of Strings) for the list of fully qualified occupants * in the group chat. For example, "conference@chat.jivesoftware.com/SomeUser". - * Typically, a client would only display the nickname of the participant. To + * Typically, a client would only display the nickname of the occupant. To * get the nickname from the fully qualified name, use the * {@link org.jivesoftware.smack.util.StringUtils#parseResource(String)} method. * Note: this value will only be accurate after joining the group chat, and may * fluctuate over time. * - * @return an Iterator for the participants in the group chat. + * @return an Iterator for the occupants in the group chat. */ - public Iterator getParticipants() { - synchronized (participantsMap) { - return Collections.unmodifiableList(new ArrayList(participantsMap.keySet())).iterator(); + public Iterator getOccupants() { + synchronized (occupantsMap) { + return Collections.unmodifiableList(new ArrayList(occupantsMap.keySet())).iterator(); } } /** - * Returns the presence info for a particular participant, or null if the participant + * Returns the presence info for a particular user, or null if the user * is not in the room.

* - * @param participant the room occupant to search for his presence. The format of participant must + * @param user the room occupant to search for his presence. The format of user must * be: roomName@service/nickname (e.g. darkcave@macbeth.shakespeare.lit/thirdwitch). - * @return the participant's current presence, or null if the user is unavailable + * @return the occupant's current presence, or null if the user is unavailable * or if no presence information is available. */ - public Presence getParticipantPresence(String participant) { - return (Presence) participantsMap.get(participant); + public Presence getOccupantPresence(String user) { + return (Presence) occupantsMap.get(user); } /** - * Returns the participant's full JID when joining a Non-Anonymous room or null - * if the room is of type anonymous. If the room is of type semi-anonymous only the - * moderators will have access to the participants full JID. - * - * @param participant the room occupant to search for his JID. The format of participant must + * Returns the Occupant information for a particular occupant, or null if the + * user is not in the room. The Occupant object may include information such as full + * JID of the user as well as the role and affiliation of the user in the room.

+ * + * @param user the room occupant to search for his presence. The format of user must * be: roomName@service/nickname (e.g. darkcave@macbeth.shakespeare.lit/thirdwitch). - * @return the participant's full JID when joining a Non-Anonymous room otherwise returns - * null. + * @return the Occupant or null if the user is unavailable (i.e. not in the room). */ - public String getParticipantJID(String participant) { - // Get the participant's presence - Presence presence = getParticipantPresence(participant); - // Get the MUC User extension - MUCUser mucUser = getMUCUserExtension(presence); - if (mucUser != null) { - return mucUser.getItem().getJid(); + public Occupant getOccupant(String user) { + Presence presence = (Presence) occupantsMap.get(user); + if (presence != null) { + return new Occupant(presence); } return null; } @@ -1410,7 +1446,7 @@ public class MultiUserChat { /** * Adds a packet listener that will be notified of any new Presence packets * sent to the group chat. Using a listener is a suitable way to know when the list - * of participants should be re-loaded due to any changes. + * of occupants should be re-loaded due to any changes. * * @param listener a packet listener that will be notified of any presence packets * sent to the group chat. @@ -1430,6 +1466,194 @@ public class MultiUserChat { connection.removePacketListener(listener); } + /** + * Returns a collection of Affiliate with the room owners. + * + * @return a collection of Affiliate with the room owners. + * @throws XMPPException if an error occured while performing the request to the server or you + * don't have enough privileges to get this information. + */ + public Collection getOwners() throws XMPPException { + return getAffiliatesByOwner("owner"); + } + + /** + * Returns a collection of Affiliate with the room administrators. + * + * @return a collection of Affiliate with the room administrators. + * @throws XMPPException if an error occured while performing the request to the server or you + * don't have enough privileges to get this information. + */ + public Collection getAdmins() throws XMPPException { + return getAffiliatesByOwner("admin"); + } + + /** + * Returns a collection of Affiliate with the room members. + * + * @return a collection of Affiliate with the room members. + * @throws XMPPException if an error occured while performing the request to the server or you + * don't have enough privileges to get this information. + */ + public Collection getMembers() throws XMPPException { + return getAffiliatesByAdmin("member"); + } + + /** + * Returns a collection of Affiliate with the room outcasts. + * + * @return a collection of Affiliate with the room outcasts. + * @throws XMPPException if an error occured while performing the request to the server or you + * don't have enough privileges to get this information. + */ + public Collection getOutcasts() throws XMPPException { + return getAffiliatesByAdmin("outcast"); + } + + /** + * Returns a collection of Affiliate that have the specified room affiliation + * sending a request in the owner namespace. + * + * @param affiliation the affiliation of the users in the room. + * @return a collection of Affiliate that have the specified room affiliation. + * @throws XMPPException if an error occured while performing the request to the server or you + * don't have enough privileges to get this information. + */ + private Collection getAffiliatesByOwner(String affiliation) throws XMPPException { + MUCOwner iq = new MUCOwner(); + iq.setTo(room); + iq.setType(IQ.Type.GET); + // Set the specified affiliation. This may request the list of owners/admins/members/outcasts. + MUCOwner.Item item = new MUCOwner.Item(affiliation); + iq.addItem(item); + + // Wait for a response packet back from the server. + PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); + PacketCollector response = connection.createPacketCollector(responseFilter); + // Send the request to the server. + connection.sendPacket(iq); + // Wait up to a certain number of seconds for a reply. + MUCOwner answer = (MUCOwner) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); + // Stop queuing results + response.cancel(); + + if (answer == null) { + throw new XMPPException("No response from server."); + } + else if (answer.getError() != null) { + throw new XMPPException(answer.getError()); + } + // Get the list of affiliates from the server's answer + List affiliates = new ArrayList(); + for (Iterator it = answer.getItems(); it.hasNext();) { + affiliates.add(new Affiliate((MUCOwner.Item) it.next())); + } + return affiliates; + } + + /** + * Returns a collection of Affiliate that have the specified room affiliation + * sending a request in the admin namespace. + * + * @param affiliation the affiliation of the users in the room. + * @return a collection of Affiliate that have the specified room affiliation. + * @throws XMPPException if an error occured while performing the request to the server or you + * don't have enough privileges to get this information. + */ + private Collection getAffiliatesByAdmin(String affiliation) throws XMPPException { + MUCAdmin iq = new MUCAdmin(); + iq.setTo(room); + iq.setType(IQ.Type.GET); + // Set the specified affiliation. This may request the list of owners/admins/members/outcasts. + MUCAdmin.Item item = new MUCAdmin.Item(affiliation, null); + iq.addItem(item); + + // Wait for a response packet back from the server. + PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); + PacketCollector response = connection.createPacketCollector(responseFilter); + // Send the request to the server. + connection.sendPacket(iq); + // Wait up to a certain number of seconds for a reply. + MUCAdmin answer = (MUCAdmin) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); + // Stop queuing results + response.cancel(); + + if (answer == null) { + throw new XMPPException("No response from server."); + } + else if (answer.getError() != null) { + throw new XMPPException(answer.getError()); + } + // Get the list of affiliates from the server's answer + List affiliates = new ArrayList(); + for (Iterator it = answer.getItems(); it.hasNext();) { + affiliates.add(new Affiliate((MUCAdmin.Item) it.next())); + } + return affiliates; + } + + /** + * Returns a collection of Occupant with the room moderators. + * + * @return a collection of Occupant with the room moderators. + * @throws XMPPException if an error occured while performing the request to the server or you + * don't have enough privileges to get this information. + */ + public Collection getModerators() throws XMPPException { + return getOccupants("moderator"); + } + + /** + * Returns a collection of Occupant with the room participants. + * + * @return a collection of Occupant with the room participants. + * @throws XMPPException if an error occured while performing the request to the server or you + * don't have enough privileges to get this information. + */ + public Collection getParticipants() throws XMPPException { + return getOccupants("participant"); + } + + /** + * Returns a collection of Occupant that have the specified room role. + * + * @param role the role of the occupant in the room. + * @return a collection of Occupant that have the specified room role. + * @throws XMPPException if an error occured while performing the request to the server or you + * don't have enough privileges to get this information. + */ + private Collection getOccupants(String role) throws XMPPException { + MUCAdmin iq = new MUCAdmin(); + iq.setTo(room); + iq.setType(IQ.Type.GET); + // Set the specified role. This may request the list of moderators/participants. + MUCAdmin.Item item = new MUCAdmin.Item(null, role); + iq.addItem(item); + + // Wait for a response packet back from the server. + PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); + PacketCollector response = connection.createPacketCollector(responseFilter); + // Send the request to the server. + connection.sendPacket(iq); + // Wait up to a certain number of seconds for a reply. + MUCAdmin answer = (MUCAdmin) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); + // Stop queuing results + response.cancel(); + + if (answer == null) { + throw new XMPPException("No response from server."); + } + else if (answer.getError() != null) { + throw new XMPPException(answer.getError()); + } + // Get the list of participants from the server's answer + List participants = new ArrayList(); + for (Iterator it = answer.getItems(); it.hasNext();) { + participants.add(new Occupant((MUCAdmin.Item) it.next())); + } + return participants; + } + /** * Sends a message to the chat room. * @@ -1443,16 +1667,16 @@ public class MultiUserChat { } /** - * Returns a new Chat for sending private messages to a given room participant. - * The Chat's participant address is the room's JID (i.e. roomName@service/nick). The server + * Returns a new Chat for sending private messages to a given room occupant. + * The Chat's occupant address is the room's JID (i.e. roomName@service/nick). The server * service will change the 'from' address to the sender's room JID and delivering the message * to the intended recipient's full JID. * - * @param participant occupant unique room JID (e.g. 'darkcave@macbeth.shakespeare.lit/Paul'). - * @return new Chat for sending private messages to a given room participant. + * @param occupant occupant unique room JID (e.g. 'darkcave@macbeth.shakespeare.lit/Paul'). + * @return new Chat for sending private messages to a given room occupant. */ - public Chat createPrivateChat(String participant) { - return new Chat(connection, participant); + public Chat createPrivateChat(String occupant) { + return new Chat(connection, occupant); } /** @@ -1669,7 +1893,7 @@ public class MultiUserChat { } /** - * Adds a listener that will be notified of changes in participants status in the room + * Adds a listener that will be notified of changes in occupants status in the room * such as the user being kicked, banned, or granted admin permissions. * * @param listener a participant status listener. @@ -1683,7 +1907,7 @@ public class MultiUserChat { } /** - * Removes a listener that was being notified of changes in participants status in the room + * Removes a listener that was being notified of changes in occupants status in the room * such as the user being kicked, banned, or granted admin permissions. * * @param listener a participant status listener. @@ -1768,16 +1992,16 @@ public class MultiUserChat { boolean isUserStatusModification = presence.getFrom().equals(myRoomJID); if (presence.getType() == Presence.Type.AVAILABLE) { Presence oldPresence; - synchronized (participantsMap) { - oldPresence = (Presence)participantsMap.get(from); - participantsMap.put(from, presence); + synchronized (occupantsMap) { + oldPresence = (Presence)occupantsMap.get(from); + occupantsMap.put(from, presence); } if (oldPresence != null) { - // Get the previous participant's affiliation & role + // Get the previous occupant's affiliation & role MUCUser mucExtension = getMUCUserExtension(oldPresence); String oldAffiliation = mucExtension.getItem().getAffiliation(); String oldRole = mucExtension.getItem().getRole(); - // Get the new participant's affiliation & role + // Get the new occupant's affiliation & role mucExtension = getMUCUserExtension(presence); String newAffiliation = mucExtension.getItem().getAffiliation(); String newRole = mucExtension.getItem().getRole(); @@ -1792,8 +2016,8 @@ public class MultiUserChat { } } else if (presence.getType() == Presence.Type.UNAVAILABLE) { - synchronized (participantsMap) { - participantsMap.remove(from); + synchronized (occupantsMap) { + occupantsMap.remove(from); } MUCUser mucUser = getMUCUserExtension(presence); if (mucUser != null && mucUser.getStatus() != null) { @@ -1861,7 +2085,7 @@ public class MultiUserChat { * @param oldRole the previous role of the user in the room before receiving the new presence * @param newRole the new role of the user in the room after receiving the new presence * @param isUserModification whether the received presence is about your user in the room or not - * @param from the participant whose role in the room has changed + * @param from the occupant whose role in the room has changed * (e.g. room@conference.jabber.org/nick). */ private void checkRoleModifications( @@ -1963,7 +2187,7 @@ public class MultiUserChat { * @param newAffiliation the new affiliation of the user in the room after receiving the new * presence * @param isUserModification whether the received presence is about your user in the room or not - * @param from the participant whose role in the room has changed + * @param from the occupant whose role in the room has changed * (e.g. room@conference.jabber.org/nick). */ private void checkAffiliationModifications( @@ -2044,9 +2268,9 @@ public class MultiUserChat { boolean isUserModification, MUCUser mucUser, String from) { - // Check if a participant was kicked from the room + // Check if an occupant was kicked from the room if ("307".equals(code)) { - // Check if this participant was kicked + // Check if this occupant was kicked if (isUserModification) { joined = false; @@ -2054,8 +2278,8 @@ public class MultiUserChat { "kicked", new Object[] { mucUser.getItem().getActor(), mucUser.getItem().getReason()}); - // Reset participant information. - participantsMap = new HashMap(); + // Reset occupant information. + occupantsMap = new HashMap(); nickname = null; userHasLeft(); } @@ -2065,7 +2289,7 @@ public class MultiUserChat { } // A user was banned from the room else if ("301".equals(code)) { - // Check if this participant was banned + // Check if this occupant was banned if (isUserModification) { joined = false; @@ -2073,8 +2297,8 @@ public class MultiUserChat { "banned", new Object[] { mucUser.getItem().getActor(), mucUser.getItem().getReason()}); - // Reset participant information. - participantsMap = new HashMap(); + // Reset occupant information. + occupantsMap = new HashMap(); nickname = null; userHasLeft(); } @@ -2085,19 +2309,19 @@ public class MultiUserChat { } // A user's membership was revoked from the room else if ("321".equals(code)) { - // Check if this participant's membership was revoked + // Check if this occupant's membership was revoked if (isUserModification) { joined = false; fireUserStatusListeners("membershipRevoked", new Object[] {}); - // Reset participant information. - participantsMap = new HashMap(); + // Reset occupant information. + occupantsMap = new HashMap(); nickname = null; userHasLeft(); } } - // A participant has changed his nickname in the room + // A occupant has changed his nickname in the room else if ("303".equals(code)) { fireParticipantStatusListeners("nicknameChanged", mucUser.getItem().getNick()); } diff --git a/test/org/jivesoftware/smackx/muc/MultiUserChatTest.java b/test/org/jivesoftware/smackx/muc/MultiUserChatTest.java index e3d6c0211..dac5d40aa 100644 --- a/test/org/jivesoftware/smackx/muc/MultiUserChatTest.java +++ b/test/org/jivesoftware/smackx/muc/MultiUserChatTest.java @@ -55,6 +55,7 @@ package org.jivesoftware.smackx.muc; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Collection; import org.jivesoftware.smack.*; import org.jivesoftware.smack.filter.*; @@ -94,7 +95,7 @@ public class MultiUserChatTest extends SmackTestCase { Thread.sleep(400); // User1 checks the presence of user2 in the room - Presence presence = muc.getParticipantPresence(room + "/testbot2"); + Presence presence = muc.getOccupantPresence(room + "/testbot2"); assertNotNull("Presence of user2 in room is missing", presence); assertEquals( "Presence mode of user2 is wrong", @@ -115,8 +116,8 @@ public class MultiUserChatTest extends SmackTestCase { groupchat.leave(); Thread.sleep(300); // User1 checks the that user2 is not present in the room - presence = muc.getParticipantPresence(room + "/testbot2"); - assertNull("Presence of participant testbot2 still exists", presence); + Occupant occupant = muc.getOccupant(room + "/testbot2"); + assertNull("Occupant testbot2 still exists", occupant); } catch (Exception e) { e.printStackTrace(); @@ -191,7 +192,7 @@ public class MultiUserChatTest extends SmackTestCase { Thread.sleep(400); // User1 checks the presence of user2 in the room - Presence presence = muc.getParticipantPresence(room + "/testbot2"); + Presence presence = muc.getOccupantPresence(room + "/testbot2"); assertNotNull("Presence of user2 in room is missing", presence); assertEquals( "Presence mode of user2 is wrong", @@ -202,7 +203,7 @@ public class MultiUserChatTest extends SmackTestCase { muc2.changeAvailabilityStatus("Gone to have lunch", Presence.Mode.AWAY); Thread.sleep(200); // User1 checks the presence of user2 in the room - presence = muc.getParticipantPresence(room + "/testbot2"); + presence = muc.getOccupantPresence(room + "/testbot2"); assertNotNull("Presence of user2 in room is missing", presence); assertEquals("Presence mode of user2 is wrong", Presence.Mode.AWAY, presence.getMode()); assertEquals( @@ -214,9 +215,9 @@ public class MultiUserChatTest extends SmackTestCase { muc2.changeNickname("testbotII"); Thread.sleep(200); // User1 checks the presence of user2 in the room - presence = muc.getParticipantPresence(room + "/testbot2"); + presence = muc.getOccupantPresence(room + "/testbot2"); assertNull("Presence of participant testbot2 still exists", presence); - presence = muc.getParticipantPresence(room + "/testbotII"); + presence = muc.getOccupantPresence(room + "/testbotII"); assertNotNull("Presence of participant testbotII does not exist", presence); assertEquals( "Presence of participant testbotII has a wrong from", @@ -227,7 +228,7 @@ public class MultiUserChatTest extends SmackTestCase { muc2.leave(); Thread.sleep(250); // User1 checks the presence of user2 in the room - presence = muc.getParticipantPresence(room + "/testbotII"); + presence = muc.getOccupantPresence(room + "/testbotII"); assertNull("Presence of participant testbotII still exists", presence); } @@ -573,7 +574,7 @@ public class MultiUserChatTest extends SmackTestCase { assertNull( "User2 wasn't kicked from the room", - muc.getParticipantPresence(room + "/testbot2")); + muc.getOccupant(room + "/testbot2")); assertFalse("User2 thinks that he's still in the room", muc2.isJoined()); @@ -650,7 +651,7 @@ public class MultiUserChatTest extends SmackTestCase { assertNull( "User2 wasn't banned from the room", - muc.getParticipantPresence(room + "/testbot2")); + muc.getOccupant(room + "/testbot2")); assertFalse("User2 thinks that he's still in the room", muc2.isJoined()); @@ -1397,6 +1398,115 @@ public class MultiUserChatTest extends SmackTestCase { } } + public void testGetAffiliationList() { + try { + // User2 joins the new room + MultiUserChat muc2 = new MultiUserChat(getConnection(1), room); + muc2.join("testbot2"); + + // User3 joins the new room + MultiUserChat muc3 = new MultiUserChat(getConnection(2), room); + muc3.join("testbot3"); + + // Grant ownership privileges to user2 + muc.grantOwnership(getBareJID(1)); + // Grant moderator privileges to user3 + muc.grantModerator("testbot3"); + + // Check that the owner list is correct + Collection affiliates = muc.getOwners(); + assertEquals("Room does not have 2 owners", 2, affiliates.size()); + for (Iterator it =affiliates.iterator(); it.hasNext();) { + Affiliate affiliate = (Affiliate)it.next(); + if (getBareJID(0).equals(affiliate.getJid())) { + assertEquals("Wrong affiliation", "owner", affiliate.getAffiliation()); + assertEquals("Wrong role", "moderator", affiliate.getRole()); + assertEquals("Wrong nick", "testbot", affiliate.getNick()); + } + else if (getBareJID(1).equals(affiliate.getJid())) { + assertEquals("Wrong affiliation", "owner", affiliate.getAffiliation()); + assertEquals("Wrong role", "moderator", affiliate.getRole()); + assertEquals("Wrong nick", "testbot2", affiliate.getNick()); + } + else { + fail("Unknown owner " + affiliate.getJid()); + } + } + + // Check that the admin list is correct + affiliates = muc.getAdmins(); + assertEquals("Room has admins", 0, affiliates.size()); + + // Check that the members list is correct + affiliates = muc.getMembers(); + assertEquals("Room has admins", 0, affiliates.size()); + // Grant membership privileges to user2 + muc.grantMembership(getBareJID(1)); + // Check that the members list is correct + affiliates = muc.getMembers(); + assertEquals("Room has admins", 1, affiliates.size()); + Affiliate affiliate = (Affiliate) affiliates.iterator().next(); + assertEquals("Wrong member jid", getBareJID(1), affiliate.getJid()); + + // Check that the members list is correct + affiliates = muc.getOutcasts(); + assertEquals("Room has outcasts", 0, affiliates.size()); + + // Check that the moderator list is correct + Collection occupants = muc.getModerators(); + assertEquals("Room does not have 2 moderators", 2, occupants.size()); + for (Iterator it =occupants.iterator(); it.hasNext();) { + Occupant occupant = (Occupant)it.next(); + if (getFullJID(0).equals(occupant.getJid())) { + assertEquals("Wrong affiliation", "owner", occupant.getAffiliation()); + assertEquals("Wrong role", "moderator", occupant.getRole()); + assertEquals("Wrong nick", "testbot", occupant.getNick()); + } + else if (getFullJID(2).equals(occupant.getJid())) { + assertEquals("Wrong affiliation", "none", occupant.getAffiliation()); + assertEquals("Wrong role", "moderator", occupant.getRole()); + assertEquals("Wrong nick", "testbot3", occupant.getNick()); + } + else { + fail("Unknown moderator " + occupant.getJid()); + } + } + + // Check that the participants list is correct + occupants = muc.getParticipants(); + assertEquals("Room does not have 1 participant", 1, occupants.size()); + Occupant occupant = (Occupant) occupants.iterator().next(); + assertEquals("Wrong participant jid", getFullJID(1), occupant.getJid()); + + Thread.sleep(500); + + // Check that we can retrieve Occupant information of a given user + occupant = muc.getOccupant(room + "/testbot2"); + assertNotNull("Occupant was not found", occupant); + assertEquals("Wrong occupant jid", getFullJID(1), occupant.getJid()); + assertEquals("Wrong occupant affiliation", "member", occupant.getAffiliation()); + assertEquals("Wrong occupant role", "participant", occupant.getRole()); + + try { + // Check whether a member can get the list of owners + muc2.getOwners(); + fail("User2 was able to get the list of owners"); + } + catch (XMPPException e) { + XMPPError xmppError = e.getXMPPError(); + assertNotNull("No XMPPError was received getting the list of owners", xmppError); + assertEquals( + "A member was able to get the list of owners", + 403, + xmppError.getCode()); + } + } + 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();