FaultTolerantNegotiator.java

  1. /**
  2.  *
  3.  * Copyright 2003-2006 Jive Software.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smackx.filetransfer;

  18. import java.io.InputStream;
  19. import java.io.OutputStream;

  20. import org.jivesoftware.smack.SmackException;
  21. import org.jivesoftware.smack.XMPPConnection;
  22. import org.jivesoftware.smack.XMPPException;
  23. import org.jivesoftware.smack.XMPPException.XMPPErrorException;
  24. import org.jivesoftware.smack.packet.IQ;
  25. import org.jivesoftware.smack.packet.Stanza;
  26. import org.jivesoftware.smackx.bytestreams.ibb.packet.Open;
  27. import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream;
  28. import org.jivesoftware.smackx.si.packet.StreamInitiation;
  29. import org.jxmpp.jid.Jid;


  30. /**
  31.  * The fault tolerant negotiator takes two stream negotiators, the primary and the secondary
  32.  * negotiator. If the primary negotiator fails during the stream negotiaton process, the second
  33.  * negotiator is used.
  34.  */
  35. public class FaultTolerantNegotiator extends StreamNegotiator {

  36.     private final StreamNegotiator primaryNegotiator;
  37.     private final StreamNegotiator secondaryNegotiator;
  38.     private final XMPPConnection connection;

  39.     public FaultTolerantNegotiator(XMPPConnection connection, StreamNegotiator primary,
  40.             StreamNegotiator secondary) {
  41.         this.primaryNegotiator = primary;
  42.         this.secondaryNegotiator = secondary;
  43.         this.connection = connection;
  44.     }

  45.     @Override
  46.     public void newStreamInitiation(Jid from, String streamID) {
  47.         primaryNegotiator.newStreamInitiation(from, streamID);
  48.         secondaryNegotiator.newStreamInitiation(from, streamID);
  49.     }

  50.     InputStream negotiateIncomingStream(Stanza streamInitiation) {
  51.         throw new UnsupportedOperationException("Negotiation only handled by create incoming " +
  52.                 "stream method.");
  53.     }

  54.     public InputStream createIncomingStream(final StreamInitiation initiation) throws SmackException, XMPPErrorException, InterruptedException {
  55.         // This could be either an xep47 ibb 'open' iq or an xep65 streamhost iq
  56.         IQ initationSet = initiateIncomingStream(connection, initiation);

  57.         StreamNegotiator streamNegotiator = determineNegotiator(initationSet);

  58.         return streamNegotiator.negotiateIncomingStream(initationSet);
  59.     }

  60.     private StreamNegotiator determineNegotiator(Stanza streamInitiation) {
  61.         if (streamInitiation instanceof Bytestream) {
  62.             return primaryNegotiator;
  63.         } else if (streamInitiation instanceof Open){
  64.             return secondaryNegotiator;
  65.         } else {
  66.             throw new IllegalStateException("Unknown stream initation type");
  67.         }
  68.     }

  69.     public OutputStream createOutgoingStream(String streamID, Jid initiator, Jid target)
  70.                     throws SmackException, XMPPException, InterruptedException {
  71.         OutputStream stream;
  72.         try {
  73.             stream = primaryNegotiator.createOutgoingStream(streamID, initiator, target);
  74.         }
  75.         catch (Exception ex) {
  76.             stream = secondaryNegotiator.createOutgoingStream(streamID, initiator, target);
  77.         }

  78.         return stream;
  79.     }

  80.     public String[] getNamespaces() {
  81.         String[] primary = primaryNegotiator.getNamespaces();
  82.         String[] secondary = secondaryNegotiator.getNamespaces();

  83.         String[] namespaces = new String[primary.length + secondary.length];
  84.         System.arraycopy(primary, 0, namespaces, 0, primary.length);
  85.         System.arraycopy(secondary, 0, namespaces, primary.length, secondary.length);

  86.         return namespaces;
  87.     }

  88. }