mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-27 00:32:07 +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:
parent
48fac74878
commit
998172b111
1 changed files with 42 additions and 73 deletions
|
@ -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.
|
||||||
|
|
Loading…
Reference in a new issue