KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jivesoftware > messenger > spi > PresenceManagerImpl


1 /**
2  * $RCSfile: PresenceManagerImpl.java,v $
3  * $Revision: 1.31 $
4  * $Date: 2005/07/28 22:19:16 $
5  *
6  * Copyright (C) 2004 Jive Software. All rights reserved.
7  *
8  * This software is published under the terms of the GNU Public License (GPL),
9  * a copy of which is included in this distribution.
10  */

11
12 package org.jivesoftware.messenger.spi;
13
14 import org.dom4j.Document;
15 import org.dom4j.DocumentHelper;
16 import org.dom4j.DocumentException;
17 import org.jivesoftware.messenger.*;
18 import org.jivesoftware.messenger.component.InternalComponentManager;
19 import org.jivesoftware.messenger.auth.UnauthorizedException;
20 import org.jivesoftware.messenger.container.BasicModule;
21 import org.jivesoftware.messenger.roster.Roster;
22 import org.jivesoftware.messenger.roster.RosterItem;
23 import org.jivesoftware.messenger.user.User;
24 import org.jivesoftware.messenger.user.UserManager;
25 import org.jivesoftware.messenger.user.UserNotFoundException;
26 import org.jivesoftware.util.CacheManager;
27 import org.jivesoftware.util.LocaleUtils;
28 import org.jivesoftware.util.Log;
29 import org.xmpp.component.Component;
30 import org.xmpp.packet.JID;
31 import org.xmpp.packet.PacketError;
32 import org.xmpp.packet.Presence;
33
34 import java.util.ArrayList JavaDoc;
35 import java.util.Collection JavaDoc;
36 import java.util.Collections JavaDoc;
37 import java.util.List JavaDoc;
38
39 /**
40  * Simple in memory implementation of the PresenceManager interface.
41  *
42  * @author Iain Shigeoka
43  */

