1 20 21 package org.jivesoftware.smackx.muc; 22 23 import java.lang.ref.WeakReference ; 24 import java.lang.reflect.*; 25 import java.util.*; 26 27 import org.jivesoftware.smack.*; 28 import org.jivesoftware.smack.filter.*; 29 import org.jivesoftware.smack.packet.*; 30 import org.jivesoftware.smackx.Form; 31 import org.jivesoftware.smackx.NodeInformationProvider; 32 import org.jivesoftware.smackx.ServiceDiscoveryManager; 33 import org.jivesoftware.smackx.packet.*; 34 35 45 public class MultiUserChat { 46 47 private final static String discoNamespace = "http://jabber.org/protocol/muc"; 48 private final static String discoNode = "http://jabber.org/protocol/muc#rooms"; 49 50 private static Map joinedRooms = new WeakHashMap(); 51 52 private XMPPConnection connection; 53 private String room; 54 private String subject; 55 private String nickname = null; 56 private boolean joined = false; 57 private Map occupantsMap = new HashMap(); 58 59 private List invitationRejectionListeners = new ArrayList(); 60 private List subjectUpdatedListeners = new ArrayList(); 61 private List userStatusListeners = new ArrayList(); 62 private List participantStatusListeners = new ArrayList(); 63 64 private PacketFilter presenceFilter; 65 private PacketListener presenceListener; 66 private PacketFilter subjectFilter; 67 private PacketListener subjectListener; 68 private PacketFilter messageFilter; 69 private PacketFilter declinesFilter; 70 private PacketListener declinesListener; 71 private PacketCollector messageCollector; 72 private List connectionListeners = new ArrayList(); 73 74 static { 75 XMPPConnection.addConnectionListener(new ConnectionEstablishedListener() { 76 public void connectionEstablished(final XMPPConnection connection) { 77 ServiceDiscoveryManager.getInstanceFor(connection).addFeature(discoNamespace); 81 ServiceDiscoveryManager.getInstanceFor(connection).setNodeInformationProvider( 84 discoNode, 85 new NodeInformationProvider() { 86 public Iterator getNodeItems() { 87 ArrayList answer = new ArrayList(); 88 Iterator rooms=MultiUserChat.getJoinedRooms(connection); 89 while (rooms.hasNext()) { 90 answer.add(new DiscoverItems.Item((String )rooms.next())); 91 } 92 return answer.iterator(); 93 } 94 }); 95 } 96 }); 97 } 98 99 114 public MultiUserChat(XMPPConnection connection, String room) { 115 this.connection = connection; 116 this.room = room.toLowerCase(); 117 init(); 118 } 119 120 127 public static boolean isServiceEnabled(XMPPConnection connection, String user) { 128 try { 129 DiscoverInfo result = 130 ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(user); 131 return result.containsFeature(discoNamespace); 132 } 133 catch (XMPPException e) { 134 e.printStackTrace(); 135 return false; 136 } 137 } 138 139 147 private static Iterator getJoinedRooms(XMPPConnection connection) { 148 ArrayList rooms = (ArrayList)joinedRooms.get(connection); 149 if (rooms != null) { 150 return rooms.iterator(); 151 } 152 return new ArrayList().iterator(); 154 } 155 156 164 public static Iterator getJoinedRooms(XMPPConnection connection, String user) { 165 try { 166 ArrayList answer = new ArrayList(); 167 DiscoverItems result = 169 ServiceDiscoveryManager.getInstanceFor(connection).discoverItems(user, discoNode); 170 for (Iterator items=result.getItems(); items.hasNext();) { 172 answer.add(((DiscoverItems.Item)items.next()).getEntityID()); 173 } 174 return answer.iterator(); 175 } 176 catch (XMPPException e) { 177 e.printStackTrace(); 178 return new ArrayList().iterator(); 180 } 181 } 182 183 193 public static RoomInfo getRoomInfo(XMPPConnection connection, String room) 194 throws XMPPException { 195 DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(room); 196 return new RoomInfo(info); 197 } 198 199 206 public static Collection getServiceNames(XMPPConnection connection) throws XMPPException { 207 List answer = new ArrayList(); 208 ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); 209 DiscoverItems items = discoManager.discoverItems(connection.getServiceName()); 210 for (Iterator it = items.getItems(); it.hasNext();) { 211 DiscoverItems.Item item = (DiscoverItems.Item) it.next(); 212 DiscoverInfo info = discoManager.discoverInfo(item.getEntityID()); 213 if (info.containsFeature("http://jabber.org/protocol/muc")) { 214 answer.add(item.getEntityID()); 215 } 216 } 217 return answer; 218 } 219 220 230 public static Collection getHostedRooms(XMPPConnection connection, String serviceName) 231 throws XMPPException { 232 List answer = new ArrayList(); 233 ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); 234 DiscoverItems items = discoManager.discoverItems(serviceName); 235 for (Iterator it = items.getItems(); it.hasNext();) { 236 DiscoverItems.Item item = (DiscoverItems.Item) it.next(); 237 answer.add(new HostedRoom(item)); 238 } 239 return answer; 240 } 241 242 247 public String getRoom() { 248 return room; 249 } 250 251 271 public synchronized void create(String nickname) throws XMPPException { 272 if (nickname == null || nickname.equals("")) { 273 throw new IllegalArgumentException ("Nickname must not be null or blank."); 274 } 275 if (joined) { 278 throw new IllegalStateException ("Creation failed - User already joined the room."); 279 } 280 Presence joinPresence = new Presence(Presence.Type.AVAILABLE); 283 joinPresence.setTo(room + "/" + nickname); 284 joinPresence.addExtension(new MUCInitialPresence()); 286 287 PacketFilter responseFilter = 289 new AndFilter( 290 new FromMatchesFilter(room + "/" + nickname), 291 new PacketTypeFilter(Presence.class)); 292 PacketCollector response = connection.createPacketCollector(responseFilter); 293 connection.sendPacket(joinPresence); 295 Presence presence = 297 (Presence) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 298 response.cancel(); 300 301 if (presence == null) { 302 throw new XMPPException("No response from server."); 303 } 304 else if (presence.getError() != null) { 305 throw new XMPPException(presence.getError()); 306 } 307 this.nickname = nickname; 309 joined = true; 310 userHasJoined(); 311 312 MUCUser mucUser = getMUCUserExtension(presence); 314 if (mucUser != null && mucUser.getStatus() != null) { 315 if ("201".equals(mucUser.getStatus().getCode())) { 316 return; 318 } 319 } 320 leave(); 322 throw new XMPPException("Creation failed - Missing acknowledge of room creation."); 323 } 324 325 340 public void join(String nickname) throws XMPPException { 341 join(nickname, null, null, SmackConfiguration.getPacketReplyTimeout()); 342 } 343 344 363 public void join(String nickname, String password) throws XMPPException { 364 join(nickname, password, null, SmackConfiguration.getPacketReplyTimeout()); 365 } 366 367 392 public synchronized void join( 393 String nickname, 394 String password, 395 DiscussionHistory history, 396 long timeout) 397 throws XMPPException { 398 if (nickname == null || nickname.equals("")) { 399 throw new IllegalArgumentException ("Nickname must not be null or blank."); 400 } 401 if (joined) { 404 leave(); 405 } 406 Presence joinPresence = new Presence(Presence.Type.AVAILABLE); 409 joinPresence.setTo(room + "/" + nickname); 410 411 MUCInitialPresence mucInitialPresence = new MUCInitialPresence(); 413 if (password != null) { 414 mucInitialPresence.setPassword(password); 415 } 416 if (history != null) { 417 mucInitialPresence.setHistory(history.getMUCHistory()); 418 } 419 joinPresence.addExtension(mucInitialPresence); 420 421 PacketFilter responseFilter = 423 new AndFilter( 424 new FromMatchesFilter(room + "/" + nickname), 425 new PacketTypeFilter(Presence.class)); 426 PacketCollector response = connection.createPacketCollector(responseFilter); 427 connection.sendPacket(joinPresence); 429 Presence presence = (Presence) response.nextResult(timeout); 431 response.cancel(); 433 434 if (presence == null) { 435 throw new XMPPException("No response from server."); 436 } 437 else if (presence.getError() != null) { 438 throw new XMPPException(presence.getError()); 439 } 440 this.nickname = nickname; 441 joined = true; 442 userHasJoined(); 443 } 444 445 451 public boolean isJoined() { 452 return joined; 453 } 454 455 458 public synchronized void leave() { 459 if (!joined) { 461 return; 462 } 463 Presence leavePresence = new Presence(Presence.Type.UNAVAILABLE); 466 leavePresence.setTo(room + "/" + nickname); 467 connection.sendPacket(leavePresence); 468 occupantsMap = new HashMap(); 470 nickname = null; 471 joined = false; 472 userHasLeft(); 473 } 474 475 484 public Form getConfigurationForm() throws XMPPException { 485 MUCOwner iq = new MUCOwner(); 486 iq.setTo(room); 487 iq.setType(IQ.Type.GET); 488 489 PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 491 PacketCollector response = connection.createPacketCollector(responseFilter); 492 connection.sendPacket(iq); 494 IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 496 response.cancel(); 498 499 if (answer == null) { 500 throw new XMPPException("No response from server."); 501 } 502 else if (answer.getError() != null) { 503 throw new XMPPException(answer.getError()); 504 } 505 return Form.getFormFrom(answer); 506 } 507 508 516 public void sendConfigurationForm(Form form) throws XMPPException { 517 MUCOwner iq = new MUCOwner(); 518 iq.setTo(room); 519 iq.setType(IQ.Type.SET); 520 iq.addExtension(form.getDataFormToSend()); 521 522 PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 524 PacketCollector response = connection.createPacketCollector(responseFilter); 525 connection.sendPacket(iq); 527 IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 529 response.cancel(); 531 532 if (answer == null) { 533 throw new XMPPException("No response from server."); 534 } 535 else if (answer.getError() != null) { 536 throw new XMPPException(answer.getError()); 537 } 538 } 539 540 554 public Form getRegistrationForm() throws XMPPException { 555 Registration reg = new Registration(); 556 reg.setType(IQ.Type.GET); 557 reg.setTo(room); 558 559 PacketFilter filter = 560 new AndFilter(new PacketIDFilter(reg.getPacketID()), new PacketTypeFilter(IQ.class)); 561 PacketCollector collector = connection.createPacketCollector(filter); 562 connection.sendPacket(reg); 563 IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); 564 collector.cancel(); 565 if (result == null) { 566 throw new XMPPException("No response from server."); 567 } 568 else if (result.getType() == IQ.Type.ERROR) { 569 throw new XMPPException(result.getError()); 570 } 571 return Form.getFormFrom(result); 572 } 573 574 588 public void sendRegistrationForm(Form form) throws XMPPException { 589 Registration reg = new Registration(); 590 reg.setType(IQ.Type.SET); 591 reg.setTo(room); 592 reg.addExtension(form.getDataFormToSend()); 593 594 PacketFilter filter = 595 new AndFilter(new PacketIDFilter(reg.getPacketID()), new PacketTypeFilter(IQ.class)); 596 PacketCollector collector = connection.createPacketCollector(filter); 597 connection.sendPacket(reg); 598 IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); 599 collector.cancel(); 600 if (result == null) { 601 throw new XMPPException("No response from server."); 602 } 603 else if (result.getType() == IQ.Type.ERROR) { 604 throw new XMPPException(result.getError()); 605 } 606 } 607 608 620 public void destroy(String reason, String alternateJID) throws XMPPException { 621 MUCOwner iq = new MUCOwner(); 622 iq.setTo(room); 623 iq.setType(IQ.Type.SET); 624 625 MUCOwner.Destroy destroy = new MUCOwner.Destroy(); 627 destroy.setReason(reason); 628 destroy.setJid(alternateJID); 629 iq.setDestroy(destroy); 630 631 PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 633 PacketCollector response = connection.createPacketCollector(responseFilter); 634 connection.sendPacket(iq); 636 IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 638 response.cancel(); 640 641 if (answer == null) { 642 throw new XMPPException("No response from server."); 643 } 644 else if (answer.getError() != null) { 645 throw new XMPPException(answer.getError()); 646 } 647 occupantsMap = new HashMap(); 649 nickname = null; 650 joined = false; 651 userHasLeft(); 652 } 653 654 664 public void invite(String user, String reason) { 665 invite(new Message(), user, reason); 666 } 667 668 679 public void invite(Message message, String user, String reason) { 680 message.setTo(room); 682 683 MUCUser mucUser = new MUCUser(); 685 MUCUser.Invite invite = new MUCUser.Invite(); 686 invite.setTo(user); 687 invite.setReason(reason); 688 mucUser.setInvite(invite); 689 message.addExtension(mucUser); 691 692 connection.sendPacket(message); 693 } 694 695 704 public static void decline(XMPPConnection conn, String room, String inviter, String reason) { 705 Message message = new Message(room); 706 707 MUCUser mucUser = new MUCUser(); 709 MUCUser.Decline decline = new MUCUser.Decline(); 710 decline.setTo(inviter); 711 decline.setReason(reason); 712 mucUser.setDecline(decline); 713 message.addExtension(mucUser); 715 716 conn.sendPacket(message); 717 } 718 719 726 public static void addInvitationListener(XMPPConnection conn, InvitationListener listener) { 727 InvitationsMonitor.getInvitationsMonitor(conn).addInvitationListener(listener); 728 } 729 730 737 public static void removeInvitationListener(XMPPConnection conn, InvitationListener listener) { 738 InvitationsMonitor.getInvitationsMonitor(conn).removeInvitationListener(listener); 739 } 740 741 747 public void addInvitationRejectionListener(InvitationRejectionListener listener) { 748 synchronized (invitationRejectionListeners) { 749 if (!invitationRejectionListeners.contains(listener)) { 750 invitationRejectionListeners.add(listener); 751 } 752 } 753 } 754 755 761 public void removeInvitationRejectionListener(InvitationRejectionListener listener) { 762 synchronized (invitationRejectionListeners) { 763 invitationRejectionListeners.remove(listener); 764 } 765 } 766 767 770 private void fireInvitationRejectionListeners(String invitee, String reason) { 771 InvitationRejectionListener[] listeners = null; 772 synchronized (invitationRejectionListeners) { 773 listeners = new InvitationRejectionListener[invitationRejectionListeners.size()]; 774 invitationRejectionListeners.toArray(listeners); 775 } 776 for (int i = 0; i < listeners.length; i++) { 777 listeners[i].invitationDeclined(invitee, reason); 778 } 779 } 780 781 787 public void addSubjectUpdatedListener(SubjectUpdatedListener listener) { 788 synchronized (subjectUpdatedListeners) { 789 if (!subjectUpdatedListeners.contains(listener)) { 790 subjectUpdatedListeners.add(listener); 791 } 792 } 793 } 794 795 801 public void removeSubjectUpdatedListener(SubjectUpdatedListener listener) { 802 synchronized (subjectUpdatedListeners) { 803 subjectUpdatedListeners.remove(listener); 804 } 805 } 806 807 810 private void fireSubjectUpdatedListeners(String subject, String from) { 811 SubjectUpdatedListener[] listeners = null; 812 synchronized (subjectUpdatedListeners) { 813 listeners = new SubjectUpdatedListener[subjectUpdatedListeners.size()]; 814 subjectUpdatedListeners.toArray(listeners); 815 } 816 for (int i = 0; i < listeners.length; i++) { 817 listeners[i].subjectUpdated(subject, from); 818 } 819 } 820 821 834 public String getSubject() { 835 return subject; 836 } 837 838 846 public String getReservedNickname() { 847 try { 848 DiscoverInfo result = 849 ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo( 850 room, 851 "x-roomuser-item"); 852 for (Iterator identities = result.getIdentities(); identities.hasNext();) { 854 DiscoverInfo.Identity identity = (DiscoverInfo.Identity) identities.next(); 855 return identity.getName(); 856 } 857 return null; 859 } 860 catch (XMPPException e) { 861 e.printStackTrace(); 862 return null; 863 } 864 } 865 866 872 public String getNickname() { 873 return nickname; 874 } 875 876 886 public void changeNickname(String nickname) throws XMPPException { 887 if (nickname == null || nickname.equals("")) { 888 throw new IllegalArgumentException ("Nickname must not be null or blank."); 889 } 890 if (!joined) { 893 throw new IllegalStateException ("Must be logged into the room to change nickname."); 894 } 895 Presence joinPresence = new Presence(Presence.Type.AVAILABLE); 899 joinPresence.setTo(room + "/" + nickname); 900 901 PacketFilter responseFilter = 903 new AndFilter( 904 new FromMatchesFilter(room + "/" + nickname), 905 new PacketTypeFilter(Presence.class)); 906 PacketCollector response = connection.createPacketCollector(responseFilter); 907 connection.sendPacket(joinPresence); 909 Presence presence = 911 (Presence) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 912 response.cancel(); 914 915 if (presence == null) { 916 throw new XMPPException("No response from server."); 917 } 918 else if (presence.getError() != null) { 919 throw new XMPPException(presence.getError()); 920 } 921 this.nickname = nickname; 922 } 923 924 932 public void changeAvailabilityStatus(String status, Presence.Mode mode) { 933 if (nickname == null || nickname.equals("")) { 934 throw new IllegalArgumentException ("Nickname must not be null or blank."); 935 } 936 if (!joined) { 939 throw new IllegalStateException ( 940 "Must be logged into the room to change the " + "availability status."); 941 } 942 Presence joinPresence = new Presence(Presence.Type.AVAILABLE); 945 joinPresence.setStatus(status); 946 joinPresence.setMode(mode); 947 joinPresence.setTo(room + "/" + nickname); 948 949 connection.sendPacket(joinPresence); 951 } 952 953 971 public void kickParticipant(String nickname, String reason) throws XMPPException { 972 changeRole(nickname, "none", reason); 973 } 974 975 986 public void grantVoice(Collection nicknames) throws XMPPException { 987 changeRole(nicknames, "participant"); 988 } 989 990 1001 public void grantVoice(String nickname) throws XMPPException { 1002 changeRole(nickname, "participant", null); 1003 } 1004 1005 1016 public void revokeVoice(Collection nicknames) throws XMPPException { 1017 changeRole(nicknames, "visitor"); 1018 } 1019 1020 1031 public void revokeVoice(String nickname) throws XMPPException { 1032 changeRole(nickname, "visitor", null); 1033 } 1034 1035 1047 public void banUsers(Collection jids) throws XMPPException { 1048 changeAffiliationByAdmin(jids, "outcast"); 1049 } 1050 1051 1064 public void banUser(String jid, String reason) throws XMPPException { 1065 changeAffiliationByAdmin(jid, "outcast", reason); 1066 } 1067 1068 1076 public void grantMembership(Collection jids) throws XMPPException { 1077 changeAffiliationByAdmin(jids, "member"); 1078 } 1079 1080 1088 public void grantMembership(String jid) throws XMPPException { 1089 changeAffiliationByAdmin(jid, "member", null); 1090 } 1091 1092 1101 public void revokeMembership(Collection jids) throws XMPPException { 1102 changeAffiliationByAdmin(jids, "none"); 1103 } 1104 1105 1114 public void revokeMembership(String jid) throws XMPPException { 1115 changeAffiliationByAdmin(jid, "none", null); 1116 } 1117 1118 1126 public void grantModerator(Collection nicknames) throws XMPPException { 1127 changeRole(nicknames, "moderator"); 1128 } 1129 1130 1138 public void grantModerator(String nickname) throws XMPPException { 1139 changeRole(nickname, "moderator", null); 1140 } 1141 1142 1151 public void revokeModerator(Collection nicknames) throws XMPPException { 1152 changeRole(nicknames, "participant"); 1153 } 1154 1155 1164 public void revokeModerator(String nickname) throws XMPPException { 1165 changeRole(nickname, "participant", null); 1166 } 1167 1168 1177 public void grantOwnership(Collection jids) throws XMPPException { 1178 changeAffiliationByOwner(jids, "owner"); 1179 } 1180 1181 1190 public void grantOwnership(String jid) throws XMPPException { 1191 changeAffiliationByOwner(jid, "owner"); 1192 } 1193 1194 1202 public void revokeOwnership(Collection jids) throws XMPPException { 1203 changeAffiliationByOwner(jids, "admin"); 1204 } 1205 1206 1214 public void revokeOwnership(String jid) throws XMPPException { 1215 changeAffiliationByOwner(jid, "admin"); 1216 } 1217 1218 1226 public void grantAdmin(Collection jids) throws XMPPException { 1227 changeAffiliationByOwner(jids, "admin"); 1228 } 1229 1230 1239 public void grantAdmin(String jid) throws XMPPException { 1240 changeAffiliationByOwner(jid, "admin"); 1241 } 1242 1243 1251 public void revokeAdmin(Collection jids) throws XMPPException { 1252 changeAffiliationByOwner(jids, "member"); 1253 } 1254 1255 1264 public void revokeAdmin(String jid) throws XMPPException { 1265 changeAffiliationByOwner(jid, "member"); 1266 } 1267 1268 private void changeAffiliationByOwner(String jid, String affiliation) throws XMPPException { 1269 MUCOwner iq = new MUCOwner(); 1270 iq.setTo(room); 1271 iq.setType(IQ.Type.SET); 1272 MUCOwner.Item item = new MUCOwner.Item(affiliation); 1274 item.setJid(jid); 1275 iq.addItem(item); 1276 1277 PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1279 PacketCollector response = connection.createPacketCollector(responseFilter); 1280 connection.sendPacket(iq); 1282 IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1284 response.cancel(); 1286 1287 if (answer == null) { 1288 throw new XMPPException("No response from server."); 1289 } 1290 else if (answer.getError() != null) { 1291 throw new XMPPException(answer.getError()); 1292 } 1293 } 1294 1295 private void changeAffiliationByOwner(Collection jids, String affiliation) 1296 throws XMPPException { 1297 MUCOwner iq = new MUCOwner(); 1298 iq.setTo(room); 1299 iq.setType(IQ.Type.SET); 1300 for (Iterator it=jids.iterator(); it.hasNext();) { 1301 MUCOwner.Item item = new MUCOwner.Item(affiliation); 1303 item.setJid((String ) it.next()); 1304 iq.addItem(item); 1305 } 1306 1307 PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1309 PacketCollector response = connection.createPacketCollector(responseFilter); 1310 connection.sendPacket(iq); 1312 IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1314 response.cancel(); 1316 1317 if (answer == null) { 1318 throw new XMPPException("No response from server."); 1319 } 1320 else if (answer.getError() != null) { 1321 throw new XMPPException(answer.getError()); 1322 } 1323 } 1324 1325 private void changeAffiliationByAdmin(String jid, String affiliation, String reason) 1326 throws XMPPException { 1327 MUCAdmin iq = new MUCAdmin(); 1328 iq.setTo(room); 1329 iq.setType(IQ.Type.SET); 1330 MUCAdmin.Item item = new MUCAdmin.Item(affiliation, null); 1332 item.setJid(jid); 1333 item.setReason(reason); 1334 iq.addItem(item); 1335 1336 PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1338 PacketCollector response = connection.createPacketCollector(responseFilter); 1339 connection.sendPacket(iq); 1341 IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1343 response.cancel(); 1345 1346 if (answer == null) { 1347 throw new XMPPException("No response from server."); 1348 } 1349 else if (answer.getError() != null) { 1350 throw new XMPPException(answer.getError()); 1351 } 1352 } 1353 1354 private void changeAffiliationByAdmin(Collection jids, String affiliation) 1355 throws XMPPException { 1356 MUCAdmin iq = new MUCAdmin(); 1357 iq.setTo(room); 1358 iq.setType(IQ.Type.SET); 1359 for (Iterator it=jids.iterator(); it.hasNext();) { 1360 MUCAdmin.Item item = new MUCAdmin.Item(affiliation, null); 1362 item.setJid((String ) it.next()); 1363 iq.addItem(item); 1364 } 1365 1366 PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1368 PacketCollector response = connection.createPacketCollector(responseFilter); 1369 connection.sendPacket(iq); 1371 IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1373 response.cancel(); 1375 1376 if (answer == null) { 1377 throw new XMPPException("No response from server."); 1378 } 1379 else if (answer.getError() != null) { 1380 throw new XMPPException(answer.getError()); 1381 } 1382 } 1383 1384 private void changeRole(String nickname, String role, String reason) throws XMPPException { 1385 MUCAdmin iq = new MUCAdmin(); 1386 iq.setTo(room); 1387 iq.setType(IQ.Type.SET); 1388 MUCAdmin.Item item = new MUCAdmin.Item(null, role); 1390 item.setNick(nickname); 1391 item.setReason(reason); 1392 iq.addItem(item); 1393 1394 PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1396 PacketCollector response = connection.createPacketCollector(responseFilter); 1397 connection.sendPacket(iq); 1399 IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1401 response.cancel(); 1403 1404 if (answer == null) { 1405 throw new XMPPException("No response from server."); 1406 } 1407 else if (answer.getError() != null) { 1408 throw new XMPPException(answer.getError()); 1409 } 1410 } 1411 1412 private void changeRole(Collection nicknames, String role) throws XMPPException { 1413 MUCAdmin iq = new MUCAdmin(); 1414 iq.setTo(room); 1415 iq.setType(IQ.Type.SET); 1416 for (Iterator it=nicknames.iterator(); it.hasNext();) { 1417 MUCAdmin.Item item = new MUCAdmin.Item(null, role); 1419 item.setNick((String ) it.next()); 1420 iq.addItem(item); 1421 } 1422 1423 PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1425 PacketCollector response = connection.createPacketCollector(responseFilter); 1426 connection.sendPacket(iq); 1428 IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1430 response.cancel(); 1432 1433 if (answer == null) { 1434 throw new XMPPException("No response from server."); 1435 } 1436 else if (answer.getError() != null) { 1437 throw new XMPPException(answer.getError()); 1438 } 1439 } 1440 1441 1451 public int getOccupantsCount() { 1452 synchronized (occupantsMap) { 1453 return occupantsMap.size(); 1454 } 1455 } 1456 1457 1468 public Iterator getOccupants() { 1469 synchronized (occupantsMap) { 1470 return Collections.unmodifiableList(new ArrayList(occupantsMap.keySet())).iterator(); 1471 } 1472 } 1473 1474 1483 public Presence getOccupantPresence(String user) { 1484 return (Presence) occupantsMap.get(user); 1485 } 1486 1487 1496 public Occupant getOccupant(String user) { 1497 Presence presence = (Presence) occupantsMap.get(user); 1498 if (presence != null) { 1499 return new Occupant(presence); 1500 } 1501 return null; 1502 } 1503 1504 1512 public void addParticipantListener(PacketListener listener) { 1513 connection.addPacketListener(listener, presenceFilter); 1514 connectionListeners.add(listener); 1515 } 1516 1517 1524 public void removeParticipantListener(PacketListener listener) { 1525 connection.removePacketListener(listener); 1526 connectionListeners.remove(listener); 1527 } 1528 1529 1536 public Collection getOwners() throws XMPPException { 1537 return getAffiliatesByOwner("owner"); 1538 } 1539 1540 1547 public Collection getAdmins() throws XMPPException { 1548 return getAffiliatesByOwner("admin"); 1549 } 1550 1551 1558 public Collection getMembers() throws XMPPException { 1559 return getAffiliatesByAdmin("member"); 1560 } 1561 1562 1569 public Collection getOutcasts() throws XMPPException { 1570 return getAffiliatesByAdmin("outcast"); 1571 } 1572 1573 1582 private Collection getAffiliatesByOwner(String affiliation) throws XMPPException { 1583 MUCOwner iq = new MUCOwner(); 1584 iq.setTo(room); 1585 iq.setType(IQ.Type.GET); 1586 MUCOwner.Item item = new MUCOwner.Item(affiliation); 1588 iq.addItem(item); 1589 1590 PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1592 PacketCollector response = connection.createPacketCollector(responseFilter); 1593 connection.sendPacket(iq); 1595 MUCOwner answer = (MUCOwner) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1597 response.cancel(); 1599 1600 if (answer == null) { 1601 throw new XMPPException("No response from server."); 1602 } 1603 else if (answer.getError() != null) { 1604 throw new XMPPException(answer.getError()); 1605 } 1606 List affiliates = new ArrayList(); 1608 for (Iterator it = answer.getItems(); it.hasNext();) { 1609 affiliates.add(new Affiliate((MUCOwner.Item) it.next())); 1610 } 1611 return affiliates; 1612 } 1613 1614 1623 private Collection getAffiliatesByAdmin(String affiliation) throws XMPPException { 1624 MUCAdmin iq = new MUCAdmin(); 1625 iq.setTo(room); 1626 iq.setType(IQ.Type.GET); 1627 MUCAdmin.Item item = new MUCAdmin.Item(affiliation, null); 1629 iq.addItem(item); 1630 1631 PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1633 PacketCollector response = connection.createPacketCollector(responseFilter); 1634 connection.sendPacket(iq); 1636 MUCAdmin answer = (MUCAdmin) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1638 response.cancel(); 1640 1641 if (answer == null) { 1642 throw new XMPPException("No response from server."); 1643 } 1644 else if (answer.getError() != null) { 1645 throw new XMPPException(answer.getError()); 1646 } 1647 List affiliates = new ArrayList(); 1649 for (Iterator it = answer.getItems(); it.hasNext();) { 1650 affiliates.add(new Affiliate((MUCAdmin.Item) it.next())); 1651 } 1652 return affiliates; 1653 } 1654 1655 1662 public Collection getModerators() throws XMPPException { 1663 return getOccupants("moderator"); 1664 } 1665 1666 1673 public Collection getParticipants() throws XMPPException { 1674 return getOccupants("participant"); 1675 } 1676 1677 1685 private Collection getOccupants(String role) throws XMPPException { 1686 MUCAdmin iq = new MUCAdmin(); 1687 iq.setTo(room); 1688 iq.setType(IQ.Type.GET); 1689 MUCAdmin.Item item = new MUCAdmin.Item(null, role); 1691 iq.addItem(item); 1692 1693 PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1695 PacketCollector response = connection.createPacketCollector(responseFilter); 1696 connection.sendPacket(iq); 1698 MUCAdmin answer = (MUCAdmin) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1700 response.cancel(); 1702 1703 if (answer == null) { 1704 throw new XMPPException("No response from server."); 1705 } 1706 else if (answer.getError() != null) { 1707 throw new XMPPException(answer.getError()); 1708 } 1709 List participants = new ArrayList(); 1711 for (Iterator it = answer.getItems(); it.hasNext();) { 1712 participants.add(new Occupant((MUCAdmin.Item) it.next())); 1713 } 1714 return participants; 1715 } 1716 1717 1723 public void sendMessage(String text) throws XMPPException { 1724 Message message = new Message(room, Message.Type.GROUP_CHAT); 1725 message.setBody(text); 1726 connection.sendPacket(message); 1727 } 1728 1729 1738 public Chat createPrivateChat(String occupant) { 1739 return new Chat(connection, occupant); 1740 } 1741 1742 1747 public Message createMessage() { 1748 return new Message(room, Message.Type.GROUP_CHAT); 1749 } 1750 1751 1757 public void sendMessage(Message message) throws XMPPException { 1758 connection.sendPacket(message); 1759 } 1760 1761 1772 public Message pollMessage() { 1773 return (Message) messageCollector.pollResult(); 1774 } 1775 1776 1782 public Message nextMessage() { 1783 return (Message) messageCollector.nextResult(); 1784 } 1785 1786 1795 public Message nextMessage(long timeout) { 1796 return (Message) messageCollector.nextResult(timeout); 1797 } 1798 1799 1809 public void addMessageListener(PacketListener listener) { 1810 connection.addPacketListener(listener, messageFilter); 1811 connectionListeners.add(listener); 1812 } 1813 1814 1821 public void removeMessageListener(PacketListener listener) { 1822 connection.removePacketListener(listener); 1823 connectionListeners.remove(listener); 1824 } 1825 1826 1835 public void changeSubject(final String subject) throws XMPPException { 1836 Message message = new Message(room, Message.Type.GROUP_CHAT); 1837 message.setSubject(subject); 1838 PacketFilter responseFilter = 1840 new AndFilter( 1841 new FromMatchesFilter(room), 1842 new PacketTypeFilter(Message.class)); 1843 responseFilter = new AndFilter(responseFilter, new PacketFilter() { 1844 public boolean accept(Packet packet) { 1845 Message msg = (Message) packet; 1846 return subject.equals(msg.getSubject()); 1847 } 1848 }); 1849 PacketCollector response = connection.createPacketCollector(responseFilter); 1850 connection.sendPacket(message); 1852 Message answer = 1854 (Message) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1855 response.cancel(); 1857 1858 if (answer == null) { 1859 throw new XMPPException("No response from server."); 1860 } 1861 else if (answer.getError() != null) { 1862 throw new XMPPException(answer.getError()); 1863 } 1864 } 1865 1866 1869 private synchronized void userHasJoined() { 1870 ArrayList rooms = (ArrayList)joinedRooms.get(connection); 1872 if (rooms == null) { 1873 rooms = new ArrayList(); 1874 joinedRooms.put(connection, rooms); 1875 } 1876 rooms.add(room); 1877 } 1878 1879 1882 private synchronized void userHasLeft() { 1883 ArrayList rooms = (ArrayList)joinedRooms.get(connection); 1885 if (rooms == null) { 1886 return; 1887 } 1888 rooms.remove(room); 1889 } 1890 1891 1897 private MUCUser getMUCUserExtension(Packet packet) { 1898 if (packet != null) { 1899 return (MUCUser) packet.getExtension("x", "http://jabber.org/protocol/muc#user"); 1901 } 1902 return null; 1903 } 1904 1905 1911 public void addUserStatusListener(UserStatusListener listener) { 1912 synchronized (userStatusListeners) { 1913 if (!userStatusListeners.contains(listener)) { 1914 userStatusListeners.add(listener); 1915 } 1916 } 1917 } 1918 1919 1925 public void removeUserStatusListener(UserStatusListener listener) { 1926 synchronized (userStatusListeners) { 1927 userStatusListeners.remove(listener); 1928 } 1929 } 1930 1931 private void fireUserStatusListeners(String methodName, Object [] params) { 1932 UserStatusListener[] listeners = null; 1933 synchronized (userStatusListeners) { 1934 listeners = new UserStatusListener[userStatusListeners.size()]; 1935 userStatusListeners.toArray(listeners); 1936 } 1937 Class [] paramClasses = new Class [params.length]; 1939 for (int i = 0; i < params.length; i++) { 1940 paramClasses[i] = params[i].getClass(); 1941 } 1942 try { 1943 Method method = UserStatusListener.class.getDeclaredMethod(methodName, paramClasses); 1945 for (int i = 0; i < listeners.length; i++) { 1946 method.invoke(listeners[i], params); 1947 } 1948 } catch (NoSuchMethodException e) { 1949 e.printStackTrace(); 1950 } catch (InvocationTargetException e) { 1951 e.printStackTrace(); 1952 } catch (IllegalAccessException e) { 1953 e.printStackTrace(); 1954 } 1955 } 1956 1957 1963 public void addParticipantStatusListener(ParticipantStatusListener listener) { 1964 synchronized (participantStatusListeners) { 1965 if (!participantStatusListeners.contains(listener)) { 1966 participantStatusListeners.add(listener); 1967 } 1968 } 1969 } 1970 1971 1977 public void removeParticipantStatusListener(ParticipantStatusListener listener) { 1978 synchronized (participantStatusListeners) { 1979 participantStatusListeners.remove(listener); 1980 } 1981 } 1982 1983 private void fireParticipantStatusListeners(String methodName, String param) { 1984 ParticipantStatusListener[] listeners = null; 1985 synchronized (participantStatusListeners) { 1986 listeners = new ParticipantStatusListener[participantStatusListeners.size()]; 1987 participantStatusListeners.toArray(listeners); 1988 } 1989 try { 1990 Method method = 1992 ParticipantStatusListener.class.getDeclaredMethod( 1993 methodName, 1994 new Class [] { String .class }); 1995 for (int i = 0; i < listeners.length; i++) { 1996 method.invoke(listeners[i], new Object [] {param}); 1997 } 1998 } catch (NoSuchMethodException e) { 1999 e.printStackTrace(); 2000 } catch (InvocationTargetException e) { 2001 e.printStackTrace(); 2002 } catch (IllegalAccessException e) { 2003 e.printStackTrace(); 2004 } 2005 } 2006 2007 private void init() { 2008 messageFilter = 2010 new AndFilter( 2011 new FromMatchesFilter(room), 2012 new MessageTypeFilter(Message.Type.GROUP_CHAT)); 2013 messageFilter = new AndFilter(messageFilter, new PacketFilter() { 2014 public boolean accept(Packet packet) { 2015 Message msg = (Message) packet; 2016 return msg.getBody() != null; 2017 } 2018 }); 2019 messageCollector = connection.createPacketCollector(messageFilter); 2020 2021 subjectFilter = 2023 new AndFilter( 2024 new FromMatchesFilter(room), 2025 new MessageTypeFilter(Message.Type.GROUP_CHAT)); 2026 subjectFilter = new AndFilter(subjectFilter, new PacketFilter() { 2027 public boolean accept(Packet packet) { 2028 Message msg = (Message) packet; 2029 return msg.getSubject() != null; 2030 } 2031 }); 2032 subjectListener = new PacketListener() { 2033 public void processPacket(Packet packet) { 2034 Message msg = (Message) packet; 2035 subject = msg.getSubject(); 2037 fireSubjectUpdatedListeners( 2039 msg.getSubject(), 2040 msg.getFrom()); 2041 2042 } 2043 }; 2044 connection.addPacketListener(subjectListener, subjectFilter); 2045 2046 presenceFilter = 2048 new AndFilter(new FromMatchesFilter(room), new PacketTypeFilter(Presence.class)); 2049 presenceListener = new PacketListener() { 2050 public void processPacket(Packet packet) { 2051 Presence presence = (Presence) packet; 2052 String from = presence.getFrom(); 2053 String myRoomJID = room + "/" + nickname; 2054 boolean isUserStatusModification = presence.getFrom().equals(myRoomJID); 2055 if (presence.getType() == Presence.Type.AVAILABLE) { 2056 Presence oldPresence; 2057 synchronized (occupantsMap) { 2058 oldPresence = (Presence)occupantsMap.get(from); 2059 occupantsMap.put(from, presence); 2060 } 2061 if (oldPresence != null) { 2062 MUCUser mucExtension = getMUCUserExtension(oldPresence); 2064 String oldAffiliation = mucExtension.getItem().getAffiliation(); 2065 String oldRole = mucExtension.getItem().getRole(); 2066 mucExtension = getMUCUserExtension(presence); 2068 String newAffiliation = mucExtension.getItem().getAffiliation(); 2069 String newRole = mucExtension.getItem().getRole(); 2070 checkRoleModifications(oldRole, newRole, isUserStatusModification, from); 2072 checkAffiliationModifications( 2074 oldAffiliation, 2075 newAffiliation, 2076 isUserStatusModification, 2077 from); 2078 } 2079 else { 2080 if (!isUserStatusModification) { 2082 fireParticipantStatusListeners("joined", from); 2083 } 2084 } 2085 } 2086 else if (presence.getType() == Presence.Type.UNAVAILABLE) { 2087 synchronized (occupantsMap) { 2088 occupantsMap.remove(from); 2089 } 2090 MUCUser mucUser = getMUCUserExtension(presence); 2091 if (mucUser != null && mucUser.getStatus() != null) { 2092 checkPresenceCode( 2094 mucUser.getStatus().getCode(), 2095 presence.getFrom().equals(myRoomJID), 2096 mucUser, 2097 from); 2098 } else { 2099 if (!isUserStatusModification) { 2101 fireParticipantStatusListeners("left", from); 2102 } 2103 } 2104 } 2105 } 2106 }; 2107 connection.addPacketListener(presenceListener, presenceFilter); 2108 2109 declinesFilter = new PacketExtensionFilter("x", "http://jabber.org/protocol/muc#user"); 2112 declinesListener = new PacketListener() { 2113 public void processPacket(Packet packet) { 2114 MUCUser mucUser = getMUCUserExtension(packet); 2116 if (mucUser.getDecline() != null) { 2118 fireInvitationRejectionListeners( 2120 mucUser.getDecline().getFrom(), 2121 mucUser.getDecline().getReason()); 2122 } 2123 }; 2124 }; 2125 connection.addPacketListener(declinesListener, declinesFilter); 2126 } 2127 2128 2164 private void checkRoleModifications( 2165 String oldRole, 2166 String newRole, 2167 boolean isUserModification, 2168 String from) { 2169 if (("visitor".equals(oldRole) || "none".equals(oldRole)) 2171 && "participant".equals(newRole)) { 2172 if (isUserModification) { 2173 fireUserStatusListeners("voiceGranted", new Object [] {}); 2174 } 2175 else { 2176 fireParticipantStatusListeners("voiceGranted", from); 2177 } 2178 } 2179 else if ( 2181 "participant".equals(oldRole) 2182 && ("visitor".equals(newRole) || "none".equals(newRole))) { 2183 if (isUserModification) { 2184 fireUserStatusListeners("voiceRevoked", new Object [] {}); 2185 } 2186 else { 2187 fireParticipantStatusListeners("voiceRevoked", from); 2188 } 2189 } 2190 if (!"moderator".equals(oldRole) && "moderator".equals(newRole)) { 2192 if ("visitor".equals(oldRole) || "none".equals(oldRole)) { 2193 if (isUserModification) { 2194 fireUserStatusListeners("voiceGranted", new Object [] {}); 2195 } 2196 else { 2197 fireParticipantStatusListeners("voiceGranted", from); 2198 } 2199 } 2200 if (isUserModification) { 2201 fireUserStatusListeners("moderatorGranted", new Object [] {}); 2202 } 2203 else { 2204 fireParticipantStatusListeners("moderatorGranted", from); 2205 } 2206 } 2207 else if ("moderator".equals(oldRole) && !"moderator".equals(newRole)) { 2209 if ("visitor".equals(newRole) || "none".equals(newRole)) { 2210 if (isUserModification) { 2211 fireUserStatusListeners("voiceRevoked", new Object [] {}); 2212 } 2213 else { 2214 fireParticipantStatusListeners("voiceRevoked", from); 2215 } 2216 } 2217 if (isUserModification) { 2218 fireUserStatusListeners("moderatorRevoked", new Object [] {}); 2219 } 2220 else { 2221 fireParticipantStatusListeners("moderatorRevoked", from); 2222 } 2223 } 2224 } 2225 2226 2266 private void checkAffiliationModifications( 2267 String oldAffiliation, 2268 String newAffiliation, 2269 boolean isUserModification, 2270 String from) { 2271 2274 if ("owner".equals(oldAffiliation) && !"owner".equals(newAffiliation)) { 2276 if (isUserModification) { 2277 fireUserStatusListeners("ownershipRevoked", new Object [] {}); 2278 } 2279 else { 2280 fireParticipantStatusListeners("ownershipRevoked", from); 2281 } 2282 } 2283 else if ("admin".equals(oldAffiliation) && !"admin".equals(newAffiliation)) { 2285 if (isUserModification) { 2286 fireUserStatusListeners("adminRevoked", new Object [] {}); 2287 } 2288 else { 2289 fireParticipantStatusListeners("adminRevoked", from); 2290 } 2291 } 2292 else if ("member".equals(oldAffiliation) && !"member".equals(newAffiliation)) { 2294 if (isUserModification) { 2295 fireUserStatusListeners("membershipRevoked", new Object [] {}); 2296 } 2297 else { 2298 fireParticipantStatusListeners("membershipRevoked", from); 2299 } 2300 } 2301 2302 if (!"owner".equals(oldAffiliation) && "owner".equals(newAffiliation)) { 2304 if (isUserModification) { 2305 fireUserStatusListeners("ownershipGranted", new Object [] {}); 2306 } 2307 else { 2308 fireParticipantStatusListeners("ownershipGranted", from); 2309 } 2310 } 2311 else if (!"admin".equals(oldAffiliation) && "admin".equals(newAffiliation)) { 2313 if (isUserModification) { 2314 fireUserStatusListeners("adminGranted", new Object [] {}); 2315 } 2316 else { 2317 fireParticipantStatusListeners("adminGranted", from); 2318 } 2319 } 2320 else if (!"member".equals(oldAffiliation) && "member".equals(newAffiliation)) { 2322 if (isUserModification) { 2323 fireUserStatusListeners("membershipGranted", new Object [] {}); 2324 } 2325 else { 2326 fireParticipantStatusListeners("membershipGranted", from); 2327 } 2328 } 2329 } 2330 2331 2339 private void checkPresenceCode( 2340 String code, 2341 boolean isUserModification, 2342 MUCUser mucUser, 2343 String from) { 2344 if ("307".equals(code)) { 2346 if (isUserModification) { 2348 joined = false; 2349 2350 fireUserStatusListeners( 2351 "kicked", 2352 new Object [] { mucUser.getItem().getActor(), mucUser.getItem().getReason()}); 2353 2354 occupantsMap = new HashMap(); 2356 nickname = null; 2357 userHasLeft(); 2358 } 2359 else { 2360 fireParticipantStatusListeners("kicked", from); 2361 } 2362 } 2363 else if ("301".equals(code)) { 2365 if (isUserModification) { 2367 joined = false; 2368 2369 fireUserStatusListeners( 2370 "banned", 2371 new Object [] { mucUser.getItem().getActor(), mucUser.getItem().getReason()}); 2372 2373 occupantsMap = new HashMap(); 2375 nickname = null; 2376 userHasLeft(); 2377 } 2378 else { 2379 fireParticipantStatusListeners("banned", from); 2381 } 2382 } 2383 else if ("321".equals(code)) { 2385 if (isUserModification) { 2387 joined = false; 2388 2389 fireUserStatusListeners("membershipRevoked", new Object [] {}); 2390 2391 occupantsMap = new HashMap(); 2393 nickname = null; 2394 userHasLeft(); 2395 } 2396 } 2397 else if ("303".equals(code)) { 2399 fireParticipantStatusListeners("nicknameChanged", mucUser.getItem().getNick()); 2400 } 2401 } 2402 2403 public void finalize() throws Throwable { 2404 super.finalize(); 2405 try { 2406 if (connection != null) { 2407 messageCollector.cancel(); 2408 connection.removePacketListener(subjectListener); 2409 connection.removePacketListener(presenceListener); 2410 connection.removePacketListener(declinesListener); 2411 for (Iterator it=connectionListeners.iterator(); it.hasNext();) { 2413 connection.removePacketListener((PacketListener) it.next()); 2414 } 2415 } 2416 } 2417 catch (Exception e) {} 2418 } 2419 2420 2426 private static class InvitationsMonitor implements ConnectionListener { 2427 private static Map monitors = new WeakHashMap(); 2430 2431 private List invitationsListeners = new ArrayList(); 2432 private XMPPConnection connection; 2433 private PacketFilter invitationFilter; 2434 private PacketListener invitationPacketListener; 2435 2436 2442 public static InvitationsMonitor getInvitationsMonitor(XMPPConnection conn) { 2443 synchronized (monitors) { 2444 if (!monitors.containsKey(conn)) { 2445 monitors.put(conn, new WeakReference (new InvitationsMonitor(conn))); 2449 } 2450 return (InvitationsMonitor) ((WeakReference ) monitors.get(conn)).get(); 2452 } 2453 } 2454 2455 2461 private InvitationsMonitor(XMPPConnection connection) { 2462 this.connection = connection; 2463 } 2464 2465 2474 public void addInvitationListener(InvitationListener listener) { 2475 synchronized (invitationsListeners) { 2476 if (invitationsListeners.size() == 0) { 2479 init(); 2480 } 2481 if (!invitationsListeners.contains(listener)) { 2482 invitationsListeners.add(listener); 2483 } 2484 } 2485 } 2486 2487 2497 public void removeInvitationListener(InvitationListener listener) { 2498 synchronized (invitationsListeners) { 2499 if (invitationsListeners.contains(listener)) { 2500 invitationsListeners.remove(listener); 2501 } 2502 if (invitationsListeners.size() == 0) { 2505 cancel(); 2506 } 2507 } 2508 } 2509 2510 2513 private void fireInvitationListeners(String room, String inviter, String reason, String password, 2514 Message message) { 2515 InvitationListener[] listeners = null; 2516 synchronized (invitationsListeners) { 2517 listeners = new InvitationListener[invitationsListeners.size()]; 2518 invitationsListeners.toArray(listeners); 2519 } 2520 for (int i = 0; i < listeners.length; i++) { 2521 listeners[i].invitationReceived(connection, room, inviter, reason, password, message); 2522 } 2523 } 2524 2525 public void connectionClosed() { 2526 cancel(); 2527 } 2528 2529 public void connectionClosedOnError(Exception e) { 2530 cancel(); 2531 } 2532 2533 2539 private void init() { 2540 invitationFilter = 2543 new PacketExtensionFilter("x", "http://jabber.org/protocol/muc#user"); 2544 invitationPacketListener = new PacketListener() { 2545 public void processPacket(Packet packet) { 2546 MUCUser mucUser = 2548 (MUCUser) packet.getExtension("x", "http://jabber.org/protocol/muc#user"); 2549 if (mucUser.getInvite() != null) { 2551 fireInvitationListeners(packet.getFrom(), mucUser.getInvite().getFrom(), 2553 mucUser.getInvite().getReason(), mucUser.getPassword(), (Message) packet); 2554 } 2555 }; 2556 }; 2557 connection.addPacketListener(invitationPacketListener, invitationFilter); 2558 connection.addConnectionListener(this); 2561 } 2562 2563 2566 private void cancel() { 2567 connection.removePacketListener(invitationPacketListener); 2568 connection.removeConnectionListener(this); 2569 } 2570 2571 } 2572} 2573 | Popular Tags |