Refactor Message Event (XEP-22) code to current design

This commit is contained in:
Florian Schmaus 2014-05-29 21:04:56 +02:00
parent 2a091debc1
commit 8cc2a76e7f
2 changed files with 69 additions and 90 deletions

View File

@ -18,11 +18,15 @@
package org.jivesoftware.smackx.xevent; package org.jivesoftware.smackx.xevent;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.Collections;
import java.util.List; 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.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
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;
@ -33,31 +37,66 @@ import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smackx.xevent.packet.MessageEvent; import org.jivesoftware.smackx.xevent.packet.MessageEvent;
/** /**
*
* Manages message events requests and notifications. A MessageEventManager provides a high * Manages message events requests and notifications. A MessageEventManager provides a high
* level access to request for notifications and send event notifications. It also provides * 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. * an easy way to hook up custom logic when requests or notifications are received.
* *
* @author Gaston Dombiak * @author Gaston Dombiak
* @see <a href="http://xmpp.org/extensions/xep-0022.html">XEP-22: Message Events</a>
*/ */
public class MessageEventManager { public class MessageEventManager extends Manager {
private static final Logger LOGGER = Logger.getLogger(MessageEventManager.class.getName()); private static final Logger LOGGER = Logger.getLogger(MessageEventManager.class.getName());
private List<MessageEventNotificationListener> messageEventNotificationListeners = new ArrayList<MessageEventNotificationListener>(); private static final Map<XMPPConnection, MessageEventManager> INSTANCES = Collections
private List<MessageEventRequestListener> messageEventRequestListeners = new ArrayList<MessageEventRequestListener>(); .synchronizedMap(new WeakHashMap<XMPPConnection, MessageEventManager>());
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 List<MessageEventNotificationListener> messageEventNotificationListeners = new CopyOnWriteArrayList<MessageEventNotificationListener>();
private PacketListener packetListener; private List<MessageEventRequestListener> messageEventRequestListeners = new CopyOnWriteArrayList<MessageEventRequestListener>();
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. * Creates a new message event manager.
* *
* @param con a XMPPConnection to a XMPP server. * @param con a XMPPConnection to a XMPP server.
*/ */
public MessageEventManager(XMPPConnection con) { private MessageEventManager(XMPPConnection connection) {
this.con = con; super(connection);
init(); // 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. * @param messageEventRequestListener a message event request listener.
*/ */
public void addMessageEventRequestListener(MessageEventRequestListener messageEventRequestListener) { public void addMessageEventRequestListener(MessageEventRequestListener messageEventRequestListener) {
synchronized (messageEventRequestListeners) { messageEventRequestListeners.add(messageEventRequestListener);
if (!messageEventRequestListeners.contains(messageEventRequestListener)) {
messageEventRequestListeners.add(messageEventRequestListener);
}
}
} }
/** /**
@ -104,9 +140,7 @@ public class MessageEventManager {
* @param messageEventRequestListener a message event request listener. * @param messageEventRequestListener a message event request listener.
*/ */
public void removeMessageEventRequestListener(MessageEventRequestListener messageEventRequestListener) { 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. * @param messageEventNotificationListener a message event notification listener.
*/ */
public void addMessageEventNotificationListener(MessageEventNotificationListener messageEventNotificationListener) { public void addMessageEventNotificationListener(MessageEventNotificationListener messageEventNotificationListener) {
synchronized (messageEventNotificationListeners) { messageEventNotificationListeners.add(messageEventNotificationListener);
if (!messageEventNotificationListeners.contains(messageEventNotificationListener)) {
messageEventNotificationListeners.add(messageEventNotificationListener);
}
}
} }
/** /**
@ -130,9 +160,7 @@ public class MessageEventManager {
* @param messageEventNotificationListener a message event notification listener. * @param messageEventNotificationListener a message event notification listener.
*/ */
public void removeMessageEventNotificationListener(MessageEventNotificationListener messageEventNotificationListener) { public void removeMessageEventNotificationListener(MessageEventNotificationListener messageEventNotificationListener) {
synchronized (messageEventNotificationListeners) { messageEventNotificationListeners.remove(messageEventNotificationListener);
messageEventNotificationListeners.remove(messageEventNotificationListener);
}
} }
/** /**
@ -142,19 +170,13 @@ public class MessageEventManager {
String from, String from,
String packetID, String packetID,
String methodName) { String methodName) {
MessageEventRequestListener[] listeners = null;
Method method;
synchronized (messageEventRequestListeners) {
listeners = new MessageEventRequestListener[messageEventRequestListeners.size()];
messageEventRequestListeners.toArray(listeners);
}
try { try {
method = Method method =
MessageEventRequestListener.class.getDeclaredMethod( MessageEventRequestListener.class.getDeclaredMethod(
methodName, methodName,
new Class[] { String.class, String.class, MessageEventManager.class }); new Class[] { String.class, String.class, MessageEventManager.class });
for (int i = 0; i < listeners.length; i++) { for (MessageEventRequestListener listener : messageEventRequestListeners) {
method.invoke(listeners[i], new Object[] { from, packetID, this }); method.invoke(listener, new Object[] { from, packetID, this });
} }
} catch (Exception e) { } catch (Exception e) {
LOGGER.log(Level.SEVERE, "Error while invoking MessageEventRequestListener", e); LOGGER.log(Level.SEVERE, "Error while invoking MessageEventRequestListener", e);
@ -168,54 +190,19 @@ public class MessageEventManager {
String from, String from,
String packetID, String packetID,
String methodName) { String methodName) {
MessageEventNotificationListener[] listeners = null;
Method method;
synchronized (messageEventNotificationListeners) {
listeners =
new MessageEventNotificationListener[messageEventNotificationListeners.size()];
messageEventNotificationListeners.toArray(listeners);
}
try { try {
method = Method method =
MessageEventNotificationListener.class.getDeclaredMethod( MessageEventNotificationListener.class.getDeclaredMethod(
methodName, methodName,
new Class[] { String.class, String.class }); new Class[] { String.class, String.class });
for (int i = 0; i < listeners.length; i++) { for (MessageEventNotificationListener listener : messageEventNotificationListeners) {
method.invoke(listeners[i], new Object[] { from, packetID }); method.invoke(listener, new Object[] { from, packetID });
} }
} catch (Exception e) { } catch (Exception e) {
LOGGER.log(Level.SEVERE, "Error while invoking MessageEventNotificationListener", 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 * 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); messageEvent.setPacketID(packetID);
msg.addExtension(messageEvent); msg.addExtension(messageEvent);
// Send the packet // Send the packet
con.sendPacket(msg); connection().sendPacket(msg);
} }
/** /**
@ -251,7 +238,7 @@ public class MessageEventManager {
messageEvent.setPacketID(packetID); messageEvent.setPacketID(packetID);
msg.addExtension(messageEvent); msg.addExtension(messageEvent);
// Send the packet // Send the packet
con.sendPacket(msg); connection().sendPacket(msg);
} }
/** /**
@ -270,7 +257,7 @@ public class MessageEventManager {
messageEvent.setPacketID(packetID); messageEvent.setPacketID(packetID);
msg.addExtension(messageEvent); msg.addExtension(messageEvent);
// Send the packet // Send the packet
con.sendPacket(msg); connection().sendPacket(msg);
} }
/** /**
@ -289,17 +276,6 @@ public class MessageEventManager {
messageEvent.setPacketID(packetID); messageEvent.setPacketID(packetID);
msg.addExtension(messageEvent); msg.addExtension(messageEvent);
// Send the packet // Send the packet
con.sendPacket(msg); connection().sendPacket(msg);
}
public void destroy() {
if (con != null) {
con.removePacketListener(packetListener);
}
}
protected void finalize() throws Throwable {
destroy();
super.finalize();
} }
} }

View File

@ -55,6 +55,9 @@ import java.util.List;
*/ */
public class MessageEvent implements PacketExtension { 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 OFFLINE = "offline";
public static final String COMPOSING = "composing"; public static final String COMPOSING = "composing";
public static final String DISPLAYED = "displayed"; public static final String DISPLAYED = "displayed";
@ -76,7 +79,7 @@ public class MessageEvent implements PacketExtension {
* @return the XML element name of the packet extension. * @return the XML element name of the packet extension.
*/ */
public String getElementName() { public String getElementName() {
return "x"; return ELEMENT;
} }
/** /**
@ -86,7 +89,7 @@ public class MessageEvent implements PacketExtension {
* @return the XML namespace of the packet extension. * @return the XML namespace of the packet extension.
*/ */
public String getNamespace() { public String getNamespace() {
return "jabber:x:event"; return NAMESPACE;
} }
/** /**