Author: berndf
Date: Mon Aug 24 12:31:59 2009
New Revision: 807187
URL: http://svn.apache.org/viewvc?rev=807187&view=rev
Log:
VYSPER-179: change stanza delivery to the highest priorized receiver, instead
of delivering to all possible receivers
VYSPER-181: cover more delivery rules on inbound relay
Added:
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/DeliveredToOfflineReceiverException.java
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/OfflineStanzaReceiver.java
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/ServiceNotAvailableException.java
Modified:
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/DeliveringInboundStanzaRelay.java
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceAvailabilityHandler.java
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanza.java
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanzaType.java
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/state/resourcebinding/ResourceRegistry.java
mina/sandbox/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/state/resourcebinding/ResourceRegistryTestCase.java
Added:
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/DeliveredToOfflineReceiverException.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/DeliveredToOfflineReceiverException.java?rev=807187&view=auto
==============================================================================
---
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/DeliveredToOfflineReceiverException.java
(added)
+++
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/DeliveredToOfflineReceiverException.java
Mon Aug 24 12:31:59 2009
@@ -0,0 +1,22 @@
+package org.apache.vysper.xmpp.delivery;
+
+/**
+ * this class is thrown if message has not been delivered and was haned over
for offline storage
+ */
+public class DeliveredToOfflineReceiverException extends DeliveryException {
+ public DeliveredToOfflineReceiverException() {
+ super();
+ }
+
+ public DeliveredToOfflineReceiverException(String string) {
+ super(string);
+ }
+
+ public DeliveredToOfflineReceiverException(String string, Throwable
throwable) {
+ super(string, throwable);
+ }
+
+ public DeliveredToOfflineReceiverException(Throwable throwable) {
+ super(throwable);
+ }
+}
Modified:
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/DeliveringInboundStanzaRelay.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/DeliveringInboundStanzaRelay.java?rev=807187&r1=807186&r2=807187&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/DeliveringInboundStanzaRelay.java
(original)
+++
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/DeliveringInboundStanzaRelay.java
Mon Aug 24 12:31:59 2009
@@ -19,6 +19,7 @@
*/
package org.apache.vysper.xmpp.delivery;
+import org.apache.vysper.storage.StorageProviderRegistry;
import org.apache.vysper.xmpp.addressing.Entity;
import org.apache.vysper.xmpp.authorization.AccountManagement;
import org.apache.vysper.xmpp.protocol.SessionStateHolder;
@@ -27,24 +28,31 @@
import org.apache.vysper.xmpp.server.SessionContext;
import org.apache.vysper.xmpp.server.SessionState;
import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.stanza.XMPPCoreStanza;
+import org.apache.vysper.xmpp.stanza.IQStanza;
+import org.apache.vysper.xmpp.stanza.PresenceStanza;
+import org.apache.vysper.xmpp.stanza.MessageStanza;
+import org.apache.vysper.xmpp.stanza.MessageStanzaType;
import org.apache.vysper.xmpp.state.resourcebinding.ResourceRegistry;
-import org.apache.vysper.storage.StorageProviderRegistry;
+import org.apache.vysper.compliance.SpecCompliant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.List;
+import java.util.ArrayList;
/**
- * relays stanzas to internal sessions, acts as a 'stage' by using a
ThreadPoolExecutor
- * TODO: re-work the whole relay result
- *
+ * relays all 'incoming' stanzas to internal sessions, acts as a 'stage' by
using a ThreadPoolExecutor
+ * 'incoming' here means:
+ * a. stanzas coming in from other servers
+ * b. stanzas coming from other (local) sessions and are targeted to clients
on this server
+ *
* @author The Apache MINA Project ([email protected])
*/
public class DeliveringInboundStanzaRelay implements StanzaRelay {
@@ -53,9 +61,12 @@
private static final InboundStanzaProtocolWorker
INBOUND_STANZA_PROTOCOL_WORKER = new InboundStanzaProtocolWorker();
+ private static final Integer PRIO_THRESHOLD = 0;
+
protected ResourceRegistry resourceRegistry;
protected ExecutorService executor;
protected AccountManagement accountVerification;
+ protected OfflineStanzaReceiver offlineStanzaReceiver = null;
public DeliveringInboundStanzaRelay(ResourceRegistry resourceRegistry,
StorageProviderRegistry storageProviderRegistry) {
this(resourceRegistry,
(AccountManagement)storageProviderRegistry.retrieve(AccountManagement.class));
@@ -118,49 +129,151 @@
return relayResult;
}
+ /**
+ * @return
+ */
+ @SpecCompliant(spec="draft-ietf-xmpp-3921bis-00", section="8.",
status= SpecCompliant.ComplianceStatus.IN_PROGRESS, coverage =
SpecCompliant.ComplianceCoverage.COMPLETE)
protected RelayResult deliver() {
- List<RelayResult> relayResults = new ArrayList<RelayResult>();
try {
- if (!accountVerification.verifyAccountExists(receiver)) {
- logger.warn("cannot relay to unexisting receiver {} stanza
{}", receiver.getFullQualifiedName(), stanza.toString());
- return new RelayResult(new NoSuchLocalUserException());
- }
- List<SessionContext> receivingSessions =
resourceRegistry.getSessions(receiver);
- if (receivingSessions == null || receivingSessions.size() ==
0) {
- logger.warn("cannot relay to offline receiver {} stanza
{}", receiver.getFullQualifiedName(), stanza.toString());
- return new RelayResult(new
LocalRecipientOfflineException());
+ if (receiver.isResourceSet()) {
+ return deliverToFullJID();
} else {
- relayToSessions(relayResults, receivingSessions);
+ return deliverToBareJID();
}
+
} catch (RuntimeException e) {
return new RelayResult(new DeliveryException(e));
}
+ }
- // TODO handle this properly, don't only return the first failure
- for (RelayResult relayResult : relayResults) {
- if (!relayResult.isRelayed()) return relayResult;
+ @SpecCompliant(spec="draft-ietf-xmpp-3921bis-00", section="8.3.",
status= SpecCompliant.ComplianceStatus.IN_PROGRESS, coverage =
SpecCompliant.ComplianceCoverage.COMPLETE)
+ private RelayResult deliverToBareJID() {
+ XMPPCoreStanza xmppStanza = XMPPCoreStanza.getWrapper(stanza);
+ if (xmppStanza == null) new RelayResult(new
DeliveryException("unable to deliver stanza which is not IQ, presence or
message"));
+
+ if (PresenceStanza.isOfType(stanza)) {
+ return relayToAllSessions();
+ } else if (MessageStanza.isOfType(stanza)) {
+ MessageStanza messageStanza = (MessageStanza)xmppStanza;
+ MessageStanzaType messageStanzaType =
messageStanza.getMessageType();
+ switch (messageStanzaType) {
+ case CHAT:
+ case NORMAL:
+ return relayToBestSession(false);
+
+ case ERROR:
+ // silently ignore
+ return null;
+
+ case GROUPCHAT:
+ return new RelayResult(new
ServiceNotAvailableException());
+
+ case HEADLINE:
+ return relayToAllSessions();
+
+ default:
+ throw new RuntimeException("unhandled message type " +
messageStanzaType.value());
+ }
+ } else if (IQStanza.isOfType(stanza)) {
+ // TODO handle on behalf of the user/client
+ throw new RuntimeException("inbound IQ not yet handled");
}
- return new RelayResult(); // return success result
+
+ return relayNotPossible();
}
- protected void relayToSessions(List<RelayResult> relayResults,
List<SessionContext> receivingSessions) {
- if (receivingSessions.size() > 1) {
- logger.warn("multiplexing: {} sessions will be processing {}
", receivingSessions.size(), stanza);
+ @SpecCompliant(spec="draft-ietf-xmpp-3921bis-00", section="8.2.",
status= SpecCompliant.ComplianceStatus.IN_PROGRESS, coverage =
SpecCompliant.ComplianceCoverage.COMPLETE)
+ private RelayResult deliverToFullJID() {
+ XMPPCoreStanza xmppStanza = XMPPCoreStanza.getWrapper(stanza);
+ if (xmppStanza == null) new RelayResult(new
DeliveryException("unable to deliver stanza which is not IQ, presence or
message"));
+
+ // all special cases are handled by the inbound handlers!
+ if (PresenceStanza.isOfType(stanza)) {
+ // TODO cannot deliver presence with type AVAIL or UNAVAIL:
silently ignore
+ // TODO cannot deliver presence with type SUBSCRIBE: see
3921bis section 3.1.3
+ // TODO cannot deliver presence with type (UN)SUBSCRIBED,
UNSUBSCRIBE: silently ignore
+ return relayToBestSession(false);
+ } else if (MessageStanza.isOfType(stanza)) {
+ MessageStanza messageStanza = (MessageStanza)xmppStanza;
+ MessageStanzaType messageStanzaType =
messageStanza.getMessageType();
+ boolean fallbackToBareJIDAllowed = messageStanzaType ==
MessageStanzaType.CHAT ||
+ messageStanzaType ==
MessageStanzaType.HEADLINE ||
+ messageStanzaType ==
MessageStanzaType.NORMAL;
+ // TODO cannot deliver ERROR: silently ignore
+ // TODO cannot deliver GROUPCHAT: service n/a
+ return relayToBestSession(fallbackToBareJIDAllowed);
+
+ } else if (IQStanza.isOfType(stanza)) {
+ // TODO no resource matches: service n/a
+ return relayToBestSession(false);
}
- for (SessionContext sessionContext : receivingSessions) {
- if (sessionContext.getState() != SessionState.AUTHENTICATED) {
- relayResults.add(new RelayResult(new DeliveryException("no
relay to non-authenticated sessions")));
- continue;
- }
- try {
- StanzaHandler stanzaHandler =
sessionContext.getServerRuntimeContext().getHandler(stanza);
-
INBOUND_STANZA_PROTOCOL_WORKER.processStanza(sessionContext,
sessionStateHolder, stanza, stanzaHandler);
- } catch (Exception e) {
- // TODO do not break out here. we should try to deliver to
the others first!
- relayResults.add(new RelayResult(new
DeliveryException(e)));
- }
+
+ // for any other type of stanza
+ return new RelayResult(new ServiceNotAvailableException());
+ }
+
+ private RelayResult relayNotPossible() {
+ if (!accountVerification.verifyAccountExists(receiver)) {
+ logger.warn("cannot relay to unexisting receiver {} stanza
{}", receiver.getFullQualifiedName(), stanza.toString());
+ return new RelayResult(new NoSuchLocalUserException());
+ } else if (offlineStanzaReceiver != null) {
+ offlineStanzaReceiver.receive(stanza);
+ return new RelayResult(new
DeliveredToOfflineReceiverException());
+ } else {
+ logger.warn("cannot relay to offline receiver {} stanza {}",
receiver.getFullQualifiedName(), stanza.toString());
+ return new RelayResult(new LocalRecipientOfflineException());
}
}
+
+ protected RelayResult relayToBestSession(final boolean
fallbackToBareJIDAllowed) {
+ SessionContext receivingSession =
resourceRegistry.getHighestPrioSession(receiver, PRIO_THRESHOLD);
+
+ if (receivingSession == null && receiver.isResourceSet() &&
fallbackToBareJIDAllowed) {
+ // no concrete session for this resource has been found
+ // fall back to bare JID
+ receivingSession =
resourceRegistry.getHighestPrioSession(receiver.getBareJID(), PRIO_THRESHOLD);
+ }
+
+ if (receivingSession == null) {
+ return relayNotPossible();
+ }
+
+ if (receivingSession.getState() != SessionState.AUTHENTICATED) {
+ return new RelayResult(new DeliveryException("no relay to
non-authenticated sessions"));
+ }
+ try {
+ StanzaHandler stanzaHandler =
receivingSession.getServerRuntimeContext().getHandler(stanza);
+ INBOUND_STANZA_PROTOCOL_WORKER.processStanza(receivingSession,
sessionStateHolder, stanza, stanzaHandler);
+ } catch (Exception e) {
+ return new RelayResult(new DeliveryException(e));
+ }
+ return new RelayResult(); // return success result
+ }
+
+ protected RelayResult relayToAllSessions() {
+ // the individual results are currently only recorded pro forma
+ List<RelayResult> relayResults = new ArrayList<RelayResult>();
+
+ List<SessionContext> receivingSessions =
resourceRegistry.getSessions(receiver);
+
+ if (receivingSessions.size() > 1) {
+ logger.warn("multiplexing: {} sessions will be processing {}
", receivingSessions.size(), stanza);
+ }
+ for (SessionContext sessionContext : receivingSessions) {
+ if (sessionContext.getState() != SessionState.AUTHENTICATED) {
+ relayResults.add(new RelayResult(new
DeliveryException("no relay to non-authenticated sessions")));
+ continue;
+ }
+ try {
+ StanzaHandler stanzaHandler =
sessionContext.getServerRuntimeContext().getHandler(stanza);
+
INBOUND_STANZA_PROTOCOL_WORKER.processStanza(sessionContext,
sessionStateHolder, stanza, stanzaHandler);
+ } catch (Exception e) {
+ relayResults.add(new RelayResult(new
DeliveryException(e)));
+ }
+ }
+
+ return new RelayResult(); // return success result
+ }
}
private static class UnmodifyableSessionStateHolder extends
SessionStateHolder {
Added:
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/OfflineStanzaReceiver.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/OfflineStanzaReceiver.java?rev=807187&view=auto
==============================================================================
---
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/OfflineStanzaReceiver.java
(added)
+++
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/OfflineStanzaReceiver.java
Mon Aug 24 12:31:59 2009
@@ -0,0 +1,13 @@
+package org.apache.vysper.xmpp.delivery;
+
+import org.apache.vysper.xmpp.stanza.Stanza;
+
+/**
+ * receives stanzas addressed to offline receivers
+ * TODO: this is more or less a placeholder interface currently.
+ */
+public interface OfflineStanzaReceiver {
+
+ public void receive(Stanza stanza);
+
+}
Added:
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/ServiceNotAvailableException.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/ServiceNotAvailableException.java?rev=807187&view=auto
==============================================================================
---
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/ServiceNotAvailableException.java
(added)
+++
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/ServiceNotAvailableException.java
Mon Aug 24 12:31:59 2009
@@ -0,0 +1,21 @@
+package org.apache.vysper.xmpp.delivery;
+
+/**
+ */
+public class ServiceNotAvailableException extends DeliveryException {
+ public ServiceNotAvailableException() {
+ super();
+ }
+
+ public ServiceNotAvailableException(String string) {
+ super(string);
+ }
+
+ public ServiceNotAvailableException(String string, Throwable throwable) {
+ super(string, throwable);
+ }
+
+ public ServiceNotAvailableException(Throwable throwable) {
+ super(throwable);
+ }
+}
Modified:
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceAvailabilityHandler.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceAvailabilityHandler.java?rev=807187&r1=807186&r2=807187&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceAvailabilityHandler.java
(original)
+++
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceAvailabilityHandler.java
Mon Aug 24 12:31:59 2009
@@ -200,7 +200,8 @@
rosterManager, user, registry);
if (!user.isResourceSet()) throw new RuntimeException("resource id not
available");
- ResourceState resourceState =
registry.getResourceState(user.getResource());
+ String resourceId = user.getResource();
+ ResourceState resourceState = registry.getResourceState(resourceId);
boolean isPresenceUpdate = resourceState != null &&
ResourceState.isAvailable(resourceState);
@@ -213,11 +214,14 @@
// things to be done for initial presence
// set resource state
- ResourceState currentState =
registry.getResourceState(user.getResource());
+ ResourceState currentState = registry.getResourceState(resourceId);
// set to AVAILABLE, but do not override AVAILABLE_INTERESTED
- registry.setResourceState(user.getResource(),
ResourceState.makeAvailable(currentState));
+ registry.setResourceState(resourceId,
ResourceState.makeAvailable(currentState));
}
- updateResourcePriority(registry, sessionContext.getInitiatingEntity(),
presenceStanza.getPrioritySafe());
+
+ // the presence priority is optional, but if contained, it might
become relevant for
+ // message delivery (see RFC3921bis-05#8.3.1.1)
+ registry.setResourcePriority(resourceId,
presenceStanza.getPrioritySafe());
List<Entity> contacts = new ArrayList<Entity>();
@@ -365,15 +369,6 @@
return stanza;
}
- /**
- * the presence priority is optional, but if contained, it might become
relevant for
- * message delivery (see RFC3921bis-05#8.3.1.1)
- */
- private void updateResourcePriority(ResourceRegistry registry, Entity
initiatingEntity, int priority) {
- if (initiatingEntity == null || initiatingEntity.getResource() ==
null) return;
- registry.setResourcePriority(initiatingEntity.getResource(), priority);
- }
-
private void relayTo(Entity from, List<Entity> tos, PresenceStanza
original, SessionContext sessionContext) {
List<Attribute> toFromReplacements = new ArrayList<Attribute>();
toFromReplacements.add(new Attribute("from",
from.getFullQualifiedName()));
Modified:
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanza.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanza.java?rev=807187&r1=807186&r2=807187&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanza.java
(original)
+++
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanza.java
Mon Aug 24 12:31:59 2009
@@ -54,7 +54,6 @@
public MessageStanzaType getMessageType() {
String type = getType();
- if (type == null) return null;
return MessageStanzaType.valueOfWithDefault(type);
}
Modified:
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanzaType.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanzaType.java?rev=807187&r1=807186&r2=807187&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanzaType.java
(original)
+++
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanzaType.java
Mon Aug 24 12:31:59 2009
@@ -39,6 +39,7 @@
* given
*/
public static MessageStanzaType valueOfWithDefault(String value) {
+ if (value == null) return NORMAL;
try {
return MessageStanzaType.valueOf(value.toUpperCase());
} catch (IllegalArgumentException e) {
Modified:
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/state/resourcebinding/ResourceRegistry.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/state/resourcebinding/ResourceRegistry.java?rev=807187&r1=807186&r2=807187&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/state/resourcebinding/ResourceRegistry.java
(original)
+++
mina/sandbox/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/state/resourcebinding/ResourceRegistry.java
Mon Aug 24 12:31:59 2009
@@ -109,7 +109,8 @@
resourceForEntityList);
}
resourceForEntityList.add(resourceId);
- logger.info("added resource no. " +
resourceForEntityList.size() + " to entity {} <- {}",
initiatingEntity.getFullQualifiedName(), resourceId);
+ logger.info("added resource no. " +
resourceForEntityList.size() + " to entity {} <- {}",
+ initiatingEntity.getFullQualifiedName(),
resourceId);
List<String> resourcesForSessionList =
sessionResources.get(sessionContext);
if (resourcesForSessionList == null) {
@@ -117,7 +118,8 @@
sessionResources.put(sessionContext,
resourcesForSessionList);
}
resourcesForSessionList.add(resourceId);
- logger.info("added resource no. " +
resourcesForSessionList.size() + " to session {} <- {}",
sessionContext.getSessionId(), resourceId);
+ logger.info("added resource no. " +
resourcesForSessionList.size() + " to session {} <- {}",
+ sessionContext.getSessionId(), resourceId);
}
}
}
@@ -276,6 +278,45 @@
return sessionContexts;
}
+
+ /**
+ * retrieves the highest priorizes session for this entity.
+ *
+ * @param entity if this is not a bare JID, only the session for the JID's
resource part will be returned, without
+ * looking at other sessions for the resource's bare JID. otherwise, in
case of a full JID, it will return the
+ * highest priorized session.
+ * @param prioThreshold if not NULL, only resources will be returned
having same or higher priority. a common value
+ * for the threshold is 0 (zero).
+ * @return for a bare JID, it will return the hightest priorized session.
for a full JID, it will return the
+ * related session.
+ */
+ public SessionContext getHighestPrioSession(Entity entity, Integer
prioThreshold) {
+ Integer currentPrio = Integer.MIN_VALUE;
+ SessionData result = null;
+
+ boolean isResourceSet = entity.isResourceSet();
+
+ List<String> boundResourceIds = getBoundResources(entity, false);
+ for (String resourceId : boundResourceIds) {
+ SessionData sessionData = boundResources.get(resourceId);
+ if (sessionData == null) continue;
+
+ if (isResourceSet) return sessionData.context; // no prio checks,
take the first proper one
+
+ if (sessionData.priority > currentPrio) {
+ currentPrio = sessionData.priority;
+ result = sessionData;
+ }
+ }
+
+ if (prioThreshold != null && prioThreshold > currentPrio) {
+ // no session over threshold
+ return null;
+ }
+
+ return result == null ? null : result.context;
+ }
+
/**
* Sets the {...@link ResourceState} for the given resource.
*
Modified:
mina/sandbox/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/state/resourcebinding/ResourceRegistryTestCase.java
URL:
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/state/resourcebinding/ResourceRegistryTestCase.java?rev=807187&r1=807186&r2=807187&view=diff
==============================================================================
---
mina/sandbox/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/state/resourcebinding/ResourceRegistryTestCase.java
(original)
+++
mina/sandbox/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/state/resourcebinding/ResourceRegistryTestCase.java
Mon Aug 24 12:31:59 2009
@@ -75,9 +75,11 @@
TestSessionContext sessionContext1 =
TestSessionContext.createSessionContext(entity);
String resourceId1 = resourceRegistry.bindSession(sessionContext1);
+ resourceRegistry.setResourcePriority(resourceId1, -1);
TestSessionContext sessionContext2 =
TestSessionContext.createSessionContext(entity);
String resourceId2 = resourceRegistry.bindSession(sessionContext2);
+ resourceRegistry.setResourcePriority(resourceId2, 1);
assertNotNull(resourceId1);
assertNotNull(resourceId2);
@@ -91,6 +93,20 @@
assertEquals(2, resourceList.size());
assertTrue(sessionList.contains(sessionContext1));
assertTrue(sessionList.contains(sessionContext2));
+
+ SessionContext hightestPrioSession =
resourceRegistry.getHighestPrioSession(entity, null);
+ assertSame(resourceRegistry.getSessionContext(resourceId2),
hightestPrioSession);
+
+ resourceRegistry.setResourcePriority(resourceId1, 2); // make this
highes prio
+ hightestPrioSession = resourceRegistry.getHighestPrioSession(entity,
null);
+ assertSame(resourceRegistry.getSessionContext(resourceId1),
hightestPrioSession);
+
+ hightestPrioSession = resourceRegistry.getHighestPrioSession(entity,
2); // still highest prio
+ assertSame(resourceRegistry.getSessionContext(resourceId1),
hightestPrioSession);
+
+ hightestPrioSession = resourceRegistry.getHighestPrioSession(entity,
3); // now, all prios are below threshold
+ assertNull(hightestPrioSession);
+
}
public void testAddOneEntityMultipleResources_TolerateResourceIds() throws
EntityFormatException {