BasicRoster.java 6.51 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
package org.jivesoftware.messenger.roster;
Matt Tucker's avatar
Matt Tucker committed
13 14 15 16 17 18 19

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;
Derek DeMoro's avatar
Derek DeMoro committed
20
import org.jivesoftware.messenger.auth.UnauthorizedException;
Matt Tucker's avatar
Matt Tucker committed
21 22 23 24
import org.jivesoftware.messenger.roster.Roster;
import org.jivesoftware.messenger.roster.RosterItem;
import org.jivesoftware.messenger.user.UserNotFoundException;
import org.jivesoftware.messenger.user.UserAlreadyExistsException;
Derek DeMoro's avatar
Derek DeMoro committed
25 26 27
import org.jivesoftware.util.CacheSizes;
import org.jivesoftware.util.Cacheable;
import org.xmpp.packet.JID;
Matt Tucker's avatar
Matt Tucker committed
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

/**
 * <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() {
    }

Derek DeMoro's avatar
Derek DeMoro committed
53
    public boolean isRosterItem(JID user) {
Matt Tucker's avatar
Matt Tucker committed
54 55
        itemLock.readLock().lock();
        try {
Derek DeMoro's avatar
Derek DeMoro committed
56
            return rosterItems.containsKey(user.toBareJID());
Matt Tucker's avatar
Matt Tucker committed
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
        }
        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();
        }
    }

Derek DeMoro's avatar
Derek DeMoro committed
88
    public RosterItem getRosterItem(JID user) throws UnauthorizedException, UserNotFoundException {
Matt Tucker's avatar
Matt Tucker committed
89 90
        itemLock.readLock().lock();
        try {
Derek DeMoro's avatar
Derek DeMoro committed
91
            RosterItem item = (RosterItem)rosterItems.get(user.toBareJID());
Matt Tucker's avatar
Matt Tucker committed
92
            if (item == null) {
Derek DeMoro's avatar
Derek DeMoro committed
93
                throw new UserNotFoundException(user.toBareJID());
Matt Tucker's avatar
Matt Tucker committed
94 95 96 97 98 99 100 101
            }
            return item;
        }
        finally {
            itemLock.readLock().unlock();
        }
    }

Derek DeMoro's avatar
Derek DeMoro committed
102
    public RosterItem createRosterItem(JID user) throws UnauthorizedException, UserAlreadyExistsException {
Matt Tucker's avatar
Matt Tucker committed
103 104 105
        return createRosterItem(user, null, null);
    }

Gaston Dombiak's avatar
Gaston Dombiak committed
106 107
    public RosterItem createRosterItem(JID user, String nickname, List<String> groups)
            throws UnauthorizedException, UserAlreadyExistsException {
Matt Tucker's avatar
Matt Tucker committed
108 109 110
        RosterItem item = provideRosterItem(user, nickname, groups);
        itemLock.writeLock().lock();
        try {
Derek DeMoro's avatar
Derek DeMoro committed
111
            rosterItems.put(item.getJid().toBareJID(), item);
Matt Tucker's avatar
Matt Tucker committed
112 113 114 115 116 117 118
            return item;
        }
        finally {
            itemLock.writeLock().unlock();
        }
    }

Gaston Dombiak's avatar
Gaston Dombiak committed
119 120 121
    public void createRosterItem(org.xmpp.packet.Roster.Item item)
            throws UnauthorizedException, UserAlreadyExistsException {
        RosterItem rosterItem = provideRosterItem(item);
Matt Tucker's avatar
Matt Tucker committed
122 123
        itemLock.writeLock().lock();
        try {
Gaston Dombiak's avatar
Gaston Dombiak committed
124
            rosterItems.put(item.getJID().toBareJID(), rosterItem);
Matt Tucker's avatar
Matt Tucker committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
        }
        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
     */
Gaston Dombiak's avatar
Gaston Dombiak committed
142
    protected RosterItem provideRosterItem(JID user, String nickname, List<String> groups)
Matt Tucker's avatar
Matt Tucker committed
143 144 145 146 147 148 149 150 151 152 153 154 155
            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
     */
Gaston Dombiak's avatar
Gaston Dombiak committed
156
    protected RosterItem provideRosterItem(org.xmpp.packet.Roster.Item item)
Matt Tucker's avatar
Matt Tucker committed
157 158 159 160 161 162 163
            throws UserAlreadyExistsException, UnauthorizedException {
        return new BasicRosterItem(item);
    }

    public void updateRosterItem(RosterItem item) throws UnauthorizedException, UserNotFoundException {
        itemLock.writeLock().lock();
        try {
Derek DeMoro's avatar
Derek DeMoro committed
164 165
            if (rosterItems.get(item.getJid().toBareJID()) == null) {
                throw new UserNotFoundException(item.getJid().toBareJID());
Matt Tucker's avatar
Matt Tucker committed
166
            }
Derek DeMoro's avatar
Derek DeMoro committed
167
            rosterItems.put(item.getJid().toBareJID(), item);
Matt Tucker's avatar
Matt Tucker committed
168 169 170 171 172 173
        }
        finally {
            itemLock.writeLock().unlock();
        }
    }

Derek DeMoro's avatar
Derek DeMoro committed
174
    public RosterItem deleteRosterItem(JID user) throws UnauthorizedException {
Matt Tucker's avatar
Matt Tucker committed
175 176 177 178

        itemLock.writeLock().lock();
        try {
            // If removing the user was successful, remove the user from the subscriber list:
Derek DeMoro's avatar
Derek DeMoro committed
179
            return (RosterItem)rosterItems.remove(user.toBareJID());
Matt Tucker's avatar
Matt Tucker committed
180 181 182 183 184 185 186 187 188 189 190 191 192 193
        }
        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;
    }
}