diff --git a/source/org/jivesoftware/smack/Roster.java b/source/org/jivesoftware/smack/Roster.java
index aeee8a3f2..eb81024c2 100644
--- a/source/org/jivesoftware/smack/Roster.java
+++ b/source/org/jivesoftware/smack/Roster.java
@@ -36,10 +36,6 @@ import java.util.*;
*
SUBSCRIPTION_REJECT_ALL -- reject all subscription requests.
* SUBSCRIPTION_MANUAL -- manually process all subscription requests.
*
- * All presence subscription requests are automatically approved to this client
- * are automatically approved. This logic will be updated in the future to allow for
- * pluggable behavior.
- *
* @see XMPPConnection#getRoster()
* @author Matt Tucker
*/
@@ -244,6 +240,7 @@ public class Roster {
new PacketIDFilter(rosterPacket.getPacketID()));
connection.sendPacket(rosterPacket);
IQ response = (IQ)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
+ collector.cancel();
if (response == null) {
throw new XMPPException("No response from the server.");
}
@@ -251,7 +248,6 @@ public class Roster {
else if (response.getType() == IQ.Type.ERROR) {
throw new XMPPException(response.getError());
}
- collector.cancel();
// Create a presence subscription packet and send.
Presence presencePacket = new Presence(Presence.Type.SUBSCRIBE);
@@ -262,24 +258,40 @@ public class Roster {
/**
* Removes a roster entry from the roster. The roster entry will also be removed from the
* unfiled entries or from any roster group where it could belong and will no longer be part
- * of the roster.
+ * of the roster. Note that this is an asynchronous call -- Smack must wait for the server
+ * to send an updated subscription status.
*
* @param entry a roster entry.
*/
- public void removeEntry(RosterEntry entry) {
+ public void removeEntry(RosterEntry entry) throws XMPPException {
// Only remove the entry if it's in the entry list.
// The actual removal logic takes place in RosterPacketListenerprocess>>Packet(Packet)
synchronized (entries) {
- if (entries.contains(entry)) {
- RosterPacket packet = new RosterPacket();
- packet.setType(IQ.Type.SET);
- RosterPacket.Item item = RosterEntry.toRosterItem(entry);
- // Set the item type as REMOVE so that the server will delete the entry
- item.setItemType(RosterPacket.ItemType.REMOVE);
- packet.addRosterItem(item);
- connection.sendPacket(packet);
+ if (!entries.contains(entry)) {
+ return;
}
}
+ RosterPacket packet = new RosterPacket();
+ packet.setType(IQ.Type.SET);
+ RosterPacket.Item item = RosterEntry.toRosterItem(entry);
+ // Set the item type as REMOVE so that the server will delete the entry
+ item.setItemType(RosterPacket.ItemType.REMOVE);
+ packet.addRosterItem(item);
+ PacketCollector collector = connection.createPacketCollector(
+ new PacketIDFilter(packet.getPacketID()));
+ connection.sendPacket(packet);
+ IQ response = (IQ)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
+ collector.cancel();
+ if (response == null) {
+ throw new XMPPException("No response from the server.");
+ }
+ // If the server replied with an error, throw an exception.
+ else if (response.getType() == IQ.Type.ERROR) {
+ throw new XMPPException(response.getError());
+ }
+ else {
+
+ }
}
/**
@@ -756,7 +768,10 @@ public class Roster {
}
// Mark the roster as initialized.
- rosterInitialized = true;
+ synchronized (this) {
+ rosterInitialized = true;
+ notifyAll();
+ }
// Fire event for roster listeners.
fireRosterChangedEvent();
diff --git a/source/org/jivesoftware/smack/XMPPConnection.java b/source/org/jivesoftware/smack/XMPPConnection.java
index bec91a0d1..4b36e6aeb 100644
--- a/source/org/jivesoftware/smack/XMPPConnection.java
+++ b/source/org/jivesoftware/smack/XMPPConnection.java
@@ -418,20 +418,27 @@ public class XMPPConnection {
return null;
}
// If this is the first time the user has asked for the roster after calling
- // login, we want to wait up to 2 seconds for the server to send back the
- // user's roster. 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. Note: because of this waiting logic, internal
+ // login, we want to wait for the server to send back the user's roster. 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. Note: because of this waiting logic, internal
// Smack code should be wary about calling the getRoster method, and may need to
// access the roster object directly.
- int elapsed = 0;
- while (!roster.rosterInitialized && elapsed <= 2000) {
+ if (!roster.rosterInitialized) {
try {
- Thread.sleep(500);
+ synchronized (roster) {
+ long waitTime = SmackConfiguration.getPacketReplyTimeout();
+ long start = System.currentTimeMillis();
+ while (!roster.rosterInitialized) {
+ if (waitTime <= 0) {
+ break;
+ }
+ roster.wait(waitTime);
+ waitTime -= System.currentTimeMillis() - start;
+ }
+ }
}
- catch (Exception e) {
- }
- elapsed += 500;
+ catch (InterruptedException ie) { }
}
return roster;
}
@@ -724,7 +731,12 @@ public class XMPPConnection {
Class.forName("org.jivesoftware.smackx.debugger.EnhancedDebugger");
}
catch (Exception ex) {
- debuggerClass = LiteDebugger.class;
+ try {
+ debuggerClass = Class.forName("org.jivesoftware.smack.debugger.LiteDebugger");
+ }
+ catch (Exception ex2) {
+ ex2.printStackTrace();
+ }
}
}
// Create a new debugger instance. If an exception occurs then disable the debugging