Commit 0eb7a17f authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gaston

Added shared groups support. JM-22


git-svn-id: http://svn.igniterealtime.org/svn/repos/messenger/trunk@772 b35dd754-fafc-0310-a699-88a17e54d16e
parent 162dded8
......@@ -385,10 +385,10 @@ public class DefaultGroupProvider implements GroupProvider {
try {
con = DbConnectionManager.getConnection();
if (adminsOnly) {
pstmt = con.prepareStatement(LOAD_MEMBERS);
pstmt = con.prepareStatement(LOAD_ADMINS);
}
else {
pstmt = con.prepareStatement(LOAD_ADMINS);
pstmt = con.prepareStatement(LOAD_MEMBERS);
}
pstmt.setString(1, groupName);
ResultSet rs = pstmt.executeQuery();
......
......@@ -161,6 +161,16 @@ public class Group implements Cacheable {
return new MemberCollection(members, false);
}
/**
* Returns true if the provided username belongs to a user of the group.
*
* @param username the username to check.
* @return true if the provided username belongs to a user of the group.
*/
public boolean isUser(String username) {
return members.contains(username) || administrators.contains(username);
}
public int getCachedSize() {
// Approximate the size of the object in bytes by calculating the size
// of each field.
......
......@@ -102,6 +102,11 @@ public class IQRosterHandler extends IQHandler implements ServerFeaturesProvider
}
return returnPacket;
}
catch (SharedGroupException e) {
IQ result = IQ.createResultIQ(packet);
result.setError(PacketError.Condition.not_acceptable);
return result;
}
catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
......@@ -116,7 +121,8 @@ public class IQRosterHandler extends IQHandler implements ServerFeaturesProvider
*
* @param packet The packet suspected of containing a roster removal
*/
private void removeRosterItem(org.xmpp.packet.Roster packet) throws UnauthorizedException {
private void removeRosterItem(org.xmpp.packet.Roster packet) throws UnauthorizedException,
SharedGroupException {
JID recipientJID = packet.getTo();
JID senderJID = packet.getFrom();
try {
......@@ -124,7 +130,7 @@ public class IQRosterHandler extends IQHandler implements ServerFeaturesProvider
if (packetItem.getSubscription() == org.xmpp.packet.Roster.Subscription.remove) {
Roster roster = userManager.getUser(recipientJID.getNode()).getRoster();
RosterItem item = roster.getRosterItem(senderJID);
roster.deleteRosterItem(senderJID);
roster.deleteRosterItem(senderJID, true);
item.setSubStatus(RosterItem.SUB_REMOVE);
item.setSubStatus(RosterItem.SUB_NONE);
......@@ -148,7 +154,7 @@ public class IQRosterHandler extends IQHandler implements ServerFeaturesProvider
* @return Either a response to the roster update or null if the packet is corrupt and the session was closed down
*/
private IQ manageRoster(org.xmpp.packet.Roster packet) throws UnauthorizedException,
UserAlreadyExistsException {
UserAlreadyExistsException, SharedGroupException {
IQ returnPacket = null;
Session session = sessionManager.getSession(packet.getFrom());
......@@ -207,15 +213,15 @@ public class IQRosterHandler extends IQHandler implements ServerFeaturesProvider
* @param item The removal item element
*/
private void removeItem(org.jivesoftware.messenger.roster.Roster roster, JID sender,
org.xmpp.packet.Roster.Item item) {
org.xmpp.packet.Roster.Item item) throws SharedGroupException {
JID recipient = item.getJID();
// Remove recipient from the sender's roster
roster.deleteRosterItem(item.getJID());
roster.deleteRosterItem(item.getJID(), true);
// Forward set packet to the subscriber
if (localServer.isLocal(recipient)) { // Recipient is local so let's handle it here
try {
Roster recipientRoster = userManager.getUser(recipient.getNode()).getRoster();
recipientRoster.deleteRosterItem(sender);
recipientRoster.deleteRosterItem(sender, true);
}
catch (UserNotFoundException e) {
}
......
......@@ -23,6 +23,7 @@ import org.jivesoftware.messenger.user.*;
import org.xmpp.packet.Presence;
import org.xmpp.packet.Packet;
import org.xmpp.packet.JID;
import org.xmpp.packet.PacketError;
import java.util.Hashtable;
import java.util.Map;
......@@ -88,6 +89,7 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand
JID recipientJID = presence.getTo();
Presence.Type type = presence.getType();
Roster roster = getRoster(senderJID);
try {
if (roster != null) {
manageSub(recipientJID, true, type, roster);
}
......@@ -95,7 +97,6 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand
if (roster != null) {
manageSub(senderJID, false, type, roster);
}
try {
// Try to obtain a handler for the packet based on the routes. If the handler is
// a module, the module will be able to handle the packet. If the handler is a
// Session the packet will be routed to the client. If a route cannot be found
......@@ -106,6 +107,14 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand
catch (NoSuchRouteException e) {
deliverer.deliver(presence.createCopy());
}
catch (SharedGroupException e) {
Presence result = presence.createCopy();
JID sender = result.getFrom();
result.setFrom(presence.getTo());
result.setTo(sender);
result.setError(PacketError.Condition.not_acceptable);
deliverer.deliver(result);
}
}
catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
......@@ -124,6 +133,9 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand
if (localServer.isLocal(address) && !"".equals(address.getNode())) {
username = address.getNode();
// Check for a cached roster:
roster = (Roster)CacheManager.getCache("username2roster").get(username);
if (roster == null) {
synchronized(address.toString().intern()) {
roster = (Roster)CacheManager.getCache("username2roster").get(username);
if (roster == null) {
// Not in cache so load a new one:
......@@ -131,6 +143,8 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand
CacheManager.getCache("username2roster").put(username, roster);
}
}
}
}
return roster;
}
......@@ -143,8 +157,8 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand
* @param isSending True if the request is being sent by the owner
* @param type The subscription change type (subscribe, unsubscribe, etc.)
*/
private void manageSub(JID target, boolean isSending, Presence.Type type,
Roster roster) throws UserAlreadyExistsException
private void manageSub(JID target, boolean isSending, Presence.Type type, Roster roster)
throws UserAlreadyExistsException, SharedGroupException
{
try {
RosterItem item;
......
......@@ -14,11 +14,12 @@ package org.jivesoftware.messenger.roster;
import org.jivesoftware.util.IntEnum;
import org.jivesoftware.util.Cacheable;
import org.jivesoftware.util.CacheSizes;
import org.jivesoftware.messenger.group.GroupManager;
import org.jivesoftware.messenger.group.GroupNotFoundException;
import org.jivesoftware.messenger.SharedGroupException;
import org.xmpp.packet.JID;
import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;
import java.util.*;
/**
* <p>Represents a single roster item for a User's Roster.</p>
......@@ -123,6 +124,7 @@ public class RosterItem implements Cacheable {
protected JID jid;
protected String nickname;
protected List<String> groups;
protected Set<String> sharedGroups = new HashSet<String>();
protected SubType subStatus;
protected AskType askStatus;
private long rosterID;
......@@ -151,9 +153,8 @@ public class RosterItem implements Cacheable {
this.nickname = nickname;
this.groups = new LinkedList<String>();
if (groups != null) {
Iterator<String> groupItr = groups.iterator();
while (groupItr.hasNext()) {
this.groups.add(groupItr.next());
for (String group : groups) {
this.groups.add(group);
}
}
}
......@@ -208,8 +209,14 @@ public class RosterItem implements Cacheable {
* @return The subscription status of the item
*/
public SubType getSubStatus() {
if (isShared()) {
// Redefine the sub status since the item belongs to a shared group
return SUB_BOTH;
}
else {
return subStatus;
}
}
/**
* <p>Set the current subscription status of the item.</p>
......@@ -226,8 +233,14 @@ public class RosterItem implements Cacheable {
* @return The ask status of the item
*/
public AskType getAskStatus() {
if (isShared()) {
// Redefine the ask status since the item belongs to a shared group
return ASK_NONE;
}
else {
return askStatus;
}
}
/**
* <p>Set the current ask status of the item.</p>
......@@ -284,9 +297,9 @@ public class RosterItem implements Cacheable {
}
/**
* <p>Obtain the groups for the item.</p>
* Returns the groups for the item. Shared groups won't be included in the answer.
*
* @return The subscription status of the item
* @return The groups for the item.
*/
public List<String> getGroups() {
return groups;
......@@ -295,17 +308,77 @@ public class RosterItem implements Cacheable {
/**
* <p>Set the current groups for the item.</p>
*
* @param groups The subscription status of the item
* @param groups The new lists of groups the item belongs to.
*/
public void setGroups(List<String> groups) {
public void setGroups(List<String> groups) throws SharedGroupException {
if (groups == null) {
this.groups = new LinkedList<String>();
}
else {
// Raise an error if the user is trying to remove the item from a shared group
for (String groupName : getSharedGroups()) {
// Check if the group has been removed from the new groups list
if (!groups.contains(groupName)) {
throw new SharedGroupException("Cannot remove item from shared group");
}
}
// Remove shared groups from the param
for (Iterator<String> it=groups.iterator(); it.hasNext();) {
try {
String group = it.next();
// Check if exists a shared group with this name
GroupManager.getInstance().getGroup(group);
// Remove the shared group from the list (since it exists)
it.remove();
}
catch (GroupNotFoundException e) {
// Do nothing since the group is a personal group
}
}
this.groups = groups;
}
}
/**
* Returns the shared groups for the item.
*
* @return The shared groups this item belongs to.
*/
public Collection<String> getSharedGroups() {
return sharedGroups;
}
/**
* Adds a new group to the shared groups list.
*
* @param sharedGroup The shared group to add to the list of shared groups.
*/
public void addSharedGroups(String sharedGroup) {
sharedGroups.add(sharedGroup);
}
/**
* Returns true if this item belongs to a shared group. Return true even if the item belongs
* to a personal group and a shared group.
*
* @return true if this item belongs to a shared group.
*/
public boolean isShared() {
return !sharedGroups.isEmpty();
}
/**
* Returns true if this item belongs ONLY to shared groups. This means that the the item is
* considered to be "only shared" if it doesn't belong to a personal group but only to shared
* groups.
*
* @return true if this item belongs ONLY to shared groups.
*/
public boolean isOnlyShared() {
return !sharedGroups.isEmpty() && groups.isEmpty();
}
/**
* <p>Obtain the roster ID associated with this particular roster item.</p>
* <p/>
......@@ -328,9 +401,9 @@ public class RosterItem implements Cacheable {
*
* @param item The item who's settings will be copied into the cached copy
*/
public void setAsCopyOf(org.xmpp.packet.Roster.Item item) {
setNickname(item.getName());
public void setAsCopyOf(org.xmpp.packet.Roster.Item item) throws SharedGroupException {
setGroups(new LinkedList<String>(item.getGroups()));
setNickname(item.getName());
}
public int getCachedSize() {
......
......@@ -16,6 +16,7 @@ import org.jivesoftware.util.Cache;
import org.jivesoftware.util.CacheManager;
import org.jivesoftware.messenger.container.BasicModule;
import org.jivesoftware.messenger.user.UserNotFoundException;
import org.jivesoftware.messenger.SharedGroupException;
import java.util.Iterator;
......@@ -82,7 +83,12 @@ public class RosterManager extends BasicModule {
}
// Remove each roster item from the user's roster
for (RosterItem item : roster.getRosterItems()) {
roster.deleteRosterItem(item.getJid());
try {
roster.deleteRosterItem(item.getJid(), false);
}
catch (SharedGroupException e) {
// Do nothing. We shouldn't have this exception since we disabled the checkings
}
}
// Remove the cached roster from memory
CacheManager.getCache("username2roster").remove(username);
......@@ -99,7 +105,12 @@ public class RosterManager extends BasicModule {
roster = new Roster(username);
}
// Remove the deleted user reference from this roster
roster.deleteRosterItem(user);
try {
roster.deleteRosterItem(user, false);
}
catch (SharedGroupException e) {
// Do nothing. We shouldn't have this exception since we disabled the checkings
}
}
}
catch (UnsupportedOperationException e) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment