diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xevent/MessageEventManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xevent/MessageEventManager.java index 42ef462d7..62e9f951d 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xevent/MessageEventManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xevent/MessageEventManager.java @@ -18,11 +18,15 @@ package org.jivesoftware.smackx.xevent; import java.lang.reflect.Method; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.logging.Level; import java.util.logging.Logger; +import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.XMPPConnection; @@ -33,31 +37,66 @@ import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smackx.xevent.packet.MessageEvent; /** + * * Manages message events requests and notifications. A MessageEventManager provides a high * level access to request for notifications and send event notifications. It also provides * an easy way to hook up custom logic when requests or notifications are received. * * @author Gaston Dombiak + * @see XEP-22: Message Events */ -public class MessageEventManager { +public class MessageEventManager extends Manager { private static final Logger LOGGER = Logger.getLogger(MessageEventManager.class.getName()); - private List messageEventNotificationListeners = new ArrayList(); - private List messageEventRequestListeners = new ArrayList(); + private static final Map INSTANCES = Collections + .synchronizedMap(new WeakHashMap()); - private XMPPConnection con; + private static final PacketFilter PACKET_FILTER = new PacketExtensionFilter( + MessageEvent.ELEMENT, MessageEvent.NAMESPACE); - private PacketFilter packetFilter = new PacketExtensionFilter("x", "jabber:x:event"); - private PacketListener packetListener; + private List messageEventNotificationListeners = new CopyOnWriteArrayList(); + private List messageEventRequestListeners = new CopyOnWriteArrayList(); + + public synchronized static MessageEventManager getInstanceFor(XMPPConnection connection) { + MessageEventManager messageEventManager = INSTANCES.get(connection); + if (messageEventManager == null) { + messageEventManager = new MessageEventManager(connection); + } + return messageEventManager; + } /** * Creates a new message event manager. * * @param con a XMPPConnection to a XMPP server. */ - public MessageEventManager(XMPPConnection con) { - this.con = con; - init(); + private MessageEventManager(XMPPConnection connection) { + super(connection); + // Listens for all message event packets and fire the proper message event listeners. + connection.addPacketListener(new PacketListener() { + public void processPacket(Packet packet) { + Message message = (Message) packet; + MessageEvent messageEvent = + (MessageEvent) message.getExtension("x", "jabber:x:event"); + if (messageEvent.isMessageEventRequest()) { + // Fire event for requests of message events + for (String eventType : messageEvent.getEventTypes()) + fireMessageEventRequestListeners( + message.getFrom(), + message.getPacketID(), + eventType.concat("NotificationRequested")); + } else + // Fire event for notifications of message events + for (String eventType : messageEvent.getEventTypes()) + fireMessageEventNotificationListeners( + message.getFrom(), + messageEvent.getPacketID(), + eventType.concat("Notification")); + + }; + + }, PACKET_FILTER); + INSTANCES.put(connection, this); } /** @@ -90,11 +129,8 @@ public class MessageEventManager { * @param messageEventRequestListener a message event request listener. */ public void addMessageEventRequestListener(MessageEventRequestListener messageEventRequestListener) { - synchronized (messageEventRequestListeners) { - if (!messageEventRequestListeners.contains(messageEventRequestListener)) { - messageEventRequestListeners.add(messageEventRequestListener); - } - } + messageEventRequestListeners.add(messageEventRequestListener); + } /** @@ -104,9 +140,7 @@ public class MessageEventManager { * @param messageEventRequestListener a message event request listener. */ public void removeMessageEventRequestListener(MessageEventRequestListener messageEventRequestListener) { - synchronized (messageEventRequestListeners) { - messageEventRequestListeners.remove(messageEventRequestListener); - } + messageEventRequestListeners.remove(messageEventRequestListener); } /** @@ -116,11 +150,7 @@ public class MessageEventManager { * @param messageEventNotificationListener a message event notification listener. */ public void addMessageEventNotificationListener(MessageEventNotificationListener messageEventNotificationListener) { - synchronized (messageEventNotificationListeners) { - if (!messageEventNotificationListeners.contains(messageEventNotificationListener)) { - messageEventNotificationListeners.add(messageEventNotificationListener); - } - } + messageEventNotificationListeners.add(messageEventNotificationListener); } /** @@ -130,9 +160,7 @@ public class MessageEventManager { * @param messageEventNotificationListener a message event notification listener. */ public void removeMessageEventNotificationListener(MessageEventNotificationListener messageEventNotificationListener) { - synchronized (messageEventNotificationListeners) { - messageEventNotificationListeners.remove(messageEventNotificationListener); - } + messageEventNotificationListeners.remove(messageEventNotificationListener); } /** @@ -142,19 +170,13 @@ public class MessageEventManager { String from, String packetID, String methodName) { - MessageEventRequestListener[] listeners = null; - Method method; - synchronized (messageEventRequestListeners) { - listeners = new MessageEventRequestListener[messageEventRequestListeners.size()]; - messageEventRequestListeners.toArray(listeners); - } try { - method = + Method method = MessageEventRequestListener.class.getDeclaredMethod( methodName, new Class[] { String.class, String.class, MessageEventManager.class }); - for (int i = 0; i < listeners.length; i++) { - method.invoke(listeners[i], new Object[] { from, packetID, this }); + for (MessageEventRequestListener listener : messageEventRequestListeners) { + method.invoke(listener, new Object[] { from, packetID, this }); } } catch (Exception e) { LOGGER.log(Level.SEVERE, "Error while invoking MessageEventRequestListener", e); @@ -168,54 +190,19 @@ public class MessageEventManager { String from, String packetID, String methodName) { - MessageEventNotificationListener[] listeners = null; - Method method; - synchronized (messageEventNotificationListeners) { - listeners = - new MessageEventNotificationListener[messageEventNotificationListeners.size()]; - messageEventNotificationListeners.toArray(listeners); - } try { - method = + Method method = MessageEventNotificationListener.class.getDeclaredMethod( methodName, new Class[] { String.class, String.class }); - for (int i = 0; i < listeners.length; i++) { - method.invoke(listeners[i], new Object[] { from, packetID }); + for (MessageEventNotificationListener listener : messageEventNotificationListeners) { + method.invoke(listener, new Object[] { from, packetID }); } } catch (Exception e) { LOGGER.log(Level.SEVERE, "Error while invoking MessageEventNotificationListener", e); } } - private void init() { - // Listens for all message event packets and fire the proper message event listeners. - packetListener = new PacketListener() { - public void processPacket(Packet packet) { - Message message = (Message) packet; - MessageEvent messageEvent = - (MessageEvent) message.getExtension("x", "jabber:x:event"); - if (messageEvent.isMessageEventRequest()) { - // Fire event for requests of message events - for (String eventType : messageEvent.getEventTypes()) - fireMessageEventRequestListeners( - message.getFrom(), - message.getPacketID(), - eventType.concat("NotificationRequested")); - } else - // Fire event for notifications of message events - for (String eventType : messageEvent.getEventTypes()) - fireMessageEventNotificationListeners( - message.getFrom(), - messageEvent.getPacketID(), - eventType.concat("Notification")); - - }; - - }; - con.addPacketListener(packetListener, packetFilter); - } - /** * Sends the notification that the message was delivered to the sender of the original message * @@ -232,7 +219,7 @@ public class MessageEventManager { messageEvent.setPacketID(packetID); msg.addExtension(messageEvent); // Send the packet - con.sendPacket(msg); + connection().sendPacket(msg); } /** @@ -251,7 +238,7 @@ public class MessageEventManager { messageEvent.setPacketID(packetID); msg.addExtension(messageEvent); // Send the packet - con.sendPacket(msg); + connection().sendPacket(msg); } /** @@ -270,7 +257,7 @@ public class MessageEventManager { messageEvent.setPacketID(packetID); msg.addExtension(messageEvent); // Send the packet - con.sendPacket(msg); + connection().sendPacket(msg); } /** @@ -289,17 +276,6 @@ public class MessageEventManager { messageEvent.setPacketID(packetID); msg.addExtension(messageEvent); // Send the packet - con.sendPacket(msg); - } - - public void destroy() { - if (con != null) { - con.removePacketListener(packetListener); - } - } - - protected void finalize() throws Throwable { - destroy(); - super.finalize(); + connection().sendPacket(msg); } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xevent/packet/MessageEvent.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xevent/packet/MessageEvent.java index 5e0df59dc..4ce6806e2 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xevent/packet/MessageEvent.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xevent/packet/MessageEvent.java @@ -55,6 +55,9 @@ import java.util.List; */ public class MessageEvent implements PacketExtension { + public static final String NAMESPACE = "jabber:x:event"; + public static final String ELEMENT = "x"; + public static final String OFFLINE = "offline"; public static final String COMPOSING = "composing"; public static final String DISPLAYED = "displayed"; @@ -76,7 +79,7 @@ public class MessageEvent implements PacketExtension { * @return the XML element name of the packet extension. */ public String getElementName() { - return "x"; + return ELEMENT; } /** @@ -86,7 +89,7 @@ public class MessageEvent implements PacketExtension { * @return the XML namespace of the packet extension. */ public String getNamespace() { - return "jabber:x:event"; + return NAMESPACE; } /**