📄 roster.java
字号:
* Create a new item to the roster based as a copy of the given item.
* Roster items may not be created that contain the same user address
* as an existing item in the roster.
*
* @param item the item to copy and add to the roster.
*/
public void createRosterItem(org.xmpp.packet.Roster.Item item)
throws UserAlreadyExistsException, SharedGroupException {
provideRosterItem(item.getJID(), item.getName(), new ArrayList<String>(item.getGroups()), true, true);
}
/**
* Generate a new RosterItem for use with createRosterItem.
*
* @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).
* @param push True if the new item must be push to the user.
* @param persistent True if the new roster item should be persisted to the DB.
* @return The newly created roster items ready to be stored by the Roster item's hash table
*/
protected RosterItem provideRosterItem(JID user, String nickname, List<String> groups,
boolean push, boolean persistent)
throws UserAlreadyExistsException, SharedGroupException {
if (groups != null && !groups.isEmpty()) {
// Raise an error if the groups the item belongs to include a shared group
Collection<Group> sharedGroups = GroupManager.getInstance().getSharedGroups();
for (String group : groups) {
for (Group sharedGroup : sharedGroups) {
if (group.equals(sharedGroup.getProperties().get("sharedRoster.displayName"))) {
throw new SharedGroupException("Cannot add an item to a shared group");
}
}
}
}
org.xmpp.packet.Roster roster = new org.xmpp.packet.Roster();
roster.setType(IQ.Type.set);
org.xmpp.packet.Roster.Item item = roster.addItem(user, nickname, null,
org.xmpp.packet.Roster.Subscription.none, groups);
RosterItem rosterItem = new RosterItem(item);
// Fire event indicating that a roster item is about to be added
persistent = RosterEventDispatcher.addingContact(this, rosterItem, persistent);
// Check if we need to make the new roster item persistent
if (persistent) {
rosterItemProvider.createItem(username, rosterItem);
}
if (push) {
// Broadcast the roster push to the user
broadcast(roster);
}
rosterItems.put(user.toBareJID(), rosterItem);
// Fire event indicating that a roster item has been added
RosterEventDispatcher.contactAdded(this, rosterItem);
return rosterItem;
}
/**
* Update an item that is already in the roster.
*
* @param item the item to update in the roster.
* @throws UserNotFoundException If the roster item for the given user doesn't already exist
*/
public void updateRosterItem(RosterItem item) throws UserNotFoundException {
// Check if we need to convert an implicit roster item into an explicit one
if (implicitFrom.remove(item.getJid().toBareJID()) != null) {
// Ensure that the item is an explicit roster item
rosterItems.put(item.getJid().toBareJID(), item);
// Fire event indicating that a roster item has been updated
RosterEventDispatcher.contactUpdated(this, item);
}
if (rosterItems.putIfAbsent(item.getJid().toBareJID(), item) == null) {
rosterItems.remove(item.getJid().toBareJID());
if (item.getSubStatus() != RosterItem.SUB_NONE) {
throw new UserNotFoundException(item.getJid().toBareJID());
}
return;
}
// Check if the item is not persistent
if (item.getID() == 0) {
// Make the item persistent if a new nickname has been set for a shared contact
if (item.isShared()) {
// Do nothing if item is only shared and it is using the default user name
if (item.isOnlyShared()) {
String defaultContactName;
try {
defaultContactName = UserNameManager.getUserName(item.getJid());
}
catch (UserNotFoundException e) {
// Cannot update a roster item for a local user that does not exist
defaultContactName = item.getNickname();
}
if (defaultContactName.equals(item.getNickname())) {
return;
}
}
try {
rosterItemProvider.createItem(username, item);
}
catch (UserAlreadyExistsException e) {
// Do nothing. We shouldn't be here.
}
}
else {
// Item is not persistent and it does not belong to a shared contact so do nothing
}
}
else {
// Update the backend data store
rosterItemProvider.updateItem(username, item);
}
// broadcast roster update
// Do not push items with a state of "None + Pending In"
if (item.getSubStatus() != RosterItem.SUB_NONE ||
item.getRecvStatus() != RosterItem.RECV_SUBSCRIBE) {
broadcast(item, true);
}
/*if (item.getSubStatus() == RosterItem.SUB_BOTH || item.getSubStatus() == RosterItem.SUB_TO) {
probePresence(item.getJid());
}*/
// Fire event indicating that a roster item has been updated
RosterEventDispatcher.contactUpdated(this, item);
}
/**
* Remove a user from the roster.
*
* @param user the user to remove from the roster.
* @param doChecking flag that indicates if checkings should be done before deleting the user.
* @return The roster item being removed or null if none existed
* @throws SharedGroupException if the user to remove belongs to a shared group
*/
public RosterItem deleteRosterItem(JID user, boolean doChecking) throws SharedGroupException {
// Answer an error if user (i.e. contact) to delete belongs to a shared group
RosterItem itemToRemove = rosterItems.get(user.toBareJID());
if (doChecking && itemToRemove != null && !itemToRemove.getSharedGroups().isEmpty()) {
throw new SharedGroupException("Cannot remove contact that belongs to a shared group");
}
if (itemToRemove != null) {
RosterItem.SubType subType = itemToRemove.getSubStatus();
// Cancel any existing presence subscription between the user and the contact
if (subType == RosterItem.SUB_TO || subType == RosterItem.SUB_BOTH) {
Presence presence = new Presence();
presence.setFrom(server.createJID(username, null));
presence.setTo(itemToRemove.getJid());
presence.setType(Presence.Type.unsubscribe);
server.getPacketRouter().route(presence);
}
// cancel any existing presence subscription between the contact and the user
if (subType == RosterItem.SUB_FROM || subType == RosterItem.SUB_BOTH) {
Presence presence = new Presence();
presence.setFrom(server.createJID(username, null));
presence.setTo(itemToRemove.getJid());
presence.setType(Presence.Type.unsubscribed);
server.getPacketRouter().route(presence);
}
// If removing the user was successful, remove the user from the subscriber list:
RosterItem item = rosterItems.remove(user.toBareJID());
if (item != null) {
// Delete the item from the provider if the item is persistent. RosteItems that only
// belong to shared groups won't be persistent
if (item.getID() > 0) {
// If removing the user was successful, remove the user from the backend store
rosterItemProvider.deleteItem(username, item.getID());
}
// Broadcast the update to the user
org.xmpp.packet.Roster roster = new org.xmpp.packet.Roster();
roster.setType(IQ.Type.set);
roster.addItem(user, org.xmpp.packet.Roster.Subscription.remove);
broadcast(roster);
// Fire event indicating that a roster item has been deleted
RosterEventDispatcher.contactDeleted(this, item);
}
return item;
}
else {
// Verify if the item being removed is an implicit roster item
// that only exists due to some shared group
RosterItem item = getImplicitRosterItem(user);
if (item != null) {
implicitFrom.remove(user.toBareJID());
// If the contact being removed is not a local user then ACK unsubscription
if (!server.isLocal(user)) {
Presence presence = new Presence();
presence.setFrom(server.createJID(username, null));
presence.setTo(user);
presence.setType(Presence.Type.unsubscribed);
server.getPacketRouter().route(presence);
}
// Fire event indicating that a roster item has been deleted
RosterEventDispatcher.contactDeleted(this, item);
}
}
return null;
}
/**
* <p>Return the username of the user or chatbot that owns this roster.</p>
*
* @return the username of the user or chatbot that owns this roster
*/
public String getUsername() {
return username;
}
/**
* <p>Obtain a 'roster reset', a snapshot of the full cached roster as an Roster.</p>
*
* @return The roster reset (snapshot) as an Roster
*/
public org.xmpp.packet.Roster getReset() {
org.xmpp.packet.Roster roster = new org.xmpp.packet.Roster();
// Add the roster items (includes the personal roster and shared groups) to the answer
for (RosterItem item : rosterItems.values()) {
// Do not include items with status FROM that exist only because of shared groups
if (item.isOnlyShared() && item.getSubStatus() == RosterItem.SUB_FROM) {
continue;
}
org.xmpp.packet.Roster.Ask ask = getAskStatus(item.getAskStatus());
org.xmpp.packet.Roster.Subscription sub = org.xmpp.packet.Roster.Subscription.valueOf(item.getSubStatus()
.getName());
// Set the groups to broadcast (include personal and shared groups)
List<String> groups = new ArrayList<String>(item.getGroups());
if (groups.contains(null)) {
Log.warn("A group is null in roster item: " + item.getJid() + " of user: " +
getUsername());
}
for (Group sharedGroup : item.getSharedGroups()) {
String displayName = sharedGroup.getProperties().get("sharedRoster.displayName");
if (displayName != null) {
groups.add(displayName);
}
else {
// Do not add the shared group if it does not have a displayName.
Log.warn("Found shared group: " + sharedGroup.getName() +
" with no displayName");
}
}
// Do not push items with a state of "None + Pending In"
if (item.getSubStatus() != RosterItem.SUB_NONE ||
item.getRecvStatus() != RosterItem.RECV_SUBSCRIBE) {
roster.addItem(item.getJid(), item.getNickname(), ask, sub, groups);
}
}
return roster;
}
private org.xmpp.packet.Roster.Ask getAskStatus(RosterItem.AskType askType) {
if (askType == null || "".equals(askType.getName())) {
return null;
}
return org.xmpp.packet.Roster.Ask.valueOf(askType.getName());
}
/**
* <p>Broadcast the presence update to all subscribers of the roter.</p>
* <p/>
* <p>Any presence change typically results in a broadcast to the roster members.</p>
*
* @param packet The presence packet to broadcast
*/
public void broadcastPresence(Presence packet) {
if (routingTable == null) {
return;
}
// Get the privacy list of this user
PrivacyList list = null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -