• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * $RCSfile$
3  * $Revision$
4  * $Date$
5  *
6  * Copyright 2003-2007 Jive Software.
7  *
8  * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 package org.jivesoftware.smackx;
22 
23 import java.lang.reflect.InvocationTargetException;
24 import java.lang.reflect.Method;
25 import java.util.ArrayList;
26 import java.util.Iterator;
27 import java.util.List;
28 
29 import org.jivesoftware.smack.PacketListener;
30 import org.jivesoftware.smack.Connection;
31 import org.jivesoftware.smack.filter.PacketExtensionFilter;
32 import org.jivesoftware.smack.filter.PacketFilter;
33 import org.jivesoftware.smack.packet.Message;
34 import org.jivesoftware.smack.packet.Packet;
35 import org.jivesoftware.smackx.packet.MessageEvent;
36 
37 /**
38  * Manages message events requests and notifications. A MessageEventManager provides a high
39  * level access to request for notifications and send event notifications. It also provides
40  * an easy way to hook up custom logic when requests or notifications are received.
41  *
42  * @author Gaston Dombiak
43  */
44 public class MessageEventManager {
45 
46     private List<MessageEventNotificationListener> messageEventNotificationListeners = new ArrayList<MessageEventNotificationListener>();
47     private List<MessageEventRequestListener> messageEventRequestListeners = new ArrayList<MessageEventRequestListener>();
48 
49     private Connection con;
50 
51     private PacketFilter packetFilter = new PacketExtensionFilter("x", "jabber:x:event");
52     private PacketListener packetListener;
53 
54     /**
55      * Creates a new message event manager.
56      *
57      * @param con a Connection to a XMPP server.
58      */
MessageEventManager(Connection con)59     public MessageEventManager(Connection con) {
60         this.con = con;
61         init();
62     }
63 
64     /**
65      * Adds event notification requests to a message. For each event type that
66      * the user wishes event notifications from the message recepient for, <tt>true</tt>
67      * should be passed in to this method.
68      *
69      * @param message the message to add the requested notifications.
70      * @param offline specifies if the offline event is requested.
71      * @param delivered specifies if the delivered event is requested.
72      * @param displayed specifies if the displayed event is requested.
73      * @param composing specifies if the composing event is requested.
74      */
addNotificationsRequests(Message message, boolean offline, boolean delivered, boolean displayed, boolean composing)75     public static void addNotificationsRequests(Message message, boolean offline,
76             boolean delivered, boolean displayed, boolean composing)
77     {
78         // Create a MessageEvent Package and add it to the message
79         MessageEvent messageEvent = new MessageEvent();
80         messageEvent.setOffline(offline);
81         messageEvent.setDelivered(delivered);
82         messageEvent.setDisplayed(displayed);
83         messageEvent.setComposing(composing);
84         message.addExtension(messageEvent);
85     }
86 
87     /**
88      * Adds a message event request listener. The listener will be fired anytime a request for
89      * event notification is received.
90      *
91      * @param messageEventRequestListener a message event request listener.
92      */
addMessageEventRequestListener(MessageEventRequestListener messageEventRequestListener)93     public void addMessageEventRequestListener(MessageEventRequestListener messageEventRequestListener) {
94         synchronized (messageEventRequestListeners) {
95             if (!messageEventRequestListeners.contains(messageEventRequestListener)) {
96                 messageEventRequestListeners.add(messageEventRequestListener);
97             }
98         }
99     }
100 
101     /**
102      * Removes a message event request listener. The listener will be fired anytime a request for
103      * event notification is received.
104      *
105      * @param messageEventRequestListener a message event request listener.
106      */
removeMessageEventRequestListener(MessageEventRequestListener messageEventRequestListener)107     public void removeMessageEventRequestListener(MessageEventRequestListener messageEventRequestListener) {
108         synchronized (messageEventRequestListeners) {
109             messageEventRequestListeners.remove(messageEventRequestListener);
110         }
111     }
112 
113     /**
114      * Adds a message event notification listener. The listener will be fired anytime a notification
115      * event is received.
116      *
117      * @param messageEventNotificationListener a message event notification listener.
118      */
addMessageEventNotificationListener(MessageEventNotificationListener messageEventNotificationListener)119     public void addMessageEventNotificationListener(MessageEventNotificationListener messageEventNotificationListener) {
120         synchronized (messageEventNotificationListeners) {
121             if (!messageEventNotificationListeners.contains(messageEventNotificationListener)) {
122                 messageEventNotificationListeners.add(messageEventNotificationListener);
123             }
124         }
125     }
126 
127     /**
128      * Removes a message event notification listener. The listener will be fired anytime a notification
129      * event is received.
130      *
131      * @param messageEventNotificationListener a message event notification listener.
132      */
removeMessageEventNotificationListener(MessageEventNotificationListener messageEventNotificationListener)133     public void removeMessageEventNotificationListener(MessageEventNotificationListener messageEventNotificationListener) {
134         synchronized (messageEventNotificationListeners) {
135             messageEventNotificationListeners.remove(messageEventNotificationListener);
136         }
137     }
138 
139     /**
140      * Fires message event request listeners.
141      */
fireMessageEventRequestListeners( String from, String packetID, String methodName)142     private void fireMessageEventRequestListeners(
143         String from,
144         String packetID,
145         String methodName) {
146         MessageEventRequestListener[] listeners = null;
147         Method method;
148         synchronized (messageEventRequestListeners) {
149             listeners = new MessageEventRequestListener[messageEventRequestListeners.size()];
150             messageEventRequestListeners.toArray(listeners);
151         }
152         try {
153             method =
154                 MessageEventRequestListener.class.getDeclaredMethod(
155                     methodName,
156                     new Class[] { String.class, String.class, MessageEventManager.class });
157             for (int i = 0; i < listeners.length; i++) {
158                 method.invoke(listeners[i], new Object[] { from, packetID, this });
159             }
160         } catch (NoSuchMethodException e) {
161             e.printStackTrace();
162         } catch (InvocationTargetException e) {
163             e.printStackTrace();
164         } catch (IllegalAccessException e) {
165             e.printStackTrace();
166         }
167     }
168 
169     /**
170      * Fires message event notification listeners.
171      */
fireMessageEventNotificationListeners( String from, String packetID, String methodName)172     private void fireMessageEventNotificationListeners(
173         String from,
174         String packetID,
175         String methodName) {
176         MessageEventNotificationListener[] listeners = null;
177         Method method;
178         synchronized (messageEventNotificationListeners) {
179             listeners =
180                 new MessageEventNotificationListener[messageEventNotificationListeners.size()];
181             messageEventNotificationListeners.toArray(listeners);
182         }
183         try {
184             method =
185                 MessageEventNotificationListener.class.getDeclaredMethod(
186                     methodName,
187                     new Class[] { String.class, String.class });
188             for (int i = 0; i < listeners.length; i++) {
189                 method.invoke(listeners[i], new Object[] { from, packetID });
190             }
191         } catch (NoSuchMethodException e) {
192             e.printStackTrace();
193         } catch (InvocationTargetException e) {
194             e.printStackTrace();
195         } catch (IllegalAccessException e) {
196             e.printStackTrace();
197         }
198     }
199 
init()200     private void init() {
201         // Listens for all message event packets and fire the proper message event listeners.
202         packetListener = new PacketListener() {
203             public void processPacket(Packet packet) {
204                 Message message = (Message) packet;
205                 MessageEvent messageEvent =
206                     (MessageEvent) message.getExtension("x", "jabber:x:event");
207                 if (messageEvent.isMessageEventRequest()) {
208                     // Fire event for requests of message events
209                     for (Iterator<String> it = messageEvent.getEventTypes(); it.hasNext();)
210                         fireMessageEventRequestListeners(
211                             message.getFrom(),
212                             message.getPacketID(),
213                             it.next().concat("NotificationRequested"));
214                 } else
215                     // Fire event for notifications of message events
216                     for (Iterator<String> it = messageEvent.getEventTypes(); it.hasNext();)
217                         fireMessageEventNotificationListeners(
218                             message.getFrom(),
219                             messageEvent.getPacketID(),
220                             it.next().concat("Notification"));
221 
222             };
223 
224         };
225         con.addPacketListener(packetListener, packetFilter);
226     }
227 
228     /**
229      * Sends the notification that the message was delivered to the sender of the original message
230      *
231      * @param to the recipient of the notification.
232      * @param packetID the id of the message to send.
233      */
sendDeliveredNotification(String to, String packetID)234     public void sendDeliveredNotification(String to, String packetID) {
235         // Create the message to send
236         Message msg = new Message(to);
237         // Create a MessageEvent Package and add it to the message
238         MessageEvent messageEvent = new MessageEvent();
239         messageEvent.setDelivered(true);
240         messageEvent.setPacketID(packetID);
241         msg.addExtension(messageEvent);
242         // Send the packet
243         con.sendPacket(msg);
244     }
245 
246     /**
247      * Sends the notification that the message was displayed to the sender of the original message
248      *
249      * @param to the recipient of the notification.
250      * @param packetID the id of the message to send.
251      */
sendDisplayedNotification(String to, String packetID)252     public void sendDisplayedNotification(String to, String packetID) {
253         // Create the message to send
254         Message msg = new Message(to);
255         // Create a MessageEvent Package and add it to the message
256         MessageEvent messageEvent = new MessageEvent();
257         messageEvent.setDisplayed(true);
258         messageEvent.setPacketID(packetID);
259         msg.addExtension(messageEvent);
260         // Send the packet
261         con.sendPacket(msg);
262     }
263 
264     /**
265      * Sends the notification that the receiver of the message is composing a reply
266      *
267      * @param to the recipient of the notification.
268      * @param packetID the id of the message to send.
269      */
sendComposingNotification(String to, String packetID)270     public void sendComposingNotification(String to, String packetID) {
271         // Create the message to send
272         Message msg = new Message(to);
273         // Create a MessageEvent Package and add it to the message
274         MessageEvent messageEvent = new MessageEvent();
275         messageEvent.setComposing(true);
276         messageEvent.setPacketID(packetID);
277         msg.addExtension(messageEvent);
278         // Send the packet
279         con.sendPacket(msg);
280     }
281 
282     /**
283      * Sends the notification that the receiver of the message has cancelled composing a reply.
284      *
285      * @param to the recipient of the notification.
286      * @param packetID the id of the message to send.
287      */
sendCancelledNotification(String to, String packetID)288     public void sendCancelledNotification(String to, String packetID) {
289         // Create the message to send
290         Message msg = new Message(to);
291         // Create a MessageEvent Package and add it to the message
292         MessageEvent messageEvent = new MessageEvent();
293         messageEvent.setCancelled(true);
294         messageEvent.setPacketID(packetID);
295         msg.addExtension(messageEvent);
296         // Send the packet
297         con.sendPacket(msg);
298     }
299 
destroy()300     public void destroy() {
301         if (con != null) {
302             con.removePacketListener(packetListener);
303         }
304     }
305 
finalize()306     protected void finalize() throws Throwable {
307         destroy();
308         super.finalize();
309     }
310 }