mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-09-26 17:49:33 +02:00
d8a5610d7b
on machine readable output. The default locale may not provide the wanted mapping. See also http://developer.android.com/reference/java/util/Locale.html#default_locale SMACK-467
217 lines
7.8 KiB
Java
217 lines
7.8 KiB
Java
/**
|
|
*
|
|
* Copyright 2003-2006 Jive Software.
|
|
*
|
|
* 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.smackx.muc;
|
|
|
|
import org.jivesoftware.smack.AbstractConnectionListener;
|
|
import org.jivesoftware.smack.PacketListener;
|
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
|
import org.jivesoftware.smack.XMPPConnection;
|
|
import org.jivesoftware.smack.filter.PacketFilter;
|
|
import org.jivesoftware.smack.packet.Packet;
|
|
import org.jivesoftware.smack.util.StringUtils;
|
|
|
|
import java.lang.ref.WeakReference;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
import java.util.WeakHashMap;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
/**
|
|
* A <code>RoomListenerMultiplexor</code> multiplexes incoming packets on
|
|
* a <code>XMPPConnection</code> using a single listener/filter pair.
|
|
* A single <code>RoomListenerMultiplexor</code> is created for each
|
|
* {@link org.jivesoftware.smack.XMPPConnection} that has joined MUC rooms
|
|
* within its session.
|
|
*
|
|
* @author Larry Kirschner
|
|
*/
|
|
class RoomListenerMultiplexor extends AbstractConnectionListener {
|
|
|
|
// We use a WeakHashMap so that the GC can collect the monitor when the
|
|
// connection is no longer referenced by any object.
|
|
private static final Map<XMPPConnection, WeakReference<RoomListenerMultiplexor>> monitors =
|
|
new WeakHashMap<XMPPConnection, WeakReference<RoomListenerMultiplexor>>();
|
|
|
|
private XMPPConnection connection;
|
|
private RoomMultiplexFilter filter;
|
|
private RoomMultiplexListener listener;
|
|
|
|
/**
|
|
* Returns a new or existing RoomListenerMultiplexor for a given connection.
|
|
*
|
|
* @param conn the connection to monitor for room invitations.
|
|
* @return a new or existing RoomListenerMultiplexor for a given connection.
|
|
*/
|
|
public static RoomListenerMultiplexor getRoomMultiplexor(XMPPConnection conn) {
|
|
synchronized (monitors) {
|
|
if (!monitors.containsKey(conn) || monitors.get(conn).get() == null) {
|
|
RoomListenerMultiplexor rm = new RoomListenerMultiplexor(conn, new RoomMultiplexFilter(),
|
|
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 monitors.get(conn).get();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* All access should be through
|
|
* the static method {@link #getRoomMultiplexor(XMPPConnection)}.
|
|
*/
|
|
private RoomListenerMultiplexor(XMPPConnection connection, RoomMultiplexFilter filter,
|
|
RoomMultiplexListener listener) {
|
|
if (connection == null) {
|
|
throw new IllegalArgumentException("XMPPConnection is null");
|
|
}
|
|
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.listener = listener;
|
|
}
|
|
|
|
public void addRoom(String address, PacketMultiplexListener roomListener) {
|
|
filter.addRoom(address);
|
|
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) {
|
|
filter.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}
|
|
* for all muc chat rooms on an <code>XMPPConnection</code>.
|
|
* Each time a muc chat room is added to/removed from an
|
|
* <code>XMPPConnection</code> the address for that chat room
|
|
* is added to/removed from that <code>XMPPConnection</code>'s
|
|
* <code>RoomMultiplexFilter</code>.
|
|
*/
|
|
private static class RoomMultiplexFilter implements PacketFilter {
|
|
|
|
private Map<String, String> roomAddressTable = new ConcurrentHashMap<String, String>();
|
|
|
|
public boolean accept(Packet p) {
|
|
String from = p.getFrom();
|
|
if (from == null) {
|
|
return false;
|
|
}
|
|
return roomAddressTable.containsKey(StringUtils.parseBareAddress(from).toLowerCase(Locale.US));
|
|
}
|
|
|
|
public void addRoom(String address) {
|
|
if (address == null) {
|
|
return;
|
|
}
|
|
roomAddressTable.put(address.toLowerCase(Locale.US), address);
|
|
}
|
|
|
|
public void removeRoom(String address) {
|
|
if (address == null) {
|
|
return;
|
|
}
|
|
roomAddressTable.remove(address.toLowerCase(Locale.US));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The single <code>XMPPConnection</code>-level <code>PacketListener</code>
|
|
* used by a {@link RoomListenerMultiplexor}
|
|
* for all muc chat rooms on an <code>XMPPConnection</code>.
|
|
* Each time a muc chat room is added to/removed from an
|
|
* <code>XMPPConnection</code> the address and listener for that chat room
|
|
* are added to/removed from that <code>XMPPConnection</code>'s
|
|
* <code>RoomMultiplexListener</code>.
|
|
*
|
|
* @author Larry Kirschner
|
|
*/
|
|
private static class RoomMultiplexListener implements PacketListener {
|
|
|
|
private Map<String, PacketMultiplexListener> roomListenersByAddress =
|
|
new ConcurrentHashMap<String, PacketMultiplexListener>();
|
|
|
|
public void processPacket(Packet p) throws NotConnectedException {
|
|
String from = p.getFrom();
|
|
if (from == null) {
|
|
return;
|
|
}
|
|
|
|
PacketMultiplexListener listener =
|
|
roomListenersByAddress.get(StringUtils.parseBareAddress(from).toLowerCase(Locale.US));
|
|
|
|
if (listener != null) {
|
|
listener.processPacket(p);
|
|
}
|
|
}
|
|
|
|
public void addRoom(String address, PacketMultiplexListener listener) {
|
|
if (address == null) {
|
|
return;
|
|
}
|
|
roomListenersByAddress.put(address.toLowerCase(Locale.US), listener);
|
|
}
|
|
|
|
public void removeRoom(String address) {
|
|
if (address == null) {
|
|
return;
|
|
}
|
|
roomListenersByAddress.remove(address.toLowerCase(Locale.US));
|
|
}
|
|
}
|
|
}
|