1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-11-30 02:02:06 +01:00

1. UNDO: Protects the access for certain methods by waiting a few seconds when the roster has not been initialized yet

2. Provides a static method to set default subscription mode
3. Modifies RosterPacketListener to remove empty groups caused by local entry removals


git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@2212 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Gaston Dombiak 2004-01-18 14:17:13 +00:00 committed by gdombiak
parent 924c27d94c
commit cd1abe75c0

View file

@ -96,6 +96,12 @@ public class Roster {
*/ */
public static final int SUBSCRIPTION_MANUAL = 2; public static final int SUBSCRIPTION_MANUAL = 2;
/**
* The default subscription processing mode to use when a Roster is created. By default
* all subscription requests are automatically accepted.
*/
private static int defaulSubscriptionMode = SUBSCRIPTION_ACCEPT_ALL;
private XMPPConnection connection; private XMPPConnection connection;
private Map groups; private Map groups;
private List entries; private List entries;
@ -106,7 +112,31 @@ public class Roster {
// has been recieved and processed. // has been recieved and processed.
boolean rosterInitialized = false; boolean rosterInitialized = false;
private int subscriptionMode = SUBSCRIPTION_ACCEPT_ALL; private int subscriptionMode = getDefaulSubscriptionMode();
/**
* Returns the default subscription processing mode to use when a new Roster is created. The
* subscription processing mode dictates what action Smack will take when subscription
* requests from other users are made. The default subscription mode
* is {@link #SUBSCRIPTION_ACCEPT_ALL}.
*
* @return the default subscription mode to use for new Rosters
*/
public static int getDefaulSubscriptionMode() {
return defaulSubscriptionMode;
}
/**
* Sets the default subscription processing mode to use when a new Roster is created. The
* subscription processing mode dictates what action Smack will take when subscription
* requests from other users are made. The default subscription mode
* is {@link #SUBSCRIPTION_ACCEPT_ALL}.
*
* @param subscriptionMode the default subscription mode to use for new Rosters.
*/
public static void setDefaulSubscriptionMode(int subscriptionMode) {
defaulSubscriptionMode = subscriptionMode;
}
/** /**
* Creates a new roster. * Creates a new roster.
@ -166,7 +196,6 @@ public class Roster {
* Reloads the entire roster from the server. This is an asynchronous operation, * Reloads the entire roster from the server. This is an asynchronous operation,
* which means the method will return immediately, and the roster will be * which means the method will return immediately, and the roster will be
* reloaded at a later point when the server responds to the reload request. * reloaded at a later point when the server responds to the reload request.
*
*/ */
public void reload() { public void reload() {
connection.sendPacket(new RosterPacket()); connection.sendPacket(new RosterPacket());
@ -228,9 +257,6 @@ public class Roster {
* the roster entry won't belong to a group. * the roster entry won't belong to a group.
*/ */
public void createEntry(String user, String name, String [] groups) throws XMPPException { public void createEntry(String user, String name, String [] groups) throws XMPPException {
if (!rosterInitialized) {
waitUntilInitialized();
}
// Create and send roster entry creation packet. // Create and send roster entry creation packet.
RosterPacket rosterPacket = new RosterPacket(); RosterPacket rosterPacket = new RosterPacket();
rosterPacket.setType(IQ.Type.SET); rosterPacket.setType(IQ.Type.SET);
@ -335,9 +361,6 @@ public class Roster {
* @return the number of unfiled entries in the roster. * @return the number of unfiled entries in the roster.
*/ */
public int getUnfiledEntryCount() { public int getUnfiledEntryCount() {
if (!rosterInitialized) {
waitUntilInitialized();
}
synchronized (unfiledEntries) { synchronized (unfiledEntries) {
return unfiledEntries.size(); return unfiledEntries.size();
} }
@ -350,9 +373,6 @@ public class Roster {
* @return an iterator the unfiled roster entries. * @return an iterator the unfiled roster entries.
*/ */
public Iterator getUnfiledEntries() { public Iterator getUnfiledEntries() {
if (!rosterInitialized) {
waitUntilInitialized();
}
synchronized (unfiledEntries) { synchronized (unfiledEntries) {
return Collections.unmodifiableList(new ArrayList(unfiledEntries)).iterator(); return Collections.unmodifiableList(new ArrayList(unfiledEntries)).iterator();
} }
@ -369,9 +389,6 @@ public class Roster {
if (user == null) { if (user == null) {
return null; return null;
} }
if (!rosterInitialized) {
waitUntilInitialized();
}
// Roster entries never include a resource so remove the resource // Roster entries never include a resource so remove the resource
// if it's a part of the XMPP address. // if it's a part of the XMPP address.
user = StringUtils.parseBareAddress(user); user = StringUtils.parseBareAddress(user);
@ -396,9 +413,6 @@ public class Roster {
if (user == null) { if (user == null) {
return false; return false;
} }
if (!rosterInitialized) {
waitUntilInitialized();
}
// Roster entries never include a resource so remove the resource // Roster entries never include a resource so remove the resource
// if it's a part of the XMPP address. // if it's a part of the XMPP address.
user = StringUtils.parseBareAddress(user); user = StringUtils.parseBareAddress(user);
@ -443,39 +457,12 @@ public class Roster {
* @return an iterator for all roster groups. * @return an iterator for all roster groups.
*/ */
public Iterator getGroups() { public Iterator getGroups() {
if (!rosterInitialized) {
waitUntilInitialized();
}
synchronized (groups) { synchronized (groups) {
List groupsList = Collections.unmodifiableList(new ArrayList(groups.values())); List groupsList = Collections.unmodifiableList(new ArrayList(groups.values()));
return groupsList.iterator(); return groupsList.iterator();
} }
} }
/**
* Waits until the roster has been initialized or 2 seconds has elapsed. It is required to
* wait before the user can make use of the roster when for example this is the first time
* the user has asked for the entries after calling login and we want to wait up to 2 seconds
* for the server to send back the user's roster.<p>
*
* This behavior shields API users from having to worry about the fact that roster operations
* are asynchronous, although they'll still have to listen for changes to the roster.
*
*/
private void waitUntilInitialized() {
if (!rosterInitialized) {
int elapsed = 0;
while (!rosterInitialized && elapsed <= 2000) {
try {
Thread.sleep(500);
}
catch (Exception e) {
}
elapsed += 500;
}
}
}
/** /**
* Returns the presence info for a particular user, or <tt>null</tt> if the user * Returns the presence info for a particular user, or <tt>null</tt> if the user
* is unavailable (offline) or if no presence information is available, such as * is unavailable (offline) or if no presence information is available, such as
@ -708,12 +695,10 @@ public class Roster {
// Find the list of groups that the user currently belongs to. // Find the list of groups that the user currently belongs to.
List currentGroupNames = new ArrayList(); List currentGroupNames = new ArrayList();
if (rosterInitialized) {
for (Iterator j = entry.getGroups(); j.hasNext(); ) { for (Iterator j = entry.getGroups(); j.hasNext(); ) {
RosterGroup group = (RosterGroup)j.next(); RosterGroup group = (RosterGroup)j.next();
currentGroupNames.add(group.getName()); currentGroupNames.add(group.getName());
} }
}
// If the packet is not of the type REMOVE then add the entry to the groups // If the packet is not of the type REMOVE then add the entry to the groups
if (!RosterPacket.ItemType.REMOVE.equals(item.getItemType())) { if (!RosterPacket.ItemType.REMOVE.equals(item.getItemType())) {
@ -743,7 +728,7 @@ public class Roster {
} }
// Loop through any groups that remain and remove the entries. // Loop through any groups that remain and remove the entries.
if (rosterInitialized) { // This is neccessary for the case of remote entry removals.
for (int n=0; n<currentGroupNames.size(); n++) { for (int n=0; n<currentGroupNames.size(); n++) {
String groupName = (String)currentGroupNames.get(n); String groupName = (String)currentGroupNames.get(n);
RosterGroup group = getGroup(groupName); RosterGroup group = getGroup(groupName);
@ -754,6 +739,17 @@ public class Roster {
} }
} }
} }
// Remove all the groups with no entries. We have to do this because
// RosterGroup.removeEntry removes the entry immediately (locally) and the
// group could remain empty.
// TODO Check the performance/logic for rosters with large number of groups
for (Iterator it = getGroups(); it.hasNext();) {
RosterGroup group = (RosterGroup)it.next();
if (group.getEntryCount() == 0) {
synchronized (groups) {
groups.remove(group.getName());
}
}
} }
} }