MUCPersistentRoomSurrogate.java 18.8 KB
Newer Older
Matt Tucker's avatar
Matt Tucker committed
1 2 3 4 5
/**
 * $RCSfile$
 * $Revision$
 * $Date$
 *
Matt Tucker's avatar
Matt Tucker committed
6
 * Copyright (C) 2004 Jive Software. All rights reserved.
Matt Tucker's avatar
Matt Tucker committed
7
 *
Matt Tucker's avatar
Matt Tucker committed
8 9
 * This software is published under the terms of the GNU Public License (GPL),
 * a copy of which is included in this distribution.
Matt Tucker's avatar
Matt Tucker committed
10
 */
Matt Tucker's avatar
Matt Tucker committed
11

Matt Tucker's avatar
Matt Tucker committed
12 13 14 15 16 17 18 19 20
package org.jivesoftware.messenger.muc.spi;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.jivesoftware.messenger.muc.*;
import org.jivesoftware.util.NotFoundException;
21 22
import org.jivesoftware.util.Cacheable;
import org.jivesoftware.util.CacheSizes;
Matt Tucker's avatar
Matt Tucker committed
23
import org.jivesoftware.messenger.*;
24
import org.jivesoftware.messenger.spi.MessageImpl;
Matt Tucker's avatar
Matt Tucker committed
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
import org.jivesoftware.messenger.auth.UnauthorizedException;
import org.jivesoftware.messenger.user.UserAlreadyExistsException;
import org.jivesoftware.messenger.user.UserNotFoundException;

import org.jivesoftware.messenger.muc.MUCRole;

/**
 * A surrogate for the persistent room that hasn't been loaded in memory. This class is an 
 * optimization so that persistent rooms don't need to be in memory in order to provide the 
 * necessary information to answer to a service discovery requests.<p>
 * 
 * The list of MUCPersistentRoomSurrogates is hold by MultiUserChatServerImpl. 
 * MultiUserChatServerImpl is also responsible for updating the list whenever a room is loaded from 
 * the database or a persistent room is removed from memory.<p>
 * 
 * Since this class is a surrogate for the real room, most of the room operations of this class will 
 * throw an UnsupportedOperationException.
 * 
 * @author Gaston Dombiak
 */
45 46 47 48 49 50
class MUCPersistentRoomSurrogate implements MUCRoom, Cacheable {

    /**
     * The server hosting the room.
     */
    private MultiUserChatServer server;
Matt Tucker's avatar
Matt Tucker committed
51 52 53 54 55 56

    /**
     * The name of the room.
     */
    private String name;

57 58 59 60 61 62 63 64 65 66
    /**
     * The role of the room itself.
     */
    private MUCRole role;

    /**
     * The router used to send packets for the room.
     */
    private PacketRouter router;

67 68 69 70 71
    /**
     * The natural language name of the room.
     */
    private String naturalLanguageName;

72 73 74 75 76 77
    /**
     * Description of the room. The owner can change the description using the room configuration
     * form.
     */
    private String description;

Matt Tucker's avatar
Matt Tucker committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
    /**
     * Indicates if occupants are allowed to change the subject of the room. 
     */
    private boolean canOccupantsChangeSubject = false;

    /**
     * Maximum number of occupants that could be present in the room. If the limit's been reached
     * and a user tries to join, a not-allowed error will be returned.
     */
    private int maxUsers = 30;

    /**
     * List of roles of which presence will be broadcasted to the rest of the occupants. This
     * feature is useful for implementing "invisible" occupants.
     */
    private List rolesToBroadcastPresence = new ArrayList();

    /**
     * Moderated rooms enable only participants to speak. Users that join the room and aren't
     * participants can't speak (they are just visitors).
     */
    private boolean moderated = false;

    /**
     * A room is considered members-only if an invitation is required in order to enter the room.
     * Any user that is not a member of the room won't be able to join the room unless the user
     * decides to register with the room (thus becoming a member).
     */
    private boolean invitationRequiredToEnter = false;

