You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by ng...@apache.org on 2011/01/01 17:49:13 UTC

svn commit: r1054253 - in /mina/vysper/branches/s2s/server/core: ./ src/main/java/org/apache/vysper/xmpp/delivery/failure/ src/main/java/org/apache/vysper/xmpp/delivery/inbound/ src/main/java/org/apache/vysper/xmpp/protocol/ src/main/java/org/apache/vy...

Author: ngn
Date: Sat Jan  1 16:49:12 2011
New Revision: 1054253

URL: http://svn.apache.org/viewvc?rev=1054253&view=rev
Log:
Adding correct error handling when relaying s2s stanzas
Adding tests for namespace rewrites, ReturnErrorToSender failure handler and for external relaying

Added:
    mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/RemoteServerNotFoundException.java
    mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/RemoteServerTimeoutException.java
    mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/SmartDeliveryException.java
    mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/DefaultXMPPServerConnector.java
      - copied, changed from r1053752, mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnector.java
    mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/DefaultXMPPServerConnectorRegistry.java
      - copied, changed from r1053752, mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnectorRegistry.java
    mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/failure/
    mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/failure/ReturnErrorToSenderFailureStrategyTestCase.java
    mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringExternalInboundStanzaRelayTestCase.java
    mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInteralInboundStanzaRelayTestCase.java
      - copied, changed from r1054013, mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringStanzaRelayTestCase.java
    mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/RecordingDeliveryFailureStrategy.java
    mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/RelayResultTestCase.java
    mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/TestExecutorService.java
    mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/server/s2s/ServerMain.java
Removed:
    mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringStanzaRelayTestCase.java
Modified:
    mina/vysper/branches/s2s/server/core/pom.xml
    mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/ReturnErrorToSenderFailureStrategy.java
    mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringExternalInboundStanzaRelay.java
    mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/RelayResult.java
    mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/protocol/ProtocolWorker.java
    mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContext.java
    mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnector.java
    mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnectorRegistry.java
    mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/server/s2s/Server2Server.java
    mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/stanza/StanzaBuilderTestCase.java

Modified: mina/vysper/branches/s2s/server/core/pom.xml
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/pom.xml?rev=1054253&r1=1054252&r2=1054253&view=diff
==============================================================================
--- mina/vysper/branches/s2s/server/core/pom.xml (original)
+++ mina/vysper/branches/s2s/server/core/pom.xml Sat Jan  1 16:49:12 2011
@@ -151,6 +151,12 @@
       <artifactId>smackx</artifactId>
       <scope>test</scope>
     </dependency>
+    
+	<dependency>
+    	<groupId>org.mockito</groupId>
+    	<artifactId>mockito-all</artifactId>
+		<scope>test</scope>
+	</dependency>
   </dependencies>
 
 </project>

Added: mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/RemoteServerNotFoundException.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/RemoteServerNotFoundException.java?rev=1054253&view=auto
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/RemoteServerNotFoundException.java (added)
+++ mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/RemoteServerNotFoundException.java Sat Jan  1 16:49:12 2011
@@ -0,0 +1,51 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.vysper.xmpp.delivery.failure;
+
+import org.apache.vysper.xmpp.stanza.StanzaErrorCondition;
+import org.apache.vysper.xmpp.stanza.StanzaErrorType;
+
+
+/**
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class RemoteServerNotFoundException extends SmartDeliveryException {
+    public RemoteServerNotFoundException() {
+        super();
+    }
+
+    public RemoteServerNotFoundException(String string) {
+        super(string);
+    }
+
+    public RemoteServerNotFoundException(String string, Throwable throwable) {
+        super(string, throwable);
+    }
+
+    public RemoteServerNotFoundException(Throwable throwable) {
+        super(throwable);
+    }
+    
+    @Override
+    public StanzaErrorCondition getStanzaErrorCondition() {
+        return StanzaErrorCondition.REMOTE_SERVER_NOT_FOUND;
+    }
+}

Added: mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/RemoteServerTimeoutException.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/RemoteServerTimeoutException.java?rev=1054253&view=auto
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/RemoteServerTimeoutException.java (added)
+++ mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/RemoteServerTimeoutException.java Sat Jan  1 16:49:12 2011
@@ -0,0 +1,51 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.vysper.xmpp.delivery.failure;
+
+import org.apache.vysper.xmpp.stanza.StanzaErrorCondition;
+import org.apache.vysper.xmpp.stanza.StanzaErrorType;
+
+
+/**
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class RemoteServerTimeoutException extends SmartDeliveryException {
+    public RemoteServerTimeoutException() {
+        super();
+    }
+
+    public RemoteServerTimeoutException(String string) {
+        super(string);
+    }
+
+    public RemoteServerTimeoutException(String string, Throwable throwable) {
+        super(string, throwable);
+    }
+
+    public RemoteServerTimeoutException(Throwable throwable) {
+        super(throwable);
+    }
+
+    @Override
+    public StanzaErrorCondition getStanzaErrorCondition() {
+        return StanzaErrorCondition.REMOTE_SERVER_TIMEOUT;
+    }
+}

Modified: mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/ReturnErrorToSenderFailureStrategy.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/ReturnErrorToSenderFailureStrategy.java?rev=1054253&r1=1054252&r2=1054253&view=diff
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/ReturnErrorToSenderFailureStrategy.java (original)
+++ mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/ReturnErrorToSenderFailureStrategy.java Sat Jan  1 16:49:12 2011
@@ -65,15 +65,17 @@ public class ReturnErrorToSenderFailureS
             @SpecCompliant(spec = "rfc3921bis-08", section = "4.3", status = NOT_STARTED, coverage = UNKNOWN) })
     public void process(Stanza failedToDeliverStanza, List<DeliveryException> deliveryExceptions)
             throws DeliveryException {
-
         StanzaErrorCondition stanzaErrorCondition = StanzaErrorCondition.SERVICE_UNAVAILABLE;
         StanzaErrorType errorType = StanzaErrorType.CANCEL;
 
+        // TODO would it be better to check for the correct stanzas instead of assuming the stanza is wrapped?
         if (!(failedToDeliverStanza instanceof XMPPCoreStanza)) {
             throw new DeliveryException("could not return to sender");
         }
+        
+        
         XMPPCoreStanza failedCoreStanza = (XMPPCoreStanza) failedToDeliverStanza;
-        if (failedCoreStanza.getType() != null && failedCoreStanza.getType().equals("error")) {
+        if ("error".equals(failedCoreStanza.getType())) {
             return; // do not answer these
         }
 
@@ -112,6 +114,15 @@ public class ReturnErrorToSenderFailureS
                         return;
                     }
                 }
+            } else if (deliveryException instanceof SmartDeliveryException) {
+                // RFC3921bis#10.4.3: return remote server error to sender
+                SmartDeliveryException smartDeliveryException = (SmartDeliveryException) deliveryException;
+                XMPPCoreStanza error = XMPPCoreStanza
+                        .getWrapper(ServerErrorResponses.getInstance().getStanzaError(
+                                smartDeliveryException.getStanzaErrorCondition(), failedCoreStanza,
+                                smartDeliveryException.getStanzaErrorType(), smartDeliveryException.getErrorText(),
+                                "en", null));
+                stanzaRelay.relay(error.getTo(), error, IgnoreFailureStrategy.IGNORE_FAILURE_STRATEGY);
             }
         } else if (deliveryExceptions.size() > 1) {
             throw new RuntimeException("cannot return to sender for multiple failed deliveries");

Added: mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/SmartDeliveryException.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/SmartDeliveryException.java?rev=1054253&view=auto
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/SmartDeliveryException.java (added)
+++ mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/failure/SmartDeliveryException.java Sat Jan  1 16:49:12 2011
@@ -0,0 +1,57 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.vysper.xmpp.delivery.failure;
+
+import org.apache.vysper.xmpp.stanza.StanzaErrorCondition;
+import org.apache.vysper.xmpp.stanza.StanzaErrorType;
+
+/**
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public abstract class SmartDeliveryException extends DeliveryException {
+
+    public SmartDeliveryException() {
+        super();
+    }
+
+    public SmartDeliveryException(String string) {
+        super(string);
+    }
+
+    public SmartDeliveryException(String string, Throwable throwable) {
+        super(string, throwable);
+    }
+
+    public SmartDeliveryException(Throwable throwable) {
+        super(throwable);
+    }
+    
+    
+   public abstract StanzaErrorCondition getStanzaErrorCondition();
+
+   public StanzaErrorType getStanzaErrorType() {
+       return StanzaErrorType.CANCEL;
+   }
+
+   public String getErrorText() {
+       return getMessage();
+   }
+}

Modified: mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringExternalInboundStanzaRelay.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringExternalInboundStanzaRelay.java?rev=1054253&r1=1054252&r2=1054253&view=diff
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringExternalInboundStanzaRelay.java (original)
+++ mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringExternalInboundStanzaRelay.java Sat Jan  1 16:49:12 2011
@@ -19,7 +19,6 @@
  */
 package org.apache.vysper.xmpp.delivery.inbound;
 
