You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by be...@apache.org on 2008/10/23 07:42:20 UTC

svn commit: r707278 - in /labs/vysper/src/main/java/org/apache/vysper/xmpp: modules/core/im/handler/ modules/roster/ modules/roster/handler/ resourcebinding/

Author: berndf
Date: Wed Oct 22 22:42:20 2008
New Revision: 707278

URL: http://svn.apache.org/viewvc?rev=707278&view=rev
Log:
[vysper] roster set, presence cancel + unsubscribe

Modified:
    labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceSubscriptionHandler.java
    labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterItem.java
    labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutator.java
    labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/handler/RosterIQHandler.java
    labs/vysper/src/main/java/org/apache/vysper/xmpp/resourcebinding/ResourceState.java

Modified: labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceSubscriptionHandler.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceSubscriptionHandler.java?rev=707278&r1=707277&r2=707278&view=diff
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceSubscriptionHandler.java (original)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceSubscriptionHandler.java Wed Oct 22 22:42:20 2008
@@ -171,24 +171,41 @@
  */
     @SpecCompliant(spec = "RFC3921bis-04", section = "3.3.3")
 	protected void handleInboundUnsubscription(PresenceStanza stanza, SessionContext sessionContext, ResourceRegistry registry, RosterManager rosterManager) {
-		Entity contact = stanza.getFrom();
-		Entity user = stanza.getTo();
+        Entity contact = stanza.getFrom();
+        Entity user = stanza.getTo();
 
-		// TODO: remove subscription from user to contact
+        Entity userBareJid = user.getBareJID();
+        Entity contactBareJid = contact.getBareJID();
 
-        // write inbound stanza to the user 
+        RosterItem rosterItem;
+        try {
+            rosterItem = rosterManager.getContact(userBareJid, contactBareJid);
+        } catch (RosterException e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
+
+        if (rosterItem == null) return;
+
+        RosterSubscriptionMutator.Result result = RosterSubscriptionMutator.getInstance().remove(rosterItem, FROM);
+
+        if (result != OK) {
+            // TODO
+            return;
+        }
+
+        // write inbound stanza to the user
         sessionContext.getResponseWriter().write(stanza);
 
-		List<String> resources = registry.getInterestedResources(user);
-		for (String resource : resources) {
-			Entity userResource = new EntityImpl(user, resource);
-			// TODO: determine the right subscription: 'none' or 'to'
-			Stanza push = buildRosterPushStanza(userResource,
-					sessionContext.nextSequenceValue(), contact.getBareJID(),
-					null /* TODO subType*/, null /*TODO ask? */);
+        // send roster push to all interested resources
+        // TODO do this only once, since inbound is multiplexed on DeliveringInboundStanzaRelay level already
+        List<String> resources = registry.getInterestedResources(user);
+        for (String resource : resources) {
+            Entity userResource = new EntityImpl(user, resource);
+            Stanza push = buildRosterPushStanza(userResource, sessionContext.nextSequenceValue(), rosterItem);
+            sessionContext.getResponseWriter().write(push);
+        }
 
-			relayStanza(userResource, push, sessionContext);
-		}
 	}
 
 /*
@@ -238,79 +255,118 @@
 	@SpecCompliant(spec = "RFC3921bis-04", section = "3.3.2")
 	protected void handleOutboundUnsubscription(PresenceStanza stanza,
                                              SessionContext sessionContext, ResourceRegistry registry, RosterManager rosterManager) {
-		Entity user = stanza.getFrom();
-		Entity contact = stanza.getTo();
+        Entity user = stanza.getFrom();
+        Entity contact = stanza.getTo();
 
-		relayStanza(contact, stanza, sessionContext);
+        Entity userBareJid = user.getBareJID();
+        Entity contactBareJid = contact.getBareJID();
 
-		List<String> resources = registry.getInterestedResources(user);
-		for (String resource : resources) {
-			Entity userResource = new EntityImpl(user, resource);
-			// TODO: determine the correct subscription state: 'none' or 'from'
-			Stanza push = buildRosterPushStanza(userResource,
-					sessionContext.nextSequenceValue(), contact.getBareJID(),
-					null /* TODO subType*/, null /*TODO ask? */);
-			relayStanza(userResource, push, sessionContext);
-		}
+        relayStanza(contact, stanza, sessionContext);
 