    /**
     * Some rooms may restrict the occupants that are able to send invitations. Sending an 
     * invitation in a members-only room adds the invitee to the members list.
     */
    private boolean canOccupantsInvite = false;

    /**
     * The password that every occupant should provide in order to enter the room.
     */
117
    private String password = null;
Matt Tucker's avatar
Matt Tucker committed
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143

    /**
     * Every presence packet can include the JID of every occupant unless the owner deactives this
     * configuration. 
     */
    private boolean canAnyoneDiscoverJID = false;

    /**
     * Enables the logging of the conversation. The conversation in the room will be saved to the
     * database.
     */
    private boolean logEnabled = false;

    /**
     * The last known subject of the room. This information is used to respond disco requests. The
     * MUCRoomHistory class holds the history of the room together with the last message that set
     * the room's subject.
     */
    private String subject = "";
    
    /**
     * The ID of the room. If the room is temporary and does not log its conversation then the value
     * will always be -1. Otherwise a value will be obtained from the database.
     */
    private long roomID = -1;

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
    /**
     * Create a new chat room.
     *
     * @param chatserver the server hosting the room.
     * @param roomname the name of the room.
     * @param packetRouter the router for sending packets from the room.
     */
    MUCPersistentRoomSurrogate(MultiUserChatServer chatserver, String roomname,
                               PacketRouter packetRouter) {
        this.server = chatserver;
        this.name = roomname;
        this.router = packetRouter;
        role = new MUCPersistentRoomSurrogate.RoomRole(this);
    }

Matt Tucker's avatar
Matt Tucker committed
159 160 161 162 163 164 165 166 167 168 169 170 171
    public String getName() {
        return name;
    }

    public long getID() {
        return roomID;
    }

    public void setID(long roomID) {
        this.roomID = roomID;
    }

    public MUCRole getRole() throws UnauthorizedException {
172
        return role;
Matt Tucker's avatar
Matt Tucker committed
173 174 175
    }

    public MUCRole getOccupant(String nickname) throws UserNotFoundException {
176
        throw new UserNotFoundException();
Matt Tucker's avatar
Matt Tucker committed
177 178 179
    }

    public List<MUCRole> getOccupantsByBareJID(String jid) throws UserNotFoundException {
180
        throw new UserNotFoundException();
Matt Tucker's avatar
Matt Tucker committed
181 182 183
    }

    public MUCRole getOccupantByFullJID(String jid) throws UserNotFoundException {
184
        throw new UserNotFoundException();
Matt Tucker's avatar
Matt Tucker committed
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
    }

    public Iterator<MUCRole> getOccupants() throws UnauthorizedException {
        return Collections.EMPTY_LIST.iterator();
    }

    public int getOccupantsCount() {
        return 0;
    }

    public boolean hasOccupant(String nickname) throws UnauthorizedException {
        return false;
    }

    public String getReservedNickname(String bareJID) {
200
        return MUCPersistenceManager.getReservedNickname(this, bareJID);
Matt Tucker's avatar
Matt Tucker committed
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
    }

    public int getAffiliation(String bareJID) {
        throw new UnsupportedOperationException();
    }

    public MUCRole joinRoom(String nickname,
                            String password,
                            HistoryRequest historyRequest,
                            MUCUser user) throws UnauthorizedException, UserAlreadyExistsException,
            RoomLockedException, ForbiddenException, RegistrationRequiredException,
            NotAllowedException, ConflictException {
        throw new UnsupportedOperationException();
    }

    public void leaveRoom(String nickname) throws UnauthorizedException, UserNotFoundException {
        throw new UnsupportedOperationException();
    }

    public void destroyRoom(String alternateJID, String reason) throws UnauthorizedException {
        throw new UnsupportedOperationException();
    }

    public Presence createPresence(int presenceStatus) throws UnauthorizedException {
        throw new UnsupportedOperationException();
    }

