mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-16 04:12:04 +01:00
Don't remove the MUC listeners after a disconnect
keep state of XMPPConnection between disconnects. Fixes SMACK-571
This commit is contained in:
parent
12b9e9d507
commit
8bf30b960c
1 changed files with 16 additions and 62 deletions
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
package org.jivesoftware.smackx.muc;
|
package org.jivesoftware.smackx.muc;
|
||||||
|
|
||||||
import org.jivesoftware.smack.AbstractConnectionListener;
|
import org.jivesoftware.smack.Manager;
|
||||||
import org.jivesoftware.smack.PacketListener;
|
import org.jivesoftware.smack.PacketListener;
|
||||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
@ -25,7 +25,6 @@ import org.jivesoftware.smack.filter.PacketFilter;
|
||||||
import org.jivesoftware.smack.packet.Packet;
|
import org.jivesoftware.smack.packet.Packet;
|
||||||
import org.jxmpp.util.XmppStringUtils;
|
import org.jxmpp.util.XmppStringUtils;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
@ -40,16 +39,14 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
*
|
*
|
||||||
* @author Larry Kirschner
|
* @author Larry Kirschner
|
||||||
*/
|
*/
|
||||||
class RoomListenerMultiplexor extends AbstractConnectionListener {
|
class RoomListenerMultiplexor extends Manager {
|
||||||
|
|
||||||
// We use a WeakHashMap so that the GC can collect the monitor when the
|
// We use a WeakHashMap so that the GC can collect the monitor when the
|
||||||
// connection is no longer referenced by any object.
|
// connection is no longer referenced by any object.
|
||||||
private static final Map<XMPPConnection, WeakReference<RoomListenerMultiplexor>> monitors =
|
private static final Map<XMPPConnection, RoomListenerMultiplexor> monitors = new WeakHashMap<XMPPConnection, RoomListenerMultiplexor>();
|
||||||
new WeakHashMap<XMPPConnection, WeakReference<RoomListenerMultiplexor>>();
|
|
||||||
|
|
||||||
private XMPPConnection connection;
|
private final RoomMultiplexFilter filter;
|
||||||
private RoomMultiplexFilter filter;
|
private final RoomMultiplexListener listener;
|
||||||
private RoomMultiplexListener listener;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new or existing RoomListenerMultiplexor for a given connection.
|
* Returns a new or existing RoomListenerMultiplexor for a given connection.
|
||||||
|
@ -57,22 +54,14 @@ class RoomListenerMultiplexor extends AbstractConnectionListener {
|
||||||
* @param conn the connection to monitor for room invitations.
|
* @param conn the connection to monitor for room invitations.
|
||||||
* @return a new or existing RoomListenerMultiplexor for a given connection.
|
* @return a new or existing RoomListenerMultiplexor for a given connection.
|
||||||
*/
|
*/
|
||||||
public static RoomListenerMultiplexor getRoomMultiplexor(XMPPConnection conn) {
|
public static synchronized RoomListenerMultiplexor getRoomMultiplexor(XMPPConnection conn) {
|
||||||
synchronized (monitors) {
|
RoomListenerMultiplexor rlm = monitors.get(conn);
|
||||||
if (!monitors.containsKey(conn) || monitors.get(conn).get() == null) {
|
if (rlm == null) {
|
||||||
RoomListenerMultiplexor rm = new RoomListenerMultiplexor(conn, new RoomMultiplexFilter(),
|
rlm = new RoomListenerMultiplexor(conn, new RoomMultiplexFilter(),
|
||||||
new RoomMultiplexListener());
|
new RoomMultiplexListener());
|
||||||
|
|
||||||
rm.init();
|
|
||||||
|
|
||||||
// We need to use a WeakReference because the monitor references the
|
|
||||||
// connection and this could prevent the GC from collecting the monitor
|
|
||||||
// when no other object references the monitor
|
|
||||||
monitors.put(conn, new WeakReference<RoomListenerMultiplexor>(rm));
|
|
||||||
}
|
}
|
||||||
// Return the InvitationsMonitor that monitors the connection
|
// Return the InvitationsMonitor that monitors the connection
|
||||||
return monitors.get(conn).get();
|
return rlm;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,18 +70,12 @@ class RoomListenerMultiplexor extends AbstractConnectionListener {
|
||||||
*/
|
*/
|
||||||
private RoomListenerMultiplexor(XMPPConnection connection, RoomMultiplexFilter filter,
|
private RoomListenerMultiplexor(XMPPConnection connection, RoomMultiplexFilter filter,
|
||||||
RoomMultiplexListener listener) {
|
RoomMultiplexListener listener) {
|
||||||
if (connection == null) {
|
super(connection);
|
||||||
throw new IllegalArgumentException("XMPPConnection is null");
|
connection.addPacketListener(listener, filter);
|
||||||
}
|
|
||||||
if (filter == null) {
|
|
||||||
throw new IllegalArgumentException("Filter is null");
|
|
||||||
}
|
|
||||||
if (listener == null) {
|
|
||||||
throw new IllegalArgumentException("Listener is null");
|
|
||||||
}
|
|
||||||
this.connection = connection;
|
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
|
monitors.put(connection, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addRoom(String address, PacketMultiplexListener roomListener) {
|
public void addRoom(String address, PacketMultiplexListener roomListener) {
|
||||||
|
@ -100,40 +83,11 @@ class RoomListenerMultiplexor extends AbstractConnectionListener {
|
||||||
listener.addRoom(address, roomListener);
|
listener.addRoom(address, roomListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void connectionClosed() {
|
|
||||||
cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void connectionClosedOnError(Exception e) {
|
|
||||||
cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the listeners to detect received room invitations and to detect when the
|
|
||||||
* connection gets closed. As soon as a room invitation is received the invitations
|
|
||||||
* listeners will be fired. When the connection gets closed the monitor will remove
|
|
||||||
* his listeners on the connection.
|
|
||||||
*/
|
|
||||||
public void init() {
|
|
||||||
connection.addConnectionListener(this);
|
|
||||||
connection.addPacketListener(listener, filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeRoom(String address) {
|
public void removeRoom(String address) {
|
||||||
filter.removeRoom(address);
|
filter.removeRoom(address);
|
||||||
listener.removeRoom(address);
|
listener.removeRoom(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancels all the listeners that this InvitationsMonitor has added to the connection.
|
|
||||||
*/
|
|
||||||
private void cancel() {
|
|
||||||
connection.removeConnectionListener(this);
|
|
||||||
connection.removePacketListener(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The single <code>XMPPConnection</code>-level <code>PacketFilter</code> used by a {@link RoomListenerMultiplexor}
|
* The single <code>XMPPConnection</code>-level <code>PacketFilter</code> used by a {@link RoomListenerMultiplexor}
|
||||||
* for all muc chat rooms on an <code>XMPPConnection</code>.
|
* for all muc chat rooms on an <code>XMPPConnection</code>.
|
||||||
|
|
Loading…
Reference in a new issue