-import java.io.IOException;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
@@ -27,19 +26,19 @@ import java.util.concurrent.LinkedBlocki
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.vysper.compliance.SpecCompliant;
 import org.apache.vysper.xmpp.addressing.Entity;
 import org.apache.vysper.xmpp.addressing.EntityImpl;
 import org.apache.vysper.xmpp.delivery.OfflineStanzaReceiver;
 import org.apache.vysper.xmpp.delivery.StanzaRelay;
-import org.apache.vysper.xmpp.delivery.failure.DeliveredToOfflineReceiverException;
 import org.apache.vysper.xmpp.delivery.failure.DeliveryException;
 import org.apache.vysper.xmpp.delivery.failure.DeliveryFailureStrategy;
-import org.apache.vysper.xmpp.delivery.failure.LocalRecipientOfflineException;
 import org.apache.vysper.xmpp.protocol.NamespaceURIs;
 import org.apache.vysper.xmpp.server.ServerRuntimeContext;
 import org.apache.vysper.xmpp.server.s2s.XMPPServerConnector;
 import org.apache.vysper.xmpp.stanza.Stanza;
 import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import org.apache.vysper.xmpp.stanza.XMPPCoreStanza;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -69,6 +68,10 @@ public class DeliveringExternalInboundSt
                 new LinkedBlockingQueue<Runnable>());
     }
 
+    public DeliveringExternalInboundStanzaRelay(ExecutorService executor) {
+        this.executor = executor;
+    }
+
     public void setServerRuntimeContext(ServerRuntimeContext serverRuntimeContext) {
         this.serverRuntimeContext = serverRuntimeContext;
     }
@@ -78,28 +81,33 @@ public class DeliveringExternalInboundSt
         
         // rewrite the namespace into the jabber:server namespace
         stanza = StanzaBuilder.rewriteNamespace(stanza, NamespaceURIs.JABBER_CLIENT, NamespaceURIs.JABBER_SERVER);
-
-        Future<RelayResult> resultFuture = executor.submit(new OutboundRelayCallable(receiver, stanza, deliveryFailureStrategy));
+        XMPPCoreStanza coreStanza = XMPPCoreStanza.getWrapper(stanza);
+        
+        if(coreStanza != null) {
+            Future<RelayResult> resultFuture = executor.submit(new OutboundRelayCallable(coreStanza, deliveryFailureStrategy));
+        } else {
+            // ignore non-core stanzas
+        }
     }
     
     private class OutboundRelayCallable implements Callable<RelayResult> {
-        private Entity receiver;
-
-        private Stanza stanza;
+        private XMPPCoreStanza stanza;
 
         private DeliveryFailureStrategy deliveryFailureStrategy;
 
-        OutboundRelayCallable(Entity receiver, Stanza stanza, DeliveryFailureStrategy deliveryFailureStrategy) {
-            this.receiver = receiver;
+        OutboundRelayCallable(XMPPCoreStanza stanza, DeliveryFailureStrategy deliveryFailureStrategy) {
             this.stanza = stanza;
             this.deliveryFailureStrategy = deliveryFailureStrategy;
         }
 
         public RelayResult call() {
             RelayResult relayResult = deliver();
-            if (relayResult == null || !relayResult.hasProcessingErrors())
+
+            if (relayResult == null || !relayResult.hasProcessingErrors()) {
                 return relayResult;
-            return runFailureStrategy(relayResult);
+            } else {
+                return runFailureStrategy(relayResult);
+            }
         }
 
         private RelayResult runFailureStrategy(RelayResult relayResult) {
@@ -119,30 +127,16 @@ public class DeliveringExternalInboundSt
         /**
          * @return
          */
-        //@SpecCompliant(spec = "draft-ietf-xmpp-3921bis-00", section = "8.", status = SpecCompliant.ComplianceStatus.IN_PROGRESS, coverage = SpecCompliant.ComplianceCoverage.COMPLETE)
+        @SpecCompliant(spec = "draft-ietf-xmpp-3920bis-22", section = "10.4", status = SpecCompliant.ComplianceStatus.IN_PROGRESS, coverage = SpecCompliant.ComplianceCoverage.COMPLETE)
         protected RelayResult deliver() {
-            RelayResult relayResult = new RelayResult();
             try {
-                XMPPServerConnector connector = serverRuntimeContext.getServerConnectorRegistry().getConnector(EntityImpl.parseUnchecked(stanza.getTo().getDomain()));
+                RelayResult relayResult = new RelayResult();
+                XMPPServerConnector connector = serverRuntimeContext.getServerConnectorRegistry().connect(EntityImpl.parseUnchecked(stanza.getTo().getDomain()));
                 
                 connector.write(stanza);
-            } catch (IOException e) {
-                return new RelayResult(new DeliveryException(e));
-            } catch (RuntimeException e) {
-                return new RelayResult(new DeliveryException(e));
-            }
-            
-            return relayResult;
-        }
-        
-        private RelayResult relayNotPossible() {
-            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());
+                return relayResult;
+            } catch (DeliveryException e) {
+                return new RelayResult(e);
             }
         }
     }

Modified: mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/RelayResult.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/RelayResult.java?rev=1054253&r1=1054252&r2=1054253&view=diff
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/RelayResult.java (original)
+++ mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/RelayResult.java Sat Jan  1 16:49:12 2011
@@ -3,14 +3,11 @@ package org.apache.vysper.xmpp.delivery.
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.vysper.xmpp.delivery.failure.DeliveryException;
 
 public class RelayResult {
-    private List<DeliveryException> processingErrors = null;
-
-    private AtomicInteger relayed = new AtomicInteger(0);
+    private List<DeliveryException> processingErrors = new ArrayList<DeliveryException>();
 
     public RelayResult() {
         // empty
@@ -21,24 +18,14 @@ public class RelayResult {
     }
 
     public void addProcessingError(DeliveryException processingError) {
-        if (processingError == null)
-            processingErrors = new ArrayList<DeliveryException>();
         processingErrors.add(processingError);
     }
 
-    public boolean isRelayed() {
-        return relayed.get() > 0;
-    }
-
     public List<DeliveryException> getProcessingErrors() {
-        if (processingErrors == null) {
-            return Collections.<DeliveryException> emptyList();
-        } else {
-            return Collections.unmodifiableList(processingErrors);
-        }
+        return Collections.unmodifiableList(processingErrors);
     }
 
     public boolean hasProcessingErrors() {
-        return processingErrors != null && processingErrors.size() > 0;
+        return processingErrors.size() > 0;
     }
 }
\ No newline at end of file

Modified: mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/protocol/ProtocolWorker.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/protocol/ProtocolWorker.java?rev=1054253&r1=1054252&r2=1054253&view=diff
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/protocol/ProtocolWorker.java (original)
+++ mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/protocol/ProtocolWorker.java Sat Jan  1 16:49:12 2011
@@ -110,7 +110,7 @@ public class ProtocolWorker implements S
         }
 
         // make sure that 'from' (if present) matches the bare authorized entity