    public void serverBroadcast(String msg) throws UnauthorizedException {
        throw new UnsupportedOperationException();
    }

    public long getChatLength() {
        return 0;
    }

    public void addFirstOwner(String bareJID) {
        throw new UnsupportedOperationException();
    }

240
    public List<Presence> addOwner(String bareJID, MUCRole sendRole) throws ForbiddenException {
Matt Tucker's avatar
Matt Tucker committed
241 242 243
        throw new UnsupportedOperationException();
    }

244
    public List<Presence> addAdmin(String bareJID, MUCRole sendRole) throws ForbiddenException,
Matt Tucker's avatar
Matt Tucker committed
245 246 247 248
            ConflictException {
        throw new UnsupportedOperationException();
    }

249
    public List<Presence> addMember(String bareJID, String nickname, MUCRole sendRole)
Matt Tucker's avatar
Matt Tucker committed
250 251 252 253
            throws ForbiddenException, ConflictException {
        throw new UnsupportedOperationException();
    }

254
    public List<Presence> addOutcast(String bareJID, String reason, MUCRole sendRole)
Matt Tucker's avatar
Matt Tucker committed
255 256 257 258
            throws NotAllowedException, ForbiddenException, ConflictException {
        throw new UnsupportedOperationException();
    }

259
    public List<Presence> addNone(String bareJID, MUCRole sendRole) throws ForbiddenException,
Matt Tucker's avatar
Matt Tucker committed
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
            ConflictException {
        throw new UnsupportedOperationException();
    }

    public boolean isLocked() {
        return false;
    }

    public void nicknameChanged(String oldNick, String newNick) {
        throw new UnsupportedOperationException();
    }

