in server/core/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceAvailabilityHandler.java [152:221]
private Stanza handleOutboundUnavailable(PresenceStanza presenceStanza, SessionContext sessionContext,
RosterManager rosterManager, Entity user, ResourceRegistry registry, StanzaBroker stanzaBroker) {
boolean hasTo = presenceStanza.getCoreVerifier().attributePresent("to");
if (hasTo)
return handleOutboundDirectedPresence(presenceStanza, sessionContext, rosterManager, registry, true,
stanzaBroker);
if (!user.isResourceSet())
throw new RuntimeException("resource id not available");
boolean stateChanged = registry.setResourceState(user.getResource(), ResourceState.UNAVAILABLE);
// avoid races from closing connections and unavail presence stanza handlings
// happening quasi-concurrently
if (!stateChanged)
return null;
sessionContext.getServerRuntimeContext().getPresenceCache().remove(user);
SessionContext.SessionTerminationCause terminationCause = null;
if (presenceStanza instanceof EndOfSessionCommandStanza) {
EndOfSessionCommandStanza commandStanza = (EndOfSessionCommandStanza) presenceStanza;
terminationCause = commandStanza.getSessionTerminationCause();
}
// TODO check if we do have to do something about resource priority
List<Entity> contacts = new ArrayList<Entity>();
Map<SubscriptionType, List<RosterItem>> itemMap = RosterUtils.getRosterItemsByState(rosterManager, user);
List<RosterItem> item_FROM = itemMap.get(SubscriptionType.FROM);
List<RosterItem> item_TO = itemMap.get(SubscriptionType.TO);
List<RosterItem> item_BOTH = itemMap.get(SubscriptionType.BOTH);
// broadcast presence from full JID to contacts
// in roster with 'subscription' either 'from' or 'both'
// TODO (for pres updates): ...and last presence stanza received from the
// contact during the user's
// presence session was not of type "error" or "unsubscribe".
List<RosterItem> rosterContacts_FROM = new ArrayList<RosterItem>();
rosterContacts_FROM.addAll(item_FROM);
rosterContacts_FROM.addAll(item_BOTH);
for (RosterItem rosterContact : rosterContacts_FROM) {
contacts.add(rosterContact.getJid());
}
// broadcast unavailable to all directed-presence contacts
Set<Entity> entitySet = getDirectedPresenceMap(sessionContext, user);
if (entitySet != null) {
logger.debug("sending unavailable info to " + entitySet.size() + " directed presence contacts for " + user);
contacts.addAll(entitySet);
entitySet.clear(); // and un-record them
}
// broadcast presence notification to all resources of
// current entity.
List<String> resources = registry.getAvailableResources(user);
if (!SessionContext.SessionTerminationCause.isClientReceivingStanzas(terminationCause)) {
resources.remove(user.getResource());
}
for (String resource : resources) {
Entity otherResource = new EntityImpl(user, resource);
contacts.add(otherResource);
}
// and send them out
relayTo(user, contacts, presenceStanza, stanzaBroker);
return null;
}