Hi Niklas,

What do you mean by "relaying" here? If you're just talking about
delivery of stanzas address to a full JID, then that is standard XMPP
functionality.

Peter

On 3/22/11 4:43 PM, Niklas Gustavsson wrote:
> Bernd,
> 
> could you please review this commit. I'm not very experienced with how
> IQ stanza relaying is supposed to work.
> 
> /niklas
> 
> On Tue, Mar 22, 2011 at 11:40 PM,  <[email protected]> wrote:
>> Author: ngn
>> Date: Tue Mar 22 22:40:49 2011
>> New Revision: 1084393
>>
>> URL: http://svn.apache.org/viewvc?rev=1084393&view=rev
>> Log:
>> Implement relaying of IQ stanzas and disco IQ stanzas to a user with a full 
>> JID provided (VYSPER-278)
>>
>> Modified:
>>    
>> mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInternalInboundStanzaRelay.java
>>    
>> mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandler.java
>>    
>> mina/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandlerTestCase.java
>>
>> Modified: 
>> mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInternalInboundStanzaRelay.java
>> URL: 
>> http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInternalInboundStanzaRelay.java?rev=1084393&r1=1084392&r2=1084393&view=diff
>> ==============================================================================
>> --- 
>> mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInternalInboundStanzaRelay.java
>>  (original)
>> +++ 
>> mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInternalInboundStanzaRelay.java
>>  Tue Mar 22 22:40:49 2011
>> @@ -232,7 +232,7 @@ public class DeliveringInternalInboundSt
>>                 }
>>             } else if (IQStanza.isOfType(stanza)) {
>>                 // TODO handle on behalf of the user/client
>> -                throw new RuntimeException("inbound IQ not yet handled");
>> +                return relayToBestSessions(false);
>>             }
>>
>>             return relayNotPossible();
>>
>> Modified: 
>> mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandler.java
>> URL: 
>> http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandler.java?rev=1084393&r1=1084392&r2=1084393&view=diff
>> ==============================================================================
>> --- 
>> mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandler.java
>>  (original)
>> +++ 
>> mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandler.java
>>  Tue Mar 22 22:40:49 2011
>> @@ -25,6 +25,8 @@ import org.apache.vysper.compliance.Spec
>>  import org.apache.vysper.compliance.SpecCompliant;
>>  import org.apache.vysper.xml.fragment.XMLElement;
>>  import org.apache.vysper.xmpp.addressing.Entity;
>> +import org.apache.vysper.xmpp.delivery.failure.DeliveryException;
>> +import 
>> org.apache.vysper.xmpp.delivery.failure.ReturnErrorToSenderFailureStrategy;
>>  import org.apache.vysper.xmpp.modules.core.base.handler.DefaultIQHandler;
>>  import 
>> org.apache.vysper.xmpp.modules.servicediscovery.collection.ServiceCollector;
>>  import 
>> org.apache.vysper.xmpp.modules.servicediscovery.collection.ServiceDiscoveryRequestListenerRegistry;
>> @@ -58,7 +60,8 @@ public class DiscoInfoIQHandler extends
>>
>>     @Override
>>     protected boolean verifyInnerElement(Stanza stanza) {
>> -        return verifyInnerElementWorker(stanza, "query") && 
>> verifyInnerNamespace(stanza, NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO);
>> +        return verifyInnerElementWorker(stanza, "query")
>> +                && verifyInnerNamespace(stanza, 
>> NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO);
>>     }
>>
>>     @Override
>> @@ -78,8 +81,8 @@ public class DiscoInfoIQHandler extends
>>         }
>>
>>         if (serviceCollector == null) {
>> -            return 
>> ServerErrorResponses.getStanzaError(StanzaErrorCondition.INTERNAL_SERVER_ERROR,
>> -                    stanza, StanzaErrorType.CANCEL, "cannot retrieve 
>> IQ-get-info result from internal components",
>> +            return 
>> ServerErrorResponses.getStanzaError(StanzaErrorCondition.INTERNAL_SERVER_ERROR,
>>  stanza,
>> +                    StanzaErrorType.CANCEL, "cannot retrieve IQ-get-info 
>> result from internal components",
>>                     getErrorLanguage(serverRuntimeContext, sessionContext), 
>> null);
>>         }
>>
>> @@ -109,25 +112,30 @@ public class DiscoInfoIQHandler extends
>>         List<InfoElement> elements = null;
>>         try {
>>             Entity from = stanza.getFrom();
>> -            if (from == null) from = sessionContext.getInitiatingEntity();
>> +            if (from == null)
>> +                from = sessionContext.getInitiatingEntity();
>>             if (isServerInfoRequest) {
>> -                elements = serviceCollector.processServerInfoRequest(new 
>> InfoRequest(from, to, node, stanza
>> -                        .getID()));
>> +                elements = serviceCollector.processServerInfoRequest(new 
>> InfoRequest(from, to, node, stanza.getID()));
>>             } else if (isComponentInfoRequest) {
>> -                elements = serviceCollector.processComponentInfoRequest(new 
>> InfoRequest(from, to, node,
>> -                        stanza.getID()));
>> +                elements = serviceCollector
>> +                        .processComponentInfoRequest(new InfoRequest(from, 
>> to, node, stanza.getID()));
>>             } else {
>> -                elements = serviceCollector.processInfoRequest(new 
>> InfoRequest(from, to, node, stanza
>> -                        .getID()));
>> +                // "When an entity sends a disco#info request to a bare JID 
>> (<[email protected]>) hosted by a server,
>> +                // the server itself MUST reply on behalf of the hosted 
>> account, either with an IQ-error or an IQ-result"
>> +                if (to.isResourceSet()) {
>> +                    relayOrWrite(stanza, serverRuntimeContext, 
>> sessionContext);
>> +                    return null;
>> +                } else {
>> +                    elements = serviceCollector.processInfoRequest(new 
>> InfoRequest(from, to, node, stanza.getID()));
>> +                }
>>             }
>>         } catch (ServiceDiscoveryRequestException e) {
>>             // the request yields an error
>>             StanzaErrorCondition stanzaErrorCondition = 
>> e.getErrorCondition();
>>             if (stanzaErrorCondition == null)
>>                 stanzaErrorCondition = 
>> StanzaErrorCondition.INTERNAL_SERVER_ERROR;
>> -            return 
>> ServerErrorResponses.getStanzaError(stanzaErrorCondition, stanza,
>> -                    StanzaErrorType.CANCEL, "disco info request failed.",
>> -                    getErrorLanguage(serverRuntimeContext, sessionContext), 
>> null);
>> +            return 
>> ServerErrorResponses.getStanzaError(stanzaErrorCondition, stanza, 
>> StanzaErrorType.CANCEL,
>> +                    "disco info request failed.", 
>> getErrorLanguage(serverRuntimeContext, sessionContext), null);
>>         }
>>
>>         //TODO check that elementSet contains at least one identity element 
>> and on feature element!
>> @@ -146,4 +154,36 @@ public class DiscoInfoIQHandler extends
>>
>>         return stanzaBuilder.build();
>>     }
>> +
>> +    @Override
>> +    protected Stanza handleResult(IQStanza stanza, ServerRuntimeContext 
>> serverRuntimeContext,
>> +            SessionContext sessionContext) {
>> +
>> +        if (stanza.getTo().isResourceSet()) {
>> +            relayOrWrite(stanza, serverRuntimeContext, sessionContext);
>> +            return null;
>> +        } else {
>> +            return super.handleResult(stanza, serverRuntimeContext, 
>> sessionContext);
>> +        }
>> +    }
>> +
>> +    private void relayOrWrite(IQStanza stanza, ServerRuntimeContext 
>> serverRuntimeContext, SessionContext sessionContext) {
>> +        boolean isOutbound = 
>> !sessionContext.getInitiatingEntity().equals(stanza.getTo().getBareJID());
>> +        if (isOutbound) {
>> +            try {
>> +                Entity from = stanza.getFrom();
>> +                if (from == null) {
>> +                    from = sessionContext.getInitiatingEntity();
>> +                }
>> +                Stanza forward = StanzaBuilder.createForwardStanza(stanza, 
>> from, null);
>> +
>> +                serverRuntimeContext.getStanzaRelay().relay(stanza.getTo(), 
>> forward,
>> +                        new 
>> ReturnErrorToSenderFailureStrategy(serverRuntimeContext.getStanzaRelay()));
>> +            } catch (DeliveryException e) {
>> +                logger.warn("relaying IQ failed", e);
>> +            }
>> +        } else {
>> +            sessionContext.getResponseWriter().write(stanza);
>> +        }
>> +    }
>>  }
>>
>> Modified: 
>> mina/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandlerTestCase.java
>> URL: 
>> http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandlerTestCase.java?rev=1084393&r1=1084392&r2=1084393&view=diff
>> ==============================================================================
>> --- 
>> mina/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandlerTestCase.java
>>  (original)
>> +++ 
>> mina/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandlerTestCase.java
>>  Tue Mar 22 22:40:49 2011
>> @@ -27,6 +27,8 @@ import junit.framework.Assert;
>>  import org.apache.vysper.StanzaAssert;
>>  import org.apache.vysper.xmpp.addressing.Entity;
>>  import org.apache.vysper.xmpp.addressing.EntityImpl;
>> +import org.apache.vysper.xmpp.delivery.StanzaRelay;
>> +import org.apache.vysper.xmpp.delivery.failure.DeliveryFailureStrategy;
>>  import 
>> org.apache.vysper.xmpp.modules.servicediscovery.collection.ServiceCollector;
>>  import 
>> org.apache.vysper.xmpp.modules.servicediscovery.collection.ServiceDiscoveryRequestListenerRegistry;
>>  import org.apache.vysper.xmpp.modules.servicediscovery.management.Feature;
>> @@ -44,6 +46,7 @@ import org.apache.vysper.xmpp.stanza.Sta
>>  import org.apache.vysper.xmpp.stanza.StanzaBuilder;
>>  import org.apache.vysper.xmpp.stanza.StanzaErrorCondition;
>>  import org.apache.vysper.xmpp.stanza.XMPPCoreStanza;
>> +import org.apache.vysper.xmpp.writer.StanzaWriter;
>>  import org.junit.Before;
>>  import org.junit.Test;
>>  import org.mockito.Mockito;
>> @@ -56,10 +59,13 @@ public class DiscoInfoIQHandlerTestCase
>>     private static final Entity SERVER = 
>> EntityImpl.parseUnchecked("vysper.org");
>>     private static final Entity COMPONENT = 
>> EntityImpl.parseUnchecked("comp.vysper.org");
>>     private static final Entity USER = 
>> EntityImpl.parseUnchecked("[email protected]");
>> +    private static final Entity USER_WITH_RESOURCE = 
>> EntityImpl.parseUnchecked("[email protected]/res1");
>>
>> -    private ServerRuntimeContext serverRuntimeContext = 
>> Mockito.mock(ServerRuntimeContext.class);
>> -    private SessionContext sessionContext = 
>> Mockito.mock(SessionContext.class);
>> -    private ServiceCollector serviceCollector = 
>> Mockito.mock(ServiceCollector.class);
>> +    private ServerRuntimeContext serverRuntimeContext = 
>> mock(ServerRuntimeContext.class);
>> +    private SessionContext sessionContext = mock(SessionContext.class);
>> +    private ServiceCollector serviceCollector = 
>> mock(ServiceCollector.class);
>> +    private StanzaRelay stanzaRelay = mock(StanzaRelay.class);
>> +    private StanzaWriter stanzaWriter = mock(StanzaWriter.class);
>>
>>     private IQStanza stanza = (IQStanza) IQStanza.getWrapper(buildStanza());
>>
>> @@ -148,6 +154,8 @@ public class DiscoInfoIQHandlerTestCase
>>             .thenReturn(serviceCollector);
>>
>>         when(serverRuntimeContext.getServerEnitity()).thenReturn(SERVER);
>> +        when(serverRuntimeContext.getStanzaRelay()).thenReturn(stanzaRelay);
>> +        when(sessionContext.getResponseWriter()).thenReturn(stanzaWriter);
>>     }
>>
>>     @Test
>> @@ -186,6 +194,32 @@ public class DiscoInfoIQHandlerTestCase
>>     }
>>
>>     @Test
>> +    public void handleGetToUserWithResource() throws Exception {
>> +        when(sessionContext.getInitiatingEntity()).thenReturn(FROM);
>> +
>> +        IQStanza stanza = createRequest(USER_WITH_RESOURCE);
>> +
>> +        Stanza response = handler.handleGet(stanza, serverRuntimeContext, 
>> sessionContext);
>> +
>> +        Assert.assertNull(response);
>> +
>> +        verify(stanzaRelay).relay(eq(USER_WITH_RESOURCE), eq(stanza), 
>> any(DeliveryFailureStrategy.class));
>> +    }
>> +
>> +    @Test
>> +    public void handleGetToUserWithResourceInbound() throws Exception {
>> +        when(sessionContext.getInitiatingEntity()).thenReturn(USER);
>> +
>> +        IQStanza stanza = createRequest(USER_WITH_RESOURCE);
>> +
>> +        Stanza response = handler.handleGet(stanza, serverRuntimeContext, 
>> sessionContext);
>> +
>> +        Assert.assertNull(response);
>> +
>> +        verify(stanzaWriter).write(stanza);
>> +    }
>> +
>> +    @Test
>>     public void handleGetToNonExistingComponent() throws Exception {
>>         IQStanza stanza = createRequest(COMPONENT);
>>
>> @@ -253,6 +287,45 @@ public class DiscoInfoIQHandlerTestCase
>>         StanzaAssert.assertEquals(expected, response);
>>     }
>>
>> +    @Test
>> +    public void handleResultToUserWithResource() throws Exception {
>> +        when(sessionContext.getInitiatingEntity()).thenReturn(FROM);
>> +
>> +        IQStanza stanza = createRequest(USER_WITH_RESOURCE, 
>> IQStanzaType.RESULT);
>> +
>> +        Stanza response = handler.handleResult(stanza, 
>> serverRuntimeContext, sessionContext);
>> +
>> +        Assert.assertNull(response);
>> +
>> +        verify(stanzaRelay).relay(eq(USER_WITH_RESOURCE), eq(stanza), 
>> any(DeliveryFailureStrategy.class));
>> +    }
>> +
>> +    @Test
>> +    public void handleResultToUserWithResourceInbound() throws Exception {
>> +        when(sessionContext.getInitiatingEntity()).thenReturn(USER);
>> +
>> +        IQStanza stanza = createRequest(USER_WITH_RESOURCE, 
>> IQStanzaType.RESULT);
>> +
>> +        Stanza response = handler.handleResult(stanza, 
>> serverRuntimeContext, sessionContext);
>> +
>> +        Assert.assertNull(response);
>> +
>> +        verify(stanzaWriter).write(stanza);
>> +    }
>> +
>> +    @Test
>> +    public void handleResultToUser() throws Exception {
>> +        when(sessionContext.getInitiatingEntity()).thenReturn(FROM);
>> +
>> +        IQStanza stanza = createRequest(USER, IQStanzaType.RESULT);
>> +
>> +        Stanza response = handler.handleResult(stanza, 
>> serverRuntimeContext, sessionContext);
>> +
>> +        Stanza expected = createErrorResponse(SERVER, 
>> "feature-not-implemented");
>> +
>> +        StanzaAssert.assertEquals(expected, response);
>> +    }
>> +
>>     private Stanza createErrorResponse(Entity from, String error) {
>>         Stanza expected = StanzaBuilder.createIQStanza(from, FROM, 
>> IQStanzaType.ERROR, "id1")
>>         .startInnerElement("query", 
>> NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO)
>> @@ -266,7 +339,11 @@ public class DiscoInfoIQHandlerTestCase
>>     }
>>
>>     private IQStanza createRequest(Entity to) {
>> -        IQStanza stanza = (IQStanza) 
>> XMPPCoreStanza.getWrapper(StanzaBuilder.createIQStanza(FROM, to, 
>> IQStanzaType.GET, "id1")
>> +        return createRequest(to, IQStanzaType.GET);
>> +    }
>> +
>> +    private IQStanza createRequest(Entity to, IQStanzaType type) {
>> +        IQStanza stanza = (IQStanza) 
>> XMPPCoreStanza.getWrapper(StanzaBuilder.createIQStanza(FROM, to, type, "id1")
>>                 .startInnerElement("query", 
>> NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO)
>>                 .addAttribute("node", "n")
>>                 .build());
>>
>>
>>

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to