-	}
+        RosterItem rosterItem = null;
+        try {
+            rosterItem = rosterManager.getContact(userBareJid, contactBareJid);
+        } catch (RosterException e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
 
-/*
-FROM: http://www.xmpp.org/internet-drafts/draft-saintandre-rfc3921bis-05.txt
+        if (rosterItem == null) return;
 
-3.2.3.  Server Processing of Inbound Subscription Cancellation
+        RosterSubscriptionMutator.Result result = RosterSubscriptionMutator.getInstance().remove(rosterItem, TO);
 
-   When the user's server receives the inbound subscription
-   cancellation, it MUST modify the subscription state and send a roster
-   push to the user's interested resources, where the subscription state
-   is now either "none" or "from" (see Appendix A).
+        if (result != OK) {
+            // TODO
+            return;
+        }
 
-   US: <iq to='romeo@example.net/foo'
-           type='set'
-           id='h37h3u1bv400'>
-         <query xmlns='jabber:iq:roster'>
-           <item jid='juliet@example.com'
-                 subscription='none'/>
-         </query>
-       </iq>
+        relayStanza(contact, stanza, sessionContext);
 
-   US: <iq to='romeo@example.net/bar'
-           type='set'
-           id='h37h3u1bv401'>
-         <query xmlns='jabber:iq:roster'>
-           <item jid='juliet@example.com'
-                 subscription='none'/>
-           </item>
-         </query>
-       </iq>
+        sendRosterUpdate(sessionContext, registry, user, rosterItem);
+    }
 
+    /**
+     * send roster push to all of the user's interested resources
+     */
+    protected void sendRosterUpdate(SessionContext sessionContext, ResourceRegistry registry, Entity user, RosterItem rosterItem) {
+        List<String> resources = registry.getInterestedResources(user);
 
- */
+        for (String resource : resources) {
+            Entity userResource = new EntityImpl(user, resource);
+            Stanza push = buildRosterPushStanza(userResource, sessionContext.nextSequenceValue(), rosterItem);
+            relayStanza(userResource, push, sessionContext);
+        }
+    }
+
+    /*
+   FROM: http://www.xmpp.org/internet-drafts/draft-saintandre-rfc3921bis-05.txt
+   
+   3.2.3.  Server Processing of Inbound Subscription Cancellation
+   
+      When the user's server receives the inbound subscription
+      cancellation, it MUST modify the subscription state and send a roster
+      push to the user's interested resources, where the subscription state
+      is now either "none" or "from" (see Appendix A).
+   
+      US: <iq to='romeo@example.net/foo'
+              type='set'
+              id='h37h3u1bv400'>
+            <query xmlns='jabber:iq:roster'>
+              <item jid='juliet@example.com'
+                    subscription='none'/>
+            </query>
+          </iq>
+   
+      US: <iq to='romeo@example.net/bar'
+              type='set'
+              id='h37h3u1bv401'>
+            <query xmlns='jabber:iq:roster'>
+              <item jid='juliet@example.com'
+                    subscription='none'/>
+              </item>
+            </query>
+          </iq>
+   
+   
+    */
     @SpecCompliant(spec = "RFC3921bis-04", section = "3.2.3")
 	protected void handleInboundSubscriptionCancellation(PresenceStanza stanza,
                                                       SessionContext sessionContext, ResourceRegistry registry, RosterManager rosterManager) {
 
-        // TODO: check if client actually requested subscription
-		// TODO: update roster for user
-		// TODO: if current subscription is either 'both' or
+        Entity contact = stanza.getFrom();
+        Entity user = stanza.getTo();
 
-        // write inbound stanza to the user 
+        Entity userBareJid = user.getBareJID();
+        Entity contactBareJid = contact.getBareJID();
+
+        RosterItem rosterItem;
+        try {
+            rosterItem = rosterManager.getContact(userBareJid, contactBareJid);
+        } catch (RosterException e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
+
+        if (rosterItem == null) return;
+
+        RosterSubscriptionMutator.Result result = RosterSubscriptionMutator.getInstance().remove(rosterItem, TO);
+
+        if (result != OK) {
+            // TODO
+            return;
+        }
+
+        // write inbound stanza to the user
         sessionContext.getResponseWriter().write(stanza);
-    
-    
-		Entity contact = stanza.getFrom();
-		Entity user = stanza.getTo();
 
-        // TODO do this only once, since inbound is multiplexed on DeliveringInboundStanzaRelay level already 
-		List<String> resources = registry.getInterestedResources(user);
-		for (String resource : resources) {
-			Entity userResource = new EntityImpl(user, resource);
-			// TODO: determine the correct subscription state
-			Stanza push = buildRosterPushStanza(userResource,
-					sessionContext.nextSequenceValue(), contact.getBareJID(),
-					null /* TODO subType*/, null /*TODO ask? */);
+        // send roster push to all interested resources
+        // TODO do this only once, since inbound is multiplexed on DeliveringInboundStanzaRelay level already
+        List<String> resources = registry.getInterestedResources(user);
+        for (String resource : resources) {
+            Entity userResource = new EntityImpl(user, resource);
+            Stanza push = buildRosterPushStanza(userResource, sessionContext.nextSequenceValue(), rosterItem);
             sessionContext.getResponseWriter().write(push);
-		}
+        }
 	}
 
 /*
@@ -362,19 +418,30 @@
 		Entity user = stanza.getFrom();
 		Entity contact = stanza.getTo();
 
-		relayStanza(contact, stanza, sessionContext);
+        Entity userBareJid = user.getBareJID();
+        Entity contactBareJid = contact.getBareJID();
+        
+        RosterItem rosterItem = null;
+        try {
+            rosterItem = rosterManager.getContact(userBareJid, contactBareJid);
+        } catch (RosterException e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
 
-		// send roster push to all of the user's interested resources
-		List<String> resources = registry.getInterestedResources(user);
-		for (String resource : resources) {
-			Entity userResource = new EntityImpl(user, resource);
-			// TODO: determine the right subscription: 'to' or 'none'
-			Stanza push = buildRosterPushStanza(userResource,
-					sessionContext.nextSequenceValue(), contact.getBareJID(),
-					null /* TODO subType*/, null /*TODO ask? */);
+        if (rosterItem == null) return;
+    
+        RosterSubscriptionMutator.Result result = RosterSubscriptionMutator.getInstance().remove(rosterItem, FROM);
 
-			relayStanza(userResource, push, sessionContext);
-		}
+        if (result != OK) {
+            // TODO
+            return;
+        }
+
+        relayStanza(contact, stanza, sessionContext);
+
+        // send roster push to all of the user's interested resources
+        sendRosterUpdate(sessionContext, registry, user, rosterItem);
 	}
 
     