-        // else repond with a stanza error 'unknown-sender'
+        // else respond with a stanza error 'unknown-sender'
         // see rfc3920_draft-saintandre-rfc3920bis-04.txt#8.5.4
         Entity from = stanza.getFrom();
         if (from != null && sessionContext.getInitiatingEntity() != null) {

Modified: mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContext.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContext.java?rev=1054253&r1=1054252&r2=1054253&view=diff
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContext.java (original)
+++ mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContext.java Sat Jan  1 16:49:12 2011
@@ -40,13 +40,13 @@ import org.apache.vysper.xmpp.modules.Mo
 import org.apache.vysper.xmpp.modules.ModuleRegistry;
 import org.apache.vysper.xmpp.modules.ServerRuntimeContextService;
 import org.apache.vysper.xmpp.protocol.HandlerDictionary;
-import org.apache.vysper.xmpp.protocol.NamespaceHandlerDictionary;
 import org.apache.vysper.xmpp.protocol.ProtocolWorker;
 import org.apache.vysper.xmpp.protocol.QueuedStanzaProcessor;
 import org.apache.vysper.xmpp.protocol.StanzaHandler;
 import org.apache.vysper.xmpp.protocol.StanzaHandlerLookup;
 import org.apache.vysper.xmpp.protocol.StanzaProcessor;
 import org.apache.vysper.xmpp.server.components.Component;
+import org.apache.vysper.xmpp.server.s2s.DefaultXMPPServerConnectorRegistry;
 import org.apache.vysper.xmpp.server.s2s.XMPPServerConnectorRegistry;
 import org.apache.vysper.xmpp.stanza.Stanza;
 import org.apache.vysper.xmpp.state.presence.LatestPresenceCache;
@@ -114,7 +114,7 @@ public class DefaultServerRuntimeContext
      */
     private LatestPresenceCache presenceCache = new SimplePresenceCache();
 
-    private XMPPServerConnectorRegistry serverConnectorRegistry = new XMPPServerConnectorRegistry(this);
+    private XMPPServerConnectorRegistry serverConnectorRegistry = new DefaultXMPPServerConnectorRegistry(this);
     
     /**
      * holds the storage services

Copied: mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/DefaultXMPPServerConnector.java (from r1053752, mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnector.java)
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/DefaultXMPPServerConnector.java?p2=mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/DefaultXMPPServerConnector.java&p1=mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnector.java&r1=1053752&r2=1054253&rev=1054253&view=diff
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnector.java (original)
+++ mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/DefaultXMPPServerConnector.java Sat Jan  1 16:49:12 2011
@@ -1,6 +1,5 @@
 package org.apache.vysper.xmpp.server.s2s;
-import java.io.IOException;
-import java.net.InetSocketAddress;
+import java.nio.channels.UnresolvedAddressException;
 import java.util.List;
 import java.util.Timer;
 import java.util.TimerTask;
@@ -19,6 +18,8 @@ import org.apache.vysper.mina.MinaBacked
 import org.apache.vysper.mina.StanzaLoggingFilter;
 import org.apache.vysper.mina.codec.XMPPProtocolCodecFactory;
 import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.delivery.failure.RemoteServerNotFoundException;
+import org.apache.vysper.xmpp.delivery.failure.RemoteServerTimeoutException;
 import org.apache.vysper.xmpp.modules.extension.xep0119_xmppping.XmppPingListener;
 import org.apache.vysper.xmpp.modules.extension.xep0119_xmppping.XmppPingModule;
 import org.apache.vysper.xmpp.modules.extension.xep0220_server_dailback.DailbackIdGenerator;
@@ -31,13 +32,12 @@ import org.apache.vysper.xmpp.server.res
 import org.apache.vysper.xmpp.server.s2s.XmppEndpointResolver.ResolvedAddress;
 import org.apache.vysper.xmpp.stanza.Stanza;
 import org.apache.vysper.xmpp.stanza.StanzaBuilder;
-import org.apache.vysper.xmpp.writer.StanzaWriter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class XMPPServerConnector implements StanzaWriter, XmppPingListener {
+public class DefaultXMPPServerConnector implements XmppPingListener, XMPPServerConnector {
 
-    private static final Logger LOG = LoggerFactory.getLogger(XMPPServerConnector.class);
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultXMPPServerConnector.class);
     
     private ServerRuntimeContext serverRuntimeContext;
     private MinaBackedSessionContext sessionContext;
@@ -55,12 +55,12 @@ public class XMPPServerConnector impleme
     
     private Timer pingTimer = new Timer("pingtimer", true);
     
-    public XMPPServerConnector(Entity otherServer, ServerRuntimeContext serverRuntimeContext) {
+    public DefaultXMPPServerConnector(Entity otherServer, ServerRuntimeContext serverRuntimeContext) {
         this.serverRuntimeContext = serverRuntimeContext;
         this.otherServer = otherServer;
     }
 
-    public synchronized void start() throws IOException {
+    public synchronized void start() throws RemoteServerNotFoundException, RemoteServerTimeoutException {
         LOG.info("Starting XMPP server connector to {}", otherServer);
 
         // make this method synchronous
@@ -71,35 +71,51 @@ public class XMPPServerConnector impleme
         XmppEndpointResolver resolver = new XmppEndpointResolver();
         List<ResolvedAddress> addresses = resolver.resolveXmppServer(otherServer.getDomain());
         
-        for(ResolvedAddress address : addresses) {
-            LOG.info("Connecting to XMPP server {} at {}", otherServer, address.getAddress());
-            
-            connector = createConnector(authenticatedLatch);
-            ConnectFuture connectFuture = connector.connect(address.getAddress());
-            if(connectFuture.awaitUninterruptibly(connectTimeout) && connectFuture.isConnected()) {
-                // success on the TCP/IP lever, now wait for the XMPP handshake
-
-                try {
-                    if(authenticatedLatch.await(xmppHandshakeTimeout, TimeUnit.MILLISECONDS)) {
-                        // success, break out of connect loop
-                        successfullyConnected = true;
-                        break;
-                    } else {
-                        // attempt next
-                        LOG.warn("XMPP handshake with {} at () timed out", otherServer, address.getAddress());
+        Throwable lastException = null;
+        
+        if(!addresses.isEmpty()) {
+            for(ResolvedAddress address : addresses) {
+                LOG.info("Connecting to XMPP server {} at {}", otherServer, address.getAddress());
+                
+                connector = createConnector(authenticatedLatch);
+                
+                ConnectFuture connectFuture = connector.connect(address.getAddress());
+                if(connectFuture.awaitUninterruptibly(connectTimeout) && connectFuture.isConnected()) {
+                    // success on the TCP/IP lever, now wait for the XMPP handshake
+    
+                    try {
+                        if(authenticatedLatch.await(xmppHandshakeTimeout, TimeUnit.MILLISECONDS)) {
+                            // success, break out of connect loop
+                            successfullyConnected = true;
+                            break;
+                        } else {
+                            // attempt next
+                            LOG.warn("XMPP handshake with {} at () timed out", otherServer, address.getAddress());
+                        }
+                    } catch (InterruptedException e) {
+                        throw new RemoteServerTimeoutException("Connection to " + otherServer + " was interrupted", e);
                     }
-                } catch (InterruptedException e) {
-                    throw new IOException("Connection to " + otherServer + " was interrupted", e);
-                }
-            } 
+                } 
 
-            LOG.warn("Failed connecting to XMPP server " + otherServer + " at " + address.getAddress(), connectFuture.getException());
-            connector.dispose();
-            connector = null;
+                lastException = connectFuture.getException();
+                LOG.warn("Failed connecting to XMPP server " + otherServer + " at " + address.getAddress(), connectFuture.getException());
+                connector.dispose();
+                connector = null;
+            }
+        } else {
+            // should never happen
+            throw new RemoteServerNotFoundException("DNS lookup of remote server failed");
         }
         
         if(!successfullyConnected) {
-            throw new IOException("Failed to connect to XMPP server at " + otherServer);
+            String exceptionMsg = "Failed to connect to XMPP server at " + otherServer;
+            
+            if(lastException instanceof UnresolvedAddressException) {
+                throw new RemoteServerNotFoundException(exceptionMsg);
+            } else {
+                throw new RemoteServerTimeoutException(exceptionMsg);
+            }
+            
         }
     }
     
@@ -119,6 +135,9 @@ public class XMPPServerConnector impleme
         pingTimer.schedule(new PingTask(), pingPeriod, pingPeriod);
     }
     
+    /* (non-Javadoc)
+     * @see org.apache.vysper.xmpp.server.s2s.XMPPServerConnector#write(org.apache.vysper.xmpp.stanza.Stanza)
+     */
     public void write(Stanza stanza) {
         sessionContext.write(stanza);
     }
@@ -252,7 +271,7 @@ public class XMPPServerConnector impleme
         public void run() {
             XmppPingModule pingModule = serverRuntimeContext.getModule(XmppPingModule.class);
             if(pingModule != null) {
-                pingModule.ping(XMPPServerConnector.this, serverRuntimeContext.getServerEnitity(), otherServer, pingTimeout, XMPPServerConnector.this);
+                pingModule.ping(DefaultXMPPServerConnector.this, serverRuntimeContext.getServerEnitity(), otherServer, pingTimeout, DefaultXMPPServerConnector.this);
             }
         }
     }