44 public class PresenceManagerImpl extends BasicModule implements PresenceManager {
45
46     private static final String JavaDoc LAST_PRESENCE_PROP = "lastUnavailablePresence";
47     private static final String JavaDoc LAST_ACTIVITY_PROP = "lastActivity";
48
49     private SessionManager sessionManager;
50     private XMPPServer server;
51     private PacketDeliverer deliverer;
52
53     private InternalComponentManager componentManager;
54
55     public PresenceManagerImpl() {
56         super("Presence manager");
57
58         // Use component manager for Presence Updates.
59
componentManager = InternalComponentManager.getInstance();
60     }
61
62     public boolean isAvailable(User user) {
63         return sessionManager.getSessionCount(user.getUsername()) > 0;
64     }
65
66     public Presence getPresence(User user) {
67         if (user == null) {
68             return null;
69         }
70         Presence presence = null;
71
72         for (ClientSession session : sessionManager.getSessions(user.getUsername())) {
73             if (presence == null) {
74                 presence = session.getPresence();
75             }
76             else {
77                 // Get the ordinals of the presences to compare. If no ordinal is available then
78
// assume a value of -1
79
int o1 = presence.getShow() != null ? presence.getShow().ordinal() : -1;
80                 int o2 = session.getPresence().getShow() != null ?
81                         session.getPresence().getShow().ordinal() : -1;
82                 // Compare the presences' show ordinals
83
if (o1 > o2) {
84                     presence = session.getPresence();
85                 }
86             }
87         }
88         return presence;
89     }
90
91     public Collection JavaDoc<Presence> getPresences(String JavaDoc username) {
92         if (username == null) {
93             return null;
94         }
95         List JavaDoc<Presence> presences = new ArrayList JavaDoc<Presence>();
96
97         for (ClientSession session : sessionManager.getSessions(username)) {
98             presences.add(session.getPresence());
99         }
100         return Collections.unmodifiableCollection(presences);
101     }
102
103     public String JavaDoc getLastPresenceStatus(User user) {
104         String JavaDoc answer = null;
105         String JavaDoc presenceXML = user.getProperties().get(LAST_PRESENCE_PROP);
106         if (presenceXML != null) {
107             try {
108                 // Parse the element
109
Document element = DocumentHelper.parseText(presenceXML);
110                 answer = element.getRootElement().elementTextTrim("status");
111             }
112             catch (DocumentException e) {
113                 Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
114             }
115         }
116         return answer;
117     }
118
119     public long getLastActivity(User user) {
120         long answer = -1;
121         String JavaDoc offline = user.getProperties().get(LAST_ACTIVITY_PROP);
122         if (offline != null) {
123             try {
124                 answer = (System.currentTimeMillis() - Long.parseLong(offline)) / 1000;
125             }
126             catch (NumberFormatException JavaDoc e) {
127                 Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
128             }
129         }
130         return answer;
131     }
132
133     public void userAvailable(Presence presence) {
134         // Delete the last unavailable presence of this user since the user is now
135
// available. Only perform this operation if this is an available presence sent to
136
// THE SERVER and the presence belongs to a local user.
137
if (presence.getTo() == null && server.isLocal(presence.getFrom())) {
138             String JavaDoc username = presence.getFrom().getNode();
139             if (username == null) {
140                 // Ignore anonymous users
141
return;
142             }
143             try {
144                 User probeeUser = UserManager.getInstance().getUser(username);
145                 probeeUser.getProperties().remove(LAST_PRESENCE_PROP);
146             }
147             catch (UserNotFoundException e) {
148             }
149         }
150     }
151
152     public void userUnavailable(Presence presence) {
153         // Only save the last presence status and keep track of the time when the user went
154
// offline if this is an unavailable presence sent to THE SERVER and the presence belongs
155
// to a local user.
156
if (presence.getTo() == null && server.isLocal(presence.getFrom())) {
157             String JavaDoc username = presence.getFrom().getNode();
158             if (username == null) {
159                 // Ignore anonymous users
160
return;
161             }
162             try {
163                 User probeeUser = UserManager.getInstance().getUser(username);
164                 if (!presence.getElement().elements().isEmpty()) {
165                     // Save the last unavailable presence of this user if the presence contains any
166
// child element such as <status>
167
probeeUser.getProperties().put(LAST_PRESENCE_PROP, presence.toXML());
168                 }
169                 // Keep track of the time when the user went offline
170
probeeUser.getProperties().put(LAST_ACTIVITY_PROP,
171                         String.valueOf(System.currentTimeMillis()));
172             }
173             catch (UserNotFoundException e) {
174             }
175         }
176     }
177
178     public void handleProbe(Presence packet) throws UnauthorizedException {
179         String JavaDoc username = packet.getTo().getNode();
180         // Check for a cached roster:
181
Roster roster = (Roster)CacheManager.getCache("username2roster").get(username);
182         if (roster == null) {
183             synchronized(username.intern()) {
184                 roster = (Roster)CacheManager.getCache("username2roster").get(username);
185                 if (roster == null) {
186                     // Not in cache so load a new one:
187
roster = new Roster(username);
188                     CacheManager.getCache("username2roster").put(username, roster);
189                 }
190             }
191         }
192         try {
193             RosterItem item = roster.getRosterItem(packet.getFrom());
194             if (item.getSubStatus() == RosterItem.SUB_FROM
195                     || item.getSubStatus() == RosterItem.SUB_BOTH) {
196                 probePresence(packet.getFrom(), packet.getTo());
197             }
198             else {
199                 PacketError.Condition error = PacketError.Condition.not_authorized;
200                 if ((item.getSubStatus() == RosterItem.SUB_NONE &&
201                         item.getRecvStatus() != RosterItem.RECV_SUBSCRIBE) ||
202                         (item.getSubStatus() == RosterItem.SUB_TO &&
203                         item.getRecvStatus() != RosterItem.RECV_SUBSCRIBE)) {
204                     error = PacketError.Condition.forbidden;
205                 }
206                 Presence presenceToSend = new Presence();
207                 presenceToSend.setError(error);
208                 presenceToSend.setTo(packet.getFrom());
209                 presenceToSend.setFrom(packet.getTo());
210                 deliverer.deliver(presenceToSend);
211             }
212         }
213         catch (UserNotFoundException e) {
214             Presence presenceToSend = new Presence();
215             presenceToSend.setError(PacketError.Condition.forbidden);
216             presenceToSend.setTo(packet.getFrom());
217             presenceToSend.setFrom(packet.getTo());
218             deliverer.deliver(presenceToSend);
219         }
220     }
221
222     public boolean canProbePresence(JID prober, String JavaDoc probee) throws UserNotFoundException {
223         // Check that the probee is a valid user
224
UserManager.getInstance().getUser(probee);
225         // Check for a cached roster:
226
Roster roster = (Roster)CacheManager.getCache("username2roster").get(probee);
227         if (roster == null) {
228             synchronized(probee.intern()) {
229                 roster = (Roster)CacheManager.getCache("username2roster").get(probee);
230                 if (roster == null) {
231                     // Not in cache so load a new one:
232
roster = new Roster(probee);
233                     CacheManager.getCache("username2roster").put(probee, roster);
234                 }
235             }
236         }
237         RosterItem item = roster.getRosterItem(prober);
238         if (item.getSubStatus() == RosterItem.SUB_FROM
239                 || item.getSubStatus() == RosterItem.SUB_BOTH) {
240             return true;
241         }
242         return false;
243     }
244
245     public void probePresence(JID prober, JID probee) {
246         try {
247             Component component = getPresenceComponent(probee);
248             if (server.isLocal(probee)) {
249                 // If the probee is a local user then don't send a probe to the contact's server.
250
// But instead just send the contact's presence to the prober
251
if (probee.getNode() != null && !"".equals(probee.getNode())) {
252                     Collection JavaDoc<ClientSession> sessions =
253                             sessionManager.getSessions(probee.getNode());
254                     if (sessions.isEmpty()) {
255                         // If the probee is not online then try to retrieve his last unavailable
256
// presence which may contain particular information and send it to the
257
// prober
258
try {
259                             User probeeUser = UserManager.getInstance().getUser(probee.getNode());
260                             String JavaDoc presenceXML = probeeUser.getProperties().get(LAST_PRESENCE_PROP);
261                             if (presenceXML != null) {
262                                 try {
263                                     // Parse the element
264
Document element = DocumentHelper.parseText(presenceXML);
265                                     // Create the presence from the parsed element
266
Presence presencePacket = new Presence(element.getRootElement());
267                                     presencePacket.setFrom(probee.toBareJID());
268                                     presencePacket.setTo(prober);
269                                     // Send the presence to the prober
270
deliverer.deliver(presencePacket);
271                                 }
272                                 catch (Exception JavaDoc e) {
273                                     Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
274                                 }
275
276                             }
277                         }
278                         catch (UserNotFoundException e) {
279                         }
280                     }
281                     else {
282                         // The contact is online so send to the prober all the resources where the
283
// probee is connected
284
for (ClientSession session : sessions) {
285                             Presence presencePacket = session.getPresence().createCopy();
286                             presencePacket.setFrom(session.getAddress());
287                             presencePacket.setTo(prober);
288                             try {
289                                 deliverer.deliver(presencePacket);
290                             }
291                             catch (Exception JavaDoc e) {
292                                 Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
293                             }
294                         }
295                     }
296                 }
297             }
298             else if (component != null) {
299                 // If the probee belongs to a component then ask the component to process the
300
// probe presence
301
Presence presence = new Presence();
302                 presence.setType(Presence.Type.probe);
303                 presence.setFrom(prober);
304                 presence.setTo(probee);
305                 component.processPacket(presence);
306             }
307             else {
308                 // Check if the probee may be hosted by this server
309
/*String serverDomain = server.getServerInfo().getName();
310                 if (!probee.getDomain().contains(serverDomain)) {*/

311                 if (server.isRemote(probee)) {
312                     // Send the probe presence to the remote server
313
Presence probePresence = new Presence();
314                     probePresence.setType(Presence.Type.probe);
315                     probePresence.setFrom(prober);
316                     probePresence.setTo(probee.toBareJID());
317                     // Send the probe presence
318
deliverer.deliver(probePresence);
319                 }
320                 else {
321                     // The probee may be related to a component that has not yet been connected so
322
// we will keep a registry of this presence probe. The component will answer
323
// this presence probe when he becomes online
324
componentManager.addPresenceRequest(prober, probee);
325                 }
326             }
327         }
328         catch (Exception JavaDoc e) {
329             Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
330         }
331     }
332
333     public void sendUnavailableFromSessions(JID recipientJID, JID userJID) {
334         if (userJID.getNode() != null && !"".equals(userJID.getNode())) {
335             for (ClientSession session : sessionManager.getSessions(userJID.getNode())) {
336                 Presence presencePacket = new Presence();
337                 presencePacket.setType(Presence.Type.unavailable);
338                 presencePacket.setFrom(session.getAddress());
339                 presencePacket.setTo(recipientJID);
340                 try {
341                     deliverer.deliver(presencePacket);
342                 }
343                 catch (Exception JavaDoc e) {
344                     Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
345                 }
346             }
347         }
348     }
349
350     // #####################################################################
351
// Module management
352
// #####################################################################
353

354     public void initialize(XMPPServer server) {
355         super.initialize(server);
356         this.server = server;
357         deliverer = server.getPacketDeliverer();
358         sessionManager = server.getSessionManager();
359     }
360
361     public Component getPresenceComponent(JID probee) {
362         // Check for registered components
363
Component component = componentManager.getComponent(probee.toBareJID());
364         if (component != null) {
365             return component;
366         }
367         return null;
368     }
369 }
Popular Tags