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