Copied: mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/DefaultXMPPServerConnectorRegistry.java (from r1053752, mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnectorRegistry.java)
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/DefaultXMPPServerConnectorRegistry.java?p2=mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/DefaultXMPPServerConnectorRegistry.java&p1=mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnectorRegistry.java&r1=1053752&r2=1054253&rev=1054253&view=diff
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnectorRegistry.java (original)
+++ mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/DefaultXMPPServerConnectorRegistry.java Sat Jan  1 16:49:12 2011
@@ -1,22 +1,28 @@
 package org.apache.vysper.xmpp.server.s2s;
-import java.io.IOException;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+import org.apache.vysper.compliance.SpecCompliant;
 import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.delivery.failure.RemoteServerNotFoundException;
+import org.apache.vysper.xmpp.delivery.failure.RemoteServerTimeoutException;
 import org.apache.vysper.xmpp.server.ServerRuntimeContext;
 
-public class XMPPServerConnectorRegistry {
+public class DefaultXMPPServerConnectorRegistry implements XMPPServerConnectorRegistry {
 
     private ServerRuntimeContext serverRuntimeContext;
-    private Map<Entity, XMPPServerConnector> connectors = new ConcurrentHashMap<Entity, XMPPServerConnector>();
+    private Map<Entity, DefaultXMPPServerConnector> connectors = new ConcurrentHashMap<Entity, DefaultXMPPServerConnector>();
     
-    public XMPPServerConnectorRegistry(ServerRuntimeContext serverRuntimeContext) {
+    public DefaultXMPPServerConnectorRegistry(ServerRuntimeContext serverRuntimeContext) {
         this.serverRuntimeContext = serverRuntimeContext;
     }
 
-    public synchronized XMPPServerConnector getConnector(Entity server) throws IOException {
-        XMPPServerConnector connector = connectors.get(server);
+    /* (non-Javadoc)
+     * @see org.apache.vysper.xmpp.server.s2s.XMPPServerConnectorRegistry#getConnector(org.apache.vysper.xmpp.addressing.Entity)
+     */
+    @SpecCompliant(spec = "draft-ietf-xmpp-3920bis-22", section = "10.4", status = SpecCompliant.ComplianceStatus.IN_PROGRESS, coverage = SpecCompliant.ComplianceCoverage.COMPLETE)
+    public synchronized XMPPServerConnector connect(Entity server) throws RemoteServerNotFoundException, RemoteServerTimeoutException {
+        DefaultXMPPServerConnector connector = connectors.get(server);
 
         if(connector != null && connector.isClosed()) {
             connectors.remove(server);
@@ -24,7 +30,7 @@ public class XMPPServerConnectorRegistry
         } 
         
         if(connector == null) {
-            connector = new XMPPServerConnector(server, serverRuntimeContext);
+            connector = new DefaultXMPPServerConnector(server, serverRuntimeContext);
             connector.start();
             connectors.put(server, connector);
         }
@@ -32,8 +38,11 @@ public class XMPPServerConnectorRegistry
         return connector;
     }
 
+    /* (non-Javadoc)
+     * @see org.apache.vysper.xmpp.server.s2s.XMPPServerConnectorRegistry#close()
+     */
     public void close() {
-        for(XMPPServerConnector connector : connectors.values()) {
+        for(DefaultXMPPServerConnector connector : connectors.values()) {
             connector.close();
         }
     }

Modified: mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnector.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnector.java?rev=1054253&r1=1054252&r2=1054253&view=diff
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnector.java (original)
+++ mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnector.java Sat Jan  1 16:49:12 2011
@@ -1,261 +1,10 @@
 package org.apache.vysper.xmpp.server.s2s;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.util.List;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
 
-import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
-import org.apache.mina.core.future.ConnectFuture;
-import org.apache.mina.core.service.IoConnector;
-import org.apache.mina.core.service.IoHandlerAdapter;
-import org.apache.mina.core.session.IoSession;
-import org.apache.mina.filter.codec.ProtocolCodecFilter;
-import org.apache.mina.filter.ssl.SslFilter;
-import org.apache.mina.transport.socket.nio.NioSocketConnector;
-import org.apache.vysper.mina.MinaBackedSessionContext;
-import org.apache.vysper.mina.StanzaLoggingFilter;
-import org.apache.vysper.mina.codec.XMPPProtocolCodecFactory;
-import org.apache.vysper.xmpp.addressing.Entity;
-import org.apache.vysper.xmpp.modules.extension.xep0119_xmppping.XmppPingListener;
-import org.apache.vysper.xmpp.modules.extension.xep0119_xmppping.XmppPingModule;
-import org.apache.vysper.xmpp.modules.extension.xep0220_server_dailback.DailbackIdGenerator;
-import org.apache.vysper.xmpp.protocol.NamespaceURIs;
-import org.apache.vysper.xmpp.protocol.SessionStateHolder;
-import org.apache.vysper.xmpp.server.ServerRuntimeContext;
-import org.apache.vysper.xmpp.server.SessionState;
-import org.apache.vysper.xmpp.server.XMPPVersion;
-import org.apache.vysper.xmpp.server.response.ServerResponses;
-import org.apache.vysper.xmpp.server.s2s.XmppEndpointResolver.ResolvedAddress;
 import org.apache.vysper.xmpp.stanza.Stanza;
-import org.apache.vysper.xmpp.stanza.StanzaBuilder;
 import org.apache.vysper.xmpp.writer.StanzaWriter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-public class XMPPServerConnector implements StanzaWriter, XmppPingListener {
+public interface XMPPServerConnector extends StanzaWriter {
 
-    private static final Logger LOG = LoggerFactory.getLogger(XMPPServerConnector.class);
-    
-    private ServerRuntimeContext serverRuntimeContext;
-    private MinaBackedSessionContext sessionContext;
-    private Entity otherServer;
-    private SessionStateHolder sessionStateHolder = new SessionStateHolder();
-    private IoConnector connector;
-    
-    private int connectTimeout = 30000;
-    private int xmppHandshakeTimeout = 30000;
+    void write(Stanza stanza);
 
-    private int pingPeriod = 30000;
-    private int pingTimeout = 10000;
-    
-    private boolean closed = false;
-    
-    private Timer pingTimer = new Timer("pingtimer", true);
-    
-    public XMPPServerConnector(Entity otherServer, ServerRuntimeContext serverRuntimeContext) {
-        this.serverRuntimeContext = serverRuntimeContext;
-        this.otherServer = otherServer;
-    }
-
-    public synchronized void start() throws IOException {
-        LOG.info("Starting XMPP server connector to {}", otherServer);
-
-        // make this method synchronous
-        final CountDownLatch authenticatedLatch = new CountDownLatch(1);
-        
-        boolean successfullyConnected = false;
-        
-        XmppEndpointResolver resolver = new XmppEndpointResolver();
-        List<ResolvedAddress> addresses = resolver.resolveXmppServer(otherServer.getDomain());
-        
-        for(ResolvedAddress address : addresses) {
-            LOG.info("Connecting to XMPP server {} at {}", otherServer, address.getAddress());
-            
-            connector = createConnector(authenticatedLatch);
-            ConnectFuture connectFuture = connector.connect(address.getAddress());
-            if(connectFuture.awaitUninterruptibly(connectTimeout) && connectFuture.isConnected()) {
-                // success on the TCP/IP lever, now wait for the XMPP handshake
-
-                try {
-                    if(authenticatedLatch.await(xmppHandshakeTimeout, TimeUnit.MILLISECONDS)) {
-                        // success, break out of connect loop
-                        successfullyConnected = true;
-                        break;
-                    } else {
-                        // attempt next
-                        LOG.warn("XMPP handshake with {} at () timed out", otherServer, address.getAddress());
-                    }
-                } catch (InterruptedException e) {
-                    throw new IOException("Connection to " + otherServer + " was interrupted", e);
-                }
-            } 
-
-            LOG.warn("Failed connecting to XMPP server " + otherServer + " at " + address.getAddress(), connectFuture.getException());
-            connector.dispose();
-            connector = null;
-        }
-        
-        if(!successfullyConnected) {
-            throw new IOException("Failed to connect to XMPP server at " + otherServer);
-        }
-    }
-    
-    private NioSocketConnector createConnector(CountDownLatch authenticatedLatch) {
-        NioSocketConnector connector = new NioSocketConnector();
-        DefaultIoFilterChainBuilder filterChainBuilder = new DefaultIoFilterChainBuilder();
-        filterChainBuilder.addLast("xmppCodec", new ProtocolCodecFilter(new XMPPProtocolCodecFactory()));
-        filterChainBuilder.addLast("loggingFilter", new StanzaLoggingFilter());
-        connector.setFilterChainBuilder(filterChainBuilder);
-        connector.setHandler(new ConnectorIoHandler(authenticatedLatch));
-        return connector;
-    }
-
-
-    
-    private void startPinging() {
-        pingTimer.schedule(new PingTask(), pingPeriod, pingPeriod);
-    }
-    
-    public void write(Stanza stanza) {
-        sessionContext.write(stanza);
-    }
-
-    public void close() {
-        closed = true;
-        if(!closed) {
-            LOG.info("XMPP server connector to {} closing", otherServer);
-            sessionContext.close();
-            
-            connector.dispose();
-            pingTimer.cancel();
-            LOG.info("XMPP server connector to {} closed", otherServer);
-        }
-    }
-
-    public void pong() {
-        // do nothing, all happy
-    }
-
-    public void timeout() {
-        LOG.debug("XMPP server connector to {} timed out, closing", otherServer);
-        close();
-    }
-
-    public boolean isClosed() {
-        return closed;
-    }
-
-    private final class ConnectorIoHandler extends IoHandlerAdapter {
-        private final CountDownLatch authenticatedLatch;
-
-        private ConnectorIoHandler(CountDownLatch authenticatedLatch) {
-            this.authenticatedLatch = authenticatedLatch;
-        }
-
-        @Override
-        public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
-            LOG.info("Exception thrown by XMPP server connector to {}, probably a bug in Vysper", otherServer);
-        }
-
-        @Override
-        public void messageReceived(IoSession session, Object message) throws Exception {
-            if(message == SslFilter.SESSION_SECURED) {
-                // TODO handle unsecure
-                // connection secured, send stream opener
-                sessionStateHolder.setState(SessionState.ENCRYPTED);
-                
-                LOG.info("XMPP server connector to {} secured using TLS", otherServer);
-                LOG.debug("XMPP server connector to {} restarting stream", otherServer);
-                
-                sessionContext.setIsReopeningXMLStream();
-                
-                Stanza opener = new ServerResponses().getStreamOpenerForServerConnector(serverRuntimeContext.getServerEnitity(), otherServer, XMPPVersion.VERSION_1_0, sessionContext);
-                
-                sessionContext.write(opener);
-            } else {
-                Stanza msg = (Stanza) message;
-                
-                if(msg.getName().equals("stream")) {
-                    sessionContext.setSessionId(msg.getAttributeValue("id"));
-                } else if(msg.getName().equals("features")) {
-                    if(startTlsSupported(msg)) {
-                        LOG.info("XMPP server connector to {} is starting TLS", otherServer);
-                        Stanza startTlsStanza = new StanzaBuilder("starttls", NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_TLS).build();
-                        
-                        sessionContext.write(startTlsStanza);
-                        
-                    } else if(dialbackSupported(msg)) {
-                        Entity originating = serverRuntimeContext.getServerEnitity();
-   
-                        String dailbackId = new DailbackIdGenerator().generate(otherServer, originating, sessionContext.getSessionId());
-                        
-                        Stanza dbResult = new StanzaBuilder("result", NamespaceURIs.JABBER_SERVER_DIALBACK, "db")
-                            .addAttribute("from", originating.getDomain())
-                            .addAttribute("to", otherServer.getDomain())
-                            .addText(dailbackId)
-                            .build();
-                        
-                        sessionContext.write(dbResult);
-                    } else {
-                        throw new RuntimeException("Unsupported features");
-                    }
-                } else if(msg.getName().equals("result") && NamespaceURIs.JABBER_SERVER_DIALBACK.equals(msg.getNamespaceURI())) {
-                    // TODO check and handle dailback result
-                    sessionStateHolder.setState(SessionState.AUTHENTICATED);
-                    
-                    LOG.info("XMPP server connector to {} authenticated using dialback", otherServer);
-                    authenticatedLatch.countDown();
-                    
-                    // connection established, start pinging
-                    startPinging();
-                } else if(msg.getName().equals("proceed") && NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_TLS.equals(msg.getNamespaceURI())) {
-                    sessionStateHolder.setState(SessionState.ENCRYPTION_STARTED);
-                    
-                    LOG.debug("XMPP server connector to {} switching to TLS", otherServer);
-                    sessionContext.switchToTLS(false, true);
-                } else {
-                    // TODO other stanzas coming here?
-                }
-            }
-        }
-
-        private boolean startTlsSupported(Stanza stanza) {
-            return !stanza.getInnerElementsNamed("starttls", NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_TLS).isEmpty();
-        }
-
-        private boolean dialbackSupported(Stanza stanza) {
-            // TODO check for dialback namespace
-            return !stanza.getInnerElementsNamed("dialback", NamespaceURIs.URN_XMPP_FEATURES_DIALBACK).isEmpty();
-        }
-
-        @Override
-        public void sessionClosed(IoSession session) throws Exception {
-            // Socket was closed, make sure we close the connector
-            LOG.info("XMPP server connector socket closed, closing connector");
-            close();
-        }
-
-        @Override
-        public void sessionOpened(IoSession session) throws Exception {
-            sessionContext = new MinaBackedSessionContext(serverRuntimeContext, sessionStateHolder, session);
-            sessionStateHolder.setState(SessionState.INITIATED);
-            Stanza opener = new ServerResponses().getStreamOpenerForServerConnector(serverRuntimeContext.getServerEnitity(), otherServer, XMPPVersion.VERSION_1_0, sessionContext);
-            
-            sessionContext.write(opener);
-        }
-    }
-
-    private class PingTask extends TimerTask {
-        public void run() {
-            XmppPingModule pingModule = serverRuntimeContext.getModule(XmppPingModule.class);
-            if(pingModule != null) {
-                pingModule.ping(XMPPServerConnector.this, serverRuntimeContext.getServerEnitity(), otherServer, pingTimeout, XMPPServerConnector.this);
-            }
-        }
-    }
-    
-
-}
+}
\ No newline at end of file

Modified: mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnectorRegistry.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnectorRegistry.java?rev=1054253&r1=1054252&r2=1054253&view=diff
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnectorRegistry.java (original)
+++ mina/vysper/branches/s2s/server/core/src/main/java/org/apache/vysper/xmpp/server/s2s/XMPPServerConnectorRegistry.java Sat Jan  1 16:49:12 2011
@@ -1,40 +1,14 @@
 package org.apache.vysper.xmpp.server.s2s;
-import java.io.IOException;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.vysper.xmpp.addressing.Entity;
-import org.apache.vysper.xmpp.server.ServerRuntimeContext;
+import org.apache.vysper.xmpp.delivery.failure.RemoteServerNotFoundException;
+import org.apache.vysper.xmpp.delivery.failure.RemoteServerTimeoutException;
 
-public class XMPPServerConnectorRegistry {
+public interface XMPPServerConnectorRegistry {
 
-    private ServerRuntimeContext serverRuntimeContext;
-    private Map<Entity, XMPPServerConnector> connectors = new ConcurrentHashMap<Entity, XMPPServerConnector>();
-    
-    public XMPPServerConnectorRegistry(ServerRuntimeContext serverRuntimeContext) {
-        this.serverRuntimeContext = serverRuntimeContext;
-    }
+    XMPPServerConnector connect(Entity server) throws RemoteServerNotFoundException,
+            RemoteServerTimeoutException;
 
-    public synchronized XMPPServerConnector getConnector(Entity server) throws IOException {
-        XMPPServerConnector connector = connectors.get(server);
+    void close();
 
-        if(connector != null && connector.isClosed()) {
-            connectors.remove(server);
-            connector = null;
-        } 
-        
-        if(connector == null) {
-            connector = new XMPPServerConnector(server, serverRuntimeContext);
-            connector.start();
-            connectors.put(server, connector);
-        }
-        
-        return connector;
-    }
-
-    public void close() {
-        for(XMPPServerConnector connector : connectors.values()) {
-            connector.close();
-        }
-    }
-}
+}
\ No newline at end of file

Added: mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/failure/ReturnErrorToSenderFailureStrategyTestCase.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/failure/ReturnErrorToSenderFailureStrategyTestCase.java?rev=1054253&view=auto
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/failure/ReturnErrorToSenderFailureStrategyTestCase.java (added)
+++ mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/failure/ReturnErrorToSenderFailureStrategyTestCase.java Sat Jan  1 16:49:12 2011
@@ -0,0 +1,136 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.vysper.xmpp.delivery.failure;
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+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.addressing.EntityImpl;
+import org.apache.vysper.xmpp.delivery.RecordingStanzaRelay;
+import org.apache.vysper.xmpp.delivery.RecordingStanzaRelay.Triple;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.stanza.MessageStanza;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import org.apache.vysper.xmpp.stanza.XMPPCoreStanza;
+
+/**
+ */
+public class ReturnErrorToSenderFailureStrategyTestCase extends TestCase {
+
+    private static final Entity FROM = EntityImpl.parseUnchecked("from@vysper.org");
+    private static final Entity TO = EntityImpl.parseUnchecked("to@vysper.org");
+    private static final Entity SERVER = EntityImpl.parseUnchecked("vysper.org");
+    private static final String LANG = "en";
+    private static final String BODY = "Hello world";
+    private static final String ERROR_TEXT = "Error!";
+    
+    @SpecCompliant(spec = "draft-ietf-xmpp-3920bis-22", section = "10.4.3", status = SpecCompliant.ComplianceStatus.FINISHED, coverage = SpecCompliant.ComplianceCoverage.COMPLETE)
+    public void testSmartDeliveryException() throws Exception {
+        RecordingStanzaRelay relay = new RecordingStanzaRelay();
+        ReturnErrorToSenderFailureStrategy strategy = new ReturnErrorToSenderFailureStrategy(relay);
+        
+        Stanza stanza = XMPPCoreStanza.getWrapper(StanzaBuilder.createMessageStanza(FROM, TO, LANG, BODY).build());
+        
+        strategy.process(stanza, Arrays.asList((DeliveryException)new RemoteServerNotFoundException(ERROR_TEXT)));
+        
+        Iterator<Triple> triples = relay.iterator();
+        Triple triple = triples.next();
+        Assert.assertEquals(FROM, triple.getEntity());
+        MessageStanza errorStanza = (MessageStanza) XMPPCoreStanza.getWrapper(triple.getStanza());
+        Assert.assertEquals("error", errorStanza.getType());
+        Assert.assertEquals(FROM, errorStanza.getTo());
+        Assert.assertEquals(SERVER, errorStanza.getFrom());
+        
+        XMLElement errorElm = errorStanza.getSingleInnerElementsNamed("error", NamespaceURIs.JABBER_CLIENT);
+        Assert.assertEquals("cancel", errorElm.getAttributeValue("type"));
+
+        Assert.assertNotNull(errorElm.getSingleInnerElementsNamed("remote-server-not-found", NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STANZAS));
+
+        XMLElement textElm = errorElm.getSingleInnerElementsNamed("text", NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STANZAS);
+        Assert.assertEquals(ERROR_TEXT, textElm.getInnerText().getText());
+        
+        Assert.assertEquals(IgnoreFailureStrategy.IGNORE_FAILURE_STRATEGY, triple.getDeliveryFailureStrategy());
+        
+        Assert.assertFalse(triples.hasNext());
+    }
+
+    public void testNoException() throws Exception {
+        RecordingStanzaRelay relay = new RecordingStanzaRelay();
+        ReturnErrorToSenderFailureStrategy strategy = new ReturnErrorToSenderFailureStrategy(relay);
+        
+        Stanza stanza = XMPPCoreStanza.getWrapper(StanzaBuilder.createMessageStanza(FROM, TO, LANG, BODY).build());
+        
+        strategy.process(stanza, null);
+        
+        Iterator<Triple> triples = relay.iterator();
+        Triple triple = triples.next();
+        Assert.assertEquals(FROM, triple.getEntity());
+        MessageStanza errorStanza = (MessageStanza) XMPPCoreStanza.getWrapper(triple.getStanza());
+        Assert.assertEquals("error", errorStanza.getType());
+        Assert.assertEquals(FROM, errorStanza.getTo());
+        Assert.assertEquals(SERVER, errorStanza.getFrom());
+        
+        XMLElement errorElm = errorStanza.getSingleInnerElementsNamed("error", NamespaceURIs.JABBER_CLIENT);
+        Assert.assertEquals("cancel", errorElm.getAttributeValue("type"));
+        Assert.assertNotNull(errorElm.getSingleInnerElementsNamed("service-unavailable", NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STANZAS));
+
+        Assert.assertNotNull(errorElm.getSingleInnerElementsNamed("text", NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STANZAS));
+        
+        Assert.assertEquals(IgnoreFailureStrategy.IGNORE_FAILURE_STRATEGY, triple.getDeliveryFailureStrategy());
+        
+        Assert.assertFalse(triples.hasNext());
+    }
+
+    
+    public void testOnlyIgnoreErrorStanzas() throws Exception {
+        RecordingStanzaRelay relay = new RecordingStanzaRelay();
+        ReturnErrorToSenderFailureStrategy strategy = new ReturnErrorToSenderFailureStrategy(relay);
+        
+        Stanza stanza = XMPPCoreStanza.getWrapper(StanzaBuilder.createMessageStanza(FROM, TO, LANG, BODY)
+            .addAttribute("type", "error")
+            .build());
+
+        strategy.process(stanza, Arrays.asList((DeliveryException)new RemoteServerNotFoundException()));
+
+        Assert.assertFalse(relay.iterator().hasNext());
+    }
+    
+    public void testOnlyHandleCoreStanzas() throws Exception {
+        RecordingStanzaRelay relay = new RecordingStanzaRelay();
+        ReturnErrorToSenderFailureStrategy strategy = new ReturnErrorToSenderFailureStrategy(relay);
+        
+        Stanza stanza = StanzaBuilder.createMessageStanza(FROM, TO, LANG, BODY).build();
+        
+        try {
+            strategy.process(stanza, Arrays.asList((DeliveryException)new RemoteServerNotFoundException()));
+            fail("Must throw DeliveryException");
+        } catch(DeliveryException e) {
+            // OK
+        }
+    }
+
+}

Added: mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringExternalInboundStanzaRelayTestCase.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringExternalInboundStanzaRelayTestCase.java?rev=1054253&view=auto
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringExternalInboundStanzaRelayTestCase.java (added)
+++ mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringExternalInboundStanzaRelayTestCase.java Sat Jan  1 16:49:12 2011
@@ -0,0 +1,106 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.vysper.xmpp.delivery.inbound;
+
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.addressing.EntityImpl;
+import org.apache.vysper.xmpp.delivery.failure.RemoteServerNotFoundException;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.server.ServerRuntimeContext;
+import org.apache.vysper.xmpp.server.s2s.XMPPServerConnector;
+import org.apache.vysper.xmpp.server.s2s.XMPPServerConnectorRegistry;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import org.apache.vysper.xmpp.stanza.XMPPCoreStanza;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+/**
+ */
+public class DeliveringExternalInboundStanzaRelayTestCase extends TestCase {
+
+    private static final Entity FROM = EntityImpl.parseUnchecked("from@vysper.org");
+
+    private static final Entity TO = EntityImpl.parseUnchecked("to@vysper.org");
+
+    private static final Entity SERVER = EntityImpl.parseUnchecked("vysper.org");
+
+    private static final String LANG = "en";
+
+    private static final String BODY = "Hello world";
+
+    private static final Stanza STANZA = XMPPCoreStanza.getWrapper(StanzaBuilder.createMessageStanza(FROM, TO, LANG,
+            BODY).build());
+
+    public void testRemoteServerError() throws Exception {
+        XMPPServerConnectorRegistry registry = Mockito.mock(XMPPServerConnectorRegistry.class);
+        Mockito.when(registry.connect(SERVER)).thenThrow(new RemoteServerNotFoundException());
+
+        ServerRuntimeContext serverRuntimeContext = Mockito.mock(ServerRuntimeContext.class);
+        Mockito.when(serverRuntimeContext.getServerConnectorRegistry()).thenReturn(registry);
+
+        DeliveringExternalInboundStanzaRelay relay = new DeliveringExternalInboundStanzaRelay(new TestExecutorService());
+        relay.setServerRuntimeContext(serverRuntimeContext);
+
+        RecordingDeliveryFailureStrategy deliveryFailureStrategy = new RecordingDeliveryFailureStrategy();
+        relay.relay(TO, STANZA, deliveryFailureStrategy);
+
+        Stanza failedStanza = deliveryFailureStrategy.getRecordedStanza();
+        Assert.assertNotNull(failedStanza);
+        
+        Assert.assertEquals("message", failedStanza.getName());
+        Assert.assertEquals(NamespaceURIs.JABBER_SERVER, failedStanza.getNamespaceURI());
+        Assert.assertEquals(FROM, failedStanza.getFrom());
+        Assert.assertEquals(TO, failedStanza.getTo());
+    }
+
+    public void testSuccessfulRelay() throws Exception {
+        XMPPServerConnector connector = Mockito.mock(XMPPServerConnector.class);
+        
+        XMPPServerConnectorRegistry registry = Mockito.mock(XMPPServerConnectorRegistry.class);
+        Mockito.when(registry.connect(SERVER)).thenReturn(connector);
+
+        ServerRuntimeContext serverRuntimeContext = Mockito.mock(ServerRuntimeContext.class);
+        Mockito.when(serverRuntimeContext.getServerConnectorRegistry()).thenReturn(registry);
+
+        DeliveringExternalInboundStanzaRelay relay = new DeliveringExternalInboundStanzaRelay(new TestExecutorService());
+        relay.setServerRuntimeContext(serverRuntimeContext);
+
+        RecordingDeliveryFailureStrategy deliveryFailureStrategy = new RecordingDeliveryFailureStrategy();
+        relay.relay(TO, STANZA, deliveryFailureStrategy);
+
+        Assert.assertNull(deliveryFailureStrategy.getRecordedStanza());
+
+        ArgumentCaptor<Stanza> writtenStanzaCaptor = ArgumentCaptor.forClass(Stanza.class);
+        Mockito.verify(connector).write(writtenStanzaCaptor.capture());
+        
+        Stanza writtenStanza = writtenStanzaCaptor.getValue();
+        
+        Assert.assertNotNull(writtenStanza);
+        Assert.assertEquals("message", writtenStanza.getName());
+        Assert.assertEquals(NamespaceURIs.JABBER_SERVER, writtenStanza.getNamespaceURI());
+        Assert.assertEquals(FROM, writtenStanza.getFrom());
+        Assert.assertEquals(TO, writtenStanza.getTo());
+    }
+}

Copied: mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInteralInboundStanzaRelayTestCase.java (from r1054013, mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringStanzaRelayTestCase.java)
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInteralInboundStanzaRelayTestCase.java?p2=mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInteralInboundStanzaRelayTestCase.java&p1=mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringStanzaRelayTestCase.java&r1=1054013&r2=1054253&rev=1054253&view=diff
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringStanzaRelayTestCase.java (original)
+++ mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInteralInboundStanzaRelayTestCase.java Sat Jan  1 16:49:12 2011
@@ -39,7 +39,7 @@ import org.apache.vysper.xmpp.state.reso
 
 /**
  */
-public class DeliveringStanzaRelayTestCase extends TestCase {
+public class DeliveringInteralInboundStanzaRelayTestCase extends TestCase {
 
     protected ResourceRegistry resourceRegistry = new ResourceRegistry();
 

Added: mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/RecordingDeliveryFailureStrategy.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/RecordingDeliveryFailureStrategy.java?rev=1054253&view=auto
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/RecordingDeliveryFailureStrategy.java (added)
+++ mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/RecordingDeliveryFailureStrategy.java Sat Jan  1 16:49:12 2011
@@ -0,0 +1,28 @@
+package org.apache.vysper.xmpp.delivery.inbound;
+
+import java.util.List;
+
+import org.apache.vysper.xmpp.delivery.failure.DeliveryException;
+import org.apache.vysper.xmpp.delivery.failure.DeliveryFailureStrategy;
+import org.apache.vysper.xmpp.stanza.Stanza;
+
+public class RecordingDeliveryFailureStrategy implements DeliveryFailureStrategy {
+
+    private Stanza recordedStanza;
+
+    private List<DeliveryException> recordedDeliveryException;
+
+    public void process(Stanza failedToDeliverStanza, List<DeliveryException> deliveryException)
+            throws DeliveryException {
+        this.recordedStanza = failedToDeliverStanza;
+        this.recordedDeliveryException = deliveryException;
+    }
+
+    public Stanza getRecordedStanza() {
+        return recordedStanza;
+    }
+
+    public List<DeliveryException> getRecordedDeliveryException() {
+        return recordedDeliveryException;
+    }
+}
\ No newline at end of file

Added: mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/RelayResultTestCase.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/RelayResultTestCase.java?rev=1054253&view=auto
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/RelayResultTestCase.java (added)
+++ mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/RelayResultTestCase.java Sat Jan  1 16:49:12 2011
@@ -0,0 +1,52 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.vysper.xmpp.delivery.inbound;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.vysper.xmpp.delivery.failure.DeliveryException;
+
+/**
+ */
+public class RelayResultTestCase extends TestCase {
+
+    public void testDefaultCstr() {
+        RelayResult relayResult = new RelayResult();
+        Assert.assertFalse(relayResult.hasProcessingErrors());
+        Assert.assertNotNull(relayResult.getProcessingErrors());
+        Assert.assertEquals(0, relayResult.getProcessingErrors().size());
+    }
+
+    public void testCstrDeliveryException() {
+        RelayResult relayResult = new RelayResult(new DeliveryException());
+        Assert.assertTrue(relayResult.hasProcessingErrors());
+        Assert.assertEquals(1, relayResult.getProcessingErrors().size());
+    }
+
+    public void testAddProcessingError() {
+        RelayResult relayResult = new RelayResult(new DeliveryException());
+        relayResult.addProcessingError(new DeliveryException());
+        
+        Assert.assertTrue(relayResult.hasProcessingErrors());
+        Assert.assertEquals(2, relayResult.getProcessingErrors().size());
+    }
+
+}

Added: mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/TestExecutorService.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/TestExecutorService.java?rev=1054253&view=auto
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/TestExecutorService.java (added)
+++ mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/TestExecutorService.java Sat Jan  1 16:49:12 2011
@@ -0,0 +1,109 @@
+package org.apache.vysper.xmpp.delivery.inbound;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Executes tasks syncronously, useful for test purposes
+ *
+ */
+public class TestExecutorService implements ExecutorService {
+
+    public void execute(Runnable command) {
+        command.run();
+    }
+
+    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+        return true;
+    }
+
+    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
+        return null;
+    }
+
+    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+            throws InterruptedException {
+        return null;
+    }
+
+    public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
+        return null;
+    }
+
+    public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        return null;
+    }
+
+    public boolean isShutdown() {
+        return false;
+    }
+
+    public boolean isTerminated() {
+        return false;
+    }
+
+    public void shutdown() {
+    }
+
+    public List<Runnable> shutdownNow() {
+        return null;
+    }
+
+    public <T> Future<T> submit(Callable<T> task) {
+        try {
+            return new TestFuture<T>(task.call());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    public Future<?> submit(Runnable task) {
+        task.run();
+        return new TestFuture();
+    }
+
+    public <T> Future<T> submit(Runnable task, T result) {
+        task.run();
+        return new TestFuture<T>(result);
+    }
+    
+    public static class TestFuture<V> implements Future<V> {
+
+        private V value;
+
+        public TestFuture() {
+        }
+
+        public TestFuture(V value) {
+            this.value = value;
+        }
+
+        public boolean cancel(boolean arg0) {
+            return false;
+        }
+
+        public V get() throws InterruptedException, ExecutionException {
+            return value;
+        }
+
+        public V get(long arg0, TimeUnit arg1) throws InterruptedException, ExecutionException, TimeoutException {
+            return value;
+        }
+
+        public boolean isCancelled() {
+            return false;
+        }
+
+        public boolean isDone() {
+            return true;
+        }
+    }
+}
\ No newline at end of file

Modified: mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/server/s2s/Server2Server.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/server/s2s/Server2Server.java?rev=1054253&r1=1054252&r2=1054253&view=diff
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/server/s2s/Server2Server.java (original)
+++ mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/server/s2s/Server2Server.java Sat Jan  1 16:49:12 2011
@@ -91,13 +91,14 @@ public class Server2Server {
         
         Thread.sleep(3000);
         
-        Message msg = new Message(remoteUser.getFullQualifiedName());
+        //Message msg = new Message(remoteUser.getFullQualifiedName());
+        Message msg = new Message("foo@sadfsdgdsfgdfsgfd.com");
         msg.setBody("Hello world");
         
         client.sendPacket(msg);
         
         
-        Thread.sleep(3000);
+        Thread.sleep(8000);
         client.disconnect();
         
         Thread.sleep(50000);

Added: mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/server/s2s/ServerMain.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/server/s2s/ServerMain.java?rev=1054253&view=auto
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/server/s2s/ServerMain.java (added)
+++ mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/server/s2s/ServerMain.java Sat Jan  1 16:49:12 2011
@@ -0,0 +1,148 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.vysper.xmpp.server.s2s;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.vysper.mina.TCPEndpoint;
+import org.apache.vysper.storage.StorageProviderRegistry;
+import org.apache.vysper.storage.inmemory.MemoryStorageProviderRegistry;
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.addressing.EntityFormatException;
+import org.apache.vysper.xmpp.addressing.EntityImpl;
+import org.apache.vysper.xmpp.authorization.AccountCreationException;
+import org.apache.vysper.xmpp.authorization.AccountManagement;
+import org.apache.vysper.xmpp.modules.Module;
+import org.apache.vysper.xmpp.modules.extension.xep0049_privatedata.PrivateDataModule;
+import org.apache.vysper.xmpp.modules.extension.xep0054_vcardtemp.VcardTempModule;
+import org.apache.vysper.xmpp.modules.extension.xep0092_software_version.SoftwareVersionModule;
+import org.apache.vysper.xmpp.modules.extension.xep0119_xmppping.XmppPingModule;
+import org.apache.vysper.xmpp.modules.extension.xep0202_entity_time.EntityTimeModule;
+import org.apache.vysper.xmpp.server.XMPPServer;
+
+/**
+ * starts the server as a standalone application
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class ServerMain {
+
+    /**
+     * boots the server as a standalone application
+     * 
+     * adding a module from the command line:
+     * using a runtime property, one or more modules can be specified, like this:
+     * -Dvysper.add.module=org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.PublishSubscribeModule,... more ...
+     * 
+     * @param args
+     */
+    public static void main(String[] args) throws AccountCreationException, EntityFormatException, FileNotFoundException {
+        Entity localServer = EntityImpl.parseUnchecked(args[0]);
+        Entity localUser = EntityImpl.parseUnchecked(args[1]);
+        String keystorePath;
+        String keystorePassword;
+        if(args.length > 2) {
+            keystorePath = args[2];
+            keystorePassword = args[3];
+        } else {
+            keystorePath = "src/main/config/bogus_mina_tls.cert";
+            keystorePassword = "boguspw";            
+        }
+
+        
+        String addedModuleProperty = System.getProperty("vysper.add.module");
+        List<Module> listOfModules = null;
+        if (addedModuleProperty != null) {
+            String[] moduleClassNames = addedModuleProperty.split(",");
+            listOfModules = createModuleInstances(moduleClassNames);
+        }
+
+        // choose the storage you want to use
+        //StorageProviderRegistry providerRegistry = new JcrStorageProviderRegistry();
+        StorageProviderRegistry providerRegistry = new MemoryStorageProviderRegistry();
+
+        final AccountManagement accountManagement = (AccountManagement) providerRegistry
+                .retrieve(AccountManagement.class);
+
+        accountManagement.addUser(localUser.getFullQualifiedName(), "password1");
+
+        XMPPServer server = new XMPPServer(localServer.getFullQualifiedName());
+
+        // S2S endpoint
+        TCPEndpoint s2sEndpoint = new TCPEndpoint();
+        s2sEndpoint.setPort(5269);
+        server.addEndpoint(s2sEndpoint);
+        
+        // C2S endpoint
+        server.addEndpoint(new TCPEndpoint());
+        
+        //server.addEndpoint(new StanzaSessionFactory());
+        server.setStorageProviderRegistry(providerRegistry);
+
+        server.setTLSCertificateInfo(new File(keystorePath), keystorePassword);
+
+        try {
+            server.start();
+            System.out.println("vysper server is running...");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        server.addModule(new SoftwareVersionModule());
+        server.addModule(new EntityTimeModule());
+        server.addModule(new VcardTempModule());
+        server.addModule(new XmppPingModule());
+        server.addModule(new PrivateDataModule());
+
+        if (listOfModules != null) {
+            for (Module module : listOfModules) {
+                server.addModule(module);
+            }
+        }
+    }
+
+    private static List<Module> createModuleInstances(String[] moduleClassNames) {
+        List<Module> modules = new ArrayList<Module>();
+
+        for (String moduleClassName : moduleClassNames) {
+            Class<Module> moduleClass;
+            try {
+                moduleClass = (Class<Module>) Class.forName(moduleClassName);
+            } catch (ClassCastException e) {
+                System.err.println("not a Vysper module class: " + moduleClassName);
+                continue;
+            } catch (ClassNotFoundException e) {
+                System.err.println("could not load module class " + moduleClassName);
+                continue;
+            }
+            try {
+                Module module = moduleClass.newInstance();
+                modules.add(module);
+            } catch (Exception e) {
+                System.err.println("failed to instantiate module class " + moduleClassName);
+                continue;
+            }
+        }
+        return modules;
+    }
+}

Modified: mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/stanza/StanzaBuilderTestCase.java
URL: http://svn.apache.org/viewvc/mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/stanza/StanzaBuilderTestCase.java?rev=1054253&r1=1054252&r2=1054253&view=diff
==============================================================================
--- mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/stanza/StanzaBuilderTestCase.java (original)
+++ mina/vysper/branches/s2s/server/core/src/test/java/org/apache/vysper/xmpp/stanza/StanzaBuilderTestCase.java Sat Jan  1 16:49:12 2011
@@ -19,16 +19,28 @@
  */
 package org.apache.vysper.xmpp.stanza;
 
+import junit.framework.Assert;
 import junit.framework.TestCase;
 
+import org.apache.derby.tools.sysinfo;
+import org.apache.vysper.xml.fragment.Renderer;
 import org.apache.vysper.xml.fragment.XMLElement;
+import org.apache.vysper.xml.fragment.XMLSemanticError;
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.addressing.EntityImpl;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
 
 /**
  */
 public class StanzaBuilderTestCase extends TestCase {
 
-    public void testInnerElementNamespace() {
+    private static final Entity FROM = EntityImpl.parseUnchecked("from@vysper.org");
+    private static final Entity TO = EntityImpl.parseUnchecked("to@vysper.org");
+    private static final String LANG = "en";
+    private static final String BODY = "Hello world";
 
+    
+    public void testInnerElementNamespace() {
         StanzaBuilder builder = new StanzaBuilder("iq");
         builder.startInnerElement("foo", "urn:bar");
         builder.endInnerElement();
@@ -41,4 +53,38 @@ public class StanzaBuilderTestCase exten
         assertEquals("urn:bar", innerElm.getNamespaceURI());
 
     }
+    
+    public void testRewriteNamespace() throws XMLSemanticError {
+        Stanza stanza = StanzaBuilder.createMessageStanza(FROM, TO, LANG, BODY)
+            .startInnerElement("foo", "http://someothernamespace")
+            .startInnerElement("bar", NamespaceURIs.JABBER_CLIENT)
+            .addAttribute("inner", "attribute")
+            .addText("inner text")
+            .endInnerElement()
+            .endInnerElement()
+            .addText("some text")
+            .build();
+        
+        Stanza rewritten = StanzaBuilder.rewriteNamespace(stanza, NamespaceURIs.JABBER_CLIENT, NamespaceURIs.JABBER_SERVER);
+
+        System.out.println(new Renderer(rewritten).getComplete());
+        Assert.assertEquals("message", rewritten.getName());
+        Assert.assertEquals(NamespaceURIs.JABBER_SERVER, rewritten.getNamespaceURI());
+        Assert.assertEquals(FROM, rewritten.getFrom());
+        Assert.assertEquals(TO, rewritten.getTo());
+        
+        XMLElement body = rewritten.getSingleInnerElementsNamed("body", NamespaceURIs.JABBER_SERVER);
+        Assert.assertNotNull(body);
+        Assert.assertEquals(BODY, body.getInnerText().getText());
+        
+        XMLElement foo = rewritten.getSingleInnerElementsNamed("foo", "http://someothernamespace");
+        Assert.assertNotNull(foo);
+        
+        // wrapped elements must not be rewritten
+        XMLElement bar = foo.getSingleInnerElementsNamed("bar", NamespaceURIs.JABBER_CLIENT);
+        Assert.assertNotNull(bar);
+        
+        Assert.assertEquals("attribute", bar.getAttributeValue("inner"));
+        Assert.assertEquals("inner text", bar.getInnerText().getText());
+    }
 }