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

Rework incoming packet listeners and Roster

Differentiate between asynchronous and synchronous ones. Asynchronous
are the ones where the invocation order may not be the same as the order
in which the stanzas arrived.

Since it's no longer guaranteed that when a unit test calls

processPacket(stanza)

the stanza will be completely processed when the call returns, it was
necessary to extend the unit tests (mostly Roster and ChatManager) with
a packet listener that waits for his invocation. Since we now also use
LinkedHashMaps as Map for the packet listeners (SMACK-531, SMACK-424),
adding a packet listeners as last also means that it will be called as
last. We exploit this behavior change now in the unit tests.

Rename 'recvListeners' to 'syncRecvListeners' in AbstractXMPPConnection.

Rename 'rosterInitialized' to 'loaded' in Roster.

Add Roster.isLoaded().

Reset 'loaded' to false in
Roster.setOfflinePresencesAndResetLoaded() (was setOfflinePresences()).

Fixes SMACK-583, SMACK-532, SMACK-424
This commit is contained in:
Florian Schmaus 2015-01-05 21:42:35 +01:00
parent e5c6c9bdf8
commit 717090d272
39 changed files with 443 additions and 306 deletions

View file

@ -169,7 +169,7 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
initDebugger(); initDebugger();
if (isFirstInitialization) { if (isFirstInitialization) {
if (debugger.getReaderListener() != null) { if (debugger.getReaderListener() != null) {
addPacketListener(debugger.getReaderListener(), null); addAsyncPacketListener(debugger.getReaderListener(), null);
} }
if (debugger.getWriterListener() != null) { if (debugger.getWriterListener() != null) {
addPacketSendingListener(debugger.getWriterListener(), null); addPacketSendingListener(debugger.getWriterListener(), null);

View file

@ -107,7 +107,7 @@ public class PacketReaderTest extends SmackTestCase {
// Keep number of current listeners // Keep number of current listeners
int listenersSize = getConnection(0).getPacketListeners().size(); int listenersSize = getConnection(0).getPacketListeners().size();
// Add a new listener // Add a new listener
getConnection(0).addPacketListener(listener, new MockPacketFilter(true)); getConnection(0).addAsyncPacketListener(listener, new MockPacketFilter(true));
// Check that the listener was added // Check that the listener was added
assertEquals("Listener was not added", listenersSize + 1, assertEquals("Listener was not added", listenersSize + 1,
getConnection(0).getPacketListeners().size()); getConnection(0).getPacketListeners().size());
@ -117,7 +117,7 @@ public class PacketReaderTest extends SmackTestCase {
getConnection(1).sendPacket(msg); getConnection(1).sendPacket(msg);
// Remove the listener // Remove the listener
getConnection(0).removePacketListener(listener); getConnection(0).removeAsyncPacketListener(listener);
// Check that the number of listeners is correct (i.e. the listener was removed) // Check that the number of listeners is correct (i.e. the listener was removed)
assertEquals("Listener was not removed", listenersSize, assertEquals("Listener was not removed", listenersSize,
getConnection(0).getPacketListeners().size()); getConnection(0).getPacketListeners().size());
@ -134,7 +134,7 @@ public class PacketReaderTest extends SmackTestCase {
packet.setBody("aloha"); packet.setBody("aloha");
// User1 will always reply to user0 when a message is received // User1 will always reply to user0 when a message is received
getConnection(1).addPacketListener(new PacketListener() { getConnection(1).addAsyncPacketListener(new PacketListener() {
public void processPacket(Packet packet) { public void processPacket(Packet packet) {
System.out.println(new Date() + " " + packet); System.out.println(new Date() + " " + packet);
@ -203,8 +203,8 @@ public class PacketReaderTest extends SmackTestCase {
} }
}; };
getConnection(0).addPacketListener(listener0, pf0); getConnection(0).addAsyncPacketListener(listener0, pf0);
getConnection(1).addPacketListener(listener1, pf1); getConnection(1).addAsyncPacketListener(listener1, pf1);
// Check that the listener was added // Check that the listener was added
@ -225,8 +225,8 @@ public class PacketReaderTest extends SmackTestCase {
} }
// Remove the listener // Remove the listener
getConnection(0).removePacketListener(listener0); getConnection(0).removeAsyncPacketListener(listener0);
getConnection(1).removePacketListener(listener1); getConnection(1).removeAsyncPacketListener(listener1);
try { try {
Thread.sleep(300); Thread.sleep(300);

View file

@ -22,6 +22,7 @@ import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -126,12 +127,14 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
private final Collection<PacketCollector> collectors = new ConcurrentLinkedQueue<PacketCollector>(); private final Collection<PacketCollector> collectors = new ConcurrentLinkedQueue<PacketCollector>();
/** /**
* List of PacketListeners that will be notified when a new packet was received. * List of PacketListeners that will be notified synchronously when a new packet was received.
*/ */
private final Map<PacketListener, ListenerWrapper> recvListeners = private final Map<PacketListener, ListenerWrapper> syncRecvListeners = new LinkedHashMap<>();
new HashMap<PacketListener, ListenerWrapper>();
private final Map<PacketListener, ListenerWrapper> asyncRecvListeners = new HashMap<>(); /**
* List of PacketListeners that will be notified asynchronously when a new packet was received.
*/
private final Map<PacketListener, ListenerWrapper> asyncRecvListeners = new LinkedHashMap<>();
/** /**
* List of PacketListeners that will be notified when a new packet was sent. * List of PacketListeners that will be notified when a new packet was sent.
@ -245,6 +248,14 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
// @formatter:on // @formatter:on
); );
/**
* A executor service used to invoke the callbacks of synchronous packet listeners. We use a executor service to
* decouple incoming stanza processing from callback invocation. It is important that order of callback invocation
* is the same as the order of the incoming stanzas. Therefore we use a <i>single</i> threaded executor service.
*/
private final ExecutorService singleThreadedExecutorService = Executors.newSingleThreadExecutor(new SmackExecutorThreadFactory(
getConnectionCounter(), "Sync PacketListener Callback"));
private Roster roster; private Roster roster;
/** /**
@ -593,27 +604,10 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
// changes to the roster. Note: because of this waiting logic, internal // 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 // Smack code should be wary about calling the getRoster method, and may need to
// access the roster object directly. // access the roster object directly.
// Also only check for rosterInitalized is isRosterLoadedAtLogin is set, otherwise the user // Also only check for rosterIsLoaded is isRosterLoadedAtLogin is set, otherwise the user
// has to manually call Roster.reload() before he can expect a initialized roster. // has to manually call Roster.reload() before he can expect a initialized roster.
if (!roster.rosterInitialized && config.isRosterLoadedAtLogin()) { if (!roster.isLoaded() && config.isRosterLoadedAtLogin()) {
try { roster.waitUntilLoaded();
synchronized (roster) {
long waitTime = getPacketReplyTimeout();
long start = System.currentTimeMillis();
while (!roster.rosterInitialized) {
if (waitTime <= 0) {
break;
}
roster.wait(waitTime);
long now = System.currentTimeMillis();
waitTime -= now - start;
start = now;
}
}
}
catch (InterruptedException ie) {
// Ignore.
}
} }
return roster; return roster;
} }
@ -727,19 +721,29 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
@Override @Override
public void addPacketListener(PacketListener packetListener, PacketFilter packetFilter) { public void addPacketListener(PacketListener packetListener, PacketFilter packetFilter) {
if (packetListener == null) { addAsyncPacketListener(packetListener, packetFilter);
throw new NullPointerException("Packet listener is null.");
}
ListenerWrapper wrapper = new ListenerWrapper(packetListener, packetFilter);
synchronized (recvListeners) {
recvListeners.put(packetListener, wrapper);
}
} }
@Override @Override
public boolean removePacketListener(PacketListener packetListener) { public boolean removePacketListener(PacketListener packetListener) {
synchronized (recvListeners) { return removeAsyncPacketListener(packetListener);
return recvListeners.remove(packetListener) != null; }
@Override
public void addSyncPacketListener(PacketListener packetListener, PacketFilter packetFilter) {
if (packetListener == null) {
throw new NullPointerException("Packet listener is null.");
}
ListenerWrapper wrapper = new ListenerWrapper(packetListener, packetFilter);
synchronized (syncRecvListeners) {
syncRecvListeners.put(packetListener, wrapper);
}
}
@Override
public boolean removeSyncPacketListener(PacketListener packetListener) {
synchronized (syncRecvListeners) {
return syncRecvListeners.remove(packetListener) != null;
} }
} }
@ -961,7 +965,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
// First handle the async recv listeners. Note that this code is very similar to what follows a few lines below, // First handle the async recv listeners. Note that this code is very similar to what follows a few lines below,
// the only difference is that asyncRecvListeners is used here and that the packet listeners are started in // the only difference is that asyncRecvListeners is used here and that the packet listeners are started in
// their own thread. // their own thread.
Collection<PacketListener> listenersToNotify = new LinkedList<PacketListener>(); final Collection<PacketListener> listenersToNotify = new LinkedList<PacketListener>();
synchronized (asyncRecvListeners) { synchronized (asyncRecvListeners) {
for (ListenerWrapper listenerWrapper : asyncRecvListeners.values()) { for (ListenerWrapper listenerWrapper : asyncRecvListeners.values()) {
if (listenerWrapper.filterMatches(packet)) { if (listenerWrapper.filterMatches(packet)) {
@ -989,15 +993,20 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
} }
// Notify the receive listeners interested in the packet // Notify the receive listeners interested in the packet
listenersToNotify = new LinkedList<PacketListener>(); listenersToNotify.clear();
synchronized (recvListeners) { synchronized (syncRecvListeners) {
for (ListenerWrapper listenerWrapper : recvListeners.values()) { for (ListenerWrapper listenerWrapper : syncRecvListeners.values()) {
if (listenerWrapper.filterMatches(packet)) { if (listenerWrapper.filterMatches(packet)) {
listenersToNotify.add(listenerWrapper.getListener()); listenersToNotify.add(listenerWrapper.getListener());
} }
} }
} }
// Decouple incoming stanza processing from listener invocation. Unlike async listeners, this uses a single
// threaded executor service and therefore keeps the order.
singleThreadedExecutorService.execute(new Runnable() {
@Override
public void run() {
for (PacketListener listener : listenersToNotify) { for (PacketListener listener : listenersToNotify) {
try { try {
listener.processPacket(packet); listener.processPacket(packet);
@ -1009,6 +1018,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
} }
} }
} }
});
}
/** /**
* Sets whether the connection has already logged in the server. This method assures that the * Sets whether the connection has already logged in the server. This method assures that the
@ -1145,6 +1157,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
executorService.shutdownNow(); executorService.shutdownNow();
cachedExecutorService.shutdown(); cachedExecutorService.shutdown();
removeCallbacksService.shutdownNow(); removeCallbacksService.shutdownNow();
singleThreadedExecutorService.shutdownNow();
} catch (Throwable t) { } catch (Throwable t) {
LOGGER.log(Level.WARNING, "finalize() threw trhowable", t); LOGGER.log(Level.WARNING, "finalize() threw trhowable", t);
} }
@ -1302,14 +1315,14 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
} }
} }
finally { finally {
removePacketListener(this); removeAsyncPacketListener(this);
} }
} }
}; };
removeCallbacksService.schedule(new Runnable() { removeCallbacksService.schedule(new Runnable() {
@Override @Override
public void run() { public void run() {
boolean removed = removePacketListener(packetListener); boolean removed = removeAsyncPacketListener(packetListener);
// If the packetListener got removed, then it was never run and // If the packetListener got removed, then it was never run and
// we never received a response, inform the exception callback // we never received a response, inform the exception callback
if (removed && exceptionCallback != null) { if (removed && exceptionCallback != null) {
@ -1317,7 +1330,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
} }
} }
}, timeout, TimeUnit.MILLISECONDS); }, timeout, TimeUnit.MILLISECONDS);
addPacketListener(packetListener, replyFilter); addAsyncPacketListener(packetListener, replyFilter);
sendPacket(stanza); sendPacket(stanza);
} }

View file

@ -137,7 +137,7 @@ public class ChatManager extends Manager{
// Add a listener for all message packets so that we can deliver // Add a listener for all message packets so that we can deliver
// messages to the best Chat instance available. // messages to the best Chat instance available.
connection.addPacketListener(new PacketListener() { connection.addSyncPacketListener(new PacketListener() {
public void processPacket(Packet packet) { public void processPacket(Packet packet) {
Message message = (Message) packet; Message message = (Message) packet;
Chat chat; Chat chat;

View file

@ -33,7 +33,7 @@ import org.jivesoftware.smack.packet.Packet;
* org.jivesoftware.smack.filter.PacketFilter)} * org.jivesoftware.smack.filter.PacketFilter)}
* </p> * </p>
* *
* @see XMPPConnection#addPacketListener(PacketListener, org.jivesoftware.smack.filter.PacketFilter) * @see XMPPConnection#addAsyncPacketListener(PacketListener, org.jivesoftware.smack.filter.PacketFilter)
* @author Matt Tucker * @author Matt Tucker
*/ */
public interface PacketListener { public interface PacketListener {

View file

@ -85,9 +85,11 @@ public class Roster {
private final List<RosterEntry> unfiledEntries = new CopyOnWriteArrayList<RosterEntry>(); private final List<RosterEntry> unfiledEntries = new CopyOnWriteArrayList<RosterEntry>();
private final List<RosterListener> rosterListeners = new CopyOnWriteArrayList<RosterListener>(); private final List<RosterListener> rosterListeners = new CopyOnWriteArrayList<RosterListener>();
private final Map<String, Map<String, Presence>> presenceMap = new ConcurrentHashMap<String, Map<String, Presence>>(); private final Map<String, Map<String, Presence>> presenceMap = new ConcurrentHashMap<String, Map<String, Presence>>();
// The roster is marked as initialized when at least a single roster packet // The roster is marked as initialized when at least a single roster packet
// has been received and processed. // has been received and processed.
boolean rosterInitialized = false; private boolean loaded = false;
private final PresencePacketListener presencePacketListener = new PresencePacketListener(); private final PresencePacketListener presencePacketListener = new PresencePacketListener();
private SubscriptionMode subscriptionMode = getDefaultSubscriptionMode(); private SubscriptionMode subscriptionMode = getDefaultSubscriptionMode();
@ -124,10 +126,13 @@ public class Roster {
Roster(final XMPPConnection connection) { Roster(final XMPPConnection connection) {
this.connection = connection; this.connection = connection;
rosterStore = connection.getRosterStore(); rosterStore = connection.getRosterStore();
// Note that we use sync packet listeners because RosterListeners should be invoked in the same order as the
// roster stanzas arrive.
// Listen for any roster packets. // Listen for any roster packets.
connection.addPacketListener(new RosterPushListener(), ROSTER_PUSH_FILTER); connection.addSyncPacketListener(new RosterPushListener(), ROSTER_PUSH_FILTER);
// Listen for any presence packets. // Listen for any presence packets.
connection.addPacketListener(presencePacketListener, PRESENCE_PACKET_FILTER); connection.addSyncPacketListener(presencePacketListener, PRESENCE_PACKET_FILTER);
// Listen for connection events // Listen for connection events
connection.addConnectionListener(new AbstractConnectionListener() { connection.addConnectionListener(new AbstractConnectionListener() {
@ -151,22 +156,12 @@ public class Roster {
public void connectionClosed() { public void connectionClosed() {
// Changes the presence available contacts to unavailable // Changes the presence available contacts to unavailable
try { setOfflinePresencesAndResetLoaded();
setOfflinePresences();
}
catch (NotConnectedException e) {
LOGGER.log(Level.SEVERE, "Not connected exception" ,e);
}
} }
public void connectionClosedOnError(Exception e) { public void connectionClosedOnError(Exception e) {
// Changes the presence available contacts to unavailable // Changes the presence available contacts to unavailable
try { setOfflinePresencesAndResetLoaded();
setOfflinePresences();
}
catch (NotConnectedException e1) {
LOGGER.log(Level.SEVERE, "Not connected exception" ,e);
}
} }
}); });
@ -238,6 +233,40 @@ public class Roster {
}); });
} }
protected boolean waitUntilLoaded() {
long waitTime = connection.getPacketReplyTimeout();
long start = System.currentTimeMillis();
while (!loaded) {
if (waitTime <= 0) {
break;
}
try {
synchronized (this) {
if (!loaded) {
wait(waitTime);
}
}
}
catch (InterruptedException e) {
LOGGER.log(Level.FINE, "spurious interrupt", e);
}
long now = System.currentTimeMillis();
waitTime -= now - start;
start = now;
}
return isLoaded();
}
/**
* Check if the roster is loaded.
*
* @return true if the roster is loaded.
* @since 4.1
*/
public boolean isLoaded() {
return loaded;
}
/** /**
* Adds a listener to this roster. The listener will be fired anytime one or more * Adds a listener to this roster. The listener will be fired anytime one or more
* changes to the roster are pushed from the server. * changes to the roster are pushed from the server.
@ -696,7 +725,7 @@ public class Roster {
* to offline. * to offline.
* @throws NotConnectedException * @throws NotConnectedException
*/ */
private void setOfflinePresences() throws NotConnectedException { private void setOfflinePresencesAndResetLoaded() {
Presence packetUnavailable; Presence packetUnavailable;
for (String user : presenceMap.keySet()) { for (String user : presenceMap.keySet()) {
Map<String, Presence> resources = presenceMap.get(user); Map<String, Presence> resources = presenceMap.get(user);
@ -704,11 +733,19 @@ public class Roster {
for (String resource : resources.keySet()) { for (String resource : resources.keySet()) {
packetUnavailable = new Presence(Presence.Type.unavailable); packetUnavailable = new Presence(Presence.Type.unavailable);
packetUnavailable.setFrom(user + "/" + resource); packetUnavailable.setFrom(user + "/" + resource);
try {
presencePacketListener.processPacket(packetUnavailable); presencePacketListener.processPacket(packetUnavailable);
} }
catch (NotConnectedException e) {
throw new IllegalStateException(
"presencePakcetListener should never throw a NotConnectedException when processPacket is called with a presence of type unavailable",
e);
} }
} }
} }
}
loaded = false;
}
/** /**
* Fires roster changed event to roster listeners indicating that the * Fires roster changed event to roster listeners indicating that the
@ -719,8 +756,8 @@ public class Roster {
* @param updatedEntries the collection of address of the updated contacts. * @param updatedEntries the collection of address of the updated contacts.
* @param deletedEntries the collection of address of the deleted contacts. * @param deletedEntries the collection of address of the deleted contacts.
*/ */
private void fireRosterChangedEvent(Collection<String> addedEntries, Collection<String> updatedEntries, private void fireRosterChangedEvent(final Collection<String> addedEntries, final Collection<String> updatedEntries,
Collection<String> deletedEntries) { final Collection<String> deletedEntries) {
for (RosterListener listener : rosterListeners) { for (RosterListener listener : rosterListeners) {
if (!addedEntries.isEmpty()) { if (!addedEntries.isEmpty()) {
listener.entriesAdded(addedEntries); listener.entriesAdded(addedEntries);
@ -739,7 +776,7 @@ public class Roster {
* *
* @param presence the presence change. * @param presence the presence change.
*/ */
private void fireRosterPresenceEvent(Presence presence) { private void fireRosterPresenceEvent(final Presence presence) {
for (RosterListener listener : rosterListeners) { for (RosterListener listener : rosterListeners) {
listener.presenceChanged(presence); listener.presenceChanged(presence);
} }
@ -1068,7 +1105,7 @@ public class Roster {
} }
} }
rosterInitialized = true; loaded = true;
synchronized (Roster.this) { synchronized (Roster.this) {
Roster.this.notifyAll(); Roster.this.notifyAll();
} }

View file

@ -246,16 +246,20 @@ public interface XMPPConnection {
public void removePacketCollector(PacketCollector collector); public void removePacketCollector(PacketCollector collector);
/** /**
* Registers a packet listener with this connection. A packet listener will be invoked only * Registers a packet listener with this connection.
* when an incoming packet is received. A packet filter determines * <p>
* which packets will be delivered to the listener. If the same packet listener * This method has been deprecated. It is important to differentiate between using an asynchronous packet listener
* is added again with a different filter, only the new filter will be used. * (preferred where possible) and a synchronous packet lister. Refer
* * {@link #addAsyncPacketListener(PacketListener, PacketFilter)} and
* NOTE: If you want get a similar callback for outgoing packets, see {@link #addPacketInterceptor(PacketListener, PacketFilter)}. * {@link #addSyncPacketListener(PacketListener, PacketFilter)} for more information.
* </p>
* *
* @param packetListener the packet listener to notify of new received packets. * @param packetListener the packet listener to notify of new received packets.
* @param packetFilter the packet filter to use. * @param packetFilter the packet filter to use.
* @deprecated use {@link #addAsyncPacketListener(PacketListener, PacketFilter)} or
* {@link #addSyncPacketListener(PacketListener, PacketFilter)}.
*/ */
@Deprecated
public void addPacketListener(PacketListener packetListener, PacketFilter packetFilter); public void addPacketListener(PacketListener packetListener, PacketFilter packetFilter);
/** /**
@ -263,21 +267,53 @@ public interface XMPPConnection {
* *
* @param packetListener the packet listener to remove. * @param packetListener the packet listener to remove.
* @return true if the packet listener was removed * @return true if the packet listener was removed
* @deprecated use {@link #removeAsyncPacketListener(PacketListener)} or {@link #removeSyncPacketListener(PacketListener)}.
*/ */
@Deprecated
public boolean removePacketListener(PacketListener packetListener); public boolean removePacketListener(PacketListener packetListener);
/**
* Registers a <b>synchronous</b> packet listener with this connection. A packet listener will be invoked only when
* an incoming packet is received. A packet filter determines which packets will be delivered to the listener. If
* the same packet listener is added again with a different filter, only the new filter will be used.
* <p>
* <b>Important:</b> This packet listeners will be called in the same <i>single</i> thread that processes all
* incoming stanzas. Only use this kind of packet filter if it does not perform any XMPP activity that waits for a
* response. Consider using {@link #addAsyncPacketListener(PacketListener, PacketFilter)} when possible, i.e. when
* the invocation order doesn't have to be the same as the order of the arriving packets. If the order of the
* arriving packets, consider using a {@link PacketCollector} when possible.
* </p>
*
* @param packetListener the packet listener to notify of new received packets.
* @param packetFilter the packet filter to use.
* @see {@link #addPacketInterceptor(PacketListener, PacketFilter)} for a similar callback for outgoing stanzas.
* @since 4.1
*/
public void addSyncPacketListener(PacketListener packetListener, PacketFilter packetFilter);
/**
* Removes a packet listener for received packets from this connection.
*
* @param packetListener the packet listener to remove.
* @return true if the packet listener was removed
* @since 4.1
*/
public boolean removeSyncPacketListener(PacketListener packetListener);
/** /**
* Registers an <b>asynchronous</b> packet listener with this connection. A packet listener will be invoked only * Registers an <b>asynchronous</b> packet listener with this connection. A packet listener will be invoked only
* when an incoming packet is received. A packet filter determines which packets will be delivered to the listener. * when an incoming packet is received. A packet filter determines which packets will be delivered to the listener.
* If the same packet listener is added again with a different filter, only the new filter will be used. * If the same packet listener is added again with a different filter, only the new filter will be used.
* <p> * <p>
* Unlike {@link #addPacketListener(PacketListener, PacketFilter)} packet listeners added with this method will be * Unlike {@link #addAsyncPacketListener(PacketListener, PacketFilter)} packet listeners added with this method will be
* invoked asynchronously in their own thread. Use this method if the order of the packet listeners must not depend * invoked asynchronously in their own thread. Use this method if the order of the packet listeners must not depend
* on the order how the stanzas where received. * on the order how the stanzas where received.
* </p> * </p>
* *
* @param packetListener the packet listener to notify of new received packets. * @param packetListener the packet listener to notify of new received packets.
* @param packetFilter the packet filter to use. * @param packetFilter the packet filter to use.
* @see {@link #addPacketInterceptor(PacketListener, PacketFilter)} for a similar callback for outgoing stanzas.
* @since 4.1
*/ */
public void addAsyncPacketListener(PacketListener packetListener, PacketFilter packetFilter); public void addAsyncPacketListener(PacketListener packetListener, PacketFilter packetFilter);
@ -286,6 +322,7 @@ public interface XMPPConnection {
* *
* @param packetListener the packet listener to remove. * @param packetListener the packet listener to remove.
* @return true if the packet listener was removed * @return true if the packet listener was removed
* @since 4.1
*/ */
public boolean removeAsyncPacketListener(PacketListener packetListener); public boolean removeAsyncPacketListener(PacketListener packetListener);
@ -316,7 +353,7 @@ public interface XMPPConnection {
* will be delivered to the interceptor. * will be delivered to the interceptor.
* *
* <p> * <p>
* NOTE: For a similar functionality on incoming packets, see {@link #addPacketListener(PacketListener, PacketFilter)}. * NOTE: For a similar functionality on incoming packets, see {@link #addAsyncPacketListener(PacketListener, PacketFilter)}.
* *
* @param packetInterceptor the packet interceptor to notify of packets about to be sent. * @param packetInterceptor the packet interceptor to notify of packets about to be sent.
* @param packetFilter the packet filter to use. * @param packetFilter the packet filter to use.

View file

@ -27,102 +27,108 @@ import org.jivesoftware.smack.ChatManager.MatchMode;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Message.Type; import org.jivesoftware.smack.packet.Message.Type;
import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.test.util.WaitForPacketListener;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
public class ChatConnectionTest { public class ChatConnectionTest {
private DummyConnection connection; private DummyConnection dc;
private ChatManager cm;
private TestChatManagerListener listener;
private WaitForPacketListener waitListener;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
connection = getConnection(); // Defaults
ChatManager.setDefaultIsNormalIncluded(true);
ChatManager.setDefaultMatchMode(MatchMode.BARE_JID);
dc = DummyConnection.newConnectedDummyConnection();
cm = ChatManager.getInstanceFor(dc);
listener = new TestChatManagerListener();
cm.addChatListener(listener);
waitListener = new WaitForPacketListener();
dc.addSyncPacketListener(waitListener, null);
} }
@After @After
public void tearDown() throws Exception { public void tearDown() throws Exception {
if (connection != null) if (dc != null) {
connection.disconnect(); dc.disconnect();
}
} }
@Test @Test
public void validateDefaultSetNormalIncluded() { public void validateDefaultSetNormalIncludedFalse() {
ChatManager.setDefaultIsNormalIncluded(false); ChatManager.setDefaultIsNormalIncluded(false);
assertFalse(ChatManager.getInstanceFor(getConnection()).isNormalIncluded()); assertFalse(ChatManager.getInstanceFor(new DummyConnection()).isNormalIncluded());
}
@Test
public void validateDefaultSetNormalIncludedTrue() {
ChatManager.setDefaultIsNormalIncluded(true); ChatManager.setDefaultIsNormalIncluded(true);
assertTrue(ChatManager.getInstanceFor(getConnection()).isNormalIncluded()); assertTrue(ChatManager.getInstanceFor(new DummyConnection()).isNormalIncluded());
} }
@Test @Test
public void validateDefaultSetMatchMode() { public void validateDefaultSetMatchModeNone() {
ChatManager.setDefaultMatchMode(MatchMode.NONE); ChatManager.setDefaultMatchMode(MatchMode.NONE);
assertEquals(MatchMode.NONE, ChatManager.getInstanceFor(getConnection()).getMatchMode()); assertEquals(MatchMode.NONE, ChatManager.getInstanceFor(new DummyConnection()).getMatchMode());
}
@Test
public void validateDefaultSetMatchModeBareJid() {
ChatManager.setDefaultMatchMode(MatchMode.BARE_JID); ChatManager.setDefaultMatchMode(MatchMode.BARE_JID);
assertEquals(MatchMode.BARE_JID, ChatManager.getInstanceFor(getConnection()).getMatchMode()); assertEquals(MatchMode.BARE_JID, ChatManager.getInstanceFor(new DummyConnection()).getMatchMode());
} }
@Test @Test
public void validateMessageTypeWithDefaults() { public void validateMessageTypeWithDefaults1() {
DummyConnection dc = getConnection();
ChatManager cm = ChatManager.getInstanceFor(dc);
TestChatManagerListener listener = new TestChatManagerListener();
cm.addChatListener(listener);
Message incomingChat = createChatPacket("134", true); Message incomingChat = createChatPacket("134", true);
incomingChat.setType(Type.chat); incomingChat.setType(Type.chat);
processServerMessage(incomingChat, dc); processServerMessage(incomingChat);
assertNotNull(listener.getNewChat()); assertNotNull(listener.getNewChat());
}
dc = getConnection(); @Test
cm = ChatManager.getInstanceFor(dc); public void validateMessageTypeWithDefaults2() {
listener = new TestChatManagerListener(); Message incomingChat = createChatPacket("134", true);
cm.addChatListener(listener);
incomingChat = createChatPacket("134", true);
incomingChat.setType(Type.normal); incomingChat.setType(Type.normal);
processServerMessage(incomingChat, dc); processServerMessage(incomingChat);
assertNotNull(listener.getNewChat()); assertNotNull(listener.getNewChat());
}
dc = getConnection(); @Test
cm = ChatManager.getInstanceFor(dc); public void validateMessageTypeWithDefaults3() {
listener = new TestChatManagerListener(); Message incomingChat = createChatPacket("134", true);
cm.addChatListener(listener);
incomingChat = createChatPacket("134", true);
incomingChat.setType(Type.groupchat); incomingChat.setType(Type.groupchat);
processServerMessage(incomingChat, dc); processServerMessage(incomingChat);
assertNull(listener.getNewChat());
dc = getConnection();
cm = ChatManager.getInstanceFor(dc);
listener = new TestChatManagerListener();
cm.addChatListener(listener);
incomingChat = createChatPacket("134", true);
incomingChat.setType(Type.headline);
processServerMessage(incomingChat, dc);
assertNull(listener.getNewChat()); assertNull(listener.getNewChat());
} }
@Test @Test
public void validateMessageTypeWithNoNormal() { public void validateMessageTypeWithDefaults4() {
DummyConnection dc = getConnection(); Message incomingChat = createChatPacket("134", true);
ChatManager cm = ChatManager.getInstanceFor(dc); incomingChat.setType(Type.headline);
assertNull(listener.getNewChat());
}
@Test
public void validateMessageTypeWithNoNormal1() {
cm.setNormalIncluded(false); cm.setNormalIncluded(false);
TestChatManagerListener listener = new TestChatManagerListener();
cm.addChatListener(listener);
Message incomingChat = createChatPacket("134", true); Message incomingChat = createChatPacket("134", true);
incomingChat.setType(Type.chat); incomingChat.setType(Type.chat);
processServerMessage(incomingChat, dc); processServerMessage(incomingChat);
assertNotNull(listener.getNewChat()); assertNotNull(listener.getNewChat());
}
dc = getConnection(); @Test
cm = ChatManager.getInstanceFor(dc); public void validateMessageTypeWithNoNormal2() {
cm.setNormalIncluded(false); cm.setNormalIncluded(false);
listener = new TestChatManagerListener(); Message incomingChat = createChatPacket("134", true);
cm.addChatListener(listener);
incomingChat = createChatPacket("134", true);
incomingChat.setType(Type.normal); incomingChat.setType(Type.normal);
processServerMessage(incomingChat, dc); processServerMessage(incomingChat);
assertNull(listener.getNewChat()); assertNull(listener.getNewChat());
} }
@ -130,65 +136,59 @@ public class ChatConnectionTest {
@Test @Test
public void chatMatchedOnJIDWhenNoThreadBareMode() { public void chatMatchedOnJIDWhenNoThreadBareMode() {
// MatchMode.BARE_JID is the default, so setting required. // MatchMode.BARE_JID is the default, so setting required.
DummyConnection con = getConnection();
TestMessageListener msgListener = new TestMessageListener(); TestMessageListener msgListener = new TestMessageListener();
TestChatManagerListener listener = new TestChatManagerListener(msgListener); TestChatManagerListener listener = new TestChatManagerListener(msgListener);
ChatManager cm = ChatManager.getInstanceFor(con);
cm.addChatListener(listener); cm.addChatListener(listener);
Packet incomingChat = createChatPacket(null, true); Packet incomingChat = createChatPacket(null, true);
processServerMessage(incomingChat, con); processServerMessage(incomingChat);
Chat newChat = listener.getNewChat(); Chat newChat = listener.getNewChat();
assertNotNull(newChat); assertNotNull(newChat);
// Should match on chat with full jid // Should match on chat with full jid
incomingChat = createChatPacket(null, true); incomingChat = createChatPacket(null, true);
processServerMessage(incomingChat, con); processServerMessage(incomingChat);
assertEquals(2, msgListener.getNumMessages()); assertEquals(2, msgListener.getNumMessages());
// Should match on chat with bare jid // Should match on chat with bare jid
incomingChat = createChatPacket(null, false); incomingChat = createChatPacket(null, false);
processServerMessage(incomingChat, con); processServerMessage(incomingChat);
assertEquals(3, msgListener.getNumMessages()); assertEquals(3, msgListener.getNumMessages());
} }
@Test @Test
public void chatMatchedOnJIDWhenNoThreadJidMode() { public void chatMatchedOnJIDWhenNoThreadJidMode() {
DummyConnection con = getConnection();
TestMessageListener msgListener = new TestMessageListener(); TestMessageListener msgListener = new TestMessageListener();
TestChatManagerListener listener = new TestChatManagerListener(msgListener); TestChatManagerListener listener = new TestChatManagerListener(msgListener);
ChatManager cm = ChatManager.getInstanceFor(con);
cm.setMatchMode(MatchMode.SUPPLIED_JID); cm.setMatchMode(MatchMode.SUPPLIED_JID);
cm.addChatListener(listener); cm.addChatListener(listener);
Packet incomingChat = createChatPacket(null, true); Packet incomingChat = createChatPacket(null, true);
processServerMessage(incomingChat, con); processServerMessage(incomingChat);
Chat newChat = listener.getNewChat(); Chat newChat = listener.getNewChat();
assertNotNull(newChat); assertNotNull(newChat);
cm.removeChatListener(listener); cm.removeChatListener(listener);
// Should match on chat with full jid // Should match on chat with full jid
incomingChat = createChatPacket(null, true); incomingChat = createChatPacket(null, true);
processServerMessage(incomingChat, con); processServerMessage(incomingChat);
assertEquals(2, msgListener.getNumMessages()); assertEquals(2, msgListener.getNumMessages());
// Should not match on chat with bare jid // Should not match on chat with bare jid
TestChatManagerListener listener2 = new TestChatManagerListener(); TestChatManagerListener listener2 = new TestChatManagerListener();
cm.addChatListener(listener2); cm.addChatListener(listener2);
incomingChat = createChatPacket(null, false); incomingChat = createChatPacket(null, false);
processServerMessage(incomingChat, con); processServerMessage(incomingChat);
assertEquals(2, msgListener.getNumMessages()); assertEquals(2, msgListener.getNumMessages());
assertNotNull(listener2.getNewChat()); assertNotNull(listener2.getNewChat());
} }
@Test @Test
public void chatMatchedOnJIDWhenNoThreadNoneMode() { public void chatMatchedOnJIDWhenNoThreadNoneMode() {
DummyConnection con = getConnection();
TestMessageListener msgListener = new TestMessageListener(); TestMessageListener msgListener = new TestMessageListener();
TestChatManagerListener listener = new TestChatManagerListener(msgListener); TestChatManagerListener listener = new TestChatManagerListener(msgListener);
ChatManager cm = ChatManager.getInstanceFor(con);
cm.setMatchMode(MatchMode.NONE); cm.setMatchMode(MatchMode.NONE);
cm.addChatListener(listener); cm.addChatListener(listener);
Packet incomingChat = createChatPacket(null, true); Packet incomingChat = createChatPacket(null, true);
processServerMessage(incomingChat, con); processServerMessage(incomingChat);
Chat newChat = listener.getNewChat(); Chat newChat = listener.getNewChat();
assertNotNull(newChat); assertNotNull(newChat);
assertEquals(1, msgListener.getNumMessages()); assertEquals(1, msgListener.getNumMessages());
@ -198,7 +198,7 @@ public class ChatConnectionTest {
TestChatManagerListener listener2 = new TestChatManagerListener(); TestChatManagerListener listener2 = new TestChatManagerListener();
cm.addChatListener(listener2); cm.addChatListener(listener2);
incomingChat = createChatPacket(null, true); incomingChat = createChatPacket(null, true);
processServerMessage(incomingChat, con); processServerMessage(incomingChat);
assertEquals(1, msgListener.getNumMessages()); assertEquals(1, msgListener.getNumMessages());
assertNotNull(newChat); assertNotNull(newChat);
cm.removeChatListener(listener2); cm.removeChatListener(listener2);
@ -207,7 +207,7 @@ public class ChatConnectionTest {
TestChatManagerListener listener3 = new TestChatManagerListener(); TestChatManagerListener listener3 = new TestChatManagerListener();
cm.addChatListener(listener3); cm.addChatListener(listener3);
incomingChat = createChatPacket(null, false); incomingChat = createChatPacket(null, false);
processServerMessage(incomingChat, con); processServerMessage(incomingChat);
assertEquals(1, msgListener.getNumMessages()); assertEquals(1, msgListener.getNumMessages());
assertNotNull(listener3.getNewChat()); assertNotNull(listener3.getNewChat());
} }
@ -218,9 +218,6 @@ public class ChatConnectionTest {
*/ */
@Test @Test
public void chatFoundWhenNoThreadFullJid() { public void chatFoundWhenNoThreadFullJid() {
TestChatManagerListener listener = new TestChatManagerListener();
ChatManager cm = ChatManager.getInstanceFor(connection);
cm.addChatListener(listener);
Chat outgoing = cm.createChat("you@testserver", null); Chat outgoing = cm.createChat("you@testserver", null);
Packet incomingChat = createChatPacket(null, true); Packet incomingChat = createChatPacket(null, true);
@ -237,9 +234,6 @@ public class ChatConnectionTest {
*/ */
@Test @Test
public void chatFoundWhenNoThreadBaseJid() { public void chatFoundWhenNoThreadBaseJid() {
TestChatManagerListener listener = new TestChatManagerListener();
ChatManager cm = ChatManager.getInstanceFor(connection);
cm.addChatListener(listener);
Chat outgoing = cm.createChat("you@testserver", null); Chat outgoing = cm.createChat("you@testserver", null);
Packet incomingChat = createChatPacket(null, false); Packet incomingChat = createChatPacket(null, false);
@ -256,9 +250,6 @@ public class ChatConnectionTest {
*/ */
@Test @Test
public void chatFoundWithSameThreadFullJid() { public void chatFoundWithSameThreadFullJid() {
TestChatManagerListener listener = new TestChatManagerListener();
ChatManager cm = ChatManager.getInstanceFor(connection);
cm.addChatListener(listener);
Chat outgoing = cm.createChat("you@testserver", null); Chat outgoing = cm.createChat("you@testserver", null);
Packet incomingChat = createChatPacket(outgoing.getThreadID(), true); Packet incomingChat = createChatPacket(outgoing.getThreadID(), true);
@ -275,9 +266,6 @@ public class ChatConnectionTest {
*/ */
@Test @Test
public void chatFoundWithSameThreadBaseJid() { public void chatFoundWithSameThreadBaseJid() {
TestChatManagerListener listener = new TestChatManagerListener();
ChatManager cm = ChatManager.getInstanceFor(connection);
cm.addChatListener(listener);
Chat outgoing = cm.createChat("you@testserver", null); Chat outgoing = cm.createChat("you@testserver", null);
Packet incomingChat = createChatPacket(outgoing.getThreadID(), false); Packet incomingChat = createChatPacket(outgoing.getThreadID(), false);
@ -294,9 +282,6 @@ public class ChatConnectionTest {
*/ */
@Test @Test
public void chatNotFoundWithDiffThreadBaseJid() { public void chatNotFoundWithDiffThreadBaseJid() {
TestChatManagerListener listener = new TestChatManagerListener();
ChatManager cm = ChatManager.getInstanceFor(connection);
cm.addChatListener(listener);
Chat outgoing = cm.createChat("you@testserver", null); Chat outgoing = cm.createChat("you@testserver", null);
Packet incomingChat = createChatPacket(outgoing.getThreadID() + "ff", false); Packet incomingChat = createChatPacket(outgoing.getThreadID() + "ff", false);
@ -313,9 +298,6 @@ public class ChatConnectionTest {
*/ */
@Test @Test
public void chatNotFoundWithDiffThreadFullJid() { public void chatNotFoundWithDiffThreadFullJid() {
TestChatManagerListener listener = new TestChatManagerListener();
ChatManager cm = ChatManager.getInstanceFor(connection);
cm.addChatListener(listener);
Chat outgoing = cm.createChat("you@testserver", null); Chat outgoing = cm.createChat("you@testserver", null);
Packet incomingChat = createChatPacket(outgoing.getThreadID() + "ff", true); Packet incomingChat = createChatPacket(outgoing.getThreadID() + "ff", true);
@ -328,11 +310,7 @@ public class ChatConnectionTest {
@Test @Test
public void chatNotMatchedWithTypeNormal() { public void chatNotMatchedWithTypeNormal() {
TestChatManagerListener listener = new TestChatManagerListener();
DummyConnection con = getConnection();
ChatManager cm = ChatManager.getInstanceFor(con);
cm.setNormalIncluded(false); cm.setNormalIncluded(false);
cm.addChatListener(listener);
Message incomingChat = createChatPacket(null, false); Message incomingChat = createChatPacket(null, false);
incomingChat.setType(Type.normal); incomingChat.setType(Type.normal);
@ -341,50 +319,26 @@ public class ChatConnectionTest {
assertNull(listener.getNewChat()); assertNull(listener.getNewChat());
} }
@SuppressWarnings("unused")
private ChatManager getChatManager(boolean includeNormal, MatchMode mode) {
ChatManager cm = ChatManager.getInstanceFor(getConnection());
cm.setMatchMode(mode);
cm.setNormalIncluded(includeNormal);
return cm;
}
private DummyConnection getConnection() {
DummyConnection con = new DummyConnection();
try {
con.connect();
con.login();
} catch (Exception e) {
// No need for handling in a dummy connection.
}
return con;
}
private Message createChatPacket(final String threadId, final boolean isFullJid) { private Message createChatPacket(final String threadId, final boolean isFullJid) {
Message chatMsg = new Message("me@testserver", Message.Type.chat); Message chatMsg = new Message("me@testserver", Message.Type.chat);
chatMsg.setBody("the body message - " + System.currentTimeMillis()); chatMsg.setBody("the body message - " + System.currentTimeMillis());
chatMsg.setFrom("you@testserver" + (isFullJid ? "/resource" : "")); chatMsg.setFrom("you@testserver" + (isFullJid ? "/resource" : ""));
if (threadId != null)
chatMsg.setThread(threadId); chatMsg.setThread(threadId);
return chatMsg; return chatMsg;
} }
private void processServerMessage(Packet incomingChat) { private void processServerMessage(Packet incomingChat) {
processServerMessage(incomingChat, connection); TestChatServer chatServer = new TestChatServer(incomingChat, dc);
}
private void processServerMessage(Packet incomingChat, DummyConnection con) {
TestChatServer chatServer = new TestChatServer(incomingChat, con);
chatServer.start(); chatServer.start();
try { try {
chatServer.join(); chatServer.join();
} catch (InterruptedException e) { } catch (InterruptedException e) {
fail(); fail();
} }
waitListener.waitAndReset();
} }
class TestChatManagerListener implements ChatManagerListener { class TestChatManagerListener extends WaitForPacketListener implements ChatManagerListener {
private Chat newChat; private Chat newChat;
private ChatMessageListener listener; private ChatMessageListener listener;
@ -401,6 +355,7 @@ public class ChatConnectionTest {
if (listener != null) if (listener != null)
newChat.addMessageListener(listener); newChat.addMessageListener(listener);
reportInvoked();
} }
public Chat getNewChat() { public Chat getNewChat() {

View file

@ -17,6 +17,7 @@
package org.jivesoftware.smack; package org.jivesoftware.smack;
import java.io.IOException;
import java.util.Date; import java.util.Date;
import java.util.Random; import java.util.Random;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
@ -189,7 +190,7 @@ public class DummyConnection extends AbstractXMPPConnection {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <P extends TopLevelStreamElement> P getSentPacket() throws InterruptedException { public <P extends TopLevelStreamElement> P getSentPacket() throws InterruptedException {
return (P) queue.poll(); return (P) queue.poll(5, TimeUnit.MINUTES);
} }
/** /**
@ -221,6 +222,18 @@ public class DummyConnection extends AbstractXMPPConnection {
invokePacketCollectorsAndNotifyRecvListeners(packet); invokePacketCollectorsAndNotifyRecvListeners(packet);
} }
public static DummyConnection newConnectedDummyConnection() {
DummyConnection dummyConnection = new DummyConnection();
try {
dummyConnection.connect();
dummyConnection.login();
}
catch (SmackException | IOException | XMPPException e) {
throw new IllegalStateException(e);
}
return dummyConnection;
}
public static class DummyConnectionConfiguration extends ConnectionConfiguration { public static class DummyConnectionConfiguration extends ConnectionConfiguration {
protected DummyConnectionConfiguration(Builder builder) { protected DummyConnectionConfiguration(Builder builder) {
super(builder); super(builder);

View file

@ -26,6 +26,7 @@ import static org.junit.Assert.fail;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
@ -36,6 +37,7 @@ import org.jivesoftware.smack.packet.IQ.Type;
import org.jivesoftware.smack.packet.RosterPacket.Item; import org.jivesoftware.smack.packet.RosterPacket.Item;
import org.jivesoftware.smack.packet.RosterPacket.ItemType; import org.jivesoftware.smack.packet.RosterPacket.ItemType;
import org.jivesoftware.smack.test.util.TestUtils; import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smack.test.util.WaitForPacketListener;
import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.util.PacketParserUtils;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -52,6 +54,7 @@ import org.xmlpull.v1.XmlPullParser;
public class RosterTest { public class RosterTest {
private DummyConnection connection; private DummyConnection connection;
private Roster roster;
private TestRosterListener rosterListener; private TestRosterListener rosterListener;
@Before @Before
@ -63,7 +66,9 @@ public class RosterTest {
connection.connect(); connection.connect();
connection.login(); connection.login();
rosterListener = new TestRosterListener(); rosterListener = new TestRosterListener();
connection.getRoster().addRosterListener(rosterListener); roster = connection.getRoster();
roster.addRosterListener(rosterListener);
connection.setPacketReplyTimeout(1000 * 60 * 5);
} }
@After @After
@ -83,19 +88,17 @@ public class RosterTest {
* <a href="http://xmpp.org/rfcs/rfc3921.html#roster-login" * <a href="http://xmpp.org/rfcs/rfc3921.html#roster-login"
* >RFC3921: Retrieving One's Roster on Login</a>. * >RFC3921: Retrieving One's Roster on Login</a>.
*/ */
@Test(timeout=5000) @Test
public void testSimpleRosterInitialization() throws Exception { public void testSimpleRosterInitialization() throws Exception {
// Setup
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster); assertNotNull("Can't get the roster from the provided connection!", roster);
assertFalse("Roster shouldn't be already initialized!", assertFalse("Roster shouldn't be already loaded!",
roster.rosterInitialized); roster.isLoaded());
// Perform roster initialization // Perform roster initialization
initRoster(connection, roster); initRoster();
// Verify roster // Verify roster
assertTrue("Roster can't be initialized!", roster.rosterInitialized); assertTrue("Roster can't be loaded!", roster.waitUntilLoaded());
verifyRomeosEntry(roster.getEntry("romeo@example.net")); verifyRomeosEntry(roster.getEntry("romeo@example.net"));
verifyMercutiosEntry(roster.getEntry("mercutio@example.com")); verifyMercutiosEntry(roster.getEntry("mercutio@example.com"));
verifyBenvoliosEntry(roster.getEntry("benvolio@example.net")); verifyBenvoliosEntry(roster.getEntry("benvolio@example.net"));
@ -121,7 +124,7 @@ public class RosterTest {
* <a href="http://xmpp.org/rfcs/rfc3921.html#roster-add" * <a href="http://xmpp.org/rfcs/rfc3921.html#roster-add"
* >RFC3921: Adding a Roster Item</a>. * >RFC3921: Adding a Roster Item</a>.
*/ */
@Test(timeout=5000) @Test
public void testAddRosterItem() throws Throwable { public void testAddRosterItem() throws Throwable {
// Constants for the new contact // Constants for the new contact
final String contactJID = "nurse@example.com"; final String contactJID = "nurse@example.com";
@ -129,9 +132,8 @@ public class RosterTest {
final String[] contactGroup = {"Servants"}; final String[] contactGroup = {"Servants"};
// Setup // Setup
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster); assertNotNull("Can't get the roster from the provided connection!", roster);
initRoster(connection, roster); initRoster();
rosterListener.reset(); rosterListener.reset();
// Adding the new roster item // Adding the new roster item
@ -161,6 +163,7 @@ public class RosterTest {
if (exception != null) { if (exception != null) {
throw exception; throw exception;
} }
rosterListener.waitUntilInvocationOrTimeout();
// Verify the roster entry of the new contact // Verify the roster entry of the new contact
final RosterEntry addedEntry = roster.getEntry(contactJID); final RosterEntry addedEntry = roster.getEntry(contactJID);
@ -192,7 +195,7 @@ public class RosterTest {
* <a href="http://xmpp.org/rfcs/rfc3921.html#roster-update" * <a href="http://xmpp.org/rfcs/rfc3921.html#roster-update"
* >RFC3921: Updating a Roster Item</a>. * >RFC3921: Updating a Roster Item</a>.
*/ */
@Test(timeout=5000) @Test
public void testUpdateRosterItem() throws Throwable { public void testUpdateRosterItem() throws Throwable {
// Constants for the updated contact // Constants for the updated contact
final String contactJID = "romeo@example.net"; final String contactJID = "romeo@example.net";
@ -200,9 +203,8 @@ public class RosterTest {
final String[] contactGroups = {"Friends", "Lovers"}; final String[] contactGroups = {"Friends", "Lovers"};
// Setup // Setup
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster); assertNotNull("Can't get the roster from the provided connection!", roster);
initRoster(connection, roster); initRoster();
rosterListener.reset(); rosterListener.reset();
// Updating the roster item // Updating the roster item
@ -235,6 +237,7 @@ public class RosterTest {
if (exception != null) { if (exception != null) {
throw exception; throw exception;
} }
rosterListener.waitUntilInvocationOrTimeout();
// Verify the roster entry of the updated contact // Verify the roster entry of the updated contact
final RosterEntry addedEntry = roster.getEntry(contactJID); final RosterEntry addedEntry = roster.getEntry(contactJID);
@ -267,15 +270,14 @@ public class RosterTest {
* <a href="http://xmpp.org/rfcs/rfc3921.html#roster-delete" * <a href="http://xmpp.org/rfcs/rfc3921.html#roster-delete"
* >RFC3921: Deleting a Roster Item</a>. * >RFC3921: Deleting a Roster Item</a>.
*/ */
@Test(timeout=5000) @Test
public void testDeleteRosterItem() throws Throwable { public void testDeleteRosterItem() throws Throwable {
// The contact which should be deleted // The contact which should be deleted
final String contactJID = "romeo@example.net"; final String contactJID = "romeo@example.net";
// Setup // Setup
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster); assertNotNull("Can't get the roster from the provided connection!", roster);
initRoster(connection, roster); initRoster();
rosterListener.reset(); rosterListener.reset();
// Delete a roster item // Delete a roster item
@ -296,6 +298,7 @@ public class RosterTest {
if (exception != null) { if (exception != null) {
throw exception; throw exception;
} }
rosterListener.waitUntilInvocationOrTimeout();
// Verify // Verify
final RosterEntry deletedEntry = roster.getEntry(contactJID); final RosterEntry deletedEntry = roster.getEntry(contactJID);
@ -314,10 +317,9 @@ public class RosterTest {
* <a href="http://xmpp.org/internet-drafts/draft-ietf-xmpp-3921bis-03.html#roster-syntax-actions-push" * <a href="http://xmpp.org/internet-drafts/draft-ietf-xmpp-3921bis-03.html#roster-syntax-actions-push"
* >RFC3921bis-03: Roster Push</a>. * >RFC3921bis-03: Roster Push</a>.
*/ */
@Test(timeout=5000) @Test
public void testSimpleRosterPush() throws Throwable { public void testSimpleRosterPush() throws Throwable {
final String contactJID = "nurse@example.com"; final String contactJID = "nurse@example.com";
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster); assertNotNull("Can't get the roster from the provided connection!", roster);
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("<iq id=\"rostertest1\" type=\"set\" ") sb.append("<iq id=\"rostertest1\" type=\"set\" ")
@ -328,11 +330,12 @@ public class RosterTest {
.append("</iq>"); .append("</iq>");
final XmlPullParser parser = TestUtils.getIQParser(sb.toString()); final XmlPullParser parser = TestUtils.getIQParser(sb.toString());
final IQ rosterPush = PacketParserUtils.parse(parser, connection); final IQ rosterPush = PacketParserUtils.parse(parser, connection);
initRoster(connection, roster); initRoster();
rosterListener.reset(); rosterListener.reset();
// Simulate receiving the roster push // Simulate receiving the roster push
connection.processPacket(rosterPush); connection.processPacket(rosterPush);
rosterListener.waitUntilInvocationOrTimeout();
// Verify the roster entry of the new contact // Verify the roster entry of the new contact
final RosterEntry addedEntry = roster.getEntry(contactJID); final RosterEntry addedEntry = roster.getEntry(contactJID);
@ -358,7 +361,7 @@ public class RosterTest {
* *
* @see <a href="http://xmpp.org/rfcs/rfc6121.html#roster-syntax-actions-push">RFC 6121, Section 2.1.6</a> * @see <a href="http://xmpp.org/rfcs/rfc6121.html#roster-syntax-actions-push">RFC 6121, Section 2.1.6</a>
*/ */
@Test(timeout=5000) @Test
public void testIgnoreInvalidFrom() { public void testIgnoreInvalidFrom() {
RosterPacket packet = new RosterPacket(); RosterPacket packet = new RosterPacket();
packet.setType(Type.set); packet.setType(Type.set);
@ -366,8 +369,11 @@ public class RosterTest {
packet.setFrom("mallory@example.com"); packet.setFrom("mallory@example.com");
packet.addRosterItem(new Item("spam@example.com", "Cool products!")); packet.addRosterItem(new Item("spam@example.com", "Cool products!"));
WaitForPacketListener waitForPacketListener = new WaitForPacketListener();
connection.addAsyncPacketListener(waitForPacketListener, null);
// Simulate receiving the roster push // Simulate receiving the roster push
connection.processPacket(packet); connection.processPacket(packet);
waitForPacketListener.waitUntilInvocationOrTimeout();
assertNull("Contact was added to roster", connection.getRoster().getEntry("spam@example.com")); assertNull("Contact was added to roster", connection.getRoster().getEntry("spam@example.com"));
} }
@ -386,9 +392,8 @@ public class RosterTest {
final String[] contactGroup = {""}; final String[] contactGroup = {""};
// Setup // Setup
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster); assertNotNull("Can't get the roster from the provided connection!", roster);
initRoster(connection, roster); initRoster();
rosterListener.reset(); rosterListener.reset();
// Adding the new roster item // Adding the new roster item
@ -416,6 +421,7 @@ public class RosterTest {
if (exception != null) { if (exception != null) {
throw exception; throw exception;
} }
rosterListener.waitUntilInvocationOrTimeout();
// Verify the roster entry of the new contact // Verify the roster entry of the new contact
final RosterEntry addedEntry = roster.getEntry(contactJID); final RosterEntry addedEntry = roster.getEntry(contactJID);
@ -445,10 +451,9 @@ public class RosterTest {
* *
* @see <a href="http://www.igniterealtime.org/issues/browse/SMACK-294">SMACK-294</a> * @see <a href="http://www.igniterealtime.org/issues/browse/SMACK-294">SMACK-294</a>
*/ */
@Test(timeout=5000) @Test
public void testEmptyGroupRosterPush() throws Throwable { public void testEmptyGroupRosterPush() throws Throwable {
final String contactJID = "nurse@example.com"; final String contactJID = "nurse@example.com";
final Roster roster = connection.getRoster();
assertNotNull("Can't get the roster from the provided connection!", roster); assertNotNull("Can't get the roster from the provided connection!", roster);
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("<iq id=\"rostertest2\" type=\"set\" ") sb.append("<iq id=\"rostertest2\" type=\"set\" ")
@ -461,11 +466,12 @@ public class RosterTest {
.append("</iq>"); .append("</iq>");
final XmlPullParser parser = TestUtils.getIQParser(sb.toString()); final XmlPullParser parser = TestUtils.getIQParser(sb.toString());
final IQ rosterPush = PacketParserUtils.parse(parser, connection); final IQ rosterPush = PacketParserUtils.parse(parser, connection);
initRoster(connection, roster); initRoster();
rosterListener.reset(); rosterListener.reset();
// Simulate receiving the roster push // Simulate receiving the roster push
connection.processPacket(rosterPush); connection.processPacket(rosterPush);
rosterListener.waitUntilInvocationOrTimeout();
// Verify the roster entry of the new contact // Verify the roster entry of the new contact
final RosterEntry addedEntry = roster.getEntry(contactJID); final RosterEntry addedEntry = roster.getEntry(contactJID);
@ -520,7 +526,7 @@ public class RosterTest {
* @param roster the roster (or buddy list) which should be initialized. * @param roster the roster (or buddy list) which should be initialized.
* @throws SmackException * @throws SmackException
*/ */
public static void initRoster(DummyConnection connection, Roster roster) throws InterruptedException, XMPPException, SmackException { private void initRoster() throws InterruptedException, XMPPException, SmackException {
roster.reload(); roster.reload();
while (true) { while (true) {
final Packet sentPacket = connection.getSentPacket(); final Packet sentPacket = connection.getSentPacket();
@ -558,6 +564,8 @@ public class RosterTest {
break; break;
} }
} }
roster.waitUntilLoaded();
rosterListener.waitUntilInvocationOrTimeout();
} }
/** /**
@ -687,10 +695,10 @@ public class RosterTest {
/** /**
* This class can be used to check if the RosterListener was invoked. * This class can be used to check if the RosterListener was invoked.
*/ */
public static class TestRosterListener implements RosterListener { public static class TestRosterListener extends WaitForPacketListener implements RosterListener {
private CopyOnWriteArrayList<String> addressesAdded = new CopyOnWriteArrayList<String>(); private final List<String> addressesAdded = new CopyOnWriteArrayList<>();
private CopyOnWriteArrayList<String> addressesDeleted = new CopyOnWriteArrayList<String>(); private final List<String> addressesDeleted = new CopyOnWriteArrayList<>();
private CopyOnWriteArrayList<String> addressesUpdated = new CopyOnWriteArrayList<String>(); private final List<String> addressesUpdated = new CopyOnWriteArrayList<>();
public synchronized void entriesAdded(Collection<String> addresses) { public synchronized void entriesAdded(Collection<String> addresses) {
addressesAdded.addAll(addresses); addressesAdded.addAll(addresses);
@ -699,6 +707,7 @@ public class RosterTest {
System.out.println("Roster entry for " + address + " added."); System.out.println("Roster entry for " + address + " added.");
} }
} }
reportInvoked();
} }
public synchronized void entriesDeleted(Collection<String> addresses) { public synchronized void entriesDeleted(Collection<String> addresses) {
@ -708,6 +717,7 @@ public class RosterTest {
System.out.println("Roster entry for " + address + " deleted."); System.out.println("Roster entry for " + address + " deleted.");
} }
} }
reportInvoked();
} }
public synchronized void entriesUpdated(Collection<String> addresses) { public synchronized void entriesUpdated(Collection<String> addresses) {
@ -717,12 +727,14 @@ public class RosterTest {
System.out.println("Roster entry for " + address + " updated."); System.out.println("Roster entry for " + address + " updated.");
} }
} }
reportInvoked();
} }
public void presenceChanged(Presence presence) { public void presenceChanged(Presence presence) {
if (SmackConfiguration.DEBUG_ENABLED) { if (SmackConfiguration.DEBUG_ENABLED) {
System.out.println("Roster presence changed: " + presence.toXML()); System.out.println("Roster presence changed: " + presence.toXML());
} }
reportInvoked();
} }
/** /**
@ -756,6 +768,7 @@ public class RosterTest {
* Reset the lists of added, deleted or updated items. * Reset the lists of added, deleted or updated items.
*/ */
public synchronized void reset() { public synchronized void reset() {
super.reset();
addressesAdded.clear(); addressesAdded.clear();
addressesDeleted.clear(); addressesDeleted.clear();
addressesUpdated.clear(); addressesUpdated.clear();

View file

@ -27,6 +27,7 @@ import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import org.jivesoftware.smack.ConnectionConfiguration.Builder; import org.jivesoftware.smack.ConnectionConfiguration.Builder;
import org.jivesoftware.smack.RosterTest.TestRosterListener;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.IQ.Type; import org.jivesoftware.smack.packet.IQ.Type;
import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.Packet;
@ -53,15 +54,14 @@ import org.junit.rules.TemporaryFolder;
public class RosterVersioningTest { public class RosterVersioningTest {
private DummyConnection connection; private DummyConnection connection;
private Roster roster;
private TestRosterListener rosterListener;
@Rule @Rule
public TemporaryFolder tmpFolder = new TemporaryFolder(); public TemporaryFolder tmpFolder = new TemporaryFolder();
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
// Uncomment this to enable debug output
//XMPPConnection.DEBUG_ENABLED = true;
DirectoryRosterStore store = DirectoryRosterStore.init(tmpFolder.newFolder("store")); DirectoryRosterStore store = DirectoryRosterStore.init(tmpFolder.newFolder("store"));
populateStore(store); populateStore(store);
@ -69,13 +69,20 @@ public class RosterVersioningTest {
builder.setRosterStore(store); builder.setRosterStore(store);
connection = new DummyConnection(builder.build()); connection = new DummyConnection(builder.build());
connection.connect(); connection.connect();
connection.login(); connection.login();
rosterListener = new TestRosterListener();
roster = connection.getRoster();
roster.addRosterListener(rosterListener);
roster.reload();
} }
@After @After
public void tearDown() throws Exception { public void tearDown() throws Exception {
if (connection != null) { if (connection != null) {
if (rosterListener != null && roster != null) {
roster.removeRosterListener(rosterListener);
rosterListener = null;
}
connection.disconnect(); connection.disconnect();
connection = null; connection = null;
} }
@ -89,10 +96,9 @@ public class RosterVersioningTest {
*/ */
@Test(timeout = 5000) @Test(timeout = 5000)
public void testEqualVersionStored() throws InterruptedException, IOException, XMPPException, SmackException { public void testEqualVersionStored() throws InterruptedException, IOException, XMPPException, SmackException {
connection.getRoster().reload();
answerWithEmptyRosterResult(); answerWithEmptyRosterResult();
roster.waitUntilLoaded();
Roster roster = connection.getRoster();
Collection<RosterEntry> entries = roster.getEntries(); Collection<RosterEntry> entries = roster.getEntries();
assertSame("Size of the roster", 3, entries.size()); assertSame("Size of the roster", 3, entries.size());
@ -124,8 +130,6 @@ public class RosterVersioningTest {
*/ */
@Test(timeout = 5000) @Test(timeout = 5000)
public void testOtherVersionStored() throws InterruptedException, XMPPException, SmackException { public void testOtherVersionStored() throws InterruptedException, XMPPException, SmackException {
connection.getRoster().reload();
Item vaglafItem = vaglafItem(); Item vaglafItem = vaglafItem();
// We expect that the roster request is the only packet sent. This is not part of the specification, // We expect that the roster request is the only packet sent. This is not part of the specification,
@ -141,7 +145,9 @@ public class RosterVersioningTest {
answer.setVersion("newVersion"); answer.setVersion("newVersion");
answer.addRosterItem(vaglafItem); answer.addRosterItem(vaglafItem);
rosterListener.reset();
connection.processPacket(answer); connection.processPacket(answer);
rosterListener.waitUntilInvocationOrTimeout();
} else { } else {
assertTrue("Expected to get a RosterPacket ", false); assertTrue("Expected to get a RosterPacket ", false);
} }
@ -164,11 +170,10 @@ public class RosterVersioningTest {
*/ */
@Test(timeout = 5000) @Test(timeout = 5000)
public void testRosterVersioningWithCachedRosterAndPushes() throws Throwable { public void testRosterVersioningWithCachedRosterAndPushes() throws Throwable {
connection.getRoster().reload();
answerWithEmptyRosterResult(); answerWithEmptyRosterResult();
rosterListener.waitAndReset();
RosterStore store = connection.getConfiguration().getRosterStore(); RosterStore store = connection.getConfiguration().getRosterStore();
Roster roster = connection.getRoster();
// Simulate a roster push adding vaglaf // Simulate a roster push adding vaglaf
{ {
@ -179,7 +184,9 @@ public class RosterVersioningTest {
Item pushedItem = vaglafItem(); Item pushedItem = vaglafItem();
rosterPush.addRosterItem(pushedItem); rosterPush.addRosterItem(pushedItem);
rosterListener.reset();
connection.processPacket(rosterPush); connection.processPacket(rosterPush);
rosterListener.waitAndReset();
assertEquals("Expect store version after push", "v97", store.getRosterVersion()); assertEquals("Expect store version after push", "v97", store.getRosterVersion());
@ -204,7 +211,9 @@ public class RosterVersioningTest {
Item item = new Item("vaglaf@example.com", "vaglaf the only"); Item item = new Item("vaglaf@example.com", "vaglaf the only");
item.setItemType(ItemType.remove); item.setItemType(ItemType.remove);
rosterPush.addRosterItem(item); rosterPush.addRosterItem(item);
rosterListener.reset();
connection.processPacket(rosterPush); connection.processPacket(rosterPush);
rosterListener.waitAndReset();
assertNull("Store doses not contain vaglaf", store.getEntry("vaglaf@example.com")); assertNull("Store doses not contain vaglaf", store.getEntry("vaglaf@example.com"));
assertEquals("Expect store version after push", "v98", store.getRosterVersion()); assertEquals("Expect store version after push", "v98", store.getRosterVersion());

View file

@ -0,0 +1,60 @@
/**
*
* Copyright 2015 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.test.util;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.packet.Packet;
public class WaitForPacketListener implements PacketListener {
private CountDownLatch latch = new CountDownLatch(1);
@Override
public void processPacket(Packet packet) throws NotConnectedException {
reportInvoked();
}
protected void reportInvoked() {
latch.countDown();
}
public void waitAndReset() {
waitUntilInvocationOrTimeout();
reset();
}
public void waitUntilInvocationOrTimeout() {
try {
boolean res = latch.await(30, TimeUnit.SECONDS);
if (!res) {
throw new IllegalStateException("Latch timed out before it reached zero");
}
}
catch (InterruptedException e) {
// TODO better handling of spurious interrupts
throw new IllegalStateException(e);
}
}
public void reset() {
latch = new CountDownLatch(1);
}
}

View file

@ -956,7 +956,7 @@ public class EnhancedDebugger implements SmackDebugger {
*/ */
void cancel() { void cancel() {
connection.removeConnectionListener(connListener); connection.removeConnectionListener(connListener);
connection.removePacketListener(packetReaderListener); connection.removeAsyncPacketListener(packetReaderListener);
connection.removePacketSendingListener(packetWriterListener); connection.removePacketSendingListener(packetWriterListener);
((ObservableReader) reader).removeReaderListener(readerListener); ((ObservableReader) reader).removeReaderListener(readerListener);
((ObservableWriter) writer).removeWriterListener(writerListener); ((ObservableWriter) writer).removeWriterListener(writerListener);

View file

@ -278,7 +278,7 @@ public class LiteDebugger implements SmackDebugger {
* @param evt the event that indicates that the root window is closing * @param evt the event that indicates that the root window is closing
*/ */
public void rootWindowClosing(WindowEvent evt) { public void rootWindowClosing(WindowEvent evt) {
connection.removePacketListener(listener); connection.removeAsyncPacketListener(listener);
((ObservableReader)reader).removeReaderListener(readerListener); ((ObservableReader)reader).removeReaderListener(readerListener);
((ObservableWriter)writer).removeWriterListener(writerListener); ((ObservableWriter)writer).removeWriterListener(writerListener);
} }

View file

@ -101,7 +101,7 @@ public class MessageEventTest extends SmackTestCase {
} }
} }
}; };
getConnection(0).addPacketListener(packetListener, packetFilter); getConnection(0).addAsyncPacketListener(packetListener, packetFilter);
// Create the message to send with the roster // Create the message to send with the roster
Message msg = new Message(); Message msg = new Message();

View file

@ -150,7 +150,7 @@ public class XHTMLExtensionTest extends SmackTestCase {
} }
}; };
getConnection(1).addPacketListener(packetListener, packetFilter); getConnection(1).addAsyncPacketListener(packetListener, packetFilter);
// User1 creates a message to send to user2 // User1 creates a message to send to user2
Message msg = new Message(); Message msg = new Message();

View file

@ -215,16 +215,16 @@ public class InBandBytestreamManager implements BytestreamManager {
// register bytestream open packet listener // register bytestream open packet listener
this.initiationListener = new InitiationListener(this); this.initiationListener = new InitiationListener(this);
this.connection.addPacketListener(this.initiationListener, this.connection.addAsyncPacketListener(this.initiationListener,
this.initiationListener.getFilter()); this.initiationListener.getFilter());
// register bytestream data packet listener // register bytestream data packet listener
this.dataListener = new DataListener(this); this.dataListener = new DataListener(this);
this.connection.addPacketListener(this.dataListener, this.dataListener.getFilter()); this.connection.addSyncPacketListener(this.dataListener, this.dataListener.getFilter());
// register bytestream close packet listener // register bytestream close packet listener
this.closeListener = new CloseListener(this); this.closeListener = new CloseListener(this);
this.connection.addPacketListener(this.closeListener, this.closeListener.getFilter()); this.connection.addSyncPacketListener(this.closeListener, this.closeListener.getFilter());
} }
@ -548,9 +548,9 @@ public class InBandBytestreamManager implements BytestreamManager {
managers.remove(connection); managers.remove(connection);
// remove all listeners registered by this manager // remove all listeners registered by this manager
this.connection.removePacketListener(this.initiationListener); this.connection.removeAsyncPacketListener(this.initiationListener);
this.connection.removePacketListener(this.dataListener); this.connection.removeSyncPacketListener(this.dataListener);
this.connection.removePacketListener(this.closeListener); this.connection.removeSyncPacketListener(this.closeListener);
// shutdown threads // shutdown threads
this.initiationListener.shutdown(); this.initiationListener.shutdown();

View file

@ -264,7 +264,7 @@ public class InBandBytestreamSession implements BytestreamSession {
public IBBInputStream() { public IBBInputStream() {
// add data packet listener to connection // add data packet listener to connection
this.dataPacketListener = getDataPacketListener(); this.dataPacketListener = getDataPacketListener();
connection.addPacketListener(this.dataPacketListener, getDataPacketFilter()); connection.addSyncPacketListener(this.dataPacketListener, getDataPacketFilter());
} }
/** /**
@ -431,7 +431,7 @@ public class InBandBytestreamSession implements BytestreamSession {
* Invoked if the session is closed. * Invoked if the session is closed.
*/ */
private void cleanup() { private void cleanup() {
connection.removePacketListener(this.dataPacketListener); connection.removeSyncPacketListener(this.dataPacketListener);
} }
} }

View file

@ -289,7 +289,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
public synchronized void disableService() { public synchronized void disableService() {
// remove initiation packet listener // remove initiation packet listener
this.connection.removePacketListener(this.initiationListener); this.connection.removeAsyncPacketListener(this.initiationListener);
// shutdown threads // shutdown threads
this.initiationListener.shutdown(); this.initiationListener.shutdown();
@ -718,7 +718,7 @@ public final class Socks5BytestreamManager implements BytestreamManager {
*/ */
private void activate() { private void activate() {
// register bytestream initiation packet listener // register bytestream initiation packet listener
this.connection.addPacketListener(this.initiationListener, this.connection.addAsyncPacketListener(this.initiationListener,
this.initiationListener.getFilter()); this.initiationListener.getFilter());
// enable SOCKS5 feature // enable SOCKS5 feature

View file

@ -315,7 +315,7 @@ public class EntityCapsManager extends Manager {
if (autoEnableEntityCaps) if (autoEnableEntityCaps)
enableEntityCaps(); enableEntityCaps();
connection.addPacketListener(new PacketListener() { connection.addAsyncPacketListener(new PacketListener() {
// Listen for remote presence stanzas with the caps extension // Listen for remote presence stanzas with the caps extension
// If we receive such a stanza, record the JID and nodeVer // If we receive such a stanza, record the JID and nodeVer
@Override @Override
@ -330,7 +330,7 @@ public class EntityCapsManager extends Manager {
}, PRESENCES_WITH_CAPS); }, PRESENCES_WITH_CAPS);
connection.addPacketListener(new PacketListener() { connection.addAsyncPacketListener(new PacketListener() {
@Override @Override
public void processPacket(Packet packet) { public void processPacket(Packet packet) {
// always remove the JID from the map, even if entityCaps are // always remove the JID from the map, even if entityCaps are

View file

@ -148,7 +148,7 @@ public class ServiceDiscoveryManager extends Manager {
connection().sendPacket(response); connection().sendPacket(response);
} }
}; };
connection.addPacketListener(packetListener, GET_DISCOVER_ITEMS); connection.addAsyncPacketListener(packetListener, GET_DISCOVER_ITEMS);
// Listen for disco#info requests and answer the client's supported features // Listen for disco#info requests and answer the client's supported features
// To add a new feature as supported use the #addFeature message // To add a new feature as supported use the #addFeature message
@ -187,7 +187,7 @@ public class ServiceDiscoveryManager extends Manager {
connection().sendPacket(response); connection().sendPacket(response);
} }
}; };
connection.addPacketListener(packetListener, GET_DISCOVER_INFO); connection.addAsyncPacketListener(packetListener, GET_DISCOVER_INFO);
} }
/** /**

View file

@ -160,7 +160,7 @@ public class LastActivityManager extends Manager {
}, PacketTypeFilter.MESSAGE); }, PacketTypeFilter.MESSAGE);
// Register a listener for a last activity query // Register a listener for a last activity query
connection.addPacketListener(new PacketListener() { connection.addAsyncPacketListener(new PacketListener() {
public void processPacket(Packet packet) throws NotConnectedException { public void processPacket(Packet packet) throws NotConnectedException {
if (!enabled) return; if (!enabled) return;

View file

@ -86,7 +86,7 @@ public class VersionManager extends Manager {
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection); ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
sdm.addFeature(Version.NAMESPACE); sdm.addFeature(Version.NAMESPACE);
connection.addPacketListener(new PacketListener() { connection.addAsyncPacketListener(new PacketListener() {
/** /**
* Sends a Version reply on request * Sends a Version reply on request
* @throws NotConnectedException * @throws NotConnectedException

View file

@ -292,12 +292,12 @@ public class MultiUserChat {
+ nickname), new PacketTypeFilter(Presence.class)); + nickname), new PacketTypeFilter(Presence.class));
// Setup the messageListeners and presenceListeners *before* the join presence is send. // Setup the messageListeners and presenceListeners *before* the join presence is send.
connection.addPacketListener(messageListener, fromRoomGroupchatFilter); connection.addSyncPacketListener(messageListener, fromRoomGroupchatFilter);
connection.addPacketListener(presenceListener, new AndFilter(fromRoomFilter, connection.addSyncPacketListener(presenceListener, new AndFilter(fromRoomFilter,
PacketTypeFilter.PRESENCE)); PacketTypeFilter.PRESENCE));
connection.addPacketListener(subjectListener, new AndFilter(fromRoomFilter, connection.addSyncPacketListener(subjectListener, new AndFilter(fromRoomFilter,
MessageWithSubjectFilter.INSTANCE)); MessageWithSubjectFilter.INSTANCE));
connection.addPacketListener(declinesListener, new AndFilter(new PacketExtensionFilter(MUCUser.ELEMENT, connection.addSyncPacketListener(declinesListener, new AndFilter(new PacketExtensionFilter(MUCUser.ELEMENT,
MUCUser.NAMESPACE), new NotFilter(MessageTypeFilter.ERROR))); MUCUser.NAMESPACE), new NotFilter(MessageTypeFilter.ERROR)));
connection.addPacketInterceptor(presenceInterceptor, new AndFilter(new ToFilter(room), connection.addPacketInterceptor(presenceInterceptor, new AndFilter(new ToFilter(room),
PacketTypeFilter.PRESENCE)); PacketTypeFilter.PRESENCE));
@ -1702,9 +1702,9 @@ public class MultiUserChat {
* connection. * connection.
*/ */
private void removeConnectionCallbacks() { private void removeConnectionCallbacks() {
connection.removePacketListener(messageListener); connection.removeSyncPacketListener(messageListener);
connection.removePacketListener(presenceListener); connection.removeSyncPacketListener(presenceListener);
connection.removePacketListener(declinesListener); connection.removeSyncPacketListener(declinesListener);
connection.removePacketInterceptor(presenceInterceptor); connection.removePacketInterceptor(presenceInterceptor);
if (messageCollector != null) { if (messageCollector != null) {
messageCollector.cancel(); messageCollector.cancel();

View file

@ -142,12 +142,12 @@ public class PEPManager {
firePEPListeners(message.getFrom(), event); firePEPListeners(message.getFrom(), event);
} }
}; };
connection.addPacketListener(packetListener, packetFilter); connection.addSyncPacketListener(packetListener, packetFilter);
} }
public void destroy() { public void destroy() {
if (connection != null) if (connection != null)
connection.removePacketListener(packetListener); connection.removeSyncPacketListener(packetListener);
} }
protected void finalize() throws Throwable { protected void finalize() throws Throwable {

View file

@ -127,7 +127,7 @@ public class PingManager extends Manager {
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection); ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
sdm.addFeature(Ping.NAMESPACE); sdm.addFeature(Ping.NAMESPACE);
connection.addPacketListener(new PacketListener() { connection.addAsyncPacketListener(new PacketListener() {
// Send a Pong for every Ping // Send a Pong for every Ping
@Override @Override
public void processPacket(Packet packet) throws NotConnectedException { public void processPacket(Packet packet) throws NotConnectedException {

View file

@ -85,7 +85,7 @@ public class PrivacyListManager extends Manager {
private PrivacyListManager(final XMPPConnection connection) { private PrivacyListManager(final XMPPConnection connection) {
super(connection); super(connection);
connection.addPacketListener(new PacketListener() { connection.addSyncPacketListener(new PacketListener() {
@Override @Override
public void processPacket(Packet packet) throws NotConnectedException { public void processPacket(Packet packet) throws NotConnectedException {
Privacy privacy = (Privacy) packet; Privacy privacy = (Privacy) packet;

View file

@ -399,7 +399,7 @@ abstract public class Node
{ {
PacketListener conListener = new ItemEventTranslator(listener); PacketListener conListener = new ItemEventTranslator(listener);
itemEventToListenerMap.put(listener, conListener); itemEventToListenerMap.put(listener, conListener);
con.addPacketListener(conListener, new EventContentFilter(EventElementType.items.toString(), "item")); con.addSyncPacketListener(conListener, new EventContentFilter(EventElementType.items.toString(), "item"));
} }
/** /**
@ -412,7 +412,7 @@ abstract public class Node
PacketListener conListener = itemEventToListenerMap.remove(listener); PacketListener conListener = itemEventToListenerMap.remove(listener);
if (conListener != null) if (conListener != null)
con.removePacketListener(conListener); con.removeSyncPacketListener(conListener);
} }
/** /**
@ -425,7 +425,7 @@ abstract public class Node
{ {
PacketListener conListener = new NodeConfigTranslator(listener); PacketListener conListener = new NodeConfigTranslator(listener);
configEventToListenerMap.put(listener, conListener); configEventToListenerMap.put(listener, conListener);
con.addPacketListener(conListener, new EventContentFilter(EventElementType.configuration.toString())); con.addSyncPacketListener(conListener, new EventContentFilter(EventElementType.configuration.toString()));
} }
/** /**
@ -438,7 +438,7 @@ abstract public class Node
PacketListener conListener = configEventToListenerMap .remove(listener); PacketListener conListener = configEventToListenerMap .remove(listener);
if (conListener != null) if (conListener != null)
con.removePacketListener(conListener); con.removeSyncPacketListener(conListener);
} }
/** /**
@ -454,7 +454,7 @@ abstract public class Node
EventContentFilter deleteItem = new EventContentFilter(EventElementType.items.toString(), "retract"); EventContentFilter deleteItem = new EventContentFilter(EventElementType.items.toString(), "retract");
EventContentFilter purge = new EventContentFilter(EventElementType.purge.toString()); EventContentFilter purge = new EventContentFilter(EventElementType.purge.toString());
con.addPacketListener(delListener, new OrFilter(deleteItem, purge)); con.addSyncPacketListener(delListener, new OrFilter(deleteItem, purge));
} }
/** /**
@ -467,7 +467,7 @@ abstract public class Node
PacketListener conListener = itemDeleteToListenerMap .remove(listener); PacketListener conListener = itemDeleteToListenerMap .remove(listener);
if (conListener != null) if (conListener != null)
con.removePacketListener(conListener); con.removeSyncPacketListener(conListener);
} }
@Override @Override

View file

@ -62,7 +62,7 @@ public class DeliveryReceiptManager extends Manager implements PacketListener {
sdm.addFeature(DeliveryReceipt.NAMESPACE); sdm.addFeature(DeliveryReceipt.NAMESPACE);
// register listener for delivery receipts and requests // register listener for delivery receipts and requests
connection.addPacketListener(this, new PacketExtensionFilter(DeliveryReceipt.NAMESPACE)); connection.addAsyncPacketListener(this, new PacketExtensionFilter(DeliveryReceipt.NAMESPACE));
} }
/** /**

View file

@ -72,7 +72,7 @@ public class EntityTimeManager extends Manager {
if (autoEnable) if (autoEnable)
enable(); enable();
connection.addPacketListener(new PacketListener() { connection.addAsyncPacketListener(new PacketListener() {
@Override @Override
public void processPacket(Packet packet) throws NotConnectedException { public void processPacket(Packet packet) throws NotConnectedException {
if (!enabled) if (!enabled)

View file

@ -159,7 +159,7 @@ public class JingleManagerTest extends SmackTestCase {
}; };
// Start a packet listener for session initiation requests // Start a packet listener for session initiation requests
getConnection(0).addPacketListener(new PacketListener() { getConnection(0).addAsyncPacketListener(new PacketListener() {
public void processPacket(final Packet packet) { public void processPacket(final Packet packet) {
System.out.println("Packet detected... "); System.out.println("Packet detected... ");
incCounter(); incCounter();

View file

@ -461,7 +461,7 @@ public class JingleManager implements JingleSessionListener {
jingleSessionRequestListeners = new ArrayList<JingleSessionRequestListener>(); jingleSessionRequestListeners = new ArrayList<JingleSessionRequestListener>();
// Start a packet listener for session initiation requests // Start a packet listener for session initiation requests
connection.addPacketListener(new PacketListener() { connection.addAsyncPacketListener(new PacketListener() {
public void processPacket(Packet packet) { public void processPacket(Packet packet) {
triggerSessionRequested((Jingle) packet); triggerSessionRequested((Jingle) packet);
} }

View file

@ -654,9 +654,9 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
/** /**
* Remove the packet listener used for processing packet. * Remove the packet listener used for processing packet.
*/ */
protected void removePacketListener() { protected void removeAsyncPacketListener() {
if (packetListener != null) { if (packetListener != null) {
getConnection().removePacketListener(packetListener); getConnection().removeAsyncPacketListener(packetListener);
LOGGER.fine("JINGLE SESSION: REMOVE PACKET LISTENER"); LOGGER.fine("JINGLE SESSION: REMOVE PACKET LISTENER");
} }
@ -667,7 +667,7 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
* to any packet that we receive... * to any packet that we receive...
*/ */
protected void updatePacketListener() { protected void updatePacketListener() {
removePacketListener(); removeAsyncPacketListener();
LOGGER.fine("UpdatePacketListener"); LOGGER.fine("UpdatePacketListener");
@ -728,7 +728,7 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
} }
}; };
getConnection().addPacketListener(packetListener, packetFilter); getConnection().addAsyncPacketListener(packetListener, packetFilter);
} }
// Listeners // Listeners
@ -1002,7 +1002,7 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
contentNegotiator.close(); contentNegotiator.close();
} }
removePacketListener(); removeAsyncPacketListener();
removeConnectionListener(); removeConnectionListener();
getConnection().removeConnectionListener(connectionListener); getConnection().removeConnectionListener(connectionListener);
LOGGER.fine("Negotiation Closed: " + getConnection().getUser() + " " + sid); LOGGER.fine("Negotiation Closed: " + getConnection().getUser() + " " + sid);

View file

@ -74,9 +74,9 @@ public class AgentRoster {
presenceMap = new HashMap<String, Map<String, Presence>>(); presenceMap = new HashMap<String, Map<String, Presence>>();
// Listen for any roster packets. // Listen for any roster packets.
PacketFilter rosterFilter = new PacketTypeFilter(AgentStatusRequest.class); PacketFilter rosterFilter = new PacketTypeFilter(AgentStatusRequest.class);
connection.addPacketListener(new AgentStatusListener(), rosterFilter); connection.addAsyncPacketListener(new AgentStatusListener(), rosterFilter);
// Listen for any presence packets. // Listen for any presence packets.
connection.addPacketListener(new PresencePacketListener(), connection.addAsyncPacketListener(new PresencePacketListener(),
new PacketTypeFilter(Presence.class)); new PacketTypeFilter(Presence.class));
// Send request for roster. // Send request for roster.

View file

@ -157,7 +157,7 @@ public class AgentSession {
} }
} }
}; };
connection.addPacketListener(packetListener, filter); connection.addAsyncPacketListener(packetListener, filter);
// Create the agent associated to this session // Create the agent associated to this session
agent = new Agent(connection, workgroupJID); agent = new Agent(connection, workgroupJID);
} }
@ -167,7 +167,7 @@ public class AgentSession {
* packet listeners that were added by this agent session will be removed. * packet listeners that were added by this agent session will be removed.
*/ */
public void close() { public void close() {
connection.removePacketListener(packetListener); connection.removeAsyncPacketListener(packetListener);
} }
/** /**

View file

@ -142,7 +142,7 @@ public class Workgroup {
// Register a packet listener for all the messages sent to this client. // Register a packet listener for all the messages sent to this client.
PacketFilter typeFilter = new PacketTypeFilter(Message.class); PacketFilter typeFilter = new PacketTypeFilter(Message.class);
connection.addPacketListener(new PacketListener() { connection.addAsyncPacketListener(new PacketListener() {
public void processPacket(Packet packet) { public void processPacket(Packet packet) {
handlePacket(packet); handlePacket(packet);
} }

View file

@ -75,7 +75,7 @@ public class MessageEventManager extends Manager {
private MessageEventManager(XMPPConnection connection) { private MessageEventManager(XMPPConnection connection) {
super(connection); super(connection);
// Listens for all message event packets and fire the proper message event listeners. // Listens for all message event packets and fire the proper message event listeners.
connection.addPacketListener(new PacketListener() { connection.addAsyncPacketListener(new PacketListener() {
public void processPacket(Packet packet) { public void processPacket(Packet packet) {
Message message = (Message) packet; Message message = (Message) packet;
MessageEvent messageEvent = MessageEvent messageEvent =

View file

@ -85,7 +85,7 @@ public class RosterExchangeManager {
fireRosterExchangeListeners(message.getFrom(), rosterExchange.getRosterEntries()); fireRosterExchangeListeners(message.getFrom(), rosterExchange.getRosterEntries());
} }
}; };
connection.addPacketListener(packetListener, PACKET_FILTER); connection.addAsyncPacketListener(packetListener, PACKET_FILTER);
} }
/** /**

View file

@ -568,7 +568,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
// If debugging is enabled, we should start the thread that will listen for // If debugging is enabled, we should start the thread that will listen for
// all packets and then log them. // all packets and then log them.
if (config.isDebuggerEnabled()) { if (config.isDebuggerEnabled()) {
addPacketListener(debugger.getReaderListener(), null); addAsyncPacketListener(debugger.getReaderListener(), null);
if (debugger.getWriterListener() != null) { if (debugger.getWriterListener() != null) {
addPacketSendingListener(debugger.getWriterListener(), null); addPacketSendingListener(debugger.getWriterListener(), null);
} }