1 11 12 package org.jivesoftware.messenger.muc.spi; 13 14 import java.util.*; 15 import java.util.concurrent.ConcurrentHashMap ; 16 import java.util.concurrent.CopyOnWriteArrayList ; 17 import java.util.concurrent.locks.ReadWriteLock ; 18 import java.util.concurrent.locks.ReentrantReadWriteLock ; 19 20 import org.jivesoftware.database.SequenceManager; 21 import org.jivesoftware.messenger.muc.*; 22 import org.jivesoftware.util.*; 23 import org.jivesoftware.messenger.*; 24 import org.jivesoftware.messenger.auth.UnauthorizedException; 25 import org.jivesoftware.messenger.user.UserAlreadyExistsException; 26 import org.jivesoftware.messenger.user.UserNotFoundException; 27 import org.xmpp.packet.*; 28 import org.dom4j.Element; 29 30 37 public class MUCRoomImpl implements MUCRoom { 38 39 42 private MultiUserChatServer server; 43 44 47 private Map <String ,MUCRole> occupants = new ConcurrentHashMap <String , MUCRole>(); 48 49 52 private Map <String , List <MUCRole>> occupantsByBareJID = new ConcurrentHashMap <String , List <MUCRole>>(); 53 54 57 private Map <JID, MUCRole> occupantsByFullJID = new ConcurrentHashMap <JID, MUCRole>(); 58 59 62 private String name; 63 64 67 ReadWriteLock lock = new ReentrantReadWriteLock (); 68 69 72 private MUCRole role; 73 74 77 private PacketRouter router; 78 79 82 long startTime; 83 84 87 long endTime; 88 89 95 boolean isDestroyed = false; 96 97 100 private MUCRoomHistory roomHistory; 101 102 105 private long lockedTime; 106 107 110 List <String > owners = new CopyOnWriteArrayList <String >(); 111 112 115 List <String > admins = new CopyOnWriteArrayList <String >(); 116 117 120 private Map <String , String > members = new ConcurrentHashMap <String ,String >(); 121 122 125 private List <String > outcasts = new CopyOnWriteArrayList <String >(); 126 127 130 private String naturalLanguageName; 131 132 136 private String description; 137 138 141 private boolean canOccupantsChangeSubject = false; 142 143 147 private int maxUsers = 30; 148 149 153 private List <String > rolesToBroadcastPresence = new ArrayList <String >(); 154 155 159 private boolean publicRoom = true; 160 161 165 private boolean persistent = false; 166 167 171 private boolean moderated = false; 172 173 178 private boolean membersOnly = false; 179 180 184 private boolean canOccupantsInvite = false; 185 186 189 private String password = null; 190 191 195 private boolean canAnyoneDiscoverJID = false; 196 197 201 private boolean logEnabled = false; 202 203 207 private boolean loginRestrictedToNickname = false; 208 209 213 private boolean canChangeNickname = true; 214 215 219 private boolean registrationEnabled = true; 220 221 224 private IQOwnerHandler iqOwnerHandler; 225 226 229 private IQAdminHandler iqAdminHandler; 230 231 236 private String subject = ""; 237 238 242 private long roomID = -1; 243 244 247 private Date creationDate; 248 249 252 private Date modificationDate; 253 254 258 private Date emptyDate; 259 260 263 private boolean savedToDB = false; 264 265 272 MUCRoomImpl(MultiUserChatServer chatserver, String roomname, PacketRouter packetRouter) { 273 this.server = chatserver; 274 this.name = roomname; 275 this.naturalLanguageName = roomname; 276 this.description = roomname; 277 this.router = packetRouter; 278 this.startTime = System.currentTimeMillis(); 279 this.creationDate = new Date(startTime); 280 this.modificationDate = new Date(startTime); 281 this.emptyDate = new Date(startTime); 282 roomHistory = new MUCRoomHistory(this, new HistoryStrategy(server.getHistoryStrategy())); 284 role = new RoomRole(this); 285 this.iqOwnerHandler = new IQOwnerHandler(this, packetRouter); 286 this.iqAdminHandler = new IQAdminHandler(this, packetRouter); 287 this.lockedTime = startTime; 289 rolesToBroadcastPresence.add("moderator"); 291 rolesToBroadcastPresence.add("participant"); 292 rolesToBroadcastPresence.add("visitor"); 293 } 294 295 public String getName() { 296 return name; 297 } 298 299 public long getID() { 300 if (isPersistent() || isLogEnabled()) { 301 if (roomID == -1) { 302 roomID = SequenceManager.nextID(JiveConstants.MUC_ROOM); 303 } 304 } 305 return roomID; 306 } 307 308 public void setID(long roomID) { 309 this.roomID = roomID; 310 } 311 312 public Date getCreationDate() { 313 return creationDate; 314 } 315 316 public void setCreationDate(Date creationDate) { 317 this.creationDate = creationDate; 318 } 319 320 public Date getModificationDate() { 321 return modificationDate; 322 } 323 324 public void setModificationDate(Date modificationDate) { 325 this.modificationDate = modificationDate; 326 } 327 328 public void setEmptyDate(Date emptyDate) { 329 if (this.emptyDate == emptyDate) { 331 return; 332 } 333 this.emptyDate = emptyDate; 334 MUCPersistenceManager.updateRoomEmptyDate(this); 335 } 336 337 public Date getEmptyDate() { 338 return this.emptyDate; 339 } 340 341 public MUCRole getRole() { 342 return role; 343 } 344 345 public MUCRole getOccupant(String nickname) throws UserNotFoundException { 346 if (nickname == null) { 347 throw new UserNotFoundException(); 348 } 349 MUCRole role = occupants.get(nickname.toLowerCase()); 350 if (role != null) { 351 return role; 352 } 353 throw new UserNotFoundException(); 354 } 355 356 public List <MUCRole> getOccupantsByBareJID(String jid) throws UserNotFoundException { 357 List <MUCRole> roles = occupantsByBareJID.get(jid); 358 if (roles != null && !roles.isEmpty()) { 359 return Collections.unmodifiableList(roles); 360 } 361 throw new UserNotFoundException(); 362 } 363 364 public MUCRole getOccupantByFullJID(String jid) throws UserNotFoundException { 365 MUCRole role = occupantsByFullJID.get(jid); 366 if (role != null) { 367 return role; 368 } 369 throw new UserNotFoundException(); 370 } 371 372 public Collection<MUCRole> getOccupants() { 373 return Collections.unmodifiableCollection(occupants.values()); 374 } 375 376 public int getOccupantsCount() { 377 return occupants.size(); 378 } 379 380 public boolean hasOccupant(String nickname) { 381 return occupants.containsKey(nickname.toLowerCase()); 382 } 383 384 public String getReservedNickname(String bareJID) { 385 String answer = members.get(bareJID); 386 if (answer == null || answer.trim().length() == 0) { 387 return null; 388 } 389 return answer; 390 } 391 392 public MUCRole.Affiliation getAffiliation(String bareJID) { 393 if (owners.contains(bareJID)) { 394 return MUCRole.Affiliation.owner; 395 } 396 else if (admins.contains(bareJID)) { 397 return MUCRole.Affiliation.admin; 398 } 399 else if (members.containsKey(bareJID)) { 400 return MUCRole.Affiliation.member; 401 } 402 else if (outcasts.contains(bareJID)) { 403 return MUCRole.Affiliation.outcast; 404 } 405 return MUCRole.Affiliation.none; 406 } 407 408 public MUCRole joinRoom(String nickname, String password, HistoryRequest historyRequest, 409 MUCUser user, Presence presence) throws UnauthorizedException, 410 UserAlreadyExistsException, RoomLockedException, ForbiddenException, 411 RegistrationRequiredException, ConflictException, ServiceUnavailableException, 412 NotAcceptableException { 413 MUCRoleImpl joinRole = null; 414 lock.writeLock().lock(); 415 try { 416 if (isDestroyed || (getMaxUsers() > 0 && getOccupantsCount() >= getMaxUsers())) { 418 throw new ServiceUnavailableException(); 419 } 420 boolean isOwner = owners.contains(user.getAddress().toBareJID()); 421 if (isLocked()) { 423 if (!isOwner) { 424 throw new RoomLockedException(); 425 } 426 } 427 if (occupants.containsKey(nickname.toLowerCase())) { 429 throw new UserAlreadyExistsException(); 430 } 431 if (isPasswordProtected()) { 434 if (password == null || !password.equals(getPassword())) { 435 throw new UnauthorizedException(); 436 } 437 } 438 if (members.containsValue(nickname)) { 441 if (!nickname.equals(members.get(user.getAddress().toBareJID()))) { 442 throw new ConflictException(); 443 } 444 } 445 if (isLoginRestrictedToNickname()) { 446 String reservedNickname = members.get(user.getAddress().toBareJID()); 447 if (reservedNickname != null && !nickname.equals(reservedNickname)) { 448 throw new NotAcceptableException(); 449 } 450 } 451 452 MUCRole.Role role; 454 MUCRole.Affiliation affiliation; 455 if (isOwner) { 456 role = MUCRole.Role.moderator; 458 affiliation = MUCRole.Affiliation.owner; 459 } 460 else if (server.getSysadmins().contains(user.getAddress().toBareJID())) { 461 role = MUCRole.Role.moderator; 464 affiliation = MUCRole.Affiliation.owner; 465 } 466 else if (admins.contains(user.getAddress().toBareJID())) { 467 role = MUCRole.Role.moderator; 469 affiliation = MUCRole.Affiliation.admin; 470 } 471 else if (members.containsKey(user.getAddress().toBareJID())) { 472 role = MUCRole.Role.participant; 474 affiliation = MUCRole.Affiliation.member; 475 } 476 else if (outcasts.contains(user.getAddress().toBareJID())) { 477 throw new ForbiddenException(); 479 } 480 else { 481 if (isMembersOnly()) { 483 throw new RegistrationRequiredException(); 486 } 487 role = (isModerated() ? MUCRole.Role.visitor : MUCRole.Role.participant); 488 affiliation = MUCRole.Affiliation.none; 489 } 490 joinRole = 492 new MUCRoleImpl(server, this, nickname, role, affiliation, (MUCUserImpl) user, 493 presence, router); 494 occupants.put(nickname.toLowerCase(), joinRole); 496 List <MUCRole> list = occupantsByBareJID.get(user.getAddress().toBareJID()); 498 if (list == null) { 499 list = new ArrayList <MUCRole>(); 500 occupantsByBareJID.put(user.getAddress().toBareJID(), list); 501 } 502 list.add(joinRole); 503 occupantsByFullJID.put(user.getAddress(), joinRole); 504 } 505 finally { 506 lock.writeLock().unlock(); 507 } 508 sendInitialPresences(joinRole); 510 boolean isRoomNew = isLocked() && creationDate.getTime() == lockedTime; 513 try { 514 Presence joinPresence = joinRole.getPresence().createCopy(); 516 if (isRoomNew) { 517 Element frag = joinPresence.getChildElement( 518 "x", "http://jabber.org/protocol/muc#user"); 519 frag.addElement("status").addAttribute("code", "201"); 520 } 521 broadcastPresence(joinPresence); 522 } 523 catch (Exception e) { 524 Log.error(LocaleUtils.getLocalizedString("admin.error"), e); 525 } 526 if (isRoomNew) { 529 Message message = new Message(); 530 message.setType(Message.Type.groupchat); 531 message.setBody(LocaleUtils.getLocalizedString("muc.new")); 532 message.setFrom(role.getRoleAddress()); 533 joinRole.send(message); 534 } 535 else if (isLocked()) { 536 Message message = new Message(); 538 message.setType(Message.Type.groupchat); 539 message.setBody(LocaleUtils.getLocalizedString("muc.locked")); 540 message.setFrom(role.getRoleAddress()); 541 joinRole.send(message); 542 } 543 else if (canAnyoneDiscoverJID()) { 544 Message message = new Message(); 547 message.setType(Message.Type.groupchat); 548 message.setBody(LocaleUtils.getLocalizedString("muc.warnnonanonymous")); 549 message.setFrom(role.getRoleAddress()); 550 Element frag = message.addChildElement("x", "http://jabber.org/protocol/muc#user"); 551 frag.addElement("status").addAttribute("code", "100"); 552 joinRole.send(message); 553 } 554 if (historyRequest == null) { 555 Iterator history = roomHistory.getMessageHistory(); 556 while (history.hasNext()) { 557 joinRole.send((Message) history.next()); 558 } 559 } 560 else { 561 historyRequest.sendHistory(joinRole, roomHistory); 562 } 563 setEmptyDate(null); 565 return joinRole; 566 } 567 568 573 private void sendInitialPresences(MUCRoleImpl joinRole) { 574 for (MUCRole occupant : occupants.values()) { 575 if (occupant == joinRole) { 576 continue; 577 } 578 Presence occupantPresence = occupant.getPresence().createCopy(); 579 if (hasToCheckRoleToBroadcastPresence()) { 581 Element frag = occupantPresence.getChildElement("x", 582 "http://jabber.org/protocol/muc#user"); 583 if (!canBroadcastPresence(frag.element("item").attributeValue("role"))) { 585 continue; 586 } 587 } 588 if (!canAnyoneDiscoverJID() && MUCRole.Role.moderator != joinRole.getRole()) { 591 Element frag = occupantPresence.getChildElement("x", 592 "http://jabber.org/protocol/muc#user"); 593 frag.element("item").addAttribute("jid", null); 594 } 595 joinRole.send(occupantPresence); 596 } 597 } 598 599 public void leaveRoom(String nickname) throws UserNotFoundException { 600 MUCRole leaveRole = null; 601 lock.writeLock().lock(); 602 try { 603 leaveRole = occupants.remove(nickname.toLowerCase()); 604 if (leaveRole == null) { 605 throw new UserNotFoundException(); 606 } 607 removeOccupantRole(leaveRole); 609 610 617 if (occupants.isEmpty() && !isPersistent()) { 620 endTime = System.currentTimeMillis(); 621 server.removeChatRoom(name); 622 } 623 if (occupants.isEmpty()) { 624 setEmptyDate(new Date()); 626 } 627 } 628 finally { 629 lock.writeLock().unlock(); 630 } 631 632 try { 633 Presence presence = leaveRole.getPresence().createCopy(); 634 presence.setType(Presence.Type.unavailable); 635 presence.setStatus(null); 636 leaveRole.send(presence); 638 broadcastPresence(presence); 640 } 641 catch (Exception e) { 642 Log.error(e); 643 } 644 } 645 646 652 private void removeOccupantRole(MUCRole leaveRole) { 653 occupants.remove(leaveRole.getNickname().toLowerCase()); 654 655 MUCUser user = leaveRole.getChatUser(); 656 user.removeRole(getName()); 658 List list = occupantsByBareJID.get(user.getAddress().toBareJID()); 660 if (list != null) { 661 list.remove(leaveRole); 662 if (list.isEmpty()) { 663 occupantsByBareJID.remove(user.getAddress().toBareJID()); 664 } 665 } 666 occupantsByFullJID.remove(user.getAddress().toString()); 667 } 668 669 public void destroyRoom(String alternateJID, String reason) { 670 MUCRole leaveRole = null; 671 Collection<MUCRole> removedRoles = new ArrayList <MUCRole>(); 672 lock.writeLock().lock(); 673 try { 674 for (String nickname: occupants.keySet()) { 676 leaveRole = occupants.remove(nickname); 677 678 if (leaveRole != null) { 679 removedRoles.add(leaveRole); 682 removeOccupantRole(leaveRole); 683 } 684 } 685 endTime = System.currentTimeMillis(); 686 server.removeChatRoom(name); 688 isDestroyed = true; 690 } 691 finally { 692 lock.writeLock().unlock(); 693 } 694 for (MUCRole removedRole : removedRoles) { 696 try { 697 Presence presence = createPresence(Presence.Type.unavailable); 699 presence.setFrom(removedRole.getRoleAddress()); 700 701 Element fragment = presence.addChildElement("x", 703 "http://jabber.org/protocol/muc#user"); 704 Element item = fragment.addElement("item"); 705 item.addAttribute("affiliation", "none"); 706 item.addAttribute("role", "none"); 707 if (alternateJID != null && alternateJID.length() > 0) { 708 fragment.addElement("destroy").addAttribute("jid", alternateJID); 709 } 710 if (reason != null && reason.length() > 0) { 711 Element destroy = fragment.element("destroy"); 712 if (destroy == null) { 713 destroy = fragment.addElement("destroy"); 714 } 715 destroy.addElement("reason").setText(reason); 716 } 717 removedRole.send(presence); 718 } 719 catch (Exception e) { 720 Log.error(e); 721 } 722 } 723 MUCPersistenceManager.deleteFromDB(this); 725 } 726 727 public Presence createPresence(Presence.Type presenceType) throws UnauthorizedException { 728 Presence presence = new Presence(); 729 presence.setType(presenceType); 730 presence.setFrom(role.getRoleAddress()); 731 return presence; 732 } 733 734 public void serverBroadcast(String msg) { 735 Message message = new Message(); 736 message.setType(Message.Type.groupchat); 737 message.setBody(msg); 738 message.setFrom(role.getRoleAddress()); 739 roomHistory.addMessage(message); 740 broadcast(message); 741 } 742 743 public void sendPublicMessage(Message message, MUCRole senderRole) throws ForbiddenException { 744 if (isModerated() && senderRole.getRole().compareTo(MUCRole.Role.participant) > 0) { 746 throw new ForbiddenException(); 747 } 748 message.setFrom(senderRole.getRoleAddress()); 750 send(message); 751 } 752 753 public void sendPrivateMessage(Message message, MUCRole senderRole) throws NotFoundException { 754 String resource = message.getTo().getResource(); 755 MUCRole occupant = occupants.get(resource.toLowerCase()); 756 if (occupant != null) { 757 message.setFrom(senderRole.getRoleAddress()); 758 occupant.send(message); 759 } 760 else { 761 throw new NotFoundException(); 762 } 763 } 764 765 public void send(Packet packet) { 766 if (packet instanceof Message) { 767 roomHistory.addMessage((Message)packet); 768 broadcast((Message)packet); 769 } 770 else if (packet instanceof Presence) { 771 broadcastPresence((Presence)packet); 772 } 773 else if (packet instanceof IQ) { 774 IQ reply = IQ.createResultIQ((IQ) packet); 775 reply.setChildElement(((IQ) packet).getChildElement()); 776 reply.setError(PacketError.Condition.bad_request); 777 router.route(reply); 778 } 779 } 780 781 789 private void broadcastPresence(Presence presence) { 790 if (presence == null) { 791 return; 792 } 793 Element frag = null; 794 String jid = null; 795 if (hasToCheckRoleToBroadcastPresence()) { 796 frag = presence.getChildElement("x", "http://jabber.org/protocol/muc#user"); 797 if (!canBroadcastPresence(frag.element("item").attributeValue("role"))) { 799 try { 801 MUCRole occupant = getOccupant(presence.getFrom().getResource()); 802 occupant.send(presence); 803 } 804 catch (UserNotFoundException e) { 805 } 807 return; 808 } 809 } 810 811 if (!canAnyoneDiscoverJID()) { 814 if (frag == null) { 815 frag = presence.getChildElement("x", "http://jabber.org/protocol/muc#user"); 816 } 817 jid = frag.element("item").attributeValue("jid"); 818 } 819 for (MUCRole occupant : occupants.values()) { 820 if (!canAnyoneDiscoverJID()) { 823 if (MUCRole.Role.moderator == occupant.getRole()) { 824 frag.element("item").addAttribute("jid", jid); 825 } 826 else { 827 frag.element("item").addAttribute("jid", null); 828 } 829 } 830 occupant.send(presence); 831 } 832 } 833 834 private void broadcast(Message message) { 835 for (MUCRole occupant : occupants.values()) { 836 occupant.send(message); 837 } 838 if (isLogEnabled()) { 839 MUCRole senderRole = null; 840 JID senderAddress = null; 841 if (message.getTo() != null && message.getTo().getResource() != null) { 842 senderRole = occupants.get(message.getTo().getResource()); 843 } 844 if (senderRole == null) { 845 senderAddress = getRole().getRoleAddress(); 847 } 848 else { 849 senderAddress = senderRole.getChatUser().getAddress(); 851 } 852 server.logConversation(this, message, senderAddress); 854 } 855 } 856 857 861 private class RoomRole implements MUCRole { 862 863 private MUCRoom room; 864 865 private RoomRole(MUCRoom room) { 866 this.room = room; 867 } 868 869 public Presence getPresence() { 870 return null; 871 } 872 873 public Element getExtendedPresenceInformation() { 874 return null; 875 } 876 877 public void setPresence(Presence presence) { 878 } 879 880 public void setRole(MUCRole.Role newRole) { 881 } 882 883 public MUCRole.Role getRole() { 884 return MUCRole.Role.moderator; 885 } 886 887 public void setAffiliation(MUCRole.Affiliation newAffiliation) { 888 } 889 890 public MUCRole.Affiliation getAffiliation() { 891 return MUCRole.Affiliation.owner; 892 } 893 894 public String getNickname() { 895 return null; 896 } 897 898 public MUCUser getChatUser() { 899 return null; 900 } 901 902 public MUCRoom getChatRoom() { 903 return room; 904 } 905 906 private JID crJID = null; 907 908 public JID getRoleAddress() { 909 if (crJID == null) { 910 crJID = new JID(room.getName(), server.getServiceDomain(), ""); 911 } 912 return crJID; 913 } 914 915 public void send(Packet packet) { 916 room.send(packet); 917 } 918 919 public void changeNickname(String nickname) { 920 } 921 } 922 923 public long getChatLength() { 924 return endTime - startTime; 925 } 926 927 940 private List <Presence> changeOccupantAffiliation(String bareJID, MUCRole.Affiliation newAffiliation, MUCRole.Role newRole) 941 throws NotAllowedException { 942 List <Presence> presences = new ArrayList <Presence>(); 943 List <MUCRole> roles = occupantsByBareJID.get(bareJID); 945 if (roles == null) { 946 return presences; 947 } 948 for (MUCRole role : roles) { 950 role.setAffiliation(newAffiliation); 952 role.setRole(newRole); 953 presences.add(role.getPresence().createCopy()); 955 } 956 return presences; 958 } 959 960 969 private Presence changeOccupantRole(JID jid, MUCRole.Role newRole) throws NotAllowedException { 970 MUCRole role = occupantsByFullJID.get(jid); 972 if (role != null) { 973 role.setRole(newRole); 975 return role.getPresence().createCopy(); 977 } 978 return null; 979 } 980 981 public void addFirstOwner(String bareJID) { 982 owners.add(bareJID); 983 } 984 985 public List <Presence> addOwner(String bareJID, MUCRole sendRole) throws ForbiddenException { 986 MUCRole.Affiliation oldAffiliation = MUCRole.Affiliation.none; 987 if (MUCRole.Affiliation.owner != sendRole.getAffiliation()) { 988 throw new ForbiddenException(); 989 } 990 owners.add(bareJID); 991 if (removeAdmin(bareJID)) { 993 oldAffiliation = MUCRole.Affiliation.admin; 994 } 995 else if (removeMember(bareJID)) { 996 oldAffiliation = MUCRole.Affiliation.member; 997 } 998 else if (removeOutcast(bareJID)) { 999 oldAffiliation = MUCRole.Affiliation.outcast; 1000 } 1001 MUCPersistenceManager.saveAffiliationToDB( 1003 this, 1004 bareJID, 1005 null, 1006 MUCRole.Affiliation.owner, 1007 oldAffiliation); 1008 try { 1010 return changeOccupantAffiliation(bareJID, MUCRole.Affiliation.owner, 1011 MUCRole.Role.moderator); 1012 } 1013 catch (NotAllowedException e) { 1014 return null; 1016 } 1017 } 1018 1019 private boolean removeOwner(String bareJID) { 1020 return owners.remove(bareJID); 1021 } 1022 1023 public List <Presence> addAdmin(String bareJID, MUCRole sendRole) throws ForbiddenException, 1024 ConflictException { 1025 MUCRole.Affiliation oldAffiliation = MUCRole.Affiliation.none; 1026 if (MUCRole.Affiliation.owner != sendRole.getAffiliation()) { 1027 throw new ForbiddenException(); 1028 } 1029 if (owners.contains(bareJID) && owners.size() == 1) { 1031 throw new ConflictException(); 1032 } 1033 admins.add(bareJID); 1034 if (removeOwner(bareJID)) { 1036 oldAffiliation = MUCRole.Affiliation.owner; 1037 } 1038 else if (removeMember(bareJID)) { 1039 oldAffiliation = MUCRole.Affiliation.member; 1040 } 1041 else if (removeOutcast(bareJID)) { 1042 oldAffiliation = MUCRole.Affiliation.outcast; 1043 } 1044 MUCPersistenceManager.saveAffiliationToDB( 1046 this, 1047 bareJID, 1048 null, 1049 MUCRole.Affiliation.admin, 1050 oldAffiliation); 1051 try { 1053 return changeOccupantAffiliation(bareJID, MUCRole.Affiliation.admin, 1054 MUCRole.Role.moderator); 1055 } 1056 catch (NotAllowedException e) { 1057 return null; 1059 } 1060 } 1061 1062 private boolean removeAdmin(String bareJID) { 1063 return admins.remove(bareJID); 1064 } 1065 1066 public List <Presence> addMember(String bareJID, String nickname, MUCRole sendRole) 1067 throws ForbiddenException, ConflictException { 1068 MUCRole.Affiliation oldAffiliation = (members.containsKey(bareJID) ? 1069 MUCRole.Affiliation.member : MUCRole.Affiliation.none); 1070 if (isMembersOnly()) { 1071 if (!canOccupantsInvite()) { 1072 if (MUCRole.Affiliation.admin != sendRole.getAffiliation() 1073 && MUCRole.Affiliation.owner != sendRole.getAffiliation()) { 1074 throw new ForbiddenException(); 1075 } 1076 } 1077 } 1078 else { 1079 if (MUCRole.Affiliation.admin != sendRole.getAffiliation() 1080 && MUCRole.Affiliation.owner != sendRole.getAffiliation()) { 1081 throw new ForbiddenException(); 1082 } 1083 } 1084 if (nickname != null && nickname.trim().length() > 0 && members.containsValue(nickname)) { 1086 if (!nickname.equals(members.get(bareJID))) { 1087 throw new ConflictException(); 1088 } 1089 } 1090 if (owners.contains(bareJID) && owners.size() == 1) { 1092 throw new ConflictException(); 1093 } 1094 members.put(bareJID, (nickname == null ? "" : nickname)); 1097 if (removeOwner(bareJID)) { 1099 oldAffiliation = MUCRole.Affiliation.owner; 1100 } 1101 else if (removeAdmin(bareJID)) { 1102 oldAffiliation = MUCRole.Affiliation.admin; 1103 } 1104 else if (removeOutcast(bareJID)) { 1105 oldAffiliation = MUCRole.Affiliation.outcast; 1106 } 1107 MUCPersistenceManager.saveAffiliationToDB( 1109 this, 1110 bareJID, 1111 nickname, 1112 MUCRole.Affiliation.member, 1113 oldAffiliation); 1114 try { 1116 return changeOccupantAffiliation(bareJID, MUCRole.Affiliation.member, 1117 MUCRole.Role.participant); 1118 } 1119 catch (NotAllowedException e) { 1120 return null; 1122 } 1123 } 1124 1125 private boolean removeMember(String bareJID) { 1126 boolean answer = members.containsKey(bareJID); 1127 members.remove(bareJID); 1128 return answer; 1129 } 1130 1131 public List <Presence> addOutcast(String bareJID, String reason, MUCRole senderRole) 1132 throws NotAllowedException, ForbiddenException, ConflictException { 1133 MUCRole.Affiliation oldAffiliation = MUCRole.Affiliation.none; 1134 if (MUCRole.Affiliation.admin != senderRole.getAffiliation() 1135 && MUCRole.Affiliation.owner != senderRole.getAffiliation()) { 1136 throw new ForbiddenException(); 1137 } 1138 if (owners.contains(bareJID) && owners.size() == 1) { 1140 throw new ConflictException(); 1141 } 1142 JID actorJID = null; 1144 if (senderRole.getChatUser() != null) { 1146 actorJID = senderRole.getChatUser().getAddress(); 1147 } 1148 List <Presence> updatedPresences = changeOccupantAffiliation( 1149 bareJID, 1150 MUCRole.Affiliation.outcast, 1151 MUCRole.Role.none); 1152 Element frag; 1153 for (Presence presence : updatedPresences) { 1156 frag = presence.getChildElement("x", "http://jabber.org/protocol/muc#user"); 1157 frag.addElement("status").addAttribute("code", "301"); 1159 if (reason != null && reason.trim().length() > 0) { 1161 frag.element("item").addElement("reason").setText(reason); 1162 } 1163 1164 kickPresence(presence, actorJID); 1168 } 1169 outcasts.add(bareJID); 1171 if (removeOwner(bareJID)) { 1173 oldAffiliation = MUCRole.Affiliation.owner; 1174 } 1175 else if (removeAdmin(bareJID)) { 1176 oldAffiliation = MUCRole.Affiliation.admin; 1177 } 1178 else if (removeMember(bareJID)) { 1179 oldAffiliation = MUCRole.Affiliation.member; 1180 } 1181 MUCPersistenceManager.saveAffiliationToDB( 1183 this, 1184 bareJID, 1185 null, 1186 MUCRole.Affiliation.outcast, 1187 oldAffiliation); 1188 return updatedPresences; 1189 } 1190 1191 private boolean removeOutcast(String bareJID) { 1192 return outcasts.remove(bareJID); 1193 } 1194 1195 public List <Presence> addNone(String bareJID, MUCRole senderRole) throws ForbiddenException, 1196 ConflictException { 1197 MUCRole.Affiliation oldAffiliation = MUCRole.Affiliation.none; 1198 if (MUCRole.Affiliation.admin != senderRole.getAffiliation() 1199 && MUCRole.Affiliation.owner != senderRole.getAffiliation()) { 1200 throw new ForbiddenException(); 1201 } 1202 if (owners.contains(bareJID) && owners.size() == 1) { 1204 throw new ConflictException(); 1205 } 1206 List <Presence> updatedPresences = null; 1207 boolean wasMember = members.containsKey(bareJID) || admins.contains(bareJID) || 1208 owners.contains(bareJID); 1209 if (removeOwner(bareJID)) { 1211 oldAffiliation = MUCRole.Affiliation.owner; 1212 } 1213 else if (removeAdmin(bareJID)) { 1214 oldAffiliation = MUCRole.Affiliation.admin; 1215 } 1216 else if (removeMember(bareJID)) { 1217 oldAffiliation = MUCRole.Affiliation.member; 1218 } 1219 else if (removeOutcast(bareJID)) { 1220 oldAffiliation = MUCRole.Affiliation.outcast; 1221 } 1222 MUCPersistenceManager.removeAffiliationFromDB(this, bareJID, oldAffiliation); 1224 1225 try { 1227 MUCRole.Role newRole; 1228 if (isMembersOnly() && wasMember) { 1229 newRole = MUCRole.Role.none; 1230 } 1231 else { 1232 newRole = isModerated() ? MUCRole.Role.visitor : MUCRole.Role.participant; 1233 } 1234 updatedPresences = changeOccupantAffiliation(bareJID, MUCRole.Affiliation.none, newRole); 1235 if (isMembersOnly() && wasMember) { 1236 Element frag; 1240 for (Presence presence : updatedPresences) { 1242 presence.setType(Presence.Type.unavailable); 1244 presence.setStatus(null); 1245 frag = presence.getChildElement("x", "http://jabber.org/protocol/muc#user"); 1246 frag.addElement("status").addAttribute("code", "321"); 1249 1250 MUCUser senderUser = senderRole.getChatUser(); 1255 JID actorJID = (senderUser == null ? null : senderUser.getAddress()); 1256 kickPresence(presence, actorJID); 1257 } 1258 } 1259 } 1260 catch (NotAllowedException e) { 1261 } 1263 return updatedPresences; 1264 } 1265 1266 public boolean isLocked() { 1267 return lockedTime > 0; 1268 } 1269 1270 public boolean isManuallyLocked() { 1271 return lockedTime > 0 && creationDate.getTime() != lockedTime; 1272 } 1273 1274 public void nicknameChanged(String oldNick, String newNick) { 1275 MUCRole occupant = occupants.get(oldNick.toLowerCase()); 1277 if (occupant != null) { 1279 occupants.put(newNick.toLowerCase(), occupant); 1280 occupants.remove(oldNick.toLowerCase()); 1282 } 1283 } 1284 1285 public void changeSubject(Message packet, MUCRole role) throws ForbiddenException { 1286 if ((canOccupantsChangeSubject() && role.getRole().compareTo(MUCRole.Role.visitor) < 0) || 1287 MUCRole.Role.moderator == role.getRole()) { 1288 if (packet.getSubject().equals(subject)) { 1290 return; 1291 } 1292 subject = packet.getSubject(); 1294 MUCPersistenceManager.updateRoomSubject(this); 1295 packet.setFrom(role.getRoleAddress()); 1297 send(packet); 1298 } 1299 else { 1300 throw new ForbiddenException(); 1301 } 1302 } 1303 1304 public String getSubject() { 1305 return subject; 1306 } 1307 1308 public void setSubject(String subject) { 1309 this.subject = subject; 1310 } 1311 1312 public void sendInvitation(JID to, String reason, MUCRole senderRole, List <Element> extensions) 1313 throws ForbiddenException { 1314 if (!isMembersOnly() || canOccupantsInvite() 1315 || MUCRole.Affiliation.admin == senderRole.getAffiliation() 1316 || MUCRole.Affiliation.owner == senderRole.getAffiliation()) { 1317 Message message = new Message(); 1320 message.setFrom(role.getRoleAddress()); 1321 message.setTo(to); 1322 if (extensions != null) { 1324 for(Element element : extensions) { 1325 element.setParent(null); 1326 message.getElement().add(element); 1327 } 1328 } 1329 Element frag = message.addChildElement("x", "http://jabber.org/protocol/muc#user"); 1330 if (senderRole.getChatUser() != null) { 1332 frag.addElement("invite").addAttribute("from", senderRole.getChatUser().getAddress() 1333 .toBareJID()); 1334 } 1335 if (reason != null && reason.length() > 0) { 1336 Element invite = frag.element("invite"); 1337 if (invite == null) { 1338 invite.addElement("invite"); 1339 } 1340 invite.addElement("reason").setText(reason); 1341 } 1342 if (isPasswordProtected()) { 1343 frag.addElement("password").setText(getPassword()); 1344 } 1345 1346 frag = message.addChildElement("x", "jabber:x:conference"); 1348 frag.addAttribute("jid", role.getRoleAddress().toBareJID()); 1349 1350 router.route(message); 1352 } 1353 else { 1354 throw new ForbiddenException(); 1355 } 1356 } 1357 1358 public void sendInvitationRejection(JID to, String reason, JID sender) { 1359 Message message = new Message(); 1360 message.setFrom(role.getRoleAddress()); 1361 message.setTo(to); 1362 Element frag = message.addChildElement("x", "http://jabber.org/protocol/muc#user"); 1363 frag.addElement("decline").addAttribute("from", sender.toBareJID()); 1364 if (reason != null && reason.length() > 0) { 1365 frag.element("decline").addElement("reason").setText(reason); 1366 } 1367 1368 router.route(message); 1370 } 1371 1372 public IQOwnerHandler getIQOwnerHandler() { 1373 return iqOwnerHandler; 1374 } 1375 1376 public IQAdminHandler getIQAdminHandler() { 1377 return iqAdminHandler; 1378 } 1379 1380 public MUCRoomHistory getRoomHistory() { 1381 return roomHistory; 1382 } 1383 1384 public Collection<String > getOwners() { 1385 return Collections.unmodifiableList(owners); 1386 } 1387 1388 public Collection<String > getAdmins() { 1389 return Collections.unmodifiableList(admins); 1390 } 1391 1392 public Collection<String > getMembers() { 1393 return Collections.unmodifiableMap(members).keySet(); 1394 } 1395 1396 public Collection<String > getOutcasts() { 1397 return Collections.unmodifiableList(outcasts); 1398 } 1399 1400 public Collection<MUCRole> getModerators() { 1401 List <MUCRole> moderators = new ArrayList <MUCRole>(); 1402 for (MUCRole role : occupants.values()) { 1403 if (MUCRole.Role.moderator == role.getRole()) { 1404 moderators.add(role); 1405 } 1406 } 1407 return moderators; 1408 } 1409 1410 public Collection<MUCRole> getParticipants() { 1411 List <MUCRole> participants = new ArrayList <MUCRole>(); 1412 for (MUCRole role : occupants.values()) { 1413 if (MUCRole.Role.participant == role.getRole()) { 1414 participants.add(role); 1415 } 1416 } 1417 return participants; 1418 } 1419 1420 public Presence addModerator(JID jid, MUCRole senderRole) throws ForbiddenException { 1421 if (MUCRole.Affiliation.admin != senderRole.getAffiliation() 1422 && MUCRole.Affiliation.owner != senderRole.getAffiliation()) { 1423 throw new ForbiddenException(); 1424 } 1425 try { 1427 return changeOccupantRole(jid, MUCRole.Role.moderator); 1428 } 1429 catch (NotAllowedException e) { 1430 return null; 1432 } 1433 } 1434 1435 public Presence addParticipant(JID jid, String reason, MUCRole senderRole) 1436 throws NotAllowedException, ForbiddenException { 1437 if (MUCRole.Role.moderator != senderRole.getRole()) { 1438 throw new ForbiddenException(); 1439 } 1440 Presence updatedPresence = changeOccupantRole(jid, MUCRole.Role.participant); 1442 if (updatedPresence != null) { 1443 Element frag = updatedPresence.getChildElement( 1444 "x", "http://jabber.org/protocol/muc#user"); 1445 if (reason != null && reason.trim().length() > 0) { 1447 frag.element("item").addElement("reason").setText(reason); 1448 } 1449 } 1450 return updatedPresence; 1451 } 1452 1453 public Presence addVisitor(JID jid, MUCRole senderRole) throws NotAllowedException, 1454 ForbiddenException { 1455 if (MUCRole.Role.moderator != senderRole.getRole()) { 1456 throw new ForbiddenException(); 1457 } 1458 return changeOccupantRole(jid, MUCRole.Role.visitor); 1459 } 1460 1461 public Presence kickOccupant(JID jid, JID actorJID, String reason) 1462 throws NotAllowedException { 1463 Presence updatedPresence = changeOccupantRole(jid, MUCRole.Role.none); 1465 if (updatedPresence != null) { 1466 Element frag = updatedPresence.getChildElement( 1467 "x", "http://jabber.org/protocol/muc#user"); 1468 1469 frag.addElement("status").addAttribute("code", "307"); 1471 if (reason != null && reason.trim().length() > 0) { 1473 frag.element("item").addElement("reason").setText(reason); 1474 } 1475 1476 kickPresence(updatedPresence, actorJID); 1478 } 1479 return updatedPresence; 1480 } 1481 1482 1491 private void kickPresence(Presence kickPresence, JID actorJID) { 1492 MUCRole kickedRole; 1493 kickedRole = occupants.get(kickPresence.getFrom().getResource()); 1495 if (kickedRole != null) { 1496 kickPresence = kickPresence.createCopy(); 1497 if (actorJID != null && actorJID.toString().length() > 0) { 1499 Element frag = kickPresence.getChildElement( 1500 "x", "http://jabber.org/protocol/muc#user"); 1501 frag.element("item").addElement("actor").addAttribute("jid", actorJID.toBareJID()); 1502 } 1503 kickedRole.send(kickPresence); 1505 removeOccupantRole(kickedRole); 1507 } 1508 } 1509 1510 public boolean canAnyoneDiscoverJID() { 1511 return canAnyoneDiscoverJID; 1512 } 1513 1514 public void setCanAnyoneDiscoverJID(boolean canAnyoneDiscoverJID) { 1515 this.canAnyoneDiscoverJID = canAnyoneDiscoverJID; 1516 } 1517 1518 public boolean canOccupantsChangeSubject() { 1519 return canOccupantsChangeSubject; 1520 } 1521 1522 public void setCanOccupantsChangeSubject(boolean canOccupantsChangeSubject) { 1523 this.canOccupantsChangeSubject = canOccupantsChangeSubject; 1524 } 1525 1526 public boolean canOccupantsInvite() { 1527 return canOccupantsInvite; 1528 } 1529 1530 public void setCanOccupantsInvite(boolean canOccupantsInvite) { 1531 this.canOccupantsInvite = canOccupantsInvite; 1532 } 1533 1534 public String getNaturalLanguageName() { 1535 return naturalLanguageName; 1536 } 1537 1538 public void setNaturalLanguageName(String naturalLanguageName) { 1539 this.naturalLanguageName = naturalLanguageName; 1540 } 1541 1542 public String getDescription() { 1543 return description; 1544 } 1545 1546 public void setDescription(String description) { 1547 this.description = description; 1548 } 1549 1550 public boolean isMembersOnly() { 1551 return membersOnly; 1552 } 1553 1554 public List <Presence> setMembersOnly(boolean membersOnly) { 1555 List <Presence> presences = new ArrayList <Presence>(); 1556 if (membersOnly && !this.membersOnly) { 1557 for (MUCRole occupant : occupants.values()) { 1560 if (occupant.getAffiliation().compareTo(MUCRole.Affiliation.member) > 0) { 1561 try { 1562 presences.add(kickOccupant(occupant.getRoleAddress(), null, 1563 LocaleUtils.getLocalizedString("muc.roomIsNowMembersOnly"))); 1564 } 1565 catch (NotAllowedException e) { 1566 Log.error(e); 1567 } 1568 } 1569 } 1570 } 1571 this.membersOnly = membersOnly; 1572 return presences; 1573 } 1574 1575 public boolean isLogEnabled() { 1576 return logEnabled; 1577 } 1578 1579 public void setLogEnabled(boolean logEnabled) { 1580 this.logEnabled = logEnabled; 1581 } 1582 1583 public void setLoginRestrictedToNickname(boolean restricted) { 1584 this.loginRestrictedToNickname = restricted; 1585 } 1586 1587 public boolean isLoginRestrictedToNickname() { 1588 return loginRestrictedToNickname; 1589 } 1590 1591 public void setChangeNickname(boolean canChange) { 1592 this.canChangeNickname = canChange; 1593 } 1594 1595 public boolean canChangeNickname() { 1596 return canChangeNickname; 1597 } 1598 1599 public void setRegistrationEnabled(boolean registrationEnabled) { 1600 this.registrationEnabled = registrationEnabled; 1601 } 1602 1603 public boolean isRegistrationEnabled() { 1604 return registrationEnabled; 1605 } 1606 1607 public int getMaxUsers() { 1608 return maxUsers; 1609 } 1610 1611 public void setMaxUsers(int maxUsers) { 1612 this.maxUsers = maxUsers; 1613 } 1614 1615 public boolean isModerated() { 1616 return moderated; 1617 } 1618 1619 public void setModerated(boolean moderated) { 1620 this.moderated = moderated; 1621 } 1622 1623 public String getPassword() { 1624 return password; 1625 } 1626 1627 public void setPassword(String password) { 1628 this.password = password; 1629 } 1630 1631 public boolean isPasswordProtected() { 1632 return password != null && password.trim().length() > 0; 1633 } 1634 1635 public boolean isPersistent() { 1636 return persistent; 1637 } 1638 1639 public boolean wasSavedToDB() { 1640 if (!isPersistent()) { 1641 return false; 1642 } 1643 return savedToDB; 1644 } 1645 1646 public void setSavedToDB(boolean saved) { 1647 this.savedToDB = saved; 1648 } 1649 1650 public void setPersistent(boolean persistent) { 1651 this.persistent = persistent; 1652 } 1653 1654 public boolean isPublicRoom() { 1655 return !isDestroyed && publicRoom; 1656 } 1657 1658 public void setPublicRoom(boolean publicRoom) { 1659 this.publicRoom = publicRoom; 1660 } 1661 1662 public List <String > getRolesToBroadcastPresence() { 1663 return Collections.unmodifiableList(rolesToBroadcastPresence); 1664 } 1665 1666 public void setRolesToBroadcastPresence(List <String > rolesToBroadcastPresence) { 1667 this.rolesToBroadcastPresence = rolesToBroadcastPresence; 1670 } 1671 1672 1677 private boolean hasToCheckRoleToBroadcastPresence() { 1678 return rolesToBroadcastPresence.size() < 3; 1680 } 1681 1682 public boolean canBroadcastPresence(String roleToBroadcast) { 1683 return "none".equals(roleToBroadcast) || rolesToBroadcastPresence.contains(roleToBroadcast); 1684 } 1685 1686 public void lock(MUCRole senderRole) throws ForbiddenException { 1687 if (MUCRole.Affiliation.owner != senderRole.getAffiliation()) { 1688 throw new ForbiddenException(); 1689 } 1690 if (isLocked()) { 1691 return; 1693 } 1694 setLocked(true); 1695 if (senderRole.getChatUser() != null) { 1696 Message message = new Message(); 1698 message.setType(Message.Type.groupchat); 1699 message.setBody(LocaleUtils.getLocalizedString("muc.locked")); 1700 message.setFrom(getRole().getRoleAddress()); 1701 senderRole.send(message); 1702 } 1703 } 1704 1705 public void unlock(MUCRole senderRole) throws ForbiddenException { 1706 if (MUCRole.Affiliation.owner != senderRole.getAffiliation()) { 1707 throw new ForbiddenException(); 1708 } 1709 if (!isLocked()) { 1710 return; 1712 } 1713 setLocked(false); 1714 if (senderRole.getChatUser() != null) { 1715 Message message = new Message(); 1717 message.setType(Message.Type.groupchat); 1718 message.setBody(LocaleUtils.getLocalizedString("muc.unlocked")); 1719 message.setFrom(getRole().getRoleAddress()); 1720 senderRole.send(message); 1721 } 1722 } 1723 1724 private void setLocked(boolean locked) { 1725 if (locked) { 1726 this.lockedTime = System.currentTimeMillis(); 1727 } 1728 else { 1729 this.lockedTime = 0; 1730 } 1731 MUCPersistenceManager.updateRoomLock(this); 1732 } 1733 1734 1742 void setLockedDate(Date lockedTime) { 1743 this.lockedTime = lockedTime.getTime(); 1744 } 1745 1746 1754 Date getLockedDate() { 1755 return new Date(lockedTime); 1756 } 1757 1758 public List <Presence> addAdmins(List <String > newAdmins, MUCRole senderRole) 1759 throws ForbiddenException, ConflictException { 1760 List <Presence> answer = new ArrayList <Presence>(newAdmins.size()); 1761 for (String newAdmin : newAdmins) { 1762 if (newAdmin.trim().length() > 0 && !admins.contains(newAdmin)) { 1763 answer.addAll(addAdmin(newAdmin, senderRole)); 1764 } 1765 } 1766 return answer; 1767 } 1768 1769 public List <Presence> addOwners(List <String > newOwners, MUCRole senderRole) 1770 throws ForbiddenException { 1771 List <Presence> answer = new ArrayList <Presence>(newOwners.size()); 1772 for (String newOwner : newOwners) { 1773 if (newOwner.trim().length() > 0 && !owners.contains(newOwner)) { 1774 answer.addAll(addOwner(newOwner, senderRole)); 1775 } 1776 } 1777 return answer; 1778 } 1779 1780 public void saveToDB() { 1781 MUCPersistenceManager.saveToDB(this); 1783 if (!savedToDB) { 1784 savedToDB = true; 1786 for (String owner : owners) { 1788 MUCPersistenceManager.saveAffiliationToDB( 1789 this, 1790 owner, 1791 null, 1792 MUCRole.Affiliation.owner, 1793 MUCRole.Affiliation.none); 1794 } 1795 for (String admin : admins) { 1797 MUCPersistenceManager.saveAffiliationToDB( 1798 this, 1799 admin, 1800 null, 1801 MUCRole.Affiliation.admin, 1802 MUCRole.Affiliation.none); 1803 } 1804 for (Iterator it=members.keySet().iterator(); it.hasNext();) { 1806 String bareJID = (String )it.next(); 1807 MUCPersistenceManager.saveAffiliationToDB(this, bareJID, (String ) members 1808 .get(bareJID), MUCRole.Affiliation.member, MUCRole.Affiliation.none); 1809 } 1810 for (String outcast : outcasts) { 1812 MUCPersistenceManager.saveAffiliationToDB( 1813 this, 1814 outcast, 1815 null, 1816 MUCRole.Affiliation.outcast, 1817 MUCRole.Affiliation.none); 1818 } 1819 } 1820 } 1821} | Popular Tags |