@@ -461,17 +528,11 @@
         relayStanza(contact, stanza, sessionContext);
 
         // send roster push to all of the user's interested resources
-		List<String> resources = registry.getInterestedResources(user);
-
-		for (String resource : resources) {
-			Entity userResource = new EntityImpl(user, resource);
-			Stanza push = buildRosterPushStanza(userResource, sessionContext.nextSequenceValue(), rosterItem);
-			relayStanza(userResource, push, sessionContext);
-		}
+        sendRosterUpdate(sessionContext, registry, user, rosterItem);
 
 		// send presence information from user's available resource to the
 		// contact
-		resources = registry.getAvailableResources(user);
+        List<String> resources = registry.getAvailableResources(user);
 		for (String resource : resources) {
 			Entity userResource = new EntityImpl(user, resource);
             // TODO check: send real presence, or initial pres?

Modified: labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterItem.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterItem.java?rev=707278&r1=707277&r2=707278&view=diff
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterItem.java (original)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterItem.java Wed Oct 22 22:42:20 2008
@@ -50,6 +50,11 @@
         this.askSubscriptionType = askSubscriptionType == null ? NOT_SET : askSubscriptionType;
     }
 
+    public RosterItem(Entity jid, String name, SubscriptionType subscriptionType, AskSubscriptionType askSubscriptionType, List<RosterGroup> groups) {
+        this(jid, name, subscriptionType, askSubscriptionType);
+        this.groups.addAll(groups);
+    }
+
     public Entity getJid() {
         return jid;
     }