    public void changeSubject(Message packet, MUCRole role) throws UnauthorizedException,
            ForbiddenException {
        throw new UnsupportedOperationException();
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public void sendPublicMessage(Message message, MUCRole senderRole)
            throws UnauthorizedException, ForbiddenException {
        throw new UnsupportedOperationException();
    }

    public void sendPrivateMessage(Message message, MUCRole senderRole) throws NotFoundException {
        throw new UnsupportedOperationException();
    }

    public Presence addModerator(String fullJID, MUCRole sendRole) throws ForbiddenException {
        throw new UnsupportedOperationException();
    }

    public Presence addParticipant(String fullJID, String reason, MUCRole sendRole)
            throws NotAllowedException, ForbiddenException {
        throw new UnsupportedOperationException();
    }

    public Presence addVisitor(String fullJID, MUCRole sendRole) throws NotAllowedException,
            ForbiddenException {
        throw new UnsupportedOperationException();
    }

    public Presence kickOccupant(String fullJID, String actorJID, String reason)
            throws NotAllowedException {
        throw new UnsupportedOperationException();
    }

    public IQOwnerHandler getIQOwnerHandler() {
        throw new UnsupportedOperationException();
    }

    public IQAdminHandler getIQAdminHandler() {
        throw new UnsupportedOperationException();
    }

    public Iterator getOwners() {
        return Collections.EMPTY_LIST.iterator();
    }

    public Iterator getAdmins() {
        return Collections.EMPTY_LIST.iterator();
    }

    public Iterator getMembers() {
        return Collections.EMPTY_LIST.iterator();
    }

    public Iterator getOutcasts() {
        return Collections.EMPTY_LIST.iterator();
    }

    public Iterator getModerators() {
        return Collections.EMPTY_LIST.iterator();
    }

    public Iterator getParticipants() {
        return Collections.EMPTY_LIST.iterator();
    }

    public boolean canAnyoneDiscoverJID() {
        return canAnyoneDiscoverJID;
    }

    public void setCanAnyoneDiscoverJID(boolean canAnyoneDiscoverJID) {
        this.canAnyoneDiscoverJID = canAnyoneDiscoverJID;
    }

    public boolean canOccupantsChangeSubject() {
        return canOccupantsChangeSubject;
    }

    public void setCanOccupantsChangeSubject(boolean canOccupantsChangeSubject) {
        this.canOccupantsChangeSubject = canOccupantsChangeSubject;
    }

    public boolean canOccupantsInvite() {
        return canOccupantsInvite;
    }

    public void setCanOccupantsInvite(boolean canOccupantsInvite) {
        this.canOccupantsInvite = canOccupantsInvite;
    }

369 370 371 372 373 374 375 376
    public String getNaturalLanguageName() {
        return naturalLanguageName;
    }

    public void setNaturalLanguageName(String naturalLanguageName) {
        this.naturalLanguageName = naturalLanguageName;
    }

Matt Tucker's avatar
Matt Tucker committed
377
    public String getDescription() {
378
        return description;
Matt Tucker's avatar
Matt Tucker committed
379 380 381
    }

    public void setDescription(String description) {
382
        this.description = description;
Matt Tucker's avatar
Matt Tucker committed
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
    }

    public boolean isInvitationRequiredToEnter() {
        return invitationRequiredToEnter;
    }

    public void setInvitationRequiredToEnter(boolean invitationRequiredToEnter) {
        this.invitationRequiredToEnter = invitationRequiredToEnter;
    }

    public boolean isLogEnabled() {
        return logEnabled;
    }

    public void setLogEnabled(boolean logEnabled) {
        this.logEnabled = logEnabled;
    }

    public int getMaxUsers() {
        return maxUsers;
    }

    public void setMaxUsers(int maxUsers) {
        this.maxUsers = maxUsers;
    }

    public boolean isModerated() {
        return moderated;
    }

    public void setModerated(boolean moderated) {
        this.moderated = moderated;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public boolean isPasswordProtected() {
426
        return password != null && password.trim().length() > 0;
Matt Tucker's avatar
Matt Tucker committed
427 428 429
    }

    public boolean isPersistent() {
430
        return true;
Matt Tucker's avatar
Matt Tucker committed
431 432 433
    }

    public void setPersistent(boolean persistent) {
434
        throw new UnsupportedOperationException();
Matt Tucker's avatar
Matt Tucker committed
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
    }

    public boolean wasSavedToDB() {
        return true;
    }

    public void setSavedToDB(boolean saved) {
        throw new UnsupportedOperationException();
    }

    public void saveToDB() {
        throw new UnsupportedOperationException();
    }

    public boolean isPublicRoom() {
        return true;
    }

    public void setPublicRoom(boolean publicRoom) {
        throw new UnsupportedOperationException();
    }

    public Iterator getRolesToBroadcastPresence() {
        return rolesToBroadcastPresence.iterator();
    }

    public void setRolesToBroadcastPresence(List rolesToBroadcastPresence) {
        this.rolesToBroadcastPresence = rolesToBroadcastPresence;
    }

    public boolean canBroadcastPresence(String roleToBroadcast) {
        throw new UnsupportedOperationException();
    }

469
    public void unlockRoom(MUCRole senderRole) {
Matt Tucker's avatar
Matt Tucker committed
470 471 472
        throw new UnsupportedOperationException();
    }

473 474
    public List<Presence> addAdmins(List<String> newAdmins, MUCRole sendRole)
            throws ForbiddenException, ConflictException {
Matt Tucker's avatar
Matt Tucker committed
475 476 477
        throw new UnsupportedOperationException();
    }

478 479
    public List<Presence> addOwners(List<String> newOwners, MUCRole sendRole)
            throws ForbiddenException {
Matt Tucker's avatar
Matt Tucker committed
480 481 482 483 484 485 486 487 488 489 490 491
        throw new UnsupportedOperationException();
    }

    public void sendInvitation(String to, String reason, MUCRole role, Session session)
            throws ForbiddenException {
        throw new UnsupportedOperationException();
    }

    public void sendInvitationRejection(String to,
                                        String reason,
                                        XMPPAddress sender,
                                        Session session) {
492 493 494 495 496 497 498 499 500 501 502 503 504
        Message message = new MessageImpl();
        message.setOriginatingSession(session);
        message.setSender(role.getRoleAddress());
        message.setRecipient(XMPPAddress.parseJID(to));
        MetaDataFragment frag = new MetaDataFragment("http://jabber.org/protocol/muc#user", "x");
        frag.setProperty("x.decline:from", sender.toBareStringPrep());
        if (reason != null && reason.length() > 0) {
            frag.setProperty("x.decline.reason", reason);
        }
        message.addFragment(frag);

        // Send the message with the invitation
        router.route(message);
Matt Tucker's avatar
Matt Tucker committed
505 506 507 508 509 510 511 512 513 514 515 516 517 518
    }

    public void send(Message packet) throws UnauthorizedException {
        throw new UnsupportedOperationException();
    }

    public void send(Presence packet) throws UnauthorizedException {
        throw new UnsupportedOperationException();
    }

    public void send(IQ packet) throws UnauthorizedException {
        throw new UnsupportedOperationException();
    }

519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
    /**
     * An empty role that represents the room itself in the chatroom. Chatrooms need to be able to
     * speak (server messages) and so must have their own role in the chatroom.
     */
    private class RoomRole implements MUCRole {

        private MUCRoom room;

        private RoomRole(MUCRoom room) {
            this.room = room;
        }

        public Presence getPresence() throws UnauthorizedException {
            return null;
        }

        public MetaDataFragment getExtendedPresenceInformation() throws UnauthorizedException {
            return null;
        }

        public void setPresence(Presence presence) throws UnauthorizedException {
        }

        public void setRole(int newRole) throws UnauthorizedException {
        }

        public int getRole() {
            return MUCRole.MODERATOR;
        }

        public String getRoleAsString() {
            return "moderator";
        }

        public void setAffiliation(int newAffiliation) throws UnauthorizedException {
        }

        public int getAffiliation() {
            return MUCRole.OWNER;
        }

        public String getAffiliationAsString() {
            return "owner";
        }

        public String getNickname() {
            return null;
        }

        public void kick() throws UnauthorizedException {
        }

        public MUCUser getChatUser() {
            return null;
        }

        public MUCRoom getChatRoom() {
            return room;
        }

        private XMPPAddress crJID = null;

        public XMPPAddress getRoleAddress() {
            if (crJID == null) {
583
                crJID = new XMPPAddress(room.getName(), server.getServiceName(), "");
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
            }
            return crJID;
        }

        public void send(Message packet) throws UnauthorizedException {
            room.send(packet);
        }

        public void send(Presence packet) throws UnauthorizedException {
            room.send(packet);
        }

        public void send(IQ packet) throws UnauthorizedException {
            room.send(packet);
        }

        public void changeNickname(String nickname) {
        }
    }

    public int getCachedSize() {
        // Approximate the size of the object in bytes by calculating the size
        // of each field.
        int size = 0;
        size += CacheSizes.sizeOfObject();                 // overhead of object
        size += CacheSizes.sizeOfLong();                   // roomID
        size += CacheSizes.sizeOfString(name);             // name
        size += CacheSizes.sizeOfBoolean();                // canOccupantsChangeSubject
        size += CacheSizes.sizeOfInt();                    // maxUsers
        size += CacheSizes.sizeOfList(rolesToBroadcastPresence); // rolesToBroadcastPresence
        size += CacheSizes.sizeOfBoolean();                // moderated
        size += CacheSizes.sizeOfBoolean();                // invitationRequiredToEnter
        size += CacheSizes.sizeOfBoolean();                // canOccupantsInvite
        size += CacheSizes.sizeOfString(password);         // password
        size += CacheSizes.sizeOfBoolean();                // canAnyoneDiscoverJID
        size += CacheSizes.sizeOfBoolean();                // logEnabled
        size += CacheSizes.sizeOfString(subject);          // subject
        return size;
    }
Matt Tucker's avatar
Matt Tucker committed
623
}