blob: 3502509d4394394c354061a7885ed8136c6c626d [file] [log] [blame]
Shuyi Chend7955ce2013-05-22 14:51:55 -07001/**
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
21package org.jivesoftware.smackx;
22
23import java.lang.reflect.InvocationTargetException;
24import java.lang.reflect.Method;
25import java.util.ArrayList;
26import java.util.Iterator;
27import java.util.List;
28
29import org.jivesoftware.smack.PacketListener;
30import org.jivesoftware.smack.Connection;
31import org.jivesoftware.smack.filter.PacketExtensionFilter;
32import org.jivesoftware.smack.filter.PacketFilter;
33import org.jivesoftware.smack.packet.Message;
34import org.jivesoftware.smack.packet.Packet;
35import 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 */
44public 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 */
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 */
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 */
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 */
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 */
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 */
133 public void removeMessageEventNotificationListener(MessageEventNotificationListener messageEventNotificationListener) {
134 synchronized (messageEventNotificationListeners) {
135 messageEventNotificationListeners.remove(messageEventNotificationListener);
136 }
137 }
138
139 /**
140 * Fires message event request listeners.
141 */
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 */
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
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 */
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 */
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 */
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 */
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
300 public void destroy() {
301 if (con != null) {
302 con.removePacketListener(packetListener);
303 }
304 }
305
306 protected void finalize() throws Throwable {
307 destroy();
308 super.finalize();
309 }
310}