1 11 12 package org.jivesoftware.messenger.handler; 13 14 import org.jivesoftware.messenger.*; 15 import org.jivesoftware.messenger.container.BasicModule; 16 import org.jivesoftware.messenger.roster.Roster; 17 import org.jivesoftware.messenger.roster.RosterItem; 18 import org.jivesoftware.messenger.user.UserAlreadyExistsException; 19 import org.jivesoftware.messenger.user.UserNotFoundException; 20 import org.jivesoftware.util.CacheManager; 21 import org.jivesoftware.util.LocaleUtils; 22 import org.jivesoftware.util.Log; 23 import org.xmpp.packet.JID; 24 import org.xmpp.packet.Packet; 25 import org.xmpp.packet.PacketError; 26 import org.xmpp.packet.Presence; 27 28 import java.util.Hashtable ; 29 import java.util.Map ; 30 31 75 public class PresenceSubscribeHandler extends BasicModule implements ChannelHandler { 76 77 private RoutingTable routingTable; 78 private XMPPServer localServer; 79 private PacketDeliverer deliverer; 80 private PresenceManager presenceManager; 81 82 public PresenceSubscribeHandler() { 83 super("Presence subscription handler"); 84 } 85 86 public void process(Packet xmppPacket) throws PacketException { 87 Presence presence = (Presence)xmppPacket; 88 try { 89 JID senderJID = presence.getFrom(); 90 JID recipientJID = presence.getTo(); 91 Presence.Type type = presence.getType(); 92 try { 93 Roster senderRoster = getRoster(senderJID); 94 boolean senderSubChanged = false; 95 if (senderRoster != null) { 96 senderSubChanged = manageSub(recipientJID, true, type, senderRoster); 97 } 98 Roster recipientRoster = getRoster(recipientJID); 99 boolean recipientSubChanged = false; 100 if (recipientRoster != null) { 101 recipientSubChanged = manageSub(senderJID, false, type, recipientRoster); 102 } 103 104 if (!(type == Presence.Type.subscribed && recipientRoster != null && 107 !recipientSubChanged)) { 108 109 if (type == Presence.Type.subscribe && recipientRoster != null && 113 !recipientSubChanged) { 114 try { 115 RosterItem.SubType subType = recipientRoster.getRosterItem(senderJID) 116 .getSubStatus(); 117 if (subType == RosterItem.SUB_FROM || subType == RosterItem.SUB_BOTH) { 118 Presence reply = new Presence(); 121 reply.setTo(senderJID); 122 reply.setFrom(recipientJID); 123 reply.setType(Presence.Type.subscribed); 124 deliverer.deliver(reply); 125 return; 126 } 127 } 128 catch (UserNotFoundException e) { 129 } 131 } 132 133 ChannelHandler handler = routingTable.getRoute(recipientJID); 138 Presence presenteToSend = presence.createCopy(); 139 presenteToSend.setFrom(senderJID.toBareJID()); 141 handler.process(presenteToSend); 142 143 if (type == Presence.Type.subscribed) { 144 presenceManager.probePresence(recipientJID, senderJID); 147 } 148 } 149 150 if (type == Presence.Type.unsubscribed) { 151 presenceManager.sendUnavailableFromSessions(recipientJID, senderJID); 154 } 155 } 156 catch (NoSuchRouteException e) { 157 deliverer.deliver(presence.createCopy()); 158 } 159 catch (SharedGroupException e) { 160 Presence result = presence.createCopy(); 161 JID sender = result.getFrom(); 162 result.setFrom(presence.getTo()); 163 result.setTo(sender); 164 result.setError(PacketError.Condition.not_acceptable); 165 deliverer.deliver(result); 166 } 167 } 168 catch (Exception e) { 169 Log.error(LocaleUtils.getLocalizedString("admin.error"), e); 170 } 171 } 172 173 179 private Roster getRoster(JID address) { 180 String username = null; 181 Roster roster = null; 182 if (localServer.isLocal(address) && address.getNode() != null && 183 !"".equals(address.getNode())) { 184 username = address.getNode(); 185 roster = (Roster)CacheManager.getCache("username2roster").get(username); 187 if (roster == null) { 188 synchronized(address.toString().intern()) { 189 roster = (Roster)CacheManager.getCache("username2roster").get(username); 190 if (roster == null) { 191 roster = new Roster(username); 193 CacheManager.getCache("username2roster").put(username, roster); 194 } 195 } 196 } 197 } 198 return roster; 199 } 200 201 211 private boolean manageSub(JID target, boolean isSending, Presence.Type type, Roster roster) 212 throws UserAlreadyExistsException, SharedGroupException 213 { 214 RosterItem item = null; 215 RosterItem.AskType oldAsk = null; 216 RosterItem.SubType oldSub = null; 217 RosterItem.RecvType oldRecv = null; 218 try { 219 if (roster.isRosterItem(target)) { 220 item = roster.getRosterItem(target); 221 } 222 else { 223 item = roster.createRosterItem(target); 224 } 225 oldAsk = item.getAskStatus(); 227 oldSub = item.getSubStatus(); 228 oldRecv = item.getRecvStatus(); 229 updateState(item, type, isSending); 231 if (oldAsk != item.getAskStatus() || oldSub != item.getSubStatus() || 233 oldRecv != item.getRecvStatus()) { 234 roster.updateRosterItem(item); 235 } 236 } 237 catch (UserNotFoundException e) { 238 Log.error(LocaleUtils.getLocalizedString("admin.error"), e); 240 } 241 return oldSub != item.getSubStatus(); 242 } 243 244 254 private static Hashtable stateTable = new Hashtable (); 255 256 static { 257 Hashtable subrTable; 258 Hashtable subsTable; 259 Hashtable sr; 260 261 sr = new Hashtable (); 262 subrTable = new Hashtable (); 263 subsTable = new Hashtable (); 264 sr.put("recv", subrTable); 265 sr.put("send", subsTable); 266 stateTable.put(RosterItem.SUB_NONE, sr); 267 subrTable.put(Presence.Type.subscribe, new Change(RosterItem.RECV_SUBSCRIBE, null, null)); subrTable.put(Presence.Type.subscribed, new Change(null, RosterItem.SUB_TO, RosterItem.ASK_NONE)); 274 subrTable.put(Presence.Type.unsubscribe, new Change(null, null, null)); 277 subrTable.put(Presence.Type.unsubscribed, new Change(null, null, RosterItem.ASK_NONE)); 280 subsTable.put(Presence.Type.subscribe, new Change(null, null, RosterItem.ASK_SUBSCRIBE)); 283 subsTable.put(Presence.Type.subscribed, new Change(RosterItem.RECV_NONE, RosterItem.SUB_FROM, null)); 285 subsTable.put(Presence.Type.unsubscribe, new Change(null, null, null)); 288 subsTable.put(Presence.Type.unsubscribed, new Change(RosterItem.RECV_NONE, null, null)); 291 292 sr = new Hashtable (); 293 subrTable = new Hashtable (); 294 subsTable = new Hashtable (); 295 sr.put("recv", subrTable); 296 sr.put("send", subsTable); 297 stateTable.put(RosterItem.SUB_FROM, sr); 298 subsTable.put(Presence.Type.subscribe, new Change(null, null, RosterItem.ASK_SUBSCRIBE)); 302 subsTable.put(Presence.Type.subscribed, new Change(RosterItem.RECV_NONE, null, null)); 306 subsTable.put(Presence.Type.unsubscribe, new Change(null, RosterItem.SUB_NONE, null)); 309 subsTable.put(Presence.Type.unsubscribed, new Change(RosterItem.RECV_NONE, RosterItem.SUB_NONE, null)); 312 subrTable.put(Presence.Type.subscribe, new Change(RosterItem.RECV_NONE, null, null)); 317 subrTable.put(Presence.Type.subscribed, new Change(null, RosterItem.SUB_BOTH, RosterItem.ASK_NONE)); 320 subrTable.put(Presence.Type.unsubscribe, new Change(RosterItem.RECV_UNSUBSCRIBE, RosterItem.SUB_NONE, null)); 323 subrTable.put(Presence.Type.unsubscribed, new Change(null, null, RosterItem.ASK_NONE)); 326 327 sr = new Hashtable (); 328 subrTable = new Hashtable (); 329 subsTable = new Hashtable (); 330 sr.put("recv", subrTable); 331 sr.put("send", subsTable); 332 stateTable.put(RosterItem.SUB_TO, sr); 333 subsTable.put(Presence.Type.subscribe, new Change(null, null, RosterItem.ASK_NONE)); 336 subsTable.put(Presence.Type.subscribed, new Change(RosterItem.RECV_NONE, RosterItem.SUB_BOTH, null)); 339 subsTable.put(Presence.Type.unsubscribe, new Change(null, RosterItem.SUB_NONE, RosterItem.ASK_UNSUBSCRIBE)); 342 subsTable.put(Presence.Type.unsubscribed, new Change(RosterItem.RECV_NONE, null, null)); 346 subrTable.put(Presence.Type.subscribe, new Change(RosterItem.RECV_SUBSCRIBE, null, null)); 349 subrTable.put(Presence.Type.subscribed, new Change(null, null, RosterItem.ASK_NONE)); 352 subrTable.put(Presence.Type.unsubscribe, new Change(RosterItem.RECV_NONE, RosterItem.SUB_NONE, null)); 355 subrTable.put(Presence.Type.unsubscribed, new Change(null, RosterItem.SUB_NONE, RosterItem.ASK_NONE)); 358 359 sr = new Hashtable (); 360 subrTable = new Hashtable (); 361 subsTable = new Hashtable (); 362 sr.put("recv", subrTable); 363 sr.put("send", subsTable); 364 stateTable.put(RosterItem.SUB_BOTH, sr); 365 subsTable.put(Presence.Type.subscribe, new Change(null, null, RosterItem.ASK_NONE)); 368 subsTable.put(Presence.Type.subscribed, new Change(RosterItem.RECV_NONE, null, null)); 372 subsTable.put(Presence.Type.unsubscribe, new Change(null, RosterItem.SUB_FROM, RosterItem.ASK_UNSUBSCRIBE)); 375 subsTable.put(Presence.Type.unsubscribed, new Change(RosterItem.RECV_NONE, RosterItem.SUB_TO, null)); 378 subrTable.put(Presence.Type.subscribe, new Change(RosterItem.RECV_NONE, null, null)); 383 subrTable.put(Presence.Type.subscribed, new Change(null, null, RosterItem.ASK_NONE)); 386 subrTable.put(Presence.Type.unsubscribe, new Change(RosterItem.RECV_UNSUBSCRIBE, RosterItem.SUB_TO, null)); 389 subrTable.put(Presence.Type.unsubscribed, new Change(RosterItem.RECV_NONE, RosterItem.SUB_FROM, RosterItem.ASK_NONE)); 392 } 393 394 398 private static class Change { 399 public Change(RosterItem.RecvType recv, RosterItem.SubType sub, RosterItem.AskType ask) { 400 newRecv = recv; 401 newSub = sub; 402 newAsk = ask; 403 } 404 405 public RosterItem.RecvType newRecv; 406 public RosterItem.SubType newSub; 407 public RosterItem.AskType newAsk; 408 } 409 410 425 private static void updateState(RosterItem item, Presence.Type action, boolean isSending) { 426 Map srTable = (Map )stateTable.get(item.getSubStatus()); 427 Map changeTable = (Map )srTable.get(isSending ? "send" : "recv"); 428 Change change = (Change)changeTable.get(action); 429 boolean modified = false; 430 if (change.newAsk != null && change.newAsk != item.getAskStatus()) { 431 item.setAskStatus(change.newAsk); 432 } 433 if (change.newSub != null && change.newSub != item.getSubStatus()) { 434 item.setSubStatus(change.newSub); 435 modified = true; 436 } 437 if (change.newRecv != null && change.newRecv != item.getRecvStatus()) { 438 item.setRecvStatus(change.newRecv); 439 } 440 } 441 442 public void initialize(XMPPServer server) { 443 super.initialize(server); 444 localServer = server; 445 routingTable = server.getRoutingTable(); 446 deliverer = server.getPacketDeliverer(); 447 presenceManager = server.getPresenceManager(); 448 } 449 } | Popular Tags |