1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-11-23 04:22:05 +01:00

Removed extra synchronization (SMACK-177).

git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@5645 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Matt Tucker 2006-10-07 23:16:20 +00:00 committed by matt
parent 48fac74878
commit 998172b111

View file

@ -31,6 +31,7 @@ import org.jivesoftware.smack.util.StringUtils;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/** /**
* Represents a user's roster, which is the collection of users a person receives * Represents a user's roster, which is the collection of users a person receives
@ -99,10 +100,10 @@ public class Roster implements ConnectionListener {
Roster(final XMPPConnection connection) { Roster(final XMPPConnection connection) {
this.connection = connection; this.connection = connection;
groups = new ConcurrentHashMap<String,RosterGroup>(); groups = new ConcurrentHashMap<String,RosterGroup>();
unfiledEntries = new ArrayList<RosterEntry>(); unfiledEntries = new CopyOnWriteArrayList<RosterEntry>();
entries = new ArrayList<RosterEntry>(); entries = new CopyOnWriteArrayList<RosterEntry>();
rosterListeners = new ArrayList<RosterListener>(); rosterListeners = new CopyOnWriteArrayList<RosterListener>();
presenceMap = new HashMap<String, Map<String, Presence>>(); presenceMap = new ConcurrentHashMap<String, Map<String, Presence>>();
// Listen for any roster packets. // Listen for any roster packets.
PacketFilter rosterFilter = new PacketTypeFilter(RosterPacket.class); PacketFilter rosterFilter = new PacketTypeFilter(RosterPacket.class);
connection.addPacketListener(new RosterPacketListener(), rosterFilter); connection.addPacketListener(new RosterPacketListener(), rosterFilter);
@ -160,12 +161,10 @@ public class Roster implements ConnectionListener {
* @param rosterListener a roster listener. * @param rosterListener a roster listener.
*/ */
public void addRosterListener(RosterListener rosterListener) { public void addRosterListener(RosterListener rosterListener) {
synchronized (rosterListeners) {
if (!rosterListeners.contains(rosterListener)) { if (!rosterListeners.contains(rosterListener)) {
rosterListeners.add(rosterListener); rosterListeners.add(rosterListener);
} }
} }
}
/** /**
* Removes a listener from this roster. The listener will be fired anytime one or more * Removes a listener from this roster. The listener will be fired anytime one or more
@ -174,10 +173,8 @@ public class Roster implements ConnectionListener {
* @param rosterListener a roster listener. * @param rosterListener a roster listener.
*/ */
public void removeRosterListener(RosterListener rosterListener) { public void removeRosterListener(RosterListener rosterListener) {
synchronized (rosterListeners) {
rosterListeners.remove(rosterListener); rosterListeners.remove(rosterListener);
} }
}
/** /**
* Creates a new group.<p> * Creates a new group.<p>
@ -189,7 +186,6 @@ public class Roster implements ConnectionListener {
* @return a new group. * @return a new group.
*/ */
public RosterGroup createGroup(String name) { public RosterGroup createGroup(String name) {
synchronized (groups) {
if (groups.containsKey(name)) { if (groups.containsKey(name)) {
throw new IllegalArgumentException("Group with name " + name + " alread exists."); throw new IllegalArgumentException("Group with name " + name + " alread exists.");
} }
@ -197,7 +193,6 @@ public class Roster implements ConnectionListener {
groups.put(name, group); groups.put(name, group);
return group; return group;
} }
}
/** /**
* Creates a new roster entry and presence subscription. The server will asynchronously * Creates a new roster entry and presence subscription. The server will asynchronously
@ -207,6 +202,7 @@ public class Roster implements ConnectionListener {
* @param name the nickname of the user. * @param name the nickname of the user.
* @param groups the list of group names the entry will belong to, or <tt>null</tt> if the * @param groups the list of group names the entry will belong to, or <tt>null</tt> if the
* the roster entry won't belong to a group. * the roster entry won't belong to a group.
* @throws XMPPException if an XMPP exception occurs.
*/ */
public void createEntry(String user, String name, String [] groups) throws XMPPException { public void createEntry(String user, String name, String [] groups) throws XMPPException {
// Create and send roster entry creation packet. // Create and send roster entry creation packet.
@ -248,15 +244,14 @@ public class Roster implements ConnectionListener {
* to send an updated subscription status. * to send an updated subscription status.
* *
* @param entry a roster entry. * @param entry a roster entry.
* @throws XMPPException if an XMPP error occurs.
*/ */
public void removeEntry(RosterEntry entry) throws XMPPException { public void removeEntry(RosterEntry entry) throws XMPPException {
// Only remove the entry if it's in the entry list. // Only remove the entry if it's in the entry list.
// The actual removal logic takes place in RosterPacketListenerprocess>>Packet(Packet) // The actual removal logic takes place in RosterPacketListenerprocess>>Packet(Packet)
synchronized (entries) {
if (!entries.contains(entry)) { if (!entries.contains(entry)) {
return; return;
} }
}
RosterPacket packet = new RosterPacket(); RosterPacket packet = new RosterPacket();
packet.setType(IQ.Type.SET); packet.setType(IQ.Type.SET);
RosterPacket.Item item = RosterEntry.toRosterItem(entry); RosterPacket.Item item = RosterEntry.toRosterItem(entry);
@ -302,9 +297,8 @@ public class Roster implements ConnectionListener {
allEntries.addAll(rosterGroup.getEntries()); allEntries.addAll(rosterGroup.getEntries());
} }
// Add the roster unfiled entries to the answer // Add the roster unfiled entries to the answer
synchronized (unfiledEntries) {
allEntries.addAll(unfiledEntries); allEntries.addAll(unfiledEntries);
}
return Collections.unmodifiableCollection(allEntries); return Collections.unmodifiableCollection(allEntries);
} }
@ -334,10 +328,8 @@ public class Roster implements ConnectionListener {
* @return the number of unfiled entries in the roster. * @return the number of unfiled entries in the roster.
*/ */
public int getUnfiledEntryCount() { public int getUnfiledEntryCount() {
synchronized (unfiledEntries) {
return unfiledEntries.size(); return unfiledEntries.size();
} }
}
/** /**
* Returns an unmodifiable collection for the unfiled roster entries. An unfiled entry is * Returns an unmodifiable collection for the unfiled roster entries. An unfiled entry is
@ -346,9 +338,7 @@ public class Roster implements ConnectionListener {
* @return the unfiled roster entries. * @return the unfiled roster entries.
*/ */
public Collection<RosterEntry> getUnfiledEntries() { public Collection<RosterEntry> getUnfiledEntries() {
synchronized (unfiledEntries) { return Collections.unmodifiableList(unfiledEntries);
return Collections.unmodifiableList(new ArrayList<RosterEntry>(unfiledEntries));
}
} }
/** /**
@ -364,13 +354,11 @@ public class Roster implements ConnectionListener {
return null; return null;
} }
String userLowerCase = user.toLowerCase(); String userLowerCase = user.toLowerCase();
synchronized (entries) {
for (RosterEntry entry : entries) { for (RosterEntry entry : entries) {
if (entry.getUser().equals(userLowerCase)) { if (entry.getUser().equals(userLowerCase)) {
return entry; return entry;
} }
} }
}
return null; return null;
} }
@ -539,13 +527,9 @@ public class Roster implements ConnectionListener {
* @param deletedEntries the collection of address of the deleted contacts. * @param deletedEntries the collection of address of the deleted contacts.
*/ */
private void fireRosterChangedEvent(Collection addedEntries, Collection updatedEntries, private void fireRosterChangedEvent(Collection addedEntries, Collection updatedEntries,
Collection deletedEntries) { Collection deletedEntries)
RosterListener [] listeners; {
synchronized (rosterListeners) { for (RosterListener listener : rosterListeners) {
listeners = new RosterListener[rosterListeners.size()];
rosterListeners.toArray(listeners);
}
for (RosterListener listener : listeners) {
if (!addedEntries.isEmpty()) { if (!addedEntries.isEmpty()) {
listener.entriesAdded(addedEntries); listener.entriesAdded(addedEntries);
} }
@ -560,14 +544,11 @@ public class Roster implements ConnectionListener {
/** /**
* Fires roster presence changed event to roster listeners. * Fires roster presence changed event to roster listeners.
*
* @param user the user with a presence change.
*/ */
private void fireRosterPresenceEvent(String user) { private void fireRosterPresenceEvent(String user) {
RosterListener [] listeners; for (RosterListener listener : rosterListeners) {
synchronized (rosterListeners) {
listeners = new RosterListener[rosterListeners.size()];
rosterListeners.toArray(listeners);
}
for (RosterListener listener : listeners) {
listener.presenceChanged(user); listener.presenceChanged(user);
} }
} }
@ -624,14 +605,12 @@ public class Roster implements ConnectionListener {
userPresences.put(StringUtils.parseResource(from), presence); userPresences.put(StringUtils.parseResource(from), presence);
} }
// If the user is in the roster, fire an event. // If the user is in the roster, fire an event.
synchronized (entries) {
for (RosterEntry entry : entries) { for (RosterEntry entry : entries) {
if (entry.getUser().equals(key)) { if (entry.getUser().equals(key)) {
fireRosterPresenceEvent(from); fireRosterPresenceEvent(from);
} }
} }
} }
}
// If an "unavailable" packet, remove any entries in the presence map. // If an "unavailable" packet, remove any entries in the presence map.
else if (presence.getType() == Presence.Type.unavailable) { else if (presence.getType() == Presence.Type.unavailable) {
if (presenceMap.get(key) != null) { if (presenceMap.get(key) != null) {
@ -644,14 +623,12 @@ public class Roster implements ConnectionListener {
} }
} }
// If the user is in the roster, fire an event. // If the user is in the roster, fire an event.
synchronized (entries) {
for (RosterEntry entry : entries) { for (RosterEntry entry : entries) {
if (entry.getUser().equals(key)) { if (entry.getUser().equals(key)) {
fireRosterPresenceEvent(from); fireRosterPresenceEvent(from);
} }
} }
} }
}
else if (presence.getType() == Presence.Type.subscribe) { else if (presence.getType() == Presence.Type.subscribe) {
if (subscriptionMode == SubscriptionMode.accept_all) { if (subscriptionMode == SubscriptionMode.accept_all) {
// Accept all subscription requests. // Accept all subscription requests.
@ -705,11 +682,9 @@ public class Roster implements ConnectionListener {
entries.remove(entry); entries.remove(entry);
} }
// Remove the entry from the unfiled entry list. // Remove the entry from the unfiled entry list.
synchronized (unfiledEntries) {
if (unfiledEntries.contains(entry)) { if (unfiledEntries.contains(entry)) {
unfiledEntries.remove(entry); unfiledEntries.remove(entry);
} }
}
// Removing the user from the roster, so remove any presence information // Removing the user from the roster, so remove any presence information
// about them. // about them.
String key = StringUtils.parseName(item.getUser()) + "@" + String key = StringUtils.parseName(item.getUser()) + "@" +
@ -736,19 +711,15 @@ public class Roster implements ConnectionListener {
// If the roster entry belongs to any groups, remove it from the // If the roster entry belongs to any groups, remove it from the
// list of unfiled entries. // list of unfiled entries.
if (!item.getGroupNames().isEmpty()) { if (!item.getGroupNames().isEmpty()) {
synchronized (unfiledEntries) {
unfiledEntries.remove(entry); unfiledEntries.remove(entry);
} }
}
// Otherwise add it to the list of unfiled entries. // Otherwise add it to the list of unfiled entries.
else { else {
synchronized (unfiledEntries) {
if (!unfiledEntries.contains(entry)) { if (!unfiledEntries.contains(entry)) {
unfiledEntries.add(entry); unfiledEntries.add(entry);
} }
} }
} }
}
// Find the list of groups that the user currently belongs to. // Find the list of groups that the user currently belongs to.
List<String> currentGroupNames = new ArrayList<String>(); List<String> currentGroupNames = new ArrayList<String>();
@ -788,11 +759,9 @@ public class Roster implements ConnectionListener {
RosterGroup group = getGroup(groupName); RosterGroup group = getGroup(groupName);
group.removeEntryLocal(entry); group.removeEntryLocal(entry);
if (group.getEntryCount() == 0) { if (group.getEntryCount() == 0) {
synchronized (groups) {
groups.remove(groupName); groups.remove(groupName);
} }
} }
}
// Remove all the groups with no entries. We have to do this because // Remove all the groups with no entries. We have to do this because
// RosterGroup.removeEntry removes the entry immediately (locally) and the // RosterGroup.removeEntry removes the entry immediately (locally) and the
// group could remain empty. // group could remain empty.