BasicRoster.java 6.35 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 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 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 117 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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
package org.jivesoftware.messenger.user;

import org.jivesoftware.util.CacheSizes;
import org.jivesoftware.messenger.XMPPAddress;
import org.jivesoftware.messenger.auth.UnauthorizedException;
import org.jivesoftware.util.Cacheable;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * <p>Implements the basic Roster interface storing all roster items into a simple hash table.</p>
 * <p>This class is intended to be used as a simple based for creating specialized Roster
 * implementations without having to recode the very boring item management.</p>
 *
 * @author Iain Shigeoka
 */
public class BasicRoster implements Roster, Cacheable {

    /**
     * <p>Roster item cache - table: key jabberid string; value roster item.</p>
     */
    protected Hashtable rosterItems = new Hashtable();
    /**
     * <p>Lock for the roster item map.</p>
     */
    private ReadWriteLock itemLock = new ReentrantReadWriteLock();

    /**
     * <p>Create an empty iq roster packet.</p>
     */
    public BasicRoster() {
    }

    public boolean isRosterItem(XMPPAddress user) {
        itemLock.readLock().lock();
        try {
            return rosterItems.containsKey(user.toBareStringPrep());
        }
        finally {
            itemLock.readLock().unlock();
        }
    }

    public Iterator getRosterItems() throws UnauthorizedException {
        itemLock.readLock().lock();
        try {
            LinkedList itemList = new LinkedList();
            Iterator items = rosterItems.values().iterator();
            while (items.hasNext()) {
                itemList.add(items.next());
            }
            return itemList.iterator();
        }
        finally {
            itemLock.readLock().unlock();
        }
    }

    public int getTotalRosterItemCount() throws UnauthorizedException {
        itemLock.readLock().lock();
        try {
            return rosterItems.size();
        }
        finally {
            itemLock.readLock().unlock();
        }
    }

    public RosterItem getRosterItem(XMPPAddress user) throws UnauthorizedException, UserNotFoundException {
        itemLock.readLock().lock();
        try {
            RosterItem item = (RosterItem)rosterItems.get(user.toBareStringPrep());
            if (item == null) {
                throw new UserNotFoundException(user.toBareStringPrep());
            }
            return item;
        }
        finally {
            itemLock.readLock().unlock();
        }
    }

    public RosterItem createRosterItem(XMPPAddress user) throws UnauthorizedException, UserAlreadyExistsException {
        return createRosterItem(user, null, null);
    }

    public RosterItem createRosterItem(XMPPAddress user, String nickname, List groups) throws UnauthorizedException, UserAlreadyExistsException {
        RosterItem item = provideRosterItem(user, nickname, groups);
        itemLock.writeLock().lock();
        try {
            rosterItems.put(item.getJid().toBareStringPrep(), item);
            return item;
        }
        finally {
            itemLock.writeLock().unlock();
        }
    }

    public RosterItem createRosterItem(RosterItem item) throws UnauthorizedException, UserAlreadyExistsException {
        item = provideRosterItem(item);
        itemLock.writeLock().lock();
        try {
            rosterItems.put(item.getJid().toBareStringPrep(), item);
            return item;
        }
        finally {
            itemLock.writeLock().unlock();
        }
    }

    /**
     * <p>Generate a new RosterItem for use with createRosterItem.<p>
     * <p/>
     * <p>Overriding classes will want to override this method to produce the roster
     * item implementation to be used by the BasicRoster.createRsterItem() methods.</p>
     *
     * @param user     The roster jid address to create the roster item for
     * @param nickname The nickname to assign the item (or null for none)
     * @param groups   The groups the item belongs to (or null for none)
     * @return The newly created roster items ready to be stored by the BasicRoster item's hash table
     */
    protected RosterItem provideRosterItem(XMPPAddress user, String nickname, List groups)
            throws UserAlreadyExistsException, UnauthorizedException {
        return new BasicRosterItem(user, nickname, groups);
    }

    /**
     * <p>Generate a new RosterItem for use with createRosterItem.<p>
     * <p/>
     * <p>Overriding classes will want to override this method to produce the roster
     * item implementation to be used by the BasicRoster.createRsterItem() methods.</p>
     *
     * @param item The item to copy settings for the new item in this roster
     * @return The newly created roster items ready to be stored by the BasicRoster item's hash table
     */
    protected RosterItem provideRosterItem(RosterItem item)
            throws UserAlreadyExistsException, UnauthorizedException {
        return new BasicRosterItem(item);
    }

    public void updateRosterItem(RosterItem item) throws UnauthorizedException, UserNotFoundException {
        itemLock.writeLock().lock();
        try {
            if (rosterItems.get(item.getJid().toBareStringPrep()) == null) {
                throw new UserNotFoundException(item.getJid().toBareStringPrep());
            }
            rosterItems.put(item.getJid().toBareStringPrep(), item);
        }
        finally {
            itemLock.writeLock().unlock();
        }
    }

    public RosterItem deleteRosterItem(XMPPAddress user) throws UnauthorizedException {

        itemLock.writeLock().lock();
        try {
            // If removing the user was successful, remove the user from the subscriber list:
            return (RosterItem)rosterItems.remove(user.toBareStringPrep());
        }
        finally {
            itemLock.writeLock().unlock();
        }
    }

    public int getCachedSize() {
        // Approximate the size of the object in bytes by calculating the size
        // of each field.
        int size = 0;
        size += CacheSizes.sizeOfMap(rosterItems);          // roster item cache
        return size;
    }
}