1 20 21 package org.jivesoftware.smack; 22 23 import org.jivesoftware.smack.packet.*; 24 import org.jivesoftware.smack.filter.*; 25 import org.jivesoftware.smack.util.StringUtils; 26 27 import java.util.*; 28 29 42 public class Roster { 43 44 49 public static final int SUBSCRIPTION_ACCEPT_ALL = 0; 50 51 54 public static final int SUBSCRIPTION_REJECT_ALL = 1; 55 56 61 public static final int SUBSCRIPTION_MANUAL = 2; 62 63 67 private static int defaultSubscriptionMode = SUBSCRIPTION_ACCEPT_ALL; 68 69 private XMPPConnection connection; 70 private Map groups; 71 private List entries; 72 private List unfiledEntries; 73 private List rosterListeners; 74 private Map presenceMap; 75 boolean rosterInitialized = false; 78 79 private int subscriptionMode = getDefaultSubscriptionMode(); 80 81 89 public static int getDefaultSubscriptionMode() { 90 return defaultSubscriptionMode; 91 } 92 93 101 public static void setDefaultSubscriptionMode(int subscriptionMode) { 102 defaultSubscriptionMode = subscriptionMode; 103 } 104 105 110 Roster(final XMPPConnection connection) { 111 this.connection = connection; 112 groups = new Hashtable(); 113 unfiledEntries = new ArrayList(); 114 entries = new ArrayList(); 115 rosterListeners = new ArrayList(); 116 presenceMap = new HashMap(); 117 PacketFilter rosterFilter = new PacketTypeFilter(RosterPacket.class); 119 connection.addPacketListener(new RosterPacketListener(), rosterFilter); 120 PacketFilter presenceFilter = new PacketTypeFilter(Presence.class); 122 connection.addPacketListener(new PresencePacketListener(), presenceFilter); 123 } 124 125 136 public int getSubscriptionMode() { 137 return subscriptionMode; 138 } 139 140 151 public void setSubscriptionMode(int subscriptionMode) { 152 if (subscriptionMode != SUBSCRIPTION_ACCEPT_ALL && 153 subscriptionMode != SUBSCRIPTION_REJECT_ALL && 154 subscriptionMode != SUBSCRIPTION_MANUAL) 155 { 156 throw new IllegalArgumentException ("Invalid mode."); 157 } 158 this.subscriptionMode = subscriptionMode; 159 } 160 161 166 public void reload() { 167 connection.sendPacket(new RosterPacket()); 168 } 169 170 176 public void addRosterListener(RosterListener rosterListener) { 177 synchronized (rosterListeners) { 178 if (!rosterListeners.contains(rosterListener)) { 179 rosterListeners.add(rosterListener); 180 } 181 } 182 } 183 184 190 public void removeRosterListener(RosterListener rosterListener) { 191 synchronized (rosterListeners) { 192 rosterListeners.remove(rosterListener); 193 } 194 } 195 196 205 public RosterGroup createGroup(String name) { 206 synchronized (groups) { 207 if (groups.containsKey(name)) { 208 throw new IllegalArgumentException ("Group with name " + name + " alread exists."); 209 } 210 RosterGroup group = new RosterGroup(name, connection); 211 groups.put(name, group); 212 return group; 213 } 214 } 215 216 225 public void createEntry(String user, String name, String [] groups) throws XMPPException { 226 RosterPacket rosterPacket = new RosterPacket(); 228 rosterPacket.setType(IQ.Type.SET); 229 RosterPacket.Item item = new RosterPacket.Item(user, name); 230 if (groups != null) { 231 for (int i=0; i<groups.length; i++) { 232 if (groups[i] != null) { 233 item.addGroupName(groups[i]); 234 } 235 } 236 } 237 rosterPacket.addRosterItem(item); 238 PacketCollector collector = connection.createPacketCollector( 240 new PacketIDFilter(rosterPacket.getPacketID())); 241 connection.sendPacket(rosterPacket); 242 IQ response = (IQ)collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); 243 collector.cancel(); 244 if (response == null) { 245 throw new XMPPException("No response from the server."); 246 } 247 else if (response.getType() == IQ.Type.ERROR) { 249 throw new XMPPException(response.getError()); 250 } 251 252 Presence presencePacket = new Presence(Presence.Type.SUBSCRIBE); 254 presencePacket.setTo(user); 255 connection.sendPacket(presencePacket); 256 } 257 258 266 public void removeEntry(RosterEntry entry) throws XMPPException { 267 synchronized (entries) { 270 if (!entries.contains(entry)) { 271 return; 272 } 273 } 274 RosterPacket packet = new RosterPacket(); 275 packet.setType(IQ.Type.SET); 276 RosterPacket.Item item = RosterEntry.toRosterItem(entry); 277 item.setItemType(RosterPacket.ItemType.REMOVE); 279 packet.addRosterItem(item); 280 PacketCollector collector = connection.createPacketCollector( 281 new PacketIDFilter(packet.getPacketID())); 282 connection.sendPacket(packet); 283 IQ response = (IQ)collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); 284 collector.cancel(); 285 if (response == null) { 286 throw new XMPPException("No response from the server."); 287 } 288 else if (response.getType() == IQ.Type.ERROR) { 290 throw new XMPPException(response.getError()); 291 } 292 else { 293 294 } 295 } 296 297 302 public int getEntryCount() { 303 HashMap entryMap = new HashMap(); 304 for (Iterator groups = getGroups(); groups.hasNext(); ) { 306 RosterGroup rosterGroup = (RosterGroup) groups.next(); 307 for (Iterator entries = rosterGroup.getEntries(); entries.hasNext(); ) { 308 entryMap.put(entries.next(), ""); 309 } 310 } 311 synchronized (unfiledEntries) { 312 return entryMap.size() + unfiledEntries.size(); 313 } 314 } 315 316 322 public Iterator getEntries() { 323 ArrayList allEntries = new ArrayList(); 324 for (Iterator groups = getGroups(); groups.hasNext(); ) { 326 RosterGroup rosterGroup = (RosterGroup) groups.next(); 327 for (Iterator entries = rosterGroup.getEntries(); entries.hasNext(); ) { 328 RosterEntry entry = (RosterEntry)entries.next(); 329 if (!allEntries.contains(entry)) { 330 allEntries.add(entry); 331 } 332 } 333 } 334 synchronized (unfiledEntries) { 336 allEntries.addAll(unfiledEntries); 337 } 338 return allEntries.iterator(); 339 } 340 341 347 public int getUnfiledEntryCount() { 348 synchronized (unfiledEntries) { 349 return unfiledEntries.size(); 350 } 351 } 352 353 359 public Iterator getUnfiledEntries() { 360 synchronized (unfiledEntries) { 361 return Collections.unmodifiableList(new ArrayList(unfiledEntries)).iterator(); 362 } 363 } 364 365 373 public RosterEntry getEntry(String user) { 374 if (user == null) { 375 return null; 376 } 377 synchronized (entries) { 378 for (Iterator i=entries.iterator(); i.hasNext(); ) { 379 RosterEntry entry = (RosterEntry)i.next(); 380 if (entry.getUser().toLowerCase().equals(user.toLowerCase())) { 381 return entry; 382 } 383 } 384 } 385 return null; 386 } 387 388 395 public boolean contains(String user) { 396 if (user == null) { 397 return false; 398 } 399 synchronized (entries) { 400 for (Iterator i=entries.iterator(); i.hasNext(); ) { 401 RosterEntry entry = (RosterEntry)i.next(); 402 if (entry.getUser().toLowerCase().equals(user.toLowerCase())) { 403 return true; 404 } 405 } 406 } 407 return false; 408 } 409 410 417 public RosterGroup getGroup(String name) { 418 synchronized (groups) { 419 return (RosterGroup)groups.get(name); 420 } 421 } 422 423 428 public int getGroupCount() { 429 synchronized (groups) { 430 return groups.size(); 431 } 432 } 433 434 439 public Iterator getGroups() { 440 synchronized (groups) { 441 List groupsList = Collections.unmodifiableList(new ArrayList(groups.values())); 442 return groupsList.iterator(); 443 } 444 } 445 446 459 public Presence getPresence(String user) { 460 String key = getPresenceMapKey(user); 461 Map userPresences = (Map) presenceMap.get(key); 462 if (userPresences == null) { 463 return null; 464 } 465 else { 466 Iterator it = userPresences.keySet().iterator(); 469 Presence p; 470 Presence presence = null; 471 472 while (it.hasNext()) { 473 p = (Presence) userPresences.get(it.next()); 474 if (presence == null) { 475 presence = p; 476 } 477 else { 478 if (p.getPriority() > presence.getPriority()) { 479 presence = p; 480 } 481 } 482 } 483 return presence; 484 } 485 } 486 487 496 public Presence getPresenceResource(String userResource) { 497 String key = getPresenceMapKey(userResource); 498 String resource = StringUtils.parseResource(userResource); 499 Map userPresences = (Map)presenceMap.get(key); 500 if (userPresences == null) { 501 return null; 502 } 503 else { 504 return (Presence) userPresences.get(resource); 505 } 506 } 507 508 518 public Iterator getPresences(String user) { 519 String key = getPresenceMapKey(user); 520 Map userPresences = (Map)presenceMap.get(key); 521 if (userPresences == null) { 522 return null; 523 } 524 else { 525 synchronized (userPresences) { 526 return new HashMap(userPresences).values().iterator(); 527 } 528 } 529 } 530 531 542 private String getPresenceMapKey(String user) { 543 String key = user; 544 if (!contains(user)) { 545 key = StringUtils.parseBareAddress(user); 546 } 547 return key; 548 } 549 550 553 private void fireRosterChangedEvent() { 554 RosterListener [] listeners = null; 555 synchronized (rosterListeners) { 556 listeners = new RosterListener[rosterListeners.size()]; 557 rosterListeners.toArray(listeners); 558 } 559 for (int i=0; i<listeners.length; i++) { 560 listeners[i].rosterModified(); 561 } 562 } 563 564 567 private void fireRosterPresenceEvent(String user) { 568 RosterListener [] listeners = null; 569 synchronized (rosterListeners) { 570 listeners = new RosterListener[rosterListeners.size()]; 571 rosterListeners.toArray(listeners); 572 } 573 for (int i=0; i<listeners.length; i++) { 574 listeners[i].presenceChanged(user); 575 } 576 } 577 578 581 private class PresencePacketListener implements PacketListener { 582 public void processPacket(Packet packet) { 583 Presence presence = (Presence)packet; 584 String from = presence.getFrom(); 585 String key = getPresenceMapKey(from); 586 587 if (presence.getType() == Presence.Type.AVAILABLE) { 590 Map userPresences; 591 if (presenceMap.get(key) == null) { 593 userPresences = new HashMap(); 594 presenceMap.put(key, userPresences); 595 } 596 else { 597 userPresences = (Map)presenceMap.get(key); 598 } 599 synchronized (userPresences) { 601 userPresences.put(StringUtils.parseResource(from), presence); 602 } 603 synchronized (entries) { 605 for (Iterator i = entries.iterator(); i.hasNext();) { 606 RosterEntry entry = (RosterEntry) i.next(); 607 if (entry.getUser().toLowerCase().equals(key.toLowerCase())) { 608 fireRosterPresenceEvent(from); 609 } 610 } 611 } 612 } 613 else if (presence.getType() == Presence.Type.UNAVAILABLE) { 615 if (presenceMap.get(key) != null) { 616 Map userPresences = (Map) presenceMap.get(key); 617 synchronized (userPresences) { 618 userPresences.remove(StringUtils.parseResource(from)); 619 } 620 if (userPresences.isEmpty()) { 621 presenceMap.remove(key); 622 } 623 } 624 synchronized (entries) { 626 for (Iterator i=entries.iterator(); i.hasNext(); ) { 627 RosterEntry entry = (RosterEntry)i.next(); 628 if (entry.getUser().toLowerCase().equals(key.toLowerCase())) { 629 fireRosterPresenceEvent(from); 630 } 631 } 632 } 633 } 634 else if (presence.getType() == Presence.Type.SUBSCRIBE) { 635 if (subscriptionMode == SUBSCRIPTION_ACCEPT_ALL) { 636 Presence response = new Presence(Presence.Type.SUBSCRIBED); 638 response.setTo(presence.getFrom()); 639 connection.sendPacket(response); 640 } 641 else if (subscriptionMode == SUBSCRIPTION_REJECT_ALL) { 642 Presence response = new Presence(Presence.Type.UNSUBSCRIBED); 644 response.setTo(presence.getFrom()); 645 connection.sendPacket(response); 646 } 647 } 649 } 650 } 651 652 655 private class RosterPacketListener implements PacketListener { 656 657 public void processPacket(Packet packet) { 658 RosterPacket rosterPacket = (RosterPacket)packet; 659 for (Iterator i=rosterPacket.getRosterItems(); i.hasNext(); ) { 660 RosterPacket.Item item = (RosterPacket.Item)i.next(); 661 RosterEntry entry = new RosterEntry(item.getUser(), item.getName(), 662 item.getItemType(), connection); 663 664 if (RosterPacket.ItemType.REMOVE.equals(item.getItemType())) { 666 if (entries.contains(entry)) { 668 entries.remove(entry); 669 } 670 synchronized (unfiledEntries) { 672 if (unfiledEntries.contains(entry)) { 673 unfiledEntries.remove(entry); 674 } 675 } 676 String key = StringUtils.parseName(item.getUser()) + "@" + 679 StringUtils.parseServer(item.getUser()); 680 presenceMap.remove(key); 681 } 682 else { 683 if (!entries.contains(entry)) { 685 entries.add(entry); 686 } 687 else { 688 RosterEntry existingEntry = 690 (RosterEntry) entries.get(entries.indexOf(entry)); 691 existingEntry.updateState(entry.getName(), entry.getType()); 692 } 693 if (item.getGroupNames().hasNext()) { 696 synchronized (unfiledEntries) { 697 unfiledEntries.remove(entry); 698 } 699 } 700 else { 702 synchronized (unfiledEntries) { 703 if (!unfiledEntries.contains(entry)) { 704 unfiledEntries.add(entry); 705 } 706 } 707 } 708 } 709 710 List currentGroupNames = new ArrayList(); 712 for (Iterator j = entry.getGroups(); j.hasNext(); ) { 713 RosterGroup group = (RosterGroup)j.next(); 714 currentGroupNames.add(group.getName()); 715 } 716 717 if (!RosterPacket.ItemType.REMOVE.equals(item.getItemType())) { 719 List newGroupNames = new ArrayList(); 721 for (Iterator k = item.getGroupNames(); k.hasNext(); ) { 722 String groupName = (String )k.next(); 723 newGroupNames.add(groupName); 725 726 RosterGroup group = getGroup(groupName); 728 if (group == null) { 729 group = createGroup(groupName); 730 groups.put(groupName, group); 731 } 732 group.addEntryLocal(entry); 734 } 735 736 for (int m=0; m<newGroupNames.size(); m++) { 740 currentGroupNames.remove(newGroupNames.get(m)); 741 } 742 } 743 744 for (int n=0; n<currentGroupNames.size(); n++) { 747 String groupName = (String )currentGroupNames.get(n); 748 RosterGroup group = getGroup(groupName); 749 group.removeEntryLocal(entry); 750 if (group.getEntryCount() == 0) { 751 synchronized (groups) { 752 groups.remove(groupName); 753 } 754 } 755 } 756 for (Iterator it = getGroups(); it.hasNext();) { 761 RosterGroup group = (RosterGroup)it.next(); 762 if (group.getEntryCount() == 0) { 763 synchronized (groups) { 764 groups.remove(group.getName()); 765 } 766 } 767 } 768 } 769 770 synchronized (Roster.this) { 772 rosterInitialized = true; 773 Roster.this.notifyAll(); 774 } 775 776 fireRosterChangedEvent(); 778 } 779 } 780 } | Popular Tags |