mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-23 04:22:05 +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:
parent
924c27d94c
commit
cd1abe75c0
1 changed files with 54 additions and 58 deletions
|
@ -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,11 +695,9 @@ 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
|
||||||
|
@ -743,18 +728,29 @@ 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);
|
||||||
group.removeEntryLocal(entry);
|
group.removeEntryLocal(entry);
|
||||||
if (group.getEntryCount() == 0) {
|
if (group.getEntryCount() == 0) {
|
||||||
synchronized (groups) {
|
synchronized (groups) {
|
||||||
groups.remove(groupName);
|
groups.remove(groupName);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark the roster as initialized.
|
// Mark the roster as initialized.
|
||||||
|
|
Loading…
Reference in a new issue