Modified: labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutator.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutator.java?rev=707278&r1=707277&r2=707278&view=diff
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutator.java (original)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutator.java Wed Oct 22 22:42:20 2008
@@ -150,9 +150,9 @@
             case REMOVE:
                 return Result.ILLEGAL_ARGUMENT;
             case FROM:
-                return removeTo(item);
-            case TO:
                 return removeFrom(item);
+            case TO:
+                return removeTo(item);
             default:
                 throw new IllegalArgumentException("unhandled SubscriptionType " + removeSubscriptionType.value());
         }
@@ -160,7 +160,13 @@
 
     protected Result removeTo(RosterItem item) {
         SubscriptionType type = item.getSubscriptionType();
-        if (!type.includesTo()) return ALREADY_SET;
+        if (!type.includesTo()) {
+            // if sub was asked, remove that.
+            AskSubscriptionType askType = item.getAskSubscriptionType();
+            if (askType != ASK_SUBSCRIBE) return ALREADY_SET;
+            item.setAskSubscriptionType(NOT_SET);
+            return OK;
+        }
         if (type == BOTH) {
             type = FROM;
         } else if (type == TO) {
@@ -172,7 +178,13 @@
 
     protected Result removeFrom(RosterItem item) {
         SubscriptionType type = item.getSubscriptionType();
-        if (!type.includesFrom()) return ALREADY_SET;
+        if (!type.includesFrom()) {
+            // if sub was asked, remove that.
+            AskSubscriptionType askType = item.getAskSubscriptionType();
+            if (askType != ASK_SUBSCRIBED) return ALREADY_SET;
+            item.setAskSubscriptionType(NOT_SET);
+            return OK;
+        }
         if (type == BOTH) {
             type = TO;
         } else if (type == FROM) {

Modified: labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/handler/RosterIQHandler.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/handler/RosterIQHandler.java?rev=707278&r1=707277&r2=707278&view=diff
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/handler/RosterIQHandler.java (original)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/handler/RosterIQHandler.java Wed Oct 22 22:42:20 2008
@@ -18,9 +18,7 @@
 package org.apache.vysper.xmpp.modules.roster.handler;
 
 import org.apache.vysper.xmpp.modules.core.base.handler.IQHandler;
-import org.apache.vysper.xmpp.modules.roster.Roster;
-import org.apache.vysper.xmpp.modules.roster.RosterException;
-import org.apache.vysper.xmpp.modules.roster.RosterStanzaUtils;
+import org.apache.vysper.xmpp.modules.roster.*;
 import org.apache.vysper.xmpp.modules.roster.persistence.RosterManager;
 import org.apache.vysper.xmpp.protocol.NamespaceURIs;
 import org.apache.vysper.xmpp.resourcebinding.ResourceRegistry;
@@ -32,6 +30,15 @@
 import org.apache.vysper.xmpp.stanza.Stanza;
 import org.apache.vysper.xmpp.stanza.StanzaBuilder;
 import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.addressing.EntityImpl;
+import org.apache.vysper.xmpp.addressing.EntityFormatException;
+import org.apache.vysper.xmpp.xmlfragment.XMLElement;
+import org.apache.vysper.xmpp.xmlfragment.XMLSemanticError;
+import org.apache.vysper.xmpp.xmlfragment.Attribute;
+import org.apache.vysper.xmpp.xmlfragment.XMLElementVerifier;
+
+import java.util.List;
+import java.util.ArrayList;
 
 /**
  * handles roster get, set, push & result requests
@@ -58,8 +65,7 @@
                 new RuntimeException("iq stanza type RESULT not yet handled");
                 break;
             case SET:
-                new RuntimeException("iq stanza type SET not yet handled");
-                break;
+                return handleRosterSet(stanza, sessionContext);
             default:
                 new RuntimeException("iq stanza type not supported: " + stanza.getIQType());
         }
@@ -75,24 +81,16 @@
 
         if (rosterManager == null) {
             return handleCannotRetrieveRoster(stanza, sessionContext);
-        }        
-        
+        }
+
         String resourceId = registry.getFirstResourceForSession(sessionContext);
         ResourceState currentState = registry.getResourceState(resourceId);
         if (currentState != null) {
-            if (currentState == ResourceState.CONNECTED) {
-                registry.setResourceState(resourceId, ResourceState.INTERESTED_NOT_YET_AVAILABLE);
-            } else if (currentState == ResourceState.AVAILABLE) {
-                registry.setResourceState(resourceId, ResourceState.INTERESTED);
-            } 
+            registry.setResourceState(resourceId, ResourceState.makeInterested(currentState));
         }
 
-        Entity from = stanza.getFrom();
-        if (from == null) {
-            if (sessionContext.getInitiatingEntity() == null) throw new RuntimeException("handle this case");
-            else from = sessionContext.getInitiatingEntity();
-        }
-        
+        Entity from = determineFrom(stanza, sessionContext);
+
         Roster roster = null;
         try {
             roster = rosterManager.retrieve(from.getBareJID());
@@ -106,6 +104,125 @@
         return stanzaBuilder.getFinalStanza();
     }
 
+    private Entity determineFrom(IQStanza stanza, SessionContext sessionContext) {
+        Entity from = stanza.getFrom();
+        if (from == null) {
+            if (sessionContext.getInitiatingEntity() == null) throw new RuntimeException("handle this case");
+            else from = sessionContext.getInitiatingEntity();
+        }
+        return from;
+    }
+
+    /*
+        2.1.3. Roster Set
+        
+
+           A ROSTER SET is a client's request for the server to modify (i.e.,
+           create, update, or delete) a roster item; syntactically it is an IQ
+           stanza of type "set" sent from client to server and containing a
+           <query/> element qualified by the 'jabber:iq:roster' namespace.
+
+           The following rules apply to roster sets:
+
+           1.  The <query/> element MUST contain one and only one <item/>
+               element.
+           2.  The server MUST ignore any value of the 'subscription' attribute
+               other than "remove" (see Section 2.1.6).
+           3.  The server MUST ignore any 'to' address specified on the IQ
+               stanza and MUST handle the IQ stanza as if it included no 'to'
+               attribute.
+
+           C: <iq from='juliet@example.com/balcony'
+                  id='rs1'
+                  type='set'>
+               <query xmlns='jabber:iq:roster'>
+                 <item jid='nurse@example.com'/>
+               </query>
+             </iq>
+
+    */
+    protected Stanza handleRosterSet(IQStanza stanza, SessionContext sessionContext) {
+        ServerRuntimeContext serverContext = sessionContext.getServerRuntimeContext();
+        ResourceRegistry registry = serverContext.getResourceRegistry();
+        RosterManager rosterManager = (RosterManager)serverContext.getServerRuntimeContextService(RosterManager.SERVER_SERVICE_ROSTERMANAGER);
+
+        if (rosterManager == null) {
+            return handleCannotRetrieveRoster(stanza, sessionContext);
+        }
+
+        Entity user = determineFrom(stanza, sessionContext);
+
+        XMLElement itemElement = null;
+        RosterItem setRosterItem = null;
+        try {
+            XMLElement queryElement = stanza.getSingleInnerElementsNamed("query");
+            if (queryElement != null) {
+                itemElement = queryElement.getSingleInnerElementsNamed("item");
+
+                setRosterItem = parseRosterItem(itemElement);
+            }
+        } catch (XMLSemanticError xmlSemanticError) {
+            xmlSemanticError.printStackTrace();
+            throw new RuntimeException("roster set needs proper item node", xmlSemanticError);
+        }
+
+        RosterItem existingItem;
+        try {
+            existingItem = rosterManager.getContact(user.getBareJID(), setRosterItem.getJid().getBareJID());
+        } catch (RosterException e) {
+            existingItem = null;
+        }
+
+        if (setRosterItem.getSubscriptionType() == SubscriptionType.REMOVE) {
+            throw new RuntimeException("roster set REMOVE not yet implemented");
+        }
+
+        if (existingItem == null) {
+            // TODO
+            return null;
+        }
+
+        if (setRosterItem.getName() != null) {
+            System.out.println("set name to " + setRosterItem.getName());
+        }
+
+        return null;
+    }
+
+    private RosterItem parseRosterItem(XMLElement itemElement) throws org.apache.vysper.xmpp.xmlfragment.XMLSemanticError {
+
+        if (itemElement == null) {
+            throw new XMLSemanticError("missing 'item' element");
+        }
+        Attribute attributeJID = itemElement.getAttribute("jid");
+        if (attributeJID == null || attributeJID.getValue() == null) throw new XMLSemanticError("missing 'jid' attribute");
+
+        XMLElementVerifier verifier = itemElement.getVerifier();
+        String name = verifier.attributePresent("name") ? itemElement.getAttribute("name").getValue() : null;
+        SubscriptionType subscription = verifier.attributePresent("subscription") ? SubscriptionType.valueOf(itemElement.getAttribute("subscription").getValue()) : null;
+
+        String contactJid = attributeJID.getValue();
+        Entity contact;
+        try {
+            contact = EntityImpl.parse(contactJid);
+        } catch (EntityFormatException e) {
+            throw new XMLSemanticError("jid cannot be parsed: " + contactJid);
+        }
+
+        List<RosterGroup> groups = new ArrayList<RosterGroup>();
+        List<XMLElement> groupElements = itemElement.getInnerElementsNamed("group");
+        if (groupElements != null) {
+            for (XMLElement groupElement : groupElements) {
+                String groupName = groupElement.getSingleInnerText().getText();
+                if (groupName == null || groupName.length() == 0) continue;
+                groups.add(new RosterGroup(groupName));
+            }
+        }
+
+        RosterItem rosterItem = new RosterItem(contact, name, subscription, AskSubscriptionType.NOT_SET, groups);
+        return rosterItem;
+    }
+
     private Stanza handleCannotRetrieveRoster(IQStanza stanza, SessionContext sessionContext) {
         throw new RuntimeException("gracefully handling roster management problem not implemented");
     }

Modified: labs/vysper/src/main/java/org/apache/vysper/xmpp/resourcebinding/ResourceState.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/resourcebinding/ResourceState.java?rev=707278&r1=707277&r2=707278&view=diff
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/resourcebinding/ResourceState.java (original)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/resourcebinding/ResourceState.java Wed Oct 22 22:42:20 2008
@@ -50,4 +50,9 @@
         if (inState == null || !isInterested(inState)) return AVAILABLE;
         return INTERESTED;
     }
+
+    public static ResourceState makeInterested(ResourceState inState) {
+        if (inState == AVAILABLE) return INTERESTED;
+        return INTERESTED_NOT_YET_AVAILABLE;
+    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org