Commit 7050fe49 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gaston

1. Removed unnecessary locks/synchronized blocks.

2. Many collections were replaced with its similar new concurrent version.
3. Code modified to take advantage of Generics and new "for" format.


git-svn-id: http://svn.igniterealtime.org/svn/repos/messenger/trunk@224 b35dd754-fafc-0310-a699-88a17e54d16e
parent fbdf2a96
......@@ -13,6 +13,7 @@ package org.jivesoftware.messenger.muc.spi;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
......@@ -93,6 +94,14 @@ public class MUCRoomImpl implements MUCRoom {
*/
long endTime;
/**
* After a room has been destroyed it may remain in memory but it won't be possible to use it.
* When a room is destroyed it is immediately removed from the MultiUserChatServer but it's
* possible that while the room was being destroyed it was being used by another thread so we
* need to protect the room under these rare circumstances.
*/
boolean isDestroyed = false;
/**
* ChatRoomHistory object.
*/
......@@ -111,12 +120,12 @@ public class MUCRoomImpl implements MUCRoom {
/**
* List of chatroom's owner. The list contains only bare jid.
*/
List<String> owners = new ArrayList<String>();
List<String> owners = new CopyOnWriteArrayList<String>();
/**
* List of chatroom's admin. The list contains only bare jid.
*/
List<String> admins = new ArrayList<String>();
List<String> admins = new CopyOnWriteArrayList<String>();
/**
* List of chatroom's members. The list contains only bare jid.
......@@ -126,7 +135,7 @@ public class MUCRoomImpl implements MUCRoom {
/**
* List of chatroom's outcast. The list contains only bare jid of not allowed users.
*/
private List<String> outcasts = new ArrayList<String>();
private List<String> outcasts = new CopyOnWriteArrayList<String>();
/**
* The natural language name of the room.
......@@ -293,56 +302,31 @@ public class MUCRoomImpl implements MUCRoom {
}
public MUCRole getOccupant(String nickname) throws UserNotFoundException {
lock.readLock().lock();
try {
MUCRole role = occupants.get(nickname.toLowerCase());
if (role != null) {
return role;
}
throw new UserNotFoundException();
}
finally {
lock.readLock().unlock();
}
}
public List<MUCRole> getOccupantsByBareJID(String jid) throws UserNotFoundException {
lock.readLock().lock();
try {
List<MUCRole> roles = occupantsByBareJID.get(jid);
if (roles != null && !roles.isEmpty()) {
return roles;
return (List<MUCRole>)Collections.unmodifiableCollection(roles);
}
throw new UserNotFoundException();
}
finally {
lock.readLock().unlock();
}
}
public MUCRole getOccupantByFullJID(String jid) throws UserNotFoundException {
lock.readLock().lock();
try {
MUCRole role = occupantsByFullJID.get(jid);
if (role != null) {
return role;
}
throw new UserNotFoundException();
}
finally {
lock.readLock().unlock();
}
}
public Iterator<MUCRole> getOccupants() throws UnauthorizedException {
lock.readLock().lock();
try {
List<MUCRole> list = new ArrayList<MUCRole>(occupants.values());
return list.iterator();
}
finally {
lock.readLock().unlock();
}
return occupants.values().iterator();
}
public int getOccupantsCount() {
......@@ -350,28 +334,16 @@ public class MUCRoomImpl implements MUCRoom {
}
public boolean hasOccupant(String nickname) throws UnauthorizedException {
lock.readLock().lock();
try {
return occupants.containsKey(nickname.toLowerCase());
}
finally {
lock.readLock().unlock();
}
}
public String getReservedNickname(String bareJID) {
lock.readLock().lock();
try {
String answer = members.get(bareJID);
if (answer == null || answer.trim().length() == 0) {
return null;
}
return answer;
}
finally {
lock.readLock().unlock();
}
}
public int getAffiliation(String bareJID) {
if (owners.contains(bareJID)) {
......@@ -397,7 +369,7 @@ public class MUCRoomImpl implements MUCRoom {
lock.writeLock().lock();
try {
// If the room has a limit of max user then check if the limit was reached
if (getMaxUsers() > 0 && getOccupantsCount() >= getMaxUsers()) {
if (isDestroyed || (getMaxUsers() > 0 && getOccupantsCount() >= getMaxUsers())) {
throw new NotAllowedException();
}
boolean isOwner = owners.contains(user.getAddress().toBareStringPrep());
......@@ -469,9 +441,7 @@ public class MUCRoomImpl implements MUCRoom {
(MUCUserImpl) user, router);
// Send presence of existing occupants to new occupant
Iterator iter = occupants.values().iterator();
while (iter.hasNext()) {
MUCRole occupantsRole = (MUCRole) iter.next();
for (MUCRole occupantsRole : occupants.values()) {
Presence occupantsPresence = (Presence) occupantsRole.getPresence()
.createDeepCopy();
occupantsPresence.setSender(occupantsRole.getRoleAddress());
......@@ -670,6 +640,8 @@ public class MUCRoomImpl implements MUCRoom {
MUCPersistenceManager.deleteFromDB(this);
server.removeChatRoom(name);
// Set that the room has been destroyed
isDestroyed = true;
}
finally {
lock.writeLock().unlock();
......@@ -785,8 +757,6 @@ public class MUCRoomImpl implements MUCRoom {
}
jid = frag.getProperty("x.item:jid");
}
lock.readLock().lock();
try {
for (MUCRole occupant : occupants.values()) {
presence.setRecipient(occupant.getChatUser().getAddress());
// Don't include the occupant's JID if the room is semi-anon and the new occupant
......@@ -802,24 +772,15 @@ public class MUCRoomImpl implements MUCRoom {
router.route(presence);
}
}
finally {
lock.readLock().unlock();
}
}
private void broadcast(Message message) {
lock.readLock().lock();
try {
Iterator itr = occupants.values().iterator();
while (itr.hasNext()) {
MUCRole occupant = (MUCRole) itr.next();
for (MUCRole occupant : occupants.values()) {
message.setRecipient(occupant.getChatUser().getAddress());
router.route(message);
}
if (isLogEnabled()) {
lock.readLock().unlock();
lock.writeLock().lock();
try {
MUCRole senderRole;
XMPPAddress senderAddress;
senderRole = occupants.get(message.getSender().getResourcePrep());
......@@ -834,11 +795,6 @@ public class MUCRoomImpl implements MUCRoom {
// Log the conversation
server.logConversation(this, message, senderAddress);
}
finally {
lock.writeLock().unlock();
lock.readLock().lock();
}
}
}
finally {
lock.readLock().unlock();
......@@ -947,9 +903,9 @@ public class MUCRoomImpl implements MUCRoom {
* @throws NotAllowedException If trying to change the moderator role to an owner or an admin or
* if trying to ban an owner or an administrator.
*/
private List changeOccupantAffiliation(String bareJID, int newAffiliation, int newRole)
private List<Presence> changeOccupantAffiliation(String bareJID, int newAffiliation, int newRole)
throws NotAllowedException {
List presences = new ArrayList();
List<Presence> presences = new ArrayList<Presence>();
// Get all the roles (i.e. occupants) of this user based on his/her bare JID
List roles = occupantsByBareJID.get(bareJID);
if (roles == null) {
......@@ -1008,7 +964,7 @@ public class MUCRoomImpl implements MUCRoom {
owners.add(bareJID);
}
public List addOwner(String bareJID, MUCRole sendRole) throws ForbiddenException {
public List<Presence> addOwner(String bareJID, MUCRole sendRole) throws ForbiddenException {
int oldAffiliation = MUCRole.NONE;
if (MUCRole.OWNER != sendRole.getAffiliation()) {
throw new ForbiddenException();
......@@ -1045,7 +1001,7 @@ public class MUCRoomImpl implements MUCRoom {
return owners.remove(bareJID);
}
public List addAdmin(String bareJID, MUCRole sendRole) throws ForbiddenException,
public List<Presence> addAdmin(String bareJID, MUCRole sendRole) throws ForbiddenException,
ConflictException {
int oldAffiliation = MUCRole.NONE;
if (MUCRole.OWNER != sendRole.getAffiliation()) {
......@@ -1087,7 +1043,7 @@ public class MUCRoomImpl implements MUCRoom {
return admins.remove(bareJID);
}
public List addMember(String bareJID, String nickname, MUCRole sendRole)
public List<Presence> addMember(String bareJID, String nickname, MUCRole sendRole)
throws ForbiddenException, ConflictException {
int oldAffiliation = (members.containsKey(bareJID) ? MUCRole.MEMBER : MUCRole.NONE);
if (isInvitationRequiredToEnter()) {
......@@ -1150,7 +1106,7 @@ public class MUCRoomImpl implements MUCRoom {
return answer;
}
public List addOutcast(String bareJID, String reason, MUCRole senderRole)
public List<Presence> addOutcast(String bareJID, String reason, MUCRole senderRole)
throws NotAllowedException, ForbiddenException, ConflictException {
int oldAffiliation = MUCRole.NONE;
if (MUCRole.ADMINISTRATOR != senderRole.getAffiliation()
......@@ -1163,7 +1119,7 @@ public class MUCRoomImpl implements MUCRoom {
}
// Update the presence with the new affiliation and inform all occupants
String actorJID = senderRole.getChatUser().getAddress().toBareStringPrep();
List updatedPresences = changeOccupantAffiliation(
List<Presence> updatedPresences = changeOccupantAffiliation(
bareJID,
MUCRole.OUTCAST,
MUCRole.NONE_ROLE);
......@@ -1216,7 +1172,7 @@ public class MUCRoomImpl implements MUCRoom {
return outcasts.remove(bareJID);
}
public List addNone(String bareJID, MUCRole senderRole) throws ForbiddenException,
public List<Presence> addNone(String bareJID, MUCRole senderRole) throws ForbiddenException,
ConflictException {
int oldAffiliation = MUCRole.NONE;
if (MUCRole.ADMINISTRATOR != senderRole.getAffiliation()
......@@ -1227,7 +1183,7 @@ public class MUCRoomImpl implements MUCRoom {
if (owners.contains(bareJID) && owners.size() == 1) {
throw new ConflictException();
}
List updatedPresences = null;
List<Presence> updatedPresences = null;
boolean wasMember = members.containsKey(bareJID);
// Remove the user from ALL the affiliation lists
if (removeOwner(bareJID)) {
......@@ -1304,29 +1260,19 @@ public class MUCRoomImpl implements MUCRoom {
}
public void nicknameChanged(String oldNick, String newNick) {
lock.writeLock().lock();
try {
// Associate the existing MUCRole with the new nickname
occupants.put(newNick.toLowerCase(), occupants.get(oldNick.toLowerCase()));
// Remove the old nickname
occupants.remove(oldNick.toLowerCase());
}
finally {
lock.writeLock().unlock();
}
}
public void changeSubject(Message packet, MUCRole role) throws UnauthorizedException,
ForbiddenException {
if ((canOccupantsChangeSubject() && role.getRole() > MUCRole.VISITOR) ||
MUCRole.MODERATOR == role.getRole()) {
lock.writeLock().lock();
try {
// Set the new subject to the room
subject = packet.getSubject();
MUCPersistenceManager.updateRoomSubject(this, subject);
}
finally {
lock.writeLock().unlock();
}
// Notify all the occupants that the subject has changed
packet.setSender(role.getRoleAddress());
send(packet);
......@@ -1405,49 +1351,23 @@ public class MUCRoomImpl implements MUCRoom {
}
public Iterator<String> getOwners() {
lock.readLock().lock();
try {
return Collections.unmodifiableCollection(owners).iterator();
}
finally {
lock.readLock().unlock();
}
}
public Iterator<String> getAdmins() {
lock.readLock().lock();
try {
return Collections.unmodifiableCollection(admins).iterator();
}
finally {
lock.readLock().unlock();
}
}
public Iterator<String> getMembers() {
lock.readLock().lock();
try {
return Collections.unmodifiableMap(members).keySet().iterator();
}
finally {
lock.readLock().unlock();
}
}
public Iterator<String> getOutcasts() {
lock.readLock().lock();
try {
return outcasts.iterator();
}
finally {
lock.readLock().unlock();
}
return Collections.unmodifiableCollection(outcasts).iterator();
}
public Iterator<MUCRole> getModerators() {
lock.readLock().lock();
try {
ArrayList<MUCRole> moderators = new ArrayList<MUCRole>();
List<MUCRole> moderators = new ArrayList<MUCRole>();
for (MUCRole role : occupants.values()) {
if (MUCRole.MODERATOR == role.getRole()) {
moderators.add(role);
......@@ -1455,15 +1375,9 @@ public class MUCRoomImpl implements MUCRoom {
}
return moderators.iterator();
}
finally {
lock.readLock().unlock();
}
}
public Iterator<MUCRole> getParticipants() {
lock.readLock().lock();
try {
ArrayList<MUCRole> participants = new ArrayList<MUCRole>();
List<MUCRole> participants = new ArrayList<MUCRole>();
for (MUCRole role : occupants.values()) {
if (MUCRole.PARTICIPANT == role.getRole()) {
participants.add(role);
......@@ -1471,10 +1385,6 @@ public class MUCRoomImpl implements MUCRoom {
}
return participants.iterator();
}
finally {
lock.readLock().unlock();
}
}
public Presence addModerator(String fullJID, MUCRole senderRole) throws ForbiddenException {
if (MUCRole.ADMINISTRATOR != senderRole.getAffiliation()
......@@ -1685,7 +1595,7 @@ public class MUCRoomImpl implements MUCRoom {
}
public boolean isPublicRoom() {
return publicRoom;
return !isDestroyed && publicRoom;
}
public void setPublicRoom(boolean publicRoom) {
......@@ -1728,12 +1638,10 @@ public class MUCRoomImpl implements MUCRoom {
router.route(message);
}
public List addAdmins(List newAdmins, MUCRole senderRole) throws ForbiddenException,
ConflictException {
List answer = new ArrayList(newAdmins.size());
String newAdmin;
for (Iterator it = newAdmins.iterator(); it.hasNext();) {
newAdmin = (String) it.next();
public List<Presence> addAdmins(List<String> newAdmins, MUCRole senderRole)
throws ForbiddenException, ConflictException {
List<Presence> answer = new ArrayList<Presence>(newAdmins.size());
for (String newAdmin : newAdmins) {
if (newAdmin.trim().length() > 0 && !admins.contains(newAdmin)) {
answer.addAll(addAdmin(newAdmin, senderRole));
}
......@@ -1741,11 +1649,10 @@ public class MUCRoomImpl implements MUCRoom {
return answer;
}
public List addOwners(List newOwners, MUCRole senderRole) throws ForbiddenException {
List answer = new ArrayList(newOwners.size());
String newOwner;
for (Iterator it = newOwners.iterator(); it.hasNext();) {
newOwner = (String) it.next();
public List<Presence> addOwners(List<String> newOwners, MUCRole senderRole)
throws ForbiddenException {
List<Presence> answer = new ArrayList<Presence>(newOwners.size());
for (String newOwner : newOwners) {
if (newOwner.trim().length() > 0 && !owners.contains(newOwner)) {
answer.addAll(addOwner(newOwner, senderRole));
}
......@@ -1760,19 +1667,19 @@ public class MUCRoomImpl implements MUCRoom {
// Set that the room is now in the DB
savedToDB = true;
// Save the existing room owners to the DB
for (Iterator it=owners.iterator(); it.hasNext();) {
for (String owner : owners) {
MUCPersistenceManager.saveAffiliationToDB(
this,
(String) it.next(),
owner,
null,
MUCRole.OWNER,
MUCRole.NONE);
}
// Save the existing room admins to the DB
for (Iterator it=admins.iterator(); it.hasNext();) {
for (String admin : admins) {
MUCPersistenceManager.saveAffiliationToDB(
this,
(String) it.next(),
admin,
null,
MUCRole.ADMINISTRATOR,
MUCRole.NONE);
......@@ -1784,10 +1691,10 @@ public class MUCRoomImpl implements MUCRoom {
.get(bareJID), MUCRole.MEMBER, MUCRole.NONE);
}
// Save the existing room outcasts to the DB
for (Iterator it=outcasts.iterator(); it.hasNext();) {
for (String outcast : outcasts) {
MUCPersistenceManager.saveAffiliationToDB(
this,
(String) it.next(),
outcast,
null,
MUCRole.OUTCAST,
MUCRole.NONE);
......
......@@ -30,6 +30,7 @@ import org.jivesoftware.messenger.user.UserNotFoundException;
import java.util.*;
import java.util.LinkedList;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
......@@ -88,7 +89,7 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
/**
* chatrooms managed by this manager, table: key room name (String); value ChatRoom
*/
private Map<String,MUCRoom> rooms = Collections.synchronizedMap(new HashMap<String,MUCRoom>());
private Map<String,MUCRoom> rooms = new ConcurrentHashMap<String,MUCRoom>();
/**
* Cache for the persistent room surrogates. There will be a persistent room surrogate for each
......@@ -100,7 +101,7 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
/**
* chat users managed by this manager, table: key user jid (XMPPAddress); value ChatUser
*/
private Map users = Collections.synchronizedMap(new HashMap());
private Map<XMPPAddress, MUCUser> users = new ConcurrentHashMap<XMPPAddress, MUCUser>();
private HistoryStrategy historyStrategy;
private RoutingTable routingTable = null;
......@@ -146,7 +147,7 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
/**
* Queue that holds the messages to log for the rooms that need to log their conversations.
*/
private Queue logQueue = new LinkedBlockingQueue();
private Queue<ConversationLogEntry> logQueue = new LinkedBlockingQueue<ConversationLogEntry>();
/**
* Create a new group chat server.
......@@ -171,28 +172,18 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
* Remove any user that has been idle for longer than the user timeout time.
*/
public void run() {
synchronized (users) {
try {
checkForTimedOutUsers();
}
catch (ConcurrentModificationException e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
}
}
}
private void checkForTimedOutUsers() throws ConcurrentModificationException {
private void checkForTimedOutUsers() {
// Do nothing if this feature is disabled (i.e USER_IDLE equals -1)
if (USER_IDLE == -1) {
return;
}
final long deadline = System.currentTimeMillis() - USER_IDLE;
final Map userMap = new HashMap(users);
final Iterator userIter = userMap.values().iterator();
while (userIter.hasNext()) {
for (MUCUser user : users.values()) {
try {
MUCUser user = (MUCUser) userIter.next();
if (user.getLastPacketTime() < deadline) {
// Kick the user from all the rooms that he/she had previuosly joined
Iterator<MUCRole> roles = user.getRoles();
......@@ -217,7 +208,7 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
}
}
}
catch (Exception e) {
catch (Throwable e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
}
......@@ -228,7 +219,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
*/
private class LogConversationTask extends TimerTask {
public void run() {
synchronized (users) {
try {
logConversation();
}
......@@ -237,13 +227,12 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
}
}
}
}
private void logConversation() {
ConversationLogEntry entry = null;
boolean success = false;
for (int index = 0; index <= LOG_BATCH_SIZE && !logQueue.isEmpty(); index++) {
entry = (ConversationLogEntry)logQueue.poll();
entry = logQueue.poll();
if (entry != null) {
success = MUCPersistenceManager.saveConversationLogEntry(entry);
if (!success) {
......@@ -287,20 +276,20 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
}
public MUCRoom getChatRoom(String roomName) {
synchronized (rooms) {
MUCRoom answer = rooms.get(roomName.toLowerCase());
// If the room is not in memory check if there exists a surrogate of the room. There
// will be a surrogate if and only if exists an room in the database for the requested
// room name
if (answer == null) {
synchronized (persistentRoomSurrogateCache) {
if (persistentRoomSurrogateCache.size() == 0) {
populateRoomSurrogateCache();
}
}
answer = (MUCRoom) persistentRoomSurrogateCache.get(roomName);
}
return answer;
}
}
private void populateRoomSurrogateCache() {
for (MUCRoom room : MUCPersistenceManager.getRoomSurrogates(this, router)) {
......@@ -313,8 +302,8 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
}
public void removeChatRoom(String roomName) throws UnauthorizedException {
synchronized (rooms) {
final MUCRoom room = rooms.get(roomName.toLowerCase());
final MUCRoom room = rooms.remove(roomName.toLowerCase());
if (room != null) {
final long chatLength = room.getChatLength();
totalChatTime += chatLength;
// Update the database to indicate that the room is no longer in memory (only if the
......@@ -329,7 +318,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
// Just force to expire old entries since the cache doesn't have a clean-up thread
persistentRoomSurrogateCache.size();
}
rooms.remove(roomName.toLowerCase());
}
}
......@@ -342,12 +330,11 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
}
public void removeUser(XMPPAddress jabberID) throws UnauthorizedException {
synchronized (users) {
MUCUser user = (MUCUser)users.remove(jabberID);
MUCUser user = users.remove(jabberID);
if (user != null) {
Iterator roles = user.getRoles();
Iterator<MUCRole> roles = user.getRoles();
while (roles.hasNext()) {
MUCRole role = (MUCRole)roles.next();
MUCRole role = roles.next();
try {
role.getChatRoom().leaveRoom(role.getNickname());
}
......@@ -357,7 +344,6 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
}
}
}
}
public MUCUser getChatUser(XMPPAddress userjid) throws UnauthorizedException,
UserNotFoundException {
......@@ -366,7 +352,7 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
}
MUCUser user = null;
synchronized (users) {
user = (MUCUser) users.get(userjid);
user = users.get(userjid);
if (user == null) {
user = new MUCUserImpl(this, router, userjid);
users.put(userjid, user);
......@@ -376,11 +362,8 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
}
public void serverBroadcast(String msg) throws UnauthorizedException {
synchronized (rooms) {
Iterator itr = rooms.values().iterator();
while (itr.hasNext()) {
((MUCRoom)itr.next()).serverBroadcast(msg);
}
for (MUCRoom room : rooms.values()) {
room.serverBroadcast(msg);
}
}
......@@ -782,13 +765,9 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
throws UnauthorizedException {
List answer = new ArrayList();
if (name == null && node == null) {
// Answer all the public rooms as items
synchronized (rooms) {
Iterator itr = rooms.values().iterator();
MUCRoom room;
Element item;
while (itr.hasNext()) {
room = (MUCRoom)itr.next();
// Answer all the public rooms as items
for (MUCRoom room : rooms.values()) {
if (room.isPublicRoom()) {
item = DocumentHelper.createElement("item");
item.addAttribute("jid", room.getRole().getRoleAddress().toStringPrep());
......@@ -799,11 +778,14 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
}
// Load the room surrogates for persistent rooms that aren't in memory (if the cache
// is still empty)
synchronized(persistentRoomSurrogateCache) {
if (persistentRoomSurrogateCache.size() == 0) {
populateRoomSurrogateCache();
}
}
// Add items for each room surrogate (persistent room that is not in memory at
// the moment)
MUCRoom room;
for (Iterator it=persistentRoomSurrogateCache.values().iterator(); it.hasNext();) {
room = (MUCRoom)it.next();
item = DocumentHelper.createElement("item");
......@@ -813,15 +795,14 @@ public class MultiUserChatServerImpl extends BasicModule implements MultiUserCha
answer.add(item);
}
}
}
else if (name != null && node == null) {
// Answer the room occupants as items if that info is publicly available
MUCRoom room = getChatRoom(name);
if (room != null && room.isPublicRoom()) {
MUCRole role;
Element item;
for (Iterator members = room.getOccupants(); members.hasNext();) {
role = (MUCRole)members.next();
for (Iterator<MUCRole> members = room.getOccupants(); members.hasNext();) {
role = members.next();
item = DocumentHelper.createElement("item");
item.addAttribute("jid", role.getRoleAddress().toStringPrep());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment